8
.editorconfig
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[{src, translations}/*]
|
||||||
|
end_of_line = crlf
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
charset = utf-8
|
||||||
18
.github/workflows/ci.yml
vendored
@ -35,19 +35,23 @@ jobs:
|
|||||||
cd gulp/
|
cd gulp/
|
||||||
yarn
|
yarn
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: |
|
run: |
|
||||||
yarn lint
|
yarn lint
|
||||||
|
|
||||||
- name: YAML Lint
|
|
||||||
uses: ibiqlik/action-yamllint@v1.0.0
|
|
||||||
with:
|
|
||||||
file_or_dir: translations/*.yaml
|
|
||||||
|
|
||||||
- name: TSLint
|
- name: TSLint
|
||||||
run: |
|
run: |
|
||||||
cd gulp
|
cd gulp
|
||||||
yarn gulp translations.fullBuild
|
yarn gulp translations.fullBuild
|
||||||
cd ..
|
cd ..
|
||||||
yarn tslint
|
yarn tslint
|
||||||
|
|
||||||
|
yaml-lint:
|
||||||
|
name: yaml-lint
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: YAML Lint
|
||||||
|
uses: ibiqlik/action-yamllint@v1.0.0
|
||||||
|
with:
|
||||||
|
file_or_dir: translations/*.yaml
|
||||||
|
|||||||
@ -4,3 +4,4 @@ rules:
|
|||||||
line-length:
|
line-length:
|
||||||
level: warning
|
level: warning
|
||||||
max: 200
|
max: 200
|
||||||
|
document-start: disable
|
||||||
|
|||||||
31
Dockerfile
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
FROM node:12 as base
|
||||||
|
|
||||||
|
EXPOSE 3001 3005
|
||||||
|
|
||||||
|
WORKDIR /shapez.io
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
ffmpeg default-jre \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
COPY package.json yarn.lock ./
|
||||||
|
RUN yarn
|
||||||
|
|
||||||
|
COPY gulp ./gulp
|
||||||
|
WORKDIR /shapez.io/gulp
|
||||||
|
RUN yarn
|
||||||
|
|
||||||
|
WORKDIR /shapez.io
|
||||||
|
COPY res ./res
|
||||||
|
COPY src/html ./src/html
|
||||||
|
COPY src/css ./src/css
|
||||||
|
COPY version ./version
|
||||||
|
COPY sync-translations.js ./
|
||||||
|
COPY translations ./translations
|
||||||
|
COPY src/js ./src/js
|
||||||
|
COPY res_raw ./res_raw
|
||||||
|
COPY .git ./.git
|
||||||
|
|
||||||
|
WORKDIR /shapez.io/gulp
|
||||||
|
ENTRYPOINT ["yarn", "gulp"]
|
||||||
@ -86,8 +86,16 @@ gulp.task("utils.cleanBuildTempFolder", () => {
|
|||||||
.src(path.join(__dirname, "..", "src", "js", "built-temp"), { read: false, allowEmpty: true })
|
.src(path.join(__dirname, "..", "src", "js", "built-temp"), { read: false, allowEmpty: true })
|
||||||
.pipe($.clean({ force: true }));
|
.pipe($.clean({ force: true }));
|
||||||
});
|
});
|
||||||
|
gulp.task("utils.cleanImageBuildFolder", () => {
|
||||||
|
return gulp
|
||||||
|
.src(path.join(__dirname, "res_built"), { read: false, allowEmpty: true })
|
||||||
|
.pipe($.clean({ force: true }));
|
||||||
|
});
|
||||||
|
|
||||||
gulp.task("utils.cleanup", gulp.series("utils.cleanBuildFolder", "utils.cleanBuildTempFolder"));
|
gulp.task(
|
||||||
|
"utils.cleanup",
|
||||||
|
gulp.series("utils.cleanBuildFolder", "utils.cleanImageBuildFolder", "utils.cleanBuildTempFolder")
|
||||||
|
);
|
||||||
|
|
||||||
// Requires no uncomitted files
|
// Requires no uncomitted files
|
||||||
gulp.task("utils.requireCleanWorkingTree", cb => {
|
gulp.task("utils.requireCleanWorkingTree", cb => {
|
||||||
@ -234,12 +242,13 @@ gulp.task(
|
|||||||
"build.standalone.dev",
|
"build.standalone.dev",
|
||||||
gulp.series(
|
gulp.series(
|
||||||
"utils.cleanup",
|
"utils.cleanup",
|
||||||
|
"imgres.buildAtlas",
|
||||||
|
"imgres.atlasToJson",
|
||||||
"imgres.atlas",
|
"imgres.atlas",
|
||||||
"sounds.dev",
|
"sounds.dev",
|
||||||
"imgres.copyImageResources",
|
"imgres.copyImageResources",
|
||||||
"imgres.copyNonImageResources",
|
"imgres.copyNonImageResources",
|
||||||
"translations.fullBuild",
|
"translations.fullBuild",
|
||||||
"js.standalone-dev",
|
|
||||||
"css.dev",
|
"css.dev",
|
||||||
"html.standalone-dev"
|
"html.standalone-dev"
|
||||||
)
|
)
|
||||||
|
|||||||
@ -173,6 +173,8 @@ function gulptasksImageResources($, gulp, buildFolder) {
|
|||||||
gulp.task(
|
gulp.task(
|
||||||
"imgres.allOptimized",
|
"imgres.allOptimized",
|
||||||
gulp.parallel(
|
gulp.parallel(
|
||||||
|
"imgres.buildAtlas",
|
||||||
|
"imgres.atlasToJson",
|
||||||
"imgres.atlasOptimized",
|
"imgres.atlasOptimized",
|
||||||
"imgres.copyNonImageResources",
|
"imgres.copyNonImageResources",
|
||||||
"imgres.copyImageResourcesOptimized"
|
"imgres.copyImageResourcesOptimized"
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 8.5 KiB |
@ -17,13 +17,10 @@
|
|||||||
grid-template-rows: 1fr 1fr;
|
grid-template-rows: 1fr 1fr;
|
||||||
@include S(margin-bottom, 4px);
|
@include S(margin-bottom, 4px);
|
||||||
color: #333438;
|
color: #333438;
|
||||||
// text-shadow: #{D(1px)} #{D(1px)} 0 rgba(0, 10, 20, 0.2);
|
|
||||||
|
|
||||||
&.unpinable {
|
&.removable {
|
||||||
> canvas {
|
cursor: pointer;
|
||||||
cursor: pointer;
|
pointer-events: all;
|
||||||
pointer-events: all;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
> canvas {
|
> canvas {
|
||||||
@ -31,16 +28,9 @@
|
|||||||
@include S(height, 25px);
|
@include S(height, 25px);
|
||||||
grid-column: 1 / 2;
|
grid-column: 1 / 2;
|
||||||
grid-row: 1 / 3;
|
grid-row: 1 / 3;
|
||||||
pointer-events: all;
|
pointer-events: none;
|
||||||
transition: transform 0.1s ease-in-out;
|
|
||||||
transform-origin: D(2px) center;
|
|
||||||
will-change: transform;
|
|
||||||
position: relative;
|
|
||||||
z-index: 20;
|
z-index: 20;
|
||||||
&:hover {
|
position: relative;
|
||||||
transform: scale(2);
|
|
||||||
z-index: 21;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
> .amountLabel,
|
> .amountLabel,
|
||||||
|
|||||||
@ -29,6 +29,7 @@ import { MobileWarningState } from "./states/mobile_warning";
|
|||||||
import { PreloadState } from "./states/preload";
|
import { PreloadState } from "./states/preload";
|
||||||
import { SettingsState } from "./states/settings";
|
import { SettingsState } from "./states/settings";
|
||||||
import { ShapezGameAnalytics } from "./platform/browser/game_analytics";
|
import { ShapezGameAnalytics } from "./platform/browser/game_analytics";
|
||||||
|
import { RestrictionManager } from "./core/restriction_manager";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import("./platform/game_analytics").GameAnalyticsInterface} GameAnalyticsInterface
|
* @typedef {import("./platform/game_analytics").GameAnalyticsInterface} GameAnalyticsInterface
|
||||||
@ -70,6 +71,9 @@ export class Application {
|
|||||||
this.inputMgr = new InputDistributor(this);
|
this.inputMgr = new InputDistributor(this);
|
||||||
this.backgroundResourceLoader = new BackgroundResourcesLoader(this);
|
this.backgroundResourceLoader = new BackgroundResourcesLoader(this);
|
||||||
|
|
||||||
|
// Restrictions (Like demo etc)
|
||||||
|
this.restrictionMgr = new RestrictionManager(this);
|
||||||
|
|
||||||
// Platform dependent stuff
|
// Platform dependent stuff
|
||||||
|
|
||||||
/** @type {StorageInterface} */
|
/** @type {StorageInterface} */
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
import { queryParamOptions } from "./query_parameters";
|
|
||||||
|
|
||||||
export const IS_DEBUG =
|
export const IS_DEBUG =
|
||||||
G_IS_DEV &&
|
G_IS_DEV &&
|
||||||
typeof window !== "undefined" &&
|
typeof window !== "undefined" &&
|
||||||
@ -7,13 +5,10 @@ export const IS_DEBUG =
|
|||||||
(window.location.host.indexOf("localhost:") >= 0 || window.location.host.indexOf("192.168.0.") >= 0) &&
|
(window.location.host.indexOf("localhost:") >= 0 || window.location.host.indexOf("192.168.0.") >= 0) &&
|
||||||
window.location.search.indexOf("nodebug") < 0;
|
window.location.search.indexOf("nodebug") < 0;
|
||||||
|
|
||||||
export const IS_DEMO = queryParamOptions.fullVersion
|
|
||||||
? false
|
|
||||||
: (!G_IS_DEV && !G_IS_STANDALONE) ||
|
|
||||||
(typeof window !== "undefined" && window.location.search.indexOf("demo") >= 0);
|
|
||||||
|
|
||||||
export const SUPPORT_TOUCH = false;
|
export const SUPPORT_TOUCH = false;
|
||||||
|
|
||||||
|
export const IS_MAC = navigator.platform.toLowerCase().indexOf("mac") >= 0;
|
||||||
|
|
||||||
const smoothCanvas = true;
|
const smoothCanvas = true;
|
||||||
|
|
||||||
export const THIRDPARTY_URLS = {
|
export const THIRDPARTY_URLS = {
|
||||||
@ -64,7 +59,7 @@ export const globalConfig = {
|
|||||||
|
|
||||||
undergroundBeltMaxTilesByTier: [5, 9],
|
undergroundBeltMaxTilesByTier: [5, 9],
|
||||||
|
|
||||||
readerAnalyzeIntervalSeconds: G_IS_DEV ? 3 : 10,
|
readerAnalyzeIntervalSeconds: 10,
|
||||||
|
|
||||||
buildingSpeeds: {
|
buildingSpeeds: {
|
||||||
cutter: 1 / 4,
|
cutter: 1 / 4,
|
||||||
|
|||||||
@ -81,10 +81,6 @@ export class ReadWriteProxy {
|
|||||||
return this.writeAsync();
|
return this.writeAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentData() {
|
|
||||||
return this.currentData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {object} obj
|
* @param {object} obj
|
||||||
|
|||||||
155
src/js/core/restriction_manager.js
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/* typehints:start */
|
||||||
|
import { Application } from "../application";
|
||||||
|
/* typehints:end */
|
||||||
|
import { IS_MAC } from "./config";
|
||||||
|
import { ExplainedResult } from "./explained_result";
|
||||||
|
import { queryParamOptions } from "./query_parameters";
|
||||||
|
import { ReadWriteProxy } from "./read_write_proxy";
|
||||||
|
|
||||||
|
export class RestrictionManager extends ReadWriteProxy {
|
||||||
|
/**
|
||||||
|
* @param {Application} app
|
||||||
|
*/
|
||||||
|
constructor(app) {
|
||||||
|
super(app, "restriction-flags.bin");
|
||||||
|
|
||||||
|
this.currentData = this.getDefaultData();
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- RW Proxy Impl
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {any} data
|
||||||
|
*/
|
||||||
|
verify(data) {
|
||||||
|
return ExplainedResult.good();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
getDefaultData() {
|
||||||
|
return {
|
||||||
|
version: this.getCurrentVersion(),
|
||||||
|
savegameV1119Imported: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
getCurrentVersion() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {any} data
|
||||||
|
*/
|
||||||
|
migrate(data) {
|
||||||
|
// Todo
|
||||||
|
return ExplainedResult.good();
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize() {
|
||||||
|
return this.readAsync().then(() => {
|
||||||
|
if (this.currentData.savegameV1119Imported) {
|
||||||
|
console.warn("Levelunlock is granted to current user due to past savegame");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- End RW Proxy Impl
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if there are any savegames from the 1.1.19 version
|
||||||
|
*/
|
||||||
|
onHasLegacySavegamesChanged(has119Savegames = false) {
|
||||||
|
if (has119Savegames && !this.currentData.savegameV1119Imported) {
|
||||||
|
this.currentData.savegameV1119Imported = true;
|
||||||
|
console.warn("Current user now has access to all levels due to 1119 savegame");
|
||||||
|
return this.writeAsync();
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if the app is currently running as the limited version
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
isLimitedVersion() {
|
||||||
|
if (IS_MAC) {
|
||||||
|
// On mac, the full version is always active
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G_IS_STANDALONE) {
|
||||||
|
// Standalone is never limited
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (queryParamOptions.fullVersion) {
|
||||||
|
// Full version is activated via flag
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G_IS_DEV) {
|
||||||
|
return typeof window !== "undefined" && window.location.search.indexOf("demo") >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if the app markets the standalone version on steam
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
getIsStandaloneMarketingActive() {
|
||||||
|
return this.isLimitedVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if exporting the base as a screenshot is possible
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
getIsExportingScreenshotsPossible() {
|
||||||
|
return !this.isLimitedVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the maximum number of supported waypoints
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
getMaximumWaypoints() {
|
||||||
|
return this.isLimitedVersion() ? 2 : 1e20;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if the user has unlimited savegames
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
getHasUnlimitedSavegames() {
|
||||||
|
return !this.isLimitedVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if the app has all settings available
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
getHasExtendedSettings() {
|
||||||
|
return !this.isLimitedVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if all upgrades are available
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
getHasExtendedUpgrades() {
|
||||||
|
return !this.isLimitedVersion() || this.currentData.savegameV1119Imported;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if all levels & freeplay is available
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
getHasExtendedLevelsAndFreeplay() {
|
||||||
|
return !this.isLimitedVersion() || this.currentData.savegameV1119Imported;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -108,17 +108,6 @@ export class RandomNumberGenerator {
|
|||||||
assert(max > min, "rng: max <= min");
|
assert(max > min, "rng: max <= min");
|
||||||
return Math.floor(this.next() * (max - min) + min);
|
return Math.floor(this.next() * (max - min) + min);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {number} min
|
|
||||||
* @param {number} max
|
|
||||||
* @returns {number} Integer in range [min, max]
|
|
||||||
*/
|
|
||||||
nextIntRangeInclusive(min, max) {
|
|
||||||
assert(Number.isFinite(min), "Minimum is no integer");
|
|
||||||
assert(Number.isFinite(max), "Maximum is no integer");
|
|
||||||
assert(max > min, "rng: max <= min");
|
|
||||||
return Math.round(this.next() * (max - min) + min);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {number} min
|
* @param {number} min
|
||||||
|
|||||||
@ -681,3 +681,72 @@ export function fillInLinkIntoTranslation(translation, link) {
|
|||||||
.replace("<link>", "<a href='" + link + "' target='_blank'>")
|
.replace("<link>", "<a href='" + link + "' target='_blank'>")
|
||||||
.replace("</link>", "</a>");
|
.replace("</link>", "</a>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a file download
|
||||||
|
* @param {string} filename
|
||||||
|
* @param {string} text
|
||||||
|
*/
|
||||||
|
export function generateFileDownload(filename, text) {
|
||||||
|
var element = document.createElement("a");
|
||||||
|
element.setAttribute("href", "data:text/plain;charset=utf-8," + encodeURIComponent(text));
|
||||||
|
element.setAttribute("download", filename);
|
||||||
|
|
||||||
|
element.style.display = "none";
|
||||||
|
document.body.appendChild(element);
|
||||||
|
|
||||||
|
element.click();
|
||||||
|
document.body.removeChild(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a file chooser
|
||||||
|
* @param {string} acceptedType
|
||||||
|
*/
|
||||||
|
export function startFileChoose(acceptedType = ".bin") {
|
||||||
|
var input = document.createElement("input");
|
||||||
|
input.type = "file";
|
||||||
|
input.accept = acceptedType;
|
||||||
|
|
||||||
|
return new Promise(resolve => {
|
||||||
|
input.onchange = _ => resolve(input.files[0]);
|
||||||
|
input.click();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const romanLiterals = [
|
||||||
|
"0", // NULL
|
||||||
|
"I",
|
||||||
|
"II",
|
||||||
|
"III",
|
||||||
|
"IV",
|
||||||
|
"V",
|
||||||
|
"VI",
|
||||||
|
"VII",
|
||||||
|
"VIII",
|
||||||
|
"IX",
|
||||||
|
"X",
|
||||||
|
"XI",
|
||||||
|
"XII",
|
||||||
|
"XIII",
|
||||||
|
"XIV",
|
||||||
|
"XV",
|
||||||
|
"XVI",
|
||||||
|
"XVII",
|
||||||
|
"XVIII",
|
||||||
|
"XIX",
|
||||||
|
"XX",
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {number} number
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export function getRomanNumber(number) {
|
||||||
|
number = Math.max(0, Math.round(number));
|
||||||
|
if (number < romanLiterals.length) {
|
||||||
|
return romanLiterals[number];
|
||||||
|
}
|
||||||
|
return String(number);
|
||||||
|
}
|
||||||
|
|||||||
@ -1111,7 +1111,7 @@ export class BeltPath extends BasicSerializableObject {
|
|||||||
|
|
||||||
isFirstItemProcessed = false;
|
isFirstItemProcessed = false;
|
||||||
this.spacingToFirstItem += clampedProgress;
|
this.spacingToFirstItem += clampedProgress;
|
||||||
if (remainingVelocity < 0.01) {
|
if (remainingVelocity < 1e-7) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,9 @@
|
|||||||
import { globalConfig } from "../core/config";
|
import { globalConfig } from "../core/config";
|
||||||
import { DrawParameters } from "../core/draw_parameters";
|
import { DrawParameters } from "../core/draw_parameters";
|
||||||
import { createLogger } from "../core/logging";
|
|
||||||
import { findNiceIntegerValue } from "../core/utils";
|
import { findNiceIntegerValue } from "../core/utils";
|
||||||
import { Vector } from "../core/vector";
|
import { Vector } from "../core/vector";
|
||||||
import { Entity } from "./entity";
|
import { Entity } from "./entity";
|
||||||
import { GameRoot } from "./root";
|
import { GameRoot } from "./root";
|
||||||
import { blueprintShape } from "./upgrades";
|
|
||||||
|
|
||||||
const logger = createLogger("blueprint");
|
|
||||||
|
|
||||||
export class Blueprint {
|
export class Blueprint {
|
||||||
/**
|
/**
|
||||||
@ -142,7 +138,7 @@ export class Blueprint {
|
|||||||
* @param {GameRoot} root
|
* @param {GameRoot} root
|
||||||
*/
|
*/
|
||||||
canAfford(root) {
|
canAfford(root) {
|
||||||
return root.hubGoals.getShapesStoredByKey(blueprintShape) >= this.getCost();
|
return root.hubGoals.getShapesStoredByKey(root.gameMode.getBlueprintShapeKey()) >= this.getCost();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -110,12 +110,7 @@ export class MetaVirtualProcessorBuilding extends MetaBuilding {
|
|||||||
pinComp.setSlots([
|
pinComp.setSlots([
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 0),
|
pos: new Vector(0, 0),
|
||||||
direction: enumDirection.left,
|
direction: enumDirection.top,
|
||||||
type: enumPinSlotType.logicalEjector,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
pos: new Vector(0, 0),
|
|
||||||
direction: enumDirection.right,
|
|
||||||
type: enumPinSlotType.logicalEjector,
|
type: enumPinSlotType.logicalEjector,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -511,7 +511,11 @@ export class Camera extends BasicSerializableObject {
|
|||||||
this.clampZoomLevel();
|
this.clampZoomLevel();
|
||||||
this.desiredZoom = null;
|
this.desiredZoom = null;
|
||||||
|
|
||||||
const mousePosition = this.root.app.mousePosition;
|
let mousePosition = this.root.app.mousePosition;
|
||||||
|
if (!this.root.app.settings.getAllSettings().zoomToCursor) {
|
||||||
|
mousePosition = new Vector(this.root.gameWidth / 2, this.root.gameHeight / 2);
|
||||||
|
}
|
||||||
|
|
||||||
if (mousePosition) {
|
if (mousePosition) {
|
||||||
const worldPos = this.root.camera.screenToWorld(mousePosition);
|
const worldPos = this.root.camera.screenToWorld(mousePosition);
|
||||||
const worldDelta = worldPos.sub(this.center);
|
const worldDelta = worldPos.sub(this.center);
|
||||||
|
|||||||
@ -31,6 +31,7 @@ import { KeyActionMapper } from "./key_action_mapper";
|
|||||||
import { GameLogic } from "./logic";
|
import { GameLogic } from "./logic";
|
||||||
import { MapView } from "./map_view";
|
import { MapView } from "./map_view";
|
||||||
import { defaultBuildingVariant } from "./meta_building";
|
import { defaultBuildingVariant } from "./meta_building";
|
||||||
|
import { RegularGameMode } from "./modes/regular";
|
||||||
import { ProductionAnalytics } from "./production_analytics";
|
import { ProductionAnalytics } from "./production_analytics";
|
||||||
import { GameRoot } from "./root";
|
import { GameRoot } from "./root";
|
||||||
import { ShapeDefinitionManager } from "./shape_definition_manager";
|
import { ShapeDefinitionManager } from "./shape_definition_manager";
|
||||||
@ -101,6 +102,9 @@ export class GameCore {
|
|||||||
// Needs to come first
|
// Needs to come first
|
||||||
root.dynamicTickrate = new DynamicTickrate(root);
|
root.dynamicTickrate = new DynamicTickrate(root);
|
||||||
|
|
||||||
|
// Init game mode
|
||||||
|
root.gameMode = new RegularGameMode(root);
|
||||||
|
|
||||||
// Init classes
|
// Init classes
|
||||||
root.camera = new Camera(root);
|
root.camera = new Camera(root);
|
||||||
root.map = new MapView(root);
|
root.map = new MapView(root);
|
||||||
|
|||||||
71
src/js/game/game_mode.js
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/* typehints:start */
|
||||||
|
import { enumHubGoalRewards } from "./tutorial_goals";
|
||||||
|
/* typehints:end */
|
||||||
|
|
||||||
|
import { GameRoot } from "./root";
|
||||||
|
|
||||||
|
/** @typedef {{
|
||||||
|
* shape: string,
|
||||||
|
* amount: number
|
||||||
|
* }} UpgradeRequirement */
|
||||||
|
|
||||||
|
/** @typedef {{
|
||||||
|
* required: Array<UpgradeRequirement>
|
||||||
|
* improvement?: number,
|
||||||
|
* excludePrevious?: boolean
|
||||||
|
* }} TierRequirement */
|
||||||
|
|
||||||
|
/** @typedef {Array<TierRequirement>} UpgradeTiers */
|
||||||
|
|
||||||
|
/** @typedef {{
|
||||||
|
* shape: string,
|
||||||
|
* required: number,
|
||||||
|
* reward: enumHubGoalRewards,
|
||||||
|
* throughputOnly?: boolean
|
||||||
|
* }} LevelDefinition */
|
||||||
|
|
||||||
|
export class GameMode {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {GameRoot} root
|
||||||
|
*/
|
||||||
|
constructor(root) {
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should return all available upgrades
|
||||||
|
* @returns {Object<string, UpgradeTiers>}
|
||||||
|
*/
|
||||||
|
getUpgrades() {
|
||||||
|
abstract;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the blueprint shape key
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
getBlueprintShapeKey() {
|
||||||
|
abstract;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the goals for all levels including their reward
|
||||||
|
* @returns {Array<LevelDefinition>}
|
||||||
|
*/
|
||||||
|
getLevelDefinitions() {
|
||||||
|
abstract;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should return whether free play is available or if the game stops
|
||||||
|
* after the predefined levels
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
getIsFreeplayAvailable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,14 +1,13 @@
|
|||||||
import { globalConfig, IS_DEMO } from "../core/config";
|
import { globalConfig } from "../core/config";
|
||||||
import { RandomNumberGenerator } from "../core/rng";
|
import { RandomNumberGenerator } from "../core/rng";
|
||||||
import { clamp, findNiceIntegerValue, randomChoice, randomInt } from "../core/utils";
|
import { clamp } from "../core/utils";
|
||||||
import { BasicSerializableObject, types } from "../savegame/serialization";
|
import { BasicSerializableObject, types } from "../savegame/serialization";
|
||||||
import { enumColors } from "./colors";
|
import { enumColors } from "./colors";
|
||||||
import { enumItemProcessorTypes } from "./components/item_processor";
|
import { enumItemProcessorTypes } from "./components/item_processor";
|
||||||
import { enumAnalyticsDataSource } from "./production_analytics";
|
import { enumAnalyticsDataSource } from "./production_analytics";
|
||||||
import { GameRoot } from "./root";
|
import { GameRoot } from "./root";
|
||||||
import { enumSubShape, ShapeDefinition } from "./shape_definition";
|
import { enumSubShape, ShapeDefinition } from "./shape_definition";
|
||||||
import { enumHubGoalRewards, tutorialGoals } from "./tutorial_goals";
|
import { enumHubGoalRewards } from "./tutorial_goals";
|
||||||
import { UPGRADES } from "./upgrades";
|
|
||||||
|
|
||||||
export class HubGoals extends BasicSerializableObject {
|
export class HubGoals extends BasicSerializableObject {
|
||||||
static getId() {
|
static getId() {
|
||||||
@ -23,27 +22,36 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
deserialize(data) {
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} data
|
||||||
|
* @param {GameRoot} root
|
||||||
|
*/
|
||||||
|
deserialize(data, root) {
|
||||||
const errorCode = super.deserialize(data);
|
const errorCode = super.deserialize(data);
|
||||||
if (errorCode) {
|
if (errorCode) {
|
||||||
return errorCode;
|
return errorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_DEMO) {
|
const levels = root.gameMode.getLevelDefinitions();
|
||||||
this.level = Math.min(this.level, tutorialGoals.length);
|
|
||||||
|
// If freeplay is not available, clamp the level
|
||||||
|
if (!root.gameMode.getIsFreeplayAvailable()) {
|
||||||
|
this.level = Math.min(this.level, levels.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute gained rewards
|
// Compute gained rewards
|
||||||
for (let i = 0; i < this.level - 1; ++i) {
|
for (let i = 0; i < this.level - 1; ++i) {
|
||||||
if (i < tutorialGoals.length) {
|
if (i < levels.length) {
|
||||||
const reward = tutorialGoals[i].reward;
|
const reward = levels[i].reward;
|
||||||
this.gainedRewards[reward] = (this.gainedRewards[reward] || 0) + 1;
|
this.gainedRewards[reward] = (this.gainedRewards[reward] || 0) + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute upgrade improvements
|
// Compute upgrade improvements
|
||||||
for (const upgradeId in UPGRADES) {
|
const upgrades = this.root.gameMode.getUpgrades();
|
||||||
const tiers = UPGRADES[upgradeId];
|
for (const upgradeId in upgrades) {
|
||||||
|
const tiers = upgrades[upgradeId];
|
||||||
const level = this.upgradeLevels[upgradeId] || 0;
|
const level = this.upgradeLevels[upgradeId] || 0;
|
||||||
let totalImprovement = 1;
|
let totalImprovement = 1;
|
||||||
for (let i = 0; i < level; ++i) {
|
for (let i = 0; i < level; ++i) {
|
||||||
@ -84,17 +92,16 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
*/
|
*/
|
||||||
this.upgradeLevels = {};
|
this.upgradeLevels = {};
|
||||||
|
|
||||||
// Reset levels
|
|
||||||
for (const key in UPGRADES) {
|
|
||||||
this.upgradeLevels[key] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the improvements for all upgrades
|
* Stores the improvements for all upgrades
|
||||||
* @type {Object<string, number>}
|
* @type {Object<string, number>}
|
||||||
*/
|
*/
|
||||||
this.upgradeImprovements = {};
|
this.upgradeImprovements = {};
|
||||||
for (const key in UPGRADES) {
|
|
||||||
|
// Reset levels first
|
||||||
|
const upgrades = this.root.gameMode.getUpgrades();
|
||||||
|
for (const key in upgrades) {
|
||||||
|
this.upgradeLevels[key] = 0;
|
||||||
this.upgradeImprovements[key] = 1;
|
this.upgradeImprovements[key] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +127,10 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
isEndOfDemoReached() {
|
isEndOfDemoReached() {
|
||||||
return IS_DEMO && this.level >= tutorialGoals.length;
|
return (
|
||||||
|
!this.root.gameMode.getIsFreeplayAvailable() &&
|
||||||
|
this.level >= this.root.gameMode.getLevelDefinitions().length
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -215,8 +225,9 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
*/
|
*/
|
||||||
computeNextGoal() {
|
computeNextGoal() {
|
||||||
const storyIndex = this.level - 1;
|
const storyIndex = this.level - 1;
|
||||||
if (storyIndex < tutorialGoals.length) {
|
const levels = this.root.gameMode.getLevelDefinitions();
|
||||||
const { shape, required, reward, throughputOnly } = tutorialGoals[storyIndex];
|
if (storyIndex < levels.length) {
|
||||||
|
const { shape, required, reward, throughputOnly } = levels[storyIndex];
|
||||||
this.currentGoal = {
|
this.currentGoal = {
|
||||||
/** @type {ShapeDefinition} */
|
/** @type {ShapeDefinition} */
|
||||||
definition: this.root.shapeDefinitionMgr.getShapeFromShortKey(shape),
|
definition: this.root.shapeDefinitionMgr.getShapeFromShortKey(shape),
|
||||||
@ -254,7 +265,7 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
* Returns whether we are playing in free-play
|
* Returns whether we are playing in free-play
|
||||||
*/
|
*/
|
||||||
isFreePlay() {
|
isFreePlay() {
|
||||||
return this.level >= tutorialGoals.length;
|
return this.level >= this.root.gameMode.getLevelDefinitions().length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -262,7 +273,7 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
* @param {string} upgradeId
|
* @param {string} upgradeId
|
||||||
*/
|
*/
|
||||||
canUnlockUpgrade(upgradeId) {
|
canUnlockUpgrade(upgradeId) {
|
||||||
const tiers = UPGRADES[upgradeId];
|
const tiers = this.root.gameMode.getUpgrades()[upgradeId];
|
||||||
const currentLevel = this.getUpgradeLevel(upgradeId);
|
const currentLevel = this.getUpgradeLevel(upgradeId);
|
||||||
|
|
||||||
if (currentLevel >= tiers.length) {
|
if (currentLevel >= tiers.length) {
|
||||||
@ -270,11 +281,6 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_DEMO && currentLevel >= 4) {
|
|
||||||
// DEMO
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (G_IS_DEV && globalConfig.debug.upgradesNoCost) {
|
if (G_IS_DEV && globalConfig.debug.upgradesNoCost) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -296,7 +302,7 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
*/
|
*/
|
||||||
getAvailableUpgradeCount() {
|
getAvailableUpgradeCount() {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
for (const upgradeId in UPGRADES) {
|
for (const upgradeId in this.root.gameMode.getUpgrades()) {
|
||||||
if (this.canUnlockUpgrade(upgradeId)) {
|
if (this.canUnlockUpgrade(upgradeId)) {
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
@ -314,7 +320,7 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const upgradeTiers = UPGRADES[upgradeId];
|
const upgradeTiers = this.root.gameMode.getUpgrades()[upgradeId];
|
||||||
const currentLevel = this.getUpgradeLevel(upgradeId);
|
const currentLevel = this.getUpgradeLevel(upgradeId);
|
||||||
|
|
||||||
const tierData = upgradeTiers[currentLevel];
|
const tierData = upgradeTiers[currentLevel];
|
||||||
@ -363,7 +369,7 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
if (allowUncolored) {
|
if (allowUncolored) {
|
||||||
universalColors.push(enumColors.uncolored);
|
universalColors.push(enumColors.uncolored);
|
||||||
}
|
}
|
||||||
const index = rng.nextIntRangeInclusive(0, colorWheel.length - 3);
|
const index = rng.nextIntRange(0, colorWheel.length - 2);
|
||||||
const pickedColors = colorWheel.slice(index, index + 3);
|
const pickedColors = colorWheel.slice(index, index + 3);
|
||||||
pickedColors.push(rng.choice(universalColors));
|
pickedColors.push(rng.choice(universalColors));
|
||||||
return pickedColors;
|
return pickedColors;
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import { HUDKeybindingOverlay } from "./parts/keybinding_overlay";
|
|||||||
import { HUDUnlockNotification } from "./parts/unlock_notification";
|
import { HUDUnlockNotification } from "./parts/unlock_notification";
|
||||||
import { HUDGameMenu } from "./parts/game_menu";
|
import { HUDGameMenu } from "./parts/game_menu";
|
||||||
import { HUDShop } from "./parts/shop";
|
import { HUDShop } from "./parts/shop";
|
||||||
import { IS_MOBILE, globalConfig, IS_DEMO } from "../../core/config";
|
import { IS_MOBILE, globalConfig } from "../../core/config";
|
||||||
import { HUDMassSelector } from "./parts/mass_selector";
|
import { HUDMassSelector } from "./parts/mass_selector";
|
||||||
import { HUDVignetteOverlay } from "./parts/vignette_overlay";
|
import { HUDVignetteOverlay } from "./parts/vignette_overlay";
|
||||||
import { HUDStatistics } from "./parts/statistics";
|
import { HUDStatistics } from "./parts/statistics";
|
||||||
@ -46,7 +46,6 @@ import { HUDEditConstantSignal } from "./parts/edit_constant_signal";
|
|||||||
import { HUDLayerPreview } from "./parts/layer_preview";
|
import { HUDLayerPreview } from "./parts/layer_preview";
|
||||||
import { HUDMinerHighlight } from "./parts/miner_highlight";
|
import { HUDMinerHighlight } from "./parts/miner_highlight";
|
||||||
import { HUDBetaOverlay } from "./parts/beta_overlay";
|
import { HUDBetaOverlay } from "./parts/beta_overlay";
|
||||||
import { HUDPerformanceWarning } from "./parts/performance_warning";
|
|
||||||
import { HUDStandaloneAdvantages } from "./parts/standalone_advantages";
|
import { HUDStandaloneAdvantages } from "./parts/standalone_advantages";
|
||||||
import { HUDCatMemes } from "./parts/cat_memes";
|
import { HUDCatMemes } from "./parts/cat_memes";
|
||||||
|
|
||||||
@ -90,7 +89,6 @@ export class GameHUD {
|
|||||||
layerPreview: new HUDLayerPreview(this.root),
|
layerPreview: new HUDLayerPreview(this.root),
|
||||||
|
|
||||||
minerHighlight: new HUDMinerHighlight(this.root),
|
minerHighlight: new HUDMinerHighlight(this.root),
|
||||||
performanceWarning: new HUDPerformanceWarning(this.root),
|
|
||||||
|
|
||||||
// Typing hints
|
// Typing hints
|
||||||
/* typehints:start */
|
/* typehints:start */
|
||||||
@ -118,7 +116,7 @@ export class GameHUD {
|
|||||||
this.parts.entityDebugger = new HUDEntityDebugger(this.root);
|
this.parts.entityDebugger = new HUDEntityDebugger(this.root);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_DEMO) {
|
if (this.root.app.restrictionMgr.getIsStandaloneMarketingActive()) {
|
||||||
this.parts.watermark = new HUDWatermark(this.root);
|
this.parts.watermark = new HUDWatermark(this.root);
|
||||||
this.parts.standaloneAdvantages = new HUDStandaloneAdvantages(this.root);
|
this.parts.standaloneAdvantages = new HUDStandaloneAdvantages(this.root);
|
||||||
this.parts.catMemes = new HUDCatMemes(this.root);
|
this.parts.catMemes = new HUDCatMemes(this.root);
|
||||||
|
|||||||
@ -7,7 +7,7 @@ export class HUDBetaOverlay extends BaseHUDPart {
|
|||||||
parent,
|
parent,
|
||||||
"ingame_HUD_BetaOverlay",
|
"ingame_HUD_BetaOverlay",
|
||||||
[],
|
[],
|
||||||
"<h2>UNSTABLE BETA VERSION</h2><span>Steam Release: 9th October 2020!</span>"
|
"<h2>UNSTABLE BETA VERSION</h2><span>Unfinalized & potential buggy content!</span>"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,202 +1,203 @@
|
|||||||
import { DrawParameters } from "../../../core/draw_parameters";
|
import { DrawParameters } from "../../../core/draw_parameters";
|
||||||
import { STOP_PROPAGATION } from "../../../core/signal";
|
import { STOP_PROPAGATION } from "../../../core/signal";
|
||||||
import { TrackedState } from "../../../core/tracked_state";
|
import { TrackedState } from "../../../core/tracked_state";
|
||||||
import { makeDiv } from "../../../core/utils";
|
import { makeDiv } from "../../../core/utils";
|
||||||
import { Vector } from "../../../core/vector";
|
import { Vector } from "../../../core/vector";
|
||||||
import { T } from "../../../translations";
|
import { SOUNDS } from "../../../platform/sound";
|
||||||
import { enumMouseButton } from "../../camera";
|
import { T } from "../../../translations";
|
||||||
import { KEYMAPPINGS } from "../../key_action_mapper";
|
import { Blueprint } from "../../blueprint";
|
||||||
import { blueprintShape } from "../../upgrades";
|
import { enumMouseButton } from "../../camera";
|
||||||
import { BaseHUDPart } from "../base_hud_part";
|
import { KEYMAPPINGS } from "../../key_action_mapper";
|
||||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
import { BaseHUDPart } from "../base_hud_part";
|
||||||
import { Blueprint } from "../../blueprint";
|
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||||
import { SOUNDS } from "../../../platform/sound";
|
|
||||||
|
export class HUDBlueprintPlacer extends BaseHUDPart {
|
||||||
export class HUDBlueprintPlacer extends BaseHUDPart {
|
createElements(parent) {
|
||||||
createElements(parent) {
|
const blueprintCostShape = this.root.shapeDefinitionMgr.getShapeFromShortKey(
|
||||||
const blueprintCostShape = this.root.shapeDefinitionMgr.getShapeFromShortKey(blueprintShape);
|
this.root.gameMode.getBlueprintShapeKey()
|
||||||
const blueprintCostShapeCanvas = blueprintCostShape.generateAsCanvas(80);
|
);
|
||||||
|
const blueprintCostShapeCanvas = blueprintCostShape.generateAsCanvas(80);
|
||||||
this.costDisplayParent = makeDiv(parent, "ingame_HUD_BlueprintPlacer", [], ``);
|
|
||||||
|
this.costDisplayParent = makeDiv(parent, "ingame_HUD_BlueprintPlacer", [], ``);
|
||||||
makeDiv(this.costDisplayParent, null, ["label"], T.ingame.blueprintPlacer.cost);
|
|
||||||
const costContainer = makeDiv(this.costDisplayParent, null, ["costContainer"], "");
|
makeDiv(this.costDisplayParent, null, ["label"], T.ingame.blueprintPlacer.cost);
|
||||||
this.costDisplayText = makeDiv(costContainer, null, ["costText"], "");
|
const costContainer = makeDiv(this.costDisplayParent, null, ["costContainer"], "");
|
||||||
costContainer.appendChild(blueprintCostShapeCanvas);
|
this.costDisplayText = makeDiv(costContainer, null, ["costText"], "");
|
||||||
}
|
costContainer.appendChild(blueprintCostShapeCanvas);
|
||||||
|
}
|
||||||
initialize() {
|
|
||||||
this.root.hud.signals.buildingsSelectedForCopy.add(this.createBlueprintFromBuildings, this);
|
initialize() {
|
||||||
|
this.root.hud.signals.buildingsSelectedForCopy.add(this.createBlueprintFromBuildings, this);
|
||||||
/** @type {TypedTrackedState<Blueprint?>} */
|
|
||||||
this.currentBlueprint = new TrackedState(this.onBlueprintChanged, this);
|
/** @type {TypedTrackedState<Blueprint?>} */
|
||||||
/** @type {Blueprint?} */
|
this.currentBlueprint = new TrackedState(this.onBlueprintChanged, this);
|
||||||
this.lastBlueprintUsed = null;
|
/** @type {Blueprint?} */
|
||||||
|
this.lastBlueprintUsed = null;
|
||||||
const keyActionMapper = this.root.keyMapper;
|
|
||||||
keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.abortPlacement, this);
|
const keyActionMapper = this.root.keyMapper;
|
||||||
keyActionMapper.getBinding(KEYMAPPINGS.placement.pipette).add(this.abortPlacement, this);
|
keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.abortPlacement, this);
|
||||||
keyActionMapper.getBinding(KEYMAPPINGS.placement.rotateWhilePlacing).add(this.rotateBlueprint, this);
|
keyActionMapper.getBinding(KEYMAPPINGS.placement.pipette).add(this.abortPlacement, this);
|
||||||
keyActionMapper.getBinding(KEYMAPPINGS.massSelect.pasteLastBlueprint).add(this.pasteBlueprint, this);
|
keyActionMapper.getBinding(KEYMAPPINGS.placement.rotateWhilePlacing).add(this.rotateBlueprint, this);
|
||||||
|
keyActionMapper.getBinding(KEYMAPPINGS.massSelect.pasteLastBlueprint).add(this.pasteBlueprint, this);
|
||||||
this.root.camera.downPreHandler.add(this.onMouseDown, this);
|
|
||||||
this.root.camera.movePreHandler.add(this.onMouseMove, this);
|
this.root.camera.downPreHandler.add(this.onMouseDown, this);
|
||||||
|
this.root.camera.movePreHandler.add(this.onMouseMove, this);
|
||||||
this.root.hud.signals.selectedPlacementBuildingChanged.add(this.abortPlacement, this);
|
|
||||||
this.root.signals.editModeChanged.add(this.onEditModeChanged, this);
|
this.root.hud.signals.selectedPlacementBuildingChanged.add(this.abortPlacement, this);
|
||||||
|
this.root.signals.editModeChanged.add(this.onEditModeChanged, this);
|
||||||
this.domAttach = new DynamicDomAttach(this.root, this.costDisplayParent);
|
|
||||||
this.trackedCanAfford = new TrackedState(this.onCanAffordChanged, this);
|
this.domAttach = new DynamicDomAttach(this.root, this.costDisplayParent);
|
||||||
}
|
this.trackedCanAfford = new TrackedState(this.onCanAffordChanged, this);
|
||||||
|
}
|
||||||
abortPlacement() {
|
|
||||||
if (this.currentBlueprint.get()) {
|
abortPlacement() {
|
||||||
this.currentBlueprint.set(null);
|
if (this.currentBlueprint.get()) {
|
||||||
|
this.currentBlueprint.set(null);
|
||||||
return STOP_PROPAGATION;
|
|
||||||
}
|
return STOP_PROPAGATION;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Called when the layer was changed
|
/**
|
||||||
* @param {Layer} layer
|
* Called when the layer was changed
|
||||||
*/
|
* @param {Layer} layer
|
||||||
onEditModeChanged(layer) {
|
*/
|
||||||
// Check if the layer of the blueprint differs and thus we have to deselect it
|
onEditModeChanged(layer) {
|
||||||
const blueprint = this.currentBlueprint.get();
|
// Check if the layer of the blueprint differs and thus we have to deselect it
|
||||||
if (blueprint) {
|
const blueprint = this.currentBlueprint.get();
|
||||||
if (blueprint.layer !== layer) {
|
if (blueprint) {
|
||||||
this.currentBlueprint.set(null);
|
if (blueprint.layer !== layer) {
|
||||||
}
|
this.currentBlueprint.set(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Called when the blueprint is now affordable or not
|
/**
|
||||||
* @param {boolean} canAfford
|
* Called when the blueprint is now affordable or not
|
||||||
*/
|
* @param {boolean} canAfford
|
||||||
onCanAffordChanged(canAfford) {
|
*/
|
||||||
this.costDisplayParent.classList.toggle("canAfford", canAfford);
|
onCanAffordChanged(canAfford) {
|
||||||
}
|
this.costDisplayParent.classList.toggle("canAfford", canAfford);
|
||||||
|
}
|
||||||
update() {
|
|
||||||
const currentBlueprint = this.currentBlueprint.get();
|
update() {
|
||||||
this.domAttach.update(currentBlueprint && currentBlueprint.getCost() > 0);
|
const currentBlueprint = this.currentBlueprint.get();
|
||||||
this.trackedCanAfford.set(currentBlueprint && currentBlueprint.canAfford(this.root));
|
this.domAttach.update(currentBlueprint && currentBlueprint.getCost() > 0);
|
||||||
}
|
this.trackedCanAfford.set(currentBlueprint && currentBlueprint.canAfford(this.root));
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Called when the blueprint was changed
|
/**
|
||||||
* @param {Blueprint} blueprint
|
* Called when the blueprint was changed
|
||||||
*/
|
* @param {Blueprint} blueprint
|
||||||
onBlueprintChanged(blueprint) {
|
*/
|
||||||
if (blueprint) {
|
onBlueprintChanged(blueprint) {
|
||||||
this.lastBlueprintUsed = blueprint;
|
if (blueprint) {
|
||||||
this.costDisplayText.innerText = "" + blueprint.getCost();
|
this.lastBlueprintUsed = blueprint;
|
||||||
}
|
this.costDisplayText.innerText = "" + blueprint.getCost();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* mouse down pre handler
|
/**
|
||||||
* @param {Vector} pos
|
* mouse down pre handler
|
||||||
* @param {enumMouseButton} button
|
* @param {Vector} pos
|
||||||
*/
|
* @param {enumMouseButton} button
|
||||||
onMouseDown(pos, button) {
|
*/
|
||||||
if (button === enumMouseButton.right) {
|
onMouseDown(pos, button) {
|
||||||
if (this.currentBlueprint.get()) {
|
if (button === enumMouseButton.right) {
|
||||||
this.abortPlacement();
|
if (this.currentBlueprint.get()) {
|
||||||
return STOP_PROPAGATION;
|
this.abortPlacement();
|
||||||
}
|
return STOP_PROPAGATION;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
const blueprint = this.currentBlueprint.get();
|
|
||||||
if (!blueprint) {
|
const blueprint = this.currentBlueprint.get();
|
||||||
return;
|
if (!blueprint) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
if (!blueprint.canAfford(this.root)) {
|
|
||||||
this.root.soundProxy.playUiError();
|
if (!blueprint.canAfford(this.root)) {
|
||||||
return;
|
this.root.soundProxy.playUiError();
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
const worldPos = this.root.camera.screenToWorld(pos);
|
|
||||||
const tile = worldPos.toTileSpace();
|
const worldPos = this.root.camera.screenToWorld(pos);
|
||||||
if (blueprint.tryPlace(this.root, tile)) {
|
const tile = worldPos.toTileSpace();
|
||||||
const cost = blueprint.getCost();
|
if (blueprint.tryPlace(this.root, tile)) {
|
||||||
this.root.hubGoals.takeShapeByKey(blueprintShape, cost);
|
const cost = blueprint.getCost();
|
||||||
this.root.soundProxy.playUi(SOUNDS.placeBuilding);
|
this.root.hubGoals.takeShapeByKey(this.root.gameMode.getBlueprintShapeKey(), cost);
|
||||||
}
|
this.root.soundProxy.playUi(SOUNDS.placeBuilding);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Mose move handler
|
/**
|
||||||
*/
|
* Mose move handler
|
||||||
onMouseMove() {
|
*/
|
||||||
// Prevent movement while blueprint is selected
|
onMouseMove() {
|
||||||
if (this.currentBlueprint.get()) {
|
// Prevent movement while blueprint is selected
|
||||||
return STOP_PROPAGATION;
|
if (this.currentBlueprint.get()) {
|
||||||
}
|
return STOP_PROPAGATION;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Called when an array of bulidings was selected
|
/**
|
||||||
* @param {Array<number>} uids
|
* Called when an array of bulidings was selected
|
||||||
*/
|
* @param {Array<number>} uids
|
||||||
createBlueprintFromBuildings(uids) {
|
*/
|
||||||
if (uids.length === 0) {
|
createBlueprintFromBuildings(uids) {
|
||||||
return;
|
if (uids.length === 0) {
|
||||||
}
|
return;
|
||||||
this.currentBlueprint.set(Blueprint.fromUids(this.root, uids));
|
}
|
||||||
}
|
this.currentBlueprint.set(Blueprint.fromUids(this.root, uids));
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Attempts to rotate the current blueprint
|
/**
|
||||||
*/
|
* Attempts to rotate the current blueprint
|
||||||
rotateBlueprint() {
|
*/
|
||||||
if (this.currentBlueprint.get()) {
|
rotateBlueprint() {
|
||||||
if (this.root.keyMapper.getBinding(KEYMAPPINGS.placement.rotateInverseModifier).pressed) {
|
if (this.currentBlueprint.get()) {
|
||||||
this.currentBlueprint.get().rotateCcw();
|
if (this.root.keyMapper.getBinding(KEYMAPPINGS.placement.rotateInverseModifier).pressed) {
|
||||||
} else {
|
this.currentBlueprint.get().rotateCcw();
|
||||||
this.currentBlueprint.get().rotateCw();
|
} else {
|
||||||
}
|
this.currentBlueprint.get().rotateCw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Attempts to paste the last blueprint
|
/**
|
||||||
*/
|
* Attempts to paste the last blueprint
|
||||||
pasteBlueprint() {
|
*/
|
||||||
if (this.lastBlueprintUsed !== null) {
|
pasteBlueprint() {
|
||||||
if (this.lastBlueprintUsed.layer !== this.root.currentLayer) {
|
if (this.lastBlueprintUsed !== null) {
|
||||||
// Not compatible
|
if (this.lastBlueprintUsed.layer !== this.root.currentLayer) {
|
||||||
this.root.soundProxy.playUiError();
|
// Not compatible
|
||||||
return;
|
this.root.soundProxy.playUiError();
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
this.root.hud.signals.pasteBlueprintRequested.dispatch();
|
|
||||||
this.currentBlueprint.set(this.lastBlueprintUsed);
|
this.root.hud.signals.pasteBlueprintRequested.dispatch();
|
||||||
} else {
|
this.currentBlueprint.set(this.lastBlueprintUsed);
|
||||||
this.root.soundProxy.playUiError();
|
} else {
|
||||||
}
|
this.root.soundProxy.playUiError();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
*
|
/**
|
||||||
* @param {DrawParameters} parameters
|
*
|
||||||
*/
|
* @param {DrawParameters} parameters
|
||||||
draw(parameters) {
|
*/
|
||||||
const blueprint = this.currentBlueprint.get();
|
draw(parameters) {
|
||||||
if (!blueprint) {
|
const blueprint = this.currentBlueprint.get();
|
||||||
return;
|
if (!blueprint) {
|
||||||
}
|
return;
|
||||||
const mousePosition = this.root.app.mousePosition;
|
}
|
||||||
if (!mousePosition) {
|
const mousePosition = this.root.app.mousePosition;
|
||||||
// Not on screen
|
if (!mousePosition) {
|
||||||
return;
|
// Not on screen
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
const worldPos = this.root.camera.screenToWorld(mousePosition);
|
|
||||||
const tile = worldPos.toTileSpace();
|
const worldPos = this.root.camera.screenToWorld(mousePosition);
|
||||||
blueprint.draw(parameters, tile);
|
const tile = worldPos.toTileSpace();
|
||||||
}
|
blueprint.draw(parameters, tile);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,16 +0,0 @@
|
|||||||
import { T } from "../../../translations";
|
|
||||||
import { BaseHUDPart } from "../base_hud_part";
|
|
||||||
|
|
||||||
export class HUDPerformanceWarning extends BaseHUDPart {
|
|
||||||
initialize() {
|
|
||||||
this.warningShown = false;
|
|
||||||
this.root.signals.entityManuallyPlaced.add(this.checkAfterPlace, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
checkAfterPlace() {
|
|
||||||
if (!this.warningShown && this.root.entityMgr.entities.length > 10000) {
|
|
||||||
this.root.hud.parts.dialogs.showInfo(T.dialogs.entityWarning.title, T.dialogs.entityWarning.desc);
|
|
||||||
this.warningShown = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,12 +1,11 @@
|
|||||||
import { ClickDetector } from "../../../core/click_detector";
|
import { ClickDetector } from "../../../core/click_detector";
|
||||||
import { formatBigNumber, makeDiv, arrayDeleteValue } from "../../../core/utils";
|
|
||||||
import { ShapeDefinition } from "../../shape_definition";
|
|
||||||
import { BaseHUDPart } from "../base_hud_part";
|
|
||||||
import { blueprintShape, UPGRADES } from "../../upgrades";
|
|
||||||
import { enumHubGoalRewards } from "../../tutorial_goals";
|
|
||||||
import { enumAnalyticsDataSource } from "../../production_analytics";
|
|
||||||
import { T } from "../../../translations";
|
|
||||||
import { globalConfig } from "../../../core/config";
|
import { globalConfig } from "../../../core/config";
|
||||||
|
import { arrayDeleteValue, formatBigNumber, makeDiv } from "../../../core/utils";
|
||||||
|
import { T } from "../../../translations";
|
||||||
|
import { enumAnalyticsDataSource } from "../../production_analytics";
|
||||||
|
import { ShapeDefinition } from "../../shape_definition";
|
||||||
|
import { enumHubGoalRewards } from "../../tutorial_goals";
|
||||||
|
import { BaseHUDPart } from "../base_hud_part";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages the pinned shapes on the left side of the screen
|
* Manages the pinned shapes on the left side of the screen
|
||||||
@ -82,7 +81,7 @@ export class HUDPinnedShapes extends BaseHUDPart {
|
|||||||
updateShapesAfterUpgrade() {
|
updateShapesAfterUpgrade() {
|
||||||
for (let i = 0; i < this.pinnedShapes.length; ++i) {
|
for (let i = 0; i < this.pinnedShapes.length; ++i) {
|
||||||
const key = this.pinnedShapes[i];
|
const key = this.pinnedShapes[i];
|
||||||
if (key === blueprintShape) {
|
if (key === this.root.gameMode.getBlueprintShapeKey()) {
|
||||||
// Ignore blueprint shapes
|
// Ignore blueprint shapes
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -107,13 +106,14 @@ export class HUDPinnedShapes extends BaseHUDPart {
|
|||||||
if (key === this.root.hubGoals.currentGoal.definition.getHash()) {
|
if (key === this.root.hubGoals.currentGoal.definition.getHash()) {
|
||||||
return this.root.hubGoals.currentGoal.required;
|
return this.root.hubGoals.currentGoal.required;
|
||||||
}
|
}
|
||||||
if (key === blueprintShape) {
|
if (key === this.root.gameMode.getBlueprintShapeKey()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this shape is required for any upgrade
|
// Check if this shape is required for any upgrade
|
||||||
for (const upgradeId in UPGRADES) {
|
const upgrades = this.root.gameMode.getUpgrades();
|
||||||
const upgradeTiers = UPGRADES[upgradeId];
|
for (const upgradeId in upgrades) {
|
||||||
|
const upgradeTiers = upgrades[upgradeId];
|
||||||
const currentTier = this.root.hubGoals.getUpgradeLevel(upgradeId);
|
const currentTier = this.root.hubGoals.getUpgradeLevel(upgradeId);
|
||||||
const tierHandle = upgradeTiers[currentTier];
|
const tierHandle = upgradeTiers[currentTier];
|
||||||
|
|
||||||
@ -138,7 +138,10 @@ export class HUDPinnedShapes extends BaseHUDPart {
|
|||||||
* @param {string} key
|
* @param {string} key
|
||||||
*/
|
*/
|
||||||
isShapePinned(key) {
|
isShapePinned(key) {
|
||||||
if (key === this.root.hubGoals.currentGoal.definition.getHash() || key === blueprintShape) {
|
if (
|
||||||
|
key === this.root.hubGoals.currentGoal.definition.getHash() ||
|
||||||
|
key === this.root.gameMode.getBlueprintShapeKey()
|
||||||
|
) {
|
||||||
// This is a "special" shape which is always pinned
|
// This is a "special" shape which is always pinned
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -178,7 +181,7 @@ export class HUDPinnedShapes extends BaseHUDPart {
|
|||||||
// Pin blueprint shape as well
|
// Pin blueprint shape as well
|
||||||
if (this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_blueprints)) {
|
if (this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_blueprints)) {
|
||||||
this.internalPinShape({
|
this.internalPinShape({
|
||||||
key: blueprintShape,
|
key: this.root.gameMode.getBlueprintShapeKey(),
|
||||||
canUnpin: false,
|
canUnpin: false,
|
||||||
className: "blueprint",
|
className: "blueprint",
|
||||||
});
|
});
|
||||||
@ -214,11 +217,11 @@ export class HUDPinnedShapes extends BaseHUDPart {
|
|||||||
|
|
||||||
let detector = null;
|
let detector = null;
|
||||||
if (canUnpin) {
|
if (canUnpin) {
|
||||||
element.classList.add("unpinable");
|
element.classList.add("removable");
|
||||||
detector = new ClickDetector(element, {
|
detector = new ClickDetector(element, {
|
||||||
consumeEvents: true,
|
consumeEvents: true,
|
||||||
preventDefault: true,
|
preventDefault: true,
|
||||||
targetOnly: true,
|
targetOnly: false,
|
||||||
});
|
});
|
||||||
detector.click.add(() => this.unpinShape(key));
|
detector.click.add(() => this.unpinShape(key));
|
||||||
} else {
|
} else {
|
||||||
@ -291,6 +294,7 @@ export class HUDPinnedShapes extends BaseHUDPart {
|
|||||||
* @param {string} key
|
* @param {string} key
|
||||||
*/
|
*/
|
||||||
unpinShape(key) {
|
unpinShape(key) {
|
||||||
|
console.log("unpin", key);
|
||||||
arrayDeleteValue(this.pinnedShapes, key);
|
arrayDeleteValue(this.pinnedShapes, key);
|
||||||
this.rerenderFull();
|
this.rerenderFull();
|
||||||
}
|
}
|
||||||
@ -306,7 +310,7 @@ export class HUDPinnedShapes extends BaseHUDPart {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === blueprintShape) {
|
if (key === this.root.gameMode.getBlueprintShapeKey()) {
|
||||||
// Can not pin the blueprint shape
|
// Can not pin the blueprint shape
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
import { BaseHUDPart } from "../base_hud_part";
|
|
||||||
import { makeDiv } from "../../../core/utils";
|
import { makeDiv } from "../../../core/utils";
|
||||||
|
import { BaseHUDPart } from "../base_hud_part";
|
||||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||||
import { blueprintShape, UPGRADES } from "../../upgrades";
|
|
||||||
import { enumNotificationType } from "./notifications";
|
import { enumNotificationType } from "./notifications";
|
||||||
import { tutorialGoals } from "../../tutorial_goals";
|
|
||||||
|
|
||||||
export class HUDSandboxController extends BaseHUDPart {
|
export class HUDSandboxController extends BaseHUDPart {
|
||||||
createElements(parent) {
|
createElements(parent) {
|
||||||
@ -75,10 +73,11 @@ export class HUDSandboxController extends BaseHUDPart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
giveBlueprints() {
|
giveBlueprints() {
|
||||||
if (!this.root.hubGoals.storedShapes[blueprintShape]) {
|
const shape = this.root.gameMode.getBlueprintShapeKey();
|
||||||
this.root.hubGoals.storedShapes[blueprintShape] = 0;
|
if (!this.root.hubGoals.storedShapes[shape]) {
|
||||||
|
this.root.hubGoals.storedShapes[shape] = 0;
|
||||||
}
|
}
|
||||||
this.root.hubGoals.storedShapes[blueprintShape] += 1e9;
|
this.root.hubGoals.storedShapes[shape] += 1e9;
|
||||||
}
|
}
|
||||||
|
|
||||||
maxOutAll() {
|
maxOutAll() {
|
||||||
@ -89,7 +88,7 @@ export class HUDSandboxController extends BaseHUDPart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
modifyUpgrade(id, amount) {
|
modifyUpgrade(id, amount) {
|
||||||
const upgradeTiers = UPGRADES[id];
|
const upgradeTiers = this.root.gameMode.getUpgrades()[id];
|
||||||
const maxLevel = upgradeTiers.length;
|
const maxLevel = upgradeTiers.length;
|
||||||
|
|
||||||
this.root.hubGoals.upgradeLevels[id] = Math.max(
|
this.root.hubGoals.upgradeLevels[id] = Math.max(
|
||||||
@ -122,9 +121,10 @@ export class HUDSandboxController extends BaseHUDPart {
|
|||||||
|
|
||||||
// Compute gained rewards
|
// Compute gained rewards
|
||||||
hubGoals.gainedRewards = {};
|
hubGoals.gainedRewards = {};
|
||||||
|
const levels = this.root.gameMode.getLevelDefinitions();
|
||||||
for (let i = 0; i < hubGoals.level - 1; ++i) {
|
for (let i = 0; i < hubGoals.level - 1; ++i) {
|
||||||
if (i < tutorialGoals.length) {
|
if (i < levels.length) {
|
||||||
const reward = tutorialGoals[i].reward;
|
const reward = levels[i].reward;
|
||||||
hubGoals.gainedRewards[reward] = (hubGoals.gainedRewards[reward] || 0) + 1;
|
hubGoals.gainedRewards[reward] = (hubGoals.gainedRewards[reward] || 0) + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
import { BaseHUDPart } from "../base_hud_part";
|
|
||||||
import { KEYMAPPINGS } from "../../key_action_mapper";
|
|
||||||
import { IS_DEMO, globalConfig } from "../../../core/config";
|
|
||||||
import { T } from "../../../translations";
|
|
||||||
import { createLogger } from "../../../core/logging";
|
|
||||||
import { StaticMapEntityComponent } from "../../components/static_map_entity";
|
|
||||||
import { Vector } from "../../../core/vector";
|
|
||||||
import { makeOffscreenBuffer } from "../../../core/buffer_utils";
|
import { makeOffscreenBuffer } from "../../../core/buffer_utils";
|
||||||
|
import { globalConfig } from "../../../core/config";
|
||||||
import { DrawParameters } from "../../../core/draw_parameters";
|
import { DrawParameters } from "../../../core/draw_parameters";
|
||||||
|
import { createLogger } from "../../../core/logging";
|
||||||
import { Rectangle } from "../../../core/rectangle";
|
import { Rectangle } from "../../../core/rectangle";
|
||||||
|
import { Vector } from "../../../core/vector";
|
||||||
|
import { T } from "../../../translations";
|
||||||
|
import { StaticMapEntityComponent } from "../../components/static_map_entity";
|
||||||
|
import { KEYMAPPINGS } from "../../key_action_mapper";
|
||||||
|
import { BaseHUDPart } from "../base_hud_part";
|
||||||
|
|
||||||
const logger = createLogger("screenshot_exporter");
|
const logger = createLogger("screenshot_exporter");
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ export class HUDScreenshotExporter extends BaseHUDPart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
startExport() {
|
startExport() {
|
||||||
if (IS_DEMO) {
|
if (!this.root.app.restrictionMgr.getIsExportingScreenshotsPossible()) {
|
||||||
this.root.hud.parts.dialogs.showFeatureRestrictionInfo(T.demo.features.exportingBase);
|
this.root.hud.parts.dialogs.showFeatureRestrictionInfo(T.demo.features.exportingBase);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -87,7 +87,7 @@ export class HUDScreenshotExporter extends BaseHUDPart {
|
|||||||
const parameters = new DrawParameters({
|
const parameters = new DrawParameters({
|
||||||
context,
|
context,
|
||||||
visibleRect,
|
visibleRect,
|
||||||
desiredAtlasScale: chunkScale,
|
desiredAtlasScale: 0.25,
|
||||||
root: this.root,
|
root: this.root,
|
||||||
zoomLevel: chunkScale,
|
zoomLevel: chunkScale,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
import { ClickDetector } from "../../../core/click_detector";
|
import { ClickDetector } from "../../../core/click_detector";
|
||||||
import { InputReceiver } from "../../../core/input_receiver";
|
import { InputReceiver } from "../../../core/input_receiver";
|
||||||
import { formatBigNumber, makeDiv } from "../../../core/utils";
|
import { formatBigNumber, getRomanNumber, makeDiv } from "../../../core/utils";
|
||||||
import { T } from "../../../translations";
|
import { T } from "../../../translations";
|
||||||
import { KeyActionMapper, KEYMAPPINGS } from "../../key_action_mapper";
|
import { KeyActionMapper, KEYMAPPINGS } from "../../key_action_mapper";
|
||||||
import { UPGRADES } from "../../upgrades";
|
|
||||||
import { BaseHUDPart } from "../base_hud_part";
|
import { BaseHUDPart } from "../base_hud_part";
|
||||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||||
|
|
||||||
@ -21,7 +20,7 @@ export class HUDShop extends BaseHUDPart {
|
|||||||
this.upgradeToElements = {};
|
this.upgradeToElements = {};
|
||||||
|
|
||||||
// Upgrades
|
// Upgrades
|
||||||
for (const upgradeId in UPGRADES) {
|
for (const upgradeId in this.root.gameMode.getUpgrades()) {
|
||||||
const handle = {};
|
const handle = {};
|
||||||
handle.requireIndexToElement = [];
|
handle.requireIndexToElement = [];
|
||||||
|
|
||||||
@ -59,7 +58,7 @@ export class HUDShop extends BaseHUDPart {
|
|||||||
rerenderFull() {
|
rerenderFull() {
|
||||||
for (const upgradeId in this.upgradeToElements) {
|
for (const upgradeId in this.upgradeToElements) {
|
||||||
const handle = this.upgradeToElements[upgradeId];
|
const handle = this.upgradeToElements[upgradeId];
|
||||||
const upgradeTiers = UPGRADES[upgradeId];
|
const upgradeTiers = this.root.gameMode.getUpgrades()[upgradeId];
|
||||||
|
|
||||||
const currentTier = this.root.hubGoals.getUpgradeLevel(upgradeId);
|
const currentTier = this.root.hubGoals.getUpgradeLevel(upgradeId);
|
||||||
const currentTierMultiplier = this.root.hubGoals.upgradeImprovements[upgradeId];
|
const currentTierMultiplier = this.root.hubGoals.upgradeImprovements[upgradeId];
|
||||||
@ -68,7 +67,7 @@ export class HUDShop extends BaseHUDPart {
|
|||||||
// Set tier
|
// Set tier
|
||||||
handle.elemTierLabel.innerText = T.ingame.shop.tier.replace(
|
handle.elemTierLabel.innerText = T.ingame.shop.tier.replace(
|
||||||
"<x>",
|
"<x>",
|
||||||
"" + T.ingame.shop.tierLabels[currentTier]
|
getRomanNumber(currentTier + 1)
|
||||||
);
|
);
|
||||||
|
|
||||||
handle.elemTierLabel.setAttribute("data-tier", currentTier);
|
handle.elemTierLabel.setAttribute("data-tier", currentTier);
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
import { globalConfig } from "../../../core/config";
|
import { globalConfig } from "../../../core/config";
|
||||||
import { gMetaBuildingRegistry } from "../../../core/global_registries";
|
import { gMetaBuildingRegistry } from "../../../core/global_registries";
|
||||||
|
import { InputReceiver } from "../../../core/input_receiver";
|
||||||
import { makeDiv } from "../../../core/utils";
|
import { makeDiv } from "../../../core/utils";
|
||||||
import { SOUNDS } from "../../../platform/sound";
|
import { SOUNDS } from "../../../platform/sound";
|
||||||
import { T } from "../../../translations";
|
import { T } from "../../../translations";
|
||||||
import { defaultBuildingVariant } from "../../meta_building";
|
import { defaultBuildingVariant } from "../../meta_building";
|
||||||
import { enumHubGoalRewards, tutorialGoals } from "../../tutorial_goals";
|
import { enumHubGoalRewards } from "../../tutorial_goals";
|
||||||
|
import { enumHubGoalRewardsToContentUnlocked } from "../../tutorial_goals_mappings";
|
||||||
import { BaseHUDPart } from "../base_hud_part";
|
import { BaseHUDPart } from "../base_hud_part";
|
||||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||||
import { enumHubGoalRewardsToContentUnlocked } from "../../tutorial_goals_mappings";
|
|
||||||
import { InputReceiver } from "../../../core/input_receiver";
|
|
||||||
import { enumNotificationType } from "./notifications";
|
import { enumNotificationType } from "./notifications";
|
||||||
|
|
||||||
export class HUDUnlockNotification extends BaseHUDPart {
|
export class HUDUnlockNotification extends BaseHUDPart {
|
||||||
@ -53,7 +53,9 @@ export class HUDUnlockNotification extends BaseHUDPart {
|
|||||||
showForLevel(level, reward) {
|
showForLevel(level, reward) {
|
||||||
this.root.soundProxy.playUi(SOUNDS.levelComplete);
|
this.root.soundProxy.playUi(SOUNDS.levelComplete);
|
||||||
|
|
||||||
if (level > tutorialGoals.length) {
|
const levels = this.root.gameMode.getLevelDefinitions();
|
||||||
|
// Don't use getIsFreeplay() because we want the freeplay level up to show
|
||||||
|
if (level > levels.length) {
|
||||||
this.root.hud.signals.notification.dispatch(
|
this.root.hud.signals.notification.dispatch(
|
||||||
T.ingame.notifications.freeplayLevelComplete.replace("<level>", String(level)),
|
T.ingame.notifications.freeplayLevelComplete.replace("<level>", String(level)),
|
||||||
enumNotificationType.success
|
enumNotificationType.success
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { makeOffscreenBuffer } from "../../../core/buffer_utils";
|
import { makeOffscreenBuffer } from "../../../core/buffer_utils";
|
||||||
import { globalConfig, IS_DEMO, THIRDPARTY_URLS } from "../../../core/config";
|
import { globalConfig, THIRDPARTY_URLS } from "../../../core/config";
|
||||||
import { DrawParameters } from "../../../core/draw_parameters";
|
import { DrawParameters } from "../../../core/draw_parameters";
|
||||||
import { Loader } from "../../../core/loader";
|
import { Loader } from "../../../core/loader";
|
||||||
import { DialogWithForm } from "../../../core/modal_dialog_elements";
|
import { DialogWithForm } from "../../../core/modal_dialog_elements";
|
||||||
@ -302,7 +302,7 @@ export class HUDWaypoints extends BaseHUDPart {
|
|||||||
// Show info that you can have only N markers in the demo,
|
// Show info that you can have only N markers in the demo,
|
||||||
// actually show this *after* entering the name so you want the
|
// actually show this *after* entering the name so you want the
|
||||||
// standalone even more (I'm evil :P)
|
// standalone even more (I'm evil :P)
|
||||||
if (IS_DEMO && this.waypoints.length > 2) {
|
if (this.waypoints.length > this.root.app.restrictionMgr.getMaximumWaypoints()) {
|
||||||
this.root.hud.parts.dialogs.showFeatureRestrictionInfo(
|
this.root.hud.parts.dialogs.showFeatureRestrictionInfo(
|
||||||
"",
|
"",
|
||||||
T.dialogs.markerDemoLimit.desc
|
T.dialogs.markerDemoLimit.desc
|
||||||
|
|||||||
@ -248,6 +248,8 @@ export function getStringForKeyCode(code) {
|
|||||||
return ",";
|
return ",";
|
||||||
case 189:
|
case 189:
|
||||||
return "-";
|
return "-";
|
||||||
|
case 190:
|
||||||
|
return ".";
|
||||||
case 191:
|
case 191:
|
||||||
return "/";
|
return "/";
|
||||||
case 219:
|
case 219:
|
||||||
@ -260,7 +262,9 @@ export function getStringForKeyCode(code) {
|
|||||||
return "'";
|
return "'";
|
||||||
}
|
}
|
||||||
|
|
||||||
return String.fromCharCode(code);
|
return (48 <= code && code <= 57) || (65 <= code && code <= 90)
|
||||||
|
? String.fromCharCode(code)
|
||||||
|
: "[" + code + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Keybinding {
|
export class Keybinding {
|
||||||
|
|||||||
480
src/js/game/modes/regular.js
Normal file
@ -0,0 +1,480 @@
|
|||||||
|
import { findNiceIntegerValue } from "../../core/utils";
|
||||||
|
import { GameMode } from "../game_mode";
|
||||||
|
import { ShapeDefinition } from "../shape_definition";
|
||||||
|
import { enumHubGoalRewards } from "../tutorial_goals";
|
||||||
|
|
||||||
|
const rocketShape = "CbCuCbCu:Sr------:--CrSrCr:CwCwCwCw";
|
||||||
|
const finalGameShape = "RuCw--Cw:----Ru--";
|
||||||
|
const preparementShape = "CpRpCp--:SwSwSwSw";
|
||||||
|
const blueprintShape = "CbCbCbRb:CwCwCwCw";
|
||||||
|
|
||||||
|
// Tiers need % of the previous tier as requirement too
|
||||||
|
const tierGrowth = 2.5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates all upgrades
|
||||||
|
* @returns {Object<string, import("../game_mode").UpgradeTiers>} */
|
||||||
|
function generateUpgrades(limitedVersion = false) {
|
||||||
|
const fixedImprovements = [0.5, 0.5, 1, 1, 2, 1, 1];
|
||||||
|
const numEndgameUpgrades = limitedVersion ? 0 : 1000 - fixedImprovements.length - 1;
|
||||||
|
|
||||||
|
function generateInfiniteUnlocks() {
|
||||||
|
return new Array(numEndgameUpgrades).fill(null).map((_, i) => ({
|
||||||
|
required: [
|
||||||
|
{ shape: preparementShape, amount: 30000 + i * 10000 },
|
||||||
|
{ shape: finalGameShape, amount: 20000 + i * 5000 },
|
||||||
|
{ shape: rocketShape, amount: 20000 + i * 5000 },
|
||||||
|
],
|
||||||
|
excludePrevious: true,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill in endgame upgrades
|
||||||
|
for (let i = 0; i < numEndgameUpgrades; ++i) {
|
||||||
|
if (i < 20) {
|
||||||
|
fixedImprovements.push(0.1);
|
||||||
|
} else if (i < 50) {
|
||||||
|
fixedImprovements.push(0.05);
|
||||||
|
} else if (i < 100) {
|
||||||
|
fixedImprovements.push(0.025);
|
||||||
|
} else {
|
||||||
|
fixedImprovements.push(0.0125);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const upgrades = {
|
||||||
|
belt: [
|
||||||
|
{
|
||||||
|
required: [{ shape: "CuCuCuCu", amount: 60 }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [{ shape: "--CuCu--", amount: 500 }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [{ shape: "CpCpCpCp", amount: 1000 }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [{ shape: "SrSrSrSr:CyCyCyCy", amount: 6000 }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [{ shape: "SrSrSrSr:CyCyCyCy:SwSwSwSw", amount: 25000 }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [{ shape: preparementShape, amount: 25000 }],
|
||||||
|
excludePrevious: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [
|
||||||
|
{ shape: preparementShape, amount: 25000 },
|
||||||
|
{ shape: finalGameShape, amount: 50000 },
|
||||||
|
],
|
||||||
|
excludePrevious: true,
|
||||||
|
},
|
||||||
|
...generateInfiniteUnlocks(),
|
||||||
|
],
|
||||||
|
|
||||||
|
miner: [
|
||||||
|
{
|
||||||
|
required: [{ shape: "RuRuRuRu", amount: 300 }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [{ shape: "Cu------", amount: 800 }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [{ shape: "ScScScSc", amount: 3500 }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [{ shape: "CwCwCwCw:WbWbWbWb", amount: 23000 }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [{ shape: "CbRbRbCb:CwCwCwCw:WbWbWbWb", amount: 50000 }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [{ shape: preparementShape, amount: 25000 }],
|
||||||
|
excludePrevious: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [
|
||||||
|
{ shape: preparementShape, amount: 25000 },
|
||||||
|
{ shape: finalGameShape, amount: 50000 },
|
||||||
|
],
|
||||||
|
excludePrevious: true,
|
||||||
|
},
|
||||||
|
...generateInfiniteUnlocks(),
|
||||||
|
],
|
||||||
|
|
||||||
|
processors: [
|
||||||
|
{
|
||||||
|
required: [{ shape: "SuSuSuSu", amount: 500 }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [{ shape: "RuRu----", amount: 600 }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [{ shape: "CgScScCg", amount: 3500 }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [{ shape: "CwCrCwCr:SgSgSgSg", amount: 25000 }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [{ shape: "WrRgWrRg:CwCrCwCr:SgSgSgSg", amount: 50000 }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [{ shape: preparementShape, amount: 25000 }],
|
||||||
|
excludePrevious: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [
|
||||||
|
{ shape: preparementShape, amount: 25000 },
|
||||||
|
{ shape: finalGameShape, amount: 50000 },
|
||||||
|
],
|
||||||
|
excludePrevious: true,
|
||||||
|
},
|
||||||
|
...generateInfiniteUnlocks(),
|
||||||
|
],
|
||||||
|
|
||||||
|
painting: [
|
||||||
|
{
|
||||||
|
required: [{ shape: "RbRb----", amount: 600 }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [{ shape: "WrWrWrWr", amount: 3800 }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [{ shape: "RpRpRpRp:CwCwCwCw", amount: 6500 }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [{ shape: "WpWpWpWp:CwCwCwCw:WpWpWpWp", amount: 25000 }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [{ shape: "WpWpWpWp:CwCwCwCw:WpWpWpWp:CwCwCwCw", amount: 50000 }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [{ shape: preparementShape, amount: 25000 }],
|
||||||
|
excludePrevious: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: [
|
||||||
|
{ shape: preparementShape, amount: 25000 },
|
||||||
|
{ shape: finalGameShape, amount: 50000 },
|
||||||
|
],
|
||||||
|
excludePrevious: true,
|
||||||
|
},
|
||||||
|
...generateInfiniteUnlocks(),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
// Automatically generate tier levels
|
||||||
|
for (const upgradeId in upgrades) {
|
||||||
|
const upgradeTiers = upgrades[upgradeId];
|
||||||
|
|
||||||
|
let currentTierRequirements = [];
|
||||||
|
for (let i = 0; i < upgradeTiers.length; ++i) {
|
||||||
|
const tierHandle = upgradeTiers[i];
|
||||||
|
tierHandle.improvement = fixedImprovements[i];
|
||||||
|
const originalRequired = tierHandle.required.slice();
|
||||||
|
|
||||||
|
for (let k = currentTierRequirements.length - 1; k >= 0; --k) {
|
||||||
|
const oldTierRequirement = currentTierRequirements[k];
|
||||||
|
if (!tierHandle.excludePrevious) {
|
||||||
|
tierHandle.required.unshift({
|
||||||
|
shape: oldTierRequirement.shape,
|
||||||
|
amount: oldTierRequirement.amount,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentTierRequirements.push(
|
||||||
|
...originalRequired.map(req => ({
|
||||||
|
amount: req.amount,
|
||||||
|
shape: req.shape,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
currentTierRequirements.forEach(tier => {
|
||||||
|
tier.amount = findNiceIntegerValue(tier.amount * tierGrowth);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// VALIDATE
|
||||||
|
if (G_IS_DEV) {
|
||||||
|
for (const upgradeId in upgrades) {
|
||||||
|
upgrades[upgradeId].forEach(tier => {
|
||||||
|
tier.required.forEach(({ shape }) => {
|
||||||
|
try {
|
||||||
|
ShapeDefinition.fromShortKey(shape);
|
||||||
|
} catch (ex) {
|
||||||
|
throw new Error("Invalid upgrade goal: '" + ex + "' for shape" + shape);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return upgrades;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the level definitions
|
||||||
|
* @param {boolean} limitedVersion
|
||||||
|
*/
|
||||||
|
export function generateLevelDefinitions(limitedVersion = false) {
|
||||||
|
const levelDefinitions = [
|
||||||
|
// 1
|
||||||
|
// Circle
|
||||||
|
{
|
||||||
|
shape: "CuCuCuCu", // belts t1
|
||||||
|
required: 30,
|
||||||
|
reward: enumHubGoalRewards.reward_cutter_and_trash,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 2
|
||||||
|
// Cutter
|
||||||
|
{
|
||||||
|
shape: "----CuCu", //
|
||||||
|
required: 40,
|
||||||
|
reward: enumHubGoalRewards.no_reward,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 3
|
||||||
|
// Rectangle
|
||||||
|
{
|
||||||
|
shape: "RuRuRuRu", // miners t1
|
||||||
|
required: 70,
|
||||||
|
reward: enumHubGoalRewards.reward_balancer,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 4
|
||||||
|
{
|
||||||
|
shape: "RuRu----", // processors t2
|
||||||
|
required: 70,
|
||||||
|
reward: enumHubGoalRewards.reward_rotater,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 5
|
||||||
|
// Rotater
|
||||||
|
{
|
||||||
|
shape: "Cu----Cu", // belts t2
|
||||||
|
required: 170,
|
||||||
|
reward: enumHubGoalRewards.reward_tunnel,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 6
|
||||||
|
{
|
||||||
|
shape: "Cu------", // miners t2
|
||||||
|
required: 270,
|
||||||
|
reward: enumHubGoalRewards.reward_painter,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 7
|
||||||
|
// Painter
|
||||||
|
{
|
||||||
|
shape: "CrCrCrCr", // unused
|
||||||
|
required: 300,
|
||||||
|
reward: enumHubGoalRewards.reward_rotater_ccw,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 8
|
||||||
|
{
|
||||||
|
shape: "RbRb----", // painter t2
|
||||||
|
required: 480,
|
||||||
|
reward: enumHubGoalRewards.reward_mixer,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 9
|
||||||
|
// Mixing (purple)
|
||||||
|
{
|
||||||
|
shape: "CpCpCpCp", // belts t3
|
||||||
|
required: 600,
|
||||||
|
reward: enumHubGoalRewards.reward_merger,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 10
|
||||||
|
// STACKER: Star shape + cyan
|
||||||
|
{
|
||||||
|
shape: "ScScScSc", // miners t3
|
||||||
|
required: 800,
|
||||||
|
reward: enumHubGoalRewards.reward_stacker,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 11
|
||||||
|
// Chainable miner
|
||||||
|
{
|
||||||
|
shape: "CgScScCg", // processors t3
|
||||||
|
required: 1000,
|
||||||
|
reward: enumHubGoalRewards.reward_miner_chainable,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 12
|
||||||
|
// Blueprints
|
||||||
|
{
|
||||||
|
shape: "CbCbCbRb:CwCwCwCw",
|
||||||
|
required: 1000,
|
||||||
|
reward: enumHubGoalRewards.reward_blueprints,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 13
|
||||||
|
// Tunnel Tier 2
|
||||||
|
{
|
||||||
|
shape: "RpRpRpRp:CwCwCwCw", // painting t3
|
||||||
|
required: 3800,
|
||||||
|
reward: enumHubGoalRewards.reward_underground_belt_tier_2,
|
||||||
|
},
|
||||||
|
|
||||||
|
// DEMO STOPS HERE
|
||||||
|
...(limitedVersion
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
shape: "RpRpRpRp:CwCwCwCw",
|
||||||
|
required: 0,
|
||||||
|
reward: enumHubGoalRewards.reward_demo_end,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: [
|
||||||
|
// 14
|
||||||
|
// Belt reader
|
||||||
|
{
|
||||||
|
shape: "--Cg----:--Cr----", // unused
|
||||||
|
required: 16, // Per second!
|
||||||
|
reward: enumHubGoalRewards.reward_belt_reader,
|
||||||
|
throughputOnly: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 15
|
||||||
|
// Storage
|
||||||
|
{
|
||||||
|
shape: "SrSrSrSr:CyCyCyCy", // unused
|
||||||
|
required: 10000,
|
||||||
|
reward: enumHubGoalRewards.reward_storage,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 16
|
||||||
|
// Quad Cutter
|
||||||
|
{
|
||||||
|
shape: "SrSrSrSr:CyCyCyCy:SwSwSwSw", // belts t4 (two variants)
|
||||||
|
required: 6000,
|
||||||
|
reward: enumHubGoalRewards.reward_cutter_quad,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 17
|
||||||
|
// Double painter
|
||||||
|
{
|
||||||
|
shape: "CbRbRbCb:CwCwCwCw:WbWbWbWb", // miner t4 (two variants)
|
||||||
|
required: 20000,
|
||||||
|
reward: enumHubGoalRewards.reward_painter_double,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 18
|
||||||
|
// Rotater (180deg)
|
||||||
|
{
|
||||||
|
shape: "Sg----Sg:CgCgCgCg:--CyCy--", // unused
|
||||||
|
required: 20000,
|
||||||
|
reward: enumHubGoalRewards.reward_rotater_180,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 19
|
||||||
|
// Compact splitter
|
||||||
|
{
|
||||||
|
shape: "CpRpCp--:SwSwSwSw",
|
||||||
|
required: 25000,
|
||||||
|
reward: enumHubGoalRewards.reward_splitter,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 20
|
||||||
|
// WIRES
|
||||||
|
{
|
||||||
|
shape: finalGameShape,
|
||||||
|
required: 25000,
|
||||||
|
reward: enumHubGoalRewards.reward_wires_painter_and_levers,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 21
|
||||||
|
// Filter
|
||||||
|
{
|
||||||
|
shape: "CrCwCrCw:CwCrCwCr:CrCwCrCw:CwCrCwCr",
|
||||||
|
required: 25000,
|
||||||
|
reward: enumHubGoalRewards.reward_filter,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 22
|
||||||
|
// Constant signal
|
||||||
|
{
|
||||||
|
shape: "Cg----Cr:Cw----Cw:Sy------:Cy----Cy",
|
||||||
|
required: 25000,
|
||||||
|
reward: enumHubGoalRewards.reward_constant_signal,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 23
|
||||||
|
// Display
|
||||||
|
{
|
||||||
|
shape: "CcSyCcSy:SyCcSyCc:CcSyCcSy",
|
||||||
|
required: 25000,
|
||||||
|
reward: enumHubGoalRewards.reward_display,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 24 Logic gates
|
||||||
|
{
|
||||||
|
shape: "CcRcCcRc:RwCwRwCw:Sr--Sw--:CyCyCyCy",
|
||||||
|
required: 25000,
|
||||||
|
reward: enumHubGoalRewards.reward_logic_gates,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 25 Virtual Processing
|
||||||
|
{
|
||||||
|
shape: "Rg--Rg--:CwRwCwRw:--Rg--Rg",
|
||||||
|
required: 25000,
|
||||||
|
reward: enumHubGoalRewards.reward_virtual_processing,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 26 Freeplay
|
||||||
|
{
|
||||||
|
shape: "CbCuCbCu:Sr------:--CrSrCr:CwCwCwCw",
|
||||||
|
required: 50000,
|
||||||
|
reward: enumHubGoalRewards.reward_freeplay,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (G_IS_DEV) {
|
||||||
|
levelDefinitions.forEach(({ shape }) => {
|
||||||
|
try {
|
||||||
|
ShapeDefinition.fromShortKey(shape);
|
||||||
|
} catch (ex) {
|
||||||
|
throw new Error("Invalid tutorial goal: '" + ex + "' for shape" + shape);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return levelDefinitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fullVersionUpgrades = generateUpgrades(false);
|
||||||
|
const demoVersionUpgrades = generateUpgrades(true);
|
||||||
|
|
||||||
|
const fullVersionLevels = generateLevelDefinitions(false);
|
||||||
|
const demoVersionLevels = generateLevelDefinitions(true);
|
||||||
|
|
||||||
|
export class RegularGameMode extends GameMode {
|
||||||
|
constructor(root) {
|
||||||
|
super(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
getUpgrades() {
|
||||||
|
return this.root.app.restrictionMgr.getHasExtendedUpgrades()
|
||||||
|
? fullVersionUpgrades
|
||||||
|
: demoVersionUpgrades;
|
||||||
|
}
|
||||||
|
|
||||||
|
getIsFreeplayAvailable() {
|
||||||
|
return this.root.app.restrictionMgr.getHasExtendedLevelsAndFreeplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
getBlueprintShapeKey() {
|
||||||
|
return blueprintShape;
|
||||||
|
}
|
||||||
|
|
||||||
|
getLevelDefinitions() {
|
||||||
|
return this.root.app.restrictionMgr.getHasExtendedLevelsAndFreeplay()
|
||||||
|
? fullVersionLevels
|
||||||
|
: demoVersionLevels;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,221 +1,225 @@
|
|||||||
/* eslint-disable no-unused-vars */
|
/* eslint-disable no-unused-vars */
|
||||||
import { Signal } from "../core/signal";
|
import { Signal } from "../core/signal";
|
||||||
import { RandomNumberGenerator } from "../core/rng";
|
import { RandomNumberGenerator } from "../core/rng";
|
||||||
import { createLogger } from "../core/logging";
|
import { createLogger } from "../core/logging";
|
||||||
|
|
||||||
// Type hints
|
// Type hints
|
||||||
/* typehints:start */
|
/* typehints:start */
|
||||||
import { GameTime } from "./time/game_time";
|
import { GameTime } from "./time/game_time";
|
||||||
import { EntityManager } from "./entity_manager";
|
import { EntityManager } from "./entity_manager";
|
||||||
import { GameSystemManager } from "./game_system_manager";
|
import { GameSystemManager } from "./game_system_manager";
|
||||||
import { GameHUD } from "./hud/hud";
|
import { GameHUD } from "./hud/hud";
|
||||||
import { MapView } from "./map_view";
|
import { MapView } from "./map_view";
|
||||||
import { Camera } from "./camera";
|
import { Camera } from "./camera";
|
||||||
import { InGameState } from "../states/ingame";
|
import { InGameState } from "../states/ingame";
|
||||||
import { AutomaticSave } from "./automatic_save";
|
import { AutomaticSave } from "./automatic_save";
|
||||||
import { Application } from "../application";
|
import { Application } from "../application";
|
||||||
import { SoundProxy } from "./sound_proxy";
|
import { SoundProxy } from "./sound_proxy";
|
||||||
import { Savegame } from "../savegame/savegame";
|
import { Savegame } from "../savegame/savegame";
|
||||||
import { GameLogic } from "./logic";
|
import { GameLogic } from "./logic";
|
||||||
import { ShapeDefinitionManager } from "./shape_definition_manager";
|
import { ShapeDefinitionManager } from "./shape_definition_manager";
|
||||||
import { HubGoals } from "./hub_goals";
|
import { HubGoals } from "./hub_goals";
|
||||||
import { BufferMaintainer } from "../core/buffer_maintainer";
|
import { BufferMaintainer } from "../core/buffer_maintainer";
|
||||||
import { ProductionAnalytics } from "./production_analytics";
|
import { ProductionAnalytics } from "./production_analytics";
|
||||||
import { Entity } from "./entity";
|
import { Entity } from "./entity";
|
||||||
import { ShapeDefinition } from "./shape_definition";
|
import { ShapeDefinition } from "./shape_definition";
|
||||||
import { BaseItem } from "./base_item";
|
import { BaseItem } from "./base_item";
|
||||||
import { DynamicTickrate } from "./dynamic_tickrate";
|
import { DynamicTickrate } from "./dynamic_tickrate";
|
||||||
import { KeyActionMapper } from "./key_action_mapper";
|
import { KeyActionMapper } from "./key_action_mapper";
|
||||||
import { Vector } from "../core/vector";
|
import { Vector } from "../core/vector";
|
||||||
/* typehints:end */
|
import { GameMode } from "./game_mode";
|
||||||
|
/* typehints:end */
|
||||||
const logger = createLogger("game/root");
|
|
||||||
|
const logger = createLogger("game/root");
|
||||||
/** @type {Array<Layer>} */
|
|
||||||
export const layers = ["regular", "wires"];
|
/** @type {Array<Layer>} */
|
||||||
|
export const layers = ["regular", "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
|
* The game root is basically the whole game state at a given point,
|
||||||
* class is passed to almost all game classes.
|
* combining all important classes. We don't have globals, but this
|
||||||
*/
|
* class is passed to almost all game classes.
|
||||||
export class GameRoot {
|
*/
|
||||||
/**
|
export class GameRoot {
|
||||||
* Constructs a new game root
|
/**
|
||||||
* @param {Application} app
|
* Constructs a new game root
|
||||||
*/
|
* @param {Application} app
|
||||||
constructor(app) {
|
*/
|
||||||
this.app = app;
|
constructor(app) {
|
||||||
|
this.app = app;
|
||||||
/** @type {Savegame} */
|
|
||||||
this.savegame = null;
|
/** @type {Savegame} */
|
||||||
|
this.savegame = null;
|
||||||
/** @type {InGameState} */
|
|
||||||
this.gameState = null;
|
/** @type {InGameState} */
|
||||||
|
this.gameState = null;
|
||||||
/** @type {KeyActionMapper} */
|
|
||||||
this.keyMapper = null;
|
/** @type {KeyActionMapper} */
|
||||||
|
this.keyMapper = null;
|
||||||
// Store game dimensions
|
|
||||||
this.gameWidth = 500;
|
// Store game dimensions
|
||||||
this.gameHeight = 500;
|
this.gameWidth = 500;
|
||||||
|
this.gameHeight = 500;
|
||||||
// Stores whether the current session is a fresh game (true), or was continued (false)
|
|
||||||
/** @type {boolean} */
|
// Stores whether the current session is a fresh game (true), or was continued (false)
|
||||||
this.gameIsFresh = true;
|
/** @type {boolean} */
|
||||||
|
this.gameIsFresh = true;
|
||||||
// Stores whether the logic is already initialized
|
|
||||||
/** @type {boolean} */
|
// Stores whether the logic is already initialized
|
||||||
this.logicInitialized = false;
|
/** @type {boolean} */
|
||||||
|
this.logicInitialized = false;
|
||||||
// Stores whether the game is already initialized, that is, all systems etc have been created
|
|
||||||
/** @type {boolean} */
|
// Stores whether the game is already initialized, that is, all systems etc have been created
|
||||||
this.gameInitialized = false;
|
/** @type {boolean} */
|
||||||
|
this.gameInitialized = false;
|
||||||
/**
|
|
||||||
* Whether a bulk operation is running
|
/**
|
||||||
*/
|
* Whether a bulk operation is running
|
||||||
this.bulkOperationRunning = false;
|
*/
|
||||||
|
this.bulkOperationRunning = false;
|
||||||
//////// Other properties ///////
|
|
||||||
|
//////// Other properties ///////
|
||||||
/** @type {Camera} */
|
|
||||||
this.camera = null;
|
/** @type {Camera} */
|
||||||
|
this.camera = null;
|
||||||
/** @type {HTMLCanvasElement} */
|
|
||||||
this.canvas = null;
|
/** @type {HTMLCanvasElement} */
|
||||||
|
this.canvas = null;
|
||||||
/** @type {CanvasRenderingContext2D} */
|
|
||||||
this.context = null;
|
/** @type {CanvasRenderingContext2D} */
|
||||||
|
this.context = null;
|
||||||
/** @type {MapView} */
|
|
||||||
this.map = null;
|
/** @type {MapView} */
|
||||||
|
this.map = null;
|
||||||
/** @type {GameLogic} */
|
|
||||||
this.logic = null;
|
/** @type {GameLogic} */
|
||||||
|
this.logic = null;
|
||||||
/** @type {EntityManager} */
|
|
||||||
this.entityMgr = null;
|
/** @type {EntityManager} */
|
||||||
|
this.entityMgr = null;
|
||||||
/** @type {GameHUD} */
|
|
||||||
this.hud = null;
|
/** @type {GameHUD} */
|
||||||
|
this.hud = null;
|
||||||
/** @type {GameSystemManager} */
|
|
||||||
this.systemMgr = null;
|
/** @type {GameSystemManager} */
|
||||||
|
this.systemMgr = null;
|
||||||
/** @type {GameTime} */
|
|
||||||
this.time = null;
|
/** @type {GameTime} */
|
||||||
|
this.time = null;
|
||||||
/** @type {HubGoals} */
|
|
||||||
this.hubGoals = null;
|
/** @type {HubGoals} */
|
||||||
|
this.hubGoals = null;
|
||||||
/** @type {BufferMaintainer} */
|
|
||||||
this.buffers = null;
|
/** @type {BufferMaintainer} */
|
||||||
|
this.buffers = null;
|
||||||
/** @type {AutomaticSave} */
|
|
||||||
this.automaticSave = null;
|
/** @type {AutomaticSave} */
|
||||||
|
this.automaticSave = null;
|
||||||
/** @type {SoundProxy} */
|
|
||||||
this.soundProxy = null;
|
/** @type {SoundProxy} */
|
||||||
|
this.soundProxy = null;
|
||||||
/** @type {ShapeDefinitionManager} */
|
|
||||||
this.shapeDefinitionMgr = null;
|
/** @type {ShapeDefinitionManager} */
|
||||||
|
this.shapeDefinitionMgr = null;
|
||||||
/** @type {ProductionAnalytics} */
|
|
||||||
this.productionAnalytics = null;
|
/** @type {ProductionAnalytics} */
|
||||||
|
this.productionAnalytics = null;
|
||||||
/** @type {DynamicTickrate} */
|
|
||||||
this.dynamicTickrate = null;
|
/** @type {DynamicTickrate} */
|
||||||
|
this.dynamicTickrate = null;
|
||||||
/** @type {Layer} */
|
|
||||||
this.currentLayer = "regular";
|
/** @type {Layer} */
|
||||||
|
this.currentLayer = "regular";
|
||||||
this.signals = {
|
|
||||||
// Entities
|
/** @type {GameMode} */
|
||||||
entityManuallyPlaced: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
|
this.gameMode = null;
|
||||||
entityAdded: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
|
|
||||||
entityChanged: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
|
this.signals = {
|
||||||
entityGotNewComponent: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
|
// Entities
|
||||||
entityComponentRemoved: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
|
entityManuallyPlaced: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
|
||||||
entityQueuedForDestroy: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
|
entityAdded: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
|
||||||
entityDestroyed: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
|
entityChanged: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
|
||||||
|
entityGotNewComponent: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
|
||||||
// Global
|
entityComponentRemoved: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
|
||||||
resized: /** @type {TypedSignal<[number, number]>} */ (new Signal()),
|
entityQueuedForDestroy: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
|
||||||
readyToRender: /** @type {TypedSignal<[]>} */ (new Signal()),
|
entityDestroyed: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
|
||||||
aboutToDestruct: /** @type {TypedSignal<[]>} */ new Signal(),
|
|
||||||
|
// Global
|
||||||
// Game Hooks
|
resized: /** @type {TypedSignal<[number, number]>} */ (new Signal()),
|
||||||
gameSaved: /** @type {TypedSignal<[]>} */ (new Signal()), // Game got saved
|
readyToRender: /** @type {TypedSignal<[]>} */ (new Signal()),
|
||||||
gameRestored: /** @type {TypedSignal<[]>} */ (new Signal()), // Game got restored
|
aboutToDestruct: /** @type {TypedSignal<[]>} */ new Signal(),
|
||||||
|
|
||||||
gameFrameStarted: /** @type {TypedSignal<[]>} */ (new Signal()), // New frame
|
// Game Hooks
|
||||||
|
gameSaved: /** @type {TypedSignal<[]>} */ (new Signal()), // Game got saved
|
||||||
storyGoalCompleted: /** @type {TypedSignal<[number, string]>} */ (new Signal()),
|
gameRestored: /** @type {TypedSignal<[]>} */ (new Signal()), // Game got restored
|
||||||
upgradePurchased: /** @type {TypedSignal<[string]>} */ (new Signal()),
|
|
||||||
|
gameFrameStarted: /** @type {TypedSignal<[]>} */ (new Signal()), // New frame
|
||||||
// Called right after game is initialized
|
|
||||||
postLoadHook: /** @type {TypedSignal<[]>} */ (new Signal()),
|
storyGoalCompleted: /** @type {TypedSignal<[number, string]>} */ (new Signal()),
|
||||||
|
upgradePurchased: /** @type {TypedSignal<[string]>} */ (new Signal()),
|
||||||
shapeDelivered: /** @type {TypedSignal<[ShapeDefinition]>} */ (new Signal()),
|
|
||||||
itemProduced: /** @type {TypedSignal<[BaseItem]>} */ (new Signal()),
|
// Called right after game is initialized
|
||||||
|
postLoadHook: /** @type {TypedSignal<[]>} */ (new Signal()),
|
||||||
bulkOperationFinished: /** @type {TypedSignal<[]>} */ (new Signal()),
|
|
||||||
|
shapeDelivered: /** @type {TypedSignal<[ShapeDefinition]>} */ (new Signal()),
|
||||||
editModeChanged: /** @type {TypedSignal<[Layer]>} */ (new Signal()),
|
itemProduced: /** @type {TypedSignal<[BaseItem]>} */ (new Signal()),
|
||||||
|
|
||||||
// Called to check if an entity can be placed, second parameter is an additional offset.
|
bulkOperationFinished: /** @type {TypedSignal<[]>} */ (new Signal()),
|
||||||
// Use to introduce additional placement checks
|
|
||||||
prePlacementCheck: /** @type {TypedSignal<[Entity, Vector]>} */ (new Signal()),
|
editModeChanged: /** @type {TypedSignal<[Layer]>} */ (new Signal()),
|
||||||
|
|
||||||
// Called before actually placing an entity, use to perform additional logic
|
// Called to check if an entity can be placed, second parameter is an additional offset.
|
||||||
// for freeing space before actually placing.
|
// Use to introduce additional placement checks
|
||||||
freeEntityAreaBeforeBuild: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
|
prePlacementCheck: /** @type {TypedSignal<[Entity, Vector]>} */ (new Signal()),
|
||||||
};
|
|
||||||
|
// Called before actually placing an entity, use to perform additional logic
|
||||||
// RNG's
|
// for freeing space before actually placing.
|
||||||
/** @type {Object.<string, Object.<string, RandomNumberGenerator>>} */
|
freeEntityAreaBeforeBuild: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
|
||||||
this.rngs = {};
|
};
|
||||||
|
|
||||||
// Work queue
|
// RNG's
|
||||||
this.queue = {
|
/** @type {Object.<string, Object.<string, RandomNumberGenerator>>} */
|
||||||
requireRedraw: false,
|
this.rngs = {};
|
||||||
};
|
|
||||||
}
|
// Work queue
|
||||||
|
this.queue = {
|
||||||
/**
|
requireRedraw: false,
|
||||||
* Destructs the game root
|
};
|
||||||
*/
|
}
|
||||||
destruct() {
|
|
||||||
logger.log("destructing root");
|
/**
|
||||||
this.signals.aboutToDestruct.dispatch();
|
* Destructs the game root
|
||||||
|
*/
|
||||||
this.reset();
|
destruct() {
|
||||||
}
|
logger.log("destructing root");
|
||||||
|
this.signals.aboutToDestruct.dispatch();
|
||||||
/**
|
|
||||||
* Resets the whole root and removes all properties
|
this.reset();
|
||||||
*/
|
}
|
||||||
reset() {
|
|
||||||
if (this.signals) {
|
/**
|
||||||
// Destruct all signals
|
* Resets the whole root and removes all properties
|
||||||
for (let i = 0; i < this.signals.length; ++i) {
|
*/
|
||||||
this.signals[i].removeAll();
|
reset() {
|
||||||
}
|
if (this.signals) {
|
||||||
}
|
// Destruct all signals
|
||||||
|
for (let i = 0; i < this.signals.length; ++i) {
|
||||||
if (this.hud) {
|
this.signals[i].removeAll();
|
||||||
this.hud.cleanup();
|
}
|
||||||
}
|
}
|
||||||
if (this.camera) {
|
|
||||||
this.camera.cleanup();
|
if (this.hud) {
|
||||||
}
|
this.hud.cleanup();
|
||||||
|
}
|
||||||
// Finally free all properties
|
if (this.camera) {
|
||||||
for (let prop in this) {
|
this.camera.cleanup();
|
||||||
if (this.hasOwnProperty(prop)) {
|
}
|
||||||
delete this[prop];
|
|
||||||
}
|
// Finally free all properties
|
||||||
}
|
for (let prop in this) {
|
||||||
}
|
if (this.hasOwnProperty(prop)) {
|
||||||
}
|
delete this[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -12,7 +12,6 @@ import { GameSystemWithFilter } from "../game_system_with_filter";
|
|||||||
import { BOOL_FALSE_SINGLETON, BOOL_TRUE_SINGLETON } from "../items/boolean_item";
|
import { BOOL_FALSE_SINGLETON, BOOL_TRUE_SINGLETON } from "../items/boolean_item";
|
||||||
import { COLOR_ITEM_SINGLETONS } from "../items/color_item";
|
import { COLOR_ITEM_SINGLETONS } from "../items/color_item";
|
||||||
import { ShapeDefinition } from "../shape_definition";
|
import { ShapeDefinition } from "../shape_definition";
|
||||||
import { blueprintShape } from "../upgrades";
|
|
||||||
|
|
||||||
export class ConstantSignalSystem extends GameSystemWithFilter {
|
export class ConstantSignalSystem extends GameSystemWithFilter {
|
||||||
constructor(root) {
|
constructor(root) {
|
||||||
@ -64,7 +63,9 @@ export class ConstantSignalSystem extends GameSystemWithFilter {
|
|||||||
this.root.shapeDefinitionMgr.getShapeItemFromDefinition(
|
this.root.shapeDefinitionMgr.getShapeItemFromDefinition(
|
||||||
this.root.hubGoals.currentGoal.definition
|
this.root.hubGoals.currentGoal.definition
|
||||||
),
|
),
|
||||||
this.root.shapeDefinitionMgr.getShapeItemFromShortKey(blueprintShape),
|
this.root.shapeDefinitionMgr.getShapeItemFromShortKey(
|
||||||
|
this.root.gameMode.getBlueprintShapeKey()
|
||||||
|
),
|
||||||
...this.root.hud.parts.pinnedShapes.pinnedShapes.map(key =>
|
...this.root.hud.parts.pinnedShapes.pinnedShapes.map(key =>
|
||||||
this.root.shapeDefinitionMgr.getShapeItemFromShortKey(key)
|
this.root.shapeDefinitionMgr.getShapeItemFromShortKey(key)
|
||||||
),
|
),
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { globalConfig, IS_DEMO } from "../../core/config";
|
import { globalConfig } from "../../core/config";
|
||||||
import { smoothenDpi } from "../../core/dpi_manager";
|
import { smoothenDpi } from "../../core/dpi_manager";
|
||||||
import { DrawParameters } from "../../core/draw_parameters";
|
import { DrawParameters } from "../../core/draw_parameters";
|
||||||
import { drawSpriteClipped } from "../../core/draw_utils";
|
import { drawSpriteClipped } from "../../core/draw_utils";
|
||||||
|
|||||||
@ -154,22 +154,18 @@ export class LogicGateSystem extends GameSystemWithFilter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Array<BaseItem|null>} parameters
|
* @param {Array<BaseItem|null>} parameters
|
||||||
* @returns {[BaseItem, BaseItem]}
|
* @returns {BaseItem}
|
||||||
*/
|
*/
|
||||||
compute_ROTATE(parameters) {
|
compute_ROTATE(parameters) {
|
||||||
const item = parameters[0];
|
const item = parameters[0];
|
||||||
if (!item || item.getItemType() !== "shape") {
|
if (!item || item.getItemType() !== "shape") {
|
||||||
// Not a shape
|
// Not a shape
|
||||||
return [null, null];
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const definition = /** @type {ShapeItem} */ (item).definition;
|
const definition = /** @type {ShapeItem} */ (item).definition;
|
||||||
const rotatedDefinitionCCW = this.root.shapeDefinitionMgr.shapeActionRotateCCW(definition);
|
|
||||||
const rotatedDefinitionCW = this.root.shapeDefinitionMgr.shapeActionRotateCW(definition);
|
const rotatedDefinitionCW = this.root.shapeDefinitionMgr.shapeActionRotateCW(definition);
|
||||||
return [
|
return this.root.shapeDefinitionMgr.getShapeItemFromDefinition(rotatedDefinitionCW);
|
||||||
this.root.shapeDefinitionMgr.getShapeItemFromDefinition(rotatedDefinitionCCW),
|
|
||||||
this.root.shapeDefinitionMgr.getShapeItemFromDefinition(rotatedDefinitionCW),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,7 +1,3 @@
|
|||||||
import { IS_DEMO } from "../core/config";
|
|
||||||
import { ShapeDefinition } from "./shape_definition";
|
|
||||||
import { finalGameShape } from "./upgrades";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Don't forget to also update tutorial_goals_mappings.js as well as the translations!
|
* Don't forget to also update tutorial_goals_mappings.js as well as the translations!
|
||||||
* @enum {string}
|
* @enum {string}
|
||||||
@ -40,229 +36,3 @@ export const enumHubGoalRewards = {
|
|||||||
no_reward: "no_reward",
|
no_reward: "no_reward",
|
||||||
no_reward_freeplay: "no_reward_freeplay",
|
no_reward_freeplay: "no_reward_freeplay",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const tutorialGoals = [
|
|
||||||
// 1
|
|
||||||
// Circle
|
|
||||||
{
|
|
||||||
shape: "CuCuCuCu", // belts t1
|
|
||||||
required: 30,
|
|
||||||
reward: enumHubGoalRewards.reward_cutter_and_trash,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 2
|
|
||||||
// Cutter
|
|
||||||
{
|
|
||||||
shape: "----CuCu", //
|
|
||||||
required: 40,
|
|
||||||
reward: enumHubGoalRewards.no_reward,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 3
|
|
||||||
// Rectangle
|
|
||||||
{
|
|
||||||
shape: "RuRuRuRu", // miners t1
|
|
||||||
required: 70,
|
|
||||||
reward: enumHubGoalRewards.reward_balancer,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 4
|
|
||||||
{
|
|
||||||
shape: "RuRu----", // processors t2
|
|
||||||
required: 70,
|
|
||||||
reward: enumHubGoalRewards.reward_rotater,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 5
|
|
||||||
// Rotater
|
|
||||||
{
|
|
||||||
shape: "Cu----Cu", // belts t2
|
|
||||||
required: 170,
|
|
||||||
reward: enumHubGoalRewards.reward_tunnel,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 6
|
|
||||||
{
|
|
||||||
shape: "Cu------", // miners t2
|
|
||||||
required: 270,
|
|
||||||
reward: enumHubGoalRewards.reward_painter,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 7
|
|
||||||
// Painter
|
|
||||||
{
|
|
||||||
shape: "CrCrCrCr", // unused
|
|
||||||
required: 300,
|
|
||||||
reward: enumHubGoalRewards.reward_rotater_ccw,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 8
|
|
||||||
{
|
|
||||||
shape: "RbRb----", // painter t2
|
|
||||||
required: 480,
|
|
||||||
reward: enumHubGoalRewards.reward_mixer,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 9
|
|
||||||
// Mixing (purple)
|
|
||||||
{
|
|
||||||
shape: "CpCpCpCp", // belts t3
|
|
||||||
required: 600,
|
|
||||||
reward: enumHubGoalRewards.reward_merger,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 10
|
|
||||||
// STACKER: Star shape + cyan
|
|
||||||
{
|
|
||||||
shape: "ScScScSc", // miners t3
|
|
||||||
required: 800,
|
|
||||||
reward: enumHubGoalRewards.reward_stacker,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 11
|
|
||||||
// Chainable miner
|
|
||||||
{
|
|
||||||
shape: "CgScScCg", // processors t3
|
|
||||||
required: 1000,
|
|
||||||
reward: enumHubGoalRewards.reward_miner_chainable,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 12
|
|
||||||
// Blueprints
|
|
||||||
{
|
|
||||||
shape: "CbCbCbRb:CwCwCwCw",
|
|
||||||
required: 1000,
|
|
||||||
reward: enumHubGoalRewards.reward_blueprints,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 13
|
|
||||||
// Tunnel Tier 2
|
|
||||||
{
|
|
||||||
shape: "RpRpRpRp:CwCwCwCw", // painting t3
|
|
||||||
required: 3800,
|
|
||||||
reward: enumHubGoalRewards.reward_underground_belt_tier_2,
|
|
||||||
},
|
|
||||||
|
|
||||||
// DEMO STOPS HERE
|
|
||||||
...(IS_DEMO
|
|
||||||
? [
|
|
||||||
{
|
|
||||||
shape: "RpRpRpRp:CwCwCwCw",
|
|
||||||
required: 0,
|
|
||||||
reward: enumHubGoalRewards.reward_demo_end,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
: [
|
|
||||||
// 14
|
|
||||||
// Belt reader
|
|
||||||
{
|
|
||||||
shape: "--Cg----:--Cr----", // unused
|
|
||||||
required: 16, // Per second!
|
|
||||||
reward: enumHubGoalRewards.reward_belt_reader,
|
|
||||||
throughputOnly: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 15
|
|
||||||
// Storage
|
|
||||||
{
|
|
||||||
shape: "SrSrSrSr:CyCyCyCy", // unused
|
|
||||||
required: 10000,
|
|
||||||
reward: enumHubGoalRewards.reward_storage,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 16
|
|
||||||
// Quad Cutter
|
|
||||||
{
|
|
||||||
shape: "SrSrSrSr:CyCyCyCy:SwSwSwSw", // belts t4 (two variants)
|
|
||||||
required: 6000,
|
|
||||||
reward: enumHubGoalRewards.reward_cutter_quad,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 17
|
|
||||||
// Double painter
|
|
||||||
{
|
|
||||||
shape: "CbRbRbCb:CwCwCwCw:WbWbWbWb", // miner t4 (two variants)
|
|
||||||
required: 20000,
|
|
||||||
reward: enumHubGoalRewards.reward_painter_double,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 18
|
|
||||||
// Rotater (180deg)
|
|
||||||
{
|
|
||||||
shape: "Sg----Sg:CgCgCgCg:--CyCy--", // unused
|
|
||||||
required: 20000,
|
|
||||||
reward: enumHubGoalRewards.reward_rotater_180,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 19
|
|
||||||
// Compact splitter
|
|
||||||
{
|
|
||||||
shape: "CpRpCp--:SwSwSwSw",
|
|
||||||
required: 25000,
|
|
||||||
reward: enumHubGoalRewards.reward_splitter,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 20
|
|
||||||
// WIRES
|
|
||||||
{
|
|
||||||
shape: finalGameShape,
|
|
||||||
required: 25000,
|
|
||||||
reward: enumHubGoalRewards.reward_wires_painter_and_levers,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 21
|
|
||||||
// Filter
|
|
||||||
{
|
|
||||||
shape: "CrCwCrCw:CwCrCwCr:CrCwCrCw:CwCrCwCr",
|
|
||||||
required: 25000,
|
|
||||||
reward: enumHubGoalRewards.reward_filter,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 22
|
|
||||||
// Constant signal
|
|
||||||
{
|
|
||||||
shape: "Cg----Cr:Cw----Cw:Sy------:Cy----Cy",
|
|
||||||
required: 25000,
|
|
||||||
reward: enumHubGoalRewards.reward_constant_signal,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 23
|
|
||||||
// Display
|
|
||||||
{
|
|
||||||
shape: "CcSyCcSy:SyCcSyCc:CcSyCcSy",
|
|
||||||
required: 25000,
|
|
||||||
reward: enumHubGoalRewards.reward_display,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 24 Logic gates
|
|
||||||
{
|
|
||||||
shape: "CcRcCcRc:RwCwRwCw:Sr--Sw--:CyCyCyCy",
|
|
||||||
required: 25000,
|
|
||||||
reward: enumHubGoalRewards.reward_logic_gates,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 25 Virtual Processing
|
|
||||||
{
|
|
||||||
shape: "Rg--Rg--:CwRwCwRw:--Rg--Rg",
|
|
||||||
required: 25000,
|
|
||||||
reward: enumHubGoalRewards.reward_virtual_processing,
|
|
||||||
},
|
|
||||||
|
|
||||||
// 26 Freeplay
|
|
||||||
{
|
|
||||||
shape: "CbCuCbCu:Sr------:--CrSrCr:CwCwCwCw",
|
|
||||||
required: 50000,
|
|
||||||
reward: enumHubGoalRewards.reward_freeplay,
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
];
|
|
||||||
|
|
||||||
if (G_IS_DEV) {
|
|
||||||
tutorialGoals.forEach(({ shape }) => {
|
|
||||||
try {
|
|
||||||
ShapeDefinition.fromShortKey(shape);
|
|
||||||
} catch (ex) {
|
|
||||||
throw new Error("Invalid tutorial goal: '" + ex + "' for shape" + shape);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,212 +0,0 @@
|
|||||||
import { IS_DEMO } from "../core/config";
|
|
||||||
import { findNiceIntegerValue } from "../core/utils";
|
|
||||||
import { ShapeDefinition } from "./shape_definition";
|
|
||||||
|
|
||||||
export const preparementShape = "CpRpCp--:SwSwSwSw";
|
|
||||||
export const finalGameShape = "RuCw--Cw:----Ru--";
|
|
||||||
export const rocketShape = "CbCuCbCu:Sr------:--CrSrCr:CwCwCwCw";
|
|
||||||
export const blueprintShape = "CbCbCbRb:CwCwCwCw";
|
|
||||||
|
|
||||||
const fixedImprovements = [0.5, 0.5, 1, 1, 2, 1, 1];
|
|
||||||
|
|
||||||
const numEndgameUpgrades = !IS_DEMO ? 20 - fixedImprovements.length - 1 : 0;
|
|
||||||
|
|
||||||
function generateEndgameUpgrades() {
|
|
||||||
return new Array(numEndgameUpgrades).fill(null).map((_, i) => ({
|
|
||||||
required: [
|
|
||||||
{ shape: preparementShape, amount: 30000 + i * 10000 },
|
|
||||||
{ shape: finalGameShape, amount: 20000 + i * 5000 },
|
|
||||||
{ shape: rocketShape, amount: 20000 + i * 5000 },
|
|
||||||
],
|
|
||||||
excludePrevious: true,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < numEndgameUpgrades; ++i) {
|
|
||||||
fixedImprovements.push(0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @typedef {{
|
|
||||||
* shape: string,
|
|
||||||
* amount: number
|
|
||||||
* }} UpgradeRequirement */
|
|
||||||
|
|
||||||
/** @typedef {{
|
|
||||||
* required: Array<UpgradeRequirement>
|
|
||||||
* improvement?: number,
|
|
||||||
* excludePrevious?: boolean
|
|
||||||
* }} TierRequirement */
|
|
||||||
|
|
||||||
/** @typedef {Array<TierRequirement>} UpgradeTiers */
|
|
||||||
|
|
||||||
/** @type {Object<string, UpgradeTiers>} */
|
|
||||||
export const UPGRADES = {
|
|
||||||
belt: [
|
|
||||||
{
|
|
||||||
required: [{ shape: "CuCuCuCu", amount: 60 }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [{ shape: "--CuCu--", amount: 500 }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [{ shape: "CpCpCpCp", amount: 1000 }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [{ shape: "SrSrSrSr:CyCyCyCy", amount: 6000 }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [{ shape: "SrSrSrSr:CyCyCyCy:SwSwSwSw", amount: 25000 }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [{ shape: preparementShape, amount: 25000 }],
|
|
||||||
excludePrevious: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [
|
|
||||||
{ shape: preparementShape, amount: 25000 },
|
|
||||||
{ shape: finalGameShape, amount: 50000 },
|
|
||||||
],
|
|
||||||
excludePrevious: true,
|
|
||||||
},
|
|
||||||
...generateEndgameUpgrades(),
|
|
||||||
],
|
|
||||||
|
|
||||||
miner: [
|
|
||||||
{
|
|
||||||
required: [{ shape: "RuRuRuRu", amount: 300 }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [{ shape: "Cu------", amount: 800 }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [{ shape: "ScScScSc", amount: 3500 }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [{ shape: "CwCwCwCw:WbWbWbWb", amount: 23000 }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [{ shape: "CbRbRbCb:CwCwCwCw:WbWbWbWb", amount: 50000 }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [{ shape: preparementShape, amount: 25000 }],
|
|
||||||
excludePrevious: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [
|
|
||||||
{ shape: preparementShape, amount: 25000 },
|
|
||||||
{ shape: finalGameShape, amount: 50000 },
|
|
||||||
],
|
|
||||||
excludePrevious: true,
|
|
||||||
},
|
|
||||||
...generateEndgameUpgrades(),
|
|
||||||
],
|
|
||||||
|
|
||||||
processors: [
|
|
||||||
{
|
|
||||||
required: [{ shape: "SuSuSuSu", amount: 500 }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [{ shape: "RuRu----", amount: 600 }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [{ shape: "CgScScCg", amount: 3500 }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [{ shape: "CwCrCwCr:SgSgSgSg", amount: 25000 }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [{ shape: "WrRgWrRg:CwCrCwCr:SgSgSgSg", amount: 50000 }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [{ shape: preparementShape, amount: 25000 }],
|
|
||||||
excludePrevious: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [
|
|
||||||
{ shape: preparementShape, amount: 25000 },
|
|
||||||
{ shape: finalGameShape, amount: 50000 },
|
|
||||||
],
|
|
||||||
excludePrevious: true,
|
|
||||||
},
|
|
||||||
...generateEndgameUpgrades(),
|
|
||||||
],
|
|
||||||
|
|
||||||
painting: [
|
|
||||||
{
|
|
||||||
required: [{ shape: "RbRb----", amount: 600 }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [{ shape: "WrWrWrWr", amount: 3800 }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [{ shape: "RpRpRpRp:CwCwCwCw", amount: 6500 }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [{ shape: "WpWpWpWp:CwCwCwCw:WpWpWpWp", amount: 25000 }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [{ shape: "WpWpWpWp:CwCwCwCw:WpWpWpWp:CwCwCwCw", amount: 50000 }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [{ shape: preparementShape, amount: 25000 }],
|
|
||||||
excludePrevious: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
required: [
|
|
||||||
{ shape: preparementShape, amount: 25000 },
|
|
||||||
{ shape: finalGameShape, amount: 50000 },
|
|
||||||
],
|
|
||||||
excludePrevious: true,
|
|
||||||
},
|
|
||||||
...generateEndgameUpgrades(),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
// Tiers need % of the previous tier as requirement too
|
|
||||||
const tierGrowth = 2.5;
|
|
||||||
|
|
||||||
// Automatically generate tier levels
|
|
||||||
for (const upgradeId in UPGRADES) {
|
|
||||||
const upgradeTiers = UPGRADES[upgradeId];
|
|
||||||
|
|
||||||
let currentTierRequirements = [];
|
|
||||||
for (let i = 0; i < upgradeTiers.length; ++i) {
|
|
||||||
const tierHandle = upgradeTiers[i];
|
|
||||||
tierHandle.improvement = fixedImprovements[i];
|
|
||||||
const originalRequired = tierHandle.required.slice();
|
|
||||||
|
|
||||||
for (let k = currentTierRequirements.length - 1; k >= 0; --k) {
|
|
||||||
const oldTierRequirement = currentTierRequirements[k];
|
|
||||||
if (!tierHandle.excludePrevious) {
|
|
||||||
tierHandle.required.unshift({
|
|
||||||
shape: oldTierRequirement.shape,
|
|
||||||
amount: oldTierRequirement.amount,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
currentTierRequirements.push(
|
|
||||||
...originalRequired.map(req => ({
|
|
||||||
amount: req.amount,
|
|
||||||
shape: req.shape,
|
|
||||||
}))
|
|
||||||
);
|
|
||||||
currentTierRequirements.forEach(tier => {
|
|
||||||
tier.amount = findNiceIntegerValue(tier.amount * tierGrowth);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// VALIDATE
|
|
||||||
if (G_IS_DEV) {
|
|
||||||
for (const upgradeId in UPGRADES) {
|
|
||||||
UPGRADES[upgradeId].forEach(tier => {
|
|
||||||
tier.required.forEach(({ shape }) => {
|
|
||||||
try {
|
|
||||||
ShapeDefinition.fromShortKey(shape);
|
|
||||||
} catch (ex) {
|
|
||||||
throw new Error("Invalid upgrade goal: '" + ex + "' for shape" + shape);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,14 +1,12 @@
|
|||||||
import { globalConfig } from "../../core/config";
|
import { globalConfig } from "../../core/config";
|
||||||
import { createLogger } from "../../core/logging";
|
import { createLogger } from "../../core/logging";
|
||||||
|
import { queryParamOptions } from "../../core/query_parameters";
|
||||||
|
import { BeltComponent } from "../../game/components/belt";
|
||||||
|
import { StaticMapEntityComponent } from "../../game/components/static_map_entity";
|
||||||
import { GameRoot } from "../../game/root";
|
import { GameRoot } from "../../game/root";
|
||||||
import { InGameState } from "../../states/ingame";
|
import { InGameState } from "../../states/ingame";
|
||||||
import { GameAnalyticsInterface } from "../game_analytics";
|
import { GameAnalyticsInterface } from "../game_analytics";
|
||||||
import { FILE_NOT_FOUND } from "../storage";
|
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";
|
|
||||||
import { queryParamOptions } from "../../core/query_parameters";
|
|
||||||
|
|
||||||
const logger = createLogger("game_analytics");
|
const logger = createLogger("game_analytics");
|
||||||
|
|
||||||
@ -190,23 +188,26 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the shape is interesting
|
* Returns true if the shape is interesting
|
||||||
|
* @param {GameRoot} root
|
||||||
* @param {string} key
|
* @param {string} key
|
||||||
*/
|
*/
|
||||||
isInterestingShape(key) {
|
isInterestingShape(root, key) {
|
||||||
if (key === blueprintShape) {
|
if (key === root.gameMode.getBlueprintShapeKey()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if its a story goal
|
// Check if its a story goal
|
||||||
for (let i = 0; i < tutorialGoals.length; ++i) {
|
const levels = root.gameMode.getLevelDefinitions();
|
||||||
if (key === tutorialGoals[i].shape) {
|
for (let i = 0; i < levels.length; ++i) {
|
||||||
|
if (key === levels[i].shape) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if its required to unlock an upgrade
|
// Check if its required to unlock an upgrade
|
||||||
for (const upgradeKey in UPGRADES) {
|
const upgrades = root.gameMode.getUpgrades();
|
||||||
const upgradeTiers = UPGRADES[upgradeKey];
|
for (const upgradeKey in upgrades) {
|
||||||
|
const upgradeTiers = upgrades[upgradeKey];
|
||||||
for (let i = 0; i < upgradeTiers.length; ++i) {
|
for (let i = 0; i < upgradeTiers.length; ++i) {
|
||||||
const tier = upgradeTiers[i];
|
const tier = upgradeTiers[i];
|
||||||
const required = tier.required;
|
const required = tier.required;
|
||||||
@ -226,7 +227,9 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface {
|
|||||||
* @param {GameRoot} root
|
* @param {GameRoot} root
|
||||||
*/
|
*/
|
||||||
generateGameDump(root) {
|
generateGameDump(root) {
|
||||||
const shapeIds = Object.keys(root.hubGoals.storedShapes).filter(this.isInterestingShape.bind(this));
|
const shapeIds = Object.keys(root.hubGoals.storedShapes).filter(key =>
|
||||||
|
this.isInterestingShape(root, key)
|
||||||
|
);
|
||||||
let shapes = {};
|
let shapes = {};
|
||||||
for (let i = 0; i < shapeIds.length; ++i) {
|
for (let i = 0; i < shapeIds.length; ++i) {
|
||||||
shapes[shapeIds[i]] = root.hubGoals.storedShapes[shapeIds[i]];
|
shapes[shapeIds[i]] = root.hubGoals.storedShapes[shapeIds[i]];
|
||||||
|
|||||||
@ -1,214 +1,202 @@
|
|||||||
import { globalConfig, IS_DEMO, IS_MOBILE } from "../../core/config";
|
import { globalConfig, IS_MOBILE } from "../../core/config";
|
||||||
import { createLogger } from "../../core/logging";
|
import { createLogger } from "../../core/logging";
|
||||||
import { queryParamOptions } from "../../core/query_parameters";
|
import { queryParamOptions } from "../../core/query_parameters";
|
||||||
import { clamp } from "../../core/utils";
|
import { clamp } from "../../core/utils";
|
||||||
import { GamedistributionAdProvider } from "../ad_providers/gamedistribution";
|
import { GamedistributionAdProvider } from "../ad_providers/gamedistribution";
|
||||||
import { NoAdProvider } from "../ad_providers/no_ad_provider";
|
import { NoAdProvider } from "../ad_providers/no_ad_provider";
|
||||||
import { PlatformWrapperInterface } from "../wrapper";
|
import { PlatformWrapperInterface } from "../wrapper";
|
||||||
import { StorageImplBrowser } from "./storage";
|
import { StorageImplBrowser } from "./storage";
|
||||||
import { StorageImplBrowserIndexedDB } from "./storage_indexed_db";
|
import { StorageImplBrowserIndexedDB } from "./storage_indexed_db";
|
||||||
|
|
||||||
const logger = createLogger("platform/browser");
|
const logger = createLogger("platform/browser");
|
||||||
|
|
||||||
export class PlatformWrapperImplBrowser extends PlatformWrapperInterface {
|
export class PlatformWrapperImplBrowser extends PlatformWrapperInterface {
|
||||||
initialize() {
|
initialize() {
|
||||||
this.recaptchaTokenCallback = null;
|
this.recaptchaTokenCallback = null;
|
||||||
|
|
||||||
this.embedProvider = {
|
this.embedProvider = {
|
||||||
id: "shapezio-website",
|
id: "shapezio-website",
|
||||||
adProvider: NoAdProvider,
|
adProvider: NoAdProvider,
|
||||||
iframed: false,
|
iframed: false,
|
||||||
externalLinks: true,
|
externalLinks: true,
|
||||||
iogLink: true,
|
iogLink: true,
|
||||||
unlimitedSavegames: IS_DEMO ? false : true,
|
};
|
||||||
showDemoBadge: IS_DEMO,
|
|
||||||
};
|
if (!G_IS_STANDALONE && queryParamOptions.embedProvider) {
|
||||||
|
const providerId = queryParamOptions.embedProvider;
|
||||||
if (!G_IS_STANDALONE && queryParamOptions.embedProvider) {
|
this.embedProvider.iframed = true;
|
||||||
const providerId = queryParamOptions.embedProvider;
|
this.embedProvider.iogLink = false;
|
||||||
this.embedProvider.iframed = true;
|
|
||||||
this.embedProvider.iogLink = false;
|
switch (providerId) {
|
||||||
|
case "armorgames": {
|
||||||
switch (providerId) {
|
this.embedProvider.id = "armorgames";
|
||||||
case "armorgames": {
|
break;
|
||||||
this.embedProvider.id = "armorgames";
|
}
|
||||||
break;
|
|
||||||
}
|
case "iogames.space": {
|
||||||
|
this.embedProvider.id = "iogames.space";
|
||||||
case "iogames.space": {
|
this.embedProvider.iogLink = true;
|
||||||
this.embedProvider.id = "iogames.space";
|
break;
|
||||||
this.embedProvider.iogLink = true;
|
}
|
||||||
this.embedProvider.unlimitedSavegames = true;
|
|
||||||
this.embedProvider.showDemoBadge = false;
|
case "miniclip": {
|
||||||
break;
|
this.embedProvider.id = "miniclip";
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
case "miniclip": {
|
|
||||||
this.embedProvider.id = "miniclip";
|
case "gamedistribution": {
|
||||||
break;
|
this.embedProvider.id = "gamedistribution";
|
||||||
}
|
this.embedProvider.externalLinks = false;
|
||||||
|
this.embedProvider.adProvider = GamedistributionAdProvider;
|
||||||
case "gamedistribution": {
|
break;
|
||||||
this.embedProvider.id = "gamedistribution";
|
}
|
||||||
this.embedProvider.externalLinks = false;
|
|
||||||
this.embedProvider.adProvider = GamedistributionAdProvider;
|
case "kongregate": {
|
||||||
break;
|
this.embedProvider.id = "kongregate";
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
case "kongregate": {
|
|
||||||
this.embedProvider.id = "kongregate";
|
case "crazygames": {
|
||||||
break;
|
this.embedProvider.id = "crazygames";
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
case "crazygames": {
|
|
||||||
this.embedProvider.id = "crazygames";
|
default: {
|
||||||
break;
|
logger.error("Got unsupported embed provider:", providerId);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
default: {
|
}
|
||||||
logger.error("Got unsupported embed provider:", providerId);
|
|
||||||
}
|
logger.log("Embed provider:", this.embedProvider.id);
|
||||||
}
|
|
||||||
}
|
return this.detectStorageImplementation()
|
||||||
|
.then(() => this.initializeAdProvider())
|
||||||
logger.log("Embed provider:", this.embedProvider.id);
|
.then(() => super.initialize());
|
||||||
|
}
|
||||||
return this.detectStorageImplementation()
|
|
||||||
.then(() => this.initializeAdProvider())
|
detectStorageImplementation() {
|
||||||
.then(() => super.initialize());
|
return new Promise(resolve => {
|
||||||
}
|
logger.log("Detecting storage");
|
||||||
|
|
||||||
detectStorageImplementation() {
|
if (!window.indexedDB) {
|
||||||
return new Promise(resolve => {
|
logger.log("Indexed DB not supported");
|
||||||
logger.log("Detecting storage");
|
this.app.storage = new StorageImplBrowser(this.app);
|
||||||
|
resolve();
|
||||||
if (!window.indexedDB) {
|
return;
|
||||||
logger.log("Indexed DB not supported");
|
}
|
||||||
this.app.storage = new StorageImplBrowser(this.app);
|
|
||||||
resolve();
|
// Try accessing the indexedb
|
||||||
return;
|
let request;
|
||||||
}
|
try {
|
||||||
|
request = window.indexedDB.open("indexeddb_feature_detection", 1);
|
||||||
// Try accessing the indexedb
|
} catch (ex) {
|
||||||
let request;
|
logger.warn("Error while opening indexed db:", ex);
|
||||||
try {
|
this.app.storage = new StorageImplBrowser(this.app);
|
||||||
request = window.indexedDB.open("indexeddb_feature_detection", 1);
|
resolve();
|
||||||
} catch (ex) {
|
return;
|
||||||
logger.warn("Error while opening indexed db:", ex);
|
}
|
||||||
this.app.storage = new StorageImplBrowser(this.app);
|
request.onerror = err => {
|
||||||
resolve();
|
logger.log("Indexed DB can *not* be accessed: ", err);
|
||||||
return;
|
logger.log("Using fallback to local storage");
|
||||||
}
|
this.app.storage = new StorageImplBrowser(this.app);
|
||||||
request.onerror = err => {
|
resolve();
|
||||||
logger.log("Indexed DB can *not* be accessed: ", err);
|
};
|
||||||
logger.log("Using fallback to local storage");
|
request.onsuccess = () => {
|
||||||
this.app.storage = new StorageImplBrowser(this.app);
|
logger.log("Indexed DB *can* be accessed");
|
||||||
resolve();
|
this.app.storage = new StorageImplBrowserIndexedDB(this.app);
|
||||||
};
|
resolve();
|
||||||
request.onsuccess = () => {
|
};
|
||||||
logger.log("Indexed DB *can* be accessed");
|
});
|
||||||
this.app.storage = new StorageImplBrowserIndexedDB(this.app);
|
}
|
||||||
resolve();
|
|
||||||
};
|
getId() {
|
||||||
});
|
return "browser@" + this.embedProvider.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
getHasUnlimitedSavegames() {
|
getUiScale() {
|
||||||
return this.embedProvider.unlimitedSavegames;
|
if (IS_MOBILE) {
|
||||||
}
|
return 1;
|
||||||
|
}
|
||||||
getShowDemoBadges() {
|
|
||||||
return this.embedProvider.showDemoBadge;
|
const avgDims = Math.min(this.app.screenWidth, this.app.screenHeight);
|
||||||
}
|
return clamp((avgDims / 1000.0) * 1.9, 0.1, 10);
|
||||||
|
}
|
||||||
getId() {
|
|
||||||
return "browser@" + this.embedProvider.id;
|
getSupportsRestart() {
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
getUiScale() {
|
|
||||||
if (IS_MOBILE) {
|
getTouchPanStrength() {
|
||||||
return 1;
|
return IS_MOBILE ? 1 : 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
const avgDims = Math.min(this.app.screenWidth, this.app.screenHeight);
|
openExternalLink(url, force = false) {
|
||||||
return clamp((avgDims / 1000.0) * 1.9, 0.1, 10);
|
logger.log("Opening external:", url);
|
||||||
}
|
if (force || this.embedProvider.externalLinks) {
|
||||||
|
window.open(url);
|
||||||
getSupportsRestart() {
|
} else {
|
||||||
return true;
|
// Do nothing
|
||||||
}
|
alert(
|
||||||
|
"This platform does not allow opening external links. You can play on https://shapez.io directly to open them.\n\nClicked Link: " +
|
||||||
getTouchPanStrength() {
|
url
|
||||||
return IS_MOBILE ? 1 : 0.5;
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
openExternalLink(url, force = false) {
|
|
||||||
logger.log("Opening external:", url);
|
performRestart() {
|
||||||
if (force || this.embedProvider.externalLinks) {
|
logger.log("Performing restart");
|
||||||
window.open(url);
|
window.location.reload(true);
|
||||||
} else {
|
}
|
||||||
// Do nothing
|
|
||||||
alert(
|
/**
|
||||||
"This platform does not allow opening external links. You can play on https://shapez.io directly to open them.\n\nClicked Link: " +
|
* Detects if there is an adblocker installed
|
||||||
url
|
* @returns {Promise<boolean>}
|
||||||
);
|
*/
|
||||||
}
|
detectAdblock() {
|
||||||
}
|
return Promise.race([
|
||||||
|
new Promise(resolve => {
|
||||||
performRestart() {
|
// If the request wasn't blocked within a very short period of time, this means
|
||||||
logger.log("Performing restart");
|
// the adblocker is not active and the request was actually made -> ignore it then
|
||||||
window.location.reload(true);
|
setTimeout(() => resolve(false), 30);
|
||||||
}
|
}),
|
||||||
|
new Promise(resolve => {
|
||||||
/**
|
fetch("https://googleads.g.doubleclick.net/pagead/id", {
|
||||||
* Detects if there is an adblocker installed
|
method: "HEAD",
|
||||||
* @returns {Promise<boolean>}
|
mode: "no-cors",
|
||||||
*/
|
})
|
||||||
detectAdblock() {
|
.then(res => {
|
||||||
return Promise.race([
|
resolve(false);
|
||||||
new Promise(resolve => {
|
})
|
||||||
// If the request wasn't blocked within a very short period of time, this means
|
.catch(err => {
|
||||||
// the adblocker is not active and the request was actually made -> ignore it then
|
resolve(true);
|
||||||
setTimeout(() => resolve(false), 30);
|
});
|
||||||
}),
|
}),
|
||||||
new Promise(resolve => {
|
]);
|
||||||
fetch("https://googleads.g.doubleclick.net/pagead/id", {
|
}
|
||||||
method: "HEAD",
|
|
||||||
mode: "no-cors",
|
initializeAdProvider() {
|
||||||
})
|
if (G_IS_DEV && !globalConfig.debug.testAds) {
|
||||||
.then(res => {
|
logger.log("Ads disabled in local environment");
|
||||||
resolve(false);
|
return Promise.resolve();
|
||||||
})
|
}
|
||||||
.catch(err => {
|
|
||||||
resolve(true);
|
// First, detect adblocker
|
||||||
});
|
return this.detectAdblock().then(hasAdblocker => {
|
||||||
}),
|
if (hasAdblocker) {
|
||||||
]);
|
logger.log("Adblock detected");
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
initializeAdProvider() {
|
|
||||||
if (G_IS_DEV && !globalConfig.debug.testAds) {
|
const adProvider = this.embedProvider.adProvider;
|
||||||
logger.log("Ads disabled in local environment");
|
this.app.adProvider = new adProvider(this.app);
|
||||||
return Promise.resolve();
|
return this.app.adProvider.initialize().catch(err => {
|
||||||
}
|
logger.error("Failed to initialize ad provider, disabling ads:", err);
|
||||||
|
this.app.adProvider = new NoAdProvider(this.app);
|
||||||
// First, detect adblocker
|
});
|
||||||
return this.detectAdblock().then(hasAdblocker => {
|
});
|
||||||
if (hasAdblocker) {
|
}
|
||||||
logger.log("Adblock detected");
|
|
||||||
return;
|
exitApp() {
|
||||||
}
|
// Can not exit app
|
||||||
|
}
|
||||||
const adProvider = this.embedProvider.adProvider;
|
}
|
||||||
this.app.adProvider = new adProvider(this.app);
|
|
||||||
return this.app.adProvider.initialize().catch(err => {
|
|
||||||
logger.error("Failed to initialize ad provider, disabling ads:", err);
|
|
||||||
this.app.adProvider = new NoAdProvider(this.app);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
exitApp() {
|
|
||||||
// Can not exit app
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,65 +1,57 @@
|
|||||||
import { PlatformWrapperImplBrowser } from "../browser/wrapper";
|
import { PlatformWrapperImplBrowser } from "../browser/wrapper";
|
||||||
import { getIPCRenderer } from "../../core/utils";
|
import { getIPCRenderer } from "../../core/utils";
|
||||||
import { createLogger } from "../../core/logging";
|
import { createLogger } from "../../core/logging";
|
||||||
import { StorageImplElectron } from "./storage";
|
import { StorageImplElectron } from "./storage";
|
||||||
import { PlatformWrapperInterface } from "../wrapper";
|
import { PlatformWrapperInterface } from "../wrapper";
|
||||||
|
|
||||||
const logger = createLogger("electron-wrapper");
|
const logger = createLogger("electron-wrapper");
|
||||||
|
|
||||||
export class PlatformWrapperImplElectron extends PlatformWrapperImplBrowser {
|
export class PlatformWrapperImplElectron extends PlatformWrapperImplBrowser {
|
||||||
initialize() {
|
initialize() {
|
||||||
this.app.storage = new StorageImplElectron(this);
|
this.app.storage = new StorageImplElectron(this);
|
||||||
return PlatformWrapperInterface.prototype.initialize.call(this);
|
return PlatformWrapperInterface.prototype.initialize.call(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
getId() {
|
getId() {
|
||||||
return "electron";
|
return "electron";
|
||||||
}
|
}
|
||||||
|
|
||||||
getSupportsRestart() {
|
getSupportsRestart() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
openExternalLink(url) {
|
openExternalLink(url) {
|
||||||
logger.log(this, "Opening external:", url);
|
logger.log(this, "Opening external:", url);
|
||||||
window.open(url, "about:blank");
|
window.open(url, "about:blank");
|
||||||
}
|
}
|
||||||
|
|
||||||
getSupportsAds() {
|
getSupportsAds() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
getHasUnlimitedSavegames() {
|
performRestart() {
|
||||||
return true;
|
logger.log(this, "Performing restart");
|
||||||
}
|
window.location.reload(true);
|
||||||
|
}
|
||||||
getShowDemoBadges() {
|
|
||||||
return false;
|
initializeAdProvider() {
|
||||||
}
|
return Promise.resolve();
|
||||||
|
}
|
||||||
performRestart() {
|
|
||||||
logger.log(this, "Performing restart");
|
getSupportsFullscreen() {
|
||||||
window.location.reload(true);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
initializeAdProvider() {
|
setFullscreen(flag) {
|
||||||
return Promise.resolve();
|
getIPCRenderer().send("set-fullscreen", flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
getSupportsFullscreen() {
|
getSupportsAppExit() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
setFullscreen(flag) {
|
exitApp() {
|
||||||
getIPCRenderer().send("set-fullscreen", flag);
|
logger.log(this, "Sending app exit signal");
|
||||||
}
|
getIPCRenderer().send("exit-app");
|
||||||
|
}
|
||||||
getSupportsAppExit() {
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
exitApp() {
|
|
||||||
logger.log(this, "Sending app exit signal");
|
|
||||||
getIPCRenderer().send("exit-app");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { GameRoot } from "../game/root";
|
|||||||
|
|
||||||
import { newEmptyMap, clamp } from "../core/utils";
|
import { newEmptyMap, clamp } from "../core/utils";
|
||||||
import { createLogger } from "../core/logging";
|
import { createLogger } from "../core/logging";
|
||||||
import { globalConfig, IS_DEMO } from "../core/config";
|
import { globalConfig } from "../core/config";
|
||||||
|
|
||||||
const logger = createLogger("sound");
|
const logger = createLogger("sound");
|
||||||
|
|
||||||
@ -29,7 +29,9 @@ export const SOUNDS = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const MUSIC = {
|
export const MUSIC = {
|
||||||
theme: IS_DEMO ? "theme-short" : "theme-full",
|
// The theme always depends on the standalone only, even if running the full
|
||||||
|
// version in the browser
|
||||||
|
theme: G_IS_STANDALONE ? "theme-full" : "theme-short",
|
||||||
menu: "menu",
|
menu: "menu",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,142 +1,131 @@
|
|||||||
/* typehints:start */
|
/* typehints:start */
|
||||||
import { Application } from "../application";
|
import { Application } from "../application";
|
||||||
/* typehints:end */
|
/* typehints:end */
|
||||||
|
|
||||||
import { IS_MOBILE } from "../core/config";
|
import { IS_MOBILE } from "../core/config";
|
||||||
|
|
||||||
export class PlatformWrapperInterface {
|
export class PlatformWrapperInterface {
|
||||||
constructor(app) {
|
constructor(app) {
|
||||||
/** @type {Application} */
|
/** @type {Application} */
|
||||||
this.app = app;
|
this.app = app;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {string} */
|
/** @returns {string} */
|
||||||
getId() {
|
getId() {
|
||||||
abstract;
|
abstract;
|
||||||
return "unknown-platform";
|
return "unknown-platform";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the UI scale, called on every resize
|
* Returns the UI scale, called on every resize
|
||||||
* @returns {number} */
|
* @returns {number} */
|
||||||
getUiScale() {
|
getUiScale() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {boolean} */
|
/** @returns {boolean} */
|
||||||
getSupportsRestart() {
|
getSupportsRestart() {
|
||||||
abstract;
|
abstract;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the user has unlimited savegames
|
* Returns the strength of touch pans with the mouse
|
||||||
*/
|
*/
|
||||||
getHasUnlimitedSavegames() {
|
getTouchPanStrength() {
|
||||||
return true;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
getShowDemoBadges() {
|
/** @returns {Promise<void>} */
|
||||||
return false;
|
initialize() {
|
||||||
}
|
document.documentElement.classList.add("p-" + this.getId());
|
||||||
|
return Promise.resolve();
|
||||||
/**
|
}
|
||||||
* Returns the strength of touch pans with the mouse
|
|
||||||
*/
|
/**
|
||||||
getTouchPanStrength() {
|
* Should initialize the apps ad provider in case supported
|
||||||
return 1;
|
* @returns {Promise<void>}
|
||||||
}
|
*/
|
||||||
|
initializeAdProvider() {
|
||||||
/** @returns {Promise<void>} */
|
return Promise.resolve();
|
||||||
initialize() {
|
}
|
||||||
document.documentElement.classList.add("p-" + this.getId());
|
|
||||||
return Promise.resolve();
|
/**
|
||||||
}
|
* Should return the minimum supported zoom level
|
||||||
|
* @returns {number}
|
||||||
/**
|
*/
|
||||||
* Should initialize the apps ad provider in case supported
|
getMinimumZoom() {
|
||||||
* @returns {Promise<void>}
|
return 0.1 * this.getScreenScale();
|
||||||
*/
|
}
|
||||||
initializeAdProvider() {
|
|
||||||
return Promise.resolve();
|
/**
|
||||||
}
|
* Should return the maximum supported zoom level
|
||||||
|
* @returns {number}
|
||||||
/**
|
*/
|
||||||
* Should return the minimum supported zoom level
|
getMaximumZoom() {
|
||||||
* @returns {number}
|
return 3.5 * this.getScreenScale();
|
||||||
*/
|
}
|
||||||
getMinimumZoom() {
|
|
||||||
return 0.1 * this.getScreenScale();
|
getScreenScale() {
|
||||||
}
|
return Math.min(window.innerWidth, window.innerHeight) / 1024.0;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Should return the maximum supported zoom level
|
/**
|
||||||
* @returns {number}
|
* Should return if this platform supports ads at all
|
||||||
*/
|
*/
|
||||||
getMaximumZoom() {
|
getSupportsAds() {
|
||||||
return 3.5 * this.getScreenScale();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
getScreenScale() {
|
/**
|
||||||
return Math.min(window.innerWidth, window.innerHeight) / 1024.0;
|
* Attempt to open an external url
|
||||||
}
|
* @param {string} url
|
||||||
|
* @param {boolean=} force Whether to always open the url even if not allowed
|
||||||
/**
|
*/
|
||||||
* Should return if this platform supports ads at all
|
openExternalLink(url, force = false) {
|
||||||
*/
|
abstract;
|
||||||
getSupportsAds() {
|
}
|
||||||
return false;
|
|
||||||
}
|
/**
|
||||||
|
* Attempt to restart the app
|
||||||
/**
|
*/
|
||||||
* Attempt to open an external url
|
performRestart() {
|
||||||
* @param {string} url
|
abstract;
|
||||||
* @param {boolean=} force Whether to always open the url even if not allowed
|
}
|
||||||
*/
|
|
||||||
openExternalLink(url, force = false) {
|
/**
|
||||||
abstract;
|
* Returns whether this platform supports a toggleable fullscreen
|
||||||
}
|
*/
|
||||||
|
getSupportsFullscreen() {
|
||||||
/**
|
return false;
|
||||||
* Attempt to restart the app
|
}
|
||||||
*/
|
|
||||||
performRestart() {
|
/**
|
||||||
abstract;
|
* Should set the apps fullscreen state to the desired state
|
||||||
}
|
* @param {boolean} flag
|
||||||
|
*/
|
||||||
/**
|
setFullscreen(flag) {
|
||||||
* Returns whether this platform supports a toggleable fullscreen
|
abstract;
|
||||||
*/
|
}
|
||||||
getSupportsFullscreen() {
|
|
||||||
return false;
|
/**
|
||||||
}
|
* Returns whether this platform supports quitting the app
|
||||||
|
*/
|
||||||
/**
|
getSupportsAppExit() {
|
||||||
* Should set the apps fullscreen state to the desired state
|
return false;
|
||||||
* @param {boolean} flag
|
}
|
||||||
*/
|
|
||||||
setFullscreen(flag) {
|
/**
|
||||||
abstract;
|
* Attempts to quit the app
|
||||||
}
|
*/
|
||||||
|
exitApp() {
|
||||||
/**
|
abstract;
|
||||||
* Returns whether this platform supports quitting the app
|
}
|
||||||
*/
|
|
||||||
getSupportsAppExit() {
|
/**
|
||||||
return false;
|
* Whether this platform supports a keyboard
|
||||||
}
|
*/
|
||||||
|
getSupportsKeyboard() {
|
||||||
/**
|
return !IS_MOBILE;
|
||||||
* Attempts to quit the app
|
}
|
||||||
*/
|
}
|
||||||
exitApp() {
|
|
||||||
abstract;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether this platform supports a keyboard
|
|
||||||
*/
|
|
||||||
getSupportsKeyboard() {
|
|
||||||
return !IS_MOBILE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -6,8 +6,7 @@ import { ReadWriteProxy } from "../core/read_write_proxy";
|
|||||||
import { BoolSetting, EnumSetting, RangeSetting, BaseSetting } from "./setting_types";
|
import { BoolSetting, EnumSetting, RangeSetting, BaseSetting } from "./setting_types";
|
||||||
import { createLogger } from "../core/logging";
|
import { createLogger } from "../core/logging";
|
||||||
import { ExplainedResult } from "../core/explained_result";
|
import { ExplainedResult } from "../core/explained_result";
|
||||||
import { THEMES, THEME, applyGameTheme } from "../game/theme";
|
import { THEMES, applyGameTheme } from "../game/theme";
|
||||||
import { IS_DEMO } from "../core/config";
|
|
||||||
import { T } from "../translations";
|
import { T } from "../translations";
|
||||||
import { LANGUAGES } from "../languages";
|
import { LANGUAGES } from "../languages";
|
||||||
|
|
||||||
@ -187,7 +186,9 @@ export const allApplicationSettings = [
|
|||||||
app.platformWrapper.setFullscreen(value);
|
app.platformWrapper.setFullscreen(value);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
!IS_DEMO
|
/**
|
||||||
|
* @param {Application} app
|
||||||
|
*/ app => app.restrictionMgr.getHasExtendedSettings()
|
||||||
),
|
),
|
||||||
|
|
||||||
new BoolSetting(
|
new BoolSetting(
|
||||||
@ -215,7 +216,9 @@ export const allApplicationSettings = [
|
|||||||
applyGameTheme(id);
|
applyGameTheme(id);
|
||||||
document.documentElement.setAttribute("data-theme", id);
|
document.documentElement.setAttribute("data-theme", id);
|
||||||
},
|
},
|
||||||
enabled: !IS_DEMO,
|
enabledCb: /**
|
||||||
|
* @param {Application} app
|
||||||
|
*/ app => app.restrictionMgr.getHasExtendedSettings(),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
new EnumSetting("autosaveInterval", {
|
new EnumSetting("autosaveInterval", {
|
||||||
@ -255,6 +258,7 @@ export const allApplicationSettings = [
|
|||||||
|
|
||||||
new BoolSetting("enableMousePan", enumCategories.advanced, (app, value) => {}),
|
new BoolSetting("enableMousePan", enumCategories.advanced, (app, value) => {}),
|
||||||
new BoolSetting("alwaysMultiplace", enumCategories.advanced, (app, value) => {}),
|
new BoolSetting("alwaysMultiplace", enumCategories.advanced, (app, value) => {}),
|
||||||
|
new BoolSetting("zoomToCursor", enumCategories.advanced, (app, value) => {}),
|
||||||
new BoolSetting("clearCursorOnDeleteWhilePlacing", enumCategories.advanced, (app, value) => {}),
|
new BoolSetting("clearCursorOnDeleteWhilePlacing", enumCategories.advanced, (app, value) => {}),
|
||||||
new BoolSetting("enableTunnelSmartplace", enumCategories.advanced, (app, value) => {}),
|
new BoolSetting("enableTunnelSmartplace", enumCategories.advanced, (app, value) => {}),
|
||||||
new BoolSetting("vignette", enumCategories.userInterface, (app, value) => {}),
|
new BoolSetting("vignette", enumCategories.userInterface, (app, value) => {}),
|
||||||
@ -271,7 +275,9 @@ export const allApplicationSettings = [
|
|||||||
category: enumCategories.performance,
|
category: enumCategories.performance,
|
||||||
restartRequired: false,
|
restartRequired: false,
|
||||||
changeCb: (app, id) => {},
|
changeCb: (app, id) => {},
|
||||||
enabled: !IS_DEMO,
|
enabledCb: /**
|
||||||
|
* @param {Application} app
|
||||||
|
*/ app => app.restrictionMgr.getHasExtendedSettings(),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
new BoolSetting("lowQualityMapResources", enumCategories.performance, (app, value) => {}),
|
new BoolSetting("lowQualityMapResources", enumCategories.performance, (app, value) => {}),
|
||||||
@ -317,6 +323,7 @@ class SettingsStorage {
|
|||||||
this.disableTileGrid = false;
|
this.disableTileGrid = false;
|
||||||
this.lowQualityTextures = false;
|
this.lowQualityTextures = false;
|
||||||
this.simplifiedBelts = false;
|
this.simplifiedBelts = false;
|
||||||
|
this.zoomToCursor = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {Object.<string, number>}
|
* @type {Object.<string, number>}
|
||||||
@ -355,7 +362,7 @@ export class ApplicationSettings extends ReadWriteProxy {
|
|||||||
* @returns {SettingsStorage}
|
* @returns {SettingsStorage}
|
||||||
*/
|
*/
|
||||||
getAllSettings() {
|
getAllSettings() {
|
||||||
return this.getCurrentData().settings;
|
return this.currentData.settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -527,7 +534,7 @@ export class ApplicationSettings extends ReadWriteProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getCurrentVersion() {
|
getCurrentVersion() {
|
||||||
return 28;
|
return 29;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {{settings: SettingsStorage, version: number}} data */
|
/** @param {{settings: SettingsStorage, version: number}} data */
|
||||||
@ -660,6 +667,11 @@ export class ApplicationSettings extends ReadWriteProxy {
|
|||||||
data.version = 28;
|
data.version = 28;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.version < 29) {
|
||||||
|
data.settings.zoomToCursor = true;
|
||||||
|
data.version = 29;
|
||||||
|
}
|
||||||
|
|
||||||
return ExplainedResult.good();
|
return ExplainedResult.good();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,13 +13,13 @@ export class BaseSetting {
|
|||||||
* @param {string} id
|
* @param {string} id
|
||||||
* @param {string} categoryId
|
* @param {string} categoryId
|
||||||
* @param {function(Application, any):void} changeCb
|
* @param {function(Application, any):void} changeCb
|
||||||
* @param {boolean} enabled
|
* @param {function(Application) : boolean=} enabledCb
|
||||||
*/
|
*/
|
||||||
constructor(id, categoryId, changeCb, enabled) {
|
constructor(id, categoryId, changeCb, enabledCb = null) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.categoryId = categoryId;
|
this.categoryId = categoryId;
|
||||||
this.changeCb = changeCb;
|
this.changeCb = changeCb;
|
||||||
this.enabled = enabled;
|
this.enabledCb = enabledCb;
|
||||||
|
|
||||||
/** @type {Application} */
|
/** @type {Application} */
|
||||||
this.app = null;
|
this.app = null;
|
||||||
@ -39,6 +39,7 @@ export class BaseSetting {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Binds all parameters
|
||||||
* @param {Application} app
|
* @param {Application} app
|
||||||
* @param {HTMLElement} element
|
* @param {HTMLElement} element
|
||||||
* @param {any} dialogs
|
* @param {any} dialogs
|
||||||
@ -49,19 +50,37 @@ export class BaseSetting {
|
|||||||
this.dialogs = dialogs;
|
this.dialogs = dialogs;
|
||||||
}
|
}
|
||||||
|
|
||||||
getHtml() {
|
/**
|
||||||
|
* Returns the HTML for this setting
|
||||||
|
* @param {Application} app
|
||||||
|
*/
|
||||||
|
getHtml(app) {
|
||||||
abstract;
|
abstract;
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this setting is enabled and available
|
||||||
|
* @param {Application} app
|
||||||
|
*/
|
||||||
|
getIsAvailable(app) {
|
||||||
|
return this.enabledCb ? this.enabledCb(app) : true;
|
||||||
|
}
|
||||||
|
|
||||||
syncValueToElement() {
|
syncValueToElement() {
|
||||||
abstract;
|
abstract;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to modify the setting
|
||||||
|
*/
|
||||||
modify() {
|
modify() {
|
||||||
abstract;
|
abstract;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the dialog that a restart is required
|
||||||
|
*/
|
||||||
showRestartRequiredDialog() {
|
showRestartRequiredDialog() {
|
||||||
const { restart } = this.dialogs.showInfo(
|
const { restart } = this.dialogs.showInfo(
|
||||||
T.dialogs.restartRequired.title,
|
T.dialogs.restartRequired.title,
|
||||||
@ -74,6 +93,7 @@ export class BaseSetting {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Validates the set value
|
||||||
* @param {any} value
|
* @param {any} value
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
@ -96,10 +116,10 @@ export class EnumSetting extends BaseSetting {
|
|||||||
iconPrefix = null,
|
iconPrefix = null,
|
||||||
changeCb = null,
|
changeCb = null,
|
||||||
magicValue = null,
|
magicValue = null,
|
||||||
enabled = true,
|
enabledCb = null,
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
super(id, category, changeCb, enabled);
|
super(id, category, changeCb, enabledCb);
|
||||||
|
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.valueGetter = valueGetter;
|
this.valueGetter = valueGetter;
|
||||||
@ -110,10 +130,14 @@ export class EnumSetting extends BaseSetting {
|
|||||||
this.magicValue = magicValue;
|
this.magicValue = magicValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
getHtml() {
|
/**
|
||||||
|
* @param {Application} app
|
||||||
|
*/
|
||||||
|
getHtml(app) {
|
||||||
|
const available = this.getIsAvailable(app);
|
||||||
return `
|
return `
|
||||||
<div class="setting cardbox ${this.enabled ? "enabled" : "disabled"}">
|
<div class="setting cardbox ${available ? "enabled" : "disabled"}">
|
||||||
${this.enabled ? "" : `<span class="standaloneOnlyHint">${T.demo.settingNotAvailable}</span>`}
|
${available ? "" : `<span class="standaloneOnlyHint">${T.demo.settingNotAvailable}</span>`}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label>${T.settings.labels[this.id].title}</label>
|
<label>${T.settings.labels[this.id].title}</label>
|
||||||
<div class="value enum" data-setting="${this.id}"></div>
|
<div class="value enum" data-setting="${this.id}"></div>
|
||||||
@ -180,14 +204,18 @@ export class EnumSetting extends BaseSetting {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class BoolSetting extends BaseSetting {
|
export class BoolSetting extends BaseSetting {
|
||||||
constructor(id, category, changeCb = null, enabled = true) {
|
constructor(id, category, changeCb = null, enabledCb = null) {
|
||||||
super(id, category, changeCb, enabled);
|
super(id, category, changeCb, enabledCb);
|
||||||
}
|
}
|
||||||
|
|
||||||
getHtml() {
|
/**
|
||||||
|
* @param {Application} app
|
||||||
|
*/
|
||||||
|
getHtml(app) {
|
||||||
|
const available = this.getIsAvailable(app);
|
||||||
return `
|
return `
|
||||||
<div class="setting cardbox ${this.enabled ? "enabled" : "disabled"}">
|
<div class="setting cardbox ${available ? "enabled" : "disabled"}">
|
||||||
${this.enabled ? "" : `<span class="standaloneOnlyHint">${T.demo.settingNotAvailable}</span>`}
|
${available ? "" : `<span class="standaloneOnlyHint">${T.demo.settingNotAvailable}</span>`}
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label>${T.settings.labels[this.id].title}</label>
|
<label>${T.settings.labels[this.id].title}</label>
|
||||||
@ -226,13 +254,13 @@ export class RangeSetting extends BaseSetting {
|
|||||||
id,
|
id,
|
||||||
category,
|
category,
|
||||||
changeCb = null,
|
changeCb = null,
|
||||||
enabled = true,
|
|
||||||
defaultValue = 1.0,
|
defaultValue = 1.0,
|
||||||
minValue = 0,
|
minValue = 0,
|
||||||
maxValue = 1.0,
|
maxValue = 1.0,
|
||||||
stepSize = 0.0001
|
stepSize = 0.0001,
|
||||||
|
enabledCb = null
|
||||||
) {
|
) {
|
||||||
super(id, category, changeCb, enabled);
|
super(id, category, changeCb, enabledCb);
|
||||||
|
|
||||||
this.defaultValue = defaultValue;
|
this.defaultValue = defaultValue;
|
||||||
this.minValue = minValue;
|
this.minValue = minValue;
|
||||||
@ -240,10 +268,14 @@ export class RangeSetting extends BaseSetting {
|
|||||||
this.stepSize = stepSize;
|
this.stepSize = stepSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
getHtml() {
|
/**
|
||||||
|
* @param {Application} app
|
||||||
|
*/
|
||||||
|
getHtml(app) {
|
||||||
|
const available = this.getIsAvailable(app);
|
||||||
return `
|
return `
|
||||||
<div class="setting cardbox ${this.enabled ? "enabled" : "disabled"}">
|
<div class="setting cardbox ${available ? "enabled" : "disabled"}">
|
||||||
${this.enabled ? "" : `<span class="standaloneOnlyHint">${T.demo.settingNotAvailable}</span>`}
|
${available ? "" : `<span class="standaloneOnlyHint">${T.demo.settingNotAvailable}</span>`}
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label>${T.settings.labels[this.id].title}</label>
|
<label>${T.settings.labels[this.id].title}</label>
|
||||||
|
|||||||
@ -40,13 +40,6 @@ export class SavegameManager extends ReadWriteProxy {
|
|||||||
return 1002;
|
return 1002;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {SavegamesData}
|
|
||||||
*/
|
|
||||||
getCurrentData() {
|
|
||||||
return super.getCurrentData();
|
|
||||||
}
|
|
||||||
|
|
||||||
verify(data) {
|
verify(data) {
|
||||||
// TODO / FIXME!!!!
|
// TODO / FIXME!!!!
|
||||||
return ExplainedResult.good();
|
return ExplainedResult.good();
|
||||||
@ -96,6 +89,14 @@ export class SavegameManager extends ReadWriteProxy {
|
|||||||
return new Savegame(this.app, { internalId, metaDataRef: metadata });
|
return new Savegame(this.app, { internalId, metaDataRef: metadata });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if this manager has any savegame of a 1.1.19 version, which
|
||||||
|
* enables all levels
|
||||||
|
*/
|
||||||
|
getHasAnyLegacySavegames() {
|
||||||
|
return this.currentData.savegames.some(savegame => savegame.version === 1005 || savegame.level > 14);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a savegame
|
* Deletes a savegame
|
||||||
* @param {SavegameMetadata} game
|
* @param {SavegameMetadata} game
|
||||||
@ -149,7 +150,9 @@ export class SavegameManager extends ReadWriteProxy {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.currentData.savegames.push(metaData);
|
this.currentData.savegames.push(metaData);
|
||||||
this.sortSavegames();
|
|
||||||
|
// Notice: This is async and happening in the background
|
||||||
|
this.updateAfterSavegamesChanged();
|
||||||
|
|
||||||
return new Savegame(this.app, {
|
return new Savegame(this.app, {
|
||||||
internalId: id,
|
internalId: id,
|
||||||
@ -157,8 +160,16 @@ export class SavegameManager extends ReadWriteProxy {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to import a savegame
|
||||||
|
* @param {object} data
|
||||||
|
*/
|
||||||
importSavegame(data) {
|
importSavegame(data) {
|
||||||
const savegame = this.createNewSavegame();
|
const savegame = this.createNewSavegame();
|
||||||
|
|
||||||
|
// Track legacy savegames
|
||||||
|
const isOldSavegame = data.version < 1006;
|
||||||
|
|
||||||
const migrationResult = savegame.migrate(data);
|
const migrationResult = savegame.migrate(data);
|
||||||
if (migrationResult.isBad()) {
|
if (migrationResult.isBad()) {
|
||||||
return Promise.reject("Failed to migrate: " + migrationResult.reason);
|
return Promise.reject("Failed to migrate: " + migrationResult.reason);
|
||||||
@ -170,7 +181,19 @@ export class SavegameManager extends ReadWriteProxy {
|
|||||||
return Promise.reject("Verification failed: " + verification.result);
|
return Promise.reject("Verification failed: " + verification.result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return savegame.writeSavegameAndMetadata().then(() => this.sortSavegames());
|
return savegame
|
||||||
|
.writeSavegameAndMetadata()
|
||||||
|
.then(() => this.updateAfterSavegamesChanged())
|
||||||
|
.then(() => this.app.restrictionMgr.onHasLegacySavegamesChanged(isOldSavegame));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook after the savegames got changed
|
||||||
|
*/
|
||||||
|
updateAfterSavegamesChanged() {
|
||||||
|
return this.sortSavegames()
|
||||||
|
.then(() => this.writeAsync())
|
||||||
|
.then(() => this.app.restrictionMgr.onHasLegacySavegamesChanged(this.getHasAnyLegacySavegames()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -219,7 +242,7 @@ export class SavegameManager extends ReadWriteProxy {
|
|||||||
if (G_IS_DEV && globalConfig.debug.disableSavegameWrite) {
|
if (G_IS_DEV && globalConfig.debug.disableSavegameWrite) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
return this.sortSavegames().then(() => this.writeAsync());
|
return this.updateAfterSavegamesChanged();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -130,7 +130,7 @@ export class SavegameSerializer {
|
|||||||
errorReason = errorReason || root.time.deserialize(savegame.time);
|
errorReason = errorReason || root.time.deserialize(savegame.time);
|
||||||
errorReason = errorReason || root.camera.deserialize(savegame.camera);
|
errorReason = errorReason || root.camera.deserialize(savegame.camera);
|
||||||
errorReason = errorReason || root.map.deserialize(savegame.map);
|
errorReason = errorReason || root.map.deserialize(savegame.map);
|
||||||
errorReason = errorReason || root.hubGoals.deserialize(savegame.hubGoals);
|
errorReason = errorReason || root.hubGoals.deserialize(savegame.hubGoals, root);
|
||||||
errorReason = errorReason || root.hud.parts.pinnedShapes.deserialize(savegame.pinnedShapes);
|
errorReason = errorReason || root.hud.parts.pinnedShapes.deserialize(savegame.pinnedShapes);
|
||||||
errorReason = errorReason || root.hud.parts.waypoints.deserialize(savegame.waypoints);
|
errorReason = errorReason || root.hud.parts.waypoints.deserialize(savegame.waypoints);
|
||||||
errorReason = errorReason || this.internal.deserializeEntityArray(root, savegame.entities);
|
errorReason = errorReason || this.internal.deserializeEntityArray(root, savegame.entities);
|
||||||
|
|||||||
@ -19,7 +19,6 @@ import { getCodeFromBuildingData } from "../../game/building_codes.js";
|
|||||||
import { StaticMapEntityComponent } from "../../game/components/static_map_entity.js";
|
import { StaticMapEntityComponent } from "../../game/components/static_map_entity.js";
|
||||||
import { Entity } from "../../game/entity.js";
|
import { Entity } from "../../game/entity.js";
|
||||||
import { defaultBuildingVariant, MetaBuilding } from "../../game/meta_building.js";
|
import { defaultBuildingVariant, MetaBuilding } from "../../game/meta_building.js";
|
||||||
import { finalGameShape } from "../../game/upgrades.js";
|
|
||||||
import { SavegameInterface_V1005 } from "./1005.js";
|
import { SavegameInterface_V1005 } from "./1005.js";
|
||||||
|
|
||||||
const schema = require("./1006.json");
|
const schema = require("./1006.json");
|
||||||
@ -152,7 +151,8 @@ export class SavegameInterface_V1006 extends SavegameInterface_V1005 {
|
|||||||
stored[shapeKey] = rebalance(stored[shapeKey]);
|
stored[shapeKey] = rebalance(stored[shapeKey]);
|
||||||
}
|
}
|
||||||
|
|
||||||
stored[finalGameShape] = 0;
|
// Reset final game shape
|
||||||
|
stored["RuCw--Cw:----Ru--"] = 0;
|
||||||
|
|
||||||
// Reduce goals
|
// Reduce goals
|
||||||
if (dump.hubGoals.currentGoal) {
|
if (dump.hubGoals.currentGoal) {
|
||||||
|
|||||||
@ -1,179 +1,173 @@
|
|||||||
import { TextualGameState } from "../core/textual_game_state";
|
import { Dialog } from "../core/modal_dialog_elements";
|
||||||
import { SOUNDS } from "../platform/sound";
|
import { TextualGameState } from "../core/textual_game_state";
|
||||||
import { T } from "../translations";
|
import { getStringForKeyCode, KEYMAPPINGS } from "../game/key_action_mapper";
|
||||||
import { KEYMAPPINGS, getStringForKeyCode } from "../game/key_action_mapper";
|
import { SOUNDS } from "../platform/sound";
|
||||||
import { Dialog } from "../core/modal_dialog_elements";
|
import { T } from "../translations";
|
||||||
import { IS_DEMO } from "../core/config";
|
|
||||||
|
export class KeybindingsState extends TextualGameState {
|
||||||
export class KeybindingsState extends TextualGameState {
|
constructor() {
|
||||||
constructor() {
|
super("KeybindingsState");
|
||||||
super("KeybindingsState");
|
}
|
||||||
}
|
|
||||||
|
getStateHeaderTitle() {
|
||||||
getStateHeaderTitle() {
|
return T.keybindings.title;
|
||||||
return T.keybindings.title;
|
}
|
||||||
}
|
|
||||||
|
getMainContentHTML() {
|
||||||
getMainContentHTML() {
|
return `
|
||||||
return `
|
|
||||||
|
<div class="topEntries">
|
||||||
<div class="topEntries">
|
<span class="hint">${T.keybindings.hint}</span>
|
||||||
<span class="hint">${T.keybindings.hint}</span>
|
<button class="styledButton resetBindings">${T.keybindings.resetKeybindings}</button>
|
||||||
<button class="styledButton resetBindings">${T.keybindings.resetKeybindings}</button>
|
|
||||||
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="keybindings">
|
||||||
<div class="keybindings">
|
|
||||||
|
</div>
|
||||||
</div>
|
`;
|
||||||
`;
|
}
|
||||||
}
|
|
||||||
|
onEnter() {
|
||||||
onEnter() {
|
const keybindingsElem = this.htmlElement.querySelector(".keybindings");
|
||||||
const keybindingsElem = this.htmlElement.querySelector(".keybindings");
|
|
||||||
|
this.trackClicks(this.htmlElement.querySelector(".resetBindings"), this.resetBindings);
|
||||||
this.trackClicks(this.htmlElement.querySelector(".resetBindings"), this.resetBindings);
|
|
||||||
|
for (const category in KEYMAPPINGS) {
|
||||||
for (const category in KEYMAPPINGS) {
|
const categoryDiv = document.createElement("div");
|
||||||
const categoryDiv = document.createElement("div");
|
categoryDiv.classList.add("category");
|
||||||
categoryDiv.classList.add("category");
|
keybindingsElem.appendChild(categoryDiv);
|
||||||
keybindingsElem.appendChild(categoryDiv);
|
|
||||||
|
const labelDiv = document.createElement("strong");
|
||||||
const labelDiv = document.createElement("strong");
|
labelDiv.innerText = T.keybindings.categoryLabels[category];
|
||||||
labelDiv.innerText = T.keybindings.categoryLabels[category];
|
labelDiv.classList.add("categoryLabel");
|
||||||
labelDiv.classList.add("categoryLabel");
|
categoryDiv.appendChild(labelDiv);
|
||||||
categoryDiv.appendChild(labelDiv);
|
|
||||||
|
for (const keybindingId in KEYMAPPINGS[category]) {
|
||||||
for (const keybindingId in KEYMAPPINGS[category]) {
|
const mapped = KEYMAPPINGS[category][keybindingId];
|
||||||
const mapped = KEYMAPPINGS[category][keybindingId];
|
|
||||||
|
const elem = document.createElement("div");
|
||||||
const elem = document.createElement("div");
|
elem.classList.add("entry");
|
||||||
elem.classList.add("entry");
|
elem.setAttribute("data-keybinding", keybindingId);
|
||||||
elem.setAttribute("data-keybinding", keybindingId);
|
categoryDiv.appendChild(elem);
|
||||||
categoryDiv.appendChild(elem);
|
|
||||||
|
const title = document.createElement("span");
|
||||||
const title = document.createElement("span");
|
title.classList.add("title");
|
||||||
title.classList.add("title");
|
title.innerText = T.keybindings.mappings[keybindingId];
|
||||||
title.innerText = T.keybindings.mappings[keybindingId];
|
elem.appendChild(title);
|
||||||
elem.appendChild(title);
|
|
||||||
|
const mappingDiv = document.createElement("span");
|
||||||
const mappingDiv = document.createElement("span");
|
mappingDiv.classList.add("mapping");
|
||||||
mappingDiv.classList.add("mapping");
|
elem.appendChild(mappingDiv);
|
||||||
elem.appendChild(mappingDiv);
|
|
||||||
|
const editBtn = document.createElement("button");
|
||||||
const editBtn = document.createElement("button");
|
editBtn.classList.add("styledButton", "editKeybinding");
|
||||||
editBtn.classList.add("styledButton", "editKeybinding");
|
|
||||||
|
const resetBtn = document.createElement("button");
|
||||||
const resetBtn = document.createElement("button");
|
resetBtn.classList.add("styledButton", "resetKeybinding");
|
||||||
resetBtn.classList.add("styledButton", "resetKeybinding");
|
|
||||||
|
if (mapped.builtin) {
|
||||||
if (mapped.builtin) {
|
editBtn.classList.add("disabled");
|
||||||
editBtn.classList.add("disabled");
|
resetBtn.classList.add("disabled");
|
||||||
resetBtn.classList.add("disabled");
|
} else {
|
||||||
} else {
|
this.trackClicks(editBtn, () => this.editKeybinding(keybindingId));
|
||||||
this.trackClicks(editBtn, () => this.editKeybinding(keybindingId));
|
this.trackClicks(resetBtn, () => this.resetKeybinding(keybindingId));
|
||||||
this.trackClicks(resetBtn, () => this.resetKeybinding(keybindingId));
|
}
|
||||||
}
|
elem.appendChild(editBtn);
|
||||||
elem.appendChild(editBtn);
|
elem.appendChild(resetBtn);
|
||||||
elem.appendChild(resetBtn);
|
}
|
||||||
}
|
}
|
||||||
}
|
this.updateKeybindings();
|
||||||
this.updateKeybindings();
|
}
|
||||||
}
|
|
||||||
|
editKeybinding(id) {
|
||||||
editKeybinding(id) {
|
const dialog = new Dialog({
|
||||||
// if (IS_DEMO) {
|
app: this.app,
|
||||||
// this.dialogs.showFeatureRestrictionInfo(T.demo.features.customizeKeybindings);
|
title: T.dialogs.editKeybinding.title,
|
||||||
// return;
|
contentHTML: T.dialogs.editKeybinding.desc,
|
||||||
// }
|
buttons: ["cancel:good"],
|
||||||
|
type: "info",
|
||||||
const dialog = new Dialog({
|
});
|
||||||
app: this.app,
|
|
||||||
title: T.dialogs.editKeybinding.title,
|
dialog.inputReciever.keydown.add(({ keyCode, shift, alt, event }) => {
|
||||||
contentHTML: T.dialogs.editKeybinding.desc,
|
if (keyCode === 27) {
|
||||||
buttons: ["cancel:good"],
|
this.dialogs.closeDialog(dialog);
|
||||||
type: "info",
|
return;
|
||||||
});
|
}
|
||||||
|
|
||||||
dialog.inputReciever.keydown.add(({ keyCode, shift, alt, event }) => {
|
if (event) {
|
||||||
if (keyCode === 27) {
|
event.preventDefault();
|
||||||
this.dialogs.closeDialog(dialog);
|
}
|
||||||
return;
|
|
||||||
}
|
if (event.target && event.target.tagName === "BUTTON" && keyCode === 1) {
|
||||||
|
return;
|
||||||
if (event) {
|
}
|
||||||
event.preventDefault();
|
|
||||||
}
|
if (
|
||||||
|
// Enter
|
||||||
if (event.target && event.target.tagName === "BUTTON" && keyCode === 1) {
|
keyCode === 13
|
||||||
return;
|
) {
|
||||||
}
|
// Ignore builtins
|
||||||
|
return;
|
||||||
if (
|
}
|
||||||
// Enter
|
|
||||||
keyCode === 13
|
this.app.settings.updateKeybindingOverride(id, keyCode);
|
||||||
) {
|
|
||||||
// Ignore builtins
|
this.dialogs.closeDialog(dialog);
|
||||||
return;
|
this.updateKeybindings();
|
||||||
}
|
});
|
||||||
|
|
||||||
this.app.settings.updateKeybindingOverride(id, keyCode);
|
dialog.inputReciever.backButton.add(() => {});
|
||||||
|
this.dialogs.internalShowDialog(dialog);
|
||||||
this.dialogs.closeDialog(dialog);
|
|
||||||
this.updateKeybindings();
|
this.app.sound.playUiSound(SOUNDS.dialogOk);
|
||||||
});
|
}
|
||||||
|
|
||||||
dialog.inputReciever.backButton.add(() => {});
|
updateKeybindings() {
|
||||||
this.dialogs.internalShowDialog(dialog);
|
const overrides = this.app.settings.getKeybindingOverrides();
|
||||||
|
for (const category in KEYMAPPINGS) {
|
||||||
this.app.sound.playUiSound(SOUNDS.dialogOk);
|
for (const keybindingId in KEYMAPPINGS[category]) {
|
||||||
}
|
const mapped = KEYMAPPINGS[category][keybindingId];
|
||||||
|
|
||||||
updateKeybindings() {
|
const container = this.htmlElement.querySelector("[data-keybinding='" + keybindingId + "']");
|
||||||
const overrides = this.app.settings.getKeybindingOverrides();
|
assert(container, "Container for keybinding not found: " + keybindingId);
|
||||||
for (const category in KEYMAPPINGS) {
|
|
||||||
for (const keybindingId in KEYMAPPINGS[category]) {
|
let keyCode = mapped.keyCode;
|
||||||
const mapped = KEYMAPPINGS[category][keybindingId];
|
if (overrides[keybindingId]) {
|
||||||
|
keyCode = overrides[keybindingId];
|
||||||
const container = this.htmlElement.querySelector("[data-keybinding='" + keybindingId + "']");
|
}
|
||||||
assert(container, "Container for keybinding not found: " + keybindingId);
|
|
||||||
|
const mappingDiv = container.querySelector(".mapping");
|
||||||
let keyCode = mapped.keyCode;
|
mappingDiv.innerHTML = getStringForKeyCode(keyCode);
|
||||||
if (overrides[keybindingId]) {
|
mappingDiv.classList.toggle("changed", !!overrides[keybindingId]);
|
||||||
keyCode = overrides[keybindingId];
|
|
||||||
}
|
const resetBtn = container.querySelector("button.resetKeybinding");
|
||||||
|
resetBtn.classList.toggle("disabled", mapped.builtin || !overrides[keybindingId]);
|
||||||
const mappingDiv = container.querySelector(".mapping");
|
}
|
||||||
mappingDiv.innerHTML = getStringForKeyCode(keyCode);
|
}
|
||||||
mappingDiv.classList.toggle("changed", !!overrides[keybindingId]);
|
}
|
||||||
|
|
||||||
const resetBtn = container.querySelector("button.resetKeybinding");
|
resetKeybinding(id) {
|
||||||
resetBtn.classList.toggle("disabled", mapped.builtin || !overrides[keybindingId]);
|
this.app.settings.resetKeybindingOverride(id);
|
||||||
}
|
this.updateKeybindings();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
resetBindings() {
|
||||||
resetKeybinding(id) {
|
const { reset } = this.dialogs.showWarning(
|
||||||
this.app.settings.resetKeybindingOverride(id);
|
T.dialogs.resetKeybindingsConfirmation.title,
|
||||||
this.updateKeybindings();
|
T.dialogs.resetKeybindingsConfirmation.desc,
|
||||||
}
|
["cancel:good", "reset:bad"]
|
||||||
|
);
|
||||||
resetBindings() {
|
|
||||||
const { reset } = this.dialogs.showWarning(
|
reset.add(() => {
|
||||||
T.dialogs.resetKeybindingsConfirmation.title,
|
this.app.settings.resetKeybindingOverrides();
|
||||||
T.dialogs.resetKeybindingsConfirmation.desc,
|
this.updateKeybindings();
|
||||||
["cancel:good", "reset:bad"]
|
|
||||||
);
|
this.dialogs.showInfo(T.dialogs.keybindingsResetOk.title, T.dialogs.keybindingsResetOk.desc);
|
||||||
|
});
|
||||||
reset.add(() => {
|
}
|
||||||
this.app.settings.resetKeybindingOverrides();
|
|
||||||
this.updateKeybindings();
|
getDefaultPreviousState() {
|
||||||
|
return "SettingsState";
|
||||||
this.dialogs.showInfo(T.dialogs.keybindingsResetOk.title, T.dialogs.keybindingsResetOk.desc);
|
}
|
||||||
});
|
}
|
||||||
}
|
|
||||||
|
|
||||||
getDefaultPreviousState() {
|
|
||||||
return "SettingsState";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,21 +1,23 @@
|
|||||||
import { GameState } from "../core/game_state";
|
|
||||||
import { cachebust } from "../core/cachebust";
|
import { cachebust } from "../core/cachebust";
|
||||||
import { A_B_TESTING_LINK_TYPE, globalConfig, IS_DEMO, THIRDPARTY_URLS } from "../core/config";
|
import { A_B_TESTING_LINK_TYPE, globalConfig, THIRDPARTY_URLS } from "../core/config";
|
||||||
|
import { GameState } from "../core/game_state";
|
||||||
|
import { DialogWithForm } from "../core/modal_dialog_elements";
|
||||||
|
import { FormElementInput } from "../core/modal_dialog_forms";
|
||||||
|
import { ReadWriteProxy } from "../core/read_write_proxy";
|
||||||
import {
|
import {
|
||||||
makeDiv,
|
|
||||||
makeButtonElement,
|
|
||||||
formatSecondsToTimeAgo,
|
formatSecondsToTimeAgo,
|
||||||
waitNextFrame,
|
generateFileDownload,
|
||||||
isSupportedBrowser,
|
isSupportedBrowser,
|
||||||
makeButton,
|
makeButton,
|
||||||
|
makeButtonElement,
|
||||||
|
makeDiv,
|
||||||
removeAllChildren,
|
removeAllChildren,
|
||||||
|
startFileChoose,
|
||||||
|
waitNextFrame,
|
||||||
} from "../core/utils";
|
} from "../core/utils";
|
||||||
import { ReadWriteProxy } from "../core/read_write_proxy";
|
|
||||||
import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs";
|
import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs";
|
||||||
import { T } from "../translations";
|
|
||||||
import { getApplicationSettingById } from "../profile/application_settings";
|
import { getApplicationSettingById } from "../profile/application_settings";
|
||||||
import { FormElementInput } from "../core/modal_dialog_forms";
|
import { T } from "../translations";
|
||||||
import { DialogWithForm } from "../core/modal_dialog_elements";
|
|
||||||
|
|
||||||
const trim = require("trim");
|
const trim = require("trim");
|
||||||
|
|
||||||
@ -24,23 +26,6 @@ const trim = require("trim");
|
|||||||
* @typedef {import("../profile/setting_types").EnumSetting} EnumSetting
|
* @typedef {import("../profile/setting_types").EnumSetting} EnumSetting
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a file download
|
|
||||||
* @param {string} filename
|
|
||||||
* @param {string} text
|
|
||||||
*/
|
|
||||||
function generateFileDownload(filename, text) {
|
|
||||||
var element = document.createElement("a");
|
|
||||||
element.setAttribute("href", "data:text/plain;charset=utf-8," + encodeURIComponent(text));
|
|
||||||
element.setAttribute("download", filename);
|
|
||||||
|
|
||||||
element.style.display = "none";
|
|
||||||
document.body.appendChild(element);
|
|
||||||
|
|
||||||
element.click();
|
|
||||||
document.body.removeChild(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
export class MainMenuState extends GameState {
|
export class MainMenuState extends GameState {
|
||||||
constructor() {
|
constructor() {
|
||||||
super("MainMenuState");
|
super("MainMenuState");
|
||||||
@ -49,18 +34,16 @@ export class MainMenuState extends GameState {
|
|||||||
getInnerHTML() {
|
getInnerHTML() {
|
||||||
const bannerHtml = `
|
const bannerHtml = `
|
||||||
<h3>${T.demoBanners.title}</h3>
|
<h3>${T.demoBanners.title}</h3>
|
||||||
|
|
||||||
<p>${T.demoBanners.intro}</p>
|
<p>${T.demoBanners.intro}</p>
|
||||||
|
|
||||||
<a href="#" class="steamLink ${A_B_TESTING_LINK_TYPE}" target="_blank">Get the shapez.io standalone!</a>
|
<a href="#" class="steamLink ${A_B_TESTING_LINK_TYPE}" target="_blank">Get the shapez.io standalone!</a>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
return `
|
const showDemoBadges = this.app.restrictionMgr.getIsStandaloneMarketingActive();
|
||||||
|
|
||||||
|
return `
|
||||||
<div class="topButtons">
|
<div class="topButtons">
|
||||||
<button class="languageChoose" data-languageicon="${this.app.settings.getLanguage()}"></button>
|
<button class="languageChoose" data-languageicon="${this.app.settings.getLanguage()}"></button>
|
||||||
<button class="settingsButton"></button>
|
<button class="settingsButton"></button>
|
||||||
|
|
||||||
${
|
${
|
||||||
G_IS_STANDALONE || G_IS_DEV
|
G_IS_STANDALONE || G_IS_DEV
|
||||||
? `
|
? `
|
||||||
@ -74,17 +57,14 @@ export class MainMenuState extends GameState {
|
|||||||
<source src="${cachebust("res/bg_render.webm")}" type="video/webm">
|
<source src="${cachebust("res/bg_render.webm")}" type="video/webm">
|
||||||
</video>
|
</video>
|
||||||
|
|
||||||
|
|
||||||
<div class="logo">
|
<div class="logo">
|
||||||
<img src="${cachebust("res/logo.png")}" alt="shapez.io Logo">
|
<img src="${cachebust("res/logo.png")}" alt="shapez.io Logo">
|
||||||
<span class="updateLabel">Wires update!</span>
|
<span class="updateLabel">Wires update!</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="mainWrapper ${showDemoBadges ? "demo" : "noDemo"}">
|
||||||
<div class="mainWrapper ${IS_DEMO ? "demo" : "noDemo"}">
|
|
||||||
|
|
||||||
<div class="sideContainer">
|
<div class="sideContainer">
|
||||||
${IS_DEMO ? `<div class="standaloneBanner">${bannerHtml}</div>` : ""}
|
${showDemoBadges ? `<div class="standaloneBanner">${bannerHtml}</div>` : ""}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mainContainer">
|
<div class="mainContainer">
|
||||||
@ -95,12 +75,9 @@ export class MainMenuState extends GameState {
|
|||||||
}
|
}
|
||||||
<div class="buttons"></div>
|
<div class="buttons"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
|
|
||||||
<a class="githubLink boxLink" target="_blank">
|
<a class="githubLink boxLink" target="_blank">
|
||||||
${T.mainMenu.openSourceHint}
|
${T.mainMenu.openSourceHint}
|
||||||
<span class="thirdpartyLogo githubLogo"></span>
|
<span class="thirdpartyLogo githubLogo"></span>
|
||||||
@ -123,32 +100,29 @@ export class MainMenuState extends GameState {
|
|||||||
"<author-link>",
|
"<author-link>",
|
||||||
'<a class="producerLink" target="_blank">Tobias Springer</a>'
|
'<a class="producerLink" target="_blank">Tobias Springer</a>'
|
||||||
)}</div>
|
)}</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asks the user to import a savegame
|
||||||
|
*/
|
||||||
requestImportSavegame() {
|
requestImportSavegame() {
|
||||||
if (
|
if (
|
||||||
IS_DEMO &&
|
|
||||||
this.app.savegameMgr.getSavegamesMetaData().length > 0 &&
|
this.app.savegameMgr.getSavegamesMetaData().length > 0 &&
|
||||||
!this.app.platformWrapper.getHasUnlimitedSavegames()
|
!this.app.restrictionMgr.getHasUnlimitedSavegames()
|
||||||
) {
|
) {
|
||||||
this.app.analytics.trackUiClick("importgame_slot_limit_show");
|
this.app.analytics.trackUiClick("importgame_slot_limit_show");
|
||||||
this.showSavegameSlotLimit();
|
this.showSavegameSlotLimit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var input = document.createElement("input");
|
// Create a 'fake' file-input to accept savegames
|
||||||
input.type = "file";
|
startFileChoose(".bin").then(file => {
|
||||||
input.accept = ".bin";
|
|
||||||
|
|
||||||
input.onchange = e => {
|
|
||||||
const file = input.files[0];
|
|
||||||
if (file) {
|
if (file) {
|
||||||
|
const closeLoader = this.dialogs.showLoadingDialog();
|
||||||
waitNextFrame().then(() => {
|
waitNextFrame().then(() => {
|
||||||
this.app.analytics.trackUiClick("import_savegame");
|
this.app.analytics.trackUiClick("import_savegame");
|
||||||
const closeLoader = this.dialogs.showLoadingDialog();
|
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.addEventListener("load", event => {
|
reader.addEventListener("load", event => {
|
||||||
const contents = event.target.result;
|
const contents = event.target.result;
|
||||||
@ -194,8 +168,7 @@ export class MainMenuState extends GameState {
|
|||||||
reader.readAsText(file, "utf-8");
|
reader.readAsText(file, "utf-8");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
input.click();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onBackButton() {
|
onBackButton() {
|
||||||
@ -557,9 +530,8 @@ export class MainMenuState extends GameState {
|
|||||||
|
|
||||||
onPlayButtonClicked() {
|
onPlayButtonClicked() {
|
||||||
if (
|
if (
|
||||||
IS_DEMO &&
|
|
||||||
this.app.savegameMgr.getSavegamesMetaData().length > 0 &&
|
this.app.savegameMgr.getSavegamesMetaData().length > 0 &&
|
||||||
!this.app.platformWrapper.getHasUnlimitedSavegames()
|
!this.app.restrictionMgr.getHasUnlimitedSavegames()
|
||||||
) {
|
) {
|
||||||
this.app.analytics.trackUiClick("startgame_slot_limit_show");
|
this.app.analytics.trackUiClick("startgame_slot_limit_show");
|
||||||
this.showSavegameSlotLimit();
|
this.showSavegameSlotLimit();
|
||||||
|
|||||||
@ -145,6 +145,11 @@ export class PreloadState extends GameState {
|
|||||||
this.app.backgroundResourceLoader.startLoading();
|
this.app.backgroundResourceLoader.startLoading();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
.then(() => this.setStatus("Initializing restrictions"))
|
||||||
|
.then(() => {
|
||||||
|
return this.app.restrictionMgr.initialize();
|
||||||
|
})
|
||||||
|
|
||||||
.then(() => this.setStatus("Initializing savegame"))
|
.then(() => this.setStatus("Initializing savegame"))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return this.app.savegameMgr.initialize().catch(err => {
|
return this.app.savegameMgr.initialize().catch(err => {
|
||||||
|
|||||||
@ -1,169 +1,169 @@
|
|||||||
import { TextualGameState } from "../core/textual_game_state";
|
import { TextualGameState } from "../core/textual_game_state";
|
||||||
import { formatSecondsToTimeAgo } from "../core/utils";
|
import { formatSecondsToTimeAgo } from "../core/utils";
|
||||||
import { allApplicationSettings, enumCategories } from "../profile/application_settings";
|
import { allApplicationSettings, enumCategories } from "../profile/application_settings";
|
||||||
import { T } from "../translations";
|
import { T } from "../translations";
|
||||||
|
|
||||||
export class SettingsState extends TextualGameState {
|
export class SettingsState extends TextualGameState {
|
||||||
constructor() {
|
constructor() {
|
||||||
super("SettingsState");
|
super("SettingsState");
|
||||||
}
|
}
|
||||||
|
|
||||||
getStateHeaderTitle() {
|
getStateHeaderTitle() {
|
||||||
return T.settings.title;
|
return T.settings.title;
|
||||||
}
|
}
|
||||||
|
|
||||||
getMainContentHTML() {
|
getMainContentHTML() {
|
||||||
return `
|
return `
|
||||||
|
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
${this.getCategoryButtonsHtml()}
|
${this.getCategoryButtonsHtml()}
|
||||||
|
|
||||||
${
|
${
|
||||||
this.app.platformWrapper.getSupportsKeyboard()
|
this.app.platformWrapper.getSupportsKeyboard()
|
||||||
? `
|
? `
|
||||||
<button class="styledButton categoryButton editKeybindings">
|
<button class="styledButton categoryButton editKeybindings">
|
||||||
${T.keybindings.title}
|
${T.keybindings.title}
|
||||||
</button>`
|
</button>`
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="other">
|
<div class="other">
|
||||||
<button class="styledButton about">${T.about.title}</button>
|
<button class="styledButton about">${T.about.title}</button>
|
||||||
|
|
||||||
<div class="versionbar">
|
<div class="versionbar">
|
||||||
<div class="buildVersion">${T.global.loading} ...</div>
|
<div class="buildVersion">${T.global.loading} ...</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="categoryContainer">
|
<div class="categoryContainer">
|
||||||
${this.getSettingsHtml()}
|
${this.getSettingsHtml()}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getCategoryButtonsHtml() {
|
getCategoryButtonsHtml() {
|
||||||
return Object.keys(enumCategories)
|
return Object.keys(enumCategories)
|
||||||
.map(key => enumCategories[key])
|
.map(key => enumCategories[key])
|
||||||
.map(
|
.map(
|
||||||
category =>
|
category =>
|
||||||
`
|
`
|
||||||
<button class="styledButton categoryButton" data-category-btn="${category}">
|
<button class="styledButton categoryButton" data-category-btn="${category}">
|
||||||
${T.settings.categories[category]}
|
${T.settings.categories[category]}
|
||||||
</button>
|
</button>
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
.join("");
|
.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
getSettingsHtml() {
|
getSettingsHtml() {
|
||||||
const categoriesHTML = {};
|
const categoriesHTML = {};
|
||||||
|
|
||||||
Object.keys(enumCategories).forEach(key => {
|
Object.keys(enumCategories).forEach(key => {
|
||||||
const catName = enumCategories[key];
|
const catName = enumCategories[key];
|
||||||
categoriesHTML[catName] = `<div class="category" data-category="${catName}">`;
|
categoriesHTML[catName] = `<div class="category" data-category="${catName}">`;
|
||||||
});
|
});
|
||||||
|
|
||||||
for (let i = 0; i < allApplicationSettings.length; ++i) {
|
for (let i = 0; i < allApplicationSettings.length; ++i) {
|
||||||
const setting = allApplicationSettings[i];
|
const setting = allApplicationSettings[i];
|
||||||
|
|
||||||
categoriesHTML[setting.categoryId] += setting.getHtml();
|
categoriesHTML[setting.categoryId] += setting.getHtml(this.app);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Object.keys(categoriesHTML)
|
return Object.keys(categoriesHTML)
|
||||||
.map(k => categoriesHTML[k] + "</div>")
|
.map(k => categoriesHTML[k] + "</div>")
|
||||||
.join("");
|
.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
renderBuildText() {
|
renderBuildText() {
|
||||||
const labelVersion = this.htmlElement.querySelector(".buildVersion");
|
const labelVersion = this.htmlElement.querySelector(".buildVersion");
|
||||||
const lastBuildMs = new Date().getTime() - G_BUILD_TIME;
|
const lastBuildMs = new Date().getTime() - G_BUILD_TIME;
|
||||||
const lastBuildText = formatSecondsToTimeAgo(lastBuildMs / 1000.0);
|
const lastBuildText = formatSecondsToTimeAgo(lastBuildMs / 1000.0);
|
||||||
|
|
||||||
const version = T.settings.versionBadges[G_APP_ENVIRONMENT];
|
const version = T.settings.versionBadges[G_APP_ENVIRONMENT];
|
||||||
|
|
||||||
labelVersion.innerHTML = `
|
labelVersion.innerHTML = `
|
||||||
<span class='version'>
|
<span class='version'>
|
||||||
${G_BUILD_VERSION} @ ${version} @ ${G_BUILD_COMMIT_HASH}
|
${G_BUILD_VERSION} @ ${version} @ ${G_BUILD_COMMIT_HASH}
|
||||||
</span>
|
</span>
|
||||||
<span class='buildTime'>
|
<span class='buildTime'>
|
||||||
${T.settings.buildDate.replace("<at-date>", lastBuildText)}<br />
|
${T.settings.buildDate.replace("<at-date>", lastBuildText)}<br />
|
||||||
</span>`;
|
</span>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
onEnter(payload) {
|
onEnter(payload) {
|
||||||
this.renderBuildText();
|
this.renderBuildText();
|
||||||
this.trackClicks(this.htmlElement.querySelector(".about"), this.onAboutClicked, {
|
this.trackClicks(this.htmlElement.querySelector(".about"), this.onAboutClicked, {
|
||||||
preventDefault: false,
|
preventDefault: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const keybindingsButton = this.htmlElement.querySelector(".editKeybindings");
|
const keybindingsButton = this.htmlElement.querySelector(".editKeybindings");
|
||||||
|
|
||||||
if (keybindingsButton) {
|
if (keybindingsButton) {
|
||||||
this.trackClicks(keybindingsButton, this.onKeybindingsClicked, { preventDefault: false });
|
this.trackClicks(keybindingsButton, this.onKeybindingsClicked, { preventDefault: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
this.initSettings();
|
this.initSettings();
|
||||||
this.initCategoryButtons();
|
this.initCategoryButtons();
|
||||||
|
|
||||||
this.htmlElement.querySelector(".category").classList.add("active");
|
this.htmlElement.querySelector(".category").classList.add("active");
|
||||||
this.htmlElement.querySelector(".categoryButton").classList.add("active");
|
this.htmlElement.querySelector(".categoryButton").classList.add("active");
|
||||||
}
|
}
|
||||||
|
|
||||||
setActiveCategory(category) {
|
setActiveCategory(category) {
|
||||||
const previousCategory = this.htmlElement.querySelector(".category.active");
|
const previousCategory = this.htmlElement.querySelector(".category.active");
|
||||||
const previousCategoryButton = this.htmlElement.querySelector(".categoryButton.active");
|
const previousCategoryButton = this.htmlElement.querySelector(".categoryButton.active");
|
||||||
|
|
||||||
if (previousCategory.getAttribute("data-category") == category) {
|
if (previousCategory.getAttribute("data-category") == category) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
previousCategory.classList.remove("active");
|
previousCategory.classList.remove("active");
|
||||||
previousCategoryButton.classList.remove("active");
|
previousCategoryButton.classList.remove("active");
|
||||||
|
|
||||||
const newCategory = this.htmlElement.querySelector("[data-category='" + category + "']");
|
const newCategory = this.htmlElement.querySelector("[data-category='" + category + "']");
|
||||||
const newCategoryButton = this.htmlElement.querySelector("[data-category-btn='" + category + "']");
|
const newCategoryButton = this.htmlElement.querySelector("[data-category-btn='" + category + "']");
|
||||||
|
|
||||||
newCategory.classList.add("active");
|
newCategory.classList.add("active");
|
||||||
newCategoryButton.classList.add("active");
|
newCategoryButton.classList.add("active");
|
||||||
}
|
}
|
||||||
|
|
||||||
initSettings() {
|
initSettings() {
|
||||||
allApplicationSettings.forEach(setting => {
|
allApplicationSettings.forEach(setting => {
|
||||||
/** @type {HTMLElement} */
|
/** @type {HTMLElement} */
|
||||||
const element = this.htmlElement.querySelector("[data-setting='" + setting.id + "']");
|
const element = this.htmlElement.querySelector("[data-setting='" + setting.id + "']");
|
||||||
setting.bind(this.app, element, this.dialogs);
|
setting.bind(this.app, element, this.dialogs);
|
||||||
setting.syncValueToElement();
|
setting.syncValueToElement();
|
||||||
this.trackClicks(
|
this.trackClicks(
|
||||||
element,
|
element,
|
||||||
() => {
|
() => {
|
||||||
setting.modify();
|
setting.modify();
|
||||||
},
|
},
|
||||||
{ preventDefault: false }
|
{ preventDefault: false }
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
initCategoryButtons() {
|
initCategoryButtons() {
|
||||||
Object.keys(enumCategories).forEach(key => {
|
Object.keys(enumCategories).forEach(key => {
|
||||||
const category = enumCategories[key];
|
const category = enumCategories[key];
|
||||||
const button = this.htmlElement.querySelector("[data-category-btn='" + category + "']");
|
const button = this.htmlElement.querySelector("[data-category-btn='" + category + "']");
|
||||||
this.trackClicks(
|
this.trackClicks(
|
||||||
button,
|
button,
|
||||||
() => {
|
() => {
|
||||||
this.setActiveCategory(category);
|
this.setActiveCategory(category);
|
||||||
},
|
},
|
||||||
{ preventDefault: false }
|
{ preventDefault: false }
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onAboutClicked() {
|
onAboutClicked() {
|
||||||
this.moveToStateAddGoBack("AboutState");
|
this.moveToStateAddGoBack("AboutState");
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeybindingsClicked() {
|
onKeybindingsClicked() {
|
||||||
this.moveToStateAddGoBack("KeybindingsState");
|
this.moveToStateAddGoBack("KeybindingsState");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,6 +33,7 @@ The base language is English and can be found [here](base-en.yaml).
|
|||||||
- [Ukrainian](base-uk.yaml)
|
- [Ukrainian](base-uk.yaml)
|
||||||
- [Indonesian](base-ind.yaml)
|
- [Indonesian](base-ind.yaml)
|
||||||
- [Serbian](base-sr.yaml)
|
- [Serbian](base-sr.yaml)
|
||||||
|
- [Czech](base-cz.yaml)
|
||||||
|
|
||||||
(If you want to translate into a new language, see below!)
|
(If you want to translate into a new language, see below!)
|
||||||
|
|
||||||
|
|||||||
@ -1,20 +1,17 @@
|
|||||||
steamPage:
|
steamPage:
|
||||||
shortText: shapez.io is a game about building factories to automate the creation
|
shortText: لعبة شيبز (أشكال) هي لعبة تدور حول بناء مصانع وتوصيلها حتى تقوم بشكل
|
||||||
and processing of increasingly complex shapes across an infinitely
|
.آلي بصناعة أشكال مختلفة تزداد تعقيدا في خريطة لانهائية.
|
||||||
expanding map.
|
|
||||||
discordLinkShort: Official Discord
|
discordLinkShort: Official Discord
|
||||||
intro: >-
|
intro: >-
|
||||||
Shapez.io is a relaxed game in which you have to build factories for the
|
لعبة شيبز (أشكال) هي لعبة مريحة تقوم فيها ببناء مصانع ووتشغيلها آليا لصناعة أشكال هندسية.
|
||||||
automated production of geometric shapes.
|
|
||||||
|
|
||||||
As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map.
|
مع التقدم في المستوى، تزداد الأشكال تعقيداً، فيتوجب عليك التوسع في الخريطة اللانهائية، وذلك ليس كافياً للتقدم في مستوى اللعبة
|
||||||
|
حيث عليك صناعة المزيد بأضعاف مضاعفة لتلبية الطلب، الشيء الوحيد الذي يمكنه مساعدتك هو التوسع.
|
||||||
|
|
||||||
And as if that wasn't enough, you also have to produce exponentially more to satisfy the demands - the only thing that helps is scaling!
|
بينما في البداية تقوم بصناعة أشكال مختلفة، تتطلب منك المراحل المتقدمة تلوين هذه الأشكال، حيث يتوجب عليك استخراج وخلط الألوان.
|
||||||
|
|
||||||
While you only process shapes at the beginning, you have to color them later - for this you have to extract and mix colors!
|
عند شراءك اللعبة على ستيم (Steam) تحصل على الإصدار الكامل للعبة، ولكن يمكن أيضاً لعبة نسخة تجريبية على موقع shapez.io ثم يمكنك القرار لاحقا
|
||||||
|
title_advantages: ميزات نسخة الحاسوب
|
||||||
Buying the game on Steam gives you access to the full version, but you can also play a demo on shapez.io first and decide later!
|
|
||||||
title_advantages: Standalone Advantages
|
|
||||||
advantages:
|
advantages:
|
||||||
- <b>12 New Level</b> for a total of 26 levels
|
- <b>12 New Level</b> for a total of 26 levels
|
||||||
- <b>18 New Buildings</b> for a fully automated factory!
|
- <b>18 New Buildings</b> for a fully automated factory!
|
||||||
|
|||||||
@ -5,7 +5,7 @@ steamPage:
|
|||||||
discordLinkShort: Official Discord
|
discordLinkShort: Official Discord
|
||||||
intro: >-
|
intro: >-
|
||||||
Shapez.io es un joc relaxant en el qual has de construir fàbriques per a
|
Shapez.io es un joc relaxant en el qual has de construir fàbriques per a
|
||||||
la producció automàtica de formes geomètriques.
|
la producció automàtica de formes geomètriques.
|
||||||
|
|
||||||
A mesura que el nivell augmenta, les formes esdevenen més complexes, i has d'explorar el mapa infinit.
|
A mesura que el nivell augmenta, les formes esdevenen més complexes, i has d'explorar el mapa infinit.
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ mainMenu:
|
|||||||
helpTranslate: Ajuda a traduir-lo!
|
helpTranslate: Ajuda a traduir-lo!
|
||||||
madeBy: Creat per <author-link>
|
madeBy: Creat per <author-link>
|
||||||
browserWarning: >-
|
browserWarning: >-
|
||||||
|
|
||||||
Disculpa, però el joc funcionarà lent al teu navegador! Aconsegueix el joc complet o descarrega't chrome per una millor experiència.
|
Disculpa, però el joc funcionarà lent al teu navegador! Aconsegueix el joc complet o descarrega't chrome per una millor experiència.
|
||||||
savegameLevel: Nivell <x>
|
savegameLevel: Nivell <x>
|
||||||
savegameLevelUnknown: Nivell desconegut
|
savegameLevelUnknown: Nivell desconegut
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
steamPage:
|
steamPage:
|
||||||
shortText: shapez.io je hra o stavbě továren pro automatizaci výroby a
|
shortText: shapez.io je hra o stavbě továren pro automatizaci výroby a
|
||||||
kombinování čím dál složitějších tvarů na nekonečné mapě.
|
kombinování čím dál složitějších tvarů na nekonečné mapě.
|
||||||
discordLinkShort: Official Discord
|
discordLinkShort: Oficiální Discord
|
||||||
intro: >-
|
intro: >-
|
||||||
Shapez.io je relaxační hra, ve které musíte stavět továrny pro
|
Shapez.io je relaxační hra, ve které musíte stavět továrny pro
|
||||||
automatizaci výroby geometrických tvarů.
|
automatizaci výroby geometrických tvarů.
|
||||||
|
|
||||||
Jak se zvyšuje úroveň, tvary se stávají stále složitějšími a vy se musíte rozšířit po nekonečné mapě.
|
Jak se zvyšuje úroveň, tvary se stávají stále složitějšími a vy se musíte rozšířit po nekonečné mapě.
|
||||||
|
|
||||||
@ -13,38 +13,38 @@ steamPage:
|
|||||||
Zatímco tvary zpracováváte pouze na začátku, musíte je později obarvit - k tomu musíte těžit a míchat barvy!
|
Zatímco tvary zpracováváte pouze na začátku, musíte je později obarvit - k tomu musíte těžit a míchat barvy!
|
||||||
|
|
||||||
Koupením hry na platformě Steam vám dá přístup k plné verzi hry, ale také můžete hrát demo verzi na shapez.io a potom se můžete rozhodnou jestli hru koupíte!
|
Koupením hry na platformě Steam vám dá přístup k plné verzi hry, ale také můžete hrát demo verzi na shapez.io a potom se můžete rozhodnou jestli hru koupíte!
|
||||||
title_advantages: Samostatné výhody
|
title_advantages: Výhody samostatné verze hry
|
||||||
advantages:
|
advantages:
|
||||||
- <b>12 Nových úrovní</b> celkem 26 úrovní
|
- <b>12 Nových úrovní</b> celkem 26 úrovní
|
||||||
- <b>18 Nových budov</b> pro plně automatizovanou továrnu!
|
- <b>18 Nových budov</b> pro plně automatizovanou továrnu!
|
||||||
- <b>20 vylepšení</b> pro mnoho hodin zábavy!
|
- <b>20 vylepšení</b> pro mnoho hodin zábavy!
|
||||||
- <b>Wires Update</b> pro zcela nové rozměry!
|
- <b>Wires Update</b> pro zcela nové rozměry!
|
||||||
- <b>Dark Mode</b>!
|
- <b>Dark Mode</b>!
|
||||||
- Neomezené Savegames
|
- Neomezený počet uložených her
|
||||||
- Neomezené značky
|
- Neomezené značky
|
||||||
- Podpořte mě! ❤️
|
- Podpořte mě! ❤️
|
||||||
title_future: Plánovaný kontent
|
title_future: Plánovaný kontent
|
||||||
planned:
|
planned:
|
||||||
- Blueprintová knihovna (Samostatně exkluzivní)
|
- Blueprintová knihovna
|
||||||
- Steam Achievements
|
- Steam Achievements
|
||||||
- Puzzle Mode
|
- Puzzle Mód
|
||||||
- Minnimapa
|
- Minimapa
|
||||||
- Mody
|
- Módy
|
||||||
- Sandbox mode
|
- Sandbox Mód
|
||||||
- ... a o hodně víc!
|
- ... a o hodně víc!
|
||||||
title_open_source: Tato hra je open source!
|
title_open_source: Tato hra je open source!
|
||||||
title_links: Odkazy
|
title_links: Odkazy
|
||||||
links:
|
links:
|
||||||
discord: Officiální Discord
|
discord: Oficiální Discord
|
||||||
roadmap: Roadmap
|
roadmap: Roadmap
|
||||||
subreddit: Subreddit
|
subreddit: Subreddit
|
||||||
source_code: Source code (GitHub)
|
source_code: Source code (GitHub)
|
||||||
translate: Pomozte přeložit hru!
|
translate: Pomozte přeložit hru!
|
||||||
text_open_source: |-
|
text_open_source: |-
|
||||||
Kdokoli může přispět, aktivně se zapojit do komunity,
|
Kdokoli může přispět, jsem aktivně zapojený do komunity,
|
||||||
pokusit se zkontrolovat všechny návrhy a vzít v úvahu zpětnou vazbu
|
pokouším se zkontrolovat všechny návrhy a vzít v úvahu zpětnou vazbu všude,
|
||||||
kde je to možné.
|
kde je to možné.
|
||||||
|
|
||||||
Nezapomeňte se podívat na můj trello board, kde najdete kompletní plán!
|
Nezapomeňte se podívat na můj trello board, kde najdete kompletní plán!
|
||||||
global:
|
global:
|
||||||
loading: Načítám
|
loading: Načítám
|
||||||
@ -105,8 +105,8 @@ dialogs:
|
|||||||
later: Později
|
later: Později
|
||||||
restart: Restart
|
restart: Restart
|
||||||
reset: Reset
|
reset: Reset
|
||||||
getStandalone: Získejte Plnou verzi
|
getStandalone: Získejte plnou verzi
|
||||||
deleteGame: Vím co dělám
|
deleteGame: Vím, co dělám
|
||||||
viewUpdate: Zobrazit aktualizaci
|
viewUpdate: Zobrazit aktualizaci
|
||||||
showUpgrades: Zobrazit vylepšení
|
showUpgrades: Zobrazit vylepšení
|
||||||
showKeybindings: Zobrazit klávesové zkratky
|
showKeybindings: Zobrazit klávesové zkratky
|
||||||
@ -345,7 +345,7 @@ ingame:
|
|||||||
desc: Kliknutím sem zobrazíte výhody Steam verze!
|
desc: Kliknutím sem zobrazíte výhody Steam verze!
|
||||||
get_on_steam: Získejte na steamu
|
get_on_steam: Získejte na steamu
|
||||||
standaloneAdvantages:
|
standaloneAdvantages:
|
||||||
title: Získejte plnou verzy!
|
title: Získejte plnou verzi!
|
||||||
no_thanks: Ne, děkuji!
|
no_thanks: Ne, děkuji!
|
||||||
points:
|
points:
|
||||||
levels:
|
levels:
|
||||||
@ -399,10 +399,10 @@ buildings:
|
|||||||
miner:
|
miner:
|
||||||
default:
|
default:
|
||||||
name: Extraktor
|
name: Extraktor
|
||||||
description: Umístěte na náleziště tvaru nebo barvy pro zahájení těžby.
|
description: Umístěte na naleziště tvaru nebo barvy pro zahájení těžby.
|
||||||
chainable:
|
chainable:
|
||||||
name: Extraktor (Navazující)
|
name: Extraktor (Navazující)
|
||||||
description: Umístěte na náleziště tvaru nebo barvy pro zahájení těžby. Lze
|
description: Umístěte na naleziště tvaru nebo barvy pro zahájení těžby. Lze
|
||||||
zapojit po skupinách.
|
zapojit po skupinách.
|
||||||
underground_belt:
|
underground_belt:
|
||||||
default:
|
default:
|
||||||
@ -470,7 +470,7 @@ buildings:
|
|||||||
balancer:
|
balancer:
|
||||||
default:
|
default:
|
||||||
name: Vyvažovač
|
name: Vyvažovač
|
||||||
description: Multifunkční - Rozděluje vstupy do výstupy.
|
description: Multifunkční - Rovnoměrně rozděluje vstupy na výstupech.
|
||||||
merger:
|
merger:
|
||||||
name: Spojovač (kompaktní)
|
name: Spojovač (kompaktní)
|
||||||
description: Spojí dva pásy do jednoho.
|
description: Spojí dva pásy do jednoho.
|
||||||
@ -535,7 +535,7 @@ buildings:
|
|||||||
reader:
|
reader:
|
||||||
default:
|
default:
|
||||||
name: Čtečka pásů
|
name: Čtečka pásů
|
||||||
description: Umožňuje měřit průměrnou propustnost pásu. Výstup čte poslední
|
description: Umožňuje změřit průměrnou propustnost pásu. Výstup čte poslední
|
||||||
položku ve vrstvě kabelů.
|
položku ve vrstvě kabelů.
|
||||||
analyzer:
|
analyzer:
|
||||||
default:
|
default:
|
||||||
@ -633,7 +633,7 @@ storyRewards:
|
|||||||
barvy!
|
barvy!
|
||||||
reward_storage:
|
reward_storage:
|
||||||
title: Sklad
|
title: Sklad
|
||||||
desc: Právě jste odemkli <strong>sklad</strong> - Umožnuje skladovat přebytečné věci
|
desc: Právě jste odemkli <strong>sklad</strong> - Umožnuje skladovat přebytečné věci
|
||||||
až do naplnění kapacity!<br><br> Dává prioritu levému
|
až do naplnění kapacity!<br><br> Dává prioritu levému
|
||||||
výstupu, takže ho také můžete použít jako <strong>průtokovou bránu</strong>!
|
výstupu, takže ho také můžete použít jako <strong>průtokovou bránu</strong>!
|
||||||
reward_freeplay:
|
reward_freeplay:
|
||||||
@ -732,7 +732,7 @@ settings:
|
|||||||
general: Obecné
|
general: Obecné
|
||||||
userInterface: Uživatelské rozhraní
|
userInterface: Uživatelské rozhraní
|
||||||
advanced: Rozšířené
|
advanced: Rozšířené
|
||||||
performance: Performance
|
performance: Výkon
|
||||||
versionBadges:
|
versionBadges:
|
||||||
dev: Vývojová verze
|
dev: Vývojová verze
|
||||||
staging: Testovací verze
|
staging: Testovací verze
|
||||||
@ -742,7 +742,7 @@ settings:
|
|||||||
uiScale:
|
uiScale:
|
||||||
title: Škálování UI
|
title: Škálování UI
|
||||||
description: Změní velikost uživatelského rozhraní. Rozhraní se bude stále
|
description: Změní velikost uživatelského rozhraní. Rozhraní se bude stále
|
||||||
přizpůsobovoat rozlišení vaší obrazovky, toto nastavení pouze
|
přizpůsobovat rozlišení vaší obrazovky, toto nastavení pouze
|
||||||
mění jeho škálu.
|
mění jeho škálu.
|
||||||
scales:
|
scales:
|
||||||
super_small: Velmi malé
|
super_small: Velmi malé
|
||||||
@ -751,7 +751,7 @@ settings:
|
|||||||
large: Velké
|
large: Velké
|
||||||
huge: Obrovské
|
huge: Obrovské
|
||||||
scrollWheelSensitivity:
|
scrollWheelSensitivity:
|
||||||
title: Citlivost přibížení
|
title: Citlivost přiblížení
|
||||||
description: Změní citlivost přiblížení (kolečkem myši nebo trackpadem).
|
description: Změní citlivost přiblížení (kolečkem myši nebo trackpadem).
|
||||||
sensitivity:
|
sensitivity:
|
||||||
super_slow: Hodně pomalé
|
super_slow: Hodně pomalé
|
||||||
@ -801,8 +801,8 @@ settings:
|
|||||||
slow: Pomalá
|
slow: Pomalá
|
||||||
regular: Normální
|
regular: Normální
|
||||||
fast: Rychlá
|
fast: Rychlá
|
||||||
super_fast: Hodně Rychlá
|
super_fast: Hodně rychlá
|
||||||
extremely_fast: Extrémně Rychlá
|
extremely_fast: Extrémně rychlá
|
||||||
enableTunnelSmartplace:
|
enableTunnelSmartplace:
|
||||||
title: Chytré tunely
|
title: Chytré tunely
|
||||||
description: Pokládání tunelů po zapnutí bude samo odstraňovat nepotřebné pásy.
|
description: Pokládání tunelů po zapnutí bude samo odstraňovat nepotřebné pásy.
|
||||||
@ -829,7 +829,7 @@ settings:
|
|||||||
koeficient. V opačném případě zobrazí popis a obrázek.
|
koeficient. V opačném případě zobrazí popis a obrázek.
|
||||||
disableCutDeleteWarnings:
|
disableCutDeleteWarnings:
|
||||||
title: Zakázat upozornění o vyjmutí nebo odstranění
|
title: Zakázat upozornění o vyjmutí nebo odstranění
|
||||||
description: Deaktivujte varovná dialogová okna vyvolaná při vymutí/mazání více
|
description: Deaktivujte varovná dialogová okna vyvolaná při vyjmutí/mazání více
|
||||||
než 100 entit.
|
než 100 entit.
|
||||||
enableColorBlindHelper:
|
enableColorBlindHelper:
|
||||||
title: Režim pro barvoslepé
|
title: Režim pro barvoslepé
|
||||||
@ -965,7 +965,7 @@ about:
|
|||||||
|
|
||||||
Pokud se chceš na hře podílet, podívej se na <a href="<githublink>" target="_blank">shapez.io na githubu</a>.<br><br>
|
Pokud se chceš na hře podílet, podívej se na <a href="<githublink>" target="_blank">shapez.io na githubu</a>.<br><br>
|
||||||
|
|
||||||
Tato hra by nebyla ani možná bez skvělé Discord komunity okolo Tobiasových her - Vážně by ses měl přijít mrknout na <a href="<discordlink>" target="_blank">Discord server</a>!<br><br>
|
Tato hra by nebyla možná ani bez skvělé Discord komunity okolo Tobiasových her - Vážně by ses měl přijít mrknout na <a href="<discordlink>" target="_blank">Discord server</a>!<br><br>
|
||||||
|
|
||||||
Soundtrack udělal <a href="https://soundcloud.com/pettersumelius" target="_blank">Peppsen</a> - Je úžasnej.<br><br>
|
Soundtrack udělal <a href="https://soundcloud.com/pettersumelius" target="_blank">Peppsen</a> - Je úžasnej.<br><br>
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ steamPage:
|
|||||||
discordLinkShort: Official Discord
|
discordLinkShort: Official Discord
|
||||||
intro: >-
|
intro: >-
|
||||||
Shapez.io er et afslapet spil hvor du skal bygge fabrikker for at
|
Shapez.io er et afslapet spil hvor du skal bygge fabrikker for at
|
||||||
automatisere productionen af geometriske figurer.
|
automatisere productionen af geometriske figurer.
|
||||||
|
|
||||||
Jo længer du når, jo mere kompliseret bliver figurene, og du bliver nød til at spræde dig ud på den grænseløse spilleflade.
|
Jo længer du når, jo mere kompliseret bliver figurene, og du bliver nød til at spræde dig ud på den grænseløse spilleflade.
|
||||||
|
|
||||||
|
|||||||
@ -1,40 +1,39 @@
|
|||||||
|
---
|
||||||
steamPage:
|
steamPage:
|
||||||
shortText: In shapez.io nutzt du die vorhandenen Ressourcen, um mit deinen
|
shortText: In shapez.io nutzt du die vorhandenen Ressourcen, um mit deinen
|
||||||
Maschinen durch Kombination immer komplexere Formen zu erschaffen.
|
Maschinen durch Kombination immer komplexere Formen zu erschaffen.
|
||||||
|
discordLinkShort: Offizieller Discord
|
||||||
intro: >-
|
intro: >-
|
||||||
Du magst Automatisierungsspiele? Dann bist du hier genau richtig!
|
Du magst Automatisierungsspiele? Dann bist du hier genau richtig!
|
||||||
|
shapez.io ist ein ruhiges Spiel, in dem du Fabriken zur automatisierten Produktion von geometrischen Formen bauen musst.
|
||||||
shapez.io ist ein ruhiges Spiel, in dem du Fabriken zur automatisierten Produktion von geometrischen Formen bauen musst. Mit steigendem Level werden die Formen immer komplexer, und du musst dich auf der unendlich großen Karte ausbreiten.
|
Mit steigendem Level werden die Formen immer komplexer, und du musst dich auf der unendlich großen Karte ausbreiten.
|
||||||
|
Das ist noch nicht alles, denn du musst exponentiell mehr produzieren, um die Anforderungen zu erfüllen - Da hilft nur skalieren!
|
||||||
Und als ob das noch nicht genug wäre, musst du auch exponentiell mehr produzieren, um die Anforderungen zu erfüllen - Da hilft nur skalieren! Während du am Anfang nur Formen verarbeitest, musst du diese später einfärben - Dafür musst du Farben extrahieren und mischen!
|
Während du am Anfang nur Formen verarbeitest, musst du diese später auch einfärben - Dafür musst du Farben extrahieren und mischen!
|
||||||
|
Der Kauf des Spiels auf Steam gibt dir Zugriff auf die Vollversion, aber du kannst auch zuerst die Demo auf shapez.io spielen und dich später entscheiden!
|
||||||
Der Kauf des Spiels auf Steam gibt dir Zugriff auf die Vollversion, du kannst aber auch zuerst eine Demo auf shapez.io spielen und dich später entscheiden!
|
|
||||||
title_advantages: Vorteile der Vollversion
|
title_advantages: Vorteile der Vollversion
|
||||||
advantages:
|
advantages:
|
||||||
- <b>12 Neue Level</b> für insgesamt 26 Level
|
- <b>12 Neue Level</b> für insgesamt 26 Level
|
||||||
- <b>18 Neue Gebäude</b> für eine komplett automatisierte Fabrik!
|
- <b>18 Neue Gebäude</b> für eine komplett automatisierte Fabrik!
|
||||||
- <b>20 Upgrade Stufen</b> für viele Stunden Spielspaß
|
- <b>20 Upgrade-Stufen</b> für viele Stunden Spielspaß
|
||||||
- <b>Wires Update</b> für eine komplett neue Dimension!
|
- <b>Wires-Update</b> für eine komplett neue Dimension!
|
||||||
- <b>Dark Mode</b>!
|
- <b>Dark-Mode</b>!
|
||||||
- Unbegrenzte Speicherstände
|
- Unbegrenzte Speicherstände
|
||||||
- Unbegrenzte Wegpunkte
|
- Unbegrenzte Wegpunkte
|
||||||
- Unterstütze mich! ❤️
|
- Unterstütze mich! ❤️
|
||||||
discordLinkShort: Offizieller Discord
|
|
||||||
title_future: Geplante Inhalte
|
title_future: Geplante Inhalte
|
||||||
planned:
|
planned:
|
||||||
- Blaupausen-Bibliothek
|
- Blaupausen-Bibliothek
|
||||||
- Steam Errungenschaften
|
- Errungenschaften auf Steam
|
||||||
- Puzzel-Modus
|
- Puzzel-Modus
|
||||||
- Minimap
|
- Minimap
|
||||||
- Mod Unterstützung
|
- Modunterstützung
|
||||||
- Sandkasten - Modus
|
- Sandkastenmodus
|
||||||
- ... und noch viel mehr!
|
- ... und noch viel mehr!
|
||||||
title_open_source: Dieses Spiel ist Quelloffen!
|
title_open_source: Dieses Spiel ist quelloffen!
|
||||||
text_open_source: >-
|
text_open_source: >-
|
||||||
Jeder kann etwas zum Spiel beitragen! Ich engagiere mich aktiv in der
|
Jeder kann etwas zum Spiel beitragen! Ich engagiere mich aktiv in der
|
||||||
Community und versuche alle Vorschläge zu berücksichtigen.
|
Community und versuche alle Vorschläge zu berücksichtigen.
|
||||||
|
Die vollständige Roadmap findet ihr auf meinem Trello-Board!
|
||||||
Die vollständige Roadmap findet ihr in meinem Trello-Board!
|
|
||||||
title_links: Links
|
title_links: Links
|
||||||
links:
|
links:
|
||||||
discord: Offizieller Discord
|
discord: Offizieller Discord
|
||||||
@ -45,7 +44,7 @@ steamPage:
|
|||||||
global:
|
global:
|
||||||
loading: Laden
|
loading: Laden
|
||||||
error: Fehler
|
error: Fehler
|
||||||
thousandsDivider: .
|
thousandsDivider: "."
|
||||||
decimalSeparator: ","
|
decimalSeparator: ","
|
||||||
suffix:
|
suffix:
|
||||||
thousands: k
|
thousands: k
|
||||||
@ -74,16 +73,16 @@ global:
|
|||||||
shift: UMSCH
|
shift: UMSCH
|
||||||
space: LEER
|
space: LEER
|
||||||
demoBanners:
|
demoBanners:
|
||||||
title: Demo Version
|
title: Demo-Version
|
||||||
intro: Kauf die Vollversion für alle Features!
|
intro: Kauf die Vollversion für alle Features!
|
||||||
mainMenu:
|
mainMenu:
|
||||||
play: Spielen
|
play: Spielen
|
||||||
changelog: Änderungsprotokoll
|
|
||||||
continue: Fortsetzen
|
continue: Fortsetzen
|
||||||
newGame: Neues Spiel
|
newGame: Neues Spiel
|
||||||
|
changelog: Änderungsprotokoll
|
||||||
subreddit: Reddit
|
subreddit: Reddit
|
||||||
importSavegame: Importieren
|
importSavegame: Importieren
|
||||||
openSourceHint: Dieses Spiel ist Open Source!
|
openSourceHint: Dieses Spiel ist quelloffen!
|
||||||
discordLink: Offizieller Discord Server
|
discordLink: Offizieller Discord Server
|
||||||
helpTranslate: Hilf beim Übersetzen!
|
helpTranslate: Hilf beim Übersetzen!
|
||||||
madeBy: Ein Spiel von <author-link>
|
madeBy: Ein Spiel von <author-link>
|
||||||
@ -110,7 +109,7 @@ dialogs:
|
|||||||
title: Importfehler
|
title: Importfehler
|
||||||
text: "Fehler beim Importieren deines Speicherstands:"
|
text: "Fehler beim Importieren deines Speicherstands:"
|
||||||
importSavegameSuccess:
|
importSavegameSuccess:
|
||||||
title: Speicherstand Importieren
|
title: Speicherstand importiert
|
||||||
text: Dein Speicherstand wurde erfolgreich importiert.
|
text: Dein Speicherstand wurde erfolgreich importiert.
|
||||||
gameLoadFailure:
|
gameLoadFailure:
|
||||||
title: Der Speicherstand ist kaputt
|
title: Der Speicherstand ist kaputt
|
||||||
@ -121,13 +120,13 @@ dialogs:
|
|||||||
'<savegameName>' auf Level <savegameLevel><br><br>Das kann nicht rückgängig gemacht werden!
|
'<savegameName>' auf Level <savegameLevel><br><br>Das kann nicht rückgängig gemacht werden!
|
||||||
savegameDeletionError:
|
savegameDeletionError:
|
||||||
title: Löschen fehlgeschlagen
|
title: Löschen fehlgeschlagen
|
||||||
text: "Das Löschen des Spiels ist fehlgeschlagen:"
|
text: "Das Löschen des Speicherstands ist fehlgeschlagen:"
|
||||||
restartRequired:
|
restartRequired:
|
||||||
title: Neustart nötig
|
title: Neustart nötig
|
||||||
text: Du musst das Spiel neu starten, um die Einstellungen anzuwenden.
|
text: Du musst das Spiel neu starten, um die Einstellungen anzuwenden.
|
||||||
editKeybinding:
|
editKeybinding:
|
||||||
title: Tastenbelegung ändern
|
title: Tastenbelegung ändern
|
||||||
desc: Drücke die (Maus-)Taste, die du belegen möchtest, oder ESC um abzubrechen.
|
desc: Drücke die (Maus-)Taste, die du belegen möchtest, oder ESC zum Abbrechen.
|
||||||
resetKeybindingsConfirmation:
|
resetKeybindingsConfirmation:
|
||||||
title: Tastenbelegung zurücksetzen
|
title: Tastenbelegung zurücksetzen
|
||||||
desc: Dies wird alle deine Tastenbelegungen auf den Standard zurücksetzen. Bist
|
desc: Dies wird alle deine Tastenbelegungen auf den Standard zurücksetzen. Bist
|
||||||
@ -138,16 +137,16 @@ dialogs:
|
|||||||
featureRestriction:
|
featureRestriction:
|
||||||
title: Demo-Version
|
title: Demo-Version
|
||||||
desc: Du hast ein Feature benutzt (<feature>), welches nicht in der Demo
|
desc: Du hast ein Feature benutzt (<feature>), welches nicht in der Demo
|
||||||
enthalten ist. Erwerbe die Vollversion auf Steam für das volle Erlebnis!
|
enthalten ist. Erwerbe die Vollversion für das volle Erlebnis!
|
||||||
oneSavegameLimit:
|
oneSavegameLimit:
|
||||||
title: Begrenzte Spielstände
|
title: Begrenzte Speicherstände
|
||||||
desc: Du kannst in der Demo nur einen Spielstand haben. Bitte lösche den
|
desc: Du kannst in der Demo nur einen Speicherstand haben. Bitte lösche den
|
||||||
existierenden Spielstand oder hole dir die Vollversion!
|
existierenden oder hole dir die Vollversion!
|
||||||
updateSummary:
|
updateSummary:
|
||||||
title: Neues Update!
|
title: Neues Update!
|
||||||
desc: "Hier sind die Änderungen, seitdem du das letzte Mal gespielt hast:"
|
desc: "Hier sind die Änderungen, seitdem du das letzte Mal gespielt hast:"
|
||||||
upgradesIntroduction:
|
upgradesIntroduction:
|
||||||
title: Upgrades Freischalten
|
title: Upgrades freischalten
|
||||||
desc: >-
|
desc: >-
|
||||||
Viele deiner Formen können noch benutzt werden, um Upgrades freizuschalten
|
Viele deiner Formen können noch benutzt werden, um Upgrades freizuschalten
|
||||||
- <strong>Zerstöre deine alten Fabriken nicht!</strong> Den
|
- <strong>Zerstöre deine alten Fabriken nicht!</strong> Den
|
||||||
@ -179,26 +178,26 @@ dialogs:
|
|||||||
<code class='keybinding'>ALT</code>: Invertiere die Platzierungsrichtung der Förderbänder.<br>
|
<code class='keybinding'>ALT</code>: Invertiere die Platzierungsrichtung der Förderbänder.<br>
|
||||||
createMarker:
|
createMarker:
|
||||||
title: Neuer Marker
|
title: Neuer Marker
|
||||||
desc: Vergib einen vernünftigen namen, du kannst auch den <strong>Kurz-Code</strong> einer Form eingeben (Welchen du <link>hier</link>) generieren kannst.
|
|
||||||
titleEdit: Marker bearbeiten
|
titleEdit: Marker bearbeiten
|
||||||
|
desc: Gib ihm einen griffigen Namen. Du kannst auch den <strong>Kurz-Code</strong> einer Form eingeben (Welchen du <link>hier</link> generieren kannst).
|
||||||
|
editSignal:
|
||||||
|
title: Signal setzen
|
||||||
|
descItems: "Wähle ein vordefiniertes Item:"
|
||||||
|
descShortKey: ... oder gib den <strong>Kurz-Code</strong> einer Form an (Welchen du <link>hier</link> generieren kannst).
|
||||||
markerDemoLimit:
|
markerDemoLimit:
|
||||||
desc: Du kannst nur 2 Marker in der Demo benutzen. Hol dir die Vollversion, um
|
desc: Du kannst nur 2 Marker in der Demo benutzen. Hole dir die Vollversion, um
|
||||||
unendlich viele Marker zu erstellen!
|
unendlich viele Marker zu erstellen!
|
||||||
exportScreenshotWarning:
|
exportScreenshotWarning:
|
||||||
title: Bildschirmfoto exportieren
|
title: Bildschirmfoto exportieren
|
||||||
desc: Hier kannst du ein Bildschirmfoto von deiner ganzen Fabrik erstellen. Für
|
desc: Hier kannst du ein Bildschirmfoto von deiner ganzen Fabrik erstellen. Für
|
||||||
extrem große Fabriken kann das jedoch sehr lange dauern und ggf. zum
|
extrem große Fabriken kann das jedoch sehr lange dauern und ggf. zum
|
||||||
Spielabsturz führen!
|
Spielabsturz führen!
|
||||||
editSignal:
|
|
||||||
title: Signal Setzen
|
|
||||||
descItems: "Wähle ein vordefiniertes item:"
|
|
||||||
descShortKey: ... oder gib den <strong>Kurz-Code</strong> einer Form an (Welchen du <link>hier</link> generieren kannst)
|
|
||||||
renameSavegame:
|
renameSavegame:
|
||||||
title: Speicherstand umbenennen
|
title: Speicherstand umbenennen
|
||||||
desc: Hier kannst du deinen Speicherstand umbenennen.
|
desc: Hier kannst du deinen Speicherstand umbenennen.
|
||||||
entityWarning:
|
entityWarning:
|
||||||
title: Leistungswarnung
|
title: Leistungswarnung
|
||||||
desc: Du hast eine Menge Gebäude platziert, das hier ist nur ein freundlicher Hinweis dass das Spiel nicht mit unendlich vielen Gebäuden umgehen kann!
|
desc: Du hast eine Menge Gebäude platziert. Das hier ist nur ein freundlicher Hinweis, dass das Spiel nicht mit unendlich vielen Gebäuden umgehen kann. Halte deine Fabriken kompakt!
|
||||||
ingame:
|
ingame:
|
||||||
keybindingsOverlay:
|
keybindingsOverlay:
|
||||||
moveMap: Bewegen
|
moveMap: Bewegen
|
||||||
@ -229,9 +228,9 @@ ingame:
|
|||||||
cyan: Cyan
|
cyan: Cyan
|
||||||
white: Weiß
|
white: Weiß
|
||||||
black: Schwarz
|
black: Schwarz
|
||||||
uncolored: Farblos
|
uncolored: Grau
|
||||||
buildingPlacement:
|
buildingPlacement:
|
||||||
cycleBuildingVariants: Presse <key> zum Wechseln
|
cycleBuildingVariants: Drücke <key> zum Wechseln
|
||||||
hotkeyLabel: "Taste: <key>"
|
hotkeyLabel: "Taste: <key>"
|
||||||
infoTexts:
|
infoTexts:
|
||||||
speed: Geschw.
|
speed: Geschw.
|
||||||
@ -284,11 +283,10 @@ ingame:
|
|||||||
description: Alle im Hub gelagerten Formen.
|
description: Alle im Hub gelagerten Formen.
|
||||||
produced:
|
produced:
|
||||||
title: Produziert
|
title: Produziert
|
||||||
description: Alle Formen, die in deiner Fabrik hergestellt werden, einschließlich Zwischenprodukte.
|
description: Alle in deiner Fabrik hergestellten Formen inkl. Zwischenprodukte.
|
||||||
delivered:
|
delivered:
|
||||||
title: Geliefert
|
title: Geliefert
|
||||||
description: Formen, die an den Hub geliefert werden.
|
description: An den Hub gelieferte Formen.
|
||||||
|
|
||||||
noShapesProduced: Es werden noch keine Formen produziert oder geliefert.
|
noShapesProduced: Es werden noch keine Formen produziert oder geliefert.
|
||||||
shapesDisplayUnits:
|
shapesDisplayUnits:
|
||||||
second: <shapes> / s
|
second: <shapes> / s
|
||||||
@ -298,7 +296,6 @@ ingame:
|
|||||||
playtime: Spielzeit
|
playtime: Spielzeit
|
||||||
buildingsPlaced: Gebäude
|
buildingsPlaced: Gebäude
|
||||||
beltsPlaced: Förderbänder
|
beltsPlaced: Förderbänder
|
||||||
|
|
||||||
tutorialHints:
|
tutorialHints:
|
||||||
title: Brauchst du Hilfe?
|
title: Brauchst du Hilfe?
|
||||||
showHint: Hinweis
|
showHint: Hinweis
|
||||||
@ -306,7 +303,7 @@ ingame:
|
|||||||
blueprintPlacer:
|
blueprintPlacer:
|
||||||
cost: Kosten
|
cost: Kosten
|
||||||
waypoints:
|
waypoints:
|
||||||
waypoints: Markierungen
|
waypoints: Marker
|
||||||
hub: Hub
|
hub: Hub
|
||||||
description: Linksklick auf einen Marker, um dort hinzugelangen. Rechtsklick, um
|
description: Linksklick auf einen Marker, um dort hinzugelangen. Rechtsklick, um
|
||||||
ihn zu löschen.<br><br>Drücke <keybinding>, um einen Marker aus
|
ihn zu löschen.<br><br>Drücke <keybinding>, um einen Marker aus
|
||||||
@ -318,29 +315,29 @@ ingame:
|
|||||||
empty: Leer
|
empty: Leer
|
||||||
copyKey: Schlüssel kopieren
|
copyKey: Schlüssel kopieren
|
||||||
interactiveTutorial:
|
interactiveTutorial:
|
||||||
title: Tutorial
|
title: Einführung
|
||||||
hints:
|
hints:
|
||||||
1_1_extractor: Platziere einen <strong>Extrahierer</strong> auf der
|
1_1_extractor: Platziere einen <strong>Extrahierer</strong> auf der
|
||||||
<strong>Kreisform</strong>, um sie zu extrahieren!
|
<strong>Kreisform</strong>, um sie zu extrahieren!
|
||||||
1_2_conveyor: "Verbinde den Extrahierer mit einem <strong>Förderband</strong>
|
1_2_conveyor: "Verbinde den Extrahierer mit einem <strong>Fließband</strong>
|
||||||
und schließe ihn am Hub an!<br><br>Tipp: <strong>Drücke und
|
und schließe ihn am Hub an!<br><br>Tipp: <strong>Drücke und
|
||||||
ziehe</strong> das Förderband mit der Maus!"
|
ziehe</strong> das Fließband mit der Maus!"
|
||||||
1_3_expand: "Dies ist <strong>KEIN</strong> Idle-Game! Baue mehr Extrahierer und
|
1_3_expand: "Dies ist <strong>KEIN</strong> Idle-Game! Baue mehr Extrahierer und
|
||||||
Förderbänder, um das Ziel schneller zu erreichen.<br><br>Tipp:
|
Förderbänder, um das Ziel schneller zu erreichen.<br><br>Tipp:
|
||||||
Halte <strong>UMSCH</strong>, um mehrere Gebäude zu platzieren
|
Halte <strong>UMSCH</strong>, um mehrere Gebäude zu platzieren
|
||||||
und nutze <strong>R</strong>, um sie zu rotieren."
|
und nutze <strong>R</strong>, um sie zu rotieren."
|
||||||
connectedMiners:
|
connectedMiners:
|
||||||
one_miner: 1 Extrahierer
|
one_miner: Ein Extrahierer
|
||||||
n_miners: <amount> Extrahierer
|
n_miners: <amount> Extrahierer
|
||||||
limited_items: Begrenzt auf <max_throughput>
|
limited_items: Begrenzt auf <max_throughput>
|
||||||
watermark:
|
watermark:
|
||||||
title: Demo Version
|
title: Demo-Version
|
||||||
desc: Klicke hier, um die Vorteile der Vollversion zu sehen!
|
desc: Klicke hier, um die Vorteile der Vollversion zu sehen!
|
||||||
get_on_steam: Zur Vollversion
|
get_on_steam: Zur Vollversion
|
||||||
|
|
||||||
standaloneAdvantages:
|
standaloneAdvantages:
|
||||||
title: Vorteile der Vollversion
|
title: Vorteile der Vollversion
|
||||||
no_thanks: Nein, Dank!
|
no_thanks: Nein, danke!
|
||||||
points:
|
points:
|
||||||
levels:
|
levels:
|
||||||
title: 12 Neue Level
|
title: 12 Neue Level
|
||||||
@ -352,20 +349,20 @@ ingame:
|
|||||||
title: ∞ Speicherstände
|
title: ∞ Speicherstände
|
||||||
desc: So viele dein Herz begehrt!
|
desc: So viele dein Herz begehrt!
|
||||||
upgrades:
|
upgrades:
|
||||||
title: 20 Upgrade Stufen
|
title: 20 Upgrade-Stufen
|
||||||
desc: Diese Demo hat nur 5!
|
desc: Diese Demo hat nur 5!
|
||||||
markers:
|
markers:
|
||||||
title: ∞ Marker
|
title: ∞ Marker
|
||||||
desc: Verliere dich nie in deiner Fabrik!
|
desc: Verliere nie den Überblick!
|
||||||
wires:
|
wires:
|
||||||
title: Wires
|
title: Wires
|
||||||
desc: Eine ganz neue Dimension!
|
desc: Eine ganz neue Dimension!
|
||||||
darkmode:
|
darkmode:
|
||||||
title: Dark Mode
|
title: Dark-Mode
|
||||||
desc: Werde nicht mehr geblendet!
|
desc: Werde nicht mehr geblendet!
|
||||||
support:
|
support:
|
||||||
title: Unterstütze Mich
|
title: Unterstütze Mich
|
||||||
desc: Ich verwende meine Freizeit!
|
desc: Ich entwickle in meiner Freizeit!
|
||||||
shopUpgrades:
|
shopUpgrades:
|
||||||
belt:
|
belt:
|
||||||
name: Förderbänder, Verteiler & Tunnel
|
name: Förderbänder, Verteiler & Tunnel
|
||||||
@ -382,12 +379,12 @@ shopUpgrades:
|
|||||||
buildings:
|
buildings:
|
||||||
hub:
|
hub:
|
||||||
deliver: Liefere
|
deliver: Liefere
|
||||||
toUnlock: "Für die Belohnung:"
|
toUnlock: "und schalte frei:"
|
||||||
levelShortcut: LVL
|
levelShortcut: LVL
|
||||||
endOfDemo: Ende der Demo
|
endOfDemo: Ende der Demo
|
||||||
belt:
|
belt:
|
||||||
default:
|
default:
|
||||||
name: Förderband
|
name: Fließband
|
||||||
description: Transportiert Items. Halte und ziehe, um mehrere zu platzieren.
|
description: Transportiert Items. Halte und ziehe, um mehrere zu platzieren.
|
||||||
miner:
|
miner:
|
||||||
default:
|
default:
|
||||||
@ -406,13 +403,29 @@ buildings:
|
|||||||
name: Tunnel Stufe II
|
name: Tunnel Stufe II
|
||||||
description: Erlaubt dir, Formen und Farbe unter Gebäuden und Förderbändern
|
description: Erlaubt dir, Formen und Farbe unter Gebäuden und Förderbändern
|
||||||
durchzuleiten. Höhere Reichweite.
|
durchzuleiten. Höhere Reichweite.
|
||||||
|
balancer:
|
||||||
|
default:
|
||||||
|
name: Verteiler
|
||||||
|
description: Multifunktional - Verteilt alle Eingänge gleichmäßig auf die Ausgänge.
|
||||||
|
merger:
|
||||||
|
name: Kombinierer (kompakt)
|
||||||
|
description: Kombiniert zwei Fließbänder zu einem.
|
||||||
|
merger-inverse:
|
||||||
|
name: Kombinierer (kompakt)
|
||||||
|
description: Kombiniert zwei Fließbänder zu einem.
|
||||||
|
splitter:
|
||||||
|
name: Aufteiler (kompakt)
|
||||||
|
description: Teilt ein Fließband in zwei.
|
||||||
|
splitter-inverse:
|
||||||
|
name: Aufteiler (kompakt)
|
||||||
|
description: Teilt ein Fließband in zwei.
|
||||||
cutter:
|
cutter:
|
||||||
default:
|
default:
|
||||||
name: Schneider
|
name: Schneider
|
||||||
description: Zerschneidet Formen von oben nach unten. <strong>Benutze oder
|
description: Zerschneidet Formen von oben nach unten. <strong>Benutze oder
|
||||||
zerstöre beide Hälften, sonst verstopft die Maschine!</strong>
|
zerstöre beide Hälften, sonst verstopft die Maschine!</strong>
|
||||||
quad:
|
quad:
|
||||||
name: Schneider (Vierfach)
|
name: Schneider (vierfach)
|
||||||
description: Zerschneidet Formen in vier Teile. <strong>Benutze oder zerstöre
|
description: Zerschneidet Formen in vier Teile. <strong>Benutze oder zerstöre
|
||||||
alle Viertel, sonst verstopft die Maschine!</strong>
|
alle Viertel, sonst verstopft die Maschine!</strong>
|
||||||
rotater:
|
rotater:
|
||||||
@ -444,11 +457,11 @@ buildings:
|
|||||||
description: Färbt die ganze Form aus dem linken Eingang mit der Farbe aus dem
|
description: Färbt die ganze Form aus dem linken Eingang mit der Farbe aus dem
|
||||||
oberen Eingang.
|
oberen Eingang.
|
||||||
double:
|
double:
|
||||||
name: Färber (2-fach)
|
name: Färber (zweifach)
|
||||||
description: Färbt beide Formen aus dem linken Eingang mit der Farbe aus dem
|
description: Färbt beide Formen aus dem linken Eingang mit der Farbe aus dem
|
||||||
oberen Eingang.
|
oberen Eingang.
|
||||||
quad:
|
quad:
|
||||||
name: Färber (4-fach)
|
name: Färber (vierfach)
|
||||||
description: Erlaubt dir, jeden Quadranten der Form individuell zu färben. Nur
|
description: Erlaubt dir, jeden Quadranten der Form individuell zu färben. Nur
|
||||||
Quadranten mit einem <strong>wahren Signal</strong> auf der Wires-Ebene
|
Quadranten mit einem <strong>wahren Signal</strong> auf der Wires-Ebene
|
||||||
werden angemalt!
|
werden angemalt!
|
||||||
@ -457,49 +470,33 @@ buildings:
|
|||||||
name: Mülleimer
|
name: Mülleimer
|
||||||
description: Akzeptiert Formen und Farben aus jeder Richtung und zerstört sie.
|
description: Akzeptiert Formen und Farben aus jeder Richtung und zerstört sie.
|
||||||
Für immer ...
|
Für immer ...
|
||||||
wire:
|
|
||||||
default:
|
|
||||||
name: Signalkabel
|
|
||||||
description: Erlaubt dir Signale zu transportieren.
|
|
||||||
second:
|
|
||||||
name: Signalkabel
|
|
||||||
description: Überträgt Signale, die Gegenstände, Farben oder Wahrheitswerte (1 oder 0) sein können. Unterschiedlich farbige Kabel verbinden sich nicht miteinander.
|
|
||||||
balancer:
|
|
||||||
default:
|
|
||||||
name: Verteiler
|
|
||||||
description: Multifunktional - Verteilt alle Eingänge gleichmäßig auf alle Ausgänge.
|
|
||||||
merger:
|
|
||||||
name: Kombinierer (kompakt)
|
|
||||||
description: Kombiniert zwei Fließbänder in eins.
|
|
||||||
merger-inverse:
|
|
||||||
name: Kombinierer (kompakt)
|
|
||||||
description: Kombiniert zwei Fließbänder in eins.
|
|
||||||
splitter:
|
|
||||||
name: Verteiler (kompakt)
|
|
||||||
description: Teilt ein Fließband in zwei.
|
|
||||||
splitter-inverse:
|
|
||||||
name: Verteiler (kompakt)
|
|
||||||
description: Teilt ein Fließband in zwei.
|
|
||||||
storage:
|
storage:
|
||||||
default:
|
default:
|
||||||
name: Speicher
|
name: Speicher
|
||||||
description:
|
description:
|
||||||
Speichert überschüssige Gegenstände, bis zu einer bestimmten Kapazität. Priorisiert den linken
|
Speichert überschüssige Gegenstände, bis zu einer bestimmten Kapazität. Priorisiert den linken
|
||||||
Ausgang und kann als Überlauftor verwendet werden.
|
Ausgang und kann als Überlauftor verwendet werden.
|
||||||
|
wire:
|
||||||
|
default:
|
||||||
|
name: Signalkabel
|
||||||
|
description: Erlaubt den Transport von Signalen. Das sind Items, Farben oder Wahrheitswerte (1 oder 0). Unterschiedlich gefärbte Kabel verbinden sich nicht.
|
||||||
|
second:
|
||||||
|
name: Signalkabel
|
||||||
|
description: Erlaubt den Transport von Signalen. Das sind Items, Farben oder Wahrheitswerte (1 oder 0). Unterschiedlich gefärbte Kabel verbinden sich nicht.
|
||||||
wire_tunnel:
|
wire_tunnel:
|
||||||
default:
|
default:
|
||||||
name: Signal-Kreuzung
|
name: Kabelkreuzung
|
||||||
description: Erlaubt es, zwei Kabel zu kreuzen, ohne sie zu verbinden.
|
description: Erschafft eine isolierte Kreuzung zweier Kabel.
|
||||||
constant_signal:
|
constant_signal:
|
||||||
default:
|
default:
|
||||||
name: Konstantes Signal
|
name: Signalgeber
|
||||||
description: Sendet ein konstantes Signal, das entweder eine Form, eine Farbe oder
|
description: Sendet ein konstantes Signal. Du wählst zwischen Formen, Farben oder
|
||||||
Wahrheitswert (1 / 0) sein kann.
|
Wahrheitswerten (1 oder 0).
|
||||||
lever:
|
lever:
|
||||||
default:
|
default:
|
||||||
name: Schalter
|
name: Schalter
|
||||||
description:
|
description:
|
||||||
Kann umgeschaltet werden, um einen Wahrheitswert (1 / 0) auf der Wires-Ebene auszusenden,
|
Sendet einen Wahrheitswert (1 oder 0) auf der Wires-Ebene abhängig von seiner Stellung,
|
||||||
welcher dann z.B. zur Steuerung eines Filters verwendet werden kann.
|
welcher dann z.B. zur Steuerung eines Filters verwendet werden kann.
|
||||||
logic_gate:
|
logic_gate:
|
||||||
default:
|
default:
|
||||||
@ -516,7 +513,7 @@ buildings:
|
|||||||
(wahr bedeutet Form, Farbe oder "1").
|
(wahr bedeutet Form, Farbe oder "1").
|
||||||
or:
|
or:
|
||||||
name: ODER Gatter
|
name: ODER Gatter
|
||||||
description: Gibt eine "1" aus, wenn eine der Eingäge wahr ist (wahr bedeutet Form, Farbe oder "1").
|
description: Gibt eine "1" aus, wenn einer der Eingänge wahr ist (wahr bedeutet Form, Farbe oder "1").
|
||||||
transistor:
|
transistor:
|
||||||
default:
|
default:
|
||||||
name: Transistor
|
name: Transistor
|
||||||
@ -533,12 +530,12 @@ buildings:
|
|||||||
restlichen nach rechts. Kann auch mit Wahrheitswerten gesteuert werden.
|
restlichen nach rechts. Kann auch mit Wahrheitswerten gesteuert werden.
|
||||||
display:
|
display:
|
||||||
default:
|
default:
|
||||||
name: Display
|
name: Anzeige
|
||||||
description: Verbinde ein Signal, um es auf dem Display anzuzeigen - Es kann eine Form sein,
|
description: Verbinde ein Signal, um es auf der Anzeige darzustellen. Es kann eine Form,
|
||||||
Farbe oder Wahrheitswert.
|
Farbe oder ein Wahrheitswert sein.
|
||||||
reader:
|
reader:
|
||||||
default:
|
default:
|
||||||
name: Fließband Leser
|
name: Fließbandkontrolle
|
||||||
description:
|
description:
|
||||||
Ermöglicht es, den durchschnittlichen Durchsatz des Fließbandes zu messen. Gibt den letzten
|
Ermöglicht es, den durchschnittlichen Durchsatz des Fließbandes zu messen. Gibt den letzten
|
||||||
Gegenstand auf der Wires-Ebene aus (sobald freigeschaltet).
|
Gegenstand auf der Wires-Ebene aus (sobald freigeschaltet).
|
||||||
@ -550,7 +547,7 @@ buildings:
|
|||||||
comparator:
|
comparator:
|
||||||
default:
|
default:
|
||||||
name: Vergleich
|
name: Vergleich
|
||||||
description: Gibt eine "1" zurück, wenn beide Signale genau gleich sind. Kann Formen, Gegenstände und Wahrheitswerte vergleichen.
|
description: Gibt eine "1" zurück, wenn beide Signale genau gleich sind. Kann Formen, Farben und Wahrheitswerte vergleichen.
|
||||||
virtual_processor:
|
virtual_processor:
|
||||||
default:
|
default:
|
||||||
name: Virtueller Schneider
|
name: Virtueller Schneider
|
||||||
@ -559,7 +556,7 @@ buildings:
|
|||||||
name: Virtueller Rotierer
|
name: Virtueller Rotierer
|
||||||
description: Dreht die Form virtuell, sowohl im als auch gegen den Uhrzeigersinn.
|
description: Dreht die Form virtuell, sowohl im als auch gegen den Uhrzeigersinn.
|
||||||
unstacker:
|
unstacker:
|
||||||
name: Virtueller Unstapler
|
name: Virtueller Entstapler
|
||||||
description: Extrahiert virtuell die oberste Ebene nach rechts und die
|
description: Extrahiert virtuell die oberste Ebene nach rechts und die
|
||||||
die restlichen Ebenen nach links.
|
die restlichen Ebenen nach links.
|
||||||
stacker:
|
stacker:
|
||||||
@ -568,11 +565,10 @@ buildings:
|
|||||||
painter:
|
painter:
|
||||||
name: Virtueller Färber
|
name: Virtueller Färber
|
||||||
description: Färbt virtuell die Form vom unteren Eingang mit der Farbe aus dem rechten Eingang.
|
description: Färbt virtuell die Form vom unteren Eingang mit der Farbe aus dem rechten Eingang.
|
||||||
|
|
||||||
item_producer:
|
item_producer:
|
||||||
default:
|
default:
|
||||||
name: Item-Produzent
|
name: Item-Produzent
|
||||||
description: Nur im Sandbox-Modus verfügbar, gibt das Signal aus der Wires-Ebene auf der regulären Schicht aus.
|
description: Nur im Sandkastenmodus verfügbar. Gibt das Signal aus der Wires-Ebene auf der regulären Ebene aus.
|
||||||
storyRewards:
|
storyRewards:
|
||||||
reward_cutter_and_trash:
|
reward_cutter_and_trash:
|
||||||
title: Formen zerschneiden
|
title: Formen zerschneiden
|
||||||
@ -602,10 +598,10 @@ storyRewards:
|
|||||||
sie nebeneinander, werden sie <strong>verschmolzen</strong>.
|
sie nebeneinander, werden sie <strong>verschmolzen</strong>.
|
||||||
Anderenfalls wird die rechte auf die linke Form
|
Anderenfalls wird die rechte auf die linke Form
|
||||||
<strong>gestapelt</strong>.
|
<strong>gestapelt</strong>.
|
||||||
reward_splitter:
|
reward_balancer:
|
||||||
title: Verteiler/Kombinierer
|
title: Verteiler
|
||||||
desc: Du hast eine <strong>Splitter</strong> Variante des
|
desc: Der multifunktionale <strong>Verteiler</strong> wurde freigeschaltet! Er kann
|
||||||
<strong>Verteilers</strong> freigeschaltet - Er teilt ein Fließband auf zwei auf!
|
benutzt werden, um größere Fabriken zu bauen, indem Items auf Fließbänder aufgeteilt oder zusammengelegt werden!
|
||||||
reward_tunnel:
|
reward_tunnel:
|
||||||
title: Tunnel
|
title: Tunnel
|
||||||
desc: Der <strong>Tunnel</strong> wurde freigeschaltet! Du kannst Items nun
|
desc: Der <strong>Tunnel</strong> wurde freigeschaltet! Du kannst Items nun
|
||||||
@ -627,68 +623,59 @@ storyRewards:
|
|||||||
desc: Du hast eine neue Variante des <strong>Tunnels</strong> freigeschaltet!
|
desc: Du hast eine neue Variante des <strong>Tunnels</strong> freigeschaltet!
|
||||||
Dieser hat eine <strong>höhere Reichweite</strong> und du kannst
|
Dieser hat eine <strong>höhere Reichweite</strong> und du kannst
|
||||||
beide Tunnel miteinander mischen.
|
beide Tunnel miteinander mischen.
|
||||||
|
reward_merger:
|
||||||
|
title: Kompakter Kombinierer
|
||||||
|
desc: Du hast eine <strong>kompakte Variante</strong> des <strong>Verteilers</strong>
|
||||||
|
freigeschaltet! Der Kombinierer vereint zwei Eingäge zu einem Ausgang.
|
||||||
|
reward_splitter:
|
||||||
|
title: Kompakter Aufteiler
|
||||||
|
desc: Du hast eine <strong>kompakte Variante</strong> des <strong>Verteilers</strong>
|
||||||
|
freigeschaltet! Der Aufteiler spaltet einen Eingang in zwei Aufgänge auf.
|
||||||
|
reward_belt_reader:
|
||||||
|
title: Fließbandkontrolle
|
||||||
|
desc: Du hast nun die <strong>Fließbandkontrolle</strong> freigeschaltet! Damit kannst du dir
|
||||||
|
den Durchsatz eines Fließbandes anzeigen lassen.<br><br>Wenn du Stromkabel freischaltest,
|
||||||
|
wird er um eine sehr nützliche Funktion ergänzt!
|
||||||
reward_cutter_quad:
|
reward_cutter_quad:
|
||||||
title: Schneider (4-fach)
|
title: Schneider (4-fach)
|
||||||
desc: Du hast eine neue Variante des <strong>Schneiders</strong> freigeschaltet!
|
desc: Du hast eine neue Variante des <strong>Schneiders</strong> freigeschaltet!
|
||||||
Damit kannst du Formen in alle <strong>vier Teile</strong>
|
Damit kannst du Formen in alle <strong>vier Teile</strong> zerschneiden.
|
||||||
zerschneiden.
|
|
||||||
reward_painter_double:
|
reward_painter_double:
|
||||||
title: Färber (2-fach)
|
title: Färber (2-fach)
|
||||||
desc: Du hast eine neue Variante des <strong>Färbers</strong> freigeschaltet!
|
desc: Du hast eine neue Variante des <strong>Färbers</strong> freigeschaltet!
|
||||||
Hiermit kannst du <strong>zwei Formen auf einmal</strong> färben und
|
Hiermit kannst du <strong>zwei Formen auf einmal</strong> färben und
|
||||||
verbrauchst nur eine Farbe.
|
verbrauchst nur eine Farbe.
|
||||||
reward_storage:
|
reward_storage:
|
||||||
title: Speicher
|
title: Lager
|
||||||
desc: Du hast das <strong>Speicher</strong> Gebäude freigeschaltet - Es erlaubt dir
|
desc: Du hast das <strong>Lager</strong> freigeschaltet! Es erlaubt dir,
|
||||||
Gegenstände bis zu einer bestimmten Kapazität zu speichern!<br><br>
|
Gegenstände bis zu einer bestimmten Kapazität zu speichern!<br><br>
|
||||||
Es priorisiert den linken Ausgang, also kannst du es auch als <strong>Überlauftor</strong> benutzen!
|
Es priorisiert den linken Ausgang, also kannst du es auch als <strong>Überlauftor</strong> benutzen!
|
||||||
reward_freeplay:
|
|
||||||
title: Freies Spiel
|
|
||||||
desc: >-
|
|
||||||
Du hast es geschafft! Du hast den <strong>Freispiel-Modus</strong> freigeschaltet! Das bedeutet,
|
|
||||||
dass die Formen jetzt <strong>zufällig</strong> erzeugt werden!<br><br>
|
|
||||||
|
|
||||||
Da der Hub ab jetzt einen <strong>Durchsatz</strong> benötigt, empfehle ich dringend eine Maschine zu bauen,
|
|
||||||
die automatisch die gewünschte Form liefert!<br><br>
|
|
||||||
|
|
||||||
Der HUB gibt die gewünschte Form auf der Wires-Ebene aus, also ist alles was du tun musst, sie zu analysieren und
|
|
||||||
automatisch deine Fabrik basierend darauf zu konfigurieren.
|
|
||||||
|
|
||||||
reward_blueprints:
|
reward_blueprints:
|
||||||
title: Blaupause
|
title: Blaupausen
|
||||||
desc: Jetzt kannst du Teile deiner Fabrik <strong>kopieren und
|
desc: Jetzt kannst du Teile deiner Fabrik <strong>kopieren und
|
||||||
einfügen</strong>! Wähle ein Areal aus (Halte STRG und ziehe mit
|
einfügen</strong>! Wähle ein Areal aus (Halte STRG und ziehe mit
|
||||||
deiner Maus) und drücke 'C', um zu kopieren.<br><br>Einfügen ist
|
deiner Maus) und drücke 'C', um zu kopieren.<br><br>Einfügen ist
|
||||||
<strong>nicht kostenlos</strong>, du musst
|
<strong>nicht kostenlos</strong>! Du musst
|
||||||
<strong>Blaupausenformen</strong> produzieren, um die Kopierkosten
|
<strong>Blaupausenformen</strong> produzieren, um die Kopierkosten
|
||||||
zu decken (Welche du gerade produziert hast)!
|
zu decken (Welche du gerade produziert hast)!
|
||||||
no_reward:
|
|
||||||
title: Nächstes Level
|
|
||||||
desc: "Dieses Level hat dir keine Belohnung gegeben, aber im Nächsten gibt es
|
|
||||||
eine! <br><br> PS: Denke daran, deine alten Fabriken nicht zu
|
|
||||||
zerstören - Du wirst sie später <strong>alle</strong> noch brauchen,
|
|
||||||
um <strong>Upgrades freizuschalten</strong>!"
|
|
||||||
no_reward_freeplay:
|
|
||||||
title: Nächstes Level
|
|
||||||
desc: Du hast das nächste Level freigeschalten!
|
|
||||||
|
|
||||||
reward_balancer:
|
|
||||||
title: Verteiler
|
|
||||||
desc: Der multifunktionale <strong>Verteiler</strong> wurde freigeschaltet - Er kann
|
|
||||||
benutzt werden, um größere Fabriken zu bauen, indem Gegenstände auf mehrere Fließbänder aufgeteilt und zusammengelegt werden!
|
|
||||||
reward_merger:
|
|
||||||
title: Kompakter Verteiler
|
|
||||||
desc: >-
|
|
||||||
Du hast eine <strong>kompakte Variante</strong> des <strong>Verteilers</strong> freigeschalten - Sie verteilt zwei Fließbänder auf eins!
|
|
||||||
reward_belt_reader:
|
|
||||||
title: Fließband Leser
|
|
||||||
desc: You have now unlocked the <strong>belt reader</strong>! It allows you to
|
|
||||||
measure the throughput of a belt.<br><br>And wait until you unlock
|
|
||||||
wires - then it gets really useful!
|
|
||||||
reward_rotater_180:
|
reward_rotater_180:
|
||||||
title: Rotater (180 degrees)
|
title: Rotierer (180°)
|
||||||
desc: You just unlocked the 180 degrees <strong>rotater</strong>! - It allows
|
desc: Du hast eine weitere Variante des <strong>Rotierers</strong> freigeschaltet! Mit ihm
|
||||||
you to rotate a shape by 180 degrees (Surprise! :D)
|
kannst du Formen um 180° drehen (Überraschung! :D).
|
||||||
|
reward_wires_painter_and_levers:
|
||||||
|
title: Wires & Quad Painter
|
||||||
|
desc: "You just unlocked the <strong>Wires Layer</strong>: It is a separate
|
||||||
|
layer on top of the regular layer and introduces a lot of new
|
||||||
|
mechanics!<br><br> For the beginning I unlocked you the <strong>Quad
|
||||||
|
Painter</strong> - Connect the slots you would like to paint with on
|
||||||
|
the wires layer!<br><br> To switch to the wires layer, press
|
||||||
|
<strong>E</strong>."
|
||||||
|
reward_filter:
|
||||||
|
title: Item Filter
|
||||||
|
desc: You unlocked the <strong>Item Filter</strong>! It will route items either
|
||||||
|
to the top or the right output depending on whether they match the
|
||||||
|
signal from the wires layer or not.<br><br> You can also pass in a
|
||||||
|
boolean signal (1 / 0) to entirely activate or disable it.
|
||||||
reward_display:
|
reward_display:
|
||||||
title: Display
|
title: Display
|
||||||
desc: "You have unlocked the <strong>Display</strong> - Connect a signal on the
|
desc: "You have unlocked the <strong>Display</strong> - Connect a signal on the
|
||||||
@ -718,35 +705,39 @@ storyRewards:
|
|||||||
shape requested by the HUB (I recommend to try it!).<br><br> - Build
|
shape requested by the HUB (I recommend to try it!).<br><br> - Build
|
||||||
something cool with wires.<br><br> - Continue to play
|
something cool with wires.<br><br> - Continue to play
|
||||||
regulary.<br><br> Whatever you choose, remember to have fun!
|
regulary.<br><br> Whatever you choose, remember to have fun!
|
||||||
reward_wires_painter_and_levers:
|
no_reward:
|
||||||
title: Wires & Quad Painter
|
title: Nächstes Level
|
||||||
desc: "You just unlocked the <strong>Wires Layer</strong>: It is a separate
|
desc: "Dieses Level hat dir keine Belohnung gegeben, aber im Nächsten gibt es
|
||||||
layer on top of the regular layer and introduces a lot of new
|
eine! <br><br> PS: Denke daran, deine alten Fabriken nicht zu
|
||||||
mechanics!<br><br> For the beginning I unlocked you the <strong>Quad
|
zerstören - Du wirst sie später <strong>alle</strong> noch brauchen,
|
||||||
Painter</strong> - Connect the slots you would like to paint with on
|
um <strong>Upgrades freizuschalten</strong>!"
|
||||||
the wires layer!<br><br> To switch to the wires layer, press
|
no_reward_freeplay:
|
||||||
<strong>E</strong>."
|
title: Nächstes Level
|
||||||
reward_filter:
|
desc: Du hast das nächste Level freigeschaltet!
|
||||||
title: Item Filter
|
reward_freeplay:
|
||||||
desc: You unlocked the <strong>Item Filter</strong>! It will route items either
|
title: Freies Spiel
|
||||||
to the top or the right output depending on whether they match the
|
desc: Du hast es geschafft! Du hast den <strong>Freispiel-Modus</strong> freigeschaltet! Das bedeutet,
|
||||||
signal from the wires layer or not.<br><br> You can also pass in a
|
dass die abzuliefernden Formen jetzt <strong>zufällig</strong> erzeugt werden!<br><br>
|
||||||
boolean signal (1 / 0) to entirely activate or disable it.
|
Da der Hub ab jetzt einen bestimmten <strong>Durchsatz</strong> benötigt, empfehle ich dringend, eine Maschine zu bauen,
|
||||||
|
die automatisch die gewünschte Form liefert!<br><br>
|
||||||
|
Der Hub gibt die gewünschte Form auf der Wires-Ebene aus. Also musst du sie nur analysieren und
|
||||||
|
basierend darauf automatisch deine Fabrik konfigurieren.
|
||||||
reward_demo_end:
|
reward_demo_end:
|
||||||
title: End of Demo
|
title: Ende der Demo
|
||||||
desc: You have reached the end of the demo version!
|
desc: Du bist am Ende der Demo angekommen!
|
||||||
settings:
|
settings:
|
||||||
title: Einstellungen
|
title: Einstellungen
|
||||||
categories:
|
categories:
|
||||||
general: Allgemein
|
general: Allgemein
|
||||||
userInterface: Benutzeroberfläche
|
userInterface: Benutzeroberfläche
|
||||||
advanced: Erweitert
|
advanced: Erweitert
|
||||||
performance: Performance
|
performance: Leistung
|
||||||
versionBadges:
|
versionBadges:
|
||||||
dev: Entwicklung
|
dev: Entwicklung
|
||||||
staging: Beta
|
staging: Beta
|
||||||
prod: Produktion
|
prod: Produktion
|
||||||
buildDate: Gebaut am <at-date>
|
buildDate: Gebaut am <at-date>
|
||||||
|
rangeSliderPercentage: <amount> %
|
||||||
labels:
|
labels:
|
||||||
uiScale:
|
uiScale:
|
||||||
title: HUD Größe
|
title: HUD Größe
|
||||||
@ -862,46 +853,44 @@ settings:
|
|||||||
description: Deaktiviert die Warnung, welche beim Löschen und Ausschneiden von
|
description: Deaktiviert die Warnung, welche beim Löschen und Ausschneiden von
|
||||||
mehr als 100 Feldern angezeigt wird.
|
mehr als 100 Feldern angezeigt wird.
|
||||||
lowQualityMapResources:
|
lowQualityMapResources:
|
||||||
title: Low Quality Map Resources
|
title: Minimalistische Ressourcen
|
||||||
description: Simplifies the rendering of resources on the map when zoomed in to
|
description: Vereinfacht die Darstellung der Ressourcen auf der hereingezoomten Karte
|
||||||
improve performance. It even looks cleaner, so be sure to try it
|
zur Verbesserung der Leistung. Die Darstellung ist übersichtlicher, also probiere
|
||||||
out!
|
es ruhig aus!
|
||||||
disableTileGrid:
|
disableTileGrid:
|
||||||
title: Disable Grid
|
title: Gitter deaktivieren
|
||||||
description: Disabling the tile grid can help with the performance. This also
|
description: Das Deaktivieren des Gitters kann deine Leistung verbessern. Außerdem vereinfacht
|
||||||
makes the game look cleaner!
|
es die Darstellung!
|
||||||
clearCursorOnDeleteWhilePlacing:
|
clearCursorOnDeleteWhilePlacing:
|
||||||
title: Clear Cursor on Right Click
|
title: Abwählen mit Rechtsklick
|
||||||
description: Enabled by default, clears the cursor whenever you right click
|
description: Standardmäßig eingeschaltet, wählt es das aktuelle, zur Platzierung ausgewählte Gebäude
|
||||||
while you have a building selected for placement. If disabled,
|
ab, wenn du die rechte Masutaste drückst. Wenn du es abschaltest, kannst du mit der rechten
|
||||||
you can delete buildings by right-clicking while placing a
|
Maustaste Gebäude löschen, während du im Platzierungsmodus bist.
|
||||||
building.
|
|
||||||
lowQualityTextures:
|
lowQualityTextures:
|
||||||
title: Low quality textures (Ugly)
|
title: Niedrige Texturqualität (Unschön)
|
||||||
description: Uses low quality textures to save performance. This will make the
|
description: Das Spiel verwendet eine niedrigere Auflösung bei den Texturen.
|
||||||
game look very ugly!
|
Allerdings leidet die Grafik des Spiels sehr darunter!
|
||||||
displayChunkBorders:
|
displayChunkBorders:
|
||||||
title: Display Chunk Borders
|
title: Chunk-Ränder anzeigen
|
||||||
description: The game is divided into chunks of 16x16 tiles, if this setting is
|
description: Das Spiel ist in Blöcke (Chunks) aus je 16x16 Feldern aufgeteilt. Diese Einstellung
|
||||||
enabled the borders of each chunk are displayed.
|
lässt dich die Grenzen zwischen den Chunks anzeigen.
|
||||||
|
|
||||||
pickMinerOnPatch:
|
pickMinerOnPatch:
|
||||||
title: Pick miner on resource patch
|
title: Automatisch Extrahierer auswählen
|
||||||
description: Enabled by default, selects the miner if you use the pipette when
|
description: Standardmäßig eingeschaltet, wählst du automatisch den Extrahierer, wenn du mit
|
||||||
hovering a resource patch.
|
der Pipette auf einen Ressourcenfleck zeigst
|
||||||
simplifiedBelts:
|
simplifiedBelts:
|
||||||
title: Simplified Belts (Ugly)
|
title: Minimalistische Förderbänder (Unschön)
|
||||||
description: Does not render belt items except when hovering the belt to save
|
description: Zur Verbesserung der Leistung werden die Items auf Förderbändern nur angezeigt,
|
||||||
performance. I do not recommend to play with this setting if you
|
wenn du deine Maus darüber bewegst. Hier leidet sowohl die Grafik, also auch dein
|
||||||
do not absolutely need the performance.
|
Spielerlebnis. Benutze die Funktion nur, wenn du auf die Leistung wirklich angewiesen bist!
|
||||||
enableMousePan:
|
enableMousePan:
|
||||||
title: Enable Mouse Pan
|
title: Scrollen am Bildschirmrand
|
||||||
description: Allows to move the map by moving the cursor to the edges of the
|
description: Damit kannst du dich über die Karte bewegen, indem du deinen Mauszeiger am
|
||||||
screen. The speed depends on the Movement Speed setting.
|
Bildschirmrand platzierst. Die Geschwindigkeit stimmt dabei mit den Tasten überein.
|
||||||
rangeSliderPercentage: <amount> %
|
|
||||||
keybindings:
|
keybindings:
|
||||||
title: Tastenbelegung
|
title: Tastenbelegung
|
||||||
hint: "Tipp: Benutze STRG, UMSCH and ALT! Sie aktivieren verschiedene
|
hint: "Tipp: Benutze STRG, UMSCH and ALT! Sie aktivieren verschiedene Platzierungsoptionen."
|
||||||
Platzierungsoptionen."
|
|
||||||
resetKeybindings: Tastenbelegung zurücksetzen
|
resetKeybindings: Tastenbelegung zurücksetzen
|
||||||
categoryLabels:
|
categoryLabels:
|
||||||
general: Anwendung
|
general: Anwendung
|
||||||
@ -922,7 +911,7 @@ keybindings:
|
|||||||
centerMap: Karte zentrieren
|
centerMap: Karte zentrieren
|
||||||
mapZoomIn: Reinzoomen
|
mapZoomIn: Reinzoomen
|
||||||
mapZoomOut: Rauszoomen
|
mapZoomOut: Rauszoomen
|
||||||
createMarker: Markierung erstellen
|
createMarker: Marker erstellen
|
||||||
menuOpenShop: Upgrades
|
menuOpenShop: Upgrades
|
||||||
menuOpenStats: Statistiken
|
menuOpenStats: Statistiken
|
||||||
menuClose: Menü schließen
|
menuClose: Menü schließen
|
||||||
@ -930,61 +919,59 @@ keybindings:
|
|||||||
toggleFPSInfo: FPS und Debug-Info an/aus
|
toggleFPSInfo: FPS und Debug-Info an/aus
|
||||||
switchLayers: Ebenen wechseln
|
switchLayers: Ebenen wechseln
|
||||||
exportScreenshot: Ganze Fabrik als Foto exportieren
|
exportScreenshot: Ganze Fabrik als Foto exportieren
|
||||||
belt: Förderband
|
belt: Fließband
|
||||||
|
balancer: Verteiler
|
||||||
underground_belt: Tunnel
|
underground_belt: Tunnel
|
||||||
miner: Extrahierer
|
miner: Extrahierer
|
||||||
cutter: Schneider
|
cutter: Schneider
|
||||||
rotater: Rotierer (-90°)
|
rotater: Rotierer (90°)
|
||||||
stacker: Stapler
|
stacker: Stapler
|
||||||
mixer: Farbmischer
|
mixer: Farbmischer
|
||||||
painter: Färber
|
painter: Färber
|
||||||
trash: Mülleimer
|
trash: Mülleimer
|
||||||
|
storage: Lager
|
||||||
|
wire: Stromkabel
|
||||||
|
constant_signal: Signalgeber
|
||||||
|
logic_gate: Logikgatter
|
||||||
|
lever: Schalter (regulär)
|
||||||
|
filter: Filter
|
||||||
|
wire_tunnel: Kabelkreuzung
|
||||||
|
display: Anzeige
|
||||||
|
reader: Fließbandkontrolle
|
||||||
|
virtual_processor: Virtueller Schneider
|
||||||
|
transistor: Transistor
|
||||||
|
analyzer: Formanalyse
|
||||||
|
comparator: Vergleich
|
||||||
|
item_producer: Item-Produzent (Sandkastenmodus)
|
||||||
pipette: Pipette
|
pipette: Pipette
|
||||||
rotateWhilePlacing: Rotieren
|
rotateWhilePlacing: Rotieren
|
||||||
rotateInverseModifier: "Modifikator: stattdessen gegen den UZS rotieren"
|
rotateInverseModifier: "Modifikator: stattdessen gegen den UZS rotieren"
|
||||||
cycleBuildingVariants: Nächste Variante auswählen
|
cycleBuildingVariants: Nächste Variante auswählen
|
||||||
confirmMassDelete: Massenlöschung bestätigen
|
confirmMassDelete: Löschen bestätigen
|
||||||
pasteLastBlueprint: Letzte Blaupause einfügen
|
pasteLastBlueprint: Letzte Blaupause einfügen
|
||||||
cycleBuildings: Nächstes Gebäude auswählen
|
cycleBuildings: Nächstes Gebäude auswählen
|
||||||
lockBeltDirection: Bandplaner aktivieren
|
lockBeltDirection: Bandplaner aktivieren
|
||||||
switchDirectionLockSide: "Bandplaner: Seite wechseln"
|
switchDirectionLockSide: "Bandplaner: Seite wechseln"
|
||||||
|
copyWireValue: "Kabel: Wert unter Mauszeiger kopieren"
|
||||||
massSelectStart: Halten und ziehen zum Beginnen
|
massSelectStart: Halten und ziehen zum Beginnen
|
||||||
massSelectSelectMultiple: Mehrere Areale markieren
|
massSelectSelectMultiple: Mehrere Areale markieren
|
||||||
massSelectCopy: Areal kopieren
|
massSelectCopy: Areal kopieren
|
||||||
massSelectCut: Areal ausschneiden
|
massSelectCut: Areal ausschneiden
|
||||||
placementDisableAutoOrientation: Automatische Orientierung deaktivieren
|
placementDisableAutoOrientation: Automatische Orientierung deaktivieren
|
||||||
placeMultiple: Im Platziermodus bleiben
|
placeMultiple: Im Platziermodus bleiben
|
||||||
placeInverse: Automatische Förderbandorientierung invertieren
|
placeInverse: Automatische Fließbandorientierung invertieren
|
||||||
wire: Stromkabel
|
|
||||||
balancer: Balancer
|
|
||||||
storage: Storage
|
|
||||||
constant_signal: Constant Signal
|
|
||||||
logic_gate: Logic Gate
|
|
||||||
lever: Switch (regular)
|
|
||||||
filter: Filter
|
|
||||||
wire_tunnel: Wire Crossing
|
|
||||||
display: Display
|
|
||||||
reader: Belt Reader
|
|
||||||
virtual_processor: Virtual Cutter
|
|
||||||
transistor: Transistor
|
|
||||||
analyzer: Shape Analyzer
|
|
||||||
comparator: Compare
|
|
||||||
item_producer: Item Producer (Sandbox)
|
|
||||||
copyWireValue: "Wires: Copy value below cursor"
|
|
||||||
about:
|
about:
|
||||||
title: Über dieses Spiel
|
title: Über dieses Spiel
|
||||||
body: >-
|
body: >-
|
||||||
Dieses Spiel hat einen offenen Quellcode (Open Source) und wurde von <a
|
Dieses Spiel ist quelloffen (Open Source) und wurde von <a
|
||||||
href="https://github.com/tobspr" target="_blank">Tobias Springer</a>
|
href="https://github.com/tobspr" target="_blank">Tobias Springer</a>
|
||||||
(das bin ich!) entwickelt.<br><br>
|
(das bin ich!) entwickelt.<br><br>
|
||||||
|
|
||||||
Wenn du etwas zum Spiel beitragen möchtest, dann schaue dir <a href="<githublink>" target="_blank">shapez.io auf GitHub</a> an.<br><br>
|
Wenn du etwas zum Spiel beitragen möchtest, dann schaue dir <a href="<githublink>" target="_blank">shapez.io auf GitHub</a> an.<br><br>
|
||||||
|
Das Spiel wurde erst durch die großartige Discord-Community um meine Spiele möglich gemacht.
|
||||||
Das Spiel wurde erst durch die großartige Discord-Community um meine Spiele möglich gemacht. Komm doch einfach mal auf dem <a href="<discordlink>" target="_blank">Discord-Server</a> vorbei!<br><br>
|
Komm doch einfach mal auf dem <a href="<discordlink>" target="_blank">Discord-Server</a> vorbei!<br><br>
|
||||||
|
|
||||||
Der Soundtrack wurde von <a href="https://soundcloud.com/pettersumelius" target="_blank">Peppsen</a> komponiert! Klasse Typ.<br><br>
|
Der Soundtrack wurde von <a href="https://soundcloud.com/pettersumelius" target="_blank">Peppsen</a> komponiert! Klasse Typ.<br><br>
|
||||||
|
Abschließend möchte ich meinem Kumpel <a href="https://github.com/niklas-dahl" target="_blank">Niklas</a> danken!
|
||||||
Abschließend möchte ich meinem Kumpel <a href="https://github.com/niklas-dahl" target="_blank">Niklas</a> danken! Ohne unsere etlichen gemeinsamen Stunden in Factorio wäre dieses Projekt nie zustande gekommen.
|
Ohne unsere etlichen gemeinsamen Stunden in Factorio wäre dieses Projekt nie zustande gekommen.
|
||||||
changelog:
|
changelog:
|
||||||
title: Änderungen
|
title: Änderungen
|
||||||
demo:
|
demo:
|
||||||
@ -996,75 +983,59 @@ demo:
|
|||||||
exportingBase: Ganze Fabrik als Foto exportieren
|
exportingBase: Ganze Fabrik als Foto exportieren
|
||||||
settingNotAvailable: Nicht verfügbar in der Demo.
|
settingNotAvailable: Nicht verfügbar in der Demo.
|
||||||
tips:
|
tips:
|
||||||
- Der Hub akzeptiert jede Art von Form, nicht nur die aktuelle!
|
- Der Hub akzeptiert alle Formen, nicht nur die aktuell geforderten!
|
||||||
- Stelle sicher, dass deine Fabriken modular sind - es zahlt sich aus!
|
- Stelle sicher, dass deine Fabriken modular sind. Es zahlt sich irgendwann aus!
|
||||||
- Baue nicht zu nah am Hub, sonst wird es ein riesiges Chaos geben!
|
- Baue nicht zu nah am Hub, sonst entsteht ein riesiges Chaos!
|
||||||
- Wenn das Stapeln nicht funktioniert, versuche die Eingänge zu wechseln.
|
- Wenn der Stapler nicht die richtige Form ausspuckt, wechsle doch mal die Eingänge.
|
||||||
- Du kannst mittels <b>R</b> die Richtung des Bandplaners umkehren.
|
- Du kannst mit <b>R</b> die Richtung des Bandplaners umkehren.
|
||||||
- Halte <b>STRG</b> um die Förderbänder ohne automatische Orientierung zu
|
- Halte <b>STRG</b>, um die Förderbänder ohne automatische Orientierung zu platzieren.
|
||||||
platzieren.
|
- Die Verhältnisse der Maschinen bleiben gleich, wenn du die Upgrades gleichmäßig kaufst.
|
||||||
- Die Ratios bleiben gleich, solange die die Upgrades auf der selben Stufen
|
|
||||||
sind.
|
|
||||||
- Serielle Ausführung ist effizienter als parallele.
|
- Serielle Ausführung ist effizienter als parallele.
|
||||||
- Du wirst später im Spiel mehr Varianten von Gebäuden freischalten!
|
- Für viele Gebäude wirst du im Spielverlauf neue Varianten freischalten!
|
||||||
- Du kanst <b>T</b> drücken, um auf andere Varianten des Gebäude zu wechseln.
|
- Du kanst <b>T</b> drücken, um auf andere Varianten des Gebäudes zu wechseln.
|
||||||
- Symmetrie ist der Schlüssel!
|
- Symmetrie ist der Schlüssel!
|
||||||
- Du kannst verschiedene Arten von Tunneln miteinander verweben.
|
- Du kannst verschiedene Arten von Tunneln miteinander verweben.
|
||||||
- Versuche kompakte Fabriken zu bauen - es zahlt sich aus!
|
- Versuche kompakte Fabriken zu bauen. Es zahlt sich aus!
|
||||||
- Der Färber hat eine spiegelverkehrte Variante, die du mittels <b>T</b>
|
- Der Färber hat eine spiegelverkehrte Variante, die du mit <b>T</b> auswählen kannst.
|
||||||
auswählen kannst.
|
|
||||||
- Das richtige Verhältnis der Gebäude maximiert die Effizienz.
|
- Das richtige Verhältnis der Gebäude maximiert die Effizienz.
|
||||||
- Auf dem maximalen Level genügen 5 Extrahierer für ein einzelnes Förderband.
|
- Auf der gleichen Upgrade-Stufe genügen 5 Extrahierer für ein ganzes Fließband.
|
||||||
- Vergiss die Tunnel nicht!
|
- Vergiss die Tunnel nicht!
|
||||||
- Du musst die Items für maximale Effizienz nicht gleichmässig aufteilen.
|
- Für maximale Effizienz musst du die Items nicht gleichmässig aufteilen.
|
||||||
- Das Halten von <b>UMSCH</b> aktiviert den Bandplaner, der dir das
|
- Das Halten von <b>UMSCH</b> aktiviert den Bandplaner, der lange Förderbänder ganz einfach platziert.
|
||||||
Platzieren langer Linien vereinfacht.
|
- Schneider teilen die Form immer vertikal, unabhängig von der Orientierung.
|
||||||
- Schneider schneiden immer vertikal, egal deren Orientierung.
|
- Weiß erhälst du aus der Kombination aller 3 Grundfarben.
|
||||||
- Um Weiss zu erhalten, mixe alle Farben zusammen.
|
- Das Lager gibt Items immer zuerst am linken Ausgang ab.
|
||||||
- Der Speicher priorisiert den linken Ausgang.
|
- Es lohnt sich, Zeit in den Bau von wiederverwendbaren Designs zu stecken!
|
||||||
- Investiere Zeit, um wiederholbare Designs zu erstellen - es lohnt sich!
|
- Das Halten von <b>STRG</b> ermöglicht dir, mehrere Gebäude zu platzieren.
|
||||||
- Das Halten von <b>STRG</b> ermöglicht dir mehrere Gebäude zu platzieren.
|
- Du kanst <b>ALT</b> gedrückt halten, um die Richtung der Förderbänder umzukehren.
|
||||||
- Du kanst <b>ALT</b> gedrückt halten, um die Richtung der Förderbänder
|
- Effizienz ist entscheidend!
|
||||||
umzukehren.
|
- Abbaubare Formen werden komplexer, je weiter sie vom Hub entfernt sind.
|
||||||
- Effizienz ist der Schlüssel!
|
- Gebäude haben eine limitierte Geschwindigkeit. Teile die Last zwischen mehreren auf.
|
||||||
- Formflecken, die weiter vom Hub entfernt sind, sind komplexer.
|
- Benutze Aufteiler, um deine Effizienz zu maximieren.
|
||||||
- Gebäude haben eine limitierte Geschwindigkeit, teile sie auf für maximale
|
- Organisation ist wichtig! Verheddere dich nicht in einem Gewirr aus Förderbändern.
|
||||||
Effizienz.
|
- Plane vorher und lasse dir Platz für Reserven, oder es gibt ein riesiges Chaos!
|
||||||
- Benutze Verteiler um deine Effizienz zu maximieren.
|
- Lösche deine alten Fabriken nicht! Du benötigst sie um Upgrades freizuschalten.
|
||||||
- Organisation ist wichtig. Versuch das Kreuzen von Förderbändern zu
|
- Versuche Level 20 alleine zu meistern, bevor du nach Hilfe suchst!
|
||||||
minimieren.
|
- Mache es dir nicht zu kompliziert! Auch mit einfachen Konzepten kommst du hier sehr weit.
|
||||||
- Plane im Voraus, oder es gibt ein riesigen Chaos!
|
- Manche Fabriken musst du später wiederverwenden. Also baue sie so, damit du genau das kannst.
|
||||||
- Lösche deine alten Fabriken nicht! Du benötigst sie um Upgrades
|
- Manchmal kannst du die gewünschte Form auf der Karte finden, ohne sie herstellen zu müssen.
|
||||||
freizuschalten.
|
|
||||||
- Versuch Level 20 alleine zu meistern, bevor du nach Hilfe suchst!
|
|
||||||
- Mach es dir nicht zu kompliziert, versuch es einfach zu halten und du
|
|
||||||
wirst weit vorankommen.
|
|
||||||
- Vielleicht musst du Fabriken später im Spiel wiederverwenden. Plane deine
|
|
||||||
Fabriken so, dass sie wiederverwendbar sind.
|
|
||||||
- Manchmal kannst du die gewünschte Form auf der Karte finden, ohne sie mit
|
|
||||||
Staplern zu erstellen.
|
|
||||||
- Vollständige Windmühlen werden nicht natürlich generiert.
|
- Vollständige Windmühlen werden nicht natürlich generiert.
|
||||||
- Färbe deine Formen vor dem Schneiden für maximale Effizienz.
|
- Färbe deine Formen vor dem Schneiden! Das geht viel schneller.
|
||||||
- Mit Modulen ist der Raum nur eine Wahrnehmung; eine Sorge für die
|
- Mit Modulen wird Platz nur noch zum Begriff; eine Sorge für Sterbliche.
|
||||||
sterblichen Menschen.
|
- Stelle deinen Nachschub an Blaupausen sicher. Ohne sie sind Module nutzlos.
|
||||||
- Mache eine separate Blaupausenfabrik. Sie sind wichtig für Module.
|
- Schau dir den Farbmischer genauer an und du wirst deine Antwort finden.
|
||||||
- Schau dir den Farbmischer genauer an, und deine Fragen werden beantwortet.
|
- Benutze <b>STRG</b> + Rechtsklick, um einen Bereich zu selektieren.
|
||||||
- Benutze <b>STRG</b> + rechter Mausklick, um einen Bereich zu selektieren.
|
|
||||||
- Zu nahe am Hub zu bauen, kann späteren Projekten im Weg stehen.
|
- Zu nahe am Hub zu bauen, kann späteren Projekten im Weg stehen.
|
||||||
- Das Pin-Symbol neben jeder Form in der Upgrade-Liste heftet sie an den
|
- Die Reißzwecke neben Formen in der Upgrade-Liste lässt sie dich am Bildschirm anheften.
|
||||||
Bildschirm.
|
|
||||||
- Mische alle drei Grundfarben, um Weiß zu erhalten!
|
- Mische alle drei Grundfarben, um Weiß zu erhalten!
|
||||||
- Du hast eine unendlich grosse Karte, nutze den Platz, expandiere!
|
- Du hast eine unendlich grosse Karte, nutze den Platz und expandiere!
|
||||||
- Probier auch mal Factorio! Es ist mein Lieblingsspiel.
|
- Probier auch mal Factorio! Es ist mein Lieblingsspiel.
|
||||||
- Der Vierfachschneider schneidet im Uhrzeigersinn von oben rechts beginnend!
|
- Der Vierfachschneider schneidet im Uhrzeigersinn von oben rechts beginnend!
|
||||||
- Du kannst deine Speicherstände im Hauptmenü herunterladen!
|
- Du kannst deine Speicherstände im Hauptmenü herunterladen!
|
||||||
- Diese Spiel hat viele nützliche Tastenbelegungen! Schau sie dir in den
|
- Diese Spiel hat viele nützliche Tastenbelegungen! Schau sie dir in den Einstellungen an.
|
||||||
Einstellungen an.
|
- Dieses Spiel hat eine Menge Einstellungen, schaue sie dir einmal an!
|
||||||
- Dieses Spiel hat viele Einstellungen, schau sie dir einmal an!
|
- Die Richtung zu deinem Hub ist oben rechts mit einer kleinen Kompassnadel markiert!
|
||||||
- Die Markierung des Hubs hat einen kleinen Kompass, der die Richtung
|
- Um alle Förderbänder zu leeren, schneide den Bereich aus und füge ihn auf der selben Position wieder ein.
|
||||||
anzeigt!
|
- Drücke F4 um deine FPS und Tickrate anzuzeigen.
|
||||||
- Um die Förderbänder zu leeren, schneide den Bereich aus und füge ihn in
|
- Drücke doppelt F4 um den Standort des Mauszeigers und der Kamera zu bestimmen.
|
||||||
der gleichen Position wieder ein.
|
- Du kannst die angehefteten Formen am linken Rand wieder entfernen.
|
||||||
- Drücke F4 um deine FPS und Tick Rate anzuzeigen.
|
|
||||||
- Drücke doppelt F4 um die Kachel des Zeigers und der Kamera anzuzeigen.
|
|
||||||
- Du kannst die angehefteten Formen auf der linken Seite ablösen.
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ steamPage:
|
|||||||
discordLinkShort: Official Discord
|
discordLinkShort: Official Discord
|
||||||
intro: >-
|
intro: >-
|
||||||
Shapez.io is a relaxed game in which you have to build factories for the
|
Shapez.io is a relaxed game in which you have to build factories for the
|
||||||
automated production of geometric shapes.
|
automated production of geometric shapes.
|
||||||
|
|
||||||
As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map.
|
As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map.
|
||||||
|
|
||||||
|
|||||||
@ -272,10 +272,6 @@ dialogs:
|
|||||||
title: Rename Savegame
|
title: Rename Savegame
|
||||||
desc: You can rename your savegame here.
|
desc: You can rename your savegame here.
|
||||||
|
|
||||||
entityWarning:
|
|
||||||
title: Performance Warning
|
|
||||||
desc: You have placed a lot of buildings, this is just a friendly reminder that the game can not handle an endless number of buildings - try to keep your factories compact!
|
|
||||||
|
|
||||||
ingame:
|
ingame:
|
||||||
# This is shown in the top left corner and displays useful keybindings in
|
# This is shown in the top left corner and displays useful keybindings in
|
||||||
# every situation
|
# every situation
|
||||||
@ -355,10 +351,6 @@ ingame:
|
|||||||
# Gets replaced to e.g. "Tier IX"
|
# Gets replaced to e.g. "Tier IX"
|
||||||
tier: Tier <x>
|
tier: Tier <x>
|
||||||
|
|
||||||
# The roman number for each tier
|
|
||||||
tierLabels:
|
|
||||||
[I, II, III, IV, V, VI, VII, VIII, IX, X, XI, XII, XIII, XIV, XV, XVI, XVII, XVIII, XIX, XX]
|
|
||||||
|
|
||||||
maximumLevel: MAXIMUM LEVEL (Speed x<currentMult>)
|
maximumLevel: MAXIMUM LEVEL (Speed x<currentMult>)
|
||||||
|
|
||||||
# The "Statistics" window
|
# The "Statistics" window
|
||||||
@ -1033,6 +1025,11 @@ settings:
|
|||||||
description: >-
|
description: >-
|
||||||
Allows panning the map by moving the cursor to the edges of the screen. The scroll speed depends on the Movement Speed setting.
|
Allows panning the map by moving the cursor to the edges of the screen. The scroll speed depends on the Movement Speed setting.
|
||||||
|
|
||||||
|
zoomToCursor:
|
||||||
|
title: Zoom towards Cursor
|
||||||
|
description: >-
|
||||||
|
If activated the zoom will happen in the direction of your mouse position, otherwise in the middle of the screen.
|
||||||
|
|
||||||
keybindings:
|
keybindings:
|
||||||
title: Keybindings
|
title: Keybindings
|
||||||
hint: >-
|
hint: >-
|
||||||
|
|||||||
@ -2,29 +2,29 @@ steamPage:
|
|||||||
shortText: shapez.io es un juego sobre construir fábricas para automatizar la
|
shortText: shapez.io es un juego sobre construir fábricas para automatizar la
|
||||||
creación y combinación de figuras cada vez más complejas en un mapa
|
creación y combinación de figuras cada vez más complejas en un mapa
|
||||||
infinito.
|
infinito.
|
||||||
discordLinkShort: Official Discord
|
discordLinkShort: Discord oficial
|
||||||
intro: >-
|
intro: >-
|
||||||
Shapez.io is a relaxed game in which you have to build factories for the
|
Shapez.io es un juego tranquilo en el que tienes que construir fábricas para la
|
||||||
automated production of geometric shapes.
|
producción automatizada de formas geométricas.
|
||||||
|
|
||||||
As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map.
|
A medida que el nivel aumenta, las formas se vuelven más y más complejas, y tienes que extenderte en un mapa infinito.
|
||||||
|
|
||||||
And as if that wasn't enough, you also have to produce exponentially more to satisfy the demands - the only thing that helps is scaling!
|
Y por si fuera poco, también tienes que producir exponencialmente más para satisfacer las demandas - ¡lo único que ayuda es escalar!
|
||||||
|
|
||||||
While you only process shapes at the beginning, you have to color them later - for this you have to extract and mix colors!
|
Mientras que sólo procesas formas al principio, tienes que colorearlas después - ¡para ello tienes que extraer y mezclar los colores!
|
||||||
|
|
||||||
Buying the game on Steam gives you access to the full version, but you can also play a demo on shapez.io first and decide later!
|
Comprando el juego en Steam tienes acceso a la versión completa, ¡pero también puedes jugar una demo en shapez.io primero y decidir después!
|
||||||
title_advantages: Standalone Advantages
|
title_advantages: Ventajas del juego
|
||||||
advantages:
|
advantages:
|
||||||
- <b>12 New Level</b> for a total of 26 levels
|
- <b>12 nuevos niveles</b> de un total de 26 niveles
|
||||||
- <b>18 New Buildings</b> for a fully automated factory!
|
- <b>18 nuevos edificios</b> ¡para una fábrica totalmente automatizada!
|
||||||
- <b>20 Upgrade Tiers</b> for many hours of fun!
|
- <b>20 Upgrade Tiers</b> for many hours of fun!
|
||||||
- <b>Wires Update</b> for an entirely new dimension!
|
- <b>Wires Update</b> for an entirely new dimension!
|
||||||
- <b>Dark Mode</b>!
|
- <b>Modo oscuro</b>!
|
||||||
- Unlimited Savegames
|
- Partidad guardadas ilimitadas
|
||||||
- Unlimited Markers
|
- Marcadores ilimitados
|
||||||
- Support me! ❤️
|
- Support me! ❤️
|
||||||
title_future: Planned Content
|
title_future: Contenido futuro
|
||||||
planned:
|
planned:
|
||||||
- Blueprint Library (Standalone Exclusive)
|
- Blueprint Library (Standalone Exclusive)
|
||||||
- Steam Achievements
|
- Steam Achievements
|
||||||
|
|||||||
@ -5,7 +5,7 @@ steamPage:
|
|||||||
discordLinkShort: Official Discord
|
discordLinkShort: Official Discord
|
||||||
intro: >-
|
intro: >-
|
||||||
Shapez.io is a relaxed game in which you have to build factories for the
|
Shapez.io is a relaxed game in which you have to build factories for the
|
||||||
automated production of geometric shapes.
|
automated production of geometric shapes.
|
||||||
|
|
||||||
As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map.
|
As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map.
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@ steamPage:
|
|||||||
discordLinkShort: Official Discord
|
discordLinkShort: Official Discord
|
||||||
intro: >-
|
intro: >-
|
||||||
Shapez.io is a relaxed game in which you have to build factories for the
|
Shapez.io is a relaxed game in which you have to build factories for the
|
||||||
automated production of geometric shapes.
|
automated production of geometric shapes.
|
||||||
|
|
||||||
As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map.
|
As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map.
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ steamPage:
|
|||||||
discordLinkShort: Official Discord
|
discordLinkShort: Official Discord
|
||||||
intro: >-
|
intro: >-
|
||||||
Shapez.io is a relaxed game in which you have to build factories for the
|
Shapez.io is a relaxed game in which you have to build factories for the
|
||||||
automated production of geometric shapes.
|
automated production of geometric shapes.
|
||||||
|
|
||||||
As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map.
|
As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map.
|
||||||
|
|
||||||
|
|||||||
@ -4,17 +4,17 @@ steamPage:
|
|||||||
yang meluas tanpa batas.
|
yang meluas tanpa batas.
|
||||||
discordLinkShort: Official Discord
|
discordLinkShort: Official Discord
|
||||||
intro: >-
|
intro: >-
|
||||||
Shapez.io is a relaxed game in which you have to build factories for the
|
Shapez.io adalah game santai dimana anda harus membuat pabrik untuk
|
||||||
automated production of geometric shapes.
|
mengotomatiskan produksi bentuk-bentuk geometris.
|
||||||
|
|
||||||
As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map.
|
Semakin meningkatnya level, bentuk-bentuknya menjadi lebih kompleks, dan anda perlu meluas di peta yang tak terbatas.
|
||||||
|
|
||||||
And as if that wasn't enough, you also have to produce exponentially more to satisfy the demands - the only thing that helps is scaling!
|
Dan jita itu tidak cukup, anda juga perlu untuk memproduksi secara ekxponensial untuk memenuhkan kebutuhan - hal yang membantu hanyalah memperbesar pabrik!
|
||||||
|
|
||||||
While you only process shapes at the beginning, you have to color them later - for this you have to extract and mix colors!
|
Walaupun anda hanya memproses bentuk di awal, anda perlu mewarnainya untuk nanti - untuk ini, anda perlu untuk mengekstrak dan mencampur warna!
|
||||||
|
|
||||||
Buying the game on Steam gives you access to the full version, but you can also play a demo on shapez.io first and decide later!
|
Membeli game ini di Steam memberikan anda akses ke versi lengkap, namun anda juga dapat mencoba demo dan memutuskan nanti!
|
||||||
title_advantages: Standalone Advantages
|
title_advantages: Keuntungan versi penuh
|
||||||
advantages:
|
advantages:
|
||||||
- <b>12 New Level</b> for a total of 26 levels
|
- <b>12 New Level</b> for a total of 26 levels
|
||||||
- <b>18 New Buildings</b> for a fully automated factory!
|
- <b>18 New Buildings</b> for a fully automated factory!
|
||||||
@ -411,12 +411,12 @@ buildings:
|
|||||||
beberapa.
|
beberapa.
|
||||||
wire:
|
wire:
|
||||||
default:
|
default:
|
||||||
name: Kawat Energi
|
name: Kabel
|
||||||
description: Memungkinkan anda untuk mengangkut energi.
|
description: Memungkinkan anda untuk mengangkut Energi.
|
||||||
second:
|
second:
|
||||||
name: Wire
|
name: Kabel
|
||||||
description: Transfers signals, which can be items, colors or booleans (1 / 0).
|
description: Mentransfer sinyal, dapat berupa bentuk, warna, atau boolean (1 / 0).
|
||||||
Different colored wires do not connect.
|
Kabel dengan warna berbeda tidak akan menyambung.
|
||||||
miner:
|
miner:
|
||||||
default:
|
default:
|
||||||
name: Ekstraktor
|
name: Ekstraktor
|
||||||
@ -455,13 +455,13 @@ buildings:
|
|||||||
name: Pemutar (Berlawanan Arah Jarum Jam)
|
name: Pemutar (Berlawanan Arah Jarum Jam)
|
||||||
description: Memutar bentuk berlawanan arah jarum jam sebesar 90 derajat.
|
description: Memutar bentuk berlawanan arah jarum jam sebesar 90 derajat.
|
||||||
rotate180:
|
rotate180:
|
||||||
name: Rotate (180)
|
name: Pemutar (180)
|
||||||
description: Rotates shapes by 180 degrees.
|
description: Memutar bentuk searah jarum jam sebesar 180 derajat.
|
||||||
stacker:
|
stacker:
|
||||||
default:
|
default:
|
||||||
name: Penyusun
|
name: Penumpuk
|
||||||
description: Menggabungkan kedua artikel. Apabila mereka tidak dapat
|
description: Menumpukkan kedua bentuk. Apabila mereka tidak dapat
|
||||||
digabungkan, artikel kanan akan diletakkan diatas artikel kiri.
|
digabungkan, bentuk kanan akan diletakkan diatas bentuk kiri.
|
||||||
mixer:
|
mixer:
|
||||||
default:
|
default:
|
||||||
name: Pencampur Warna
|
name: Pencampur Warna
|
||||||
@ -489,123 +489,120 @@ buildings:
|
|||||||
description: Menerima input dari semua sisi dan menghancurkannya. Selamanya.
|
description: Menerima input dari semua sisi dan menghancurkannya. Selamanya.
|
||||||
balancer:
|
balancer:
|
||||||
default:
|
default:
|
||||||
name: Balancer
|
name: Pengimbang
|
||||||
description: Multifunctional - Evenly distributes all inputs onto all outputs.
|
description: Multifungsional - Mendistribusikan seluruh input secara merata ke seluruh output.
|
||||||
merger:
|
merger:
|
||||||
name: Merger (compact)
|
name: Penggabung (Kompak)
|
||||||
description: Merges two conveyor belts into one.
|
description: Menggabungkan dua sabuk konveyor menjadi satu.
|
||||||
merger-inverse:
|
merger-inverse:
|
||||||
name: Merger (compact)
|
name: Penggabung (Kompak)
|
||||||
description: Merges two conveyor belts into one.
|
description: Menggabungkan dua sabuk konveyor menjadi satu.
|
||||||
splitter:
|
splitter:
|
||||||
name: Splitter (compact)
|
name: Pemisah (Kompak)
|
||||||
description: Splits one conveyor belt into two.
|
description: Memisahkan satu sabuk konveyor menjadi dua.
|
||||||
splitter-inverse:
|
splitter-inverse:
|
||||||
name: Splitter (compact)
|
name: Pemisah (Kompak)
|
||||||
description: Splits one conveyor belt into two.
|
description: Memisahkan satu sabuk konveyor menjadi dua.
|
||||||
storage:
|
storage:
|
||||||
default:
|
default:
|
||||||
name: Storage
|
name: Tempat Penyimpanan
|
||||||
description: Stores excess items, up to a given capacity. Prioritizes the left
|
description: Menyumpan bentuk yang berlebuhan, hingga kapasitas yang tertentu. Memprioritaskan output dari kiri
|
||||||
output and can be used as an overflow gate.
|
|
||||||
wire_tunnel:
|
wire_tunnel:
|
||||||
default:
|
default:
|
||||||
name: Wire Crossing
|
name: Penyebrangan Kabel
|
||||||
description: Allows to cross two wires without connecting them.
|
description: Memungkinkan untuk menyebrangkan 2 kabel tanpa menyambungkannya.
|
||||||
constant_signal:
|
constant_signal:
|
||||||
default:
|
default:
|
||||||
name: Constant Signal
|
name: Sinyal Konstan
|
||||||
description: Emits a constant signal, which can be either a shape, color or
|
description: Mengeluarkan sinyal yang konstan, dapat berupa bentuk, warna atau boolean (1 / 0).
|
||||||
boolean (1 / 0).
|
|
||||||
lever:
|
lever:
|
||||||
default:
|
default:
|
||||||
name: Switch
|
name: Saklar
|
||||||
description: Can be toggled to emit a boolean signal (1 / 0) on the wires layer,
|
description: Dapat diubah untuk mengeluarkan sinyal boolean (1 / 0) pada lapisan kabel,
|
||||||
which can then be used to control for example an item filter.
|
yang bisa digunakan untuk mengontrol seperti penyaring.
|
||||||
logic_gate:
|
logic_gate:
|
||||||
default:
|
default:
|
||||||
name: AND Gate
|
name: Gerbang AND
|
||||||
description: Emits a boolean "1" if both inputs are truthy. (Truthy means shape,
|
description: Mengeluarkan boolean "1" jika kedua input adalah benar. (Benar berarti sebuah bentuk,
|
||||||
color or boolean "1")
|
warna atau boolean "1")
|
||||||
not:
|
not:
|
||||||
name: NOT Gate
|
name: Gerbang NOT
|
||||||
description: Emits a boolean "1" if the input is not truthy. (Truthy means
|
description: Mengeluarkan boolean "1" jika input adalah tidak benar. (Benar berarti sebuah bentuk,
|
||||||
shape, color or boolean "1")
|
warna atau boolean "1")
|
||||||
xor:
|
xor:
|
||||||
name: XOR Gate
|
name: Gerbang XOR
|
||||||
description: Emits a boolean "1" if one of the inputs is truthy, but not both.
|
description: Mengeluarkan boolean "1" jika kedua input adalah benar, namun bukan keduanya.
|
||||||
(Truthy means shape, color or boolean "1")
|
(Benar berarti sebuah bentuk, warna atau boolean "1")
|
||||||
or:
|
or:
|
||||||
name: OR Gate
|
name: Gerbang OR
|
||||||
description: Emits a boolean "1" if one of the inputs is truthy. (Truthy means
|
description: Mengeluarkan boolean "1" jika satu input adalah benar. (Benar berarti sebuah bentuk,
|
||||||
shape, color or boolean "1")
|
warna atau boolean "1")
|
||||||
transistor:
|
transistor:
|
||||||
default:
|
default:
|
||||||
name: Transistor
|
name: Transistor
|
||||||
description: Forwards the bottom input if the side input is truthy (a shape,
|
description: Melanjutkan sinyal dari input bawah jika input samping adalah benar (sebuah bentuk,
|
||||||
color or "1").
|
warna atau boolean "1")
|
||||||
mirrored:
|
mirrored:
|
||||||
name: Transistor
|
name: Transistor
|
||||||
description: Forwards the bottom input if the side input is truthy (a shape,
|
description: Melanjutkan sinyal dari input bawah jika input samping adalah benar (sebuah bentuk,
|
||||||
color or "1").
|
warna atau boolean "1")
|
||||||
filter:
|
filter:
|
||||||
default:
|
default:
|
||||||
name: Filter
|
name: Filter
|
||||||
description: Connect a signal to route all matching items to the top and the
|
description: Hubungkan sebuah sinyal untuk merutekan semua benda yang cocok ke atas dan
|
||||||
remaining to the right. Can be controlled with boolean signals
|
sisanya ke kanan. Dapat juga dikontrol dengan sinyal boolean
|
||||||
too.
|
|
||||||
display:
|
display:
|
||||||
default:
|
default:
|
||||||
name: Display
|
name: Layar
|
||||||
description: Connect a signal to show it on the display - It can be a shape,
|
description: Hubungkan dengan sebuah sinyal untuk ditunjukkan pada layar - Dapat berupa bentuk,
|
||||||
color or boolean.
|
warna atau boolean.
|
||||||
reader:
|
reader:
|
||||||
default:
|
default:
|
||||||
name: Belt Reader
|
name: Pembaca Sabuk Konveyor
|
||||||
description: Allows to measure the average belt throughput. Outputs the last
|
description: Memungkinkan untuk mengukur rata-rata benda yang melewati sabuk konveyor. Mengeluarkan output benda terakhir
|
||||||
read item on the wires layer (once unlocked).
|
yang dilewati pada lapisan kabel (Setelah terbuka).
|
||||||
analyzer:
|
analyzer:
|
||||||
default:
|
default:
|
||||||
name: Shape Analyzer
|
name: Penganalisa bentuk
|
||||||
description: Analyzes the top right quadrant of the lowest layer of the shape
|
description: Menganalisa perempat bentuk pada kanan atas dan lapisan terbawah
|
||||||
and returns its shape and color.
|
lalu mengeluarkan bentuk dan warnanya.
|
||||||
comparator:
|
comparator:
|
||||||
default:
|
default:
|
||||||
name: Compare
|
name: Pembanding
|
||||||
description: Returns boolean "1" if both signals are exactly equal. Can compare
|
description: Mengeluarkan boolean "1" jika kedua sinya adalah sama. Dapat membandingkan
|
||||||
shapes, items and booleans.
|
Bentuk, warna dan boolean.
|
||||||
virtual_processor:
|
virtual_processor:
|
||||||
default:
|
default:
|
||||||
name: Virtual Cutter
|
name: Pemotong Virtual
|
||||||
description: Virtually cuts the shape into two halves.
|
description: Memotong bentuk secara virtual menjadi dua bagian.
|
||||||
rotater:
|
rotater:
|
||||||
name: Virtual Rotater
|
name: Pemutar Virtual
|
||||||
description: Virtually rotates the shape, both clockwise and counter-clockwise.
|
description: Memutar bentuk secara virtual, searah jarum jam dan tidak searah jarum jam.
|
||||||
unstacker:
|
unstacker:
|
||||||
name: Virtual Unstacker
|
name: Pemisah Tumpukan Virtual
|
||||||
description: Virtually extracts the topmost layer to the right output and the
|
description: Memisahkan lapisan teratas secara virtual ke output kanan dan
|
||||||
remaining ones to the left.
|
sisanya ke output kiri.
|
||||||
stacker:
|
stacker:
|
||||||
name: Virtual Stacker
|
name: Penumpuk Virtual
|
||||||
description: Virtually stacks the right shape onto the left.
|
description: Menumpuk bentuk kanan ke bentuk kiri secara virtual.
|
||||||
painter:
|
painter:
|
||||||
name: Virtual Painter
|
name: Pencat Virtual
|
||||||
description: Virtually paints the shape from the bottom input with the shape on
|
description: Mengecat bentuk dari input bawah dengan warna
|
||||||
the right input.
|
dari input kanan.
|
||||||
item_producer:
|
item_producer:
|
||||||
default:
|
default:
|
||||||
name: Item Producer
|
name: Pembuat Artikel
|
||||||
description: Available in sandbox mode only, outputs the given signal from the
|
description: Hanya tersedia di dalam mode sandbox , Mengeluarkan sinyal yang diberikan dari
|
||||||
wires layer on the regular layer.
|
lapisan kabel ke lapisan biasa.
|
||||||
storyRewards:
|
storyRewards:
|
||||||
reward_cutter_and_trash:
|
reward_cutter_and_trash:
|
||||||
title: Memotong Bentuk
|
title: Memotong Bentuk
|
||||||
desc: You just unlocked the <strong>cutter</strong>, which cuts shapes in half
|
desc: <strong>Pemotong</strong> telah dibuka, yang dapat memotong bentuk menjadi dua
|
||||||
from top to bottom <strong>regardless of its
|
secara vertikal <strong>apapun
|
||||||
orientation</strong>!<br><br>Be sure to get rid of the waste, or
|
orientasinya</strong>!<br><br>Pastikan untuk membuang sisanya, jika
|
||||||
otherwise <strong>it will clog and stall</strong> - For this purpose
|
tidak <strong>ini dapat menghambat dan memperlambat</strong> - karena ini
|
||||||
I have given you the <strong>trash</strong>, which destroys
|
anda diberikan <strong>Tong sampah</strong>, yang menghapus
|
||||||
everything you put into it!
|
semua yang anda masukkan!
|
||||||
reward_rotater:
|
reward_rotater:
|
||||||
title: Memutar
|
title: Memutar
|
||||||
desc: <strong>Pemutar</strong> telah dibuka! Ia memutar bentuk-bentuk searah
|
desc: <strong>Pemutar</strong> telah dibuka! Ia memutar bentuk-bentuk searah
|
||||||
|
|||||||
@ -4,7 +4,7 @@ steamPage:
|
|||||||
discordLinkShort: 公式Discord
|
discordLinkShort: 公式Discord
|
||||||
intro: >-
|
intro: >-
|
||||||
工場の自動化ゲームはお好きですか?それなら間違いないでしょう!
|
工場の自動化ゲームはお好きですか?それなら間違いないでしょう!
|
||||||
|
|
||||||
Shapez.ioは、様々な幾何学的形状を生成するために工場を建設する、落ち着いたゲームです。レベルが上がる毎に生成すべき形はどんどん複雑になり、工場を無限に広がるマップに拡張する必要があります。
|
Shapez.ioは、様々な幾何学的形状を生成するために工場を建設する、落ち着いたゲームです。レベルが上がる毎に生成すべき形はどんどん複雑になり、工場を無限に広がるマップに拡張する必要があります。
|
||||||
|
|
||||||
しかし、それだけでは不十分です。需要は指数関数的に上昇し、より多くの形状を生産する必要があり――"スケーリング"が、唯一の対抗策と成り得ます。最初は形状を加工するだけですが、後々着色も必要になってきます――それには色を抽出して、混ぜ合わせることが必要です!
|
しかし、それだけでは不十分です。需要は指数関数的に上昇し、より多くの形状を生産する必要があり――"スケーリング"が、唯一の対抗策と成り得ます。最初は形状を加工するだけですが、後々着色も必要になってきます――それには色を抽出して、混ぜ合わせることが必要です!
|
||||||
@ -120,18 +120,17 @@ dialogs:
|
|||||||
title: セーブデータのインポートに成功
|
title: セーブデータのインポートに成功
|
||||||
text: セーブデータをインポートしました。
|
text: セーブデータをインポートしました。
|
||||||
|
|
||||||
|
|
||||||
gameLoadFailure:
|
gameLoadFailure:
|
||||||
title: ゲームが壊れています
|
title: ゲームが壊れています
|
||||||
text: >-
|
text: >-
|
||||||
セーブデータのロードに失敗しました:
|
セーブデータのロードに失敗しました:
|
||||||
|
|
||||||
confirmSavegameDelete:
|
confirmSavegameDelete:
|
||||||
title: 削除確認
|
title: 削除確認
|
||||||
text: >-
|
text: >-
|
||||||
本当に削除しますか?<br><br>
|
本当に削除しますか?<br><br>
|
||||||
レベル<savegameLevel>: '<savegameName>'<br><br>
|
レベル<savegameLevel>: '<savegameName>'<br><br>
|
||||||
この操作は取り消しできません!
|
この操作は取り消しできません!
|
||||||
|
|
||||||
savegameDeletionError:
|
savegameDeletionError:
|
||||||
title: 削除に失敗
|
title: 削除に失敗
|
||||||
@ -142,7 +141,6 @@ dialogs:
|
|||||||
title: 再起動が必要
|
title: 再起動が必要
|
||||||
text: 設定を反映するには再起動が必要です
|
text: 設定を反映するには再起動が必要です
|
||||||
|
|
||||||
|
|
||||||
editKeybinding:
|
editKeybinding:
|
||||||
title: キー設定の変更
|
title: キー設定の変更
|
||||||
desc: 割り当てるキーかマウスボタンを押してください。ESCでキャンセルします。
|
desc: 割り当てるキーかマウスボタンを押してください。ESCでキャンセルします。
|
||||||
@ -168,33 +166,26 @@ dialogs:
|
|||||||
desc: >-
|
desc: >-
|
||||||
前回からの変更点:
|
前回からの変更点:
|
||||||
|
|
||||||
|
|
||||||
upgradesIntroduction:
|
upgradesIntroduction:
|
||||||
title: アップグレード解除
|
title: アップグレード解除
|
||||||
desc: すべての納品された形はアップグレードの解除のためにカウントされています。<strong>作った生産ラインを削除しないようにしてください!</strong> アップグレードタブは画面の右上から確認できます。
|
desc: すべての納品された形はアップグレードの解除のためにカウントされています。<strong>作った生産ラインを削除しないようにしてください!</strong> アップグレードタブは画面の右上から確認できます。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
massDeleteConfirm:
|
massDeleteConfirm:
|
||||||
title: 削除確認
|
title: 削除確認
|
||||||
desc: 多数の建造物を削除しようとしています! (<count> 個の選択) 続行しますか?
|
desc: 多数の建造物を削除しようとしています! (<count> 個の選択) 続行しますか?
|
||||||
|
|
||||||
|
|
||||||
massCutConfirm:
|
massCutConfirm:
|
||||||
title: カット確認
|
title: カット確認
|
||||||
desc: 多数の建造物をカットしようとしています! (<count> 個の選択) 続行しますか?
|
desc: 多数の建造物をカットしようとしています! (<count> 個の選択) 続行しますか?
|
||||||
|
|
||||||
|
|
||||||
massCutInsufficientConfirm:
|
massCutInsufficientConfirm:
|
||||||
title: カット確認
|
title: カット確認
|
||||||
desc: 設置コストが不足しています! 続行しますか?
|
desc: 設置コストが不足しています! 続行しますか?
|
||||||
|
|
||||||
|
|
||||||
blueprintsNotUnlocked:
|
blueprintsNotUnlocked:
|
||||||
title: 未解除
|
title: 未解除
|
||||||
desc: レベル12をクリアしてブループリント機能を解除してください!
|
desc: レベル12をクリアしてブループリント機能を解除してください!
|
||||||
|
|
||||||
|
|
||||||
keybindingsIntroduction:
|
keybindingsIntroduction:
|
||||||
title: 便利なキー設定
|
title: 便利なキー設定
|
||||||
desc: >-
|
desc: >-
|
||||||
@ -228,10 +219,8 @@ dialogs:
|
|||||||
entityWarning:
|
entityWarning:
|
||||||
title: パフォーマンスの警告
|
title: パフォーマンスの警告
|
||||||
desc: あなたは沢山の工場を配置しましたが、このゲームは無限の建物を処理できるわけではありません。これは友好的なリマインダですが、より工場をコンパクトにすることに挑戦してみてください。
|
desc: あなたは沢山の工場を配置しましたが、このゲームは無限の建物を処理できるわけではありません。これは友好的なリマインダですが、より工場をコンパクトにすることに挑戦してみてください。
|
||||||
|
|
||||||
ingame:
|
ingame:
|
||||||
|
|
||||||
|
|
||||||
keybindingsOverlay:
|
keybindingsOverlay:
|
||||||
moveMap: マップ移動
|
moveMap: マップ移動
|
||||||
selectBuildings: 範囲選択
|
selectBuildings: 範囲選択
|
||||||
@ -253,7 +242,6 @@ ingame:
|
|||||||
pipette: ピペット
|
pipette: ピペット
|
||||||
switchLayers: レイヤーを変更
|
switchLayers: レイヤーを変更
|
||||||
|
|
||||||
|
|
||||||
colors:
|
colors:
|
||||||
red: 赤
|
red: 赤
|
||||||
green: 緑
|
green: 緑
|
||||||
@ -265,17 +253,10 @@ ingame:
|
|||||||
black: 黒
|
black: 黒
|
||||||
uncolored: 無色
|
uncolored: 無色
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
buildingPlacement:
|
buildingPlacement:
|
||||||
cycleBuildingVariants: <key> キーを押して変更
|
cycleBuildingVariants: <key> キーを押して変更
|
||||||
hotkeyLabel: "ホットキー: <key>"
|
hotkeyLabel: "ホットキー: <key>"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
infoTexts:
|
infoTexts:
|
||||||
speed: スピード
|
speed: スピード
|
||||||
range: レンジ
|
range: レンジ
|
||||||
@ -285,36 +266,26 @@ ingame:
|
|||||||
itemsPerSecondDouble: (x2)
|
itemsPerSecondDouble: (x2)
|
||||||
tiles: <x> タイル
|
tiles: <x> タイル
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
levelCompleteNotification:
|
levelCompleteNotification:
|
||||||
levelTitle: レベル <level>
|
levelTitle: レベル <level>
|
||||||
completed: 完了
|
completed: 完了
|
||||||
unlockText: <reward> を解除!
|
unlockText: <reward> を解除!
|
||||||
buttonNextLevel: 次のレベル
|
buttonNextLevel: 次のレベル
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
newUpgrade: 新しいアップグレードが利用可能です!
|
newUpgrade: 新しいアップグレードが利用可能です!
|
||||||
gameSaved: ゲームをセーブしました。
|
gameSaved: ゲームをセーブしました。
|
||||||
freeplayLevelComplete: レベル <level> をクリアしました!
|
freeplayLevelComplete: レベル <level> をクリアしました!
|
||||||
|
|
||||||
|
|
||||||
shop:
|
shop:
|
||||||
title: アップグレード
|
title: アップグレード
|
||||||
buttonUnlock: アップグレード
|
buttonUnlock: アップグレード
|
||||||
tier: 第 <x> 段階
|
tier: 第 <x> 段階
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
tierLabels:
|
tierLabels:
|
||||||
[I, II, III, IV, V, VI, VII, VIII, IX, X, XI, XII, XIII, XIV, XV, XVI, XVII, XVIII, XIX, XX]
|
[I, II, III, IV, V, VI, VII, VIII, IX, X, XI, XII, XIII, XIV, XV, XVI, XVII, XVIII, XIX, XX]
|
||||||
maximumLevel: 最大レベル (スピード x<currentMult>)
|
maximumLevel: 最大レベル (スピード x<currentMult>)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
statistics:
|
statistics:
|
||||||
title: 統計情報
|
title: 統計情報
|
||||||
dataSources:
|
dataSources:
|
||||||
@ -329,16 +300,14 @@ ingame:
|
|||||||
description: 中央の建造物に納品された形の総数です。
|
description: 中央の建造物に納品された形の総数です。
|
||||||
noShapesProduced: まだ形が生産されていません。
|
noShapesProduced: まだ形が生産されていません。
|
||||||
|
|
||||||
|
|
||||||
shapesDisplayUnits:
|
shapesDisplayUnits:
|
||||||
second: <shapes> / 秒
|
second: <shapes> / 秒
|
||||||
minute: <shapes> / 分
|
minute: <shapes> / 分
|
||||||
hour: <shapes> / 時間
|
hour: <shapes> / 時間
|
||||||
|
|
||||||
|
|
||||||
settingsMenu:
|
settingsMenu:
|
||||||
playtime: プレイ時間
|
playtime: プレイ時間
|
||||||
|
|
||||||
buildingsPlaced: 建造物
|
buildingsPlaced: 建造物
|
||||||
beltsPlaced: ベルト
|
beltsPlaced: ベルト
|
||||||
|
|
||||||
@ -347,17 +316,14 @@ ingame:
|
|||||||
settings: 設定
|
settings: 設定
|
||||||
menu: メニューに戻る
|
menu: メニューに戻る
|
||||||
|
|
||||||
|
|
||||||
tutorialHints:
|
tutorialHints:
|
||||||
title: ヒントが必要ですか?
|
title: ヒントが必要ですか?
|
||||||
showHint: ヒントを見る
|
showHint: ヒントを見る
|
||||||
hideHint: 閉じる
|
hideHint: 閉じる
|
||||||
|
|
||||||
|
|
||||||
blueprintPlacer:
|
blueprintPlacer:
|
||||||
cost: コスト
|
cost: コスト
|
||||||
|
|
||||||
|
|
||||||
waypoints:
|
waypoints:
|
||||||
waypoints: マーカー
|
waypoints: マーカー
|
||||||
hub: HUB
|
hub: HUB
|
||||||
@ -370,7 +336,6 @@ ingame:
|
|||||||
empty: 空
|
empty: 空
|
||||||
copyKey: キーをコピー
|
copyKey: キーをコピー
|
||||||
|
|
||||||
|
|
||||||
interactiveTutorial:
|
interactiveTutorial:
|
||||||
title: チュートリアル
|
title: チュートリアル
|
||||||
hints:
|
hints:
|
||||||
@ -528,7 +493,7 @@ buildings:
|
|||||||
second:
|
second:
|
||||||
name: *wire
|
name: *wire
|
||||||
description: *wire_desc
|
description: *wire_desc
|
||||||
|
|
||||||
wire_tunnel:
|
wire_tunnel:
|
||||||
default:
|
default:
|
||||||
name: &wire_tunnel 交差ワイヤ
|
name: &wire_tunnel 交差ワイヤ
|
||||||
@ -572,13 +537,13 @@ buildings:
|
|||||||
display:
|
display:
|
||||||
default:
|
default:
|
||||||
name: &display ディスプレイ
|
name: &display ディスプレイ
|
||||||
description: >-
|
description: >-
|
||||||
入力された信号をディスプレイに表示します。
|
入力された信号をディスプレイに表示します。
|
||||||
形状、色、真偽値のいずれでも可能です。
|
形状、色、真偽値のいずれでも可能です。
|
||||||
reader:
|
reader:
|
||||||
default:
|
default:
|
||||||
name: &reader ベルトリーダ
|
name: &reader ベルトリーダ
|
||||||
description: >-
|
description: >-
|
||||||
平均スループットを計測できます。 アンロック後は、
|
平均スループットを計測できます。 アンロック後は、
|
||||||
最後に通過したアイテムの情報を出力します。
|
最後に通過したアイテムの情報を出力します。
|
||||||
analyzer:
|
analyzer:
|
||||||
@ -773,7 +738,7 @@ settings:
|
|||||||
title: オートセーブ間隔
|
title: オートセーブ間隔
|
||||||
description: >-
|
description: >-
|
||||||
ゲームが自動的にセーブされる頻度を設定します。無効化することも可能です。
|
ゲームが自動的にセーブされる頻度を設定します。無効化することも可能です。
|
||||||
|
|
||||||
intervals:
|
intervals:
|
||||||
one_minute: 1分
|
one_minute: 1分
|
||||||
two_minutes: 2分
|
two_minutes: 2分
|
||||||
@ -818,7 +783,7 @@ settings:
|
|||||||
soundVolume:
|
soundVolume:
|
||||||
title: 音量(SE)
|
title: 音量(SE)
|
||||||
description: 効果音の音量を設定してください。
|
description: 効果音の音量を設定してください。
|
||||||
|
|
||||||
musicVolume:
|
musicVolume:
|
||||||
title: 音量(BGM)
|
title: 音量(BGM)
|
||||||
description: 音楽の音量を設定してください。
|
description: 音楽の音量を設定してください。
|
||||||
@ -866,7 +831,8 @@ settings:
|
|||||||
これにより、ゲームの見た目もすっきりします。
|
これにより、ゲームの見た目もすっきりします。
|
||||||
clearCursorOnDeleteWhilePlacing:
|
clearCursorOnDeleteWhilePlacing:
|
||||||
title: 右クリックで配置をキャンセル
|
title: 右クリックで配置をキャンセル
|
||||||
description: デフォルトで有効です。建物を設置しているときに右クリックすると、選択中の建物がキャンセルされます。
|
description:
|
||||||
|
デフォルトで有効です。建物を設置しているときに右クリックすると、選択中の建物がキャンセルされます。
|
||||||
無効にすると、建物の設置中に右クリックで建物を削除できます。
|
無効にすると、建物の設置中に右クリックで建物を削除できます。
|
||||||
lowQualityTextures:
|
lowQualityTextures:
|
||||||
title: 低品質のテクスチャ(視認性低下)
|
title: 低品質のテクスチャ(視認性低下)
|
||||||
@ -911,20 +877,20 @@ keybindings:
|
|||||||
mapMoveLeft: 左移動
|
mapMoveLeft: 左移動
|
||||||
mapMoveFaster: より速く移動
|
mapMoveFaster: より速く移動
|
||||||
centerMap: マップ中央移動
|
centerMap: マップ中央移動
|
||||||
|
|
||||||
mapZoomIn: ズームイン
|
mapZoomIn: ズームイン
|
||||||
mapZoomOut: ズームアウト
|
mapZoomOut: ズームアウト
|
||||||
createMarker: マーカー設置
|
createMarker: マーカー設置
|
||||||
|
|
||||||
menuOpenShop: アップグレード
|
menuOpenShop: アップグレード
|
||||||
menuOpenStats: 統計情報
|
menuOpenStats: 統計情報
|
||||||
menuClose: メニューを閉じる
|
menuClose: メニューを閉じる
|
||||||
|
|
||||||
toggleHud: HUD切り替え
|
toggleHud: HUD切り替え
|
||||||
toggleFPSInfo: FPS、デバッグ情報表示切り替え
|
toggleFPSInfo: FPS、デバッグ情報表示切り替え
|
||||||
switchLayers: レイヤを変更
|
switchLayers: レイヤを変更
|
||||||
exportScreenshot: 工場の全体像を画像出力
|
exportScreenshot: 工場の全体像を画像出力
|
||||||
|
|
||||||
# --- Do not translate the values in this section
|
# --- Do not translate the values in this section
|
||||||
belt: *belt
|
belt: *belt
|
||||||
balancer: *balancer
|
balancer: *balancer
|
||||||
@ -951,7 +917,7 @@ keybindings:
|
|||||||
comparator: *comparator
|
comparator: *comparator
|
||||||
item_producer: なんでも抽出機(サンドボックス)
|
item_producer: なんでも抽出機(サンドボックス)
|
||||||
# ---
|
# ---
|
||||||
|
|
||||||
pipette: スポイト
|
pipette: スポイト
|
||||||
rotateWhilePlacing: 回転
|
rotateWhilePlacing: 回転
|
||||||
rotateInverseModifier: >-
|
rotateInverseModifier: >-
|
||||||
|
|||||||
@ -4,7 +4,7 @@ steamPage:
|
|||||||
discordLinkShort: Official Discord
|
discordLinkShort: Official Discord
|
||||||
intro: >-
|
intro: >-
|
||||||
Shapez.io is a relaxed game in which you have to build factories for the
|
Shapez.io is a relaxed game in which you have to build factories for the
|
||||||
automated production of geometric shapes.
|
automated production of geometric shapes.
|
||||||
|
|
||||||
As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map.
|
As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map.
|
||||||
|
|
||||||
|
|||||||
@ -222,7 +222,7 @@ ingame:
|
|||||||
placeBuilding: Plaats gebouw
|
placeBuilding: Plaats gebouw
|
||||||
createMarker: Plaats markering
|
createMarker: Plaats markering
|
||||||
delete: Vernietig
|
delete: Vernietig
|
||||||
pasteLastBlueprint: Plak laatst gekopiëerde blauwdruk
|
pasteLastBlueprint: Plak laatst gekopieerde blauwdruk
|
||||||
lockBeltDirection: Gebruik lopende band planner
|
lockBeltDirection: Gebruik lopende band planner
|
||||||
plannerSwitchSide: Draai de richting van de planner
|
plannerSwitchSide: Draai de richting van de planner
|
||||||
cutSelection: Knip
|
cutSelection: Knip
|
||||||
@ -325,7 +325,7 @@ ingame:
|
|||||||
1_2_conveyor: "Verbind de ontginner met een <strong>lopende band</strong> aan je
|
1_2_conveyor: "Verbind de ontginner met een <strong>lopende band</strong> aan je
|
||||||
hub!<br><br>Tip: <strong>Klik en sleep</strong> de lopende band
|
hub!<br><br>Tip: <strong>Klik en sleep</strong> de lopende band
|
||||||
met je muis!"
|
met je muis!"
|
||||||
1_3_expand: "Dit is <strong>GEEN</strong> nietsdoen-spel! bouw meer ontginners
|
1_3_expand: "Dit is <strong>GEEN</strong> nietsdoen-spel! Bouw meer ontginners
|
||||||
en lopende banden om het doel sneller te behalen.<br><br>Tip:
|
en lopende banden om het doel sneller te behalen.<br><br>Tip:
|
||||||
Houd <strong>SHIFT</strong> ingedrukt om meerdere ontginners te
|
Houd <strong>SHIFT</strong> ingedrukt om meerdere ontginners te
|
||||||
plaatsen en gebruik <strong>R</strong> om ze te draaien."
|
plaatsen en gebruik <strong>R</strong> om ze te draaien."
|
||||||
@ -342,7 +342,7 @@ ingame:
|
|||||||
shapeViewer:
|
shapeViewer:
|
||||||
title: Lagen
|
title: Lagen
|
||||||
empty: Leeg
|
empty: Leeg
|
||||||
copyKey: Kopiëer sleutel
|
copyKey: Kopieer sleutel
|
||||||
connectedMiners:
|
connectedMiners:
|
||||||
one_miner: 1 Miner
|
one_miner: 1 Miner
|
||||||
n_miners: <amount> Miners
|
n_miners: <amount> Miners
|
||||||
@ -861,7 +861,7 @@ settings:
|
|||||||
kunt spelen wanneer je kleurenblind bent.
|
kunt spelen wanneer je kleurenblind bent.
|
||||||
rotationByBuilding:
|
rotationByBuilding:
|
||||||
title: Rotatie per type gebouw
|
title: Rotatie per type gebouw
|
||||||
description: Elk type gebouw onthoud apart de rotatie waarin je het voor het
|
description: Elk type gebouw onthoudt apart de rotatie waarin je het voor het
|
||||||
laatst geplaatst hebt. Dit kan handig zijn wanneer je vaak
|
laatst geplaatst hebt. Dit kan handig zijn wanneer je vaak
|
||||||
tussen verschillende soorten gebouwen wisselt.
|
tussen verschillende soorten gebouwen wisselt.
|
||||||
soundVolume:
|
soundVolume:
|
||||||
|
|||||||
@ -5,7 +5,7 @@ steamPage:
|
|||||||
discordLinkShort: Oficjalny serwer Discord
|
discordLinkShort: Oficjalny serwer Discord
|
||||||
intro: >-
|
intro: >-
|
||||||
Shapez.io jest spokojną grą, której celem jest budowanie automatycznych fabryk
|
Shapez.io jest spokojną grą, której celem jest budowanie automatycznych fabryk
|
||||||
produkujących różne kształty geometryczne.
|
produkujących różne kształty geometryczne.
|
||||||
|
|
||||||
W miarę zwiększania się poziomów, kształty będą stawać się coraz bardziej skomplikowane, a Twoja fabryka będzie musiała się rozpszetrzenić na mapie o nieskończonej wielkości.
|
W miarę zwiększania się poziomów, kształty będą stawać się coraz bardziej skomplikowane, a Twoja fabryka będzie musiała się rozpszetrzenić na mapie o nieskończonej wielkości.
|
||||||
|
|
||||||
@ -705,7 +705,7 @@ storyRewards:
|
|||||||
title: Stały sygnał
|
title: Stały sygnał
|
||||||
desc: >-
|
desc: >-
|
||||||
Właśnie odblokowałeś budynek emitujący <strong>stały sygnał</strong> na warstwie przewodów!
|
Właśnie odblokowałeś budynek emitujący <strong>stały sygnał</strong> na warstwie przewodów!
|
||||||
Jest on przydatny na przykład: do ustawiania <strong>filtrów</strong><br><br>
|
Jest on przydatny na przykład: do ustawiania <strong>filtrów</strong><br><br>
|
||||||
Sygnał może być <strong>kształtem</strong>, <strong>kolorem</strong> lub wartością
|
Sygnał może być <strong>kształtem</strong>, <strong>kolorem</strong> lub wartością
|
||||||
<strong>Prawda/Fałsz</strong>.
|
<strong>Prawda/Fałsz</strong>.
|
||||||
reward_logic_gates:
|
reward_logic_gates:
|
||||||
|
|||||||
@ -4,7 +4,7 @@ steamPage:
|
|||||||
discordLinkShort: Discord Oficial
|
discordLinkShort: Discord Oficial
|
||||||
intro: >-
|
intro: >-
|
||||||
Shapez.io é um jogo relaxante no qual você deve construir fábricas para
|
Shapez.io é um jogo relaxante no qual você deve construir fábricas para
|
||||||
produzir formas geométricas automaticamente.
|
produzir formas geométricas automaticamente.
|
||||||
|
|
||||||
Conforme os níveis aumentam, as formas se tornam mais complexas, e você terá que explorar o mapa infinito.
|
Conforme os níveis aumentam, as formas se tornam mais complexas, e você terá que explorar o mapa infinito.
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ steamPage:
|
|||||||
- Me ajuda! ❤️
|
- Me ajuda! ❤️
|
||||||
title_future: Conteúdo Planejado
|
title_future: Conteúdo Planejado
|
||||||
planned:
|
planned:
|
||||||
- Biblioteca de esquemas (Exclusivo para a versão completa)
|
- Biblioteca de projetos (Exclusivo para a versão completa)
|
||||||
- Conquistas da Steam
|
- Conquistas da Steam
|
||||||
- Modo Puzzle
|
- Modo Puzzle
|
||||||
- Minimapa
|
- Minimapa
|
||||||
@ -94,7 +94,7 @@ mainMenu:
|
|||||||
completa ou baixe o Chrome para obter uma experiência completa.
|
completa ou baixe o Chrome para obter uma experiência completa.
|
||||||
savegameLevel: Nível <x>
|
savegameLevel: Nível <x>
|
||||||
savegameLevelUnknown: Nível desconhecido
|
savegameLevelUnknown: Nível desconhecido
|
||||||
savegameUnnamed: Unnamed
|
savegameUnnamed: Sem nome
|
||||||
dialogs:
|
dialogs:
|
||||||
buttons:
|
buttons:
|
||||||
ok: OK
|
ok: OK
|
||||||
@ -119,9 +119,9 @@ dialogs:
|
|||||||
text: "Houve uma falha ao carregar seu jogo salvo:"
|
text: "Houve uma falha ao carregar seu jogo salvo:"
|
||||||
confirmSavegameDelete:
|
confirmSavegameDelete:
|
||||||
title: Confirmar exclusão
|
title: Confirmar exclusão
|
||||||
text: Are you sure you want to delete the following game?<br><br>
|
text: Tem certeza que deseja deletar o jogo a seguir?<br><br>
|
||||||
'<savegameName>' at level <savegameLevel><br><br> This can not be
|
'<savegameName>' no nível <savegameLevel><br><br> Isso não
|
||||||
undone!
|
pode ser revertido!
|
||||||
savegameDeletionError:
|
savegameDeletionError:
|
||||||
title: Falha ao deletar
|
title: Falha ao deletar
|
||||||
text: "Houve uma falha ao deletar seu jogo salvo:"
|
text: "Houve uma falha ao deletar seu jogo salvo:"
|
||||||
@ -135,14 +135,14 @@ dialogs:
|
|||||||
title: Resetar controles
|
title: Resetar controles
|
||||||
desc: Essa opção deixa os controles nas definições padrão.
|
desc: Essa opção deixa os controles nas definições padrão.
|
||||||
keybindingsResetOk:
|
keybindingsResetOk:
|
||||||
title: Resetar controles
|
title: Controles resetados
|
||||||
desc: Os controles foram resetados para as definições padrão.
|
desc: Os controles foram resetados para as definições padrão.
|
||||||
featureRestriction:
|
featureRestriction:
|
||||||
title: Versão Demo
|
title: Versão Demo
|
||||||
desc: Você tentou acessar um recurso (<feature>) que não está disponível na
|
desc: Você tentou acessar um recurso (<feature>) que não está disponível na
|
||||||
demo. Considere obter a versão completa para a proceder!
|
demo. Considere obter a versão completa para a proceder!
|
||||||
oneSavegameLimit:
|
oneSavegameLimit:
|
||||||
title: Jogo salvo limitado
|
title: Limite de jogos salvos
|
||||||
desc: Você pode ter apenas um jogo salvo por vez na versão demo. Remova o
|
desc: Você pode ter apenas um jogo salvo por vez na versão demo. Remova o
|
||||||
existente ou obtenha a versão completa!
|
existente ou obtenha a versão completa!
|
||||||
updateSummary:
|
updateSummary:
|
||||||
@ -164,7 +164,7 @@ dialogs:
|
|||||||
continuar?
|
continuar?
|
||||||
massCutInsufficientConfirm:
|
massCutInsufficientConfirm:
|
||||||
title: Confirmar Corte?
|
title: Confirmar Corte?
|
||||||
desc: You can not afford to paste this area! Are you sure you want to cut it?
|
desc: Você não conseguirá colar essa área! Tem certeza que quer cortá-la??
|
||||||
blueprintsNotUnlocked:
|
blueprintsNotUnlocked:
|
||||||
title: Não desbloqueado ainda
|
title: Não desbloqueado ainda
|
||||||
desc: Os projetos ainda não foram desbloqueados! Complete mais níveis para
|
desc: Os projetos ainda não foram desbloqueados! Complete mais níveis para
|
||||||
@ -181,8 +181,8 @@ dialogs:
|
|||||||
createMarker:
|
createMarker:
|
||||||
title: Nova Marcação
|
title: Nova Marcação
|
||||||
titleEdit: Editar Marcador
|
titleEdit: Editar Marcador
|
||||||
desc: Give it a meaningful name, you can also include a <strong>short
|
desc: Dê um nome significativo, você também pode incluir um <strong>código
|
||||||
key</strong> of a shape (Which you can generate <link>here</link>)
|
</strong> de uma forma (Você pode gerá-lo <link>aqui</link>)
|
||||||
markerDemoLimit:
|
markerDemoLimit:
|
||||||
desc: Você só pode criar dois marcadores na versão demo. Adquira a versão
|
desc: Você só pode criar dois marcadores na versão demo. Adquira a versão
|
||||||
completa para marcadores ilimitados!
|
completa para marcadores ilimitados!
|
||||||
@ -404,7 +404,7 @@ buildings:
|
|||||||
description: Permite transportar energia.
|
description: Permite transportar energia.
|
||||||
second:
|
second:
|
||||||
name: Fio
|
name: Fio
|
||||||
description: Transfere sinais, que podem ser de itens, cores or binários (1 /
|
description: Transfere sinais, que podem ser de itens, cores ou binários (1 /
|
||||||
0). Fios com cores diferentes não se conectam.
|
0). Fios com cores diferentes não se conectam.
|
||||||
miner:
|
miner:
|
||||||
default:
|
default:
|
||||||
@ -466,9 +466,9 @@ buildings:
|
|||||||
description: Colore as formas na entrada esquerda com a cor da entrada superior.
|
description: Colore as formas na entrada esquerda com a cor da entrada superior.
|
||||||
quad:
|
quad:
|
||||||
name: Pintor (Quádruplo)
|
name: Pintor (Quádruplo)
|
||||||
description: Allows you to color each quadrant of the shape individually. Only
|
description: Permite que você pinte cada quadrante da forma individualmente. Apenas
|
||||||
slots with a <strong>truthy signal</strong> on the wires layer
|
entradas com um <strong>sinal verdadeiro</strong> no plano de fios
|
||||||
will be painted!
|
serão pintadas!
|
||||||
trash:
|
trash:
|
||||||
default:
|
default:
|
||||||
name: Lixo
|
name: Lixo
|
||||||
@ -514,31 +514,31 @@ buildings:
|
|||||||
default:
|
default:
|
||||||
name: Portão E (AND)
|
name: Portão E (AND)
|
||||||
description: Emite um sinal binário "1" se ambas as entradas forem verdadeiras.
|
description: Emite um sinal binário "1" se ambas as entradas forem verdadeiras.
|
||||||
(Ser verdadeira significa receber um sinal de forma, cor or
|
(Ser verdadeira significa receber um sinal de forma, cor ou
|
||||||
binário "1")
|
binário "1")
|
||||||
not:
|
not:
|
||||||
name: Portão NEGAR (NOT)
|
name: Portão NEGAR (NOT)
|
||||||
description: Emite um sinal binário "1" se a entrada for falsa. (Ser verdadeira
|
description: Emite um sinal binário "1" se a entrada for falsa. (Ser verdadeira
|
||||||
significa receber um sinal de forma, cor or binário "1")
|
significa receber um sinal de forma, cor ou binário "1")
|
||||||
xor:
|
xor:
|
||||||
name: Portão OU EXCLUSIVO (XOR)
|
name: Portão OU EXCLUSIVO (XOR)
|
||||||
description: Emite um sinal binário "1" se uma das entradas for verdadeira, mas
|
description: Emite um sinal binário "1" se uma das entradas for verdadeira, mas
|
||||||
não duas. (Ser verdadeira significa receber um sinal de forma,
|
não duas. (Ser verdadeira significa receber um sinal de forma,
|
||||||
cor or binário "1")
|
cor ou binário "1")
|
||||||
or:
|
or:
|
||||||
name: Portão OU (OR)
|
name: Portão OU (OR)
|
||||||
description: Emite um sinal binário "1" se uma das entradas for verdadeira. (Ser
|
description: Emite um sinal binário "1" se uma das entradas for verdadeira. (Ser
|
||||||
verdadeira significa receber um sinal de forma, cor or binário
|
verdadeira significa receber um sinal de forma, cor ou binário
|
||||||
"1")
|
"1")
|
||||||
transistor:
|
transistor:
|
||||||
default:
|
default:
|
||||||
name: Transistor
|
name: Transistor
|
||||||
description: Envia o sinal adiante se a entrada for verdadeira. (Ser verdadeira
|
description: Envia o sinal adiante se a entrada for verdadeira. (Ser verdadeira
|
||||||
significa receber um sinal de forma, cor or binário "1")
|
significa receber um sinal de forma, cor ou binário "1")
|
||||||
mirrored:
|
mirrored:
|
||||||
name: Transistor
|
name: Transistor
|
||||||
description: Envia o sinal adiante se a entrada for verdadeira. (Ser verdadeira
|
description: Envia o sinal adiante se a entrada for verdadeira. (Ser verdadeira
|
||||||
significa receber um sinal de forma, cor or binário "1")
|
significa receber um sinal de forma, cor ou binário "1")
|
||||||
filter:
|
filter:
|
||||||
default:
|
default:
|
||||||
name: Filtro
|
name: Filtro
|
||||||
@ -593,12 +593,12 @@ buildings:
|
|||||||
storyRewards:
|
storyRewards:
|
||||||
reward_cutter_and_trash:
|
reward_cutter_and_trash:
|
||||||
title: Cortando formas
|
title: Cortando formas
|
||||||
desc: You just unlocked the <strong>cutter</strong>, which cuts shapes in half
|
desc: Você acabou de desbloquear o <strong>cortador</strong>, que corta formas pela metade
|
||||||
from top to bottom <strong>regardless of its
|
de cima para baixo <strong>independente de sua
|
||||||
orientation</strong>!<br><br>Be sure to get rid of the waste, or
|
orientação</strong>!<br><br>Lembre-se de se livrar do lixo, caso
|
||||||
otherwise <strong>it will clog and stall</strong> - For this purpose
|
contrário, <strong>a máquina irá entupir</strong> - Por isso
|
||||||
I have given you the <strong>trash</strong>, which destroys
|
eu te dei o <strong>lixo</strong>, que destrói
|
||||||
everything you put into it!
|
tudo que você coloca nele!
|
||||||
reward_rotater:
|
reward_rotater:
|
||||||
title: Rotação
|
title: Rotação
|
||||||
desc: O <strong>rotacionador</strong> foi desbloqueado! Gira as formas no
|
desc: O <strong>rotacionador</strong> foi desbloqueado! Gira as formas no
|
||||||
@ -620,10 +620,10 @@ storyRewards:
|
|||||||
da outra, serão <strong>fundidas</strong>. Caso contrário, a entrada
|
da outra, serão <strong>fundidas</strong>. Caso contrário, a entrada
|
||||||
direita é <strong>empilhada em cima</strong> da entrada esquerda!
|
direita é <strong>empilhada em cima</strong> da entrada esquerda!
|
||||||
reward_splitter:
|
reward_splitter:
|
||||||
title: Distribuidor
|
title: Divisor
|
||||||
desc: You have unlocked a <strong>splitter</strong> variant of the
|
desc: Você desbloqueou uma variante <strong>divisora</strong> do
|
||||||
<strong>balancer</strong> - It accepts one input and splits them
|
<strong>balanceador</strong> - Ela aceita uma entrada e a divide
|
||||||
into two!
|
em duas saídas!
|
||||||
reward_tunnel:
|
reward_tunnel:
|
||||||
title: Túnel
|
title: Túnel
|
||||||
desc: O <strong>túnel</strong> foi desbloqueado - Agora você pode transportar
|
desc: O <strong>túnel</strong> foi desbloqueado - Agora você pode transportar
|
||||||
@ -662,13 +662,13 @@ storyRewards:
|
|||||||
output, so you can also use it as an <strong>overflow gate</strong>!
|
output, so you can also use it as an <strong>overflow gate</strong>!
|
||||||
reward_freeplay:
|
reward_freeplay:
|
||||||
title: Modo Livre
|
title: Modo Livre
|
||||||
desc: You did it! You unlocked the <strong>free-play mode</strong>! This means
|
desc: Você conseguiu! Você desbloqueou o <strong>modo livre</strong>! Isso significa
|
||||||
that shapes are now <strong>randomly</strong> generated!<br><br>
|
que formas agora são geradas <strong>aleatóriamente</strong>!<br><br>
|
||||||
Since the hub will require a <strong>throughput</strong> from now
|
Já que o HUB vai precisar de uma entrada <strong>constante</strong> a partir de
|
||||||
on, I highly recommend to build a machine which automatically
|
agora, eu altamente recomendo que você construa uma máquina que entregue
|
||||||
delivers the requested shape!<br><br> The HUB outputs the requested
|
automaticamente as formas pedidas!<br><br> O HUB emite a forma pedida
|
||||||
shape on the wires layer, so all you have to do is to analyze it and
|
no plano dos fios, então tudo que você precisa fazer é analizá-la e
|
||||||
automatically configure your factory based on that.
|
automaticamente configurar sua fábrica baseado nessa análise.
|
||||||
reward_blueprints:
|
reward_blueprints:
|
||||||
title: Projetos
|
title: Projetos
|
||||||
desc: Agora você pode <strong>copiar e colar</strong> partes de sua fábrica!
|
desc: Agora você pode <strong>copiar e colar</strong> partes de sua fábrica!
|
||||||
@ -706,10 +706,10 @@ storyRewards:
|
|||||||
Ele permite que você rotacione uma forma em 180 graus (Surpresa! :D)
|
Ele permite que você rotacione uma forma em 180 graus (Surpresa! :D)
|
||||||
reward_display:
|
reward_display:
|
||||||
title: Display
|
title: Display
|
||||||
desc: "You have unlocked the <strong>Display</strong> - Connect a signal on the
|
desc: "Você desbloqueou o <strong>Display</strong> - Conecte um sinal no
|
||||||
wires layer to visualize it!<br><br> PS: Did you notice the belt
|
plano de fios para poder vê-lo!<br><br> PS: Você percebeu que ambos o leitor
|
||||||
reader and storage output their last read item? Try showing it on a
|
de esteiras e o armazenamento emitem o último item lido? Tente mostrar
|
||||||
display!"
|
isso em um display!"
|
||||||
reward_constant_signal:
|
reward_constant_signal:
|
||||||
title: Sinal Constante
|
title: Sinal Constante
|
||||||
desc: Você desbloqueou a construção que emite um <strong>sinal
|
desc: Você desbloqueou a construção que emite um <strong>sinal
|
||||||
@ -1082,4 +1082,3 @@ tips:
|
|||||||
- Pressione F4 para mostrar seu FPS e taxa de tiques.
|
- Pressione F4 para mostrar seu FPS e taxa de tiques.
|
||||||
- Pressione F4 duas vezes para mostrar o ladrilho do seu mouse e da câmera.
|
- Pressione F4 duas vezes para mostrar o ladrilho do seu mouse e da câmera.
|
||||||
- Você pode clicar em uma forma fixada na esquerda para tirá-la de lá.
|
- Você pode clicar em uma forma fixada na esquerda para tirá-la de lá.
|
||||||
- null
|
|
||||||
|
|||||||
@ -4,47 +4,49 @@ steamPage:
|
|||||||
complexas num mapa infinito.
|
complexas num mapa infinito.
|
||||||
discordLinkShort: Discord Oficial
|
discordLinkShort: Discord Oficial
|
||||||
intro: >-
|
intro: >-
|
||||||
Shapez.io é um jogo relaxante onde tens que construir fábricas para a produção automatizada de formas geométricas.
|
Shapez.io é um jogo relaxante onde tens de construir fábricas para
|
||||||
|
autumatizar a produção de formas geométricas.
|
||||||
|
|
||||||
Enquanto o nível aumenta, as formas ficam cada vez mais e mais complexas, e tens de te expandir por um mapa infinito.
|
Com o aumento do nível, as formas começam a ser cada vez mais e mais complexas, e tu terás de te expandir num mapa infinito.
|
||||||
|
|
||||||
E como se isso não fosse suficiente, também tens de produzir cada vez mais para satisfazer a demanda - a única coisa que ajuda é aumentar!
|
E como se isso não fosse suficiente, tu também terás de produzir de forma exponencial para satisfazeres as tuas necessidades - a única coisa que ajuda é aumentar!
|
||||||
|
|
||||||
Enquanto só podes processar formas no inicio, vais ter de as colorir mais tarde - para isto vais ter de extrair e juntar cores!
|
Embora no inicio apenas tenhas de processar formas, mais tarde, vais ter de as colorir - para isto terás de extrair e misturar cores!
|
||||||
|
|
||||||
Comprar o jogo na Steam dá-te acesso à versão completa, mas também podes jogar a demo em shapez.io primeiro e decidir depois!
|
Comprar o jogo na Steam dar-te-á acesso à versão completa, mas também podes jogar a versão demo em shapez.io primeiro e decidir mais tarde!
|
||||||
title_advantages: Vantagens Standalone
|
title_advantages: Vantagens da versão completa
|
||||||
advantages:
|
advantages:
|
||||||
- <b>12 Novos Níveis</b> para um total de 26 níveis
|
- <b>12 Novos Níveis</b> para um total de 26 Níves
|
||||||
- <b>18 Novos Edifícios</b> para uma fábrica totalmente automatizada!
|
- <b>18 Novas Construções</b> para uma fábrica totalmente automatizada!
|
||||||
- <b>20 Níveis de Upgrade</b> para muitas horas de diversão!
|
- <b>20 Níveis de Melhoria</b> para muitas horas de diversão!
|
||||||
- <b>Atualização de Fios</b> para uma completamente nova dimensão!
|
- <b>Atualização de Fios</b> para uma dimensão totalmente nova!
|
||||||
- <b>Modo Escuro</b>!
|
- <b>Modo escuro</b>!
|
||||||
- Savegames Ilimitados
|
- Savegames ilimitados
|
||||||
- Marcos Ilimitados
|
- Marcos ilimitados
|
||||||
- Suporta-me! ❤️
|
- Ajuda-me! ❤️
|
||||||
title_future: Conteúdo Planeado
|
title_future: Conteúdo Planeado
|
||||||
planned:
|
planned:
|
||||||
- Blueprint Library (Exclusivo Standalone)
|
- Biblioteca Blueprint (Exclusivo na versão Completa)
|
||||||
- Steam Achievements
|
- Conquistas na Steam
|
||||||
- Modo Puzzle
|
- Modo Puzzle
|
||||||
- Minimap
|
- Minimapa
|
||||||
- Mods
|
- Modos
|
||||||
- Modo Sandbox
|
- Modo Sandbox
|
||||||
- ... e muito mais!
|
- ... e Muito Mais!
|
||||||
title_open_source: Este jogo é código aberto!
|
title_open_source: Este jogo é open source (código aberto)!
|
||||||
title_links: Links
|
title_links: Links
|
||||||
links:
|
links:
|
||||||
discord: Discord Oficial
|
discord: Discord Oficial
|
||||||
roadmap: Roadmap
|
roadmap: Roteiro de desenvolvimento
|
||||||
subreddit: Subreddit
|
subreddit: Subreddit
|
||||||
source_code: Source code (GitHub)
|
source_code: Código Fonte (GitHub)
|
||||||
translate: Ajuda a traduzir
|
translate: Ajuda a Traduzir
|
||||||
text_open_source: >-
|
text_open_source: >-
|
||||||
Qualquer pessoa pode contribuir, estou ativamente envolvido na comunidade e
|
Qualquer um pode contribuir, estou ativamente envolvido na comunidade e
|
||||||
tento rever todas as sugestões e levo o feedback em consideração sempre que possível.
|
tento ver todas as sugestões e ter em consideração o feedback recebido
|
||||||
|
assim que possível.
|
||||||
|
|
||||||
Verifique o meu trello board para o roadmap completo!
|
Segue o meu trello board para veres todo o roteiro de desenvolvimento!
|
||||||
|
|
||||||
global:
|
global:
|
||||||
loading: A Carregar
|
loading: A Carregar
|
||||||
@ -97,7 +99,6 @@ mainMenu:
|
|||||||
madeBy: Criado por <author-link>
|
madeBy: Criado por <author-link>
|
||||||
subreddit: Reddit
|
subreddit: Reddit
|
||||||
savegameUnnamed: Sem Nome
|
savegameUnnamed: Sem Nome
|
||||||
|
|
||||||
dialogs:
|
dialogs:
|
||||||
buttons:
|
buttons:
|
||||||
ok: OK
|
ok: OK
|
||||||
@ -122,8 +123,9 @@ dialogs:
|
|||||||
text: "Erro ao carregar o teu savegame:"
|
text: "Erro ao carregar o teu savegame:"
|
||||||
confirmSavegameDelete:
|
confirmSavegameDelete:
|
||||||
title: Confirmar eliminação
|
title: Confirmar eliminação
|
||||||
text: Tens que queres apagar o seguinte jogo?<br><br>
|
text: >-
|
||||||
'<savegameName>' no Nível <savegameLevel><br><br> Isto não pode
|
Tens a certeza que queres apagar o seguinte jogo?<br><br>
|
||||||
|
'<savegameName>' no nível <savegameLevel><br><br> Isto não pode ser
|
||||||
desfeito!
|
desfeito!
|
||||||
savegameDeletionError:
|
savegameDeletionError:
|
||||||
title: Erro de eliminação
|
title: Erro de eliminação
|
||||||
@ -179,8 +181,8 @@ dialogs:
|
|||||||
class='keybinding'>ALT</code>: Inverte as posições.<br>"
|
class='keybinding'>ALT</code>: Inverte as posições.<br>"
|
||||||
createMarker:
|
createMarker:
|
||||||
title: Novo Marco
|
title: Novo Marco
|
||||||
desc: Dá-lhe um nome com significado, também poderás adicionar <strong>um
|
desc: Dá-lhe um nome com significado, também poderás adicionar um <strong>pequeno
|
||||||
pequeno código</strong> de uma forma (Que podes gerar aqui <link>here</link>)
|
código</strong> de uma forma. (Pode ser gerado <link>aqui</link>)
|
||||||
titleEdit: Editar Marco
|
titleEdit: Editar Marco
|
||||||
markerDemoLimit:
|
markerDemoLimit:
|
||||||
desc: Apenas podes criar dois marcos na versão Demo. Adquire o jogo completo
|
desc: Apenas podes criar dois marcos na versão Demo. Adquire o jogo completo
|
||||||
@ -199,17 +201,18 @@ dialogs:
|
|||||||
desc: Não consegues pagar para colar esta área! Tens a certeza que pretendes
|
desc: Não consegues pagar para colar esta área! Tens a certeza que pretendes
|
||||||
cortá-la?
|
cortá-la?
|
||||||
editSignal:
|
editSignal:
|
||||||
title: Definir Sinal
|
title: Define o Sinal
|
||||||
descItems: "Escolhe um item pre-definido:"
|
descItems: "Escolhe um item pre-definido:"
|
||||||
descShortKey: ... ou entra o <strong>atalho</strong> duma forma (Que podes
|
descShortKey: ... ou insere o <strong>pequeno código</strong> de uma forma (Pode ser
|
||||||
gerar <link>aqui</link>)
|
gerado <link>aqui</link>)
|
||||||
renameSavegame:
|
renameSavegame:
|
||||||
title: Renomear Savegame
|
title: Renomear Savegame
|
||||||
desc: Podes renomear o teu savegame aqui.
|
desc: Podes renomear o teu savegame aqui.
|
||||||
entityWarning:
|
entityWarning:
|
||||||
title: Aviso de Desempenho
|
title: Aviso de Desempenho
|
||||||
desc: Tu colocaste muitos edifícios, isto é apenas um lembrete amigável que o jogo não consegue aguentar com um número infinito de edifícios - Tenta meter as tuas fábricas compactas!
|
desc: Tu colocaste muitas contruções, isto é apenas um lembrete amigável de que
|
||||||
|
o que o jogo não aguenta com um número infinito de contruções - Sendo assim tenta
|
||||||
|
manter as tuas fábricas compactas!
|
||||||
ingame:
|
ingame:
|
||||||
keybindingsOverlay:
|
keybindingsOverlay:
|
||||||
moveMap: Mover
|
moveMap: Mover
|
||||||
@ -295,7 +298,6 @@ ingame:
|
|||||||
second: <shapes> / s
|
second: <shapes> / s
|
||||||
minute: <shapes> / m
|
minute: <shapes> / m
|
||||||
hour: <shapes> / h
|
hour: <shapes> / h
|
||||||
|
|
||||||
settingsMenu:
|
settingsMenu:
|
||||||
playtime: Tempo de jogo
|
playtime: Tempo de jogo
|
||||||
buildingsPlaced: Construções
|
buildingsPlaced: Construções
|
||||||
@ -345,41 +347,41 @@ ingame:
|
|||||||
empty: Vazio
|
empty: Vazio
|
||||||
copyKey: Chave de cópia
|
copyKey: Chave de cópia
|
||||||
connectedMiners:
|
connectedMiners:
|
||||||
one_miner: 1 Minerador
|
one_miner: 1 Extrator
|
||||||
n_miners: <amount> Mineradores
|
n_miners: <amount> Extratores
|
||||||
limited_items: Limitado a <max_throughput>
|
limited_items: Limite de <max_throughput>
|
||||||
watermark:
|
watermark:
|
||||||
title: Versão Demo
|
title: Versão Demo
|
||||||
desc: Clica aqui para ver as vantagens da versão Steam!
|
desc: Clica aqui para veres as vantagens da versão na Steam!
|
||||||
get_on_steam: Compra na steam
|
get_on_steam: Compra na Steam
|
||||||
standaloneAdvantages:
|
standaloneAdvantages:
|
||||||
title: Obtém a versão completa!
|
title: Obtém a versão completa!
|
||||||
no_thanks: Não, obrigado!
|
no_thanks: Não, obrigado!
|
||||||
points:
|
points:
|
||||||
levels:
|
levels:
|
||||||
title: 12 Novos Níveis
|
title: 12 Novos Níveis
|
||||||
desc: Para um total de 26 níveis!
|
desc: Para um total de 26 Níveis!
|
||||||
buildings:
|
buildings:
|
||||||
title: 18 Novos Edifícios
|
title: 18 Novas contruções
|
||||||
desc: Automatiza completamente a tua fábrica!
|
desc: Para uma fábrica totalmente automatizada!
|
||||||
savegames:
|
savegames:
|
||||||
title: Savegames ∞
|
title: Savegames ∞
|
||||||
desc: Quantos o teu coração quiser!
|
desc: Tantos quanto o teu corção desejar!
|
||||||
upgrades:
|
upgrades:
|
||||||
title: 20 Níveis de Upgrades
|
title: 20 Níveis de melhoria
|
||||||
desc: Esta versão demo só tem 5!
|
desc: Nesta versão demo apenas tens 5!
|
||||||
markers:
|
markers:
|
||||||
title: Marcos ∞
|
title: Marcos ∞
|
||||||
desc: Nunca te percas na tua fábrica!
|
desc: Nunca te percas na tua Fábrica!
|
||||||
wires:
|
wires:
|
||||||
title: Fios
|
title: Fios
|
||||||
desc: Uma completamente nova dimensão!
|
desc: Uma dimensão totalmente nova!!
|
||||||
darkmode:
|
darkmode:
|
||||||
title: Modo Escuro
|
title: Modo Escuro
|
||||||
desc: Para de magoar os meus olhos!
|
desc: Não magoes os teus olhos!
|
||||||
support:
|
support:
|
||||||
title: Suporta-me
|
title: Ajuda-me
|
||||||
desc: Eu desenvolvo o jogo no meu tempo livre!
|
desc: Eu desenvolvo este jogo no meu tempo livre!
|
||||||
|
|
||||||
shopUpgrades:
|
shopUpgrades:
|
||||||
belt:
|
belt:
|
||||||
@ -398,7 +400,7 @@ buildings:
|
|||||||
belt:
|
belt:
|
||||||
default:
|
default:
|
||||||
name: Tapete Rolante
|
name: Tapete Rolante
|
||||||
description: Transporta items. Mantém pressionado e arrasta para colocar vários.
|
description: Transporta itens. Mantém pressionado e arrasta para colocar vários.
|
||||||
miner:
|
miner:
|
||||||
default:
|
default:
|
||||||
name: Extrator
|
name: Extrator
|
||||||
@ -431,11 +433,12 @@ buildings:
|
|||||||
description: Roda as formas 90º no sentido dos ponteiros do relógio.
|
description: Roda as formas 90º no sentido dos ponteiros do relógio.
|
||||||
ccw:
|
ccw:
|
||||||
name: Rodar (CCW)
|
name: Rodar (CCW)
|
||||||
description: Roda as formas 90º no sentido contrário ao dos ponteiros do relógio.
|
description: Roda as formas 90º no sentido contrário ao dos ponteiros do
|
||||||
|
relógio.
|
||||||
|
|
||||||
rotate180:
|
rotate180:
|
||||||
name: Rodar (180)
|
name: Rodar (180º)
|
||||||
description: Roda as formas 180º.
|
description: Roda as formas 180º.
|
||||||
stacker:
|
stacker:
|
||||||
default:
|
default:
|
||||||
name: Empilhador
|
name: Empilhador
|
||||||
@ -456,7 +459,9 @@ buildings:
|
|||||||
entrada superior.
|
entrada superior.
|
||||||
quad:
|
quad:
|
||||||
name: Pintor (Quádruplo)
|
name: Pintor (Quádruplo)
|
||||||
description: Pinta cada quadrante da forma geométrica com uma cor diferente. Apenas slots com um <strong>sinal verdadeiro</strong> na camada de fios vão ser pintados!
|
description: Permite colorir cada quadrante da forma individualmente. Apenas
|
||||||
|
entradas com um <strong>sinal verdadeira</strong> na camada de fios
|
||||||
|
irá ser pintada!
|
||||||
mirrored:
|
mirrored:
|
||||||
name: Pintor
|
name: Pintor
|
||||||
description: Pinta a forma geométrica da entrada esquerda com a cor da entrada
|
description: Pinta a forma geométrica da entrada esquerda com a cor da entrada
|
||||||
@ -465,28 +470,30 @@ buildings:
|
|||||||
default:
|
default:
|
||||||
name: Lixo
|
name: Lixo
|
||||||
description: Aceita entradas de todos os lados e destrói-os. Para sempre.
|
description: Aceita entradas de todos os lados e destrói-os. Para sempre.
|
||||||
|
|
||||||
hub:
|
hub:
|
||||||
deliver: Entrega
|
deliver: Entrega
|
||||||
toUnlock: para desbloquear
|
toUnlock: para desbloquear
|
||||||
levelShortcut: NVL
|
levelShortcut: NVL
|
||||||
|
endOfDemo: Fim do Demo
|
||||||
wire:
|
wire:
|
||||||
default:
|
default:
|
||||||
name: Fio Elétrico
|
name: Fio Elétrico
|
||||||
description: Transfere sinais, que podem ser itens, cores ou boleanos (1 / 0). Fios com cores diferentes não conectam.
|
description: Tranfere sinais, que podem ser itens, cores ou um sinal binário (1 ou 0).
|
||||||
|
Fios de cores diferestes não se conectam.
|
||||||
second:
|
second:
|
||||||
name: Fio Elétrico
|
name: Fio Elétrico
|
||||||
description: Transfere sinais, que podem ser itens, cores ou boleanos (1 / 0). Fios com cores diferentes não conectam.
|
description: Tranfere sinais, que podem ser itens, cores ou um sinal binário (1 ou 0).
|
||||||
|
Fios de cores diferestes não se conectam.
|
||||||
balancer:
|
balancer:
|
||||||
default:
|
default:
|
||||||
name: Balanceador
|
name: Distribuidor
|
||||||
description: Multifuncional - Distribui uniformemente todas as entradas para todas as saídas.
|
description: Multifunções - Distribui igualmente todas as entradas por todas as saídas.
|
||||||
merger:
|
merger:
|
||||||
name: Junção (compacto)
|
name: Misturador (comp.)
|
||||||
description: Junta um tapete rolante em dois.
|
description: Junta dois tapetes rolantes num só.
|
||||||
merger-inverse:
|
merger-inverse:
|
||||||
name: Junção (compacto)
|
name: Misturador (comp.)
|
||||||
description: Junta um tapete rolante em dois.
|
description: Junta dois tapetes rolantes num só.
|
||||||
splitter:
|
splitter:
|
||||||
name: Divisor (compacto)
|
name: Divisor (compacto)
|
||||||
description: Divide um tapete rolante em dois.
|
description: Divide um tapete rolante em dois.
|
||||||
@ -494,99 +501,115 @@ buildings:
|
|||||||
name: Divisor (compacto)
|
name: Divisor (compacto)
|
||||||
description: Divide um tapete rolante em dois.
|
description: Divide um tapete rolante em dois.
|
||||||
storage:
|
storage:
|
||||||
default:
|
default:
|
||||||
name: Armazém
|
name: Armazém
|
||||||
description: >-
|
description: Armazena itens em excesso, até uma determinada capacidade. Dá prioridade à saída da
|
||||||
Guarda itens em excesso, até uma quantidade determinada. Prioritiza a entrada esquerda
|
esquerda e pode ser usado como uma porta de transbordo.
|
||||||
e pode ser usada como um portão de transbordar.
|
|
||||||
wire_tunnel:
|
wire_tunnel:
|
||||||
default:
|
default:
|
||||||
name: Túnel de Fio
|
name: Túnel de Fios
|
||||||
description: Permite cruzar dois fios sem os conectar.
|
description: Permite que dois fios cruzem sem conectarem-se um ao outro.
|
||||||
constant_signal:
|
constant_signal:
|
||||||
default:
|
default:
|
||||||
name: Sinal constante
|
name: Sinal Constante
|
||||||
description: >-
|
description: Emite um sinal constante , que pode ser uma forma, cor ou
|
||||||
Emite um sinal constante, que pode ser uma forma, cor ou um booleano (1 / 0).
|
um sinal binário (1 ou 0).
|
||||||
lever:
|
lever:
|
||||||
default:
|
default:
|
||||||
name: Interruptor
|
name: Interruptor
|
||||||
description: >-
|
description: Pode emitir alternadamente um sinal binário (1 ou 0) na camada de fios,
|
||||||
Pode ser alternado para emitir um sinal booleano (1 / 0) na camada de fios, que pode então ser usada
|
que pode posteriormente ser usado, por exemplo, num filtro de itens.
|
||||||
para controlar por exemplo um filtro de itens.
|
|
||||||
logic_gate:
|
logic_gate:
|
||||||
default:
|
default:
|
||||||
name: Portão AND
|
name: Portão AND
|
||||||
description: Emite um booleano "1" se ambas as entradas são verdadeiras. (Verdadeiro significa forma, cor ou booleano "1")
|
description: >-
|
||||||
|
Emite um sinal binário "1" se ambas as entradas forem verdadeiras. (Verdadeiro significa:
|
||||||
|
forma, cor ou sinal binário "1")
|
||||||
not:
|
not:
|
||||||
name: Portão NOT
|
name: Portão NOT
|
||||||
description: Emite um booleano "1" se a entrada não é verdadeira. (Verdadeiro significa forma, cor ou booleano "1")
|
description: >-
|
||||||
|
Emite um sinal binário "1" se a entrada não for verdadeira. (Verdadeiro significa:
|
||||||
|
forma, cor ou sinal binário "1")
|
||||||
xor:
|
xor:
|
||||||
name: Portão XOR
|
name: Portão XOR
|
||||||
description: Emite um booleano "1" se uma das entradas é verdadeira, mas não as duas. (Verdadeiro significa forma, cor ou booleano "1")
|
description: >-
|
||||||
|
Emite um sinal binário "1" se uma das entradas for verdadeira, mas não as duas. (Verdadeiro significa:
|
||||||
|
forma, cor ou sinal binário "1")
|
||||||
or:
|
or:
|
||||||
name: Portão OR
|
name: Portão OR
|
||||||
description: Emite um booleano "1" se uma entrada é verdadeira. (Verdadeiro significa forma, cor ou booleano "1")
|
description: >-
|
||||||
|
Emite um sinal binário "1" se uma entrada é verdadeira. (Verdadeiro significa:
|
||||||
|
forma, cor ou sinal binário "1")
|
||||||
transistor:
|
transistor:
|
||||||
default:
|
default:
|
||||||
name: Transistor
|
name: Transístor
|
||||||
description: Encaminha a entrada inferior se a entrada lateral for verdade (uma forma, cor ou "1").
|
description: Encaminha a entrada inferior se a entrada lateral for verdade
|
||||||
|
(uma forma, cor ou "1").
|
||||||
|
|
||||||
mirrored:
|
mirrored:
|
||||||
name: Transistor
|
name: Transístor
|
||||||
description: Encaminha a entrada inferior se a entrada lateral for verdade (uma forma, cor ou "1").
|
description: Encaminha a entrada inferior se a entrada lateral for verdade
|
||||||
|
(uma forma, cor ou "1").
|
||||||
filter:
|
filter:
|
||||||
default:
|
default:
|
||||||
name: Filtro
|
name: Filtro de Itens
|
||||||
description: Conecta um sinal para encaminhar todos os itens correspondentes para o topo e o resto
|
description: Conecta um sinal que irá encaminhar todos os itens correspondentes
|
||||||
para a direita. Pode ser controlado com sinais booleanos também.
|
para o topo e os restantes para a direita. Também pode ser
|
||||||
|
controlado com sinais binários.
|
||||||
display:
|
display:
|
||||||
default:
|
default:
|
||||||
name: Display
|
name: Visor
|
||||||
description: Conecta um sinal para mostrar no display - Pode ser uma forma, cor ou
|
description: Conecta um sinal para mostrar no Visor - Pode ser uma forma, cor
|
||||||
booleano.
|
ou um sinal binário.
|
||||||
reader:
|
reader:
|
||||||
default:
|
default:
|
||||||
name: Leitor de Tapete
|
name: Leitor de Tapete
|
||||||
description: Permite medir o rendimento do tapete. Produz o último item lido na camada de
|
description:
|
||||||
fios (quando desbloqueada).
|
Permite medir a passagem média de itens no tapete. Fornece o último item lido na camada de
|
||||||
|
fios (quando desbloqueada).
|
||||||
analyzer:
|
analyzer:
|
||||||
default:
|
default:
|
||||||
name: Analizador de Forma
|
name: Analizador de Forma
|
||||||
description: Analiza o quadrante do topo direito da camada mais baixa da forma e produz
|
description: Analiza o quadrante superior direito da camada mais baixa da forma e retorna
|
||||||
a forma ou cor.
|
a forma ou cor.
|
||||||
comparator:
|
comparator:
|
||||||
default:
|
default:
|
||||||
name: Comparar
|
name: Comparador
|
||||||
description: Produz o booleano "1" se ambos os itens são exatamente iguais. Pode comparar formas,
|
description:
|
||||||
itens e booleanos.
|
Produz o sinal binário "1" se ambos os itens são exatamente iguais. Pode comparar formas,
|
||||||
|
itens e sinais binários.
|
||||||
virtual_processor:
|
virtual_processor:
|
||||||
default:
|
default:
|
||||||
name: Cortador Virtual
|
name: Cortador Virtual
|
||||||
description: Computa
|
description: Virtualmente, corta as formas em duas metades.
|
||||||
rotater:
|
rotater:
|
||||||
name: Rodar Virtual
|
name: Rodador Virtual
|
||||||
description: Roda virtualmente as formas 90º no sentido dos ponteiros do relógio.
|
description: Virtualmente, roda a forma tanto no sentido horário quanto no anti-horário.
|
||||||
unstacker:
|
unstacker:
|
||||||
name: Desempilhador Virtual
|
name: Desempilhador Virtual
|
||||||
description: Produz a camada no topo para a direita, e o resto para esquerda.
|
description: Virtualmente, remove a camada do topo para a saída da direita
|
||||||
|
e o restante para a da esquerda.
|
||||||
stacker:
|
stacker:
|
||||||
name: Empilhador Virtual
|
name: Empilhador Virtual
|
||||||
description: Empilha virtualmente o item da direita em cima do item da esquerda.
|
description: Virtualmente empilhada a forma da direita em cima do item da esquerda.
|
||||||
painter:
|
painter:
|
||||||
name: Pintor Virtual
|
name: Pintor Virtual
|
||||||
description: Pinta virtualmente a forma de baixo com a forma da direita.
|
description: Virtualmente, pinta a forma a forma da entrada de baixo
|
||||||
|
com o item da entrada da direita.
|
||||||
item_producer:
|
item_producer:
|
||||||
default:
|
default:
|
||||||
name: Produtor de Itens
|
name: Produtor de Itens
|
||||||
description: Disponível apenas no modo sandbox, produz o sinal dado da camada de fios na camala normal.
|
description: Disponível apenas no modo sandbox, produz o sinal dado na
|
||||||
|
camada de fios na camada normal.
|
||||||
storyRewards:
|
storyRewards:
|
||||||
reward_cutter_and_trash:
|
reward_cutter_and_trash:
|
||||||
title: Corte de formas
|
title: Corte de formas
|
||||||
desc: Acabaste de desbloquear o <strong>Cortador</strong>, que corta as formas
|
desc: Acabaste de desbloquear o <strong>cortador</strong>, que corta as formas ao meio
|
||||||
geométricas ao meio de cima para baixo <strong>independentemente da orientação</strong>!<br><br>Certifica-te de que te
|
de cima para baixo <strong>independentemente da sua
|
||||||
livras do desperdício, caso contrário <strong>encravará</strong> -
|
orientação</strong>!<br><br>Certefica-te de que te livras do desperdício,
|
||||||
Por isso, dou-te um lixo, que destruirá tudo o que lá colocares!
|
caso contrário <strong>irá encravar e parar</strong> - Para este propósito
|
||||||
|
eu dei-te um <strong>lixo</strong>, que destrói
|
||||||
|
tudo o que lá colocares!
|
||||||
reward_rotater:
|
reward_rotater:
|
||||||
title: Rotação
|
title: Rotação
|
||||||
desc: O <strong>Rodador</strong> foi desbloqueado! Ele roda as formas
|
desc: O <strong>Rodador</strong> foi desbloqueado! Ele roda as formas
|
||||||
@ -610,8 +633,9 @@ storyRewards:
|
|||||||
esquerda!
|
esquerda!
|
||||||
reward_splitter:
|
reward_splitter:
|
||||||
title: Divisor
|
title: Divisor
|
||||||
desc: Desbloqueaste o <strong>divisor</strong>, variante do
|
desc: Desbloqueaste o <strong>dvisor</strong> uma variante do
|
||||||
<strong>balanceador</strong> - Aceita uma entrada e divide-a em duas!
|
<strong>distribuidor</strong> - Aceita uma entradae divide-a
|
||||||
|
em duas!
|
||||||
reward_tunnel:
|
reward_tunnel:
|
||||||
title: Túnel
|
title: Túnel
|
||||||
desc: O <strong>Túnel</strong> foi desbloqueado - Com ele podes passar itens
|
desc: O <strong>Túnel</strong> foi desbloqueado - Com ele podes passar itens
|
||||||
@ -624,94 +648,120 @@ storyRewards:
|
|||||||
variantes</strong>!
|
variantes</strong>!
|
||||||
reward_miner_chainable:
|
reward_miner_chainable:
|
||||||
title: Extração em série
|
title: Extração em série
|
||||||
desc: >-
|
desc: "Desbloqueaste o <strong>extrator em séire</strong>! Permite
|
||||||
Desbloqueaste o <strong>Extrator em série</strong>! Permite <strong>enviar
|
<strong>enviar os recursos</strong> para outros extratores, sendo assim
|
||||||
o recurso extraído</strong> para outros extratores, permitindo uma
|
permite uma extração de recursos mais eficiente!<br><br> PS: O extrator
|
||||||
extração mais eficiente!<br><br> PS: O velho extrator já foi trocado na tua toolbar!
|
antigo já foi trocado na tua lista de construções!"
|
||||||
reward_underground_belt_tier_2:
|
reward_underground_belt_tier_2:
|
||||||
title: Túnel Nível II
|
title: Túnel Nível II
|
||||||
desc: Desbloqueaste uma nova variante do <strong>Túnel</strong> - Tem um <strong>maior alcance</strong>, e podes interlaçar as duas variantes entre si!
|
desc: Desbloqueaste uma nova variante do <strong>Túnel</strong> - Tem um
|
||||||
|
<strong>maior alcance</strong>, e podes interlaçar as duas variantes
|
||||||
|
entre si!
|
||||||
reward_cutter_quad:
|
reward_cutter_quad:
|
||||||
title: Corte quádruplo
|
title: Corte quádruplo
|
||||||
desc: Desbloqueaste a variante do <strong>Cortador</strong> - Permite cortar formas geométricas em <strong>quatro partes</strong> em vez de apenas duas!
|
desc: Desbloqueaste a variante do <strong>Cortador</strong> - Permite cortar
|
||||||
|
formas geométricas em <strong>quatro partes</strong> em vez de
|
||||||
|
apenas duas!
|
||||||
reward_painter_double:
|
reward_painter_double:
|
||||||
title: Pintura dupla
|
title: Pintura dupla
|
||||||
desc: Desbloqueaste uma variante do <strong>Pintor</strong> - Funciona como um pintor normal mas processa <strong>duas formas ao mesmo tempo</strong> consumindo apenas uma cor em vez de duas!
|
desc: Desbloqueaste uma variante do <strong>Pintor</strong> - Funciona como um
|
||||||
|
pintor normal mas processa <strong>duas formas ao mesmo
|
||||||
|
tempo</strong> consumindo apenas uma cor em vez de duas!
|
||||||
reward_storage:
|
reward_storage:
|
||||||
title: Armazém
|
title: Armazém
|
||||||
desc: Desbloqueaste uma variante do <strong>Lixo</strong> - Permite armazenar items até uma determinada capacidade!<br><br> Prioritiza a saída esquerda, por isso também o podes usar como um portão de transbordar.
|
desc: Desbloqueaste uma variante do <strong>lixo</strong> - Permite armazenar
|
||||||
|
itens, até uma determinada capacidade!<br><br> Dá prioridade à saída da
|
||||||
|
esquerda e pode ser usado como uma <strong>porta de transbordo</strong>!
|
||||||
reward_freeplay:
|
reward_freeplay:
|
||||||
title: Jogo livre
|
title: Jogo livre
|
||||||
desc: Conseguiste! Desbloqueaste o <strong>modo jogo livre</strong>! Isto significa que agora as formas são geradas <strong>aleatoriamente</strong>!<br><br>
|
desc: Conseguiste! Desbloqueaste o <strong>modo jogo livre</strong>! Isto
|
||||||
Como o edifício central vai precisar de uma <strong>taxa de transferência</strong> a partir de
|
significa que agora as formas são geradas <strong>aleatoriamente</strong>!<br><br>
|
||||||
agora, eu recomendo contruires uma máquina que automaticamente
|
Como o edifício central vai precisar de uma <strong>taxa de rendimento</strong> a partir
|
||||||
entrega a forma pedida!<br><br> O edifício central produz a forma pedida na camada de fios,
|
de agora, recomendo vivamente a contruires uma máquina que, automaticamente,
|
||||||
então tudo o que tens de fazer é analizar-la e automaticamente configurar a tua fábrica à volta disso.
|
entraga as formas pedidas!<br><br> O edifício central emite a forma pedida
|
||||||
|
na camada de fios,sendo assim tudo o que tens a fazer é analiza-la e
|
||||||
|
automaticamente configurares a tua fábrica baseada nisso.
|
||||||
reward_blueprints:
|
reward_blueprints:
|
||||||
title: Projetos
|
title: Projetos
|
||||||
desc: Agora podes <strong>copiar e colar</strong> partes da tua fábrica! Seleciona uma área (Mantém pressionado CTRL e arrasta com o rato), e pressiona 'C' para copiar.<br><br>Colar não é <strong>gratuito</strong>, precisas de produzir <strong>formas projeto</strong> para o pagares! (Aquelas que acabaste de entregar).
|
desc: Agora podes <strong>copiar e colar</strong> partes da tua fábrica!
|
||||||
|
Seleciona uma área (Mantém pressionado CTRL e arrasta com o rato), e
|
||||||
|
pressiona 'C' para copiar.<br><br>Colar não é
|
||||||
|
<strong>gratuito</strong>, precisas de produzir <strong>formas
|
||||||
|
projeto</strong> para o pagares! (Aquelas que acabaste de entregar).
|
||||||
no_reward:
|
no_reward:
|
||||||
title: Próximo nível
|
title: Próximo nível
|
||||||
desc: >-
|
desc: "Este nível não te deu nenhuma recompensa, mas o próximo dará! <br><br>
|
||||||
Este nível não te deu nenhuma recompensa, mas o próximo dará! <br><br> PS: É melhor não destruires a tua fábrica atual - Precisarás de <strong>todas</strong> essas formas no futuro para <strong>desbloquear upgrades</strong>!
|
PS: É melhor não destruires a tua fábrica atual - Precisarás de
|
||||||
|
<strong>todas</strong> essas formas no futuro para
|
||||||
|
<strong>desbloquear upgrades</strong>!"
|
||||||
no_reward_freeplay:
|
no_reward_freeplay:
|
||||||
title: Próximo nível
|
title: Próximo nível
|
||||||
desc: Parabéns! Já agora, está planeado mais conteúdo para o jogo completo!
|
desc: Parabéns! Já agora, está planeado mais conteúdo para o jogo completo!
|
||||||
reward_balancer:
|
reward_balancer:
|
||||||
title: Balanceador
|
title: Distribuidor
|
||||||
desc: O multifunctional <strong>balanceador</strong> foi desbloqueado - Pode ser usado
|
desc: O multifunctional <strong>distribuidor</strong> foi desbloqueado - Pode
|
||||||
para construir fábricas maiores <strong>dividindo e juntando itens</strong>
|
ser usado para construbir fábricas maiores <strong>dividindo e juntando
|
||||||
por vários tapetes!<br><br>
|
itens</strong> por vários tapetes rolantes!<br><br>
|
||||||
reward_merger:
|
reward_merger:
|
||||||
title: Junção (Compacto)
|
title: Misturador (compacto)
|
||||||
desc: Destravaste a <strong>junção</strong> variante do
|
desc: Desbloqueaste um <strong>misturador</strong>, uma variante do
|
||||||
<strong>balanceador</strong> - Aceita duas entradas e junta-as num só tapete!
|
<strong>distribuidor</strong> - Aceita duas entradas e junta-as num só
|
||||||
|
tapete rolante!
|
||||||
reward_belt_reader:
|
reward_belt_reader:
|
||||||
title: Leitor de Tapete
|
title: Leitor de Tapete
|
||||||
desc: Tu desbloqueaste o <strong>leitor de tapete</strong>! Permite-te medir
|
desc: Desbloqueaste o <strong>leitor de tapete</strong>! Permite-te medires
|
||||||
o rendimento dum tapete.<br><br>E espera até desbloqueares fios - aí é que é super útil!
|
a passagem média de itens no tapete.<br><br>E espera por desbloqueares
|
||||||
|
os fios - aí é que vão ser bastante úteis!
|
||||||
reward_rotater_180:
|
reward_rotater_180:
|
||||||
title: Rodar (180 degrees)
|
title: Rodar (180º)
|
||||||
desc: Acabaste de desbloquear a versão de 180º do <strong>Rotador</strong>! - Deixa-te rodar formas por 180º (Surpresa! :D)
|
desc: Desbloqueaste o <strong>rodador</strong> de 180 graus! - Permite-te
|
||||||
|
rodares formas 180 graus (Surpresa! :D)
|
||||||
reward_display:
|
reward_display:
|
||||||
title: Display
|
title: Visor
|
||||||
desc: >-
|
desc: "Desbloqueaste o <strong>Visor</strong> - Conecta um sinal na
|
||||||
Destravaste o <strong>Display</strong> - Conecta um sinal elétrico na camada de fios para visualizar-lo!<br><br> PS:
|
camada de fios para o visualizares!<br><br> PS: Reparaste que o leitor
|
||||||
Reparaste que o leitor de tapetes e o armazém produz o último item lido por eles na camada de fios? Tenta mostrar isso num display!
|
de tapete e o armazém emitem o último item lido por eles? tenta mostrar isso
|
||||||
|
num visor!"
|
||||||
reward_constant_signal:
|
reward_constant_signal:
|
||||||
title: Sinal Constante
|
title: Sinal Constante
|
||||||
desc: Acabaste de destravar o edifício <strong>sinal constante</strong> na camada de fios!
|
desc: Desbloqueaste o <strong>sinal constante</strong> contruido na camada
|
||||||
Isto é útil conectado a um <strong>filtro de itens</strong> por exemplo.<br><br>
|
de fios! Isto é útil conectado com um <strong>filtro de itens</strong>
|
||||||
O sinal constante pode emitir uma <strong>forma</strong>,
|
por exemplo.<br><br> O sinal constante pode emitir uma
|
||||||
<strong>cor</strong> ou um <strong>booleano</strong> (1 / 0).
|
<strong>forma</strong>, <strong>cor</strong> ou
|
||||||
|
<strong>sinal binário</strong> (1 ou 0).
|
||||||
reward_logic_gates:
|
reward_logic_gates:
|
||||||
title: Portões Lógicos
|
title: Portões Lógicos
|
||||||
desc: "Tu desbloqueaste os <strong>portões lógicos</strong>! Não tens de estar excitado sobre isto,
|
desc: Desbloqueaste os <strong>portões lógicos</strong>! N tens de te excitar
|
||||||
mas é na verdade super fixe!<br><br> Com estes portões agora podes fazer operações booleanas
|
com isto, mas é realmente super fixe!<br><br> Com estes portões
|
||||||
AND, OR, XOR e NOT!"
|
agora podes realizar operações AND, OR, XOR and NOT.<br><br> Como um
|
||||||
|
bónus anteriormente já de dei um <strong>transístor</strong>!
|
||||||
reward_virtual_processing:
|
reward_virtual_processing:
|
||||||
title: Processamento Virtual
|
title: Processamento Virtual
|
||||||
desc: >-
|
desc: Acadei de te dar um monte de novas construções, que te vão permitir
|
||||||
Acabei de te dar um monte de novos edifícios que permitem-te
|
<strong>simular o processamento de formas</strong>!<br><br> Agora podes
|
||||||
<strong>simular o processamento de formas</strong>!<br><br> Podes agora
|
simular um cortador,um rodador, um empilhador e muito mais na camada de fios!
|
||||||
simular um cortador, rodar, empilhador e mais na camada de fios!<br><br>
|
Com isto, agora tens três opções para continuares o jogo:<br><br> -
|
||||||
Com isto tens agora três opções para continuar o jogo:<br><br> - Construir
|
Construir uma <strong>máquina automática</strong> para criar qualquer forma
|
||||||
uma <strong>máquina automatizada</strong> para criar qualquer forma requerida
|
possível pedida pelo Edifício Central (Reconmento-te a experimentares!).<br><br> - Contruir
|
||||||
pelo edifício central (Isto é fixe, eu prometo!).<br><br> - Construir algo fixe com
|
algo fixe com os fios.<br><br> - Continuar a jogar
|
||||||
fios.<br><br> - Continuar a jogar regularmente. Seja lá o que escolheres, lembra-te de te divertires!
|
regularmente.<br><br> Independentemente da tua escolha, lembra-te de te divertires!
|
||||||
reward_wires_painter_and_levers:
|
reward_wires_painter_and_levers:
|
||||||
title: Fios e Pintor Quádruplo
|
title: Fios & Pintor Quádruplo
|
||||||
desc: "Acabaste de desbloquear a <strong>Camada de Fios</strong>: É uma camada separada
|
desc: "Desbloquaste a <strong>Camada de Fios</strong>: É uma camada separada
|
||||||
no topo da camada normal e introduz um monte de novas mecânicas!<br><br>
|
no topo da camada normal e introduz um monte de novas
|
||||||
Para o início eu dei-te o <strong>Pintor Quádruplo</strong> - Conecta os slots que queres pintar na
|
mecânicas!<br><br> Para o inicio eu dei-te o <strong>Pintor
|
||||||
camada de fios!<br><br> Para trocar para a camada de fios, pressiona <strong>E</strong>."
|
Quádruplo</strong> - Conecta as entradasque queres pintar na
|
||||||
|
camada de fios!<br><br> Para trocares para a camada de fios, pressiona a tecla
|
||||||
|
<strong>E</strong>."
|
||||||
reward_filter:
|
reward_filter:
|
||||||
title: Filtro de Itens
|
title: Filtro de Itens
|
||||||
desc: Desbloqueaste o <strong>Filtro de Itens</strong>! Vai mandar items para a saída de topo ou para a saída da direita
|
desc: Desbloquaste o <strong>Filtro de Itens</strong>! Vai mandar itens ou
|
||||||
dependendo se são iguais ao sinal da camada de fios.<br><br> Também podes passar um sinal booleano (1 / 0) para ativar-lo ou desativar-lo completamente.
|
para o topo ou para a saída da esquerda dependendo depending se são iguais ao
|
||||||
|
sinal da camada de fios ou não.<br><br> Também podes passar um
|
||||||
|
sinal binário (1 ou 0) para ativa-lo ou desativa-lo totalmente.
|
||||||
reward_demo_end:
|
reward_demo_end:
|
||||||
title: Fim da Demo
|
title: Fim da Demo
|
||||||
desc: Chegaste ao fim da versão demo!
|
desc: Tu chegaste ao fim da versão demo!
|
||||||
settings:
|
settings:
|
||||||
title: Definições
|
title: Definições
|
||||||
categories:
|
categories:
|
||||||
@ -727,8 +777,9 @@ settings:
|
|||||||
labels:
|
labels:
|
||||||
uiScale:
|
uiScale:
|
||||||
title: Escala da interface
|
title: Escala da interface
|
||||||
description: >-
|
description: Altera o tamanho da interface do utilizador. A interface será
|
||||||
Altera o tamanho da interface do utilizador. A interface será redimensionada com base na resolução do teu dispositivo, mas esta definição controla a escala.
|
redimensionada com base na resolução do teu dispositivo, mas
|
||||||
|
esta definição controla a escala.
|
||||||
scales:
|
scales:
|
||||||
super_small: Super pequeno
|
super_small: Super pequeno
|
||||||
small: Pequeno
|
small: Pequeno
|
||||||
@ -737,8 +788,7 @@ settings:
|
|||||||
huge: Enorme
|
huge: Enorme
|
||||||
scrollWheelSensitivity:
|
scrollWheelSensitivity:
|
||||||
title: Sensibilidade do zoom
|
title: Sensibilidade do zoom
|
||||||
description: >-
|
description: Define o quão sensível é o zoom (Roda do rato ou trackpado).
|
||||||
Define o quão sensível é o zoom (Roda do rato ou trackpad).
|
|
||||||
sensitivity:
|
sensitivity:
|
||||||
super_slow: Muito lento
|
super_slow: Muito lento
|
||||||
slow: Lento
|
slow: Lento
|
||||||
@ -747,39 +797,41 @@ settings:
|
|||||||
super_fast: Muito rápido
|
super_fast: Muito rápido
|
||||||
language:
|
language:
|
||||||
title: Língua
|
title: Língua
|
||||||
description: >-
|
description: Muda a língua. Todas as traduções são contribuições dos
|
||||||
Muda a língua. Todas as traduções são contribuições dos utilizadores e podem estar incompletas!
|
utilizadores e podem estar incompletas!
|
||||||
fullscreen:
|
fullscreen:
|
||||||
title: Ecrã inteiro
|
title: Ecrã inteiro
|
||||||
description: >-
|
description: É recomendado jogar o jogo em ecrã inteiro para a melhor
|
||||||
É recomendado jogar o jogo em ecrã inteiro para a melhor experiência. Apenas disponível no jogo completo.
|
experiência. Apenas disponível no jogo completo.
|
||||||
soundsMuted:
|
soundsMuted:
|
||||||
title: Desativar sons
|
title: Desativar sons
|
||||||
description: >-
|
description: Se ativado, desativa todos os sons.
|
||||||
Se ativado, desativa todos os sons.
|
|
||||||
musicMuted:
|
musicMuted:
|
||||||
title: Desativar música
|
title: Desativar música
|
||||||
description: >-
|
description: Se ativado, desativa todas as músicas.
|
||||||
Se ativado, desativa todas as músicas.
|
|
||||||
theme:
|
theme:
|
||||||
title: Tema do jogo
|
title: Tema do jogo
|
||||||
description: >-
|
description: Escolhe o tema do jogo (claro / escuro).
|
||||||
Escolhe o tema do jogo (claro / escuro).
|
|
||||||
themes:
|
themes:
|
||||||
dark: Escuro
|
dark: Escuro
|
||||||
light: Claro
|
light: Claro
|
||||||
refreshRate:
|
refreshRate:
|
||||||
title: Frequência
|
title: Frequência
|
||||||
description: >-
|
description: Se tens um monitor 144hz, muda a frequência para que o jogo simule
|
||||||
Isto determina quantos game ticks ocorrem por segundo. No geral, uma frequência alta significa melhor precisão mas também pior desempenho. Em frequências baixas, o rendimento pode não ser exato.
|
corretamente frequências de autalização altas. Isto pode
|
||||||
|
resultar em perda de FPS se o teu computador for demasiado
|
||||||
|
lento.
|
||||||
alwaysMultiplace:
|
alwaysMultiplace:
|
||||||
title: Colocação múltipla
|
title: Colocação múltipla
|
||||||
description: >-
|
description: Se ativado, todas as construções permanecerão selecionadas após a
|
||||||
Se ativado, todas as construções permanecerão selecionadas após a colocação até cancelares. Isto é equivalente a pressionares SHIFT permanentemente.
|
colocação até cancelares. Isto é equivalente a pressionares
|
||||||
|
SHIFT permanentemente.
|
||||||
offerHints:
|
offerHints:
|
||||||
title: Dicas e tutoriais
|
title: Dicas e tutoriais
|
||||||
description: >-
|
description: Se ativado, dá dicas e tutoriais de apoio ao jogo. Adicionalmente,
|
||||||
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.
|
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:
|
movementSpeed:
|
||||||
title: Velocidade de movimentação
|
title: Velocidade de movimentação
|
||||||
description: Define quão rápida é a movimentação usando o teclado.
|
description: Define quão rápida é a movimentação usando o teclado.
|
||||||
@ -792,19 +844,17 @@ settings:
|
|||||||
extremely_fast: Extremamente rápida
|
extremely_fast: Extremamente rápida
|
||||||
enableTunnelSmartplace:
|
enableTunnelSmartplace:
|
||||||
title: Túneis inteligentes
|
title: Túneis inteligentes
|
||||||
description: >-
|
description: Quando ativado, a colocação de túneis removerá tapetes
|
||||||
Quando ativado, a colocação de túneis removerá tapetes desnecessários automaticamente.
|
desnecessários automaticamente. Isto também permite arrastar
|
||||||
Isto também permite arrastar túneis e túneis em excesso serão removidos.
|
túneis e túneis em excesso serão removidos.
|
||||||
vignette:
|
vignette:
|
||||||
title: Vinheta
|
title: Vinheta
|
||||||
description: >-
|
description: Ativa a vinheta, que escurece os cantos do ecrã e torna a leitura
|
||||||
Ativa a vinheta, que escurece os cantos do ecrã e torna a leitura do texto
|
do texto mais fácil.
|
||||||
mais fácil.
|
|
||||||
autosaveInterval:
|
autosaveInterval:
|
||||||
title: Intervalo de gravação automática
|
title: Intervalo de gravação automática
|
||||||
description: >-
|
description: Define o quão frequentemente o jogo grava automaticamente. Também
|
||||||
Define o quão frequentemente o jogo grava automaticamente. Também podes desativar
|
podes desativar aqui.
|
||||||
aqui.
|
|
||||||
intervals:
|
intervals:
|
||||||
one_minute: 1 Minuto
|
one_minute: 1 Minuto
|
||||||
two_minutes: 2 Minutos
|
two_minutes: 2 Minutos
|
||||||
@ -814,69 +864,68 @@ settings:
|
|||||||
disabled: Desligado
|
disabled: Desligado
|
||||||
compactBuildingInfo:
|
compactBuildingInfo:
|
||||||
title: Informações de construções compactas
|
title: Informações de construções compactas
|
||||||
description: >-
|
description: Encurta caixas de informação e apenas mostra os respetivos rácios.
|
||||||
Encurta caixas de informação e apenas mostra os respetivos rácios. Caso contrário
|
Caso contrário é mostrada a descrição e a imagem.
|
||||||
é mostrada a descrição e a imagem.
|
|
||||||
disableCutDeleteWarnings:
|
disableCutDeleteWarnings:
|
||||||
title: Desativar Avisos de Corte/Eliminação
|
title: Desativar Avisos de Corte/Eliminação
|
||||||
description: >-
|
description: Desativa os avisos mostrados quando é feito o corte ou a eliminação
|
||||||
Desativa os avisos mostrados quando é feito o corte ou a eliminação de mais de 100
|
de mais de 100 entidades.
|
||||||
entidades.
|
|
||||||
enableColorBlindHelper:
|
enableColorBlindHelper:
|
||||||
title: Modo Daltónico
|
title: Modo Daltónico
|
||||||
description: Ativa várias ferramentas que te permitirão jogar o jogo se fores daltónico.
|
description: Ativa várias ferramentas que te permitirão jogar o jogo se fores
|
||||||
|
daltónico.
|
||||||
rotationByBuilding:
|
rotationByBuilding:
|
||||||
title: Rotação por tipo de construção
|
title: Rotação por tipo de construção
|
||||||
description: >-
|
description: Cada tipo construção lembra-se da última rotação que definiste.
|
||||||
Cada tipo de construção lembra-se da última rotação que definiste.
|
Esta definição pode ser mais confortável se alterares
|
||||||
Esta definição pode ser mais confortável se alterares frequentemente
|
frequentemente a colocação de diferentes tipos de construções.
|
||||||
a colocação de diferentes tipos de construções.
|
|
||||||
soundVolume:
|
soundVolume:
|
||||||
title: Volume do Som
|
title: Volume do Som
|
||||||
description: Define o volume para efeitos sonoros
|
description: Define o volume para efeitos sonoros
|
||||||
musicVolume:
|
musicVolume:
|
||||||
title: Volume da Música
|
title: Volume da Música
|
||||||
description: Define o volume para música
|
description: Define o volume para música
|
||||||
lowQualityMapResources:
|
lowQualityMapResources:
|
||||||
title: Recursos de Mapa de Baixa Qualidade
|
title: Recursos de Mapa de Baixa Qualidade
|
||||||
description: >-
|
description: Simplifica a renderização de recursos quando o mapa está ampliado para
|
||||||
Simplifica a renderização de recursos quanto o mapa está ampliado para melhorar o desempenho. Até parece mais limpo, então lembra-te de experimentar!
|
melhorar o desempenho. Até parece mais limpo, então lembra-te de
|
||||||
|
experimentares!
|
||||||
disableTileGrid:
|
disableTileGrid:
|
||||||
title: Desativar Grelha
|
title: Desativar Grelha
|
||||||
description: >-
|
description: Desativar a grelha pode ajudar com o desempenho. Isto também
|
||||||
Desativar a grelha pode ajudar com o desempenho. Isto também faz o jogo estar mais limpo!
|
fazz o jogo parecer mais limpo!
|
||||||
clearCursorOnDeleteWhilePlacing:
|
clearCursorOnDeleteWhilePlacing:
|
||||||
title: Limpar Cursor com Clique Direito
|
title: Limpar Cursor com Clique Direito
|
||||||
description: >-
|
description: Ativado por padrão, limpa o cursor sempre que pressionas o botão direito do rato
|
||||||
Ativado por default, limpa o cursos sempre que clicas no botão direito do rato enquanto tens um edifício selecionado para colocamento.
|
enquanto tens um edifício para colocamento. Se desativado,
|
||||||
Se desativado, podes apagar edifícios fazendo um clique direito enquanto colocas um edifício.
|
podes apagar construções pressionando o botão direito do rato enquanto colocas um
|
||||||
|
edifício.
|
||||||
lowQualityTextures:
|
lowQualityTextures:
|
||||||
title: Texturas de baixa qualidade (Feio)
|
title: Texturas de baixa qualidade (Feio)
|
||||||
description: >-
|
description: sa texturas de baixa qualidade para melhorar o desempenho. sto vai tornar o
|
||||||
Usa texturas de baixa qualidade para melhorar o desempenho. Isto vai tornar o jogo muito feio!
|
jogo parecer muito feio!
|
||||||
displayChunkBorders:
|
displayChunkBorders:
|
||||||
title: Mostrar bordas de Chunks
|
title: Mostrar bordas de limites (chunk borders)
|
||||||
description: >-
|
description: O jogo está dividido em partes de 16x16 quadrados, se esta dedinição estiver
|
||||||
O jogo está dividido em pedaços de 16x16 quadrados, se esta definição estiver ativada
|
ativada as bordas de cada limitece são mostradas.
|
||||||
as bordas de cada pedaço são mostradas.
|
|
||||||
pickMinerOnPatch:
|
pickMinerOnPatch:
|
||||||
title: Selecionar extrator num remendo de recursos
|
title: Selecionar extrator num quadrado de recurso
|
||||||
description: >-
|
description: Ativado por padrão, seleciona um extrator se usares a pipeta quando
|
||||||
Ativado por default, seleciona o extrator se usares a pipeta enquanto estás num remendo de recursos.
|
estiveres com o rato em cima de um quadrado de recurso.
|
||||||
simplifiedBelts:
|
simplifiedBelts:
|
||||||
title: Tapetes rolantes simplificados (Feio)
|
title: Tapetes rolantes simplificados (Feio)
|
||||||
description: >-
|
description: Não renderiza os intens nos tapetes excepto quando tens o rato em cima do tapete
|
||||||
Não renderiza itens em tapetes excepto quando tens o rato em cima do tapete para salvar desempenho.
|
para melhorar o desempenho. Não recomendo a jogares com esta definição ativada
|
||||||
Não recomendo jogares com esta definição a menos que absolutamente precisas do desempenho.
|
a não ser que precises mesmo de melhorar o desempenho.
|
||||||
enableMousePan:
|
enableMousePan:
|
||||||
title: Ativar Mouse Pan
|
title: Ativar rato panorâmico
|
||||||
description: >-
|
description: Permite-te mover o mapa movento o rato nos cantos do
|
||||||
Permite-te mover o mapa apenas movendo o rato aos cantos do ecrã. A velocidade depende da definição Velocidade de movimentação.
|
ecrâ. A velociade depende da definição de velocidade de movimentação.
|
||||||
rangeSliderPercentage: <amount> %
|
rangeSliderPercentage: <amount> %
|
||||||
keybindings:
|
keybindings:
|
||||||
title: Atalhos
|
title: Atalhos
|
||||||
hint: >-
|
hint: "Dica: Utiliza o CTRL, o SHIFT e o ALT! Eles permitem diferentes opções de
|
||||||
Tip: Utiliza o CTRL, o SHIFT e o ALT! Eles permitem diferentes opções de posicionamento.
|
posicionamento."
|
||||||
resetKeybindings: Resetar Atalhos
|
resetKeybindings: Resetar Atalhos
|
||||||
categoryLabels:
|
categoryLabels:
|
||||||
general: Aplicação
|
general: Aplicação
|
||||||
@ -931,13 +980,12 @@ keybindings:
|
|||||||
menuClose: Fechar Menu
|
menuClose: Fechar Menu
|
||||||
switchLayers: Troca de camadas
|
switchLayers: Troca de camadas
|
||||||
wire: Fio Elétrico
|
wire: Fio Elétrico
|
||||||
balancer: Balanceador
|
balancer: Distribuidor
|
||||||
storage: Armazém
|
storage: Armazém
|
||||||
constant_signal: Sinal Constante
|
constant_signal: Sinal Constante
|
||||||
logic_gate: Portões Lógicos
|
logic_gate: Portões Lógicos
|
||||||
lever: Interruptor (normal)
|
lever: Interruptor (normal)
|
||||||
lever_wires: Interruptor (fios)
|
filter: Filtro de itens
|
||||||
filter: Filtro
|
|
||||||
wire_tunnel: Túnel de Fio
|
wire_tunnel: Túnel de Fio
|
||||||
display: Display
|
display: Display
|
||||||
reader: Leitor de Tapete
|
reader: Leitor de Tapete
|
||||||
@ -972,13 +1020,13 @@ demo:
|
|||||||
exportingBase: Exportar base como uma imagem
|
exportingBase: Exportar base como uma imagem
|
||||||
settingNotAvailable: Não disponível no Demo.
|
settingNotAvailable: Não disponível no Demo.
|
||||||
tips:
|
tips:
|
||||||
- 'O edifício central aceita qualquer entrada, não apenas a forma atual!'
|
- "O edifício central aceita qualquer entrada, não apenas a forma atual!"
|
||||||
- Tem a certeza que as tuas fábricas são modulares - vai valer a pena!
|
- Tem a certeza que as tuas fábricas são modulares - vai valer a pena!
|
||||||
- 'Não construas demasiado perto do edifício, ou vai ser um grande caos!'
|
- "Não construas demasiado perto do edifício, ou vai ser um grande caos!"
|
||||||
- 'Se empilhar não funciona, tenta trocar as entradas.'
|
- "Se empilhar não funciona, tenta trocar as entradas."
|
||||||
- Podes alternar a direção do planeador de tapete rolante ao pressionar <b>R</b>.
|
- Podes alternar a direção do planeador de tapete rolante ao pressionar <b>R</b>.
|
||||||
- Ao segurar <b>CTRL</b> podes arrastar tapetes rolantes sem auto-orientação.
|
- Ao segurar <b>CTRL</b> podes arrastar tapetes rolantes sem auto-orientação.
|
||||||
- 'Os rácios continuam os mesmos, desde que todos os upgrades estejam no mesmo Nível.'
|
- "Os rácios continuam os mesmos, desde que todos os upgrades estejam no mesmo Nível."
|
||||||
- Execução em série é mais eficiente que em paralelo.
|
- Execução em série é mais eficiente que em paralelo.
|
||||||
- Vais desbloquear mais variações de edifícios mais tarde no jogo!
|
- Vais desbloquear mais variações de edifícios mais tarde no jogo!
|
||||||
- Podes usar <b>T</b> para trocar entre as diferentes variantes.
|
- Podes usar <b>T</b> para trocar entre as diferentes variantes.
|
||||||
@ -987,11 +1035,11 @@ tips:
|
|||||||
- Tenta construir fábricas compactas - vai valer a pena!
|
- Tenta construir fábricas compactas - vai valer a pena!
|
||||||
- O pintor tem uma variante espelhada que podes selectionar com <b>T</b>
|
- O pintor tem uma variante espelhada que podes selectionar com <b>T</b>
|
||||||
- Ter os rácios de edifícios corretos vai maximizar a eficiência.
|
- Ter os rácios de edifícios corretos vai maximizar a eficiência.
|
||||||
- 'No nível máximo, 5 extratores vão encher um tapete.'
|
- "No nível máximo, 5 extratores vão encher um tapete."
|
||||||
- Não te esqueças dos túneis!
|
- Não te esqueças dos túneis!
|
||||||
- Não tens de dividir os itens uniformemente para eficiência máxima.
|
- Não tens de dividir os itens uniformemente para eficiência máxima.
|
||||||
- Segurar <b>SHIFT</b> vai ativar o planeador de tapetes, deixando-te colocar longas linhas de tapetes facilmente.
|
- Segurar <b>SHIFT</b> vai ativar o planeador de tapetes, deixando-te colocar longas linhas de tapetes facilmente.
|
||||||
- 'Os cortadores cortam sempre verticalmente, independentemente da sua orientação.'
|
- "Os cortadores cortam sempre verticalmente, independentemente da sua orientação."
|
||||||
- Para obter branco junta as três cores.
|
- Para obter branco junta as três cores.
|
||||||
- O buffer do armazém prioritiza a primeira saída.
|
- O buffer do armazém prioritiza a primeira saída.
|
||||||
- Investe tempo para costruir designs repetiveis - vale a pena!
|
- Investe tempo para costruir designs repetiveis - vale a pena!
|
||||||
@ -999,32 +1047,32 @@ tips:
|
|||||||
- Podes segurar <b>ALT</b> para inverter a direção de tapetes colocados.
|
- Podes segurar <b>ALT</b> para inverter a direção de tapetes colocados.
|
||||||
- Eficiência é a solução!
|
- Eficiência é a solução!
|
||||||
- As formas que estão mais longes do edifício central são mais complexas.
|
- As formas que estão mais longes do edifício central são mais complexas.
|
||||||
- 'As Máquinas têm uma velocidade limitada, divide-as para eficiência máxima.'
|
- "As Máquinas têm uma velocidade limitada, divide-as para eficiência máxima."
|
||||||
- Usa balanceadores para maximizar a tua eficiência.
|
- Usa balanceadores para maximizar a tua eficiência.
|
||||||
- Organização é importante. Tenta não cruzar tapetes demasiado.
|
- Organização é importante. Tenta não cruzar tapetes demasiado.
|
||||||
- 'Planeja antecipadamente, ou vai ser um grande caos!'
|
- "Planeja antecipadamente, ou vai ser um grande caos!"
|
||||||
- Não removas as tuas fábricas antigas! Vais precisar delas para desbloquear upgrades.
|
- Não removas as tuas fábricas antigas! Vais precisar delas para desbloquear upgrades.
|
||||||
- Tenta superar o nível 18 sozinho sem procurar ajuda!
|
- Tenta superar o nível 18 sozinho sem procurar ajuda!
|
||||||
- 'Não complicas as coisas, tenta continuar simples e irás muito longe.'
|
- "Não complicas as coisas, tenta continuar simples e irás muito longe."
|
||||||
- Talvez precises de reusar fábricas mais tarde no jogo. Planeia as tuas fábricas para serem reutilizáveis.
|
- Talvez precises de reusar fábricas mais tarde no jogo. Planeia as tuas fábricas para serem reutilizáveis.
|
||||||
- Às vezes, podes encontrar uma forma necessária no mapa sem criar-la com empilhadoras.
|
- Às vezes, podes encontrar uma forma necessária no mapa sem criar-la com empilhadoras.
|
||||||
- Moinhos de vento e cataventos completos nunca aparecem naturalmente.
|
- Moinhos de vento e cataventos completos nunca aparecem naturalmente.
|
||||||
- Pinta as tuas formas antes de cortar-las para eficiência máxima.
|
- Pinta as tuas formas antes de cortar-las para eficiência máxima.
|
||||||
- 'Com módulos, o espaço é apenas uma percepção; uma preocupação para pessoas mortais.'
|
- "Com módulos, o espaço é apenas uma percepção; uma preocupação para pessoas mortais."
|
||||||
- Faz uma fábrica de diagramas separada. São importantes para módulos.
|
- Faz uma fábrica de diagramas separada. São importantes para módulos.
|
||||||
- 'Dá uma olhada ao misturador de cores, e as tuas questões serão respondidas.'
|
- "Dá uma olhada ao misturador de cores, e as tuas questões serão respondidas."
|
||||||
- Use <b>CTRL</b> + Clique para selecionar uma área.
|
- Use <b>CTRL</b> + Clique para selecionar uma área.
|
||||||
- Construir demasiado perto do edifício central pode ficar no caminho de projetos futuros.
|
- Construir demasiado perto do edifício central pode ficar no caminho de projetos futuros.
|
||||||
- O ícone de alfinete perto duma forma na lista de upgrades vai afixar-la ao ecrã.
|
- O ícone de alfinete perto duma forma na lista de upgrades vai afixar-la ao ecrã.
|
||||||
- Junta todas as cores primárias juntas para fazer branco!
|
- Junta todas as cores primárias juntas para fazer branco!
|
||||||
- 'Tu tens um mapa infinito, não limites a tua fábrica, expande!'
|
- "Tu tens um mapa infinito, não limites a tua fábrica, expande!"
|
||||||
- Tenta também Factorio! É o meu jogo favorito.
|
- Tenta também Factorio! É o meu jogo favorito.
|
||||||
- O cortador quádruplo corta no sentido dos ponteiros começando no canto superior direito!
|
- O cortador quádruplo corta no sentido dos ponteiros começando no canto superior direito!
|
||||||
- Podes fazer download dos teus savegames no menu principal!
|
- Podes fazer download dos teus savegames no menu principal!
|
||||||
- Este jogo tem muitos atalhos de teclado úteis! Não te esqueças de verificar a página de configurações.
|
- Este jogo tem muitos atalhos de teclado úteis! Não te esqueças de verificar a página de configurações.
|
||||||
- 'Este jogo tem muitas definições, não te esqueças de as verificar!'
|
- "Este jogo tem muitas definições, não te esqueças de as verificar!"
|
||||||
- O marco para o teu edifício central tem uma pequena bússola para indicar a sua direção!
|
- O marco para o teu edifício central tem uma pequena bússola para indicar a sua direção!
|
||||||
- 'Para limpar tapetes, corta a área e cola-a na mesma localização.'
|
- "Para limpar tapetes, corta a área e cola-a na mesma localização."
|
||||||
- Pressiona F4 para mostrar os teus FPS e Tick Rate.
|
- Pressiona F4 para mostrar os teus FPS e Tick Rate.
|
||||||
- Pressiona F4 duas vezes para mostrar a tile do teu rato e câmara.
|
- Pressiona F4 duas vezes para mostrar a tile do teu rato e câmara.
|
||||||
- Podes clicar numa forma afixada no lado direito para desafixar-la.
|
- Podes clicar numa forma afixada no lado direito para desafixar-la.
|
||||||
|
|||||||
@ -5,7 +5,7 @@ steamPage:
|
|||||||
discordLinkShort: Official Discord
|
discordLinkShort: Official Discord
|
||||||
intro: >-
|
intro: >-
|
||||||
Shapez.io is a relaxed game in which you have to build factories for the
|
Shapez.io is a relaxed game in which you have to build factories for the
|
||||||
automated production of geometric shapes.
|
automated production of geometric shapes.
|
||||||
|
|
||||||
As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map.
|
As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map.
|
||||||
|
|
||||||
|
|||||||
@ -1,51 +1,50 @@
|
|||||||
steamPage:
|
steamPage:
|
||||||
shortText: shapez.io — это игра о строительстве фабрик для автоматизации
|
shortText: shapez.io — это игра о строительстве фабрик для автоматизации
|
||||||
создания и объединения все более сложных фигур на бесконечной карте.
|
создания и объединения все более сложных фигур на бесконечной карте.
|
||||||
discordLinkShort: Official Discord
|
discordLinkShort: Официальный Discord сервер
|
||||||
intro: >-
|
intro: >-
|
||||||
Shapez.io is a relaxed game in which you have to build factories for the
|
Shapez.io - это спокойная игра о создании фабрик для автоматизации создания сложных геометрических фигур.
|
||||||
automated production of geometric shapes.
|
|
||||||
|
|
||||||
As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map.
|
По мере управления уровня, фигуры становятся все сложнее, так что придется расширять фабрику засчет бесконечной карты.
|
||||||
|
|
||||||
And as if that wasn't enough, you also have to produce exponentially more to satisfy the demands - the only thing that helps is scaling!
|
Если этого мало, то Вам так же придется экспоненциально производить все больше и больше фигур, чтобы удовлетворить потребности Вашей фабрики. Ключ к успеху - расширение!
|
||||||
|
|
||||||
While you only process shapes at the beginning, you have to color them later - for this you have to extract and mix colors!
|
Вначале игры Вам понадобится производить только фигуры, однако позже фигуры надо будет окрашивать. Для этого добывайте и смешивайте краски!
|
||||||
|
|
||||||
Buying the game on Steam gives you access to the full version, but you can also play a demo on shapez.io first and decide later!
|
Приобретение игры в Steam предоставляет доступ к полной версии игры, но вы можете опробовать демоверсию игры на shapez.io и принять решение позже!
|
||||||
title_advantages: Standalone Advantages
|
title_advantages: Преимущества полной версии
|
||||||
advantages:
|
advantages:
|
||||||
- <b>12 New Level</b> for a total of 26 levels
|
- <b>12 новых уровней</b> - всего 26 уровней!
|
||||||
- <b>18 New Buildings</b> for a fully automated factory!
|
- <b>18 новых построек</b> для полностью автоматизированной фабрики!
|
||||||
- <b>20 Upgrade Tiers</b> for many hours of fun!
|
- <b>20 стадий улучшения</b> для долгих часов веселья!
|
||||||
- <b>Wires Update</b> for an entirely new dimension!
|
- <b>Провода</b> - открывает полноценное новое измерение!
|
||||||
- <b>Dark Mode</b>!
|
- <b>Темная тема</b>!
|
||||||
- Unlimited Savegames
|
- Неограниченные сохранения
|
||||||
- Unlimited Markers
|
- Неограниченные маркеры
|
||||||
- Support me! ❤️
|
- Поддержите меня! ❤️
|
||||||
title_future: Planned Content
|
title_future: Запланированный контент
|
||||||
planned:
|
planned:
|
||||||
- Blueprint Library (Standalone Exclusive)
|
- Библиотека чертежей (только для Полной версии)
|
||||||
- Steam Achievements
|
- Достижения Steam
|
||||||
- Puzzle Mode
|
- Режим головоломок
|
||||||
- Minimap
|
- Мини-карта
|
||||||
- Mods
|
- Моды
|
||||||
- Sandbox mode
|
- Режим песочницы
|
||||||
- ... and a lot more!
|
- ... и многое другое!
|
||||||
title_open_source: This game is open source!
|
title_open_source: Эта игра находится в открытом доступе!
|
||||||
title_links: Links
|
title_links: Ссылки
|
||||||
links:
|
links:
|
||||||
discord: Official Discord
|
discord: Официальный Discord сервер
|
||||||
roadmap: Roadmap
|
roadmap: Планы
|
||||||
subreddit: Subreddit
|
subreddit: Subreddit
|
||||||
source_code: Source code (GitHub)
|
source_code: Исходный код (GitHub)
|
||||||
translate: Help translate
|
translate: Помочь с переводом
|
||||||
text_open_source: >-
|
text_open_source: >-
|
||||||
Anybody can contribute, I'm actively involved in the community and
|
Кто угодно может внести свой вклад в разработку игры - я активно вовлечен
|
||||||
attempt to review all suggestions and take feedback into consideration
|
в сообщество и стараюсь просмотреть все предложения и по возможности
|
||||||
where possible.
|
прислушиваться к отзывам.
|
||||||
|
|
||||||
Be sure to check out my trello board for the full roadmap!
|
Не забудьте заглянуть на мой Trello board, чтобы ознакомиться с планами на будущее!
|
||||||
global:
|
global:
|
||||||
loading: Загрузка
|
loading: Загрузка
|
||||||
error: Ошибка
|
error: Ошибка
|
||||||
@ -78,7 +77,7 @@ global:
|
|||||||
shift: SHIFT
|
shift: SHIFT
|
||||||
space: ПРОБЕЛ
|
space: ПРОБЕЛ
|
||||||
demoBanners:
|
demoBanners:
|
||||||
title: Демо-версия
|
title: Демоверсия
|
||||||
intro: Приобретите полную версию, чтобы разблокировать все возможности!
|
intro: Приобретите полную версию, чтобы разблокировать все возможности!
|
||||||
mainMenu:
|
mainMenu:
|
||||||
play: Играть
|
play: Играть
|
||||||
@ -121,9 +120,9 @@ dialogs:
|
|||||||
text: Не удалось загрузить сохранение игры.
|
text: Не удалось загрузить сохранение игры.
|
||||||
confirmSavegameDelete:
|
confirmSavegameDelete:
|
||||||
title: Подтвердите удаление.
|
title: Подтвердите удаление.
|
||||||
text: Are you sure you want to delete the following game?<br><br>
|
text: Вы уверены, что хотите удалить это сохранение?<br><br>
|
||||||
'<savegameName>' at level <savegameLevel><br><br> This can not be
|
'<savegameName>' на уровне <savegameLevel><br><br> Это не может
|
||||||
undone!
|
быть отменено!
|
||||||
savegameDeletionError:
|
savegameDeletionError:
|
||||||
title: Ошибка удаления
|
title: Ошибка удаления
|
||||||
text: Не удалось удалить сохранение игры.
|
text: Не удалось удалить сохранение игры.
|
||||||
@ -142,13 +141,13 @@ dialogs:
|
|||||||
title: Сброс управления
|
title: Сброс управления
|
||||||
desc: Настройки управления сброшены до соответствующих значений по умолчанию!
|
desc: Настройки управления сброшены до соответствующих значений по умолчанию!
|
||||||
featureRestriction:
|
featureRestriction:
|
||||||
title: Демо-версия
|
title: Демоверсия
|
||||||
desc: Вы попытались получить доступ к функции (<feature>), которая недоступна в
|
desc: Вы попытались получить доступ к функции (<feature>), которая недоступна в
|
||||||
демо-версии. Вы можете приобрести полную версию чтобы пользоваться
|
демоверсии. Вы можете приобрести полную версию чтобы пользоваться
|
||||||
всеми функциями!
|
всеми функциями!
|
||||||
oneSavegameLimit:
|
oneSavegameLimit:
|
||||||
title: Лимит сохранений
|
title: Лимит сохранений
|
||||||
desc: Вы можете иметь только одно сохранение игры в демо-версии. Пожалуйста,
|
desc: Вы можете иметь только одно сохранение игры в демоверсии. Пожалуйста,
|
||||||
удалите существующее или приобретите полную версию!
|
удалите существующее или приобретите полную версию!
|
||||||
updateSummary:
|
updateSummary:
|
||||||
title: Новое обновление!
|
title: Новое обновление!
|
||||||
@ -177,11 +176,11 @@ dialogs:
|
|||||||
Инвертировать направление размещаемых конвейерных лент.<br>"
|
Инвертировать направление размещаемых конвейерных лент.<br>"
|
||||||
createMarker:
|
createMarker:
|
||||||
title: Новый маркер
|
title: Новый маркер
|
||||||
desc: Give it a meaningful name, you can also include a <strong>short
|
desc: Дайте ему значимое название, вы также можете добавить <strong>короткий
|
||||||
key</strong> of a shape (Which you can generate <link>here</link>)
|
ключ</strong> фигуры (Который можно сгенерировать <link>здесь</link>)
|
||||||
titleEdit: Редактирование маркера
|
titleEdit: Редактирование маркера
|
||||||
markerDemoLimit:
|
markerDemoLimit:
|
||||||
desc: Вы можете создать только 2 своих маркера в демо-версии. Приобретите полную
|
desc: Вы можете создать только 2 своих маркера в демоверсии. Приобретите полную
|
||||||
версию для безлимитных маркеров.
|
версию для безлимитных маркеров.
|
||||||
massCutConfirm:
|
massCutConfirm:
|
||||||
title: Подтвердите вырезку
|
title: Подтвердите вырезку
|
||||||
@ -197,18 +196,17 @@ dialogs:
|
|||||||
desc: Вы не можете позволить себе вставить эту область! Вы уверены, что хотите
|
desc: Вы не можете позволить себе вставить эту область! Вы уверены, что хотите
|
||||||
вырезать ее?
|
вырезать ее?
|
||||||
editSignal:
|
editSignal:
|
||||||
title: Set Signal
|
title: Установить Сигнал
|
||||||
descItems: "Choose a pre-defined item:"
|
descItems: "Выберите объект:"
|
||||||
descShortKey: ... or enter the <strong>short key</strong> of a shape (Which you
|
descShortKey: ... или введите <strong>короткий
|
||||||
can generate <link>here</link>)
|
ключ</strong> фигуры (Который можно сгенерировать <link>здесь</link>)
|
||||||
renameSavegame:
|
renameSavegame:
|
||||||
title: Rename Savegame
|
title: Переименовать Сохранение
|
||||||
desc: You can rename your savegame here.
|
desc: Здесь вы можете изменить название своего сохранения.
|
||||||
entityWarning:
|
entityWarning:
|
||||||
title: Performance Warning
|
title: Вы разместили очень много построек, это просто напоминание о том, что игра
|
||||||
desc: You have placed a lot of buildings, this is just a friendly reminder that
|
не может справиться с бесконечным количеством построек. Так что
|
||||||
the game can not handle an endless count of buildings - So try to
|
постарайтесь создавать компактные фабрики!
|
||||||
keep your factories compact!
|
|
||||||
ingame:
|
ingame:
|
||||||
keybindingsOverlay:
|
keybindingsOverlay:
|
||||||
moveMap: Передвижение
|
moveMap: Передвижение
|
||||||
@ -217,7 +215,7 @@ ingame:
|
|||||||
rotateBuilding: Повернуть постройку
|
rotateBuilding: Повернуть постройку
|
||||||
placeMultiple: Поставить несколько
|
placeMultiple: Поставить несколько
|
||||||
reverseOrientation: Реверсировать направление
|
reverseOrientation: Реверсировать направление
|
||||||
disableAutoOrientation: Отключить авто-определение направления
|
disableAutoOrientation: Отключить автоопределение направления
|
||||||
toggleHud: Переключить HUD
|
toggleHud: Переключить HUD
|
||||||
placeBuilding: Разместить постройку
|
placeBuilding: Разместить постройку
|
||||||
createMarker: Создать маркер
|
createMarker: Создать маркер
|
||||||
@ -343,41 +341,41 @@ ingame:
|
|||||||
empty: Пусто
|
empty: Пусто
|
||||||
copyKey: Копировать
|
copyKey: Копировать
|
||||||
connectedMiners:
|
connectedMiners:
|
||||||
one_miner: 1 Miner
|
one_miner: 1 Экстрактор
|
||||||
n_miners: <amount> Miners
|
n_miners: <amount> Экстрактора(-ов)
|
||||||
limited_items: Limited to <max_throughput>
|
limited_items: Ограничено до <max_throughput>
|
||||||
watermark:
|
watermark:
|
||||||
title: Demo version
|
title: Демоверсия
|
||||||
desc: Click here to see the Steam version advantages!
|
desc: Нажмите сюда, чтобы узнать о преимуществах Steam версии!
|
||||||
get_on_steam: Get on steam
|
get_on_steam: Приобрести в Steam
|
||||||
standaloneAdvantages:
|
standaloneAdvantages:
|
||||||
title: Get the full version!
|
title: Приобретите полную версию!
|
||||||
no_thanks: No, thanks!
|
no_thanks: Нет, спасибо!
|
||||||
points:
|
points:
|
||||||
levels:
|
levels:
|
||||||
title: 12 New Levels
|
title: 12 Новых Уровней!
|
||||||
desc: For a total of 26 levels!
|
desc: Всего 26 уровней!
|
||||||
buildings:
|
buildings:
|
||||||
title: 18 New Buildings
|
title: 18 новых Построек!
|
||||||
desc: Fully automate your factory!
|
desc: Полностью автоматизируйте свою фабрику!
|
||||||
savegames:
|
savegames:
|
||||||
title: ∞ Savegames
|
title: ∞ Сохранений
|
||||||
desc: As many as your heart desires!
|
desc: Сколько Вашей душе угодно!
|
||||||
upgrades:
|
upgrades:
|
||||||
title: 20 Upgrade Tiers
|
title: 20 стадий улучшений!
|
||||||
desc: This demo version has only 5!
|
desc: В демоверсии всего 5!
|
||||||
markers:
|
markers:
|
||||||
title: ∞ Markers
|
title: ∞ Маркеров!
|
||||||
desc: Never get lost in your factory!
|
desc: Никогда не теряйтесь в своей фабрике!
|
||||||
wires:
|
wires:
|
||||||
title: Wires
|
title: Провода!
|
||||||
desc: An entirely new dimension!
|
desc: Полноценное дополнительное измерение!
|
||||||
darkmode:
|
darkmode:
|
||||||
title: Dark Mode
|
title: Темная Тема!
|
||||||
desc: Stop hurting your eyes!
|
desc: Дайте глазам отдохнуть!
|
||||||
support:
|
support:
|
||||||
title: Support me
|
title: Поддержите меня
|
||||||
desc: I develop it in my spare time!
|
desc: Я занимаюсь разработкой в свободное время!
|
||||||
shopUpgrades:
|
shopUpgrades:
|
||||||
belt:
|
belt:
|
||||||
name: Конвейеры, Разделители & Туннели
|
name: Конвейеры, Разделители & Туннели
|
||||||
@ -417,11 +415,11 @@ buildings:
|
|||||||
default:
|
default:
|
||||||
name: Резак
|
name: Резак
|
||||||
description: Разрезает фигуры сверху вниз и выводит обе половины. <strong>Если
|
description: Разрезает фигуры сверху вниз и выводит обе половины. <strong>Если
|
||||||
Вы собираетесь использовать только одну часть, уничтожьте
|
вы собираетесь использовать только одну часть, уничтожьте
|
||||||
другую, иначе производство остановится!</strong>
|
другую, иначе производство остановится!</strong>
|
||||||
quad:
|
quad:
|
||||||
name: Резак (4Вых.)
|
name: Резак (4Вых.)
|
||||||
description: Разрезает фигуры на четыре части. <strong>Если Вы собираетесь
|
description: Разрезает фигуры на четыре части. <strong>Если вы собираетесь
|
||||||
использовать не все части - уничтожьте оставшиеся, иначе
|
использовать не все части - уничтожьте оставшиеся, иначе
|
||||||
производство остановится!</strong>
|
производство остановится!</strong>
|
||||||
rotater:
|
rotater:
|
||||||
@ -432,8 +430,8 @@ buildings:
|
|||||||
name: Вращатель (Обр.)
|
name: Вращатель (Обр.)
|
||||||
description: Поворачивает фигуры против часовой стрелки на 90 градусов.
|
description: Поворачивает фигуры против часовой стрелки на 90 градусов.
|
||||||
rotate180:
|
rotate180:
|
||||||
name: Rotate (180)
|
name: Вращатель (180)
|
||||||
description: Rotates shapes by 180 degrees.
|
description: Поворачивает фигуры на 180 градусов.
|
||||||
stacker:
|
stacker:
|
||||||
default:
|
default:
|
||||||
name: Объединитель
|
name: Объединитель
|
||||||
@ -452,9 +450,9 @@ buildings:
|
|||||||
description: Красит фигуру из левых входов красителем из перпендикулярного.
|
description: Красит фигуру из левых входов красителем из перпендикулярного.
|
||||||
quad:
|
quad:
|
||||||
name: Покрасчик (4Вх.)
|
name: Покрасчик (4Вх.)
|
||||||
description: Allows you to color each quadrant of the shape individually. Only
|
description: Позволяет отдельно окрашивать каждую часть фигуры. Только ячейки с
|
||||||
slots with a <strong>truthy signal</strong> on the wires layer
|
<strong>положительным сигналом</strong> на слое с проводами
|
||||||
will be painted!
|
будут окрашены!
|
||||||
mirrored:
|
mirrored:
|
||||||
name: Покрасчик
|
name: Покрасчик
|
||||||
description: Красит всю фигуру из левого входа красителем из перпендикулярного.
|
description: Красит всю фигуру из левого входа красителем из перпендикулярного.
|
||||||
@ -466,134 +464,132 @@ buildings:
|
|||||||
deliver: Доставить
|
deliver: Доставить
|
||||||
toUnlock: чтобы открыть
|
toUnlock: чтобы открыть
|
||||||
levelShortcut: Ур.
|
levelShortcut: Ур.
|
||||||
endOfDemo: End of Demo
|
endOfDemo: Конец Демо
|
||||||
wire:
|
wire:
|
||||||
default:
|
default:
|
||||||
name: Энерг. провод
|
name: Энерг. провод
|
||||||
description: Позволяет транспортировать энергию.
|
description: Позволяет транспортировать энергию.
|
||||||
second:
|
second:
|
||||||
name: Wire
|
name: Энерг. провод
|
||||||
description: Transfers signals, which can be items, colors or booleans (1 / 0).
|
description: Передает сигналы, которые могут быть ресурсами, цветами или логическими значениями (1 / 0).
|
||||||
Different colored wires do not connect.
|
Провода разных цветов не соединяются.
|
||||||
balancer:
|
balancer:
|
||||||
default:
|
default:
|
||||||
name: Balancer
|
name: Балансер
|
||||||
description: Multifunctional - Evenly distributes all inputs onto all outputs.
|
description: Многофункциональный - равномерно распределяет все входы на выходы.
|
||||||
merger:
|
merger:
|
||||||
name: Merger (compact)
|
name: Соединитель (компактный)
|
||||||
description: Merges two conveyor belts into one.
|
description: Соединяет две линии ковейера в одну.
|
||||||
merger-inverse:
|
merger-inverse:
|
||||||
name: Merger (compact)
|
name: Соединитель (компактный)
|
||||||
description: Merges two conveyor belts into one.
|
description: Соединяет две линии ковейера в одну.
|
||||||
splitter:
|
splitter:
|
||||||
name: Splitter (compact)
|
name: Разделитель (компактный)
|
||||||
description: Splits one conveyor belt into two.
|
description: Разделяет одну линию конвейера на две.
|
||||||
splitter-inverse:
|
splitter-inverse:
|
||||||
name: Splitter (compact)
|
name: Разделитель (компактный)
|
||||||
description: Splits one conveyor belt into two.
|
description: Разделяет одну линию конвейера на две.
|
||||||
storage:
|
storage:
|
||||||
default:
|
default:
|
||||||
name: Storage
|
name: Буферное Хранилище
|
||||||
description: Stores excess items, up to a given capacity. Prioritizes the left
|
description: Хранит излишние ресурсы пока есть место. Левый выход в приоритете, может быть использован как буфер.
|
||||||
output and can be used as an overflow gate.
|
|
||||||
wire_tunnel:
|
wire_tunnel:
|
||||||
default:
|
default:
|
||||||
name: Wire Crossing
|
name: Пересечение Проводов
|
||||||
description: Allows to cross two wires without connecting them.
|
description: Позволяет пересекать провода при этом их не соединяя.
|
||||||
constant_signal:
|
constant_signal:
|
||||||
default:
|
default:
|
||||||
name: Constant Signal
|
name: Постоянный Сигнал
|
||||||
description: Emits a constant signal, which can be either a shape, color or
|
description: Издает постоянный сигнал, который может быть ресурсом, цветом или логическим значением (1 / 0).
|
||||||
boolean (1 / 0).
|
|
||||||
lever:
|
lever:
|
||||||
default:
|
default:
|
||||||
name: Switch
|
name: Переключатель
|
||||||
description: Can be toggled to emit a boolean signal (1 / 0) on the wires layer,
|
description: Может быть переключен, чтобы издавать логический сигнал (1 / 0) на слое с проводами,
|
||||||
which can then be used to control for example an item filter.
|
который может быть использован для управления Фильтром, например.
|
||||||
logic_gate:
|
logic_gate:
|
||||||
default:
|
default:
|
||||||
name: AND Gate
|
name: AND Gate
|
||||||
description: Emits a boolean "1" if both inputs are truthy. (Truthy means shape,
|
description: Издает значение "1" если оба входа положительны. (Положительный - значит ресурс,
|
||||||
color or boolean "1")
|
цвет или логическое значение "1")
|
||||||
not:
|
not:
|
||||||
name: NOT Gate
|
name: NOT Gate
|
||||||
description: Emits a boolean "1" if the input is not truthy. (Truthy means
|
description: Издает значение "1" если вход не положительный. (Положительный - значит ресурс,
|
||||||
shape, color or boolean "1")
|
цвет или логическое значение "1")
|
||||||
xor:
|
xor:
|
||||||
name: XOR Gate
|
name: XOR Gate
|
||||||
description: Emits a boolean "1" if one of the inputs is truthy, but not both.
|
description: Издает значение "1" только один из входов положительный.
|
||||||
(Truthy means shape, color or boolean "1")
|
(Положительный - значит ресурс,
|
||||||
|
цвет или логическое значение "1")
|
||||||
or:
|
or:
|
||||||
name: OR Gate
|
name: OR Gate
|
||||||
description: Emits a boolean "1" if one of the inputs is truthy. (Truthy means
|
description: Издает значение "1" если хотя бы один вход положительный. (Положительный - значит ресурс,
|
||||||
shape, color or boolean "1")
|
цвет или логическое значение "1").
|
||||||
transistor:
|
transistor:
|
||||||
default:
|
default:
|
||||||
name: Transistor
|
name: Транзистор
|
||||||
description: Forwards the bottom input if the side input is truthy (a shape,
|
description: Пропускает нижний сигнал, если боковой сигнал положительный (ресурс,
|
||||||
color or "1").
|
цвет или логическое значение "1").
|
||||||
mirrored:
|
mirrored:
|
||||||
name: Transistor
|
name: Транзистор
|
||||||
description: Forwards the bottom input if the side input is truthy (a shape,
|
description: Пропускает нижний сигнал, если боковой сигнал положительный (ресурс,
|
||||||
color or "1").
|
цвет или логическое значение "1").
|
||||||
filter:
|
filter:
|
||||||
default:
|
default:
|
||||||
name: Filter
|
name: Фильтр
|
||||||
description: Connect a signal to route all matching items to the top and the
|
description: Подключите сигнал, чтобы направить все подходящие ресурсы наверх,
|
||||||
remaining to the right. Can be controlled with boolean signals
|
а остальные направо. Также контролируемо логическими
|
||||||
too.
|
сигналами.
|
||||||
display:
|
display:
|
||||||
default:
|
default:
|
||||||
name: Display
|
name: Экран
|
||||||
description: Connect a signal to show it on the display - It can be a shape,
|
description: Подключите сигнал, чтобы отобразить его на экране. Это может ресурс, цвет
|
||||||
color or boolean.
|
или логическое значение (1 / 0).
|
||||||
reader:
|
reader:
|
||||||
default:
|
default:
|
||||||
name: Belt Reader
|
name: Измеритель
|
||||||
description: Allows to measure the average belt throughput. Outputs the last
|
description: Позволяет измерять среднюю пропускную способность конвейера. Отображает последний
|
||||||
read item on the wires layer (once unlocked).
|
прошедший ресурс на слое с проводами (когда разблокировано).
|
||||||
analyzer:
|
analyzer:
|
||||||
default:
|
default:
|
||||||
name: Shape Analyzer
|
name: Анализатор Фигур
|
||||||
description: Analyzes the top right quadrant of the lowest layer of the shape
|
description: Анализирует правую верхнюю часть низшего слоя фигуры
|
||||||
and returns its shape and color.
|
и возвращает ее форму и цвет.
|
||||||
comparator:
|
comparator:
|
||||||
default:
|
default:
|
||||||
name: Compare
|
name: Сравнить
|
||||||
description: Returns boolean "1" if both signals are exactly equal. Can compare
|
description: Возвращает значение "1" если оба сигнала полностью одинаковы. Может сравнивать
|
||||||
shapes, items and booleans.
|
фигуры, цвета и логические значения.
|
||||||
virtual_processor:
|
virtual_processor:
|
||||||
default:
|
default:
|
||||||
name: Virtual Cutter
|
name: Виртуальный Резак
|
||||||
description: Virtually cuts the shape into two halves.
|
description: Виртуально разрезает фигуру пополам.
|
||||||
rotater:
|
rotater:
|
||||||
name: Virtual Rotater
|
name: Виртуальный Вращатель
|
||||||
description: Virtually rotates the shape, both clockwise and counter-clockwise.
|
description: Виртуально вращает фигуру как по часовой стрелке, так и против часовой стрелки.
|
||||||
unstacker:
|
unstacker:
|
||||||
name: Virtual Unstacker
|
name: Виртуальный Разъединитель
|
||||||
description: Virtually extracts the topmost layer to the right output and the
|
description: Виртуально извлекает самый верхний слой фигуры направо,
|
||||||
remaining ones to the left.
|
а все остальное направо.
|
||||||
stacker:
|
stacker:
|
||||||
name: Virtual Stacker
|
name: Виртуальный Объединитель
|
||||||
description: Virtually stacks the right shape onto the left.
|
description: Виртуально помещает правый предмет поверх левого.
|
||||||
painter:
|
painter:
|
||||||
name: Virtual Painter
|
name: Виртуальный Покрасчик
|
||||||
description: Virtually paints the shape from the bottom input with the shape on
|
description: Виртуально окрашивает фигуру из нижнего входа цветом из
|
||||||
the right input.
|
правого входа.
|
||||||
item_producer:
|
item_producer:
|
||||||
default:
|
default:
|
||||||
name: Item Producer
|
name: Генератор Ресурсов
|
||||||
description: Available in sandbox mode only, outputs the given signal from the
|
description: Доступен только в режиме песочницы, производит заданный на
|
||||||
wires layer on the regular layer.
|
слое с проводами сигнал на обычном слое.
|
||||||
storyRewards:
|
storyRewards:
|
||||||
reward_cutter_and_trash:
|
reward_cutter_and_trash:
|
||||||
title: Разрезание Фигур
|
title: Разрезание Фигур
|
||||||
desc: You just unlocked the <strong>cutter</strong>, which cuts shapes in half
|
desc: Разблокирован <strong>резак</strong>, который разрезает фигуры пополам
|
||||||
from top to bottom <strong>regardless of its
|
по вертикали <strong>независимо от ориентации</strong>!<br><br>Не забудьте избавляться от излишков,
|
||||||
orientation</strong>!<br><br>Be sure to get rid of the waste, or
|
иначе <strong>он забьется и остановится</strong> - для этого
|
||||||
otherwise <strong>it will clog and stall</strong> - For this purpose
|
я также открыл для Вас <strong>мусорку</strong>, которая уничтожает
|
||||||
I have given you the <strong>trash</strong>, which destroys
|
все, что в нее попадает!
|
||||||
everything you put into it!
|
|
||||||
reward_rotater:
|
reward_rotater:
|
||||||
title: Вращение
|
title: Вращение
|
||||||
desc: Разблокирован <strong>вращатель</strong>! Он поворачивает фигуры по
|
desc: Разблокирован <strong>вращатель</strong>! Он поворачивает фигуры по
|
||||||
@ -616,9 +612,9 @@ storyRewards:
|
|||||||
правого входа <strong>наложится</strong> на фигуру из левого!
|
правого входа <strong>наложится</strong> на фигуру из левого!
|
||||||
reward_splitter:
|
reward_splitter:
|
||||||
title: Разделитель / Соединитель
|
title: Разделитель / Соединитель
|
||||||
desc: You have unlocked a <strong>splitter</strong> variant of the
|
desc: Разблокирован <strong>разделитель</strong> один из вариантов
|
||||||
<strong>balancer</strong> - It accepts one input and splits them
|
<strong>балансера</strong> - он принимает один вход и разделяет его
|
||||||
into two!
|
на два!
|
||||||
reward_tunnel:
|
reward_tunnel:
|
||||||
title: Туннель
|
title: Туннель
|
||||||
desc: Разблокирован <strong>туннель</strong>! Теперь вы можете транспортировать
|
desc: Разблокирован <strong>туннель</strong>! Теперь вы можете транспортировать
|
||||||
@ -630,10 +626,9 @@ storyRewards:
|
|||||||
<strong>нажмите 'T', чтобы переключить вариант</strong>!
|
<strong>нажмите 'T', чтобы переключить вариант</strong>!
|
||||||
reward_miner_chainable:
|
reward_miner_chainable:
|
||||||
title: Цепной Экстрактор
|
title: Цепной Экстрактор
|
||||||
desc: "You have unlocked the <strong>chained extractor</strong>! It can
|
desc: "Разблокирован <strong>цепной экстрактор</strong>! Он может <strong>передавать
|
||||||
<strong>forward its resources</strong> to other extractors so you
|
свои ресурсы</strong> другим экстракторам, чтобы вы могли эффективнее извлекать ресурсы!<br><br>
|
||||||
can more efficiently extract resources!<br><br> PS: The old
|
PS: Старый экстрактор был заменен в панели инструментов!"
|
||||||
extractor has been replaced in your toolbar now!"
|
|
||||||
reward_underground_belt_tier_2:
|
reward_underground_belt_tier_2:
|
||||||
title: Туннель II
|
title: Туннель II
|
||||||
desc: Разблокирован новый вариант <strong>туннеля</strong> с <strong>большей
|
desc: Разблокирован новый вариант <strong>туннеля</strong> с <strong>большей
|
||||||
@ -649,18 +644,18 @@ storyRewards:
|
|||||||
одновременно</strong>, потребляя только один краситель вместо двух!
|
одновременно</strong>, потребляя только один краситель вместо двух!
|
||||||
reward_storage:
|
reward_storage:
|
||||||
title: Буферное Хранилище
|
title: Буферное Хранилище
|
||||||
desc: You have unlocked the <strong>storage</strong> building - It allows you to
|
desc: Разблокировано <strong>буферное хранилище</strong> - оно позволяет
|
||||||
store items up to a given capacity!<br><br> It priorities the left
|
хранить в нем ресурсы пока есть место! <br><br> Левый выход в
|
||||||
output, so you can also use it as an <strong>overflow gate</strong>!
|
приоритете, может быть использован как <strong>буфер</strong>!
|
||||||
reward_freeplay:
|
reward_freeplay:
|
||||||
title: Свободная игра
|
title: Свободная игра
|
||||||
desc: You did it! You unlocked the <strong>free-play mode</strong>! This means
|
desc: У Вас получилось! Разблокирован <strong>свободный режим</strong>! Это означает
|
||||||
that shapes are now <strong>randomly</strong> generated!<br><br>
|
что теперь фигуры будут генерироваться <strong>случайно</strong>!<br><br>
|
||||||
Since the hub will require a <strong>throughput</strong> from now
|
Так как ХАБ отныне будет требовать определенную <strong>пропускную способность</strong>,
|
||||||
on, I highly recommend to build a machine which automatically
|
я настоятельно рекомендую построить механизм, автоматически
|
||||||
delivers the requested shape!<br><br> The HUB outputs the requested
|
доставляющий запрашиваемую фигуру!<br><br> ХАБ выводит запрашиваемую
|
||||||
shape on the wires layer, so all you have to do is to analyze it and
|
фигуру на слое с проводами, так что все, что необходимо сделать, - это
|
||||||
automatically configure your factory based on that.
|
проанализировать ее и автоматически настроить вашу фабрику.
|
||||||
reward_blueprints:
|
reward_blueprints:
|
||||||
title: Чертежи
|
title: Чертежи
|
||||||
desc: Теперь вы можете <strong>копировать и вставлять</strong> части вашей
|
desc: Теперь вы можете <strong>копировать и вставлять</strong> части вашей
|
||||||
@ -678,70 +673,69 @@ storyRewards:
|
|||||||
title: Следующий уровень
|
title: Следующий уровень
|
||||||
desc: Поздравляем! Кстати, больше контента планируется для полной версии!
|
desc: Поздравляем! Кстати, больше контента планируется для полной версии!
|
||||||
reward_balancer:
|
reward_balancer:
|
||||||
title: Balancer
|
title: Балансер
|
||||||
desc: The multifunctional <strong>balancer</strong> has been unlocked - It can
|
desc: Многофункциональный <strong>балансер</strong> разблокирован - он может
|
||||||
be used to build bigger factories by <strong>splitting and merging
|
быть использован для строительства огромных фабрик, <strong>разделяя и объединяя ресурсы</strong>
|
||||||
items</strong> onto multiple belts!<br><br>
|
на множество конвейеров!<br><br>
|
||||||
reward_merger:
|
reward_merger:
|
||||||
title: Compact Merger
|
title: Компактный Соединитель
|
||||||
desc: You have unlocked a <strong>merger</strong> variant of the
|
desc: Разблокирован <strong>соединитель</strong> - вариант
|
||||||
<strong>balancer</strong> - It accepts two inputs and merges them
|
<strong>балансера</strong> - он принимает два входа и объединяет их
|
||||||
into one belt!
|
в один конвейер.
|
||||||
reward_belt_reader:
|
reward_belt_reader:
|
||||||
title: Belt reader
|
title: Измеритель
|
||||||
desc: You have now unlocked the <strong>belt reader</strong>! It allows you to
|
desc: Разблокирован <strong>измеритель</strong>! Он позволяет
|
||||||
measure the throughput of a belt.<br><br>And wait until you unlock
|
измерять пропускную способность конвейера.<br><br>А как полезен он будет,
|
||||||
wires - then it gets really useful!
|
когда вы разблокируете провода!
|
||||||
reward_rotater_180:
|
reward_rotater_180:
|
||||||
title: Rotater (180 degrees)
|
title: Вращатель (180 градусов)
|
||||||
desc: You just unlocked the 180 degress <strong>rotater</strong>! - It allows
|
desc: Разблокирован <strong>rotater</strong> на 180 градусов! - Он позволяет
|
||||||
you to rotate a shape by 180 degress (Surprise! :D)
|
вращать фигур на 180 градусов (Сюрприз! :D)
|
||||||
reward_display:
|
reward_display:
|
||||||
title: Display
|
title: Экран
|
||||||
desc: "You have unlocked the <strong>Display</strong> - Connect a signal on the
|
desc: "Разблокирован <strong>Экран</strong> - Подключите сигнал на слое
|
||||||
wires layer to visualize it!<br><br> PS: Did you notice the belt
|
с проводами чтобы отобразить его!<br><br> PS: Заметили ли вы, что измеритель
|
||||||
reader and storage output their last read item? Try showing it on a
|
и буферное хранилище отображают последний ресурс, прошедший через них? Попробуйте
|
||||||
display!"
|
отобразить его на экране!"
|
||||||
reward_constant_signal:
|
reward_constant_signal:
|
||||||
title: Constant Signal
|
title: Постоянный Сигнал
|
||||||
desc: You unlocked the <strong>constant signal</strong> building on the wires
|
desc: Разблокирован <strong>постоянный сигнал</strong> на слое с проводами!
|
||||||
layer! This is useful to connect it to <strong>item filters</strong>
|
Он полезен для подключения к <strong>фильтрам</strong>,
|
||||||
for example.<br><br> The constant signal can emit a
|
например.<br><br> Постоянный сигнал может издавать <strong>фигуру</strong>, <strong>цвет</strong> или
|
||||||
<strong>shape</strong>, <strong>color</strong> or
|
<strong>логическое значение</strong> (1 / 0).
|
||||||
<strong>boolean</strong> (1 / 0).
|
|
||||||
reward_logic_gates:
|
reward_logic_gates:
|
||||||
title: Logic Gates
|
title: Логические Элементы
|
||||||
desc: You unlocked <strong>logic gates</strong>! You don't have to be excited
|
desc: Разблокированы <strong>логические элементы</strong>! Вы не обязаны радоваться
|
||||||
about this, but it's actually super cool!<br><br> With those gates
|
по этому поводу, но вообще это очень круто!<br><br> С этими элементами
|
||||||
you can now compute AND, OR, XOR and NOT operations.<br><br> As a
|
теперь вы можете производить И, ИЛИ, исключающее ИЛИ и НЕ операции.<br><br>
|
||||||
bonus on top I also just gave you a <strong>transistor</strong>!
|
Как бонус, я также дал вам <strong>транзистор</strong>!
|
||||||
reward_virtual_processing:
|
reward_virtual_processing:
|
||||||
title: Virtual Processing
|
title: Виртуальное Производство
|
||||||
desc: I just gave a whole bunch of new buildings which allow you to
|
desc: Только что я открыл вам множество новых построек, которые позволят
|
||||||
<strong>simulate the processing of shapes</strong>!<br><br> You can
|
<strong>симулировать производство фигур</strong>!<br><br> Теперь вы
|
||||||
now simulate a cutter, rotater, stacker and more on the wires layer!
|
можете симулировать резак, вращатель, объединитель и др. на слое с проводами!
|
||||||
With this you now have three options to continue the game:<br><br> -
|
Теперь у вас есть три варианта продолжения игры:<br><br> - Построить
|
||||||
Build an <strong>automated machine</strong> to create any possible
|
<strong>автоматический механизм</strong> для производства любой
|
||||||
shape requested by the HUB (I recommend to try it!).<br><br> - Build
|
фигуры, запрашиваемой ХАБ (рекомендую попробовать!).<br><br> - Построить
|
||||||
something cool with wires.<br><br> - Continue to play
|
что-то клевое, используя провода.<br><br> - Продолжить обычную
|
||||||
regulary.<br><br> Whatever you choose, remember to have fun!
|
игру. <br><br> Что бы вы не выбрали, не забывайте хорошо проводить время!
|
||||||
reward_wires_painter_and_levers:
|
reward_wires_painter_and_levers:
|
||||||
title: Wires & Quad Painter
|
title: Провода & Покрасчик (4 входа)
|
||||||
desc: "You just unlocked the <strong>Wires Layer</strong>: It is a separate
|
desc: "Разблокирован <strong>Слой с Проводами</strong>. Это отдельный
|
||||||
layer on top of the regular layer and introduces a lot of new
|
слой поверх обычного слоя, добавляющий множество новых
|
||||||
mechanics!<br><br> For the beginning I unlocked you the <strong>Quad
|
механик!<br><br> Для начала я разблокировал <strong>Покрасчик
|
||||||
Painter</strong> - Connect the slots you would like to paint with on
|
на четыре входа</strong> - соедините ячейки, которые вы бы хотели окрасить на
|
||||||
the wires layer!<br><br> To switch to the wires layer, press
|
слое с проводами!<br><br> Чтобы переключиться на слой слой с проводами, нажмите
|
||||||
<strong>E</strong>."
|
<strong>E</strong>."
|
||||||
reward_filter:
|
reward_filter:
|
||||||
title: Item Filter
|
title: Фильтр
|
||||||
desc: You unlocked the <strong>Item Filter</strong>! It will route items either
|
desc: Разблокирован <strong>Фильтр</strong>! Он направит ресурсы
|
||||||
to the top or the right output depending on whether they match the
|
наверх или направо в зависмости от того, совпадают ли они с
|
||||||
signal from the wires layer or not.<br><br> You can also pass in a
|
установленным сигналом. <br><br> Вы также можете передавать
|
||||||
boolean signal (1 / 0) to entirely activate or disable it.
|
логические значения (1 / 0), чтобы полностью отключить или включить его.
|
||||||
reward_demo_end:
|
reward_demo_end:
|
||||||
title: End of Demo
|
title: Конец Демо
|
||||||
desc: You have reached the end of the demo version!
|
desc: Вы достигли конца демоверсии игры!
|
||||||
settings:
|
settings:
|
||||||
title: Настройки
|
title: Настройки
|
||||||
categories:
|
categories:
|
||||||
@ -835,9 +829,9 @@ settings:
|
|||||||
description: Включает виньетирование, которое затемняет углы экрана и облегчает
|
description: Включает виньетирование, которое затемняет углы экрана и облегчает
|
||||||
чтение текста.
|
чтение текста.
|
||||||
autosaveInterval:
|
autosaveInterval:
|
||||||
title: Интервал авто-сохранения
|
title: Интервал автосохранения
|
||||||
description: Управляет тем, как часто игра автоматически сохраняется. Также
|
description: Управляет тем, как часто игра автоматически сохраняется. Также
|
||||||
здесь можно полностью отключить авто-сохранение.
|
здесь можно полностью отключить автосохранение.
|
||||||
intervals:
|
intervals:
|
||||||
one_minute: 1 Минута
|
one_minute: 1 Минута
|
||||||
two_minutes: 2 Минуты
|
two_minutes: 2 Минуты
|
||||||
@ -864,47 +858,46 @@ settings:
|
|||||||
установлен. С этой настройкой может быть удобнее, при частом
|
установлен. С этой настройкой может быть удобнее, при частом
|
||||||
переключении между различными типами зданий.
|
переключении между различными типами зданий.
|
||||||
soundVolume:
|
soundVolume:
|
||||||
title: Sound Volume
|
title: Громкость Звука
|
||||||
description: Set the volume for sound effects
|
description: Задает громкость звуковых эффектов.
|
||||||
musicVolume:
|
musicVolume:
|
||||||
title: Music Volume
|
title: Music Volume
|
||||||
description: Set the volume for music
|
description: Задает громкость музыки.
|
||||||
lowQualityMapResources:
|
lowQualityMapResources:
|
||||||
title: Low Quality Map Resources
|
title: Низкое качество ресурсов на карте
|
||||||
description: Simplifies the rendering of resources on the map when zoomed in to
|
description: Упрощает отображение ресурсов на карте при приближении для
|
||||||
improve performance. It even looks cleaner, so be sure to try it
|
улучшения производительности. Оно даже выглядит аккуратнее, поэтому обязательно
|
||||||
out!
|
попробуйте!
|
||||||
disableTileGrid:
|
disableTileGrid:
|
||||||
title: Disable Grid
|
title: Отключить Сетку
|
||||||
description: Disabling the tile grid can help with the performance. This also
|
description: Отключение разделительной сетки может помочь улучшить производительность. Кроме того,
|
||||||
makes the game look cleaner!
|
делает игру визуально проще!
|
||||||
clearCursorOnDeleteWhilePlacing:
|
clearCursorOnDeleteWhilePlacing:
|
||||||
title: Clear Cursor on Right Click
|
title: Очистить Курсор на ПКМ
|
||||||
description: Enabled by default, clears the cursor whenever you right click
|
description: Включено по умолчанию, очищает курсор от выбранной постройки
|
||||||
while you have a building selected for placement. If disabled,
|
при нажатии на ПКМ. Если отключено, вы можете удалять постройки
|
||||||
you can delete buildings by right-clicking while placing a
|
при нажатии на ПКМ во время строительства.
|
||||||
building.
|
|
||||||
lowQualityTextures:
|
lowQualityTextures:
|
||||||
title: Low quality textures (Ugly)
|
title: Низкое качество текстур (Некрасиво)
|
||||||
description: Uses low quality textures to save performance. This will make the
|
description: Использует низкое качество текстур, чтобы улучшить производительность. Это сделает
|
||||||
game look very ugly!
|
игру очень некрасивой!
|
||||||
displayChunkBorders:
|
displayChunkBorders:
|
||||||
title: Display Chunk Borders
|
title: Отображать границы чанков
|
||||||
description: The game is divided into chunks of 16x16 tiles, if this setting is
|
description: Эта игра разделена на чанки, состоящие из 16x16 ячеек, если эта настройка
|
||||||
enabled the borders of each chunk are displayed.
|
включена, границы чанков будут отображаться.
|
||||||
pickMinerOnPatch:
|
pickMinerOnPatch:
|
||||||
title: Pick miner on resource patch
|
title: Выбрать Экстрактор над Жилой
|
||||||
description: Enabled by default, selects the miner if you use the pipette when
|
description: Включено по умолчанию, выбирает экстрактор, если использовать пипетку
|
||||||
hovering a resource patch.
|
над жилой с ресурсами.
|
||||||
simplifiedBelts:
|
simplifiedBelts:
|
||||||
title: Simplified Belts (Ugly)
|
title: Упрощенные Конвейеры (Некрасиво)
|
||||||
description: Does not render belt items except when hovering the belt to save
|
description: Не отображает ресурсы, находящиеся на конвейере, если не навести курсор для улучшения
|
||||||
performance. I do not recommend to play with this setting if you
|
производительности. Не рекомендую играть с этой настройкой, если вас
|
||||||
do not absolutely need the performance.
|
устраивает производительность.
|
||||||
enableMousePan:
|
enableMousePan:
|
||||||
title: Enable Mouse Pan
|
title: Включить Перемещение Мышкой
|
||||||
description: Allows to move the map by moving the cursor to the edges of the
|
description: Позволяет двигать карту, перемещая курсор к краям
|
||||||
screen. The speed depends on the Movement Speed setting.
|
экрана. Скорость зависит от настройки Скорости движения.
|
||||||
rangeSliderPercentage: <amount> %
|
rangeSliderPercentage: <amount> %
|
||||||
keybindings:
|
keybindings:
|
||||||
title: Настройки управления
|
title: Настройки управления
|
||||||
@ -951,9 +944,9 @@ keybindings:
|
|||||||
massSelectStart: Модификатор для выделения области
|
massSelectStart: Модификатор для выделения области
|
||||||
massSelectSelectMultiple: Выбрать несколько областей
|
massSelectSelectMultiple: Выбрать несколько областей
|
||||||
massSelectCopy: Копировать область
|
massSelectCopy: Копировать область
|
||||||
placementDisableAutoOrientation: Отключить авто-определение направления
|
placementDisableAutoOrientation: Отключить автоопределение направления
|
||||||
placeMultiple: Оставаться в режиме размещения
|
placeMultiple: Оставаться в режиме размещения
|
||||||
placeInverse: Инвертировать авто-определение направления конвейеров
|
placeInverse: Инвертировать автоопределение направления конвейеров
|
||||||
pasteLastBlueprint: Вставить последний чертеж
|
pasteLastBlueprint: Вставить последний чертеж
|
||||||
massSelectCut: Вырезать область
|
massSelectCut: Вырезать область
|
||||||
exportScreenshot: Экспорт всей Базы в виде Изображения
|
exportScreenshot: Экспорт всей Базы в виде Изображения
|
||||||
@ -964,21 +957,21 @@ keybindings:
|
|||||||
menuClose: Закрыть меню
|
menuClose: Закрыть меню
|
||||||
switchLayers: Переключить слои
|
switchLayers: Переключить слои
|
||||||
wire: Энергетический провод
|
wire: Энергетический провод
|
||||||
balancer: Balancer
|
balancer: Балансер
|
||||||
storage: Storage
|
storage: Буферное Хранилище
|
||||||
constant_signal: Constant Signal
|
constant_signal: Постоянный Сигнал
|
||||||
logic_gate: Logic Gate
|
logic_gate: Логический Элемент
|
||||||
lever: Switch (regular)
|
lever: Переключатель (обычный)
|
||||||
filter: Filter
|
filter: Фильтр
|
||||||
wire_tunnel: Wire Crossing
|
wire_tunnel: Пересечение Проводов
|
||||||
display: Display
|
display: Экран
|
||||||
reader: Belt Reader
|
reader: Измеритель
|
||||||
virtual_processor: Virtual Cutter
|
virtual_processor: Виртуальный Резак
|
||||||
transistor: Transistor
|
transistor: Транзистор
|
||||||
analyzer: Shape Analyzer
|
analyzer: Анализатор Фигур
|
||||||
comparator: Compare
|
comparator: Сравнить
|
||||||
item_producer: Item Producer (Sandbox)
|
item_producer: Генератор Ресурсов (Песочница)
|
||||||
copyWireValue: "Wires: Copy value below cursor"
|
copyWireValue: "Провода: скопировать значение под курсором"
|
||||||
about:
|
about:
|
||||||
title: Об игре
|
title: Об игре
|
||||||
body: >-
|
body: >-
|
||||||
@ -988,7 +981,8 @@ about:
|
|||||||
|
|
||||||
Если вы хотите внести свой вклад игре - <a href="<githublink>" target="_blank">shapez.io в github</a>.<br><br>
|
Если вы хотите внести свой вклад игре - <a href="<githublink>" target="_blank">shapez.io в github</a>.<br><br>
|
||||||
|
|
||||||
Эта игра не была бы возможна без большого сообщества в дискорде, которое собралось вокруг моих игр - Вам действительно стоит присоединиться к <a href="<discordlink>" target="_blank">серверу Discord!</a>!<br><br>
|
Эта игра не была бы возможна без большого сообщества в дискорде, которое собралось вокруг моих игр - Вам действительно стоит присоединиться к
|
||||||
|
<a href="<discordlink>" target="_blank">серверу Discord!</a>!<br><br>
|
||||||
|
|
||||||
Саундтрек сделал <a href="https://soundcloud.com/pettersumelius" target="_blank">Peppsen</a> - Он потрясающий.<br><br>
|
Саундтрек сделал <a href="https://soundcloud.com/pettersumelius" target="_blank">Peppsen</a> - Он потрясающий.<br><br>
|
||||||
|
|
||||||
@ -1002,65 +996,57 @@ demo:
|
|||||||
oneGameLimit: Ограниченность одним сохранением игры
|
oneGameLimit: Ограниченность одним сохранением игры
|
||||||
customizeKeybindings: Пользовательская настройка Управления
|
customizeKeybindings: Пользовательская настройка Управления
|
||||||
exportingBase: Экспорт всей Базы в виде Изображения
|
exportingBase: Экспорт всей Базы в виде Изображения
|
||||||
settingNotAvailable: Не доступно в демо-версии.
|
settingNotAvailable: Недоступно в демоверсии.
|
||||||
tips:
|
tips:
|
||||||
- The hub accepts input of any kind, not just the current shape!
|
- ХАБ принимает любые ресурсы, не только текущую фигуру!
|
||||||
- Make sure your factories are modular - it will pay out!
|
- Старайтесь создавать модульные фабрики - вы не пожалеете!
|
||||||
- Don't build too close to the hub, or it will be a huge chaos!
|
- Не стройте слишком близко к ХАБ-у, иначе начнется ужасный хаос!
|
||||||
- If stacking does not work, try switching the inputs.
|
- Если не получается объединить фигуры, попробуйте поменять входы местами!
|
||||||
- You can toggle the belt planner direction by pressing <b>R</b>.
|
- Вы можете изменить направление конвейера при строительстве, нажав <b>R</b>.
|
||||||
- Holding <b>CTRL</b> allows dragging of belts without auto-orientation.
|
- Удерживая <b>CTRL</b>, вы можете перемещать конвейеры без авто ориентации.
|
||||||
- Ratios stay the same, as long as all upgrades are on the same Tier.
|
- Соотношения всегда одинаковы, если уровни улучшений равны.
|
||||||
- Serial execution is more efficient than parallel.
|
- Последовательное выполнение эффективнее, чем параллельное.
|
||||||
- You will unlock more variants of buildings later in the game!
|
- Вам будут открываться новые варианты построек по мере прохождения!
|
||||||
- You can use <b>T</b> to switch between different variants.
|
- Нажмите <b>T</b>, чтобы переключаться между различными вариантами.
|
||||||
- Symmetry is key!
|
- Симметрия - ключ к успеху!
|
||||||
- You can weave different tiers of tunnels.
|
- Вы можете переплетать между собой туннели разных уровней.
|
||||||
- Try to build compact factories - it will pay out!
|
- Попробуйте строить компактные фабрики - вы не пожалеете!
|
||||||
- The painter has a mirrored variant which you can select with <b>T</b>
|
- Покрасчик имеет зеркальный вариант, который может быть выбран, нажав <b>T</b>.
|
||||||
- Having the right building ratios will maximize efficiency.
|
- Правильные соотношения построек позволяет улучшить эффективность фабрики.
|
||||||
- At maximum level, 5 extractors will fill a single belt.
|
- Удерживая <b>SHIFT</b>, вы можете легко строить длинные конвейерные линии.
|
||||||
- Don't forget about tunnels!
|
- Резаки всегда разрезают пополам по вертикали вне зависимости от ориентации.
|
||||||
- You don't need to divide up items evenly for full efficiency.
|
- Чтобы получить белый цвет, смешайте все три цвета.
|
||||||
- Holding <b>SHIFT</b> will activate the belt planner, letting you place
|
- Левый выход Буферного Хранилища - в приоритете.
|
||||||
long lines of belts easily.
|
- Вкладывайте время в строительство повторяемых механизмов - оно того стоит!
|
||||||
- Cutters always cut vertically, regardless of their orientation.
|
- Удерживая <b>CTRL</b>, можно размещать много построек за раз.
|
||||||
- To get white mix all three colors.
|
- Вы можете удерживать <b>ALT</b>, чтобы инвертировать направление размещенных конвейеров.
|
||||||
- The storage buffer priorities the first output.
|
- Эффективность - ключ к успеху!
|
||||||
- Invest time to build repeatable designs - it's worth it!
|
- Чем дальше от ХАБ-а, тем Жилы с ресурсами сложнее.
|
||||||
- Holding <b>CTRL</b> allows to place multiple buildings.
|
- Механизмы имеют ограниченную скорость, разбивайте их для максимальной эффективности.
|
||||||
- You can hold <b>ALT</b> to invert the direction of placed belts.
|
- Используйте балансеры, чтобы максимизировать эффективность.
|
||||||
- Efficiency is key!
|
- Организация очень важна, старайтесь не пересекать конвейеры слишком часто.
|
||||||
- Shape patches that are further away from the hub are more complex.
|
- Планируйте заранее, иначе начнется ужасный хаос!
|
||||||
- Machines have a limited speed, divide them up for maximum efficiency.
|
- Не удаляйте свои старые фабрики! Они понадобятся вам, чтобы открывать улучшения.
|
||||||
- Use balancers to maximize your efficiency.
|
- Попробуйте пройти 20-ый уровень самостоятельно, прежде чем искать помощи!
|
||||||
- Organization is important. Try not to cross conveyors too much.
|
- Не усложняйте себе жизнь, старайтесь думать проще и вы достигните больших высот.
|
||||||
- Plan in advance, or it will be a huge chaos!
|
- Вам может снова понадобиться ваша старая фабрика позже в игре. Старайтесь планировать фабрику, чтобы она могла быть повторно использована.
|
||||||
- Don't remove your old factories! You'll need them to unlock upgrades.
|
- Иногда, вы можете найти необходимую фигуру на карте, вместо того, чтобы создавать ее самостоятельно.
|
||||||
- Try beating level 20 on your own before seeking for help!
|
- Полноценные мельницы/вертушки никогда не генерируются натурально.
|
||||||
- Don't complicate things, try to stay simple and you'll go far.
|
- Окрашивайте свои фигуры, прежде чем разрезать для максимальной эффективности.
|
||||||
- You may need to re-use factories later in the game. Plan your factories to
|
- С модулями теряется восприятие пространства; забота смертных.
|
||||||
be re-usable.
|
- Создайте отдельную фабрику чертежей. Они очень важны для модулей.
|
||||||
- Sometimes, you can find a needed shape in the map without creating it with
|
- Взгляните внимательнее на смешиватель и вы найдете ответы на свои вопросы.
|
||||||
stackers.
|
- Чтобы выделить область, используйте <b>CTRL</b> + Клик.
|
||||||
- Full windmills / pinwheels can never spawn naturally.
|
- Строительство вблизи ХАБ-а может помешать будущим проектам.
|
||||||
- Color your shapes before cutting for maximum efficiency.
|
- Иконка булавки на каждой фигуре закрепляет ее на экране.
|
||||||
- With modules, space is merely a perception; a concern for mortal men.
|
- Смешайте все три основных цвета, чтобы получить белый!
|
||||||
- Make a separate blueprint factory. They're important for modules.
|
- В вашем распоряжении бесконечная карта! Не загромождайте вашу фабрику, расширяйтесь!
|
||||||
- Have a closer look on the color mixer, and your questions will be answered.
|
- Также попробуйте Factorio. Это моя любимая игра.
|
||||||
- Use <b>CTRL</b> + Click to select an area.
|
- Резак(4 входа) разрезает по часовой стрелке, начиная с правой верхней части!
|
||||||
- Building too close to the hub can get in the way of later projects.
|
- Вы можете скачать свои сохранения в главном меню!
|
||||||
- The pin icon next to each shape in the upgrade list pins it to the screen.
|
- В этой игре множество полезных комбинаций клавиш. Загляните в настройки, чтобы ознакомиться с ними.
|
||||||
- Mix all primary colors together to make white!
|
- В этой игре множество настроек, не забудьте с ними ознакомиться.
|
||||||
- You have an infinite map, don't cramp your factory, expand!
|
- Маркер ХАБ-а имеет небольшой компас, указывающий его направление.
|
||||||
- Also try Factorio! It's my favorite game.
|
- Нажмите F4, чтобы показать FPS и Частоту Обновления.
|
||||||
- The quad cutter cuts clockwise starting from the top right!
|
- Нажмите F4 дважды, чтобы показать координаты курсора и камеры.
|
||||||
- You can download your savegames in the main menu!
|
- Вы можете нажать на закрепленную фигуру слева, чтобы открепить ее.
|
||||||
- This game has a lot of useful keybindings! Be sure to check out the
|
|
||||||
settings page.
|
|
||||||
- This game has a lot of settings, be sure to check them out!
|
|
||||||
- The marker to your hub has a small compass to indicate its direction!
|
|
||||||
- To clear belts, cut the area and then paste it at the same location.
|
|
||||||
- Press F4 to show your FPS and Tick Rate.
|
|
||||||
- Press F4 twice to show the tile of your mouse and camera.
|
|
||||||
- You can click a pinned shape on the left side to unpin it.
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ steamPage:
|
|||||||
discordLinkShort: Official Discord
|
discordLinkShort: Official Discord
|
||||||
intro: >-
|
intro: >-
|
||||||
Shapez.io is a relaxed game in which you have to build factories for the
|
Shapez.io is a relaxed game in which you have to build factories for the
|
||||||
automated production of geometric shapes.
|
automated production of geometric shapes.
|
||||||
|
|
||||||
As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map.
|
As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map.
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@ steamPage:
|
|||||||
discordLinkShort: Official Discord
|
discordLinkShort: Official Discord
|
||||||
intro: >-
|
intro: >-
|
||||||
Shapez.io is a relaxed game in which you have to build factories for the
|
Shapez.io is a relaxed game in which you have to build factories for the
|
||||||
automated production of geometric shapes.
|
automated production of geometric shapes.
|
||||||
|
|
||||||
As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map.
|
As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map.
|
||||||
|
|
||||||
|
|||||||