Updated to 1.4.4
@ -39,7 +39,7 @@ You can use [Gitpod](https://www.gitpod.io/) (an Online Open Source VS Code-like
|
||||
- install all of the dependencies.
|
||||
- start `gulp` in `gulp/` directory.
|
||||
|
||||
[](https://gitpod.io/from-referrer/)
|
||||
[](https://gitpod.io/#https://github.com/tobspr/shapez.io)
|
||||
|
||||
## Helping translate
|
||||
|
||||
|
||||
1
electron_wegame/README.md
Normal file
@ -0,0 +1 @@
|
||||
To build, place the lib64 folder from the wegame sdk for electron 13 in `wegame_sdk` and run the `wegame.main.standalone` gulp task.
|
||||
@ -51,8 +51,9 @@ function createWindow() {
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
webSecurity: false,
|
||||
contextIsolation: false,
|
||||
},
|
||||
// allowRunningInsecureContent: false,
|
||||
allowRunningInsecureContent: false,
|
||||
});
|
||||
|
||||
if (isLocal) {
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
"start": "electron --disable-direct-composition --in-process-gpu ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "3.1.13"
|
||||
"electron": "^13.1.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"async-lock": "^1.2.8"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
const railsdk = require("./wegame_sdk/railsdk.js");
|
||||
const { dialog } = require("electron");
|
||||
const { dialog, app, remote, ipcMain } = require("electron");
|
||||
|
||||
function init(isDev) {
|
||||
console.log("Step 1: wegame: init");
|
||||
@ -39,7 +39,7 @@ function init(isDev) {
|
||||
event.state === railsdk.RailSystemState.kSystemStatePlatformExit ||
|
||||
event.state === railsdk.RailSystemState.kSystemStateGameExitByAntiAddiction
|
||||
) {
|
||||
remote.app.exit();
|
||||
app.exit();
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -47,6 +47,17 @@ function init(isDev) {
|
||||
|
||||
function listen() {
|
||||
console.log("wegame: listen");
|
||||
ipcMain.handle("profanity-check", async (event, data) => {
|
||||
if (data.length === 0) {
|
||||
return "";
|
||||
}
|
||||
const result = railsdk.RailUtils.DirtyWordsFilter(data, true);
|
||||
if (result.check_result.dirty_type !== 0 /** kRailDirtyWordsTypeNormalAllowWords */) {
|
||||
return result.check_result.replace_string;
|
||||
}
|
||||
|
||||
return data;
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { init, listen };
|
||||
|
||||
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 37 KiB |
BIN
res/ui/interactive_tutorial.cn.noinline/1_1_extractor.gif
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
res/ui/interactive_tutorial.cn.noinline/1_2_conveyor.gif
Normal file
|
After Width: | Height: | Size: 297 KiB |
BIN
res/ui/interactive_tutorial.cn.noinline/1_3_expand.gif
Normal file
|
After Width: | Height: | Size: 993 KiB |
|
After Width: | Height: | Size: 809 KiB |
BIN
res/ui/interactive_tutorial.cn.noinline/21_2_switch_to_wires.gif
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
res/ui/interactive_tutorial.cn.noinline/21_3_place_button.gif
Normal file
|
After Width: | Height: | Size: 531 KiB |
BIN
res/ui/interactive_tutorial.cn.noinline/21_4_press_button.gif
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
res/ui/interactive_tutorial.cn.noinline/2_1_place_cutter.gif
Normal file
|
After Width: | Height: | Size: 502 KiB |
BIN
res/ui/interactive_tutorial.cn.noinline/2_2_place_trash.gif
Normal file
|
After Width: | Height: | Size: 575 KiB |
BIN
res/ui/interactive_tutorial.cn.noinline/2_3_more_cutters.gif
Normal file
|
After Width: | Height: | Size: 776 KiB |
BIN
res/ui/interactive_tutorial.cn.noinline/3_1_rectangles.gif
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
res/ui/wegame_isbn_rating.jpg
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
@ -137,16 +137,20 @@
|
||||
|
||||
button.continue {
|
||||
background: #555;
|
||||
@include S(margin-right, 10px);
|
||||
}
|
||||
|
||||
button.menu {
|
||||
background: #555;
|
||||
}
|
||||
|
||||
button.nextPuzzle {
|
||||
background-color: $colorGreenBright;
|
||||
}
|
||||
|
||||
> button {
|
||||
@include S(min-width, 100px);
|
||||
@include S(padding, 10px, 20px);
|
||||
@include S(padding, 8px, 16px);
|
||||
@include S(margin, 0, 6px);
|
||||
@include IncreasedClickArea(0px);
|
||||
}
|
||||
}
|
||||
|
||||
41
src/css/ingame_hud/puzzle_next.scss
Normal file
@ -0,0 +1,41 @@
|
||||
#ingame_HUD_PuzzleNextPuzzle {
|
||||
position: absolute;
|
||||
@include S(top, 17px);
|
||||
@include S(right, 10px);
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
backdrop-filter: blur(D(1px));
|
||||
padding: D(3px);
|
||||
|
||||
> .button {
|
||||
@include ButtonText;
|
||||
@include IncreasedClickArea(0px);
|
||||
pointer-events: all;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
color: #333438;
|
||||
transition: all 0.12s ease-in-out;
|
||||
text-transform: uppercase;
|
||||
transition-property: opacity, transform;
|
||||
@include PlainText;
|
||||
@include S(padding-right, 25px);
|
||||
opacity: 1;
|
||||
|
||||
@include DarkThemeInvert;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.9 !important;
|
||||
}
|
||||
|
||||
&.pressed {
|
||||
transform: scale(0.95) !important;
|
||||
}
|
||||
|
||||
& {
|
||||
/* @load-async */
|
||||
background: uiResource("icons/state_next_button.png") right center / D(15px) no-repeat;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -21,6 +21,7 @@
|
||||
@import "adinplay";
|
||||
@import "changelog_skins";
|
||||
|
||||
@import "states/wegame_splash";
|
||||
@import "states/preload";
|
||||
@import "states/main_menu";
|
||||
@import "states/ingame";
|
||||
@ -64,6 +65,7 @@
|
||||
@import "ingame_hud/puzzle_play_settings";
|
||||
@import "ingame_hud/puzzle_play_metadata";
|
||||
@import "ingame_hud/puzzle_complete_notification";
|
||||
@import "ingame_hud/puzzle_next";
|
||||
|
||||
// prettier-ignore
|
||||
$elements:
|
||||
@ -82,6 +84,7 @@ ingame_HUD_PinnedShapes,
|
||||
ingame_HUD_GameMenu,
|
||||
ingame_HUD_KeybindingOverlay,
|
||||
ingame_HUD_PuzzleBackToMenu,
|
||||
ingame_HUD_PuzzleNextPuzzle,
|
||||
ingame_HUD_PuzzleEditorReview,
|
||||
ingame_HUD_PuzzleEditorControls,
|
||||
ingame_HUD_PuzzleEditorTitle,
|
||||
@ -133,6 +136,7 @@ body.uiHidden {
|
||||
#ingame_HUD_GameMenu,
|
||||
#ingame_HUD_PinnedShapes,
|
||||
#ingame_HUD_PuzzleBackToMenu,
|
||||
#ingame_HUD_PuzzleNextPuzzle,
|
||||
#ingame_HUD_PuzzleEditorReview,
|
||||
#ingame_HUD_Notifications,
|
||||
#ingame_HUD_TutorialHints,
|
||||
|
||||
@ -550,6 +550,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
#crosspromo {
|
||||
position: absolute;
|
||||
@include S(bottom, 50px);
|
||||
@include S(right, 20px);
|
||||
@include S(width, 190px);
|
||||
@include S(height, 100px);
|
||||
pointer-events: all;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.footer {
|
||||
display: grid;
|
||||
flex-grow: 1;
|
||||
@ -561,10 +571,45 @@
|
||||
box-sizing: border-box;
|
||||
@include S(grid-gap, 4px);
|
||||
|
||||
&.china {
|
||||
&.noLinks {
|
||||
grid-template-columns: auto 1fr;
|
||||
}
|
||||
|
||||
&.wegameDisclaimer {
|
||||
@include SuperSmallText;
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
grid-template-columns: 1fr auto 1fr;
|
||||
text-align: center;
|
||||
|
||||
> .disclaimer {
|
||||
grid-column: 2 / 3;
|
||||
|
||||
@include DarkThemeOverride {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
> .rating {
|
||||
grid-column: 3 / 4;
|
||||
justify-self: end;
|
||||
align-self: end;
|
||||
|
||||
@include S(width, 32px);
|
||||
@include S(height, 40px);
|
||||
background: green;
|
||||
cursor: pointer !important;
|
||||
pointer-events: all;
|
||||
@include S(border-radius, 4px);
|
||||
overflow: hidden;
|
||||
|
||||
& {
|
||||
/* @load-async */
|
||||
background: #fff uiResource("wegame_isbn_rating.jpg") center center / contain no-repeat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.author {
|
||||
flex-grow: 1;
|
||||
text-align: right;
|
||||
|
||||
@ -15,8 +15,81 @@
|
||||
}
|
||||
|
||||
> .container {
|
||||
.searchForm {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
color: #333;
|
||||
background: $accentColorBright;
|
||||
@include S(padding, 5px);
|
||||
@include S(border-radius, $globalBorderRadius);
|
||||
flex-wrap: wrap;
|
||||
|
||||
@include DarkThemeOverride {
|
||||
background: $accentColorDark;
|
||||
}
|
||||
|
||||
input.search {
|
||||
color: #333;
|
||||
margin: 0;
|
||||
display: inline-block;
|
||||
flex-grow: 1;
|
||||
@include S(padding, 5px, 10px);
|
||||
@include S(min-width, 50px);
|
||||
|
||||
&::placeholder {
|
||||
color: #aaa;
|
||||
}
|
||||
}
|
||||
|
||||
select {
|
||||
color: #333;
|
||||
border: 0;
|
||||
@include S(padding, 5px);
|
||||
@include S(border-radius, $globalBorderRadius);
|
||||
@include S(padding, 7px, 10px);
|
||||
@include S(margin-left, 5px);
|
||||
@include PlainText;
|
||||
}
|
||||
|
||||
.filterCompleted {
|
||||
@include S(margin-left, 20px);
|
||||
pointer-events: all;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-transform: uppercase;
|
||||
@include PlainText;
|
||||
@include S(margin-right, 10px);
|
||||
|
||||
@include DarkThemeOverride {
|
||||
color: #bbbbc4;
|
||||
}
|
||||
|
||||
input {
|
||||
@include S(width, 15px);
|
||||
@include S(height, 15px);
|
||||
@include S(margin-right, 5px);
|
||||
@include S(border-radius, $globalBorderRadius);
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
button[type="submit"] {
|
||||
@include S(padding, 7px, 10px, 5px);
|
||||
@include S(margin-left, 20px);
|
||||
@include S(margin-top, 4px);
|
||||
@include S(margin-bottom, 4px);
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
> .mainContent {
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
> .categoryChooser {
|
||||
> .categories {
|
||||
@ -79,8 +152,8 @@
|
||||
@include S(grid-gap, 7px);
|
||||
@include S(margin-top, 10px);
|
||||
@include S(padding-right, 4px);
|
||||
@include S(height, 320px);
|
||||
overflow-y: scroll;
|
||||
flex-grow: 1;
|
||||
pointer-events: all;
|
||||
position: relative;
|
||||
|
||||
@ -246,6 +319,9 @@
|
||||
&.stage--hard {
|
||||
color: $colorRedBright;
|
||||
}
|
||||
&.stage--unknown {
|
||||
color: #888;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -50,7 +50,8 @@
|
||||
}
|
||||
|
||||
button.categoryButton,
|
||||
button.about {
|
||||
button.about,
|
||||
button.privacy {
|
||||
background-color: $colorCategoryButton;
|
||||
color: #777a7f;
|
||||
|
||||
@ -68,6 +69,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
button.privacy {
|
||||
@include S(margin-top, 4px);
|
||||
}
|
||||
|
||||
.versionbar {
|
||||
@include S(margin-top, 10px);
|
||||
|
||||
@ -180,7 +185,8 @@
|
||||
.container .content {
|
||||
.sidebar {
|
||||
button.categoryButton,
|
||||
button.about {
|
||||
button.about,
|
||||
button.privacy {
|
||||
color: #ccc;
|
||||
background-color: darken($darkModeControlsBackground, 5);
|
||||
|
||||
|
||||
38
src/css/states/wegame_splash.scss
Normal file
@ -0,0 +1,38 @@
|
||||
#state_WegameSplashState {
|
||||
background: #000 !important;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.wrapper {
|
||||
opacity: 0;
|
||||
@include InlineAnimation(5.9s ease-in-out) {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
opacity: 1;
|
||||
}
|
||||
90% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
@include Heading;
|
||||
|
||||
strong {
|
||||
display: block;
|
||||
@include SuperHeading;
|
||||
@include S(margin-bottom, 20px);
|
||||
}
|
||||
|
||||
div {
|
||||
@include S(margin-bottom, 10px);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -34,6 +34,7 @@ import { RestrictionManager } from "./core/restriction_manager";
|
||||
import { PuzzleMenuState } from "./states/puzzle_menu";
|
||||
import { ClientAPI } from "./platform/api";
|
||||
import { LoginState } from "./states/login";
|
||||
import { WegameSplashState } from "./states/wegame_splash";
|
||||
|
||||
/**
|
||||
* @typedef {import("./platform/achievement_provider").AchievementProviderInterface} AchievementProviderInterface
|
||||
@ -155,6 +156,7 @@ export class Application {
|
||||
registerStates() {
|
||||
/** @type {Array<typeof GameState>} */
|
||||
const states = [
|
||||
WegameSplashState,
|
||||
PreloadState,
|
||||
MobileWarningState,
|
||||
MainMenuState,
|
||||
@ -330,8 +332,12 @@ export class Application {
|
||||
|
||||
Loader.linkAppAfterBoot(this);
|
||||
|
||||
if (G_WEGAME_VERSION) {
|
||||
this.stateMgr.moveToState("WegameSplashState");
|
||||
}
|
||||
|
||||
// Check for mobile
|
||||
if (IS_MOBILE) {
|
||||
else if (IS_MOBILE) {
|
||||
this.stateMgr.moveToState("MobileWarningState");
|
||||
} else {
|
||||
this.stateMgr.moveToState("PreloadState");
|
||||
|
||||
@ -1,4 +1,27 @@
|
||||
export const CHANGELOG = [
|
||||
{
|
||||
version: "1.4.4",
|
||||
date: "29.08.2021",
|
||||
entries: [
|
||||
"Hotfix: Fixed the balancer not distributing items evenly, caused by the 1.4.3 update. Sorry for any inconveniences!",
|
||||
],
|
||||
},
|
||||
{
|
||||
version: "1.4.3",
|
||||
date: "28.08.2021",
|
||||
entries: [
|
||||
"You can now hold 'ALT' while hovering a building to see its output! (Thanks to Sense101) (PS: There is now a setting to have it always on!)",
|
||||
"The map overview should now be much more performant! As a consequence, you can now zoom out farther! (Thanks to PFedak)",
|
||||
"Puzzle DLC: There is now a 'next puzzle' button!",
|
||||
"Puzzle DLC: There is now a search function!",
|
||||
"Edit signal dialog now has the previous signal filled (Thanks to EmeraldBlock)",
|
||||
"Further performance improvements (Thanks to PFedak)",
|
||||
"Improved puzzle validation (Thanks to Sense101)",
|
||||
"Input fields in dialogs should now automatically focus",
|
||||
"Fix selected building being deselected at level up (Thanks to EmeraldBlock)",
|
||||
"Updated translations",
|
||||
],
|
||||
},
|
||||
{
|
||||
version: "1.4.2",
|
||||
date: "24.06.2021",
|
||||
|
||||
@ -167,4 +167,25 @@ export class BufferMaintainer {
|
||||
});
|
||||
return canvas;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object} param0
|
||||
* @param {string} param0.key
|
||||
* @param {string} param0.subKey
|
||||
* @returns {HTMLCanvasElement?}
|
||||
*
|
||||
*/
|
||||
getForKeyOrNullNoUpdate({ key, subKey }) {
|
||||
let parent = this.cache.get(key);
|
||||
if (!parent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Now search for sub key
|
||||
const cacheHit = parent.get(subKey);
|
||||
if (cacheHit) {
|
||||
return cacheHit.canvas;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ export const IS_DEBUG =
|
||||
|
||||
export const SUPPORT_TOUCH = false;
|
||||
|
||||
export const IS_MAC = navigator.platform.toLowerCase().indexOf("mac") >= 0;
|
||||
export const IS_MAC = navigator.platform.toLowerCase().indexOf("mac") >= 0 && !G_IS_DEV;
|
||||
|
||||
const smoothCanvas = true;
|
||||
|
||||
@ -17,6 +17,8 @@ export const THIRDPARTY_URLS = {
|
||||
reddit: "https://www.reddit.com/r/shapezio",
|
||||
shapeViewer: "https://viewer.shapez.io",
|
||||
|
||||
privacyPolicy: "https://tobspr.io/privacy.html",
|
||||
|
||||
standaloneStorePage: "https://store.steampowered.com/app/1318690/shapezio/",
|
||||
stanaloneCampaignLink: "https://get.shapez.io",
|
||||
puzzleDlcStorePage: "https://store.steampowered.com/app/1625400/shapezio__Puzzle_DLC",
|
||||
@ -55,6 +57,7 @@ export const globalConfig = {
|
||||
|
||||
// Map
|
||||
mapChunkSize: 16,
|
||||
chunkAggregateSize: 4,
|
||||
mapChunkOverviewMinZoom: 0.9,
|
||||
mapChunkWorldSize: null, // COMPUTED
|
||||
|
||||
|
||||
@ -53,7 +53,7 @@ export default {
|
||||
// Replace all translations with emojis to see which texts are translateable
|
||||
// testTranslations: true,
|
||||
// -----------------------------------------------------------------------------------
|
||||
// Enables an inspector which shows information about the entity below the curosr
|
||||
// Enables an inspector which shows information about the entity below the cursor
|
||||
// enableEntityInspector: true,
|
||||
// -----------------------------------------------------------------------------------
|
||||
// Enables ads in the local build (normally they are deactivated there)
|
||||
|
||||
@ -123,6 +123,4 @@ function catchErrors(message, source, lineno, colno, error) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!G_IS_DEV) {
|
||||
window.onerror = catchErrors;
|
||||
}
|
||||
window.onerror = catchErrors;
|
||||
|
||||
@ -91,26 +91,6 @@ export class GameState {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} nextStateId
|
||||
* @param {object=} nextStatePayload
|
||||
*/
|
||||
watchAdAndMoveToState(nextStateId, nextStatePayload = {}) {
|
||||
if (this.app.adProvider.getCanShowVideoAd() && this.app.isRenderable()) {
|
||||
this.moveToState(
|
||||
"WatchAdState",
|
||||
{
|
||||
nextStateId,
|
||||
nextStatePayload,
|
||||
},
|
||||
true
|
||||
);
|
||||
} else {
|
||||
this.moveToState(nextStateId, nextStatePayload);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks clicks on a given element and calls the given callback *on this state*.
|
||||
* If you want to call another function wrap it inside a lambda.
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { BaseItem } from "../game/base_item";
|
||||
import { ClickDetector } from "./click_detector";
|
||||
import { Signal } from "./signal";
|
||||
import { getIPCRenderer } from "./utils";
|
||||
|
||||
/*
|
||||
* ***************************************************
|
||||
@ -107,6 +108,19 @@ export class FormElementInput extends FormElement {
|
||||
|
||||
updateErrorState() {
|
||||
this.element.classList.toggle("errored", !this.isValid());
|
||||
|
||||
// profanity filter
|
||||
if (G_WEGAME_VERSION) {
|
||||
const value = String(this.element.value);
|
||||
|
||||
getIPCRenderer()
|
||||
.invoke("profanity-check", value)
|
||||
.then(newValue => {
|
||||
if (value !== newValue && this.element) {
|
||||
this.element.value = newValue;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
isValid() {
|
||||
@ -124,6 +138,7 @@ export class FormElementInput extends FormElement {
|
||||
|
||||
focus() {
|
||||
this.element.focus();
|
||||
this.element.select();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -89,6 +89,11 @@ export class RestrictionManager extends ReadWriteProxy {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (queryParamOptions.embedProvider === "gamedistribution") {
|
||||
// also full version on gamedistribution
|
||||
return false;
|
||||
}
|
||||
|
||||
if (G_IS_DEV) {
|
||||
return typeof window !== "undefined" && window.location.search.indexOf("demo") >= 0;
|
||||
}
|
||||
|
||||
@ -734,6 +734,10 @@ const romanLiteralsCache = ["0"];
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getRomanNumber(number) {
|
||||
if (G_WEGAME_VERSION) {
|
||||
return String(number);
|
||||
}
|
||||
|
||||
number = Math.max(0, Math.round(number));
|
||||
if (romanLiteralsCache[number]) {
|
||||
return romanLiteralsCache[number];
|
||||
|
||||
@ -11,6 +11,7 @@ import { typeItemSingleton } from "../item_resolver";
|
||||
* pos: Vector,
|
||||
* direction: enumDirection,
|
||||
* item: BaseItem,
|
||||
* lastItem: BaseItem,
|
||||
* progress: number?,
|
||||
* cachedDestSlot?: import("./item_acceptor").ItemAcceptorLocatedSlot,
|
||||
* cachedBeltPath?: BeltPath,
|
||||
@ -51,6 +52,7 @@ export class ItemEjectorComponent extends Component {
|
||||
clear() {
|
||||
for (const slot of this.slots) {
|
||||
slot.item = null;
|
||||
slot.lastItem = null;
|
||||
slot.progress = 0;
|
||||
}
|
||||
}
|
||||
@ -67,6 +69,7 @@ export class ItemEjectorComponent extends Component {
|
||||
pos: slot.pos,
|
||||
direction: slot.direction,
|
||||
item: null,
|
||||
lastItem: null,
|
||||
progress: 0,
|
||||
cachedDestSlot: null,
|
||||
cachedTargetEntity: null,
|
||||
@ -131,6 +134,7 @@ export class ItemEjectorComponent extends Component {
|
||||
return false;
|
||||
}
|
||||
this.slots[slotIndex].item = item;
|
||||
this.slots[slotIndex].lastItem = item;
|
||||
this.slots[slotIndex].progress = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -73,6 +73,12 @@ export class ItemProcessorComponent extends Component {
|
||||
// Type of processing requirement
|
||||
this.processingRequirement = processingRequirement;
|
||||
|
||||
/**
|
||||
* Our current inputs
|
||||
* @type {Map<number, BaseItem>}
|
||||
*/
|
||||
this.inputSlots = new Map();
|
||||
|
||||
this.clear();
|
||||
}
|
||||
|
||||
@ -82,11 +88,13 @@ export class ItemProcessorComponent extends Component {
|
||||
// sure the outputs always match
|
||||
this.nextOutputSlot = 0;
|
||||
|
||||
this.inputSlots.clear();
|
||||
|
||||
/**
|
||||
* Our current inputs
|
||||
* @type {Array<{ item: BaseItem, sourceSlot: number }>}
|
||||
* Current input count
|
||||
* @type {number}
|
||||
*/
|
||||
this.inputSlots = [];
|
||||
this.inputCount = 0;
|
||||
|
||||
/**
|
||||
* What we are currently processing, empty if we don't produce anything rn
|
||||
@ -115,19 +123,17 @@ export class ItemProcessorComponent extends Component {
|
||||
this.type === enumItemProcessorTypes.goal
|
||||
) {
|
||||
// Hub has special logic .. not really nice but efficient.
|
||||
this.inputSlots.push({ item, sourceSlot });
|
||||
this.inputSlots.set(this.inputCount, item);
|
||||
this.inputCount++;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check that we only take one item per slot
|
||||
for (let i = 0; i < this.inputSlots.length; ++i) {
|
||||
const slot = this.inputSlots[i];
|
||||
if (slot.sourceSlot === sourceSlot) {
|
||||
return false;
|
||||
}
|
||||
if (this.inputSlots.has(sourceSlot)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.inputSlots.push({ item, sourceSlot });
|
||||
this.inputSlots.set(sourceSlot, item);
|
||||
this.inputCount++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,7 +119,7 @@ export class GameMode extends BasicSerializableObject {
|
||||
|
||||
/** @returns {number} */
|
||||
getMinimumZoom() {
|
||||
return 0.1;
|
||||
return 0.06;
|
||||
}
|
||||
|
||||
/** @returns {number} */
|
||||
|
||||
@ -16,6 +16,7 @@ import { HUDEntityDebugger } from "./parts/entity_debugger";
|
||||
import { HUDModalDialogs } from "./parts/modal_dialogs";
|
||||
import { enumNotificationType } from "./parts/notifications";
|
||||
import { HUDSettingsMenu } from "./parts/settings_menu";
|
||||
import { HUDShapeTooltip } from "./parts/shape_tooltip";
|
||||
import { HUDVignetteOverlay } from "./parts/vignette_overlay";
|
||||
import { TrailerMaker } from "./trailer_maker";
|
||||
|
||||
@ -49,6 +50,8 @@ export class GameHUD {
|
||||
blueprintPlacer: new HUDBlueprintPlacer(this.root),
|
||||
buildingPlacer: new HUDBuildingPlacer(this.root),
|
||||
|
||||
shapeTooltip: new HUDShapeTooltip(this.root),
|
||||
|
||||
// Must always exist
|
||||
settingsMenu: new HUDSettingsMenu(this.root),
|
||||
debugInfo: new HUDDebugInfo(this.root),
|
||||
@ -189,6 +192,7 @@ export class GameHUD {
|
||||
"colorBlindHelper",
|
||||
"changesDebugger",
|
||||
"minerHighlight",
|
||||
"shapeTooltip",
|
||||
];
|
||||
|
||||
for (let i = 0; i < partsOrder.length; ++i) {
|
||||
|
||||
25
src/js/game/hud/parts/HUDPuzzleNextPuzzle.js
Normal file
@ -0,0 +1,25 @@
|
||||
import { makeDiv } from "../../../core/utils";
|
||||
import { T } from "../../../translations";
|
||||
import { PuzzlePlayGameMode } from "../../modes/puzzle_play";
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
|
||||
export class HUDPuzzleNextPuzzle extends BaseHUDPart {
|
||||
createElements(parent) {
|
||||
this.element = makeDiv(parent, "ingame_HUD_PuzzleNextPuzzle");
|
||||
this.button = document.createElement("button");
|
||||
this.button.classList.add("button");
|
||||
this.button.innerText = T.ingame.puzzleCompletion.nextPuzzle;
|
||||
this.element.appendChild(this.button);
|
||||
|
||||
this.trackClicks(this.button, this.nextPuzzle);
|
||||
}
|
||||
|
||||
initialize() {}
|
||||
|
||||
nextPuzzle() {
|
||||
const gameMode = /** @type {PuzzlePlayGameMode} */ (this.root.gameMode);
|
||||
this.root.gameState.moveToState("PuzzleMenuState", {
|
||||
continueQueue: gameMode.nextPuzzles,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -128,7 +128,6 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart {
|
||||
this.root.hud.signals.buildingsSelectedForCopy.add(this.abortPlacement, this);
|
||||
this.root.hud.signals.pasteBlueprintRequested.add(this.abortPlacement, this);
|
||||
this.root.signals.storyGoalCompleted.add(() => this.signals.variantChanged.dispatch());
|
||||
this.root.signals.storyGoalCompleted.add(() => this.currentMetaBuilding.set(null));
|
||||
this.root.signals.upgradePurchased.add(() => this.signals.variantChanged.dispatch());
|
||||
this.root.signals.editModeChanged.add(this.onEditModeChanged, this);
|
||||
|
||||
|
||||
@ -158,8 +158,13 @@ export class HUDInteractiveTutorial extends BaseHUDPart {
|
||||
|
||||
onHintChanged(hintId) {
|
||||
this.elementDescription.innerHTML = T.ingame.interactiveTutorial.hints[hintId];
|
||||
|
||||
const folder = G_WEGAME_VERSION
|
||||
? "interactive_tutorial.cn.noinline"
|
||||
: "interactive_tutorial.noinline";
|
||||
|
||||
this.elementGif.style.backgroundImage =
|
||||
"url('" + cachebust("res/ui/interactive_tutorial.noinline/" + hintId + ".gif") + "')";
|
||||
"url('" + cachebust("res/ui/" + folder + "/" + hintId + ".gif") + "')";
|
||||
this.element.classList.toggle("animEven");
|
||||
this.element.classList.toggle("animOdd");
|
||||
}
|
||||
|
||||
@ -6,13 +6,8 @@ import { InputReceiver } from "../../../core/input_receiver";
|
||||
import { makeDiv } from "../../../core/utils";
|
||||
import { SOUNDS } from "../../../platform/sound";
|
||||
import { T } from "../../../translations";
|
||||
import { enumColors } from "../../colors";
|
||||
import { ColorItem } from "../../items/color_item";
|
||||
import { finalGameShape, rocketShape } from "../../modes/regular";
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||
import { ShapeItem } from "../../items/shape_item";
|
||||
import { ShapeDefinition } from "../../shape_definition";
|
||||
|
||||
export class HUDPuzzleCompleteNotification extends BaseHUDPart {
|
||||
initialize() {
|
||||
@ -68,10 +63,21 @@ export class HUDPuzzleCompleteNotification extends BaseHUDPart {
|
||||
this.menuBtn.classList.add("menu", "styledButton");
|
||||
this.menuBtn.innerText = T.ingame.puzzleCompletion.menuBtn;
|
||||
buttonBar.appendChild(this.menuBtn);
|
||||
|
||||
this.trackClicks(this.menuBtn, () => {
|
||||
this.close(true);
|
||||
});
|
||||
|
||||
const gameMode = /** @type {PuzzlePlayGameMode} */ (this.root.gameMode);
|
||||
if (gameMode.nextPuzzles.length > 0) {
|
||||
this.nextPuzzleBtn = document.createElement("button");
|
||||
this.nextPuzzleBtn.classList.add("nextPuzzle", "styledButton");
|
||||
this.nextPuzzleBtn.innerText = T.ingame.puzzleCompletion.nextPuzzle;
|
||||
buttonBar.appendChild(this.nextPuzzleBtn);
|
||||
|
||||
this.trackClicks(this.nextPuzzleBtn, () => {
|
||||
this.nextPuzzle();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
updateState() {
|
||||
@ -93,6 +99,15 @@ export class HUDPuzzleCompleteNotification extends BaseHUDPart {
|
||||
return this.visible;
|
||||
}
|
||||
|
||||
nextPuzzle() {
|
||||
const gameMode = /** @type {PuzzlePlayGameMode} */ (this.root.gameMode);
|
||||
gameMode.trackCompleted(this.userDidLikePuzzle, Math.round(this.timeOfCompletion)).then(() => {
|
||||
this.root.gameState.moveToState("PuzzleMenuState", {
|
||||
continueQueue: gameMode.nextPuzzles,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
close(toMenu) {
|
||||
/** @type {PuzzlePlayGameMode} */ (this.root.gameMode)
|
||||
.trackCompleted(this.userDidLikePuzzle, Math.round(this.timeOfCompletion))
|
||||
|
||||
@ -81,7 +81,7 @@ export class HUDPuzzleEditorReview extends BaseHUDPart {
|
||||
closeLoading();
|
||||
|
||||
//if it took so little ticks that it must have autocompeted
|
||||
if (simulatedTicks <= 300) {
|
||||
if (simulatedTicks <= 500) {
|
||||
this.root.hud.parts.dialogs.showWarning(
|
||||
T.puzzleMenu.validation.title,
|
||||
T.puzzleMenu.validation.autoComplete
|
||||
|
||||
@ -149,8 +149,9 @@ export class HUDPuzzleEditorSettings extends BaseHUDPart {
|
||||
assertAlways(false, "Failed to re-place building in trim");
|
||||
}
|
||||
|
||||
if (building.components.ConstantSignal) {
|
||||
result.components.ConstantSignal.signal = building.components.ConstantSignal.signal;
|
||||
for (const key in building.components) {
|
||||
/** @type {import("../../../core/global_registries").Component} */ (building
|
||||
.components[key]).copyAdditionalStateTo(result.components[key]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
100
src/js/game/hud/parts/shape_tooltip.js
Normal file
@ -0,0 +1,100 @@
|
||||
import { DrawParameters } from "../../../core/draw_parameters";
|
||||
import { enumDirectionToVector, Vector } from "../../../core/vector";
|
||||
import { Entity } from "../../entity";
|
||||
import { KEYMAPPINGS } from "../../key_action_mapper";
|
||||
import { THEME } from "../../theme";
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
|
||||
export class HUDShapeTooltip extends BaseHUDPart {
|
||||
createElements(parent) {}
|
||||
|
||||
initialize() {
|
||||
/** @type {Vector} */
|
||||
this.currentTile = new Vector(0, 0);
|
||||
|
||||
/** @type {Entity} */
|
||||
this.currentEntity = null;
|
||||
|
||||
this.isPlacingBuilding = false;
|
||||
|
||||
this.root.signals.entityQueuedForDestroy.add(() => {
|
||||
this.currentEntity = null;
|
||||
}, this);
|
||||
|
||||
this.root.hud.signals.selectedPlacementBuildingChanged.add(metaBuilding => {
|
||||
this.isPlacingBuilding = metaBuilding;
|
||||
}, this);
|
||||
}
|
||||
|
||||
isActive() {
|
||||
const hudParts = this.root.hud.parts;
|
||||
|
||||
const active =
|
||||
this.root.app.settings.getSetting("shapeTooltipAlwaysOn") ||
|
||||
this.root.keyMapper.getBinding(KEYMAPPINGS.ingame.showShapeTooltip).pressed;
|
||||
|
||||
// return false if any other placer is active
|
||||
return (
|
||||
active &&
|
||||
!this.isPlacingBuilding &&
|
||||
!hudParts.massSelector.currentSelectionStartWorld &&
|
||||
hudParts.massSelector.selectedUids.size < 1 &&
|
||||
!hudParts.blueprintPlacer.currentBlueprint.get()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {DrawParameters} parameters
|
||||
*/
|
||||
draw(parameters) {
|
||||
if (this.isActive()) {
|
||||
const mousePos = this.root.app.mousePosition;
|
||||
|
||||
if (mousePos) {
|
||||
const tile = this.root.camera.screenToWorld(mousePos.copy()).toTileSpace();
|
||||
if (!tile.equals(this.currentTile)) {
|
||||
this.currentTile = tile;
|
||||
|
||||
const entity = this.root.map.getLayerContentXY(tile.x, tile.y, this.root.currentLayer);
|
||||
|
||||
if (entity && entity.components.ItemProcessor && entity.components.ItemEjector) {
|
||||
this.currentEntity = entity;
|
||||
} else {
|
||||
this.currentEntity = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.currentEntity) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ejectorComp = this.currentEntity.components.ItemEjector;
|
||||
const staticComp = this.currentEntity.components.StaticMapEntity;
|
||||
|
||||
const bounds = staticComp.getTileSize();
|
||||
const totalArea = bounds.x * bounds.y;
|
||||
const maxSlots = totalArea < 2 ? 1 : 1e10;
|
||||
|
||||
let slotsDrawn = 0;
|
||||
|
||||
for (let i = 0; i < ejectorComp.slots.length; ++i) {
|
||||
const slot = ejectorComp.slots[i];
|
||||
|
||||
if (!slot.lastItem) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (++slotsDrawn > maxSlots) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @type {Vector} */
|
||||
const drawPos = staticComp.localTileToWorld(slot.pos).toWorldSpaceCenterOfTile();
|
||||
|
||||
slot.lastItem.drawItemCenteredClipped(drawPos.x, drawPos.y, parameters, 25);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -45,7 +45,7 @@ export class HUDWaypoints extends BaseHUDPart {
|
||||
*/
|
||||
createElements(parent) {
|
||||
// Create the helper box on the lower right when zooming out
|
||||
if (this.root.app.settings.getAllSettings().offerHints) {
|
||||
if (this.root.app.settings.getAllSettings().offerHints && !G_WEGAME_VERSION) {
|
||||
this.hintElement = makeDiv(
|
||||
parent,
|
||||
"ingame_HUD_Waypoints_Hint",
|
||||
@ -121,10 +121,12 @@ export class HUDWaypoints extends BaseHUDPart {
|
||||
}
|
||||
|
||||
// Catch mouse and key events
|
||||
this.root.camera.downPreHandler.add(this.onMouseDown, this);
|
||||
this.root.keyMapper
|
||||
.getBinding(KEYMAPPINGS.navigation.createMarker)
|
||||
.add(() => this.requestSaveMarker({}));
|
||||
if (!G_WEGAME_VERSION) {
|
||||
this.root.camera.downPreHandler.add(this.onMouseDown, this);
|
||||
this.root.keyMapper
|
||||
.getBinding(KEYMAPPINGS.navigation.createMarker)
|
||||
.add(() => this.requestSaveMarker({}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores at how much opacity the markers should be rendered on the map.
|
||||
|
||||
@ -32,6 +32,8 @@ export const KEYMAPPINGS = {
|
||||
toggleFPSInfo: { keyCode: 115 }, // F4
|
||||
|
||||
switchLayers: { keyCode: key("E") },
|
||||
|
||||
showShapeTooltip: { keyCode: 18 }, // ALT
|
||||
},
|
||||
|
||||
navigation: {
|
||||
|
||||
@ -80,6 +80,15 @@ export class GameLogic {
|
||||
}
|
||||
|
||||
// Perform additional placement checks
|
||||
if (this.root.gameMode.getIsEditor()) {
|
||||
const toolbar = this.root.hud.parts.buildingsToolbar;
|
||||
const id = entity.components.StaticMapEntity.getMetaBuilding().getId();
|
||||
|
||||
if (toolbar.buildingHandles[id].puzzleLocked) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.root.signals.prePlacementCheck.dispatch(entity, offset) === STOP_PROPAGATION) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ import { Vector } from "../core/vector";
|
||||
import { BasicSerializableObject, types } from "../savegame/serialization";
|
||||
import { BaseItem } from "./base_item";
|
||||
import { Entity } from "./entity";
|
||||
import { MapChunkAggregate } from "./map_chunk_aggregate";
|
||||
import { MapChunkView } from "./map_chunk_view";
|
||||
import { GameRoot } from "./root";
|
||||
|
||||
@ -31,6 +32,11 @@ export class BaseMap extends BasicSerializableObject {
|
||||
* Mapping of 'X|Y' to chunk
|
||||
* @type {Map<string, MapChunkView>} */
|
||||
this.chunksById = new Map();
|
||||
|
||||
/**
|
||||
* Mapping of 'X|Y' to chunk aggregate
|
||||
* @type {Map<string, MapChunkAggregate>} */
|
||||
this.aggregatesById = new Map();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -55,6 +61,39 @@ export class BaseMap extends BasicSerializableObject {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the chunk aggregate containing a given chunk
|
||||
* @param {number} chunkX
|
||||
* @param {number} chunkY
|
||||
*/
|
||||
getAggregateForChunk(chunkX, chunkY, createIfNotExistent = false) {
|
||||
const aggX = Math.floor(chunkX / globalConfig.chunkAggregateSize);
|
||||
const aggY = Math.floor(chunkY / globalConfig.chunkAggregateSize);
|
||||
return this.getAggregate(aggX, aggY, createIfNotExistent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the given chunk aggregate by index
|
||||
* @param {number} aggX
|
||||
* @param {number} aggY
|
||||
*/
|
||||
getAggregate(aggX, aggY, createIfNotExistent = false) {
|
||||
const aggIdentifier = aggX + "|" + aggY;
|
||||
let storedAggregate;
|
||||
|
||||
if ((storedAggregate = this.aggregatesById.get(aggIdentifier))) {
|
||||
return storedAggregate;
|
||||
}
|
||||
|
||||
if (createIfNotExistent) {
|
||||
const instance = new MapChunkAggregate(this.root, aggX, aggY);
|
||||
this.aggregatesById.set(aggIdentifier, instance);
|
||||
return instance;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets or creates a new chunk if not existent for the given tile
|
||||
* @param {number} tileX
|
||||
|
||||
154
src/js/game/map_chunk_aggregate.js
Normal file
@ -0,0 +1,154 @@
|
||||
import { globalConfig } from "../core/config";
|
||||
import { DrawParameters } from "../core/draw_parameters";
|
||||
import { drawSpriteClipped } from "../core/draw_utils";
|
||||
import { safeModulo } from "../core/utils";
|
||||
import { GameRoot } from "./root";
|
||||
|
||||
export const CHUNK_OVERLAY_RES = 3;
|
||||
|
||||
export class MapChunkAggregate {
|
||||
/**
|
||||
*
|
||||
* @param {GameRoot} root
|
||||
* @param {number} x
|
||||
* @param {number} y
|
||||
*/
|
||||
constructor(root, x, y) {
|
||||
this.root = root;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
||||
/**
|
||||
* Whenever something changes, we increase this number - so we know we need to redraw
|
||||
*/
|
||||
this.renderIteration = 0;
|
||||
this.dirty = false;
|
||||
/** @type {Array<boolean>} */
|
||||
this.dirtyList = new Array(globalConfig.chunkAggregateSize ** 2).fill(true);
|
||||
this.markDirty(0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks this chunk as dirty, rerendering all caches
|
||||
* @param {number} chunkX
|
||||
* @param {number} chunkY
|
||||
*/
|
||||
markDirty(chunkX, chunkY) {
|
||||
const relX = safeModulo(chunkX, globalConfig.chunkAggregateSize);
|
||||
const relY = safeModulo(chunkY, globalConfig.chunkAggregateSize);
|
||||
this.dirtyList[relY * globalConfig.chunkAggregateSize + relX] = true;
|
||||
if (this.dirty) {
|
||||
return;
|
||||
}
|
||||
this.dirty = true;
|
||||
++this.renderIteration;
|
||||
this.renderKey = this.x + "/" + this.y + "@" + this.renderIteration;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {HTMLCanvasElement} canvas
|
||||
* @param {CanvasRenderingContext2D} context
|
||||
* @param {number} w
|
||||
* @param {number} h
|
||||
* @param {number} dpi
|
||||
*/
|
||||
generateOverlayBuffer(canvas, context, w, h, dpi) {
|
||||
const prevKey = this.x + "/" + this.y + "@" + (this.renderIteration - 1);
|
||||
const prevBuffer = this.root.buffers.getForKeyOrNullNoUpdate({
|
||||
key: "agg@" + this.root.currentLayer,
|
||||
subKey: prevKey,
|
||||
});
|
||||
|
||||
const overlaySize = globalConfig.mapChunkSize * CHUNK_OVERLAY_RES;
|
||||
let onlyDirty = false;
|
||||
if (prevBuffer) {
|
||||
context.drawImage(prevBuffer, 0, 0);
|
||||
onlyDirty = true;
|
||||
}
|
||||
|
||||
for (let x = 0; x < globalConfig.chunkAggregateSize; x++) {
|
||||
for (let y = 0; y < globalConfig.chunkAggregateSize; y++) {
|
||||
if (onlyDirty && !this.dirtyList[globalConfig.chunkAggregateSize * y + x]) continue;
|
||||
this.root.map
|
||||
.getChunk(
|
||||
this.x * globalConfig.chunkAggregateSize + x,
|
||||
this.y * globalConfig.chunkAggregateSize + y,
|
||||
true
|
||||
)
|
||||
.generateOverlayBuffer(
|
||||
context,
|
||||
overlaySize,
|
||||
overlaySize,
|
||||
x * overlaySize,
|
||||
y * overlaySize
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
this.dirty = false;
|
||||
this.dirtyList.fill(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overlay
|
||||
* @param {DrawParameters} parameters
|
||||
*/
|
||||
drawOverlay(parameters) {
|
||||
const aggregateOverlaySize =
|
||||
globalConfig.mapChunkSize * globalConfig.chunkAggregateSize * CHUNK_OVERLAY_RES;
|
||||
const sprite = this.root.buffers.getForKey({
|
||||
key: "agg@" + this.root.currentLayer,
|
||||
subKey: this.renderKey,
|
||||
w: aggregateOverlaySize,
|
||||
h: aggregateOverlaySize,
|
||||
dpi: 1,
|
||||
redrawMethod: this.generateOverlayBuffer.bind(this),
|
||||
});
|
||||
|
||||
const dims = globalConfig.mapChunkWorldSize * globalConfig.chunkAggregateSize;
|
||||
const extrude = 0.05;
|
||||
|
||||
// Draw chunk "pixel" art
|
||||
parameters.context.imageSmoothingEnabled = false;
|
||||
drawSpriteClipped({
|
||||
parameters,
|
||||
sprite,
|
||||
x: this.x * dims - extrude,
|
||||
y: this.y * dims - extrude,
|
||||
w: dims + 2 * extrude,
|
||||
h: dims + 2 * extrude,
|
||||
originalW: aggregateOverlaySize,
|
||||
originalH: aggregateOverlaySize,
|
||||
});
|
||||
|
||||
parameters.context.imageSmoothingEnabled = true;
|
||||
const resourcesScale = this.root.app.settings.getAllSettings().mapResourcesScale;
|
||||
|
||||
// Draw patch items
|
||||
if (
|
||||
this.root.currentLayer === "regular" &&
|
||||
resourcesScale > 0.05 &&
|
||||
this.root.camera.zoomLevel > 0.1
|
||||
) {
|
||||
const diameter = (70 / Math.pow(parameters.zoomLevel, 0.35)) * (0.2 + 2 * resourcesScale);
|
||||
|
||||
for (let x = 0; x < globalConfig.chunkAggregateSize; x++) {
|
||||
for (let y = 0; y < globalConfig.chunkAggregateSize; y++) {
|
||||
this.root.map
|
||||
.getChunk(
|
||||
this.x * globalConfig.chunkAggregateSize + x,
|
||||
this.y * globalConfig.chunkAggregateSize + y,
|
||||
true
|
||||
)
|
||||
.drawOverlayPatches(
|
||||
parameters,
|
||||
this.x * dims + x * globalConfig.mapChunkWorldSize,
|
||||
this.y * dims + y * globalConfig.mapChunkWorldSize,
|
||||
diameter
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -33,6 +33,7 @@ export class MapChunkView extends MapChunk {
|
||||
markDirty() {
|
||||
++this.renderIteration;
|
||||
this.renderKey = this.x + "/" + this.y + "@" + this.renderIteration;
|
||||
this.root.map.getAggregateForChunk(this.x, this.y, true).markDirty(this.x, this.y);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -82,73 +83,41 @@ export class MapChunkView extends MapChunk {
|
||||
}
|
||||
|
||||
/**
|
||||
* Overlay
|
||||
* @param {DrawParameters} parameters
|
||||
* @param {number} xoffs
|
||||
* @param {number} yoffs
|
||||
* @param {number} diameter
|
||||
*/
|
||||
drawOverlay(parameters) {
|
||||
const overlaySize = globalConfig.mapChunkSize * CHUNK_OVERLAY_RES;
|
||||
const sprite = this.root.buffers.getForKey({
|
||||
key: "chunk@" + this.root.currentLayer,
|
||||
subKey: this.renderKey,
|
||||
w: overlaySize,
|
||||
h: overlaySize,
|
||||
dpi: 1,
|
||||
redrawMethod: this.generateOverlayBuffer.bind(this),
|
||||
});
|
||||
|
||||
const dims = globalConfig.mapChunkWorldSize;
|
||||
const extrude = 0.05;
|
||||
|
||||
// Draw chunk "pixel" art
|
||||
parameters.context.imageSmoothingEnabled = false;
|
||||
drawSpriteClipped({
|
||||
parameters,
|
||||
sprite,
|
||||
x: this.x * dims - extrude,
|
||||
y: this.y * dims - extrude,
|
||||
w: dims + 2 * extrude,
|
||||
h: dims + 2 * extrude,
|
||||
originalW: overlaySize,
|
||||
originalH: overlaySize,
|
||||
});
|
||||
|
||||
parameters.context.imageSmoothingEnabled = true;
|
||||
const resourcesScale = this.root.app.settings.getAllSettings().mapResourcesScale;
|
||||
|
||||
// Draw patch items
|
||||
if (this.root.currentLayer === "regular" && resourcesScale > 0.05) {
|
||||
const diameter = (70 / Math.pow(parameters.zoomLevel, 0.35)) * (0.2 + 2 * resourcesScale);
|
||||
|
||||
for (let i = 0; i < this.patches.length; ++i) {
|
||||
const patch = this.patches[i];
|
||||
if (patch.item.getItemType() === "shape") {
|
||||
const destX = this.x * dims + patch.pos.x * globalConfig.tileSize;
|
||||
const destY = this.y * dims + patch.pos.y * globalConfig.tileSize;
|
||||
patch.item.drawItemCenteredClipped(destX, destY, parameters, diameter);
|
||||
}
|
||||
drawOverlayPatches(parameters, xoffs, yoffs, diameter) {
|
||||
for (let i = 0; i < this.patches.length; ++i) {
|
||||
const patch = this.patches[i];
|
||||
if (patch.item.getItemType() === "shape") {
|
||||
const destX = xoffs + patch.pos.x * globalConfig.tileSize;
|
||||
const destY = yoffs + patch.pos.y * globalConfig.tileSize;
|
||||
patch.item.drawItemCenteredClipped(destX, destY, parameters, diameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {HTMLCanvasElement} canvas
|
||||
* @param {CanvasRenderingContext2D} context
|
||||
* @param {number} w
|
||||
* @param {number} h
|
||||
* @param {number} dpi
|
||||
* @param {number=} xoffs
|
||||
* @param {number=} yoffs
|
||||
*/
|
||||
generateOverlayBuffer(canvas, context, w, h, dpi) {
|
||||
generateOverlayBuffer(context, w, h, xoffs, yoffs) {
|
||||
context.fillStyle =
|
||||
this.containedEntities.length > 0
|
||||
? THEME.map.chunkOverview.filled
|
||||
: THEME.map.chunkOverview.empty;
|
||||
context.fillRect(0, 0, w, h);
|
||||
context.fillRect(xoffs, yoffs, w, h);
|
||||
|
||||
if (this.root.app.settings.getAllSettings().displayChunkBorders) {
|
||||
context.fillStyle = THEME.map.chunkBorders;
|
||||
context.fillRect(0, 0, w, 1);
|
||||
context.fillRect(0, 1, 1, h);
|
||||
context.fillRect(xoffs, yoffs, w, 1);
|
||||
context.fillRect(xoffs, yoffs + 1, 1, h);
|
||||
}
|
||||
|
||||
for (let x = 0; x < globalConfig.mapChunkSize; ++x) {
|
||||
@ -174,8 +143,8 @@ export class MapChunkView extends MapChunk {
|
||||
if (lowerContent) {
|
||||
context.fillStyle = lowerContent.getBackgroundColorAsResource();
|
||||
context.fillRect(
|
||||
x * CHUNK_OVERLAY_RES,
|
||||
y * CHUNK_OVERLAY_RES,
|
||||
xoffs + x * CHUNK_OVERLAY_RES,
|
||||
yoffs + y * CHUNK_OVERLAY_RES,
|
||||
CHUNK_OVERLAY_RES,
|
||||
CHUNK_OVERLAY_RES
|
||||
);
|
||||
@ -190,8 +159,8 @@ export class MapChunkView extends MapChunk {
|
||||
const isFilled = overlayMatrix[dx + dy * 3];
|
||||
if (isFilled) {
|
||||
context.fillRect(
|
||||
x * CHUNK_OVERLAY_RES + dx,
|
||||
y * CHUNK_OVERLAY_RES + dy,
|
||||
xoffs + x * CHUNK_OVERLAY_RES + dx,
|
||||
yoffs + y * CHUNK_OVERLAY_RES + dy,
|
||||
1,
|
||||
1
|
||||
);
|
||||
@ -206,8 +175,8 @@ export class MapChunkView extends MapChunk {
|
||||
data.rotationVariant
|
||||
);
|
||||
context.fillRect(
|
||||
x * CHUNK_OVERLAY_RES,
|
||||
y * CHUNK_OVERLAY_RES,
|
||||
xoffs + x * CHUNK_OVERLAY_RES,
|
||||
yoffs + y * CHUNK_OVERLAY_RES,
|
||||
CHUNK_OVERLAY_RES,
|
||||
CHUNK_OVERLAY_RES
|
||||
);
|
||||
@ -220,8 +189,8 @@ export class MapChunkView extends MapChunk {
|
||||
if (lowerContent) {
|
||||
context.fillStyle = lowerContent.getBackgroundColorAsResource();
|
||||
context.fillRect(
|
||||
x * CHUNK_OVERLAY_RES,
|
||||
y * CHUNK_OVERLAY_RES,
|
||||
xoffs + x * CHUNK_OVERLAY_RES,
|
||||
yoffs + y * CHUNK_OVERLAY_RES,
|
||||
CHUNK_OVERLAY_RES,
|
||||
CHUNK_OVERLAY_RES
|
||||
);
|
||||
@ -233,7 +202,7 @@ export class MapChunkView extends MapChunk {
|
||||
// Draw wires overlay
|
||||
|
||||
context.fillStyle = THEME.map.wires.overlayColor;
|
||||
context.fillRect(0, 0, w, h);
|
||||
context.fillRect(xoffs, yoffs, w, h);
|
||||
|
||||
for (let x = 0; x < globalConfig.mapChunkSize; ++x) {
|
||||
const wiresArray = this.wireContents[x];
|
||||
@ -244,8 +213,8 @@ export class MapChunkView extends MapChunk {
|
||||
}
|
||||
MapChunkView.drawSingleWiresOverviewTile({
|
||||
context,
|
||||
x: x * CHUNK_OVERLAY_RES,
|
||||
y: y * CHUNK_OVERLAY_RES,
|
||||
x: xoffs + x * CHUNK_OVERLAY_RES,
|
||||
y: yoffs + y * CHUNK_OVERLAY_RES,
|
||||
entity: content,
|
||||
tileSizePixels: CHUNK_OVERLAY_RES,
|
||||
});
|
||||
|
||||
@ -5,6 +5,7 @@ import { freeCanvas, makeOffscreenBuffer } from "../core/buffer_utils";
|
||||
import { Entity } from "./entity";
|
||||
import { THEME } from "./theme";
|
||||
import { MapChunkView } from "./map_chunk_view";
|
||||
import { MapChunkAggregate } from "./map_chunk_aggregate";
|
||||
|
||||
/**
|
||||
* This is the view of the map, it extends the map which is the raw model and allows
|
||||
@ -164,6 +165,40 @@ export class MapView extends BaseMap {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls a given method on all given chunks
|
||||
* @param {DrawParameters} parameters
|
||||
* @param {function} method
|
||||
*/
|
||||
drawVisibleAggregates(parameters, method) {
|
||||
const cullRange = parameters.visibleRect.allScaled(1 / globalConfig.tileSize);
|
||||
const top = cullRange.top();
|
||||
const right = cullRange.right();
|
||||
const bottom = cullRange.bottom();
|
||||
const left = cullRange.left();
|
||||
|
||||
const border = 0;
|
||||
const minY = top - border;
|
||||
const maxY = bottom + border;
|
||||
const minX = left - border;
|
||||
const maxX = right + border;
|
||||
|
||||
const aggregateTiles = globalConfig.chunkAggregateSize * globalConfig.mapChunkSize;
|
||||
const aggStartX = Math.floor(minX / aggregateTiles);
|
||||
const aggStartY = Math.floor(minY / aggregateTiles);
|
||||
|
||||
const aggEndX = Math.floor(maxX / aggregateTiles);
|
||||
const aggEndY = Math.floor(maxY / aggregateTiles);
|
||||
|
||||
// Render y from top down for proper blending
|
||||
for (let aggX = aggStartX; aggX <= aggEndX; ++aggX) {
|
||||
for (let aggY = aggStartY; aggY <= aggEndY; ++aggY) {
|
||||
const aggregate = this.root.map.getAggregate(aggX, aggY, true);
|
||||
method.call(aggregate, parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the wires foreground
|
||||
* @param {DrawParameters} parameters
|
||||
@ -177,7 +212,7 @@ export class MapView extends BaseMap {
|
||||
* @param {DrawParameters} parameters
|
||||
*/
|
||||
drawOverlay(parameters) {
|
||||
this.drawVisibleChunks(parameters, MapChunkView.prototype.drawOverlay);
|
||||
this.drawVisibleAggregates(parameters, MapChunkAggregate.prototype.drawOverlay);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -30,6 +30,7 @@ import { HUDPuzzlePlaySettings } from "../hud/parts/puzzle_play_settings";
|
||||
import { MetaBlockBuilding } from "../buildings/block";
|
||||
import { MetaBuilding } from "../meta_building";
|
||||
import { gMetaBuildingRegistry } from "../../core/global_registries";
|
||||
import { HUDPuzzleNextPuzzle } from "../hud/parts/HUDPuzzleNextPuzzle";
|
||||
|
||||
const logger = createLogger("puzzle-play");
|
||||
const copy = require("clipboard-copy");
|
||||
@ -43,8 +44,9 @@ export class PuzzlePlayGameMode extends PuzzleGameMode {
|
||||
* @param {GameRoot} root
|
||||
* @param {object} payload
|
||||
* @param {import("../../savegame/savegame_typedefs").PuzzleFullData} payload.puzzle
|
||||
* @param {Array<number> | undefined} payload.nextPuzzles
|
||||
*/
|
||||
constructor(root, { puzzle }) {
|
||||
constructor(root, { puzzle, nextPuzzles }) {
|
||||
super(root);
|
||||
|
||||
/** @type {Array<typeof MetaBuilding>} */
|
||||
@ -95,6 +97,15 @@ export class PuzzlePlayGameMode extends PuzzleGameMode {
|
||||
root.signals.postLoadHook.add(this.loadPuzzle, this);
|
||||
|
||||
this.puzzle = puzzle;
|
||||
|
||||
/**
|
||||
* @type {Array<number>}
|
||||
*/
|
||||
this.nextPuzzles = nextPuzzles || [];
|
||||
|
||||
if (this.nextPuzzles.length > 0) {
|
||||
this.additionalHudParts.puzzleNext = HUDPuzzleNextPuzzle;
|
||||
}
|
||||
}
|
||||
|
||||
loadPuzzle() {
|
||||
|
||||
@ -344,61 +344,61 @@ export function generateLevelDefinitions(limitedVersion = false) {
|
||||
reward: enumHubGoalRewards.reward_rotater_ccw,
|
||||
},
|
||||
|
||||
// 8
|
||||
{
|
||||
shapes: [{ key: "RbRb----", amount: 480 }], // painter t2
|
||||
reward: enumHubGoalRewards.reward_mixer,
|
||||
},
|
||||
|
||||
// 9
|
||||
// Mixing (purple)
|
||||
{
|
||||
shapes: [{ key: "CpCpCpCp", amount: 600 }], // belts t3
|
||||
reward: enumHubGoalRewards.reward_merger,
|
||||
},
|
||||
|
||||
// 10
|
||||
// STACKER: Star shapes + cyan
|
||||
{
|
||||
shapes: [{ key: "ScScScSc", amount: 800 }], // miners t3
|
||||
reward: enumHubGoalRewards.reward_stacker,
|
||||
},
|
||||
|
||||
// 11
|
||||
// Chainable miner
|
||||
{
|
||||
shapes: [{ key: "CgScScCg", amount: 1000 }], // processors t3
|
||||
reward: enumHubGoalRewards.reward_miner_chainable,
|
||||
},
|
||||
|
||||
// 12
|
||||
// Blueprints
|
||||
{
|
||||
shapes: [{ key: "CbCbCbRb:CwCwCwCw", amount: 1000 }],
|
||||
reward: enumHubGoalRewards.reward_blueprints,
|
||||
},
|
||||
|
||||
// 13
|
||||
// Tunnel Tier 2
|
||||
{
|
||||
shapes: [{ key: chinaShapes ? "CuCuCuCu:CwCwCwCw:Sb--Sr--" : "RpRpRpRp:CwCwCwCw", amount: 3800 }], // painting t3
|
||||
reward: enumHubGoalRewards.reward_underground_belt_tier_2,
|
||||
},
|
||||
|
||||
// DEMO STOPS HERE
|
||||
...(limitedVersion
|
||||
? [
|
||||
{
|
||||
shapes: [
|
||||
{
|
||||
key: chinaShapes ? "CuCuCuCu:CwCwCwCw:Sb--Sr--" : "RpRpRpRp:CwCwCwCw",
|
||||
amount: 0,
|
||||
},
|
||||
],
|
||||
shapes: [{ key: "CrCrCrCr", amount: 0 }],
|
||||
reward: enumHubGoalRewards.reward_demo_end,
|
||||
},
|
||||
]
|
||||
: [
|
||||
// 8
|
||||
{
|
||||
shapes: [{ key: "RbRb----", amount: 480 }], // painter t2
|
||||
reward: enumHubGoalRewards.reward_mixer,
|
||||
},
|
||||
|
||||
// 9
|
||||
// Mixing (purple)
|
||||
{
|
||||
shapes: [{ key: "CpCpCpCp", amount: 600 }], // belts t3
|
||||
reward: enumHubGoalRewards.reward_merger,
|
||||
},
|
||||
|
||||
// 10
|
||||
// STACKER: Star shapes + cyan
|
||||
{
|
||||
shapes: [{ key: "ScScScSc", amount: 800 }], // miners t3
|
||||
reward: enumHubGoalRewards.reward_stacker,
|
||||
},
|
||||
|
||||
// 11
|
||||
// Chainable miner
|
||||
{
|
||||
shapes: [{ key: "CgScScCg", amount: 1000 }], // processors t3
|
||||
reward: enumHubGoalRewards.reward_miner_chainable,
|
||||
},
|
||||
|
||||
// 12
|
||||
// Blueprints
|
||||
{
|
||||
shapes: [{ key: "CbCbCbRb:CwCwCwCw", amount: 1000 }],
|
||||
reward: enumHubGoalRewards.reward_blueprints,
|
||||
},
|
||||
|
||||
// 13
|
||||
// Tunnel Tier 2
|
||||
{
|
||||
shapes: [
|
||||
{
|
||||
key: chinaShapes ? "CuCuCuCu:CwCwCwCw:Sb--Sr--" : "RpRpRpRp:CwCwCwCw",
|
||||
amount: 3800,
|
||||
},
|
||||
], // painting t3
|
||||
reward: enumHubGoalRewards.reward_underground_belt_tier_2,
|
||||
},
|
||||
|
||||
// 14
|
||||
// Belt reader
|
||||
{
|
||||
@ -585,7 +585,9 @@ export class RegularGameMode extends GameMode {
|
||||
}
|
||||
|
||||
if (this.root.app.settings.getAllSettings().offerHints) {
|
||||
this.additionalHudParts.tutorialHints = HUDPartTutorialHints;
|
||||
if (!G_WEGAME_VERSION) {
|
||||
this.additionalHudParts.tutorialHints = HUDPartTutorialHints;
|
||||
}
|
||||
this.additionalHudParts.interactiveTutorial = HUDInteractiveTutorial;
|
||||
}
|
||||
|
||||
@ -595,12 +597,12 @@ export class RegularGameMode extends GameMode {
|
||||
}
|
||||
|
||||
/** @type {(typeof MetaBuilding)[]} */
|
||||
this.hiddenBuildings = [
|
||||
MetaConstantProducerBuilding,
|
||||
MetaGoalAcceptorBuilding,
|
||||
MetaBlockBuilding,
|
||||
MetaItemProducerBuilding,
|
||||
];
|
||||
this.hiddenBuildings = [MetaConstantProducerBuilding, MetaGoalAcceptorBuilding, MetaBlockBuilding];
|
||||
|
||||
// @ts-expect-error
|
||||
if (!(G_IS_DEV || window.sandboxMode || queryParamOptions.sandboxMode)) {
|
||||
this.hiddenBuildings.push(MetaItemProducerBuilding);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -49,11 +49,12 @@ export class ConstantSignalSystem extends GameSystemWithFilter {
|
||||
// Ok, query, but also save the uid because it could get stale
|
||||
const uid = entity.uid;
|
||||
|
||||
const signal = entity.components.ConstantSignal.signal;
|
||||
const signalValueInput = new FormElementInput({
|
||||
id: "signalValue",
|
||||
label: fillInLinkIntoTranslation(T.dialogs.editSignal.descShortKey, THIRDPARTY_URLS.shapeViewer),
|
||||
placeholder: "",
|
||||
defaultValue: "",
|
||||
defaultValue: signal ? signal.getAsCopyableKey() : "",
|
||||
validator: val => this.parseSignalCode(entity, val),
|
||||
});
|
||||
|
||||
|
||||
@ -32,8 +32,8 @@ const MAX_QUEUED_CHARGES = 2;
|
||||
* Type of a processor implementation
|
||||
* @typedef {{
|
||||
* entity: Entity,
|
||||
* items: Array<{ item: BaseItem, sourceSlot: number }>,
|
||||
* itemsBySlot: Object<number, BaseItem>,
|
||||
* items: Map<number, BaseItem>,
|
||||
* inputCount: number,
|
||||
* outItems: Array<ProducedItem>
|
||||
* }} ProcessorImplementationPayload
|
||||
*/
|
||||
@ -189,7 +189,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
// DEFAULT
|
||||
// By default, we can start processing once all inputs are there
|
||||
case null: {
|
||||
return processorComp.inputSlots.length >= processorComp.inputsPerCharge;
|
||||
return processorComp.inputCount >= processorComp.inputsPerCharge;
|
||||
}
|
||||
|
||||
// QUAD PAINTER
|
||||
@ -197,18 +197,12 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
case enumItemProcessorRequirements.painterQuad: {
|
||||
const pinsComp = entity.components.WiredPins;
|
||||
|
||||
/** @type {Object.<number, { item: BaseItem, sourceSlot: number }>} */
|
||||
const itemsBySlot = {};
|
||||
for (let i = 0; i < processorComp.inputSlots.length; ++i) {
|
||||
itemsBySlot[processorComp.inputSlots[i].sourceSlot] = processorComp.inputSlots[i];
|
||||
}
|
||||
|
||||
// First slot is the shape, so if it's not there we can't do anything
|
||||
if (!itemsBySlot[0]) {
|
||||
const shapeItem = /** @type {ShapeItem} */ (processorComp.inputSlots.get(0));
|
||||
if (!shapeItem) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const shapeItem = /** @type {ShapeItem} */ (itemsBySlot[0].item);
|
||||
const slotStatus = [];
|
||||
|
||||
// Check which slots are enabled
|
||||
@ -233,7 +227,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
|
||||
// Check if all colors of the enabled slots are there
|
||||
for (let i = 0; i < slotStatus.length; ++i) {
|
||||
if (slotStatus[i] && !itemsBySlot[1 + i]) {
|
||||
if (slotStatus[i] && !processorComp.inputSlots.get(1 + i)) {
|
||||
// A slot which is enabled wasn't enabled. Make sure if there is anything on the quadrant,
|
||||
// it is not possible to paint, but if there is nothing we can ignore it
|
||||
for (let j = 0; j < 4; ++j) {
|
||||
@ -262,13 +256,6 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
|
||||
// First, take items
|
||||
const items = processorComp.inputSlots;
|
||||
processorComp.inputSlots = [];
|
||||
|
||||
/** @type {Object<string, BaseItem>} */
|
||||
const itemsBySlot = {};
|
||||
for (let i = 0; i < items.length; ++i) {
|
||||
itemsBySlot[items[i].sourceSlot] = items[i].item;
|
||||
}
|
||||
|
||||
/** @type {Array<ProducedItem>} */
|
||||
const outItems = [];
|
||||
@ -281,8 +268,8 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
handler({
|
||||
entity,
|
||||
items,
|
||||
itemsBySlot,
|
||||
outItems,
|
||||
inputCount: processorComp.inputCount,
|
||||
});
|
||||
|
||||
// Track produced items
|
||||
@ -304,6 +291,9 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
items: outItems,
|
||||
remainingTime: timeToProcess,
|
||||
});
|
||||
|
||||
processorComp.inputSlots.clear();
|
||||
processorComp.inputCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -317,12 +307,14 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
const availableSlots = payload.entity.components.ItemEjector.slots.length;
|
||||
const processorComp = payload.entity.components.ItemProcessor;
|
||||
|
||||
const nextSlot = processorComp.nextOutputSlot++ % availableSlots;
|
||||
|
||||
for (let i = 0; i < payload.items.length; ++i) {
|
||||
for (let i = 0; i < 2; ++i) {
|
||||
const item = payload.items.get(i);
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
payload.outItems.push({
|
||||
item: payload.items[i].item,
|
||||
preferredSlot: (nextSlot + i) % availableSlots,
|
||||
item,
|
||||
preferredSlot: processorComp.nextOutputSlot++ % availableSlots,
|
||||
doNotTrack: true,
|
||||
});
|
||||
}
|
||||
@ -333,20 +325,25 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
* @param {ProcessorImplementationPayload} payload
|
||||
*/
|
||||
process_CUTTER(payload) {
|
||||
const inputItem = /** @type {ShapeItem} */ (payload.items[0].item);
|
||||
const inputItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
||||
assert(inputItem instanceof ShapeItem, "Input for cut is not a shape");
|
||||
const inputDefinition = inputItem.definition;
|
||||
|
||||
const cutDefinitions = this.root.shapeDefinitionMgr.shapeActionCutHalf(inputDefinition);
|
||||
|
||||
const ejectorComp = payload.entity.components.ItemEjector;
|
||||
for (let i = 0; i < cutDefinitions.length; ++i) {
|
||||
const definition = cutDefinitions[i];
|
||||
if (!definition.isEntirelyEmpty()) {
|
||||
payload.outItems.push({
|
||||
item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(definition),
|
||||
requiredSlot: i,
|
||||
});
|
||||
|
||||
if (definition.isEntirelyEmpty()) {
|
||||
ejectorComp.slots[i].lastItem = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
payload.outItems.push({
|
||||
item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(definition),
|
||||
requiredSlot: i,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,20 +351,25 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
* @param {ProcessorImplementationPayload} payload
|
||||
*/
|
||||
process_CUTTER_QUAD(payload) {
|
||||
const inputItem = /** @type {ShapeItem} */ (payload.items[0].item);
|
||||
const inputItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
||||
assert(inputItem instanceof ShapeItem, "Input for cut is not a shape");
|
||||
const inputDefinition = inputItem.definition;
|
||||
|
||||
const cutDefinitions = this.root.shapeDefinitionMgr.shapeActionCutQuad(inputDefinition);
|
||||
|
||||
const ejectorComp = payload.entity.components.ItemEjector;
|
||||
for (let i = 0; i < cutDefinitions.length; ++i) {
|
||||
const definition = cutDefinitions[i];
|
||||
if (!definition.isEntirelyEmpty()) {
|
||||
payload.outItems.push({
|
||||
item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(definition),
|
||||
requiredSlot: i,
|
||||
});
|
||||
|
||||
if (definition.isEntirelyEmpty()) {
|
||||
ejectorComp.slots[i].lastItem = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
payload.outItems.push({
|
||||
item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(definition),
|
||||
requiredSlot: i,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -375,7 +377,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
* @param {ProcessorImplementationPayload} payload
|
||||
*/
|
||||
process_ROTATER(payload) {
|
||||
const inputItem = /** @type {ShapeItem} */ (payload.items[0].item);
|
||||
const inputItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
||||
assert(inputItem instanceof ShapeItem, "Input for rotation is not a shape");
|
||||
const inputDefinition = inputItem.definition;
|
||||
|
||||
@ -389,7 +391,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
* @param {ProcessorImplementationPayload} payload
|
||||
*/
|
||||
process_ROTATER_CCW(payload) {
|
||||
const inputItem = /** @type {ShapeItem} */ (payload.items[0].item);
|
||||
const inputItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
||||
assert(inputItem instanceof ShapeItem, "Input for rotation is not a shape");
|
||||
const inputDefinition = inputItem.definition;
|
||||
|
||||
@ -403,7 +405,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
* @param {ProcessorImplementationPayload} payload
|
||||
*/
|
||||
process_ROTATER_180(payload) {
|
||||
const inputItem = /** @type {ShapeItem} */ (payload.items[0].item);
|
||||
const inputItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
||||
assert(inputItem instanceof ShapeItem, "Input for rotation is not a shape");
|
||||
const inputDefinition = inputItem.definition;
|
||||
|
||||
@ -417,8 +419,8 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
* @param {ProcessorImplementationPayload} payload
|
||||
*/
|
||||
process_STACKER(payload) {
|
||||
const lowerItem = /** @type {ShapeItem} */ (payload.itemsBySlot[0]);
|
||||
const upperItem = /** @type {ShapeItem} */ (payload.itemsBySlot[1]);
|
||||
const lowerItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
||||
const upperItem = /** @type {ShapeItem} */ (payload.items.get(1));
|
||||
|
||||
assert(lowerItem instanceof ShapeItem, "Input for lower stack is not a shape");
|
||||
assert(upperItem instanceof ShapeItem, "Input for upper stack is not a shape");
|
||||
@ -444,8 +446,8 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
*/
|
||||
process_MIXER(payload) {
|
||||
// Find both colors and combine them
|
||||
const item1 = /** @type {ColorItem} */ (payload.items[0].item);
|
||||
const item2 = /** @type {ColorItem} */ (payload.items[1].item);
|
||||
const item1 = /** @type {ColorItem} */ (payload.items.get(0));
|
||||
const item2 = /** @type {ColorItem} */ (payload.items.get(1));
|
||||
assert(item1 instanceof ColorItem, "Input for color mixer is not a color");
|
||||
assert(item2 instanceof ColorItem, "Input for color mixer is not a color");
|
||||
|
||||
@ -467,8 +469,8 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
* @param {ProcessorImplementationPayload} payload
|
||||
*/
|
||||
process_PAINTER(payload) {
|
||||
const shapeItem = /** @type {ShapeItem} */ (payload.itemsBySlot[0]);
|
||||
const colorItem = /** @type {ColorItem} */ (payload.itemsBySlot[1]);
|
||||
const shapeItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
||||
const colorItem = /** @type {ColorItem} */ (payload.items.get(1));
|
||||
|
||||
const colorizedDefinition = this.root.shapeDefinitionMgr.shapeActionPaintWith(
|
||||
shapeItem.definition,
|
||||
@ -484,9 +486,9 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
* @param {ProcessorImplementationPayload} payload
|
||||
*/
|
||||
process_PAINTER_DOUBLE(payload) {
|
||||
const shapeItem1 = /** @type {ShapeItem} */ (payload.itemsBySlot[0]);
|
||||
const shapeItem2 = /** @type {ShapeItem} */ (payload.itemsBySlot[1]);
|
||||
const colorItem = /** @type {ColorItem} */ (payload.itemsBySlot[2]);
|
||||
const shapeItem1 = /** @type {ShapeItem} */ (payload.items.get(0));
|
||||
const shapeItem2 = /** @type {ShapeItem} */ (payload.items.get(1));
|
||||
const colorItem = /** @type {ColorItem} */ (payload.items.get(2));
|
||||
|
||||
assert(shapeItem1 instanceof ShapeItem, "Input for painter is not a shape");
|
||||
assert(shapeItem2 instanceof ShapeItem, "Input for painter is not a shape");
|
||||
@ -514,14 +516,15 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
* @param {ProcessorImplementationPayload} payload
|
||||
*/
|
||||
process_PAINTER_QUAD(payload) {
|
||||
const shapeItem = /** @type {ShapeItem} */ (payload.itemsBySlot[0]);
|
||||
const shapeItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
||||
assert(shapeItem instanceof ShapeItem, "Input for painter is not a shape");
|
||||
|
||||
/** @type {Array<enumColors>} */
|
||||
const colors = [null, null, null, null];
|
||||
for (let i = 0; i < 4; ++i) {
|
||||
if (payload.itemsBySlot[i + 1]) {
|
||||
colors[i] = /** @type {ColorItem} */ (payload.itemsBySlot[i + 1]).color;
|
||||
const colorItem = /** @type {ColorItem} */ (payload.items.get(i + 1));
|
||||
if (colorItem) {
|
||||
colors[i] = colorItem.color;
|
||||
}
|
||||
}
|
||||
|
||||
@ -540,7 +543,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
*/
|
||||
process_READER(payload) {
|
||||
// Pass through the item
|
||||
const item = payload.itemsBySlot[0];
|
||||
const item = payload.items.get(0);
|
||||
payload.outItems.push({
|
||||
item,
|
||||
doNotTrack: true,
|
||||
@ -559,8 +562,12 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
const hubComponent = payload.entity.components.Hub;
|
||||
assert(hubComponent, "Hub item processor has no hub component");
|
||||
|
||||
for (let i = 0; i < payload.items.length; ++i) {
|
||||
const item = /** @type {ShapeItem} */ (payload.items[i].item);
|
||||
// Hardcoded
|
||||
for (let i = 0; i < payload.inputCount; ++i) {
|
||||
const item = /** @type {ShapeItem} */ (payload.items.get(i));
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
this.root.hubGoals.handleDefinitionDelivered(item.definition);
|
||||
}
|
||||
}
|
||||
@ -570,7 +577,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
*/
|
||||
process_GOAL(payload) {
|
||||
const goalComp = payload.entity.components.GoalAcceptor;
|
||||
const item = payload.items[0].item;
|
||||
const item = payload.items.get(0);
|
||||
const now = this.root.time.now();
|
||||
|
||||
if (goalComp.item && !item.equals(goalComp.item)) {
|
||||
@ -584,7 +591,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
|
||||
if (this.root.gameMode.getIsEditor()) {
|
||||
// while playing in editor, assign the item
|
||||
goalComp.item = payload.items[0].item;
|
||||
goalComp.item = item;
|
||||
}
|
||||
|
||||
goalComp.lastDelivery = {
|
||||
|
||||
@ -59,5 +59,10 @@
|
||||
"outline": "#111418",
|
||||
"outlineWidth": 0.75,
|
||||
"circleBackground": "rgba(20, 30, 40, 0.3)"
|
||||
},
|
||||
|
||||
"shapeTooltip": {
|
||||
"background": "rgba(242, 245, 254, 0.9)",
|
||||
"outline": "#44464e"
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,5 +60,10 @@
|
||||
"outline": "#55575a",
|
||||
"outlineWidth": 0.75,
|
||||
"circleBackground": "rgba(40, 50, 65, 0.1)"
|
||||
},
|
||||
|
||||
"shapeTooltip": {
|
||||
"background": "#dee1ea",
|
||||
"outline": "#54565e"
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,9 @@ export const LANGUAGES = {
|
||||
"zh-CN": {
|
||||
// simplified chinese
|
||||
name: "简体中文",
|
||||
data: require("./built-temp/base-zh-CN.json"),
|
||||
data: G_WEGAME_VERSION
|
||||
? require("./built-temp/base-zh-CN-ISBN.json")
|
||||
: require("./built-temp/base-zh-CN.json"),
|
||||
code: "zh",
|
||||
region: "CN",
|
||||
},
|
||||
|
||||
@ -95,6 +95,10 @@ export class GamedistributionAdProvider extends AdProviderInterface {
|
||||
|
||||
document.body.classList.add("externalAdOpen");
|
||||
|
||||
logger.log("Set sound volume to 0");
|
||||
this.app.sound.setMusicVolume(0);
|
||||
this.app.sound.setSoundVolume(0);
|
||||
|
||||
return new Promise(resolve => {
|
||||
// So, wait for the remove call but also remove after N seconds
|
||||
this.videoAdResolveFunction = () => {
|
||||
@ -119,6 +123,11 @@ export class GamedistributionAdProvider extends AdProviderInterface {
|
||||
})
|
||||
.then(() => {
|
||||
document.body.classList.remove("externalAdOpen");
|
||||
|
||||
logger.log("Restored sound volume");
|
||||
|
||||
this.app.sound.setMusicVolume(this.app.settings.getSetting("musicVolume"));
|
||||
this.app.sound.setSoundVolume(this.app.settings.getSetting("soundVolume"));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,6 +143,20 @@ export class ClientAPI {
|
||||
return this._request("/v1/puzzles/list/" + category, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{ searchTerm: string; difficulty: string; duration: string }} searchOptions
|
||||
* @returns {Promise<import("../savegame/savegame_typedefs").PuzzleMetadata[]>}
|
||||
*/
|
||||
apiSearchPuzzles(searchOptions) {
|
||||
if (!this.isLoggedIn()) {
|
||||
return Promise.reject("not-logged-in");
|
||||
}
|
||||
return this._request("/v1/puzzles/search", {
|
||||
method: "POST",
|
||||
body: searchOptions,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} puzzleId
|
||||
* @returns {Promise<import("../savegame/savegame_typedefs").PuzzleFullData>}
|
||||
@ -169,7 +183,7 @@ export class ClientAPI {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} shortKey
|
||||
* @param {string} shortKey
|
||||
* @returns {Promise<import("../savegame/savegame_typedefs").PuzzleFullData>}
|
||||
*/
|
||||
apiDownloadPuzzleByKey(shortKey) {
|
||||
|
||||
@ -111,6 +111,10 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface {
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
sendToApi(endpoint, data) {
|
||||
if (G_WEGAME_VERSION) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const timeout = setTimeout(() => reject("Request to " + endpoint + " timed out"), 20000);
|
||||
|
||||
|
||||
@ -135,15 +135,7 @@ export class PlatformWrapperImplBrowser extends PlatformWrapperInterface {
|
||||
|
||||
openExternalLink(url, force = false) {
|
||||
logger.log("Opening external:", url);
|
||||
if (force || this.embedProvider.externalLinks) {
|
||||
window.open(url);
|
||||
} 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: " +
|
||||
url
|
||||
);
|
||||
}
|
||||
window.open(url);
|
||||
}
|
||||
|
||||
performRestart() {
|
||||
|
||||
@ -257,6 +257,7 @@ export const allApplicationSettings = [
|
||||
}),
|
||||
|
||||
new BoolSetting("enableMousePan", enumCategories.advanced, (app, value) => {}),
|
||||
new BoolSetting("shapeTooltipAlwaysOn", 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) => {}),
|
||||
@ -272,7 +273,7 @@ export const allApplicationSettings = [
|
||||
new EnumSetting("refreshRate", {
|
||||
options: refreshRateOptions,
|
||||
valueGetter: rate => rate,
|
||||
textGetter: rate => rate + " Hz",
|
||||
textGetter: rate => T.settings.tickrateHz.replace("<amount>", rate),
|
||||
category: enumCategories.performance,
|
||||
restartRequired: false,
|
||||
changeCb: (app, id) => {},
|
||||
@ -307,6 +308,7 @@ class SettingsStorage {
|
||||
this.autosaveInterval = "two_minutes";
|
||||
|
||||
this.alwaysMultiplace = false;
|
||||
this.shapeTooltipAlwaysOn = false;
|
||||
this.offerHints = true;
|
||||
this.enableTunnelSmartplace = true;
|
||||
this.vignette = true;
|
||||
@ -536,7 +538,7 @@ export class ApplicationSettings extends ReadWriteProxy {
|
||||
}
|
||||
|
||||
getCurrentVersion() {
|
||||
return 30;
|
||||
return 31;
|
||||
}
|
||||
|
||||
/** @param {{settings: SettingsStorage, version: number}} data */
|
||||
@ -683,6 +685,11 @@ export class ApplicationSettings extends ReadWriteProxy {
|
||||
data.version = 30;
|
||||
}
|
||||
|
||||
if (data.version < 31) {
|
||||
data.settings.shapeTooltipAlwaysOn = false;
|
||||
data.version = 31;
|
||||
}
|
||||
|
||||
return ExplainedResult.good();
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,6 +64,24 @@ export class Savegame extends ReadWriteProxy {
|
||||
return savegameInterfaces[Savegame.getCurrentVersion()];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Application} app
|
||||
* @returns
|
||||
*/
|
||||
static createPuzzleSavegame(app) {
|
||||
return new Savegame(app, {
|
||||
internalId: "puzzle",
|
||||
metaDataRef: {
|
||||
internalId: "puzzle",
|
||||
lastUpdate: 0,
|
||||
version: 0,
|
||||
level: 0,
|
||||
name: "puzzle",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
@ -17,6 +17,7 @@ import {
|
||||
waitNextFrame,
|
||||
} from "../core/utils";
|
||||
import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs";
|
||||
import { PlatformWrapperImplBrowser } from "../platform/browser/wrapper";
|
||||
import { PlatformWrapperImplElectron } from "../platform/electron/wrapper";
|
||||
import { getApplicationSettingById } from "../profile/application_settings";
|
||||
import { T } from "../translations";
|
||||
@ -34,35 +35,57 @@ export class MainMenuState extends GameState {
|
||||
}
|
||||
|
||||
getInnerHTML() {
|
||||
const showLanguageIcon = !G_CHINA_VERSION && !G_WEGAME_VERSION;
|
||||
const showExitAppButton = G_IS_STANDALONE;
|
||||
const showUpdateLabel = !G_WEGAME_VERSION;
|
||||
const showBrowserWarning = !G_IS_STANDALONE && !isSupportedBrowser();
|
||||
const showPuzzleDLC = !G_WEGAME_VERSION && (G_IS_STANDALONE || G_IS_DEV);
|
||||
const showWegameFooter = G_WEGAME_VERSION;
|
||||
|
||||
let showExternalLinks = true;
|
||||
|
||||
if (G_IS_STANDALONE) {
|
||||
if (G_WEGAME_VERSION || G_CHINA_VERSION) {
|
||||
showExternalLinks = false;
|
||||
}
|
||||
} else {
|
||||
const wrapper = /** @type {PlatformWrapperImplBrowser} */ (this.app.platformWrapper);
|
||||
if (!wrapper.embedProvider.externalLinks) {
|
||||
showExternalLinks = false;
|
||||
}
|
||||
}
|
||||
|
||||
let showDiscordLink = showExternalLinks;
|
||||
if (G_CHINA_VERSION) {
|
||||
showDiscordLink = true;
|
||||
}
|
||||
|
||||
const showCrosspromo = !G_IS_STANDALONE && showExternalLinks;
|
||||
const showDemoAdvertisement =
|
||||
showExternalLinks && this.app.restrictionMgr.getIsStandaloneMarketingActive();
|
||||
|
||||
const ownsPuzzleDLC =
|
||||
G_IS_DEV ||
|
||||
(G_IS_STANDALONE &&
|
||||
/** @type { PlatformWrapperImplElectron}*/ (this.app.platformWrapper).dlcs.puzzle);
|
||||
|
||||
const bannerHtml = `
|
||||
<h3>${T.demoBanners.title}</h3>
|
||||
<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>
|
||||
`;
|
||||
|
||||
const showDemoBadges = this.app.restrictionMgr.getIsStandaloneMarketingActive();
|
||||
|
||||
const puzzleDlc =
|
||||
G_IS_STANDALONE &&
|
||||
/** @type { PlatformWrapperImplElectron
|
||||
}*/ (this.app.platformWrapper).dlcs.puzzle;
|
||||
|
||||
return `
|
||||
<div class="topButtons">
|
||||
${
|
||||
G_CHINA_VERSION || G_WEGAME_VERSION
|
||||
? ""
|
||||
: `<button class="languageChoose" data-languageicon="${this.app.settings.getLanguage()}"></button>`
|
||||
showLanguageIcon
|
||||
? `<button class="languageChoose" data-languageicon="${this.app.settings.getLanguage()}"></button>`
|
||||
: ""
|
||||
}
|
||||
|
||||
<button class="settingsButton"></button>
|
||||
${
|
||||
G_IS_STANDALONE || G_IS_DEV
|
||||
? `
|
||||
<button class="exitAppButton"></button>
|
||||
`
|
||||
: ""
|
||||
}
|
||||
${showExitAppButton ? `<button class="exitAppButton"></button>` : ""}
|
||||
</div>
|
||||
|
||||
<video autoplay muted loop class="fullscreenBackgroundVideo">
|
||||
@ -71,27 +94,25 @@ export class MainMenuState extends GameState {
|
||||
|
||||
<div class="logo">
|
||||
<img src="${cachebust("res/" + getLogoSprite())}" alt="shapez.io Logo">
|
||||
${G_WEGAME_VERSION ? "" : `<span class="updateLabel">v${G_BUILD_VERSION}!</span>`}
|
||||
${showUpdateLabel ? `<span class="updateLabel">v${G_BUILD_VERSION}!</span>` : ""}
|
||||
</div>
|
||||
|
||||
<div class="mainWrapper ${showDemoBadges ? "demo" : "noDemo"}" data-columns="${
|
||||
G_IS_STANDALONE ? 2 : showDemoBadges ? 2 : 1
|
||||
}">
|
||||
<div class="mainWrapper" data-columns="${showDemoAdvertisement || showPuzzleDLC ? 2 : 1}">
|
||||
<div class="sideContainer">
|
||||
${showDemoBadges ? `<div class="standaloneBanner">${bannerHtml}</div>` : ""}
|
||||
${showDemoAdvertisement ? `<div class="standaloneBanner">${bannerHtml}</div>` : ""}
|
||||
</div>
|
||||
|
||||
<div class="mainContainer">
|
||||
${
|
||||
G_IS_STANDALONE || isSupportedBrowser()
|
||||
? ""
|
||||
: `<div class="browserWarning">${T.mainMenu.browserWarning}</div>`
|
||||
showBrowserWarning
|
||||
? `<div class="browserWarning">${T.mainMenu.browserWarning}</div>`
|
||||
: ""
|
||||
}
|
||||
<div class="buttons"></div>
|
||||
</div>
|
||||
|
||||
${
|
||||
(!G_WEGAME_VERSION && G_IS_STANDALONE && puzzleDlc) || G_IS_DEV
|
||||
showPuzzleDLC && ownsPuzzleDLC
|
||||
? `
|
||||
<div class="puzzleContainer">
|
||||
<img class="dlcLogo" src="${cachebust(
|
||||
@ -105,7 +126,7 @@ export class MainMenuState extends GameState {
|
||||
}
|
||||
|
||||
${
|
||||
!G_WEGAME_VERSION && G_IS_STANDALONE && !puzzleDlc
|
||||
showPuzzleDLC && !ownsPuzzleDLC
|
||||
? `
|
||||
<div class="puzzleContainer notOwned">
|
||||
<span class="badge">
|
||||
@ -129,40 +150,60 @@ export class MainMenuState extends GameState {
|
||||
</div>
|
||||
|
||||
${
|
||||
G_WEGAME_VERSION
|
||||
? "<div class='footer wegame'></div>"
|
||||
showWegameFooter
|
||||
? `
|
||||
<div class='footer wegameDisclaimer'>
|
||||
<div class="disclaimer">
|
||||
健康游戏忠告
|
||||
<br>
|
||||
抵制不良游戏,拒绝盗版游戏。注意自我保护,谨防受骗上当。<br>
|
||||
适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。
|
||||
</div>
|
||||
|
||||
<div class="rating"></div>
|
||||
</div>
|
||||
`
|
||||
: `
|
||||
<div class="footer ${G_CHINA_VERSION ? "china" : ""} ">
|
||||
|
||||
${
|
||||
G_CHINA_VERSION
|
||||
? ""
|
||||
: `
|
||||
<a class="githubLink boxLink" target="_blank">
|
||||
${T.mainMenu.openSourceHint}
|
||||
<span class="thirdpartyLogo githubLogo"></span>
|
||||
</a>`
|
||||
}
|
||||
<div class="footer ${showExternalLinks ? "" : "noLinks"} ">
|
||||
${
|
||||
showExternalLinks
|
||||
? `
|
||||
<a class="githubLink boxLink" target="_blank">
|
||||
${T.mainMenu.openSourceHint}
|
||||
<span class="thirdpartyLogo githubLogo"></span>
|
||||
</a>`
|
||||
: ""
|
||||
}
|
||||
|
||||
<a class="discordLink boxLink" target="_blank">
|
||||
${T.mainMenu.discordLink}
|
||||
<span class="thirdpartyLogo discordLogo"></span>
|
||||
</a>
|
||||
${
|
||||
showDiscordLink
|
||||
? `<a class="discordLink boxLink" target="_blank">
|
||||
|
||||
<div class="sidelinks">
|
||||
${G_CHINA_VERSION ? "" : `<a class="redditLink">${T.mainMenu.subreddit}</a>`}
|
||||
${T.mainMenu.discordLink}
|
||||
<span class="thirdpartyLogo discordLogo"></span>
|
||||
</a>`
|
||||
: ""
|
||||
}
|
||||
|
||||
${G_CHINA_VERSION ? "" : `<a class="changelog">${T.changelog.title}</a>`}
|
||||
<div class="sidelinks">
|
||||
${showExternalLinks ? `<a class="redditLink">${T.mainMenu.subreddit}</a>` : ""}
|
||||
|
||||
${G_CHINA_VERSION ? "" : `<a class="helpTranslate">${T.mainMenu.helpTranslate}</a>`}
|
||||
${showExternalLinks ? `<a class="changelog">${T.changelog.title}</a>` : ""}
|
||||
|
||||
${showExternalLinks ? `<a class="helpTranslate">${T.mainMenu.helpTranslate}</a>` : ""}
|
||||
</div>
|
||||
<div class="author">${T.mainMenu.madeBy.replace(
|
||||
"<author-link>",
|
||||
'<a class="producerLink" target="_blank">Tobias Springer</a>'
|
||||
)}</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="author">${T.mainMenu.madeBy.replace(
|
||||
"<author-link>",
|
||||
'<a class="producerLink" target="_blank">Tobias Springer</a>'
|
||||
)}</div>
|
||||
</div>
|
||||
${
|
||||
showCrosspromo
|
||||
? `<iframe id="crosspromo" src="https://crosspromo.tobspr.io?src=shapez_web"></iframe>`
|
||||
: ""
|
||||
}
|
||||
`
|
||||
}
|
||||
`;
|
||||
@ -251,8 +292,6 @@ export class MainMenuState extends GameState {
|
||||
);
|
||||
}
|
||||
|
||||
const qs = this.htmlElement.querySelector.bind(this.htmlElement);
|
||||
|
||||
if (G_IS_DEV && globalConfig.debug.testPuzzleMode) {
|
||||
this.onPuzzleModeButtonClicked(true);
|
||||
return;
|
||||
@ -276,71 +315,38 @@ export class MainMenuState extends GameState {
|
||||
}
|
||||
});
|
||||
|
||||
this.trackClicks(qs(".settingsButton"), this.onSettingsButtonClicked);
|
||||
const clickHandling = {
|
||||
".settingsButton": this.onSettingsButtonClicked,
|
||||
".languageChoose": this.onLanguageChooseClicked,
|
||||
".redditLink": this.onRedditClicked,
|
||||
".changelog": this.onChangelogClicked,
|
||||
".helpTranslate": this.onTranslationHelpLinkClicked,
|
||||
".exitAppButton": this.onExitAppButtonClicked,
|
||||
".steamLink": this.onSteamLinkClicked,
|
||||
".discordLink": () => {
|
||||
this.app.analytics.trackUiClick("main_menu_link_discord");
|
||||
this.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.discord);
|
||||
},
|
||||
".githubLink": () => {
|
||||
this.app.analytics.trackUiClick("main_menu_link_github");
|
||||
this.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.github);
|
||||
},
|
||||
".producerLink": () => this.app.platformWrapper.openExternalLink("https://tobspr.io"),
|
||||
".puzzleDlcPlayButton": this.onPuzzleModeButtonClicked,
|
||||
".puzzleDlcGetButton": this.onPuzzleWishlistButtonClicked,
|
||||
".wegameDisclaimer > .rating": this.onWegameRatingClicked,
|
||||
};
|
||||
|
||||
if (!G_CHINA_VERSION && !G_WEGAME_VERSION) {
|
||||
this.trackClicks(qs(".languageChoose"), this.onLanguageChooseClicked);
|
||||
this.trackClicks(qs(".redditLink"), this.onRedditClicked);
|
||||
this.trackClicks(qs(".changelog"), this.onChangelogClicked);
|
||||
this.trackClicks(qs(".helpTranslate"), this.onTranslationHelpLinkClicked);
|
||||
}
|
||||
|
||||
if (G_IS_STANDALONE) {
|
||||
this.trackClicks(qs(".exitAppButton"), this.onExitAppButtonClicked);
|
||||
for (const key in clickHandling) {
|
||||
const handler = clickHandling[key];
|
||||
const element = this.htmlElement.querySelector(key);
|
||||
if (element) {
|
||||
this.trackClicks(element, handler, { preventClick: true });
|
||||
}
|
||||
}
|
||||
|
||||
this.renderMainMenu();
|
||||
this.renderSavegames();
|
||||
|
||||
const steamLink = this.htmlElement.querySelector(".steamLink");
|
||||
if (steamLink) {
|
||||
this.trackClicks(steamLink, () => this.onSteamLinkClicked(), { preventClick: true });
|
||||
}
|
||||
|
||||
const discordLink = this.htmlElement.querySelector(".discordLink");
|
||||
if (discordLink) {
|
||||
this.trackClicks(
|
||||
discordLink,
|
||||
() => {
|
||||
this.app.analytics.trackUiClick("main_menu_link_discord");
|
||||
this.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.discord);
|
||||
},
|
||||
{ preventClick: true }
|
||||
);
|
||||
}
|
||||
|
||||
const githubLink = this.htmlElement.querySelector(".githubLink");
|
||||
if (githubLink) {
|
||||
this.trackClicks(
|
||||
githubLink,
|
||||
() => {
|
||||
this.app.analytics.trackUiClick("main_menu_link_github");
|
||||
this.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.github);
|
||||
},
|
||||
{ preventClick: true }
|
||||
);
|
||||
}
|
||||
|
||||
const producerLink = this.htmlElement.querySelector(".producerLink");
|
||||
if (producerLink) {
|
||||
this.trackClicks(
|
||||
producerLink,
|
||||
() => this.app.platformWrapper.openExternalLink("https://tobspr.io"),
|
||||
{
|
||||
preventClick: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const puzzleModeButton = qs(".puzzleDlcPlayButton");
|
||||
if (puzzleModeButton) {
|
||||
this.trackClicks(puzzleModeButton, () => this.onPuzzleModeButtonClicked());
|
||||
}
|
||||
|
||||
const puzzleWishlistButton = qs(".puzzleDlcGetButton");
|
||||
if (puzzleWishlistButton) {
|
||||
this.trackClicks(puzzleWishlistButton, () => this.onPuzzleWishlistButtonClicked());
|
||||
}
|
||||
}
|
||||
|
||||
renderMainMenu() {
|
||||
@ -511,9 +517,12 @@ export class MainMenuState extends GameState {
|
||||
downloadButton.classList.add("styledButton", "downloadGame");
|
||||
elem.appendChild(downloadButton);
|
||||
|
||||
const renameButton = document.createElement("button");
|
||||
renameButton.classList.add("styledButton", "renameGame");
|
||||
name.appendChild(renameButton);
|
||||
if (!G_WEGAME_VERSION) {
|
||||
const renameButton = document.createElement("button");
|
||||
renameButton.classList.add("styledButton", "renameGame");
|
||||
name.appendChild(renameButton);
|
||||
this.trackClicks(renameButton, () => this.requestRenameSavegame(games[i]));
|
||||
}
|
||||
|
||||
const resumeButton = document.createElement("button");
|
||||
resumeButton.classList.add("styledButton", "resumeGame");
|
||||
@ -522,7 +531,6 @@ export class MainMenuState extends GameState {
|
||||
this.trackClicks(deleteButton, () => this.deleteGame(games[i]));
|
||||
this.trackClicks(downloadButton, () => this.downloadGame(games[i]));
|
||||
this.trackClicks(resumeButton, () => this.resumeGame(games[i]));
|
||||
this.trackClicks(renameButton, () => this.requestRenameSavegame(games[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -675,6 +683,18 @@ export class MainMenuState extends GameState {
|
||||
});
|
||||
}
|
||||
|
||||
onWegameRatingClicked() {
|
||||
this.dialogs.showInfo(
|
||||
"提示说明",
|
||||
`
|
||||
1)本游戏是一款休闲建造类单机游戏,画面简洁而乐趣充足。适用于年满8周岁及以上的用户,建议未成年人在家长监护下使用游戏产品。<br>
|
||||
2)本游戏模拟简单的生产流水线,剧情简单且积极向上,没有基于真实历史和现实事件的改编内容。游戏玩法为摆放简单的部件,完成生产目标。游戏为单机作品,没有基于文字和语音的陌生人社交系统。<br>
|
||||
3)本游戏中有用户实名认证系统,认证为未成年人的用户将接受以下管理:未满8周岁的用户不能付费;8周岁以上未满16周岁的未成年人用户,单次充值金额不得超过50元人民币,每月充值金额累计不得超过200元人民币;16周岁以上的未成年人用户,单次充值金额不得超过100元人民币,每月充值金额累计不得超过400元人民币。未成年人用户每日22点到次日8点不得使用,法定节假日每天不得使用超过3小时,其他时间每天不得使用超过1.5小时。<br>
|
||||
4)游戏功能说明:一款关于传送带自动化生产特定形状产品的工厂流水线模拟游戏,画面简洁而乐趣充足,可以让玩家在轻松愉快的氛围下获得各种游戏乐趣,体验完成目标的成就感。游戏没有失败功能,自动存档,不存在较强的挫折体验。
|
||||
`
|
||||
);
|
||||
}
|
||||
|
||||
onContinueButtonClicked() {
|
||||
let latestLastUpdate = 0;
|
||||
let latestInternalId;
|
||||
@ -686,11 +706,14 @@ export class MainMenuState extends GameState {
|
||||
});
|
||||
|
||||
const savegame = this.app.savegameMgr.getSavegameById(latestInternalId);
|
||||
savegame.readAsync().then(() => {
|
||||
this.moveToState("InGameState", {
|
||||
savegame,
|
||||
savegame
|
||||
.readAsync()
|
||||
.then(() => this.app.adProvider.showVideoAd())
|
||||
.then(() => {
|
||||
this.moveToState("InGameState", {
|
||||
savegame,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
onLeave() {
|
||||
|
||||
@ -81,9 +81,11 @@ export class PreloadState extends GameState {
|
||||
} catch (ex) {
|
||||
logger.error("Failed to read/write local storage:", ex);
|
||||
return new Promise(() => {
|
||||
alert(`Your brower does not support thirdparty cookies or you have disabled it in your security settings.\n\n
|
||||
In Chrome this setting is called "Block third-party cookies and site data".\n\n
|
||||
Please allow third party cookies and then reload the page.`);
|
||||
alert(
|
||||
"Your brower does not support thirdparty cookies or you have disabled it in your security settings.\n\n" +
|
||||
"In Chrome this setting is called 'Block third-party cookies and site data'.\n\n" +
|
||||
"Please allow third party cookies and then reload the page."
|
||||
);
|
||||
// Never return
|
||||
});
|
||||
}
|
||||
|
||||
@ -13,17 +13,30 @@ const navigation = {
|
||||
categories: ["official", "top-rated", "trending", "trending-weekly", "new"],
|
||||
difficulties: ["easy", "medium", "hard"],
|
||||
account: ["mine", "completed"],
|
||||
search: ["search"],
|
||||
};
|
||||
|
||||
const logger = createLogger("puzzle-menu");
|
||||
|
||||
let lastCategory = "official";
|
||||
|
||||
let lastSearchOptions = {
|
||||
searchTerm: "",
|
||||
difficulty: "any",
|
||||
duration: "any",
|
||||
includeCompleted: false,
|
||||
};
|
||||
|
||||
export class PuzzleMenuState extends TextualGameState {
|
||||
constructor() {
|
||||
super("PuzzleMenuState");
|
||||
this.loading = false;
|
||||
this.activeCategory = "";
|
||||
|
||||
/**
|
||||
* @type {Array<import("../savegame/savegame_typedefs").PuzzleMetadata>}
|
||||
*/
|
||||
this.puzzles = [];
|
||||
}
|
||||
|
||||
getThemeMusic() {
|
||||
@ -99,13 +112,23 @@ export class PuzzleMenuState extends TextualGameState {
|
||||
activeCategory.classList.remove("active");
|
||||
}
|
||||
|
||||
this.htmlElement.querySelector(`[data-category="${category}"]`).classList.add("active");
|
||||
const categoryElement = this.htmlElement.querySelector(`[data-category="${category}"]`);
|
||||
if (categoryElement) {
|
||||
categoryElement.classList.add("active");
|
||||
}
|
||||
|
||||
const container = this.htmlElement.querySelector("#mainContainer");
|
||||
while (container.firstChild) {
|
||||
container.removeChild(container.firstChild);
|
||||
}
|
||||
|
||||
if (category === "search") {
|
||||
this.loading = false;
|
||||
|
||||
this.startSearch();
|
||||
return;
|
||||
}
|
||||
|
||||
const loadingElement = document.createElement("div");
|
||||
loadingElement.classList.add("loader");
|
||||
loadingElement.innerText = T.global.loading + "...";
|
||||
@ -160,23 +183,148 @@ export class PuzzleMenuState extends TextualGameState {
|
||||
}
|
||||
|
||||
const children = navigation[rootCategory];
|
||||
for (const category of children) {
|
||||
const button = document.createElement("button");
|
||||
button.setAttribute("data-category", category);
|
||||
button.classList.add("styledButton", "category", "child");
|
||||
button.innerText = T.puzzleMenu.categories[category];
|
||||
this.trackClicks(button, () => this.selectCategory(category));
|
||||
subContainer.appendChild(button);
|
||||
if (children.length > 1) {
|
||||
for (const category of children) {
|
||||
const button = document.createElement("button");
|
||||
button.setAttribute("data-category", category);
|
||||
button.classList.add("styledButton", "category", "child");
|
||||
button.innerText = T.puzzleMenu.categories[category];
|
||||
this.trackClicks(button, () => this.selectCategory(category));
|
||||
subContainer.appendChild(button);
|
||||
}
|
||||
}
|
||||
|
||||
if (rootCategory === "search") {
|
||||
this.renderSearchForm(subContainer);
|
||||
}
|
||||
|
||||
this.selectCategory(subCategory);
|
||||
}
|
||||
|
||||
renderSearchForm(parent) {
|
||||
const container = document.createElement("form");
|
||||
container.classList.add("searchForm");
|
||||
|
||||
// Search
|
||||
const searchField = document.createElement("input");
|
||||
searchField.value = lastSearchOptions.searchTerm;
|
||||
searchField.classList.add("search");
|
||||
searchField.setAttribute("type", "text");
|
||||
searchField.setAttribute("placeholder", T.puzzleMenu.search.placeholder);
|
||||
searchField.addEventListener("input", () => {
|
||||
lastSearchOptions.searchTerm = searchField.value.trim();
|
||||
});
|
||||
container.appendChild(searchField);
|
||||
|
||||
// Difficulty
|
||||
const difficultyFilter = document.createElement("select");
|
||||
for (const difficulty of ["any", "easy", "medium", "hard"]) {
|
||||
const option = document.createElement("option");
|
||||
option.value = difficulty;
|
||||
option.innerText = T.puzzleMenu.search.difficulties[difficulty];
|
||||
if (option.value === lastSearchOptions.difficulty) {
|
||||
option.setAttribute("selected", "selected");
|
||||
}
|
||||
difficultyFilter.appendChild(option);
|
||||
}
|
||||
difficultyFilter.addEventListener("change", () => {
|
||||
const option = difficultyFilter.value;
|
||||
lastSearchOptions.difficulty = option;
|
||||
});
|
||||
container.appendChild(difficultyFilter);
|
||||
|
||||
// Duration
|
||||
const durationFilter = document.createElement("select");
|
||||
for (const duration of ["any", "short", "medium", "long"]) {
|
||||
const option = document.createElement("option");
|
||||
option.value = duration;
|
||||
option.innerText = T.puzzleMenu.search.durations[duration];
|
||||
if (option.value === lastSearchOptions.duration) {
|
||||
option.setAttribute("selected", "selected");
|
||||
}
|
||||
durationFilter.appendChild(option);
|
||||
}
|
||||
durationFilter.addEventListener("change", () => {
|
||||
const option = durationFilter.value;
|
||||
lastSearchOptions.duration = option;
|
||||
});
|
||||
container.appendChild(durationFilter);
|
||||
|
||||
// Include completed
|
||||
const labelCompleted = document.createElement("label");
|
||||
labelCompleted.classList.add("filterCompleted");
|
||||
|
||||
const inputCompleted = document.createElement("input");
|
||||
inputCompleted.setAttribute("type", "checkbox");
|
||||
if (lastSearchOptions.includeCompleted) {
|
||||
inputCompleted.setAttribute("checked", "checked");
|
||||
}
|
||||
inputCompleted.addEventListener("change", () => {
|
||||
lastSearchOptions.includeCompleted = inputCompleted.checked;
|
||||
});
|
||||
|
||||
labelCompleted.appendChild(inputCompleted);
|
||||
|
||||
const text = document.createTextNode(T.puzzleMenu.search.includeCompleted);
|
||||
labelCompleted.appendChild(text);
|
||||
|
||||
container.appendChild(labelCompleted);
|
||||
|
||||
// Submit
|
||||
const submitButton = document.createElement("button");
|
||||
submitButton.classList.add("styledButton");
|
||||
submitButton.setAttribute("type", "submit");
|
||||
submitButton.innerText = T.puzzleMenu.search.action;
|
||||
container.appendChild(submitButton);
|
||||
|
||||
container.addEventListener("submit", event => {
|
||||
event.preventDefault();
|
||||
console.log("Search:", searchField.value.trim());
|
||||
this.startSearch();
|
||||
});
|
||||
|
||||
parent.appendChild(container);
|
||||
}
|
||||
|
||||
startSearch() {
|
||||
if (this.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
|
||||
const container = this.htmlElement.querySelector("#mainContainer");
|
||||
while (container.firstChild) {
|
||||
container.removeChild(container.firstChild);
|
||||
}
|
||||
|
||||
const loadingElement = document.createElement("div");
|
||||
loadingElement.classList.add("loader");
|
||||
loadingElement.innerText = T.global.loading + "...";
|
||||
container.appendChild(loadingElement);
|
||||
|
||||
this.asyncChannel
|
||||
.watch(this.app.clientApi.apiSearchPuzzles(lastSearchOptions))
|
||||
.then(
|
||||
puzzles => this.renderPuzzles(puzzles),
|
||||
error => {
|
||||
this.dialogs.showWarning(
|
||||
T.dialogs.puzzleLoadFailed.title,
|
||||
T.dialogs.puzzleLoadFailed.desc + " " + error
|
||||
);
|
||||
this.renderPuzzles([]);
|
||||
}
|
||||
)
|
||||
.then(() => (this.loading = false));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import("../savegame/savegame_typedefs").PuzzleMetadata[]} puzzles
|
||||
*/
|
||||
renderPuzzles(puzzles) {
|
||||
this.puzzles = puzzles;
|
||||
|
||||
const container = this.htmlElement.querySelector("#mainContainer");
|
||||
while (container.firstChild) {
|
||||
container.removeChild(container.firstChild);
|
||||
@ -209,10 +357,7 @@ export class PuzzleMenuState extends TextualGameState {
|
||||
stats.classList.add("stats");
|
||||
elem.appendChild(stats);
|
||||
|
||||
if (
|
||||
puzzle.downloads > 3 &&
|
||||
!["official", "easy", "medium", "hard"].includes(this.activeCategory)
|
||||
) {
|
||||
if (!["official", "easy", "medium", "hard"].includes(this.activeCategory)) {
|
||||
const difficulty = document.createElement("div");
|
||||
difficulty.classList.add("difficulty");
|
||||
|
||||
@ -223,15 +368,18 @@ export class PuzzleMenuState extends TextualGameState {
|
||||
difficulty.innerText = completionPercentage + "%";
|
||||
stats.appendChild(difficulty);
|
||||
|
||||
if (completionPercentage < 40) {
|
||||
difficulty.classList.add("stage--hard");
|
||||
difficulty.innerText = T.puzzleMenu.difficulties.hard;
|
||||
} else if (completionPercentage < 80) {
|
||||
difficulty.classList.add("stage--medium");
|
||||
difficulty.innerText = T.puzzleMenu.difficulties.medium;
|
||||
} else {
|
||||
if (puzzle.difficulty === null) {
|
||||
difficulty.classList.add("stage--unknown");
|
||||
difficulty.innerText = T.puzzleMenu.difficulties.unknown;
|
||||
} else if (puzzle.difficulty < 0.2) {
|
||||
difficulty.classList.add("stage--easy");
|
||||
difficulty.innerText = T.puzzleMenu.difficulties.easy;
|
||||
} else if (puzzle.difficulty > 0.6) {
|
||||
difficulty.classList.add("stage--hard");
|
||||
difficulty.innerText = T.puzzleMenu.difficulties.hard;
|
||||
} else {
|
||||
difficulty.classList.add("stage--medium");
|
||||
difficulty.innerText = T.puzzleMenu.difficulties.medium;
|
||||
}
|
||||
}
|
||||
|
||||
@ -275,7 +423,7 @@ export class PuzzleMenuState extends TextualGameState {
|
||||
|
||||
container.appendChild(elem);
|
||||
|
||||
this.trackClicks(elem, () => this.playPuzzle(puzzle));
|
||||
this.trackClicks(elem, () => this.playPuzzle(puzzle.id));
|
||||
}
|
||||
|
||||
if (puzzles.length === 0) {
|
||||
@ -328,20 +476,26 @@ export class PuzzleMenuState extends TextualGameState {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import("../savegame/savegame_typedefs").PuzzleMetadata} puzzle
|
||||
* @param {number} puzzleId
|
||||
* @param {Array<number>=} nextPuzzles
|
||||
*/
|
||||
playPuzzle(puzzle) {
|
||||
playPuzzle(puzzleId, nextPuzzles) {
|
||||
const closeLoading = this.dialogs.showLoadingDialog();
|
||||
|
||||
this.app.clientApi.apiDownloadPuzzle(puzzle.id).then(
|
||||
this.asyncChannel.watch(this.app.clientApi.apiDownloadPuzzle(puzzleId)).then(
|
||||
puzzleData => {
|
||||
closeLoading();
|
||||
logger.log("Got puzzle:", puzzleData);
|
||||
this.startLoadedPuzzle(puzzleData);
|
||||
|
||||
nextPuzzles =
|
||||
nextPuzzles || this.puzzles.filter(puzzle => !puzzle.completed).map(puzzle => puzzle.id);
|
||||
nextPuzzles = nextPuzzles.filter(id => id !== puzzleId);
|
||||
|
||||
logger.log("Got puzzle:", puzzleData, "next puzzles:", nextPuzzles);
|
||||
this.startLoadedPuzzle(puzzleData, nextPuzzles);
|
||||
},
|
||||
err => {
|
||||
closeLoading();
|
||||
logger.error("Failed to download puzzle", puzzle.id, ":", err);
|
||||
logger.error("Failed to download puzzle", puzzleId, ":", err);
|
||||
this.dialogs.showWarning(
|
||||
T.dialogs.puzzleDownloadError.title,
|
||||
T.dialogs.puzzleDownloadError.desc + " " + err
|
||||
@ -353,19 +507,26 @@ export class PuzzleMenuState extends TextualGameState {
|
||||
/**
|
||||
*
|
||||
* @param {import("../savegame/savegame_typedefs").PuzzleFullData} puzzle
|
||||
* @param {Array<number>=} nextPuzzles
|
||||
*/
|
||||
startLoadedPuzzle(puzzle) {
|
||||
const savegame = this.createEmptySavegame();
|
||||
startLoadedPuzzle(puzzle, nextPuzzles) {
|
||||
const savegame = Savegame.createPuzzleSavegame(this.app);
|
||||
this.moveToState("InGameState", {
|
||||
gameModeId: enumGameModeIds.puzzlePlay,
|
||||
gameModeParameters: {
|
||||
puzzle,
|
||||
nextPuzzles,
|
||||
},
|
||||
savegame,
|
||||
});
|
||||
}
|
||||
|
||||
onEnter(payload) {
|
||||
if (payload.continueQueue) {
|
||||
logger.log("Continuing puzzle queue:", payload);
|
||||
this.playPuzzle(payload.continueQueue[0], payload.continueQueue.slice(1));
|
||||
}
|
||||
|
||||
// Find old category
|
||||
let rootCategory = "categories";
|
||||
for (const [id, children] of Object.entries(navigation)) {
|
||||
@ -390,26 +551,13 @@ export class PuzzleMenuState extends TextualGameState {
|
||||
this.trackClicks(this.htmlElement.querySelector("button.loadPuzzle"), () => this.loadPuzzle());
|
||||
}
|
||||
|
||||
createEmptySavegame() {
|
||||
return new Savegame(this.app, {
|
||||
internalId: "puzzle",
|
||||
metaDataRef: {
|
||||
internalId: "puzzle",
|
||||
lastUpdate: 0,
|
||||
version: 0,
|
||||
level: 0,
|
||||
name: "puzzle",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
loadPuzzle() {
|
||||
const shortKeyInput = new FormElementInput({
|
||||
id: "shortKey",
|
||||
label: null,
|
||||
placeholder: "",
|
||||
defaultValue: "",
|
||||
validator: val => ShapeDefinition.isValidShortKey(val),
|
||||
validator: val => ShapeDefinition.isValidShortKey(val) || val.startsWith("/"),
|
||||
});
|
||||
|
||||
const dialog = new DialogWithForm({
|
||||
@ -422,9 +570,16 @@ export class PuzzleMenuState extends TextualGameState {
|
||||
this.dialogs.internalShowDialog(dialog);
|
||||
|
||||
dialog.buttonSignals.ok.add(() => {
|
||||
const searchTerm = shortKeyInput.getValue();
|
||||
|
||||
if (searchTerm === "/apikey") {
|
||||
alert("Your api key is: " + this.app.clientApi.token);
|
||||
return;
|
||||
}
|
||||
|
||||
const closeLoading = this.dialogs.showLoadingDialog();
|
||||
|
||||
this.app.clientApi.apiDownloadPuzzleByKey(shortKeyInput.getValue()).then(
|
||||
this.app.clientApi.apiDownloadPuzzleByKey(searchTerm).then(
|
||||
puzzle => {
|
||||
closeLoading();
|
||||
this.startLoadedPuzzle(puzzle);
|
||||
@ -451,7 +606,7 @@ export class PuzzleMenuState extends TextualGameState {
|
||||
return;
|
||||
}
|
||||
|
||||
const savegame = this.createEmptySavegame();
|
||||
const savegame = Savegame.createPuzzleSavegame(this.app);
|
||||
this.moveToState("InGameState", {
|
||||
gameModeId: enumGameModeIds.puzzleEdit,
|
||||
savegame,
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { THIRDPARTY_URLS } from "../core/config";
|
||||
import { TextualGameState } from "../core/textual_game_state";
|
||||
import { formatSecondsToTimeAgo } from "../core/utils";
|
||||
import { allApplicationSettings, enumCategories } from "../profile/application_settings";
|
||||
@ -34,6 +35,8 @@ export class SettingsState extends TextualGameState {
|
||||
? ""
|
||||
: `
|
||||
<button class="styledButton about">${T.about.title}</button>
|
||||
<button class="styledButton privacy">Privacy Policy</button>
|
||||
|
||||
`
|
||||
}
|
||||
<div class="versionbar">
|
||||
@ -109,6 +112,9 @@ export class SettingsState extends TextualGameState {
|
||||
this.trackClicks(this.htmlElement.querySelector(".about"), this.onAboutClicked, {
|
||||
preventDefault: false,
|
||||
});
|
||||
this.trackClicks(this.htmlElement.querySelector(".privacy"), this.onPrivacyClicked, {
|
||||
preventDefault: false,
|
||||
});
|
||||
}
|
||||
|
||||
const keybindingsButton = this.htmlElement.querySelector(".editKeybindings");
|
||||
@ -180,6 +186,10 @@ export class SettingsState extends TextualGameState {
|
||||
this.moveToStateAddGoBack("AboutState");
|
||||
}
|
||||
|
||||
onPrivacyClicked() {
|
||||
this.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.privacyPolicy);
|
||||
}
|
||||
|
||||
onKeybindingsClicked() {
|
||||
this.moveToStateAddGoBack("KeybindingsState");
|
||||
}
|
||||
|
||||
27
src/js/states/wegame_splash.js
Normal file
@ -0,0 +1,27 @@
|
||||
import { GameState } from "../core/game_state";
|
||||
|
||||
export class WegameSplashState extends GameState {
|
||||
constructor() {
|
||||
super("WegameSplashState");
|
||||
}
|
||||
|
||||
getInnerHTML() {
|
||||
return `
|
||||
<div class="wrapper">
|
||||
<strong>健康游戏忠告</strong>
|
||||
<div>抵制不良游戏,拒绝盗版游戏。</div>
|
||||
<div>注意自我保护,谨防受骗上当。</div>
|
||||
<div>适度游戏益脑,沉迷游戏伤身。</div>
|
||||
<div>合理安排时间,享受健康生活。</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
onEnter() {
|
||||
setTimeout(
|
||||
() => {
|
||||
this.app.stateMgr.moveToState("PreloadState");
|
||||
},
|
||||
G_IS_DEV ? 1 : 6000
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -456,6 +456,7 @@ ingame:
|
||||
titleRatingDesc: Your rating will help me to make you better suggestions in the future
|
||||
continueBtn: Keep Playing
|
||||
menuBtn: Menu
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Author
|
||||
shortKey: Short Key
|
||||
@ -1003,7 +1004,12 @@ settings:
|
||||
title: Map Resources Size
|
||||
description: Controls the size of the shapes on the map overview (when zooming
|
||||
out).
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
rangeSliderPercentage: <amount> %
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: Keybindings
|
||||
hint: "Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different
|
||||
@ -1085,6 +1091,7 @@ keybindings:
|
||||
goal_acceptor: Goal Acceptor
|
||||
block: Block
|
||||
massSelectClear: Clear belts
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: About this Game
|
||||
body: >-
|
||||
@ -1212,8 +1219,23 @@ puzzleMenu:
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
unknown: Unrated
|
||||
dlcHint: Purchased the DLC already? Make sure it is activated by right clicking
|
||||
shapez.io in your library, selecting Properties > DLCs.
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: You are performing your actions too frequent. Please wait a bit.
|
||||
invalid-api-key: Failed to communicate with the backend, please try to
|
||||
|
||||
@ -466,6 +466,7 @@ ingame:
|
||||
titleRatingDesc: Your rating will help me to make you better suggestions in the future
|
||||
continueBtn: Keep Playing
|
||||
menuBtn: Menu
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Author
|
||||
shortKey: Short Key
|
||||
@ -1030,7 +1031,12 @@ settings:
|
||||
title: Map Resources Size
|
||||
description: Controls the size of the shapes on the map overview (when zooming
|
||||
out).
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
rangeSliderPercentage: <amount> %
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: Combinacions de tecles
|
||||
hint: "Tip: Assegura't d'emprar CTRL, SHIFT i ALT! Et permeten col·locar
|
||||
@ -1112,6 +1118,7 @@ keybindings:
|
||||
goal_acceptor: Goal Acceptor
|
||||
block: Block
|
||||
massSelectClear: Clear belts
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: Sobre aquest Joc
|
||||
body: >-
|
||||
@ -1254,8 +1261,23 @@ puzzleMenu:
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
unknown: Unrated
|
||||
dlcHint: Purchased the DLC already? Make sure it is activated by right clicking
|
||||
shapez.io in your library, selecting Properties > DLCs.
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: You are performing your actions too frequent. Please wait a bit.
|
||||
invalid-api-key: Failed to communicate with the backend, please try to
|
||||
|
||||
@ -457,6 +457,7 @@ ingame:
|
||||
titleRatingDesc: Vaše hodnocení nám pomůže podat vám v budoucnu lepší návrhy
|
||||
continueBtn: Hrát dál
|
||||
menuBtn: Menu
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Autor
|
||||
shortKey: Krátký klíč
|
||||
@ -994,7 +995,12 @@ settings:
|
||||
mapResourcesScale:
|
||||
title: Velikost zdrojů na mapě
|
||||
description: Určuje velikost ikon tvarů na náhledu mapy (při oddálení).
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
rangeSliderPercentage: <amount> %
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: Klávesové zkratky
|
||||
hint: "Tip: Nezapomeňte používat CTRL, SHIFT a ALT! Díky nim můžete měnit způsob
|
||||
@ -1076,6 +1082,7 @@ keybindings:
|
||||
goal_acceptor: Přijemce cílů
|
||||
block: Blok
|
||||
massSelectClear: Vymazat pásy
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: O hře
|
||||
body: >-
|
||||
@ -1213,8 +1220,24 @@ puzzleMenu:
|
||||
easy: Lehká
|
||||
medium: Střední
|
||||
hard: Těžká
|
||||
unknown: Unrated
|
||||
dlcHint: Již jste toto DLC zakoupili? Ujistěte se, že je aktivováno kliknutím
|
||||
pravého tlačítka na shapez.io ve své knihovně, vybráním Vlastnosti > DLC.
|
||||
pravého tlačítka na shapez.io ve své knihovně, vybráním Vlastnosti >
|
||||
DLC.
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: Provádíte své akce příliš často. Počkejte prosím.
|
||||
invalid-api-key: Komunikace s back-endem se nezdařila, prosím zkuste
|
||||
|
||||
@ -22,7 +22,6 @@ steamPage:
|
||||
steam_review_comment: This game has stolen my life and I don't want it back.
|
||||
Very chill factory game that won't let me stop making my lines more
|
||||
efficient.
|
||||
|
||||
global:
|
||||
loading: Laden
|
||||
error: Fehler
|
||||
@ -55,7 +54,6 @@ global:
|
||||
escape: ESC
|
||||
shift: UMSCH
|
||||
space: LEER
|
||||
|
||||
demoBanners:
|
||||
title: Demoversion
|
||||
intro: Kauf die Vollversion für alle Features!
|
||||
@ -71,7 +69,8 @@ mainMenu:
|
||||
helpTranslate: Hilf beim Übersetzen!
|
||||
madeBy: Ein Spiel von <author-link>
|
||||
browserWarning: Sorry, aber das Spiel wird in deinem Browser langsamer laufen!
|
||||
Kaufe die Vollversion oder verwende Google Chrome für die beste Erfahrung.
|
||||
Kaufe die Vollversion oder verwende Google Chrome für die beste
|
||||
Erfahrung.
|
||||
savegameLevel: Level <x>
|
||||
savegameLevelUnknown: Unbekanntes Level
|
||||
savegameUnnamed: Unbenannt
|
||||
@ -81,7 +80,6 @@ mainMenu:
|
||||
zu machen? Hol dir das Puzzle-DLC auf Steam für noch mehr Spaß!
|
||||
puzzleDlcWishlist: Jetzt zur Wunschliste hinzufügen!
|
||||
puzzleDlcViewNow: DLC anzeigen
|
||||
|
||||
puzzleMenu:
|
||||
play: Spielen
|
||||
edit: Bearbeiten
|
||||
@ -92,9 +90,9 @@ puzzleMenu:
|
||||
validatingPuzzle: Puzzle wird überprüft
|
||||
submittingPuzzle: Puzzle wird veröffentlicht
|
||||
noPuzzles: Hier gibt es bisher noch keine Puzzles.
|
||||
dlcHint: DLC schon gekauft? Stelle sicher, dass es aktiviert ist, indem du in der Steam-Bibliothek
|
||||
shapez.io rechtsklickst und es unter Eigenschaften > Zusatzinhalte (DLC) aktivierst.
|
||||
|
||||
dlcHint: DLC schon gekauft? Stelle sicher, dass es aktiviert ist, indem du in
|
||||
der Steam-Bibliothek shapez.io rechtsklickst und es unter Eigenschaften
|
||||
> Zusatzinhalte (DLC) aktivierst.
|
||||
categories:
|
||||
levels: Levels
|
||||
new: Neu
|
||||
@ -111,26 +109,38 @@ puzzleMenu:
|
||||
difficulties: Nach Schwierigkeit
|
||||
account: Meine Puzzles
|
||||
search: Suche
|
||||
|
||||
difficulties:
|
||||
easy: Einfach
|
||||
medium: Mittel
|
||||
hard: Schwer
|
||||
|
||||
unknown: Unrated
|
||||
validation:
|
||||
title: Ungültiges Puzzle
|
||||
noProducers: Bitte platziere einen Itemproduzent!
|
||||
noGoalAcceptors: Bitte platziere einen Zielakzeptor!
|
||||
goalAcceptorNoItem: Ein oder mehrere Zielakzeptoren haben noch kein
|
||||
zugewiesenes Item. Beliefere sie mit einer Form, um ein Ziel zu
|
||||
setzen.
|
||||
goalAcceptorRateNotMet: Ein oder mehrere Zielakzeptoren bekommen nicht
|
||||
genügend Items. Stelle sicher, dass alle ihre Indikatoren grün leuchten.
|
||||
goalAcceptorNoItem: Ein oder mehrere Zielakzeptoren haben noch kein zugewiesenes
|
||||
Item. Beliefere sie mit einer Form, um ein Ziel zu setzen.
|
||||
goalAcceptorRateNotMet: Ein oder mehrere Zielakzeptoren bekommen nicht genügend
|
||||
Items. Stelle sicher, dass alle ihre Indikatoren grün leuchten.
|
||||
buildingOutOfBounds: Ein oder mehrere Gebäude befinden sich außerhalb des
|
||||
bebaubaren Bereichs. Vergrößere den Bereich oder entferne die Gebäude.
|
||||
bebaubaren Bereichs. Vergrößere den Bereich oder entferne die
|
||||
Gebäude.
|
||||
autoComplete: Dein Puzzle schließt sich selbst ab! Bitte stelle sicher, dass
|
||||
deine Itemproduzenten nicht direkt an deine Zielakzeptoren liefern.
|
||||
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
dialogs:
|
||||
buttons:
|
||||
ok: OK
|
||||
@ -190,9 +200,10 @@ dialogs:
|
||||
desc: "Hier sind die Änderungen, seitdem du das letzte Mal gespielt hast:"
|
||||
upgradesIntroduction:
|
||||
title: Upgrades freischalten
|
||||
desc: Viele deiner Formen können noch benutzt werden, um Upgrades freizuschalten, also
|
||||
<strong>zerstöre deine alten Fabriken nicht!</strong> Den
|
||||
Upgrade-Tab findest du oben rechts im Bildschirm.
|
||||
desc: Viele deiner Formen können noch benutzt werden, um Upgrades
|
||||
freizuschalten, also <strong>zerstöre deine alten Fabriken
|
||||
nicht!</strong> Den Upgrade-Tab findest du oben rechts im
|
||||
Bildschirm.
|
||||
massDeleteConfirm:
|
||||
title: Löschen bestätigen
|
||||
desc: Du löscht viele Gebäude (<count> um genau zu sein)! Bist du dir sicher?
|
||||
@ -212,7 +223,8 @@ dialogs:
|
||||
desc: >-
|
||||
Dieses Spiel hat viele Hotkeys, die den Bau von Fabriken
|
||||
vereinfachen und beschleunigen. Hier sind ein paar Beispiele, aber
|
||||
prüfe am besten die <strong>Tastenbelegung</strong> in den Einstellungen!<br><br>
|
||||
prüfe am besten die <strong>Tastenbelegung</strong> in den
|
||||
Einstellungen!<br><br>
|
||||
<code class='keybinding'>STRG</code> + Ziehen: Wähle Bereich aus.<br>
|
||||
<code class='keybinding'>UMSCH</code>: Halten, um mehrere Gebäude zu platzieren.<br>
|
||||
<code class='keybinding'>ALT</code>: Invertiere die Platzierungsrichtung der Fließbänder.<br>
|
||||
@ -220,16 +232,18 @@ dialogs:
|
||||
title: Neue Markierung
|
||||
titleEdit: Markierung bearbeiten
|
||||
desc: Gib ihm einen griffigen Namen. Du kannst auch den
|
||||
<strong>Kurzschlüssel</strong> einer Form eingeben (<link>Hier</link> geht es zum Generator).
|
||||
<strong>Kurzschlüssel</strong> einer Form eingeben
|
||||
(<link>Hier</link> geht es zum Generator).
|
||||
editSignal:
|
||||
title: Signal setzen
|
||||
descItems: "Wähle ein vordefiniertes Item:"
|
||||
descShortKey: ... oder gib den <strong>Kurzschlüssel</strong> einer Form an (<link>Hier</link> geht es zum Generator).
|
||||
descShortKey: ... oder gib den <strong>Kurzschlüssel</strong> einer Form an
|
||||
(<link>Hier</link> geht es zum Generator).
|
||||
editConstantProducer:
|
||||
title: Item wählen
|
||||
markerDemoLimit:
|
||||
desc: Du kannst nur 2 Markierungen in der Demo benutzen. Hole dir die Vollversion, um
|
||||
unbegrenzt viele Markierungen zu setzen!
|
||||
desc: Du kannst nur 2 Markierungen in der Demo benutzen. Hole dir die
|
||||
Vollversion, um unbegrenzt viele Markierungen zu setzen!
|
||||
exportScreenshotWarning:
|
||||
title: Bildschirmfoto exportieren
|
||||
desc: Hier kannst du ein Bildschirmfoto von deiner ganzen Fabrik erstellen. Für
|
||||
@ -240,7 +254,8 @@ dialogs:
|
||||
desc: Hier kannst du deinen Speicherstand umbenennen.
|
||||
tutorialVideoAvailable:
|
||||
title: Tutorial verfügbar
|
||||
desc: Für dieses Level ist ein Anleitungsvideo verfügbar. Willst du es anschauen?
|
||||
desc: Für dieses Level ist ein Anleitungsvideo verfügbar. Willst du es
|
||||
anschauen?
|
||||
tutorialVideoAvailableForeignLanguage:
|
||||
title: Tutorial verfügbar
|
||||
desc: Für dieses Level ist ein Anleitungsvideo verfügbar, allerdings nur auf
|
||||
@ -264,8 +279,9 @@ dialogs:
|
||||
desc: "Das Puzzle konnte nicht geladen werden:"
|
||||
offlineMode:
|
||||
title: Offlinemodus
|
||||
desc: Die Server konnten nicht erreicht werden, daher läuft das Spiel im Offlinemodus.
|
||||
Bitte stelle sicher, dass du eine aktive Internetverbindung hast.
|
||||
desc: Die Server konnten nicht erreicht werden, daher läuft das Spiel im
|
||||
Offlinemodus. Bitte stelle sicher, dass du eine aktive
|
||||
Internetverbindung hast.
|
||||
puzzleDownloadError:
|
||||
title: Downloadfehler
|
||||
desc: "Der Download des Puzzles ist fehlgeschlagen:"
|
||||
@ -275,17 +291,17 @@ dialogs:
|
||||
puzzleSubmitOk:
|
||||
title: Puzzle veröffentlicht
|
||||
desc: Herzlichen Glückwunsch! Dein Puzzle wurde veröffentlicht und kann nun von
|
||||
anderen gespielt werden. Du kannst es jetzt im Bereich "Meine Puzzles" finden.
|
||||
anderen gespielt werden. Du kannst es jetzt im Bereich "Meine
|
||||
Puzzles" finden.
|
||||
puzzleCreateOffline:
|
||||
title: Offlinemodus
|
||||
desc: Da du offline bist, kannst du dein Puzzle nicht speichern
|
||||
und/oder veröffentlichen. Möchtest du trotzdem fortfahren?
|
||||
desc: Da du offline bist, kannst du dein Puzzle nicht speichern und/oder
|
||||
veröffentlichen. Möchtest du trotzdem fortfahren?
|
||||
puzzlePlayRegularRecommendation:
|
||||
title: Empfehlung
|
||||
desc: Ich empfehle dir <strong>sehr</strong>, bis Level 12 zu
|
||||
spielen, bevor du dich an das Puzzle-DLC wagst. Du stößt sonst
|
||||
möglicherweise auf dir noch nicht bekannte Mechaniken. Möchtest du
|
||||
trotzdem fortfahren?
|
||||
desc: Ich empfehle dir <strong>sehr</strong>, bis Level 12 zu spielen, bevor du
|
||||
dich an das Puzzle-DLC wagst. Du stößt sonst möglicherweise auf dir
|
||||
noch nicht bekannte Mechaniken. Möchtest du trotzdem fortfahren?
|
||||
puzzleShare:
|
||||
title: Kurzschlüssel kopiert
|
||||
desc: Der Kurzschlüssel des Puzzles (<key>) wurde in die Zwischenablage kopiert!
|
||||
@ -309,7 +325,6 @@ dialogs:
|
||||
title: Puzzle löschen?
|
||||
desc: Bist du sicher, dass du '<title>' löschen möchtest? Dies kann nicht
|
||||
rückgängig gemacht werden!
|
||||
|
||||
ingame:
|
||||
keybindingsOverlay:
|
||||
moveMap: Bewegen
|
||||
@ -397,9 +412,9 @@ ingame:
|
||||
waypoints:
|
||||
waypoints: Markierungen
|
||||
hub: Hub
|
||||
description: Linksklick auf eine Markierung, um dort hinzugelangen. Rechtsklick, um
|
||||
sie zu löschen.<br><br>Drücke <keybinding>, um eine Markierung aus
|
||||
deinem Blickwinkel, oder <strong>rechtsklicke</strong>, um eine
|
||||
description: Linksklick auf eine Markierung, um dort hinzugelangen. Rechtsklick,
|
||||
um sie zu löschen.<br><br>Drücke <keybinding>, um eine Markierung
|
||||
aus deinem Blickwinkel, oder <strong>rechtsklicke</strong>, um eine
|
||||
Markierung auf der ausgewählten Position zu erschaffen.
|
||||
creationSuccessNotification: Markierung wurde erstellt.
|
||||
shapeViewer:
|
||||
@ -419,15 +434,16 @@ ingame:
|
||||
Halte <strong>UMSCH</strong>, um mehrere Gebäude zu platzieren
|
||||
und nutze <strong>R</strong>, um sie zu rotieren."
|
||||
2_1_place_cutter: "Platziere nun einen <strong>Schneider</strong>, um die Kreise
|
||||
zu halbieren.<br><br> Übrigens: Der Schneider
|
||||
teilt Items immer von <strong>oben nach unten</strong>, unabhängig von
|
||||
seiner Orientierung!"
|
||||
zu halbieren.<br><br> Übrigens: Der Schneider teilt Items immer
|
||||
von <strong>oben nach unten</strong>, unabhängig von seiner
|
||||
Orientierung!"
|
||||
2_2_place_trash: Der Schneider kann <strong>verstopfen</strong>!<br><br>Benutze
|
||||
einen <strong>Mülleimer</strong> um den aktuell (!) nicht
|
||||
benötigten Rest loszuwerden.
|
||||
2_3_more_cutters: "Gut gemacht! Platziere noch <strong>zwei andere Schneider</strong>
|
||||
um das Ganze zu beschleunigen.<br><br> Übrigens: Benutze die
|
||||
<strong>Hotkeys 0-9</strong> um Gebäude schneller auszuwählen!"
|
||||
2_3_more_cutters: "Gut gemacht! Platziere noch <strong>zwei andere
|
||||
Schneider</strong> um das Ganze zu beschleunigen.<br><br>
|
||||
Übrigens: Benutze die <strong>Hotkeys 0-9</strong> um Gebäude
|
||||
schneller auszuwählen!"
|
||||
3_1_rectangles: "Lass uns ein paar Quadrate extrahieren! <strong>Baue vier
|
||||
Extraktoren</strong> und verbinde sie mit deinem Hub.<br><br>
|
||||
PS: Halte <strong>SHIFT</strong>, während du ein Fließband
|
||||
@ -441,8 +457,9 @@ ingame:
|
||||
21_3_place_button: Perfekt! Platziere jetzt einen <strong>Schalter</strong> und
|
||||
verbinde ihn mit Signalkabeln.
|
||||
21_4_press_button: "Drücke den Schalter, damit er ein <strong>wahres
|
||||
Signal</strong> ausgibt und den Färber aktiviert.<br><br>
|
||||
PS: Du musst nicht alle Eingänge verbinden! Probiere es auch mal mit zwei."
|
||||
Signal</strong> ausgibt und den Färber aktiviert.<br><br> PS: Du
|
||||
musst nicht alle Eingänge verbinden! Probiere es auch mal mit
|
||||
zwei."
|
||||
connectedMiners:
|
||||
one_miner: Ein Extraktor
|
||||
n_miners: <amount> Extraktoren
|
||||
@ -492,12 +509,21 @@ ingame:
|
||||
puzzleEditorControls:
|
||||
title: Puzzle-Editor
|
||||
instructions:
|
||||
- 1. Platziere einen <strong>Itemproduzenten</strong> um Formen und Farben für den Spieler bereitzustellen
|
||||
- 2. Produziere eine oder mehrere Formen, die der Spieler herstellen soll und liefere diese zu einem oder mehreren <strong>Zielakzeptoren</strong>
|
||||
- 3. Sobald ein Zielakzeptor eine Form für eine gewisse Zeit erhält, <strong>speichert dieser sie als Ziel</strong> (Angezeigt durch den <strong>grünen Punkt</strong>).
|
||||
- 4. Klicke auf das <strong>Schloss</strong>, um ein Gebäude für den Spieler zu sperren.
|
||||
- 5. Sobald du auf Überprüfen gedrückt hast, wird dein Puzzle `validiert und du kannst es veröffentlichen.
|
||||
- 6. Bei der Freigabe werden <strong>alle Gebäude entfernt</strong>. Ausgenommen sind die Produzenten und Akzeptoren. Den Rest soll der Spieler schließlich selbst herausfinden :)
|
||||
- 1. Platziere einen <strong>Itemproduzenten</strong> um Formen und
|
||||
Farben für den Spieler bereitzustellen
|
||||
- 2. Produziere eine oder mehrere Formen, die der Spieler herstellen
|
||||
soll und liefere diese zu einem oder mehreren
|
||||
<strong>Zielakzeptoren</strong>
|
||||
- 3. Sobald ein Zielakzeptor eine Form für eine gewisse Zeit erhält,
|
||||
<strong>speichert dieser sie als Ziel</strong> (Angezeigt durch
|
||||
den <strong>grünen Punkt</strong>).
|
||||
- 4. Klicke auf das <strong>Schloss</strong>, um ein Gebäude für den
|
||||
Spieler zu sperren.
|
||||
- 5. Sobald du auf Überprüfen gedrückt hast, wird dein Puzzle
|
||||
`validiert und du kannst es veröffentlichen.
|
||||
- 6. Bei der Freigabe werden <strong>alle Gebäude entfernt</strong>.
|
||||
Ausgenommen sind die Produzenten und Akzeptoren. Den Rest soll der
|
||||
Spieler schließlich selbst herausfinden :)
|
||||
puzzleCompletion:
|
||||
title: Puzzle geschafft!
|
||||
titleLike: "Klicke auf das Herz, wenn dir das Puzzle gefallen hat:"
|
||||
@ -505,13 +531,13 @@ ingame:
|
||||
titleRatingDesc: Deine Bewertung hilft mir, in Zukunft bessere Vorschläge zu machen
|
||||
continueBtn: Weiterspielen
|
||||
menuBtn: Menü
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Ersteller
|
||||
shortKey: Kurzschlüssel
|
||||
rating: Schwierigkeitsgrad
|
||||
averageDuration: Durchschnittliche Dauer
|
||||
completionRate: Abschlussrate
|
||||
|
||||
shopUpgrades:
|
||||
belt:
|
||||
name: Fließbänder, Verteiler & Tunnel
|
||||
@ -525,7 +551,6 @@ shopUpgrades:
|
||||
painting:
|
||||
name: Mischer & Färber
|
||||
description: Geschw. x<currentMult> → x<newMult>
|
||||
|
||||
buildings:
|
||||
hub:
|
||||
deliver: Liefere
|
||||
@ -693,9 +718,9 @@ buildings:
|
||||
reader:
|
||||
default:
|
||||
name: Fließbandkontrolle
|
||||
description: Misst den gemittelten Durchsatz des Fließbandes. Gibt zusätzlich den
|
||||
zuletzt passierten Gegenstand auf der Wires-Ebene aus (sobald
|
||||
freigeschaltet).
|
||||
description: Misst den gemittelten Durchsatz des Fließbandes. Gibt zusätzlich
|
||||
den zuletzt passierten Gegenstand auf der Wires-Ebene aus
|
||||
(sobald freigeschaltet).
|
||||
analyzer:
|
||||
default:
|
||||
name: Formanalyse
|
||||
@ -741,13 +766,15 @@ buildings:
|
||||
default:
|
||||
name: Sperrblock
|
||||
description: Ermöglicht das Blockieren einer Kachel.
|
||||
|
||||
storyRewards:
|
||||
reward_cutter_and_trash:
|
||||
title: Formen zerschneiden
|
||||
desc: Du hast gerade den <strong>Schneider</strong> freigeschaltet, der Formen vertikal halbiert, <b>unabhängig von seiner Orientierung</b>!<br><br>
|
||||
Achte darauf, die Überreste loszuwerden, sonst <b>verstopft und blockiert er</b> - Zu diesem Zweck habe ich
|
||||
dir den <strong>Mülleimer</strong> gegeben. Er entsorgt alles, was du ihm fütterst!
|
||||
desc: Du hast gerade den <strong>Schneider</strong> freigeschaltet, der Formen
|
||||
vertikal halbiert, <b>unabhängig von seiner
|
||||
Orientierung</b>!<br><br> Achte darauf, die Überreste loszuwerden,
|
||||
sonst <b>verstopft und blockiert er</b> - Zu diesem Zweck habe ich
|
||||
dir den <strong>Mülleimer</strong> gegeben. Er entsorgt alles, was
|
||||
du ihm fütterst!
|
||||
reward_rotater:
|
||||
title: Rotieren
|
||||
desc: Der <strong>Rotierer</strong> wurde freigeschaltet! Er rotiert Formen im
|
||||
@ -772,8 +799,8 @@ storyRewards:
|
||||
reward_balancer:
|
||||
title: Verteiler
|
||||
desc: Der multifunktionale <strong>Verteiler</strong> wurde freigeschaltet!
|
||||
Damit kannst du nun endlich größere Fabriken bauen. Er kann Fließbänder
|
||||
<strong>aufteilen oder zusammenlegen</strong>!
|
||||
Damit kannst du nun endlich größere Fabriken bauen. Er kann
|
||||
Fließbänder <strong>aufteilen oder zusammenlegen</strong>!
|
||||
reward_tunnel:
|
||||
title: Tunnel
|
||||
desc: Der <strong>Tunnel</strong> wurde freigeschaltet! Du kannst Items nun
|
||||
@ -787,9 +814,9 @@ storyRewards:
|
||||
reward_miner_chainable:
|
||||
title: Extraktor (Kette)
|
||||
desc: "Du hast den <strong>Kettenextraktor</strong> freigeschaltet! Er kann
|
||||
seine Ressourcen an andere Extraktoren
|
||||
<strong>weitergeben</strong>. <br><br> PS: Der alte Extraktor
|
||||
wurde jetzt in deiner Symbolleiste ersetzt!"
|
||||
seine Ressourcen an andere Extraktoren <strong>weitergeben</strong>.
|
||||
<br><br> PS: Der alte Extraktor wurde jetzt in deiner Symbolleiste
|
||||
ersetzt!"
|
||||
reward_underground_belt_tier_2:
|
||||
title: Tunnel Stufe II
|
||||
desc: Du hast eine neue Variante des <strong>Tunnels</strong> freigeschaltet!
|
||||
@ -848,8 +875,8 @@ storyRewards:
|
||||
<strong>vierfachen Färber</strong>. Schließe die Eingänge, mit denen
|
||||
du die Quadranten färben möchtest, an ein Signalkabel auf der
|
||||
Wires-Ebene an!<br><br> Mit <strong>E</strong> wechselst du zwischen
|
||||
den Ebenen. <br><br>PS: <strong>Aktiviere die Hinweise</strong> in den
|
||||
Einstellungen, um das Tutorial anzuzeigen!"
|
||||
den Ebenen. <br><br>PS: <strong>Aktiviere die Hinweise</strong> in
|
||||
den Einstellungen, um das Tutorial anzuzeigen!"
|
||||
reward_filter:
|
||||
title: Itemfilter
|
||||
desc: Du hast den <strong>Itemfilter</strong> freigeschaltet! Items, die dem
|
||||
@ -910,11 +937,11 @@ storyRewards:
|
||||
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 deine Fabrik dementsprechend konfigurieren (lassen).
|
||||
Wires-Ebene aus, also musst du sie nur analysieren und deine Fabrik
|
||||
dementsprechend konfigurieren (lassen).
|
||||
reward_demo_end:
|
||||
title: Ende der Demo
|
||||
desc: Du bist am Ende der Demo angekommen!
|
||||
|
||||
settings:
|
||||
title: Einstellungen
|
||||
categories:
|
||||
@ -1022,11 +1049,13 @@ settings:
|
||||
title: Intelligente Tunnel
|
||||
description: Aktiviert das automatische Entfernen von überflüssigen Fließbändern
|
||||
bei der Platzierung von Tunneln. Außerdem funktioniert das
|
||||
Ziehen von Tunneln und überschüssige Tunnel werden ebenfalls entfernt.
|
||||
Ziehen von Tunneln und überschüssige Tunnel werden ebenfalls
|
||||
entfernt.
|
||||
vignette:
|
||||
title: Vignette
|
||||
description: Aktiviert den Vignetteneffekt, der den Rand des Bildschirms
|
||||
zunehmend verdunkelt und damit das Lesen der Textfelder vereinfacht.
|
||||
zunehmend verdunkelt und damit das Lesen der Textfelder
|
||||
vereinfacht.
|
||||
rotationByBuilding:
|
||||
title: Rotation pro Gebäudetyp
|
||||
description: Jeder Gebäudetyp merkt sich eigenständig, in welche Richtung er
|
||||
@ -1052,10 +1081,10 @@ settings:
|
||||
Außerdem vereinfacht es die Darstellung!
|
||||
clearCursorOnDeleteWhilePlacing:
|
||||
title: Abwählen mit Rechtsklick
|
||||
description: Ist standardmäßig eingeschaltet und wählt das aktuell
|
||||
ausgewählte Gebäude ab, wenn du die rechte Maustaste drückst.
|
||||
Wenn du es abschaltest, kannst du mit der rechten Maustaste
|
||||
Gebäude löschen, während du im Platzierungsmodus bist.
|
||||
description: Ist standardmäßig eingeschaltet und wählt das aktuell ausgewählte
|
||||
Gebäude ab, wenn du die rechte Maustaste drückst. Wenn du es
|
||||
abschaltest, kannst du mit der rechten Maustaste Gebäude
|
||||
löschen, während du im Platzierungsmodus bist.
|
||||
lowQualityTextures:
|
||||
title: Niedrige Texturqualität (Unschön)
|
||||
description: Das Spiel verwendet eine niedrigere Auflösung bei den Texturen.
|
||||
@ -1067,8 +1096,9 @@ settings:
|
||||
anzeigen.
|
||||
pickMinerOnPatch:
|
||||
title: Automatisch Extraktor auswählen
|
||||
description: Ist standardmäßig eingeschaltet und du wählst automatisch den Extraktor,
|
||||
wenn du mit der Pipette auf einen Ressourcenfleck zeigst.
|
||||
description: Ist standardmäßig eingeschaltet und du wählst automatisch den
|
||||
Extraktor, wenn du mit der Pipette auf einen Ressourcenfleck
|
||||
zeigst.
|
||||
simplifiedBelts:
|
||||
title: Minimalistische Fließbänder (Unschön)
|
||||
description: Zur Verbesserung der Leistung werden die Items auf Fließbändern nur
|
||||
@ -1088,7 +1118,11 @@ settings:
|
||||
title: Größe der Ressourcen auf der Karte
|
||||
description: Legt die Größe der Ressourcen auf der Karte (beim Herauszoomen)
|
||||
fest.
|
||||
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: Tastenbelegung
|
||||
hint: "Tipp: Benutze STRG, UMSCH and ALT! Sie aktivieren verschiedene
|
||||
@ -1170,10 +1204,11 @@ keybindings:
|
||||
placementDisableAutoOrientation: Automatische Orientierung deaktivieren
|
||||
placeMultiple: Im Platzierungsmodus bleiben
|
||||
placeInverse: Automatische Fließbandorientierung invertieren
|
||||
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: Über dieses Spiel
|
||||
body: Dieses Spiel ist quelloffen (Open Source) und wurde von <a href="https://github.com/tobspr" target="_blank">Tobias Springer</a>
|
||||
body: Dieses Spiel ist quelloffen (Open Source) und wurde von <a
|
||||
href="https://github.com/tobspr" target="_blank">Tobias Springer</a>
|
||||
(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> Das Spiel wurde
|
||||
@ -1185,10 +1220,8 @@ about:
|
||||
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.
|
||||
|
||||
changelog:
|
||||
title: Änderungsprotokoll
|
||||
|
||||
demo:
|
||||
features:
|
||||
restoringGames: Spielstände wiederherstellen
|
||||
@ -1197,15 +1230,14 @@ demo:
|
||||
customizeKeybindings: Tastenbelegung anpassen
|
||||
exportingBase: Ganze Fabrik als Foto exportieren
|
||||
settingNotAvailable: Nicht verfügbar in der Demo.
|
||||
|
||||
backendErrors:
|
||||
ratelimit: Du führst deine Aktionen zu schnell aus. Bitte warte kurz.
|
||||
invalid-api-key: Kommunikation mit dem Back-End fehlgeschlagen. Versuche das
|
||||
Spiel neu zu starten oder zu updaten (Ungültiger Api-Schlüssel).
|
||||
unauthorized: Kommunikation mit dem Back-End fehlgeschlagen. Versuche das Spiel
|
||||
neu zu starten oder zu updaten (Nicht autorisiert).
|
||||
bad-token: Kommunikation mit dem Back-End fehlgeschlagen. Versuche das Spiel
|
||||
neu zu starten oder zu updaten (Ungültiger Token).
|
||||
bad-token: Kommunikation mit dem Back-End fehlgeschlagen. Versuche das Spiel neu
|
||||
zu starten oder zu updaten (Ungültiger Token).
|
||||
bad-id: Ungültige Puzzle-ID.
|
||||
not-found: Das Puzzle konnte nicht gefunden werden.
|
||||
bad-category: Die Kategorie konnte nicht gefunden werden.
|
||||
@ -1224,7 +1256,6 @@ backendErrors:
|
||||
too-many-likes-already: Dieses Puzzle ist in der Community sehr beliebt. Wenn du
|
||||
es trotzdem löschen möchtest, wende dich bitte an support@shapez.io!
|
||||
no-permission: Dir fehlt die Berechtigung, um diese Aktion auszuführen.
|
||||
|
||||
tips:
|
||||
- Der Hub akzeptiert alle Formen, nicht nur die aktuell geforderten!
|
||||
- Stelle sicher, dass deine Fabriken modular sind. Es zahlt sich irgendwann
|
||||
@ -1290,7 +1321,8 @@ tips:
|
||||
- Mische alle drei Grundfarben, um Weiß zu erhalten!
|
||||
- Du hast eine unendlich große Karte, nutze den Platz und expandiere!
|
||||
- Probier auch mal Factorio! Es ist mein Lieblingsspiel.
|
||||
- Der vierfache Schneider schneidet im Uhrzeigersinn von oben rechts beginnend!
|
||||
- Der vierfache Schneider schneidet im Uhrzeigersinn von oben rechts
|
||||
beginnend!
|
||||
- Du kannst deine Speicherstände im Hauptmenü herunterladen!
|
||||
- Diese Spiel hat viele nützliche Tastenbelegungen! Schau sie dir in den
|
||||
Einstellungen an.
|
||||
|
||||
@ -475,6 +475,7 @@ ingame:
|
||||
titleRatingDesc: Your rating will help me to make you better suggestions in the future
|
||||
continueBtn: Keep Playing
|
||||
menuBtn: Menu
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Author
|
||||
shortKey: Short Key
|
||||
@ -1038,7 +1039,12 @@ settings:
|
||||
title: Map Resources Size
|
||||
description: Controls the size of the shapes on the map overview (when zooming
|
||||
out).
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
rangeSliderPercentage: <amount> %
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: Συνδιασμοί πλήκτρων
|
||||
hint: "Συμβουλή: Φρόντισε να χρησιμοποιήσεις τα πλήκτρα CTRL, SHIFT και ALT!
|
||||
@ -1120,6 +1126,7 @@ keybindings:
|
||||
goal_acceptor: Goal Acceptor
|
||||
block: Block
|
||||
massSelectClear: Clear belts
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: Σχετικά με αυτό το παιχνίδι
|
||||
body: >-
|
||||
@ -1254,8 +1261,23 @@ puzzleMenu:
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
unknown: Unrated
|
||||
dlcHint: Purchased the DLC already? Make sure it is activated by right clicking
|
||||
shapez.io in your library, selecting Properties > DLCs.
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: You are performing your actions too frequent. Please wait a bit.
|
||||
invalid-api-key: Failed to communicate with the backend, please try to
|
||||
|
||||
@ -155,10 +155,28 @@ puzzleMenu:
|
||||
account: My Puzzles
|
||||
search: Search
|
||||
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
|
||||
difficulties:
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
unknown: Unrated
|
||||
|
||||
validation:
|
||||
title: Invalid Puzzle
|
||||
@ -657,6 +675,7 @@ ingame:
|
||||
|
||||
continueBtn: Keep Playing
|
||||
menuBtn: Menu
|
||||
nextPuzzle: Next Puzzle
|
||||
|
||||
puzzleMetadata:
|
||||
author: Author
|
||||
@ -1080,7 +1099,7 @@ settings:
|
||||
staging: Staging
|
||||
prod: Production
|
||||
buildDate: Built <at-date>
|
||||
|
||||
tickrateHz: <amount> Hz
|
||||
rangeSliderPercentage: <amount> %
|
||||
|
||||
labels:
|
||||
@ -1267,6 +1286,11 @@ settings:
|
||||
description: >-
|
||||
Controls the size of the shapes on the map overview (when zooming out).
|
||||
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: >-
|
||||
Whether to always show the shape tooltip when hovering buildings, instead of having to hold 'ALT'.
|
||||
|
||||
keybindings:
|
||||
title: Keybindings
|
||||
hint: >-
|
||||
@ -1363,6 +1387,8 @@ keybindings:
|
||||
placeMultiple: Stay in placement mode
|
||||
placeInverse: Invert automatic belt orientation
|
||||
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
|
||||
about:
|
||||
title: About this Game
|
||||
body: >-
|
||||
|
||||
@ -25,8 +25,8 @@ steamPage:
|
||||
global:
|
||||
loading: Cargando
|
||||
error: Error
|
||||
thousandsDivider: ","
|
||||
decimalSeparator: .
|
||||
thousandsDivider: .
|
||||
decimalSeparator: ","
|
||||
suffix:
|
||||
thousands: k
|
||||
millions: M
|
||||
@ -78,7 +78,7 @@ mainMenu:
|
||||
puzzleDlcText: ¿Disfrutas compactando y optimizando fábricas? ¡Consigue ahora el
|
||||
DLC de Puzles en Steam para aún más diversión!
|
||||
puzzleDlcWishlist: ¡Añádelo ahora a tu lista de deseos!
|
||||
puzzleDlcViewNow: View Dlc
|
||||
puzzleDlcViewNow: Ver Dlc
|
||||
dialogs:
|
||||
buttons:
|
||||
ok: OK
|
||||
@ -198,7 +198,7 @@ dialogs:
|
||||
desc: Hay un video tutorial disponible para este nivel, pero solo está
|
||||
disponible en inglés ¿Te gustaría verlo?
|
||||
editConstantProducer:
|
||||
title: Set Item
|
||||
title: Elegir item
|
||||
puzzleLoadFailed:
|
||||
title: Fallo al cargar los Puzles
|
||||
desc: Desafortunadamente, no se pudieron cargar los puzles.
|
||||
@ -248,12 +248,12 @@ dialogs:
|
||||
puzzleReport:
|
||||
title: Reportar Puzle
|
||||
options:
|
||||
profane: Lenguaje soez
|
||||
profane: Profanidades
|
||||
unsolvable: Imposible de resolver
|
||||
trolling: Troll
|
||||
puzzleReportComplete:
|
||||
title: ¡Gracias por tu aporte!
|
||||
desc: El puzle ha sido marcado como abuso.
|
||||
desc: El puzle ha sido reportado exitosamente.
|
||||
puzzleReportError:
|
||||
title: No se pudo reportar
|
||||
desc: "No pudimos procesar tu informe:"
|
||||
@ -261,8 +261,8 @@ dialogs:
|
||||
title: Introducir clave
|
||||
desc: Introduce la clave del puzle para cargarlo.
|
||||
puzzleDelete:
|
||||
title: Delete Puzzle?
|
||||
desc: Are you sure you want to delete '<title>'? This can not be undone!
|
||||
title: ¿Eliminar Puzle?
|
||||
desc: ¿Estas seguro de querer eliminar '<title>'? ¡Esto no se puede deshacer!
|
||||
ingame:
|
||||
keybindingsOverlay:
|
||||
moveMap: Mover
|
||||
@ -284,7 +284,7 @@ ingame:
|
||||
clearSelection: Limpiar selección
|
||||
pipette: Cuentagotas
|
||||
switchLayers: Cambiar capas
|
||||
clearBelts: Clear belts
|
||||
clearBelts: Borrar cintas
|
||||
colors:
|
||||
red: Rojo
|
||||
green: Verde
|
||||
@ -473,6 +473,7 @@ ingame:
|
||||
titleRatingDesc: Tu puntuación me ayudará a hacerte mejores sugerencias en el futuro
|
||||
continueBtn: Continuar Jugando
|
||||
menuBtn: Menú
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Autor
|
||||
shortKey: Clave
|
||||
@ -621,29 +622,29 @@ buildings:
|
||||
default:
|
||||
name: Puerta AND
|
||||
description: Emite el valor booleano "1" si ambas entradas son verdaderas.
|
||||
(Verdadeas significa una forma, color o valor booleano "1")
|
||||
(Verdaderas significa una forma, color o valor booleano "1")
|
||||
not:
|
||||
name: Puerta NOT
|
||||
description: Emite el valor booleano "1" si ambas entradas no son verdaderas.
|
||||
(Verdadeas significa una forma, color o valor booleano "1")
|
||||
(Verdaderas significa una forma, color o valor booleano "1")
|
||||
xor:
|
||||
name: Puerta XOR
|
||||
description: Emite el valor booleano "1" si una de las entradas es verdadera,
|
||||
pero no si ambas lo son. (Verdadeas significa una forma, color o
|
||||
valor booleano "1")
|
||||
pero no si ambas lo son. (Verdaderas significa una forma, color
|
||||
o valor booleano "1")
|
||||
or:
|
||||
name: Puerta OR
|
||||
description: Emite el valor booleano "1" Si una de las entradas es verdadera.
|
||||
(Verdadeas significa una forma, color o valor booleano "1")
|
||||
(Verdaderas significa una forma, color o valor booleano "1")
|
||||
transistor:
|
||||
default:
|
||||
name: Transistor
|
||||
description: Envia la señal de abajo si la señal del costado es verdadera
|
||||
(Verdadeas significa una forma, color o valor booleano "1").
|
||||
(Verdaderas significa una forma, color o valor booleano "1").
|
||||
mirrored:
|
||||
name: Transistor
|
||||
description: Envia la señal de abajo si la señal del costado es verdadera
|
||||
(Verdadeas significa una forma, color o valor booleano "1").
|
||||
(Verdaderas significa una forma, color o valor booleano "1").
|
||||
filter:
|
||||
default:
|
||||
name: Filtro
|
||||
@ -664,7 +665,7 @@ buildings:
|
||||
analyzer:
|
||||
default:
|
||||
name: Analizador de formas
|
||||
description: analiza el cuadrante de arriba a la derecha de la capa más baja de
|
||||
description: Analiza el cuadrante de arriba a la derecha de la capa más baja de
|
||||
la forma y devuelve su figura y color.
|
||||
comparator:
|
||||
default:
|
||||
@ -1046,7 +1047,12 @@ settings:
|
||||
title: Tamaño de recursos en el mapa
|
||||
description: Controla el tamaño de los recursos en la vista de aérea del mapa
|
||||
(Al hacer zoom mínimo).
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
rangeSliderPercentage: <amount> %
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: Atajos de teclado
|
||||
hint: "Pista: ¡Asegúrate de usar CTRL, SHIFT y ALT! Habilitan distintas opciones
|
||||
@ -1128,6 +1134,7 @@ keybindings:
|
||||
goal_acceptor: Goal Acceptor
|
||||
block: Block
|
||||
massSelectClear: Clear belts
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: Sobre el juego
|
||||
body: >-
|
||||
@ -1244,22 +1251,22 @@ puzzleMenu:
|
||||
levels: Niveles
|
||||
new: Nuevos
|
||||
top-rated: Los mejor valorados
|
||||
mine: Mis Puzles
|
||||
mine: Mios
|
||||
easy: Fáciles
|
||||
hard: Difíciles
|
||||
completed: Completados
|
||||
medium: Medium
|
||||
official: Official
|
||||
trending: Trending today
|
||||
trending-weekly: Trending weekly
|
||||
categories: Categories
|
||||
difficulties: By Difficulty
|
||||
account: My Puzzles
|
||||
search: Search
|
||||
medium: Medios
|
||||
official: Oficiales
|
||||
trending: Tendencias de hoy
|
||||
trending-weekly: Tendencias de la semana
|
||||
categories: Categorías
|
||||
difficulties: Por dificultad
|
||||
account: Mis puzles
|
||||
search: Buscar
|
||||
validation:
|
||||
title: Puzle no válido
|
||||
noProducers: Por favor, ¡pon un Productor de una sola pieza!
|
||||
noGoalAcceptors: Por favor , ¡pon un Aceptador de objetivos!
|
||||
noProducers: Por favor, ¡Pon un Productor de una sola pieza!
|
||||
noGoalAcceptors: Por favor, ¡Pon un Aceptador de objetivos!
|
||||
goalAcceptorNoItem: Uno o más aceptadores de objetivos no tienen asignado un
|
||||
elemento. Transporta una forma hacia ellos para poner un objetivo.
|
||||
goalAcceptorRateNotMet: Uno o más aceptadores de objetivos no están recibiendo
|
||||
@ -1271,11 +1278,26 @@ puzzleMenu:
|
||||
solo elemento no están conectados directamente a tus aceptadores de
|
||||
objetivos.
|
||||
difficulties:
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
dlcHint: Purchased the DLC already? Make sure it is activated by right clicking
|
||||
shapez.io in your library, selecting Properties > DLCs.
|
||||
easy: Fácil
|
||||
medium: Medio
|
||||
hard: Dificil
|
||||
unknown: Unrated
|
||||
dlcHint: ¿Ya compraste el DLC? Asegurate de tenerlo activado haciendo click
|
||||
derecho a shapez.io en tu biblioteca, selecionando propiedades > DLCs.
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: Estás haciendo tus acciones con demasiada frecuencia. Por favor,
|
||||
espera un poco.
|
||||
@ -1289,7 +1311,7 @@ backendErrors:
|
||||
not-found: No pudimos encontrar ese puzle.
|
||||
bad-category: No pudimos encontar esa categoría.
|
||||
bad-short-key: La clave que nos diste no es válida.
|
||||
profane-title: El título de tu puzle contiene lenguaje soez.
|
||||
profane-title: El título de tu puzle contiene lenguaje profano.
|
||||
bad-title-too-many-spaces: El título de tu puzle es demasiado breve.
|
||||
bad-shape-key-in-emitter: Un productor de un solo elemento tiene un elemento no válido.
|
||||
bad-shape-key-in-goal: Un aceptador de objetivos tiene un elemento no válido.
|
||||
@ -1300,6 +1322,7 @@ backendErrors:
|
||||
bad-payload: La petición contiene datos no válidos.
|
||||
bad-building-placement: Tu puzle contiene edificios en posiciones no válidas.
|
||||
timeout: El tiempo para la solicitud ha expirado.
|
||||
too-many-likes-already: The puzzle alreay got too many likes. If you still want
|
||||
to remove it, please contact support@shapez.io!
|
||||
no-permission: You do not have the permission to perform this action.
|
||||
too-many-likes-already: El puzle ha recibido demasiados me gusta ¡Si todavía
|
||||
quieres eliminarlo, por favor contacta a support@shapez.io! (Solo
|
||||
inglés)
|
||||
no-permission: No tienes los permisos necesarios para llevar a cabo esta acción.
|
||||
|
||||
@ -458,6 +458,7 @@ ingame:
|
||||
titleRatingDesc: Your rating will help me to make you better suggestions in the future
|
||||
continueBtn: Keep Playing
|
||||
menuBtn: Menu
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Author
|
||||
shortKey: Short Key
|
||||
@ -1004,7 +1005,12 @@ settings:
|
||||
mapResourcesScale:
|
||||
title: Kartan resurssien koko
|
||||
description: Määrittää muotojen koon kartalla (loitonnettaessa).
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
rangeSliderPercentage: <amount> %
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: Pikanäppäimet
|
||||
hint: "Vinkki: Muista käyttää CTRL, SHIFT ja ALT! Ne ottavat käyttöön erilaisia
|
||||
@ -1086,6 +1092,7 @@ keybindings:
|
||||
goal_acceptor: Goal Acceptor
|
||||
block: Block
|
||||
massSelectClear: Clear belts
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: Tietoja tästä pelistä
|
||||
body: >-
|
||||
@ -1214,8 +1221,23 @@ puzzleMenu:
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
unknown: Unrated
|
||||
dlcHint: Purchased the DLC already? Make sure it is activated by right clicking
|
||||
shapez.io in your library, selecting Properties > DLCs.
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: You are performing your actions too frequent. Please wait a bit.
|
||||
invalid-api-key: Failed to communicate with the backend, please try to
|
||||
|
||||
@ -11,14 +11,14 @@ steamPage:
|
||||
Et en plus, vous devrez aussi produire de plus en plus pour satisfaire la demande. La seule solution est de construire en plus grand ! Au début vous ne ferez que découper les formes, mais plus tard vous devrez les peindre — et pour ça vous devrez extraire et mélanger des couleurs !
|
||||
|
||||
En achetant le jeu sur Steam, vous aurez accès à la version complète, mais vous pouvez aussi jouer à une démo sur shapez.io et vous décider ensuite !
|
||||
what_others_say: Ce que les gens pensent de shapez.io
|
||||
nothernlion_comment: This game is great - I'm having a wonderful time playing,
|
||||
and time has flown by.
|
||||
what_others_say: Ce que les gens pensent de Shapez.io
|
||||
nothernlion_comment: Ce jeu est génial - Je passe un merveilleux moment à jouer,
|
||||
et le temps s'est envolé.
|
||||
notch_comment: Mince ! Je devrais vraiment me coucher, mais je crois que j'ai
|
||||
trouvé comment faire un ordinateur dans shapez.io
|
||||
steam_review_comment: This game has stolen my life and I don't want it back.
|
||||
Very chill factory game that won't let me stop making my lines more
|
||||
efficient.
|
||||
trouvé comment faire un ordinateur dans Shapez.io
|
||||
steam_review_comment: Ce jeu a volé ma vie et je ne veux pas la récupérer. Jeu
|
||||
d'usine très cool qui ne me laissera pas arrêter de rendre mes lignes
|
||||
plus efficaces.
|
||||
global:
|
||||
loading: Chargement
|
||||
error: Erreur
|
||||
@ -71,11 +71,11 @@ mainMenu:
|
||||
savegameLevel: Niveau <x>
|
||||
savegameLevelUnknown: Niveau inconnu
|
||||
savegameUnnamed: Sans titre
|
||||
puzzleMode: Puzzle Mode
|
||||
back: Back
|
||||
puzzleMode: Mode Puzzle
|
||||
back: Retour
|
||||
puzzleDlcText: Vous aimez compacter et optimiser vos usines ? Achetez le DLC sur
|
||||
Steam dés maintenant pour encore plus d'amusement !
|
||||
puzzleDlcWishlist: Wishlist now!
|
||||
Steam dès maintenant pour encore plus d'amusement!
|
||||
puzzleDlcWishlist: Ajoute à ta liste de souhaits maintenant !
|
||||
puzzleDlcViewNow: View Dlc
|
||||
dialogs:
|
||||
buttons:
|
||||
@ -90,7 +90,7 @@ dialogs:
|
||||
viewUpdate: Voir les mises à jour
|
||||
showUpgrades: Montrer les améliorations
|
||||
showKeybindings: Montrer les raccourcis
|
||||
retry: Réesayer
|
||||
retry: Réessayer
|
||||
continue: Continuer
|
||||
playOffline: Jouer Hors-ligne
|
||||
importSavegameError:
|
||||
@ -200,63 +200,66 @@ dialogs:
|
||||
desc: "Malheuresement, le puzzle n'a pas pu être chargé :"
|
||||
submitPuzzle:
|
||||
title: Envoyer le Puzzle
|
||||
descName: "Donnez un nom à votre puzzle :"
|
||||
descIcon: "Please enter a unique short key, which will be shown as the icon of
|
||||
your puzzle (You can generate them <link>here</link>, or choose one
|
||||
of the randomly suggested shapes below):"
|
||||
placeholderName: Puzzle Title
|
||||
descName: "Donnez un nom à votre puzzle:"
|
||||
descIcon: "Veuillez entrer un raccourci de forme unique, qui sera affichée comme
|
||||
icône de votre puzzle (Vous pouvez générer le raccourci d'une forme
|
||||
<link>ici</link>, ou en choisir une parmi les formes suggérées
|
||||
alétoirement ci-dessous):"
|
||||
placeholderName: Titre du Puzzle
|
||||
puzzleResizeBadBuildings:
|
||||
title: Resize not possible
|
||||
desc: You can't make the zone any smaller, because then some buildings would be
|
||||
outside the zone.
|
||||
title: Impossible de redimensionner
|
||||
desc: Vous ne pouvez pas rétrécir la zone, car certains bâtiments seraient en
|
||||
dehors de la zone
|
||||
puzzleLoadError:
|
||||
title: Mauvais Puzzle
|
||||
desc: "Le chargement du puzzle a échoué :"
|
||||
desc: "Le chargement du puzzle a échoué:"
|
||||
offlineMode:
|
||||
title: Mode hors-ligne
|
||||
desc: We couldn't reach the servers, so the game has to run in offline mode.
|
||||
Please make sure you have an active internet connection.
|
||||
desc: Nous n'avons pas pu atteindre les serveurs, donc le jeu doit être mis en
|
||||
mode hors ligne. Veuillez vous assurez que vous disposez d'une
|
||||
connexion Internet active.
|
||||
puzzleDownloadError:
|
||||
title: Erreur de téléchargment
|
||||
desc: "Le téléchargement à échoué :"
|
||||
desc: "Le téléchargement a échoué:"
|
||||
puzzleSubmitError:
|
||||
title: Erreur d'envoi
|
||||
desc: "L'envoi à échoué :"
|
||||
desc: "L'envoi a échoué:"
|
||||
puzzleSubmitOk:
|
||||
title: Puzzle envoyé
|
||||
desc: Félicitation ! Votre puzzle à été envoyé et peut maintenant être joué.
|
||||
desc: Félicitations ! Votre puzzle a été envoyé et peut maintenant être joué.
|
||||
Vous pouvez maintenant le retrouver dans la section "Mes Puzzles".
|
||||
puzzleCreateOffline:
|
||||
title: Mode Hors-ligne
|
||||
desc: Since you are offline, you will not be able to save and/or publish your
|
||||
puzzle. Would you still like to continue?
|
||||
desc: Puisque vous êtes hors ligne, vous ne pourrez pas enregistrer et/ou
|
||||
publier votre puzzle. Souhaitez-vous toujours continuer ?
|
||||
puzzlePlayRegularRecommendation:
|
||||
title: Recommendation
|
||||
desc: I <strong>strongly</strong> recommend playing the normal game to level 12
|
||||
before attempting the puzzle DLC, otherwise you may encounter
|
||||
mechanics not yet introduced. Do you still want to continue?
|
||||
title: Recommandation
|
||||
desc: Je recommande <strong>fortement</strong> de jouer au jeu normal jusqu'au
|
||||
niveau 12 avant d'essayer le Puzzle DLC, sinon vous risqez de
|
||||
rencontrer des méchanismes pas encore introduits. Voulez-vous
|
||||
toujours continuer ?
|
||||
puzzleShare:
|
||||
title: Short Key Copied
|
||||
desc: The short key of the puzzle (<key>) has been copied to your clipboard! It
|
||||
can be entered in the puzzle menu to access the puzzle.
|
||||
title: Code copié
|
||||
desc: Le code du puzzle (<key>) a été copié dans ton presse-papiers ! Il peut
|
||||
être entré dans le menu des puzzles pour accéder au puzzle.
|
||||
puzzleReport:
|
||||
title: Report Puzzle
|
||||
title: Signaler le Puzzle
|
||||
options:
|
||||
profane: Profane
|
||||
unsolvable: Not solvable
|
||||
trolling: Trolling
|
||||
unsolvable: Irrésolvable
|
||||
trolling: Troll
|
||||
puzzleReportComplete:
|
||||
title: Merci pour votre retour !
|
||||
title: Merci pour votre retour!
|
||||
desc: Le puzzle a été marqué.
|
||||
puzzleReportError:
|
||||
title: Failed to report
|
||||
desc: "Your report could not get processed:"
|
||||
title: Échec du signalement
|
||||
desc: "Votre signalement n'a pas pu être effectué:"
|
||||
puzzleLoadShortKey:
|
||||
title: Enter short key
|
||||
desc: Enter the short key of the puzzle to load it.
|
||||
title: Entrer un code
|
||||
desc: Entrer le code du puzzle pour le charger.
|
||||
puzzleDelete:
|
||||
title: Delete Puzzle?
|
||||
desc: Are you sure you want to delete '<title>'? This can not be undone!
|
||||
title: Supprimer le puzzle ?
|
||||
desc: Êtes-vous sûr de vouloir supprimer '<title>' ? Cela sera irréversible !
|
||||
ingame:
|
||||
keybindingsOverlay:
|
||||
moveMap: Déplacer
|
||||
@ -430,28 +433,30 @@ ingame:
|
||||
title: Me soutenir
|
||||
desc: Je le développe pendant mon temps libre !
|
||||
achievements:
|
||||
title: Achievements
|
||||
desc: Hunt them all!
|
||||
title: Succès
|
||||
desc: Débloquez-les tous !
|
||||
puzzleEditorSettings:
|
||||
zoneTitle: Zone
|
||||
zoneWidth: Width
|
||||
zoneHeight: Height
|
||||
trimZone: Trim
|
||||
clearItems: Clear Items
|
||||
share: Share
|
||||
report: Report
|
||||
zoneWidth: Largeur
|
||||
zoneHeight: Hauteur
|
||||
trimZone: Optimiser la taille
|
||||
clearItems: Supprimer les objets
|
||||
share: Partager
|
||||
report: Signaler
|
||||
clearBuildings: Clear Buildings
|
||||
resetPuzzle: Reset Puzzle
|
||||
puzzleEditorControls:
|
||||
title: Puzzle Creator
|
||||
title: Créateur de Puzzles
|
||||
instructions:
|
||||
- 1. Place <strong>Constant Producers</strong> to provide shapes and
|
||||
colors to the player
|
||||
- 2. Build one or more shapes you want the player to build later and
|
||||
deliver it to one or more <strong>Goal Acceptors</strong>
|
||||
- 3. Once a Goal Acceptor receives a shape for a certain amount of
|
||||
time, it <strong>saves it as a goal</strong> that the player must
|
||||
produce later (Indicated by the <strong>green badge</strong>).
|
||||
- 1. Placez des <strong>Producteurs Constants</strong> pour fournir
|
||||
des formes et des couleurs au joueur
|
||||
- 2. Fabriquez une ou plusieurs formes que vous voulez que le joueur
|
||||
fabrique plus tard et délivrez-la/les à un ou plusieurs
|
||||
<strong>Récepteurs d'Objectif</strong>
|
||||
- 3. Une fois qu'un Récépteur d'Objectif a reçu une forme pendant un
|
||||
certain temps, il <strong>l'enregistre zn tant
|
||||
qu'objectif</strong> que le joueur devra produire plus tard
|
||||
(Indiqué par le <strong>badge vert</strong>).
|
||||
- 4. Click the <strong>lock button</strong> on a building to disable
|
||||
it.
|
||||
- 5. Once you click review, your puzzle will be validated and you
|
||||
@ -460,18 +465,19 @@ ingame:
|
||||
except for the Producers and Goal Acceptors - That's the part that
|
||||
the player is supposed to figure out for themselves, after all :)
|
||||
puzzleCompletion:
|
||||
title: Puzzle Completed!
|
||||
titleLike: "Click the heart if you liked the puzzle:"
|
||||
titleRating: How difficult did you find the puzzle?
|
||||
titleRatingDesc: Your rating will help me to make you better suggestions in the future
|
||||
continueBtn: Keep Playing
|
||||
title: Puzzle Résolu !
|
||||
titleLike: "Cliquez sur le cœur si vous avez aimé le Puzzle:"
|
||||
titleRating: À quel point avez-vous trouvé le puzzle diffcile ?
|
||||
titleRatingDesc: Votre note m'aidera à vous faire de meilleures suggestions à l'avenir
|
||||
continueBtn: Continuer à jouer
|
||||
menuBtn: Menu
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Author
|
||||
author: Auteur
|
||||
shortKey: Short Key
|
||||
rating: Difficulty score
|
||||
averageDuration: Avg. Duration
|
||||
completionRate: Completion rate
|
||||
rating: Niveau de difficulté
|
||||
averageDuration: Durée moyenne
|
||||
completionRate: Taux de réussite
|
||||
shopUpgrades:
|
||||
belt:
|
||||
name: Convoyeurs, distributeurs et tunnels
|
||||
@ -691,25 +697,26 @@ buildings:
|
||||
calque de câblage sur le calque normal.
|
||||
constant_producer:
|
||||
default:
|
||||
name: Constant Producer
|
||||
description: Constantly outputs a specified shape or color.
|
||||
name: Producteur Constabnt
|
||||
description: Sort constamment une forme ou une couleur spécifiée.
|
||||
goal_acceptor:
|
||||
default:
|
||||
name: Goal Acceptor
|
||||
description: Deliver shapes to the goal acceptor to set them as a goal.
|
||||
name: Récepteur d'Objetcif
|
||||
description: Délivrez des formes au récepteur d'objectif pour les définir comme
|
||||
objectif.
|
||||
block:
|
||||
default:
|
||||
name: Block
|
||||
description: Allows you to block a tile.
|
||||
name: Bloc
|
||||
description: Permet de bloquer une case.
|
||||
storyRewards:
|
||||
reward_cutter_and_trash:
|
||||
title: Découpage de formes
|
||||
desc: You just unlocked the <strong>cutter</strong>, which cuts shapes in half
|
||||
from top to bottom <strong>regardless of its
|
||||
orientation</strong>!<br><br>Be sure to get rid of the waste, or
|
||||
otherwise <strong>it will clog and stall</strong> - For this purpose
|
||||
I have given you the <strong>trash</strong>, which destroys
|
||||
everything you put into it!
|
||||
desc: Vous venez de déverrouiller le <strong>découpeur</strong>, qui coupe les
|
||||
formes en deux de haut en bas <strong>indépendamment de son
|
||||
orientation</strong>!<br><br>Assurez-vous de vous débarrasser des
|
||||
déchets, ou sinon <strong>il se bouchera et se bloquera</strong> - À
|
||||
cet effet, Je vous ai donné la <strong>poubelle</strong>, qui
|
||||
détruit tout ce que vous mettez dedans !
|
||||
reward_rotater:
|
||||
title: Rotation
|
||||
desc: Le <strong>pivoteur</strong> a été débloqué ! Il pivote les formes de 90
|
||||
@ -735,9 +742,10 @@ storyRewards:
|
||||
<strong>placée au-dessus</strong> de la forme de gauche.
|
||||
reward_balancer:
|
||||
title: Répartiteur
|
||||
desc: The multifunctional <strong>balancer</strong> has been unlocked - It can
|
||||
be used to build bigger factories by <strong>splitting and merging
|
||||
items</strong> onto multiple belts!
|
||||
desc: Le <strong>répartiteur</strong> multifonctionnel a été débloqué - Il peut
|
||||
être utilisé pour construire de plus grandes usines en
|
||||
<strong>divisant et en rassemblant des objets</strong> sur plusieurs
|
||||
convoyeurs !
|
||||
reward_tunnel:
|
||||
title: Tunnel
|
||||
desc: Le <strong>tunnel</strong> a été débloqué. Vous pouvez maintenant faire
|
||||
@ -843,14 +851,17 @@ storyRewards:
|
||||
gâteau : je vous donne aussi le <strong>transistor</strong> !"
|
||||
reward_virtual_processing:
|
||||
title: Traitement virtuel
|
||||
desc: I just gave a whole bunch of new buildings which allow you to
|
||||
<strong>simulate the processing of shapes</strong>!<br><br> You can
|
||||
now simulate a cutter, rotator, stacker and more on the wires layer!
|
||||
With this you now have three options to continue the game:<br><br> -
|
||||
Build an <strong>automated machine</strong> to create any possible
|
||||
shape requested by the HUB (I recommend to try it!).<br><br> - Build
|
||||
something cool with wires.<br><br> - Continue to play
|
||||
normally.<br><br> Whatever you choose, remember to have fun!
|
||||
desc: Je viens de vous donner tout un tas de nouveaux bâtiments qui vous
|
||||
permettent de <strong>simuler le traitement des
|
||||
formes</strong>!<br><br> Vous pouvez maintenant simuler un
|
||||
découpeur, un pivoteur, un assembleur et plus encore sur la couche
|
||||
des fils ! Avec cela vous avez maintenant trois options pour
|
||||
continuer le jeu:<br><br> - Construire une <strong>machine
|
||||
automatique</strong> pour créer toute forme possible demandée par le
|
||||
HUB (Je recommande d'essayer de le faire !).<br><br> - Construire
|
||||
quelque chose de cool avec les fils.<br><br> - Continuer à jouer
|
||||
normalement.<br><br> Quoi que vous choisissiez, n'oubliez pas de
|
||||
vous amuser !
|
||||
no_reward:
|
||||
title: Niveau suivant
|
||||
desc: "Ce niveau n’a pas de récompense mais le prochain, si !<br><br> PS : Ne
|
||||
@ -1049,6 +1060,11 @@ settings:
|
||||
title: Taille des ressources sur la carte
|
||||
description: Contrôle la taille des formes sur la vue d’ensemble de la carte
|
||||
visible en dézoomant.
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: Contrôles
|
||||
hint: "Astuce : N’oubliez pas d’utiliser CTRL, MAJ et ALT ! Ces touches activent
|
||||
@ -1127,10 +1143,11 @@ keybindings:
|
||||
rotateToDown: "Rotate: Point Down"
|
||||
rotateToRight: "Rotate: Point Right"
|
||||
rotateToLeft: "Rotate: Point Left"
|
||||
constant_producer: Constant Producer
|
||||
goal_acceptor: Goal Acceptor
|
||||
block: Block
|
||||
massSelectClear: Clear belts
|
||||
constant_producer: Producteur Constant
|
||||
goal_acceptor: Récepteur d'Objectif
|
||||
block: Bloc
|
||||
massSelectClear: Vider les convoyeurs
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: À propos de ce jeu
|
||||
body: >-
|
||||
@ -1156,7 +1173,7 @@ demo:
|
||||
exportingBase: Exporter une image de toute la base
|
||||
settingNotAvailable: Indisponible dans la démo.
|
||||
tips:
|
||||
- Le centre n’importe quelle forme, pas seulement la forme actuelle !
|
||||
- Le centre accepte n’importe quelle forme, pas seulement la forme actuelle !
|
||||
- Assurez-vous que vos usines soient modulaires, cela paiera !
|
||||
- Ne construisez pas trop près du centre, ou ce sera un énorme chaos !
|
||||
- Si l’empilement ne fonctionne pas, essayez d’échanger les entrées.
|
||||
@ -1237,7 +1254,7 @@ puzzleMenu:
|
||||
edit: Éditer
|
||||
title: Mode Puzzle
|
||||
createPuzzle: Créer un Puzzle
|
||||
loadPuzzle: charger
|
||||
loadPuzzle: Charger
|
||||
reviewPuzzle: Revoir & Publier
|
||||
validatingPuzzle: Validation du Puzzle
|
||||
submittingPuzzle: Publication du Puzzle
|
||||
@ -1245,19 +1262,19 @@ puzzleMenu:
|
||||
categories:
|
||||
levels: Niveaux
|
||||
new: Nouveau
|
||||
top-rated: Les-mieux notés
|
||||
top-rated: Les mieux notés
|
||||
mine: Mes puzzles
|
||||
easy: Facile
|
||||
hard: Difficile
|
||||
completed: Complété
|
||||
medium: Medium
|
||||
official: Official
|
||||
official: Officiel
|
||||
trending: Trending today
|
||||
trending-weekly: Trending weekly
|
||||
categories: Categories
|
||||
difficulties: By Difficulty
|
||||
account: My Puzzles
|
||||
search: Search
|
||||
categories: Catégories
|
||||
difficulties: Par Difficulté
|
||||
account: Mes Puzzles
|
||||
search: Rechercher
|
||||
validation:
|
||||
title: Puzzle invalide
|
||||
noProducers: Veuillez placer un producteur constant !
|
||||
@ -1276,8 +1293,23 @@ puzzleMenu:
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
unknown: Unrated
|
||||
dlcHint: Purchased the DLC already? Make sure it is activated by right clicking
|
||||
shapez.io in your library, selecting Properties > DLCs.
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: Vous effectuez vos actions trop fréquemment. Veuillez attendre un peu
|
||||
s'il vous plait.
|
||||
@ -1302,6 +1334,6 @@ backendErrors:
|
||||
bad-payload: La demande contient des données invalides.
|
||||
bad-building-placement: Votre puzzle contient des bâtiments placés non valides.
|
||||
timeout: La demande a expiré.
|
||||
too-many-likes-already: The puzzle alreay got too many likes. If you still want
|
||||
too-many-likes-already: The puzzle already got too many likes. If you still want
|
||||
to remove it, please contact support@shapez.io!
|
||||
no-permission: You do not have the permission to perform this action.
|
||||
|
||||
@ -444,6 +444,7 @@ ingame:
|
||||
titleRatingDesc: Your rating will help me to make you better suggestions in the future
|
||||
continueBtn: Keep Playing
|
||||
menuBtn: Menu
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Author
|
||||
shortKey: Short Key
|
||||
@ -952,6 +953,11 @@ settings:
|
||||
mapResourcesScale:
|
||||
title: גודל המשאבים במפה
|
||||
description: .שולט על הגודל של הצורות על המפה (בתצוגה המוקטנת)
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: מקשים
|
||||
hint: ".הם מאפשרים הרבה אפשרויות השמה !ALTו SHIFT ,CTRLטיפ: השתמש ב"
|
||||
@ -1032,6 +1038,7 @@ keybindings:
|
||||
goal_acceptor: Goal Acceptor
|
||||
block: Block
|
||||
massSelectClear: Clear belts
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: בנוגע למשחק הזה
|
||||
body: >-
|
||||
@ -1157,8 +1164,23 @@ puzzleMenu:
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
unknown: Unrated
|
||||
dlcHint: Purchased the DLC already? Make sure it is activated by right clicking
|
||||
shapez.io in your library, selecting Properties > DLCs.
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: You are performing your actions too frequent. Please wait a bit.
|
||||
invalid-api-key: Failed to communicate with the backend, please try to
|
||||
|
||||
@ -458,6 +458,7 @@ ingame:
|
||||
titleRatingDesc: Your rating will help me to make you better suggestions in the future
|
||||
continueBtn: Keep Playing
|
||||
menuBtn: Menu
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Author
|
||||
shortKey: Short Key
|
||||
@ -998,7 +999,12 @@ settings:
|
||||
title: Map Resources Size
|
||||
description: Controls the size of the shapes on the map overview (when zooming
|
||||
out).
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
rangeSliderPercentage: <amount> %
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: Tipka
|
||||
hint: "Savjet: Be sure to make use of CTRL, SHIFT and ALT! They enable different
|
||||
@ -1080,6 +1086,7 @@ keybindings:
|
||||
goal_acceptor: Goal Acceptor
|
||||
block: Block
|
||||
massSelectClear: Clear belts
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: O Igri
|
||||
body: >-
|
||||
@ -1207,8 +1214,23 @@ puzzleMenu:
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
unknown: Unrated
|
||||
dlcHint: Purchased the DLC already? Make sure it is activated by right clicking
|
||||
shapez.io in your library, selecting Properties > DLCs.
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: You are performing your actions too frequent. Please wait a bit.
|
||||
invalid-api-key: Failed to communicate with the backend, please try to
|
||||
|
||||
@ -464,6 +464,7 @@ ingame:
|
||||
jövőben
|
||||
continueBtn: Játék Folytatása
|
||||
menuBtn: Menü
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Szerző
|
||||
shortKey: Gyorskód
|
||||
@ -1025,7 +1026,12 @@ settings:
|
||||
title: Erőforrások Mérete a Térképen
|
||||
description: Kizoomolt állapotban a térképen megjelenő erőforrások (alakzatok és
|
||||
színek) méretét állítja.
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
rangeSliderPercentage: <amount> %
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: Gyorsbillentyűk
|
||||
hint: "Tipp: Használd ki a CTRL, SHIFT és ALT billentyűket, amelyek különféle
|
||||
@ -1107,6 +1113,7 @@ keybindings:
|
||||
goal_acceptor: Elfogadó
|
||||
block: Blokkolás
|
||||
massSelectClear: Futószalagok Kiürítése
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: A Játékról
|
||||
body: >-
|
||||
@ -1242,8 +1249,23 @@ puzzleMenu:
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
unknown: Unrated
|
||||
dlcHint: Purchased the DLC already? Make sure it is activated by right clicking
|
||||
shapez.io in your library, selecting Properties > DLCs.
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: Túl gyorsan csinálsz dolgokat. Kérlek, várj egy kicsit.
|
||||
invalid-api-key: Valami nem oké a játékkal. Próbáld meg frissíteni vagy
|
||||
|
||||
@ -467,6 +467,7 @@ ingame:
|
||||
titleRatingDesc: Your rating will help me to make you better suggestions in the future
|
||||
continueBtn: Keep Playing
|
||||
menuBtn: Menu
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Author
|
||||
shortKey: Short Key
|
||||
@ -1057,7 +1058,12 @@ settings:
|
||||
title: Ukuran Sumber Daya Peta
|
||||
description: Mengontrol ukuran bentuk-bentuk pada gambaran peta (ketika zoom
|
||||
out).
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
rangeSliderPercentage: <amount> %
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: Tombol Pintas
|
||||
hint: "Petunjuk: Pastikan kamu menggunakan CTRL, SHIFT and ALT! Mereka
|
||||
@ -1139,6 +1145,7 @@ keybindings:
|
||||
goal_acceptor: Goal Acceptor
|
||||
block: Block
|
||||
massSelectClear: Clear belts
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: Tentang permainan ini
|
||||
body: >-
|
||||
@ -1288,8 +1295,23 @@ puzzleMenu:
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
unknown: Unrated
|
||||
dlcHint: Purchased the DLC already? Make sure it is activated by right clicking
|
||||
shapez.io in your library, selecting Properties > DLCs.
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: You are performing your actions too frequent. Please wait a bit.
|
||||
invalid-api-key: Failed to communicate with the backend, please try to
|
||||
|
||||
@ -447,7 +447,7 @@ ingame:
|
||||
clearItems: Elimina oggetti
|
||||
share: Condividi
|
||||
report: Segnala
|
||||
clearBuildings: Clear Buildings
|
||||
clearBuildings: Cancella edifici
|
||||
resetPuzzle: Reset Puzzle
|
||||
puzzleEditorControls:
|
||||
title: Creazione puzzle
|
||||
@ -477,6 +477,7 @@ ingame:
|
||||
in futuro
|
||||
continueBtn: Continua a giocare
|
||||
menuBtn: Menù
|
||||
nextPuzzle: Puzzle successivo
|
||||
puzzleMetadata:
|
||||
author: Autore
|
||||
shortKey: Codice
|
||||
@ -745,7 +746,7 @@ storyRewards:
|
||||
reward_rotater_ccw:
|
||||
title: Rotazione antioraria
|
||||
desc: Hai sbloccato una variante del <strong>ruotatore</strong>! Consente di
|
||||
ruotare in senso antiorario! Per costruirla, seleziona la ruotatrice
|
||||
ruotare in senso antiorario! Per costruirla, seleziona il ruotatore
|
||||
e <strong>premi 'T' per cambiare variante</strong>!
|
||||
reward_miner_chainable:
|
||||
title: Estrattore a catena
|
||||
@ -823,7 +824,7 @@ storyRewards:
|
||||
la portata di un nastro.<br><br>E aspetta di sbloccare i cavi,
|
||||
allora sì che sarà molto utile!
|
||||
reward_rotater_180:
|
||||
title: Ruotatrice (180 gradi)
|
||||
title: Ruotatore (180 gradi)
|
||||
desc: Hai appena sbloccato il <strong>ruotatore</strong> a 180 gradi! Consente
|
||||
di ruotare una forma di 180 gradi (Sorpresa! :D)
|
||||
reward_display:
|
||||
@ -833,7 +834,7 @@ storyRewards:
|
||||
lettore di nastri e il magazzino mostrano l'ultimo oggetto da loro
|
||||
letto? Prova a mostrarlo su di un display!"
|
||||
reward_constant_signal:
|
||||
title: Sengale costante
|
||||
title: Segnale costante
|
||||
desc: Hai sbloccato l'edificio <strong>segnale costante</strong> sul livello
|
||||
elettrico! È utile collegarlo ai <strong>filtri di oggetti</strong>
|
||||
per esempio.<br><br> Il segnale costante può emettere una
|
||||
@ -859,7 +860,7 @@ storyRewards:
|
||||
normalmente. <br><br> Qualsiasi cosa tu scelga, ricordati di
|
||||
divertirti!
|
||||
reward_wires_painter_and_levers:
|
||||
title: Cavi e Verniciatrice quadrupla
|
||||
title: Cavi e Verniciatore quadruplo
|
||||
desc: "Hai appena sbloccato il <strong>Livello Elettrico</strong>: è un livello
|
||||
separato dal livelo normale e introduce molte altre meccaniche di
|
||||
gioco!<br><br> Per il momento ti ho sbloccato il
|
||||
@ -1048,7 +1049,12 @@ settings:
|
||||
title: Grandezza delle Risorse sulla Mappa
|
||||
description: Controlla la grandezza delle forme visualizzate sulla mappa (quando
|
||||
si fa lo zoom indietro).
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Determina se mostrare sempre la forma in uscita da un edificio quando si passa sopra di esso col cursore,
|
||||
invece di dover premere 'ALT'.
|
||||
rangeSliderPercentage: <amount> %
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: Comandi
|
||||
hint: "Suggerimento: Usa spesso CTRL, MAIUSC e ALT! Abilitano opzioni di
|
||||
@ -1065,7 +1071,7 @@ keybindings:
|
||||
mappings:
|
||||
confirm: Conferma
|
||||
back: Indietro
|
||||
mapMoveUp: Spostati sù
|
||||
mapMoveUp: Spostati su
|
||||
mapMoveRight: Spostati a destra
|
||||
mapMoveDown: Spostati giù
|
||||
mapMoveLeft: Spostati a sinistra
|
||||
@ -1130,6 +1136,7 @@ keybindings:
|
||||
goal_acceptor: Accettore di obiettivi
|
||||
block: Blocco
|
||||
massSelectClear: Sgombra nastri
|
||||
showShapeTooltip: Mostra forma di uscita di un edificio
|
||||
about:
|
||||
title: Riguardo questo gioco
|
||||
body: >-
|
||||
@ -1272,8 +1279,23 @@ puzzleMenu:
|
||||
easy: Facile
|
||||
medium: Medio
|
||||
hard: Difficile
|
||||
dlcHint: Purchased the DLC already? Make sure it is activated by right clicking
|
||||
shapez.io in your library, selecting Properties > DLCs.
|
||||
unknown: Non classificato
|
||||
dlcHint: Hai già acquistato il DLC? Assicurati che sia attivo facendo clic destro
|
||||
su shapez.io nella tua libreria e selezionando Proprietà > DLC.
|
||||
search:
|
||||
action: Cerca
|
||||
placeholder: Inserisci il nome di un puzzle o di un autore
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Qualsiasi difficoltà
|
||||
easy: Facile
|
||||
medium: Medio
|
||||
hard: Difficile
|
||||
durations:
|
||||
any: Qualsiasi durata
|
||||
short: Breve (< 2 minuti)
|
||||
medium: Normale
|
||||
long: Lunga (> 10 minuti)
|
||||
backendErrors:
|
||||
ratelimit: Stai facendo troppe azioni velocemente. Per favore attendi un attimo.
|
||||
invalid-api-key: Comunicazione con il backend fallita, per favore prova ad
|
||||
|
||||
@ -422,6 +422,7 @@ ingame:
|
||||
titleRatingDesc: Your rating will help me to make you better suggestions in the future
|
||||
continueBtn: Keep Playing
|
||||
menuBtn: Menu
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Author
|
||||
shortKey: Short Key
|
||||
@ -868,6 +869,11 @@ settings:
|
||||
mapResourcesScale:
|
||||
title: 資源アイコンのサイズ
|
||||
description: ズームアウトしたときの図形のサイズを調節します。
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: キー設定
|
||||
hint: "Tip: CTRL, SHIFT, ALTを活用してください。建造物配置の際の追加機能がそれぞれ割り当てられています。"
|
||||
@ -948,6 +954,7 @@ keybindings:
|
||||
goal_acceptor: Goal Acceptor
|
||||
block: Block
|
||||
massSelectClear: Clear belts
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: このゲームについて
|
||||
body: >-
|
||||
@ -1070,8 +1077,23 @@ puzzleMenu:
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
unknown: Unrated
|
||||
dlcHint: Purchased the DLC already? Make sure it is activated by right clicking
|
||||
shapez.io in your library, selecting Properties > DLCs.
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: You are performing your actions too frequent. Please wait a bit.
|
||||
invalid-api-key: Failed to communicate with the backend, please try to
|
||||
|
||||
@ -58,8 +58,7 @@ mainMenu:
|
||||
openSourceHint: 이 게임은 오픈 소스입니다!
|
||||
discordLink: 공식 디스코드 서버
|
||||
helpTranslate: 번역을 도와주세요!
|
||||
browserWarning:
|
||||
이 게임은 현재 브라우저에서 느리게 작동하는 것으로 알려져 있습니다! 더 좋은 성능을 위해 정식 버전을 구매하거나
|
||||
browserWarning: 이 게임은 현재 브라우저에서 느리게 작동하는 것으로 알려져 있습니다! 더 좋은 성능을 위해 정식 버전을 구매하거나
|
||||
Google Chrome 브라우저를 다운로드하세요.
|
||||
savegameLevel: 레벨 <x>
|
||||
savegameLevelUnknown: 미확인 레벨
|
||||
@ -128,8 +127,7 @@ dialogs:
|
||||
desc: 지난번 플레이 이후 변경 사항은 다음과 같습니다.
|
||||
upgradesIntroduction:
|
||||
title: 업그레이드 하기
|
||||
desc:
|
||||
<strong>기존의 공장을 허물지 마세요!</strong> 여러분이 그동안 만들어 수집한 모든 도형은 업그레이드에 사용됩니다.
|
||||
desc: <strong>기존의 공장을 허물지 마세요!</strong> 여러분이 그동안 만들어 수집한 모든 도형은 업그레이드에 사용됩니다.
|
||||
업그레이드 버튼은 화면의 오른쪽 위에 있습니다.
|
||||
massDeleteConfirm:
|
||||
title: 삭제 확인
|
||||
@ -142,8 +140,7 @@ dialogs:
|
||||
desc: 12 레벨부터 청사진 기능이 해금됩니다!
|
||||
keybindingsIntroduction:
|
||||
title: 유용한 조작법
|
||||
desc:
|
||||
"이 게임에는 거대한 공장을 수월하게 세우기 위한 많은 조작법이 있습니다. 아래는 그 대표적인 것이며, 자세한 조작법은
|
||||
desc: "이 게임에는 거대한 공장을 수월하게 세우기 위한 많은 조작법이 있습니다. 아래는 그 대표적인 것이며, 자세한 조작법은
|
||||
<strong>조작법 설정</strong>을 참고해주세요!<br><br> <code
|
||||
class='keybinding'>CTRL</code> + 드래그: 영역을 선택합니다.<br> <code
|
||||
class='keybinding'>SHIFT</code>: 누르는 동안 같은 건물을 여러개 배치할 수 있습니다.<br>
|
||||
@ -157,8 +154,7 @@ dialogs:
|
||||
desc: 체험판 버전에서는 마커를 2개 까지만 배치할 수 있습니다. 정식 버전을 구입하면 마커를 무제한으로 배치할 수 있습니다!
|
||||
exportScreenshotWarning:
|
||||
title: 스크린샷 내보내기
|
||||
desc:
|
||||
당신의 공장을 스크린샷으로 내보내려 합니다. 매우 거대한 크기의 공장이라면 그 처리 시간이 상당히 오래 걸릴 것이며, 최악의 경우
|
||||
desc: 당신의 공장을 스크린샷으로 내보내려 합니다. 매우 거대한 크기의 공장이라면 그 처리 시간이 상당히 오래 걸릴 것이며, 최악의 경우
|
||||
게임이 중단될 수 있습니다!
|
||||
massCutInsufficientConfirm:
|
||||
title: 자르기 확인
|
||||
@ -184,8 +180,7 @@ dialogs:
|
||||
submitPuzzle:
|
||||
title: 퍼즐 보내기
|
||||
descName: "퍼즐에 이름을 지어 주세요:"
|
||||
descIcon:
|
||||
"퍼즐의 아이콘으로 보여지게 될 짧은 단어를 지정해 주세요. (<link>이곳</link>에서 생성하시거나, 아래 랜덤한 모양
|
||||
descIcon: "퍼즐의 아이콘으로 보여지게 될 짧은 단어를 지정해 주세요. (<link>이곳</link>에서 생성하시거나, 아래 랜덤한 모양
|
||||
중 하나를 선택하세요):"
|
||||
placeholderName: 퍼즐 제목
|
||||
puzzleResizeBadBuildings:
|
||||
@ -211,8 +206,7 @@ dialogs:
|
||||
desc: 오프라인 모드임으로 퍼즐을 저장하거나 업로드할 수 없습니다. 그래도 계속하시겠습니까?
|
||||
puzzlePlayRegularRecommendation:
|
||||
title: 권장 사항
|
||||
desc:
|
||||
퍼즐 DLC 플레이시 소개되지 않은 요소를 접하시게 될 수 있으므로, 적어도 일반 게임을 12레벨까지 플레이하시는것을
|
||||
desc: 퍼즐 DLC 플레이시 소개되지 않은 요소를 접하시게 될 수 있으므로, 적어도 일반 게임을 12레벨까지 플레이하시는것을
|
||||
<strong>강력히</strong> 권장드립니다. 그래도 계속하시겠습니까?
|
||||
puzzleShare:
|
||||
title: 짧은 키 복사됨
|
||||
@ -256,7 +250,7 @@ ingame:
|
||||
clearSelection: 지우기
|
||||
pipette: 피펫
|
||||
switchLayers: 레이어 전환
|
||||
clearBelts: Clear belts
|
||||
clearBelts: 벨트 청소하기
|
||||
buildingPlacement:
|
||||
cycleBuildingVariants: <key> 키를 눌러 변형 전환
|
||||
hotkeyLabel: "단축키: <key>"
|
||||
@ -312,31 +306,25 @@ ingame:
|
||||
waypoints:
|
||||
waypoints: 마커
|
||||
hub: 허브
|
||||
description:
|
||||
마커를 좌클릭하여 그곳으로 이동하고, 우클릭으로 삭제할 수 있습니다.<br><br>마커를 배치하기 위해
|
||||
description: 마커를 좌클릭하여 그곳으로 이동하고, 우클릭으로 삭제할 수 있습니다.<br><br>마커를 배치하기 위해
|
||||
<keybinding> 키로 지금 있는 위치에, 또는 <strong>우클릭</strong>하여 원하는 위치에 배치할 수
|
||||
있습니다.
|
||||
creationSuccessNotification: 마커가 성공적으로 생성되었습니다.
|
||||
interactiveTutorial:
|
||||
title: 튜토리얼
|
||||
hints:
|
||||
1_1_extractor:
|
||||
<strong>원형 도형</strong>을 추출하기 위해 그 위에 <strong>추출기</strong>를 선택한 뒤
|
||||
1_1_extractor: <strong>원형 도형</strong>을 추출하기 위해 그 위에 <strong>추출기</strong>를 선택한 뒤
|
||||
배치하여 추출하세요!
|
||||
1_2_conveyor:
|
||||
"이제 <strong>컨베이어 벨트</strong>를 추출기와 허브를 서로 연결하세요!<br><br> 팁: 벨트를
|
||||
1_2_conveyor: "이제 <strong>컨베이어 벨트</strong>를 추출기와 허브를 서로 연결하세요!<br><br> 팁: 벨트를
|
||||
마우스로 <strong>클릭한 뒤 드래그</strong>하세요!"
|
||||
1_3_expand:
|
||||
"이 게임은 방치형 게임이 <strong>아닙니다</strong>! 더 많은 추출기와 벨트를 만들어 지정된 목표를 빨리
|
||||
1_3_expand: "이 게임은 방치형 게임이 <strong>아닙니다</strong>! 더 많은 추출기와 벨트를 만들어 지정된 목표를 빨리
|
||||
달성하세요.<br><br> 팁: <strong>SHIFT</strong> 키를 누른 상태에서는 빠르게 배치할 수
|
||||
있고, <strong>R</strong> 키를 눌러 회전할 수 있습니다."
|
||||
2_1_place_cutter:
|
||||
"이제 <strong>절단기</strong>를 배치해 원형 도형을 반으로 잘라보세요!<br><br> 참고:
|
||||
2_1_place_cutter: "이제 <strong>절단기</strong>를 배치해 원형 도형을 반으로 잘라보세요!<br><br> 참고:
|
||||
절단기는 놓는 방향에 상관없이 항상 <strong>위에서 아래로만</strong> 자릅니다."
|
||||
2_2_place_trash: 절단기가 <strong>막히거나 멈출 수 있습니다</strong>!<br><br>
|
||||
<strong>휴지통</strong>을 사용하여 현재 필요없는 쓰레기 도형 (!)을 제거하세요.
|
||||
2_3_more_cutters:
|
||||
"잘하셨습니다! 느린 처리 속도를 보완하기 위해 <strong>절단기를 두 개</strong> 이상
|
||||
2_3_more_cutters: "잘하셨습니다! 느린 처리 속도를 보완하기 위해 <strong>절단기를 두 개</strong> 이상
|
||||
배치해보세요!<br><br> 추신: <strong>상단 숫자 단축키 (0~9)</strong>를 사용하여 건물을
|
||||
빠르게 선택할 수 있습니다!"
|
||||
3_1_rectangles: "이제 사각형 도형을 추출해 볼까요! <strong>추출기 네 개를 배치</strong>하고 허브와
|
||||
@ -344,12 +332,10 @@ ingame:
|
||||
누른 채 드래그하세요!"
|
||||
21_1_place_quad_painter: <strong>4단 색칠기</strong>를 배치하여 <strong>흰색</strong>과
|
||||
<strong>빨간색</strong>이 칠해진 <strong>원형 도형</strong>을 만들어보세요!
|
||||
21_2_switch_to_wires:
|
||||
<strong>E 키</strong>를 눌러 전선 레이어 로 전환하세요!<br><br> 그 후 색칠기의
|
||||
21_2_switch_to_wires: <strong>E 키</strong>를 눌러 전선 레이어 로 전환하세요!<br><br> 그 후 색칠기의
|
||||
<strong>네 입력 부분</strong>을 모두 케이블로 연결하세요!
|
||||
21_3_place_button: 훌륭해요! 이제 <strong>스위치</strong>를 배치하고 전선으로 연결하세요!
|
||||
21_4_press_button:
|
||||
"스위치를 눌러서 색칠기에 <strong>참 신호를 보내</strong> 활성화해보세요.<br><br> 추신:
|
||||
21_4_press_button: "스위치를 눌러서 색칠기에 <strong>참 신호를 보내</strong> 활성화해보세요.<br><br> 추신:
|
||||
모든 입력을 연결할 필요는 없습니다! 두개만 연결해 보세요."
|
||||
colors:
|
||||
red: 빨간색
|
||||
@ -429,6 +415,7 @@ ingame:
|
||||
titleRatingDesc: 당신의 평가는 제가 미래에 더 나은 평가를 만들수 있도록 도울 수 있습니다.
|
||||
continueBtn: 계속 플레이하기
|
||||
menuBtn: 메뉴
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: 제작자
|
||||
shortKey: 짧은 키
|
||||
@ -475,13 +462,11 @@ buildings:
|
||||
cutter:
|
||||
default:
|
||||
name: 절단기
|
||||
description:
|
||||
도형을 수직으로 잘라 두 가지 도형으로 나눕니다. <strong>한쪽만 사용할 경우라면 다른 부분을 파괴하지 않을 경우
|
||||
description: 도형을 수직으로 잘라 두 가지 도형으로 나눕니다. <strong>한쪽만 사용할 경우라면 다른 부분을 파괴하지 않을 경우
|
||||
절단기가 막혀 멈추게 됩니다!</strong>
|
||||
quad:
|
||||
name: 4단 절단기
|
||||
description:
|
||||
도형을 즉시 네 개로 자릅니다. <strong>한쪽만 사용할 경우라면 다른 부분을 파괴하지 않을 경우 절단기가 막혀
|
||||
description: 도형을 즉시 네 개로 자릅니다. <strong>한쪽만 사용할 경우라면 다른 부분을 파괴하지 않을 경우 절단기가 막혀
|
||||
멈추게 됩니다!</strong>
|
||||
rotater:
|
||||
default:
|
||||
@ -496,8 +481,7 @@ buildings:
|
||||
stacker:
|
||||
default:
|
||||
name: 결합기
|
||||
description:
|
||||
도형을 서로 결합하고 쌓습니다. 서로 결합할 수 있다면 두 도형을 붙여 하나로 만들고, 그렇지 않으면 오른쪽 도형이 왼쪽
|
||||
description: 도형을 서로 결합하고 쌓습니다. 서로 결합할 수 있다면 두 도형을 붙여 하나로 만들고, 그렇지 않으면 오른쪽 도형이 왼쪽
|
||||
도형 위에 쌓이게 됩니다.
|
||||
mixer:
|
||||
default:
|
||||
@ -512,8 +496,7 @@ buildings:
|
||||
description: 색소를 이용해 도형을 색칠합니다. 위쪽에서 받는 색소로 왼쪽에서 받는 도형 전체를 색칠합니다.
|
||||
quad:
|
||||
name: 4단 색칠기
|
||||
description:
|
||||
도형의 각 사분면에 개별적으로 색상을 칠할 수 있습니다. 전선 레이어를 통해 <strong>참 신호</strong>가
|
||||
description: 도형의 각 사분면에 개별적으로 색상을 칠할 수 있습니다. 전선 레이어를 통해 <strong>참 신호</strong>가
|
||||
있는 슬롯만 칠해집니다!
|
||||
mirrored:
|
||||
name: 색칠기
|
||||
@ -560,8 +543,7 @@ buildings:
|
||||
lever:
|
||||
default:
|
||||
name: 스위치
|
||||
description:
|
||||
전선 레이어에서 불 값 (1 또는 0)을 방출하도록 전환할 수 있으며, 그 후 아이템 선별같은 구성 요소를 제어하는 데
|
||||
description: 전선 레이어에서 불 값 (1 또는 0)을 방출하도록 전환할 수 있으며, 그 후 아이템 선별같은 구성 요소를 제어하는 데
|
||||
사용될 수 있습니다.
|
||||
logic_gate:
|
||||
default:
|
||||
@ -572,8 +554,7 @@ buildings:
|
||||
description: 입력이 거짓일 경우 불 값 "1"을 내보냅니다 (참은 도형, 색상, 불 값 "1"을 의미합니다).
|
||||
xor:
|
||||
name: XOR 회로
|
||||
description:
|
||||
입력 중 하나만 참이고 둘 다 같지 않을 경우 불 값 "1"을 내보냅니다 (참은 도형, 색상, 불 값 "1"을
|
||||
description: 입력 중 하나만 참이고 둘 다 같지 않을 경우 불 값 "1"을 내보냅니다 (참은 도형, 색상, 불 값 "1"을
|
||||
의미합니다).
|
||||
or:
|
||||
name: OR 회로
|
||||
@ -640,8 +621,7 @@ buildings:
|
||||
storyRewards:
|
||||
reward_cutter_and_trash:
|
||||
title: 절단기
|
||||
desc:
|
||||
<strong>절단기</strong>가 잠금 해제되었습니다! 절단기는 들어오는 도형이 어떤 모양을 하고 있던 수직으로 잘라
|
||||
desc: <strong>절단기</strong>가 잠금 해제되었습니다! 절단기는 들어오는 도형이 어떤 모양을 하고 있던 수직으로 잘라
|
||||
<strong>반으로 나눕니다</strong>!<br><br> 쓰지 않는 도형은 쓰레기로 처리하세요, 그렇지 않으면
|
||||
<strong>작동을 멈출 것입니다</strong>! 이러한 목적을 위해 <strong>휴지통</strong>도 함께
|
||||
지급되었습니다. 휴지통에 들어간 것은 모두 파괴됩니다!
|
||||
@ -650,8 +630,7 @@ storyRewards:
|
||||
desc: <strong>회전기</strong>가 잠금 해제되었습니다! 회전기는 들어오는 도형을 시계 방향으로 90도 회전시켜줍니다.
|
||||
reward_painter:
|
||||
title: 색칠기
|
||||
desc:
|
||||
"<strong>색칠기</strong>가 잠금 해제되었습니다! 도형과 마찬가지로 색소를 추출하고 색칠기에 넣거 도형과 결합하여 색칠된
|
||||
desc: "<strong>색칠기</strong>가 잠금 해제되었습니다! 도형과 마찬가지로 색소를 추출하고 색칠기에 넣거 도형과 결합하여 색칠된
|
||||
도형을 만들도록 하세요!<br><br>추신: 만약 당신이 색맹이라면, 설정에서 <strong>색맹 모드</strong>를
|
||||
활성화하세요!"
|
||||
reward_mixer:
|
||||
@ -660,28 +639,24 @@ storyRewards:
|
||||
색소</strong>를 얻을 수 있습니다!
|
||||
reward_stacker:
|
||||
title: 결합기
|
||||
desc:
|
||||
<strong>결합기</strong>가 잠금 해제되었습니다! 이제 결합기를 통해 여러 도형을 붙이고 결합할 수 있습니다! 들어오는 두
|
||||
desc: <strong>결합기</strong>가 잠금 해제되었습니다! 이제 결합기를 통해 여러 도형을 붙이고 결합할 수 있습니다! 들어오는 두
|
||||
도형의 모양이 서로 나란히 붙일 수 있다면, 하나의 도형으로 <strong>결합</strong>됩니다. 만약 서로
|
||||
겹쳐진다면, 오른쪽 도형이 왼쪽 도형의 <strong>위에 쌓이게</strong> 됩니다!
|
||||
reward_splitter:
|
||||
title: 압축형 분배기
|
||||
desc:
|
||||
<strong>밸런서</strong>의 새로운 형태인 <strong>분배기</strong>가 잠금 해제되었습니다! 이제 벨트 한 줄을
|
||||
desc: <strong>밸런서</strong>의 새로운 형태인 <strong>분배기</strong>가 잠금 해제되었습니다! 이제 벨트 한 줄을
|
||||
즉시 두 줄로 분배합니다!
|
||||
reward_tunnel:
|
||||
title: 터널
|
||||
desc: <strong>터널</strong>이 잠금 해제되었습니다! 이제 벨트와 건물 아래로 공간을 만들어내 옮길 수 있습니다!
|
||||
reward_rotater_ccw:
|
||||
title: 반시계 방향 회전기
|
||||
desc:
|
||||
<strong>반시계 방향 회전기</strong>가 잠금 해제되었습니다! 반시계 방향 회전기는 회전기의 다른 형태로, 이름처럼
|
||||
desc: <strong>반시계 방향 회전기</strong>가 잠금 해제되었습니다! 반시계 방향 회전기는 회전기의 다른 형태로, 이름처럼
|
||||
들어오는 도형을 반시계 방향으로 90도만큼 회전시킵니다! 제작하려면 회전기를 선택한 후 <strong>'T' 키를 눌러
|
||||
다른 형태로 전환</strong>하세요!
|
||||
reward_miner_chainable:
|
||||
title: 연쇄 추출기
|
||||
desc:
|
||||
"<strong>연쇄 추출기</strong>가 잠금 해제되었습니다! 자원을 보다 더욱 효율적으로 추출할 수 있도록 <strong>앞에
|
||||
desc: "<strong>연쇄 추출기</strong>가 잠금 해제되었습니다! 자원을 보다 더욱 효율적으로 추출할 수 있도록 <strong>앞에
|
||||
있는 추출기로 자원을 보낼 수 있습니다</strong>!<br><br> 추신: 이제 툴바에 있는 기존 추출기는 연쇄
|
||||
추출기로 대체되었습니다!"
|
||||
reward_underground_belt_tier_2:
|
||||
@ -690,18 +665,15 @@ storyRewards:
|
||||
거리</strong>를 운송할 수 있고 기존 터널과 겹쳐지지 않고도 자원을 보낼 수 있습니다!
|
||||
reward_cutter_quad:
|
||||
title: 4단 절단기
|
||||
desc:
|
||||
새로운 종류의 <strong>절단기</strong>가 잠금 해제되었습니다! 4단 절단기는 도형을 두 조각이 아닌 <strong>네
|
||||
desc: 새로운 종류의 <strong>절단기</strong>가 잠금 해제되었습니다! 4단 절단기는 도형을 두 조각이 아닌 <strong>네
|
||||
조각</strong>으로 자를 수 있습니다!
|
||||
reward_painter_double:
|
||||
title: 2단 색칠기
|
||||
desc:
|
||||
새로운 종류의 <strong>절단기</strong>가 잠금 해제되었습니다! 일반적인 색칠기와 거의 동일하지만, 하나의 색소를 사용하여
|
||||
desc: 새로운 종류의 <strong>절단기</strong>가 잠금 해제되었습니다! 일반적인 색칠기와 거의 동일하지만, 하나의 색소를 사용하여
|
||||
<strong>동시에 두 개의 도형을 색칠</strong>할 수 있습니다!
|
||||
reward_storage:
|
||||
title: 저장고
|
||||
desc:
|
||||
<strong>저장고</strong>가 잠금 해제되었습니다! 저장고는 최대 용량까지 도형을 저장할 수 있습니다!<br><br> 왼쪽
|
||||
desc: <strong>저장고</strong>가 잠금 해제되었습니다! 저장고는 최대 용량까지 도형을 저장할 수 있습니다!<br><br> 왼쪽
|
||||
출력이 우선되므로 <strong>오버플로 회로</strong>로도 활용될 수 있습니다!
|
||||
reward_freeplay:
|
||||
title: 자유플레이
|
||||
@ -711,38 +683,32 @@ storyRewards:
|
||||
레이어를 통해 내보내므로 이를 분석하는 구조를 기반으로 하여 공장을 자동으로 구성하기만 하면 됩니다.
|
||||
reward_blueprints:
|
||||
title: 청사진
|
||||
desc:
|
||||
이제 공장의 일부를 <strong>복사하고 붙여넣는 기능</strong>을 사용할 수 있습니다! 영역을 선택 (CTRL 키를 누른 채
|
||||
desc: 이제 공장의 일부를 <strong>복사하고 붙여넣는 기능</strong>을 사용할 수 있습니다! 영역을 선택 (CTRL 키를 누른 채
|
||||
마우스로 드래그)한 뒤 'C' 키를 눌러 복사할 수 있습니다.<br><br>하지만 <strong>공짜는
|
||||
아닙니다</strong>, <strong>청사진 모양 도형</strong>을 허브에 저장하고 그것을 일부 사용해 붙여넣기
|
||||
기능을 사용할 수 있습니다! (방금 당신이 만든 것입니다.)
|
||||
no_reward:
|
||||
title: 다음 레벨
|
||||
desc:
|
||||
"이번 레벨의 보상은 없네요. 대신 다음 레벨에서 줄겁니다!<br><br> 추신: 기존 공장을 파괴하지는 마세요. 후에
|
||||
desc: "이번 레벨의 보상은 없네요. 대신 다음 레벨에서 줄겁니다!<br><br> 추신: 기존 공장을 파괴하지는 마세요. 후에
|
||||
<strong>업그레이드 잠금 해제</strong>되면 <strong>기존의 모든</strong> 도형이 필요합니다!"
|
||||
no_reward_freeplay:
|
||||
title: 다음 레벨
|
||||
desc: 축하드립니다!
|
||||
reward_balancer:
|
||||
title: 밸런서
|
||||
desc:
|
||||
<strong>밸런서</strong>가 잠금 해제되었습니다! 다목적 밸런서를 통해 여러 벨트의 아이템을 서로 <strong>다른
|
||||
desc: <strong>밸런서</strong>가 잠금 해제되었습니다! 다목적 밸런서를 통해 여러 벨트의 아이템을 서로 <strong>다른
|
||||
벨트로 분할하거나 합침</strong>으로써 더욱 거대한 공장을 만들 수 있습니다!
|
||||
reward_merger:
|
||||
title: 압축형 병합기
|
||||
desc:
|
||||
<strong>밸런서</strong>의 새로운 형태인 <strong>병합기</strong>가 잠금 해제되었습니다! 이제 벨트 두 줄을
|
||||
desc: <strong>밸런서</strong>의 새로운 형태인 <strong>병합기</strong>가 잠금 해제되었습니다! 이제 벨트 두 줄을
|
||||
즉시 한 줄로 병합합니다!
|
||||
reward_belt_reader:
|
||||
title: 벨트 판독기
|
||||
desc:
|
||||
<strong>벨트 판독기</strong>가 잠금 해제되었습니다! 이제 벨트의 처리량을 확인할 수 있습니다.<br><br>그리고,
|
||||
desc: <strong>벨트 판독기</strong>가 잠금 해제되었습니다! 이제 벨트의 처리량을 확인할 수 있습니다.<br><br>그리고,
|
||||
전선이 잠금 해제될 때 까지 기다리신다면 정말 유용하게 사용할 수 있을 겁니다!
|
||||
reward_rotater_180:
|
||||
title: 180도 회전기
|
||||
desc:
|
||||
<strong>180도 회전기</strong>가 잠금 해제되었습니다! 이제 도형을 바로 180도로 회전시킬 수 있습니다. (짜잔!
|
||||
desc: <strong>180도 회전기</strong>가 잠금 해제되었습니다! 이제 도형을 바로 180도로 회전시킬 수 있습니다. (짜잔!
|
||||
:D)
|
||||
reward_display:
|
||||
title: 디스플레이
|
||||
@ -750,37 +716,32 @@ storyRewards:
|
||||
있습니다.<br><br> 추신: 벨트 판독기와 저장고가 마지막으로 읽은 아이템을 출력했나요? 디스플레이로 한번 봐보세요!"
|
||||
reward_constant_signal:
|
||||
title: 일정 신호기
|
||||
desc:
|
||||
전선 레이어에서 구축할 수 있는 <strong>일정 신호기</strong>가 잠금 해제되었습니다! 간단한 예시로,
|
||||
desc: 전선 레이어에서 구축할 수 있는 <strong>일정 신호기</strong>가 잠금 해제되었습니다! 간단한 예시로,
|
||||
<strong>아이템 선별</strong>에 연결하여 사용하는 데 유용합니다.<br><br> 일정 신호기는
|
||||
<strong>도형</strong>, <strong>색상</strong>, 또는 <strong>불 값</strong> (1
|
||||
또는 0)을 출력할 수 있습니다.
|
||||
reward_logic_gates:
|
||||
title: 논리 회로
|
||||
desc:
|
||||
<strong>논리 회로</strong>가 잠금 해제되었습니다! 굳이 흥분할 필요는 없지만, 진짜 멋진 기술입니다!<br><br>
|
||||
desc: <strong>논리 회로</strong>가 잠금 해제되었습니다! 굳이 흥분할 필요는 없지만, 진짜 멋진 기술입니다!<br><br>
|
||||
논리 회로를 통해 이제 AND, OR, XOR, NOT 논리 연산을 할 수 있습니다.<br><br> 보너스로,
|
||||
<strong>트랜지스터</strong>도 지급되었습니다!
|
||||
reward_virtual_processing:
|
||||
title: 가상 처리
|
||||
desc:
|
||||
<strong>도형의 처리를 시뮬레이션</strong>할 수 있는 다양한 새로운 건물이 잠금 해제되었습니다!<br><br> 이제 전선
|
||||
desc: <strong>도형의 처리를 시뮬레이션</strong>할 수 있는 다양한 새로운 건물이 잠금 해제되었습니다!<br><br> 이제 전선
|
||||
레이어에서 도형에 대한 절단기, 회전기, 결합기 등을 가상으로 시뮬레이션할 수 있습니다! 이제 게임 진행에 있어 다음 세
|
||||
가지의 방법이 존재합니다:<br><br> - <strong>완전 자동화된 기계</strong>를 구축하고 허브에서 요구되는
|
||||
도형을 제작합니다. (먼저 시도해볼 것을 권합니다!).<br><br> - 전선을 통해 멋진 것들 만듭니다.<br><br>
|
||||
- 평소처럼 게임을 진행합니다.<br><br> 어떤 방식으로든, 재미있게 게임을 플레이해주시길 바랍니다!
|
||||
reward_wires_painter_and_levers:
|
||||
title: 전선과 4단 색칠기
|
||||
desc:
|
||||
" 방금 <strong>전선 레이어</strong>를 활성화하셨습니다: 이것은 일반 레이어 위에 존재하는 별개의 레이어로 수많은
|
||||
desc: " 방금 <strong>전선 레이어</strong>를 활성화하셨습니다: 이것은 일반 레이어 위에 존재하는 별개의 레이어로 수많은
|
||||
새로운 요소를 사용할 수 있습니다!<br><br> <strong>4단 색칠기</strong>를 활성화해 드리겠습니다 -
|
||||
전선 레이어에서 색을 칠할 부분에 연결해 보세요!<br><br> 전선 레이어로 전환하시려면
|
||||
<strong>E</strong>키를 눌러주세요.<br><br> 추신: <strong>힌트를 활성화</strong>해서
|
||||
전선 튜토리얼을 활성화해 보세요!"
|
||||
reward_filter:
|
||||
title: 아이템 선별기
|
||||
desc:
|
||||
<strong>아이템 선별기</strong>가 잠금 해제되었습니다! 전선 레이어의 신호와 일치하는지에 대한 여부로 아이템을 위쪽
|
||||
desc: <strong>아이템 선별기</strong>가 잠금 해제되었습니다! 전선 레이어의 신호와 일치하는지에 대한 여부로 아이템을 위쪽
|
||||
출력이나 오른쪽 출력으로 보냅니다.<br><br> 불 값 (1 또는 0)을 전달하여 완전히 활성화과 비활성화를 전환할 수
|
||||
있습니다.
|
||||
reward_demo_end:
|
||||
@ -801,8 +762,7 @@ settings:
|
||||
labels:
|
||||
uiScale:
|
||||
title: UI 크기
|
||||
description:
|
||||
사용자 인터페이스의 크기를 변경합니다. 인터페이스는 당신의 해상도에 따라 확장되는데 이 설정은 그 확장의 정도를
|
||||
description: 사용자 인터페이스의 크기를 변경합니다. 인터페이스는 당신의 해상도에 따라 확장되는데 이 설정은 그 확장의 정도를
|
||||
제어합니다.
|
||||
scales:
|
||||
super_small: 매우 작게
|
||||
@ -849,18 +809,15 @@ settings:
|
||||
light: 라이트
|
||||
refreshRate:
|
||||
title: 틱 빈도
|
||||
description:
|
||||
이것은 초당 발생하는 게임 틱 수를 결정합니다. 일반적으로 틱 속도가 높을수록 정밀도는 향상되나 성능은 낮아집니다. 낮은
|
||||
description: 이것은 초당 발생하는 게임 틱 수를 결정합니다. 일반적으로 틱 속도가 높을수록 정밀도는 향상되나 성능은 낮아집니다. 낮은
|
||||
틱 빈도에서는 처리량이 정확하지 않을 수 있습니다.
|
||||
alwaysMultiplace:
|
||||
title: 다수 배치 항시 켜기
|
||||
description:
|
||||
활성화할 경우 모든 건물은 배치한 후 취소할 때 까지 커서에 선택된 상태를 유지합니다. 이 기능은 SHIFT 키를 계속
|
||||
description: 활성화할 경우 모든 건물은 배치한 후 취소할 때 까지 커서에 선택된 상태를 유지합니다. 이 기능은 SHIFT 키를 계속
|
||||
누르는 것과 같습니다.
|
||||
offerHints:
|
||||
title: 힌트와 튜토리얼
|
||||
description:
|
||||
게임 플레이하는 동안 힌트와 튜토리얼을 보여줄 지를 결정합니다. 또한 게임에 더 쉽게 빠져들 수 있도록 특정 레벨까지
|
||||
description: 게임 플레이하는 동안 힌트와 튜토리얼을 보여줄 지를 결정합니다. 또한 게임에 더 쉽게 빠져들 수 있도록 특정 레벨까지
|
||||
특정한 UI 요소를 숨깁니다.
|
||||
enableTunnelSmartplace:
|
||||
title: 지능적인 터널 배치
|
||||
@ -889,8 +846,7 @@ settings:
|
||||
description: 색맹 사용자를 위해 게임을 플레이하는 데 도움을 주는 다양한 도구를 활성화합니다.
|
||||
rotationByBuilding:
|
||||
title: 건물 유형에 따른 방향
|
||||
description:
|
||||
각 건물 유형마다 개별적으로 마지막으로 설정했던 방향을 기억하도록 합니다. 다른 건물 변형을 자주 전환하는 경우 이
|
||||
description: 각 건물 유형마다 개별적으로 마지막으로 설정했던 방향을 기억하도록 합니다. 다른 건물 변형을 자주 전환하는 경우 이
|
||||
방법이 더욱 편할 수 있습니다.
|
||||
soundVolume:
|
||||
title: 효과음 볼륨
|
||||
@ -906,8 +862,7 @@ settings:
|
||||
description: 성능 향상을 위해 타일 그리드를 비활성화할 수 있습니다. 이 역시 게임을 더욱 깨끗하게 보여줍니다!
|
||||
clearCursorOnDeleteWhilePlacing:
|
||||
title: 우클릭 시 커서 지우기
|
||||
description:
|
||||
기본적으로 활성화되어 있으며, 배치할 건물을 선택한 상태에서 마우스 우클릭 시 커서를 지웁니다. 비활성화할 경우, 건물을
|
||||
description: 기본적으로 활성화되어 있으며, 배치할 건물을 선택한 상태에서 마우스 우클릭 시 커서를 지웁니다. 비활성화할 경우, 건물을
|
||||
커서에 선택한 채로 우클릭하면 바로 건물을 삭제할 수 있습니다.
|
||||
lowQualityTextures:
|
||||
title: 저품질 텍스처 (못생김)
|
||||
@ -920,8 +875,7 @@ settings:
|
||||
description: 기본적으로 활성화되어 있으며, 자원 패치에서 피펫 기능을 사용 시 즉시 추출기를 선택합니다.
|
||||
simplifiedBelts:
|
||||
title: 벨트 단순화 (못생김)
|
||||
description:
|
||||
성능 향상을 위해 벨트를 가리킬 때를 제외한 모든 상황에서 벨트 아이템을 렌더링하지 않습니다. 이 기능을 사용할 정도로
|
||||
description: 성능 향상을 위해 벨트를 가리킬 때를 제외한 모든 상황에서 벨트 아이템을 렌더링하지 않습니다. 이 기능을 사용할 정도로
|
||||
심각한 성능 문제가 일어나지 않는 한, 이 설정을 사용할 필요는 없습니다.
|
||||
enableMousePan:
|
||||
title: 화면 가장자리 패닝
|
||||
@ -932,7 +886,12 @@ settings:
|
||||
mapResourcesScale:
|
||||
title: 지도 자원 크기
|
||||
description: 지도를 축소할 때 나타나는 도형의 크기를 제어합니다.
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
rangeSliderPercentage: <amount> %
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: 조작법
|
||||
hint: "팁: CTRL, SHIFT, ALT를 적절히 사용하세요! 건물을 배치할 때 유용합니다."
|
||||
@ -1013,6 +972,7 @@ keybindings:
|
||||
goal_acceptor: 목표 수집기
|
||||
block: 블록
|
||||
massSelectClear: 벨트 초기화
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: 게임 정보
|
||||
body: >-
|
||||
@ -1131,8 +1091,23 @@ puzzleMenu:
|
||||
easy: 쉬움
|
||||
medium: 중간
|
||||
hard: 어려움
|
||||
dlcHint: DLC를 이미 구입하셨나요? 라이브러리에서 shapez.io를 오른쪽 클릭한 다음
|
||||
속성… > DLC 메뉴를 선택해서 활성화되었는지 확인해주세요.
|
||||
unknown: Unrated
|
||||
dlcHint: DLC를 이미 구입하셨나요? 라이브러리에서 shapez.io를 오른쪽 클릭한 다음 속성… > DLC 메뉴를 선택해서
|
||||
활성화되었는지 확인해주세요.
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: 너무 빠른 시간 내 작업을 반복하고 있습니다. 조금만 기다려 주세요.
|
||||
invalid-api-key: 백엔드 서버와 통신할 수 없습니다. 게임을 업데이트하거나 재시작해 주세요 (잘못된 API 키).
|
||||
|
||||
@ -457,6 +457,7 @@ ingame:
|
||||
titleRatingDesc: Your rating will help me to make you better suggestions in the future
|
||||
continueBtn: Keep Playing
|
||||
menuBtn: Menu
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Author
|
||||
shortKey: Short Key
|
||||
@ -1003,7 +1004,12 @@ settings:
|
||||
title: Map Resources Size
|
||||
description: Controls the size of the shapes on the map overview (when zooming
|
||||
out).
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
rangeSliderPercentage: <amount> %
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: Keybindings
|
||||
hint: "Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different
|
||||
@ -1085,6 +1091,7 @@ keybindings:
|
||||
goal_acceptor: Goal Acceptor
|
||||
block: Block
|
||||
massSelectClear: Clear belts
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: About this Game
|
||||
body: >-
|
||||
@ -1212,8 +1219,23 @@ puzzleMenu:
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
unknown: Unrated
|
||||
dlcHint: Purchased the DLC already? Make sure it is activated by right clicking
|
||||
shapez.io in your library, selecting Properties > DLCs.
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: You are performing your actions too frequent. Please wait a bit.
|
||||
invalid-api-key: Failed to communicate with the backend, please try to
|
||||
|
||||
@ -14,7 +14,7 @@ steamPage:
|
||||
Ondanks het feit dat je in het begin alleen vormen maakt, komt er een punt waarop je ze gaat kleuren. Deze kleuren kun je vinden en mengen!
|
||||
|
||||
Door het spel op Steam te kopen kun je de volledige versie spelen. Je kunt echter ook een demo versie spelen op shapez.io en later beslissen om over te schakelen zonder voortgang te verliezen.
|
||||
what_others_say: What people say about shapez.io
|
||||
what_others_say: Wat anderen vinden van shapez.io
|
||||
nothernlion_comment: This game is great - I'm having a wonderful time playing,
|
||||
and time has flown by.
|
||||
notch_comment: Oh crap. I really should sleep, but I think I just figured out
|
||||
@ -475,6 +475,7 @@ ingame:
|
||||
te geven
|
||||
continueBtn: Blijf Spelen
|
||||
menuBtn: Menu
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Auteur
|
||||
shortKey: Vorm Sleutel
|
||||
@ -1033,7 +1034,12 @@ settings:
|
||||
title: Kaartbronnen schaal
|
||||
description: Controleert de grootte van de vormen op het map overzicht (wanneer
|
||||
je uitzoomt).
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
rangeSliderPercentage: <amount> %
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: Sneltoetsen
|
||||
hint: "Tip: Maak gebruik van CTRL, SHIFT en ALT! Hiermee kun je dingen anders en
|
||||
@ -1115,6 +1121,7 @@ keybindings:
|
||||
goal_acceptor: Ontvanger
|
||||
block: Blokkade
|
||||
massSelectClear: Lopende banden leeg maken
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: Over dit spel
|
||||
body: >-
|
||||
@ -1166,14 +1173,12 @@ tips:
|
||||
wordt de planner geactiveerd, zodat je gemakkelijk lange rijen kunt
|
||||
plaatsen.
|
||||
- Knippers knippen altijd verticaal, ongeacht hun oriëntatie.
|
||||
- Meng alle drie de kleuren om wit te krijgen.
|
||||
- De opslagbuffer geeft prioriteit aan de eerste uitvoer.
|
||||
- Investeer tijd om herhaalbare ontwerpen te maken - het is het waard!
|
||||
- Door <b>SHIFT</b> ingedrukt te houden, kunnen meerdere gebouwen worden
|
||||
geplaatst.
|
||||
- Invest time to build repeatable designs - it's worth it!
|
||||
- Je kunt <b>ALT</b> ingedrukt houden om de richting van de geplaatste
|
||||
lopende banden om te keren.
|
||||
- Efficiëntie is de sleutel!
|
||||
- You can hold <b>ALT</b> to invert the direction of placed belts.
|
||||
- Vormontginningen die verder van de HUB verwijderd zijn, zijn complexer.
|
||||
- Machines hebben een beperkte snelheid, verdeel ze voor maximale
|
||||
efficiëntie.
|
||||
@ -1196,8 +1201,8 @@ tips:
|
||||
mannen.
|
||||
- Maak een aparte blueprint fabriek. Ze zijn belangrijk voor modules.
|
||||
- Bekijk de kleurenmixer eens wat beter, en je vragen worden beantwoord.
|
||||
- Gebruik <b>CTRL</b> + klik om een gebied te selecteren.
|
||||
- Te dicht bij de HUB bouwen kan latere projecten in de weg staan.
|
||||
- Have a closer look at the color mixer, and your questions will be answered.
|
||||
- Use <b>CTRL</b> + Click to select an area.
|
||||
- Met het speldpictogram naast elke vorm in de upgradelijst zet deze vast op
|
||||
het scherm.
|
||||
- Meng alle primaire kleuren door elkaar om wit te maken!
|
||||
@ -1216,6 +1221,7 @@ tips:
|
||||
- Druk twee keer op F4 om de tegel van je muis en camera weer te geven.
|
||||
- Je kan aan de linkerkant op een vastgezette vorm klikken om deze los te
|
||||
maken.
|
||||
- You can click a pinned shape on the left side to unpin it.
|
||||
puzzleMenu:
|
||||
play: Spelen
|
||||
edit: Bewerken
|
||||
@ -1261,6 +1267,21 @@ puzzleMenu:
|
||||
easy: Makkelijk
|
||||
medium: Medium
|
||||
hard: Moeilijk
|
||||
unknown: Unrated
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: Je voert je handelingen te vaak uit. Wacht alstublieft even.
|
||||
invalid-api-key: Kan niet communiceren met de servers, probeer alstublieft het
|
||||
|
||||
@ -464,6 +464,7 @@ ingame:
|
||||
fremtiden
|
||||
continueBtn: Fortsett å spill
|
||||
menuBtn: Meny
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Laget av
|
||||
shortKey: Kort Kode
|
||||
@ -1022,7 +1023,12 @@ settings:
|
||||
title: Kart Ressursser Størrelse
|
||||
description: Kontrollerer størrelsen på former på kartoversikten (når zoomet
|
||||
ut).
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
rangeSliderPercentage: <amount> %
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: Hurtigtaster
|
||||
hint: "Tips: Husk å bruke CTRL, SHIFT and ALT! De gir deg flere
|
||||
@ -1104,6 +1110,7 @@ keybindings:
|
||||
goal_acceptor: Mål Mottaker
|
||||
block: Blokker
|
||||
massSelectClear: Tøm Belter
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: Om dette spillet
|
||||
body: >-
|
||||
@ -1236,8 +1243,23 @@ puzzleMenu:
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
unknown: Unrated
|
||||
dlcHint: Purchased the DLC already? Make sure it is activated by right clicking
|
||||
shapez.io in your library, selecting Properties > DLCs.
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: Du gjør en handling for ofte. Vennligst vent litt.
|
||||
invalid-api-key: Kunne ikke kommunisere med kjernen, vennligst prøv å
|
||||
|
||||
@ -465,6 +465,7 @@ ingame:
|
||||
titleRatingDesc: Your rating will help me to make you better suggestions in the future
|
||||
continueBtn: Keep Playing
|
||||
menuBtn: Menu
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Author
|
||||
shortKey: Short Key
|
||||
@ -1029,7 +1030,12 @@ settings:
|
||||
title: Rozmiar mapy zasobów
|
||||
description: Steruje rozmiarem kształtów w przeglądzie mapy (podczas
|
||||
pomniejszenia).
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
rangeSliderPercentage: <amount> %
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: Klawiszologia
|
||||
hint: "Wskazówka: Upewnij się, że wykorzystujesz CTRL, SHIFT i ALT! Pozwalają na
|
||||
@ -1111,6 +1117,7 @@ keybindings:
|
||||
goal_acceptor: Goal Acceptor
|
||||
block: Block
|
||||
massSelectClear: Clear belts
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: O Grze
|
||||
body: 'Ta gra jest open-source. Rozwijana jest przez <a
|
||||
@ -1251,8 +1258,23 @@ puzzleMenu:
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
unknown: Unrated
|
||||
dlcHint: Purchased the DLC already? Make sure it is activated by right clicking
|
||||
shapez.io in your library, selecting Properties > DLCs.
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: You are performing your actions too frequent. Please wait a bit.
|
||||
invalid-api-key: Failed to communicate with the backend, please try to
|
||||
|
||||
@ -466,6 +466,7 @@ ingame:
|
||||
titleRatingDesc: Sua avaliação me ajuda a te fazer sugestões melhores no futuro!
|
||||
continueBtn: Continuar jogando
|
||||
menuBtn: Menu
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Autor
|
||||
shortKey: Código
|
||||
@ -1038,7 +1039,12 @@ settings:
|
||||
title: Tamanho do Mapa de Recursos
|
||||
description: Controla o tamanho das formas no mapa de panorama (quando afasta o
|
||||
zoom).
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
rangeSliderPercentage: <amount> %
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: Controles
|
||||
hint: "Dica: Certifique-se de usar CTRL, SHIFT e ALT! Eles permitem diferentes
|
||||
@ -1120,6 +1126,7 @@ keybindings:
|
||||
goal_acceptor: Receptor de Objetivo
|
||||
block: Bloco
|
||||
massSelectClear: Limpar esteiras
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: Sobre o jogo
|
||||
body: >-
|
||||
@ -1257,8 +1264,23 @@ puzzleMenu:
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
unknown: Unrated
|
||||
dlcHint: Purchased the DLC already? Make sure it is activated by right clicking
|
||||
shapez.io in your library, selecting Properties > DLCs.
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: Você está fazendo coisas muito rapidamente. Por favor espere um pouco.
|
||||
invalid-api-key: Falha ao comunicar com o backend, por favor tente
|
||||
|
||||
@ -476,6 +476,7 @@ ingame:
|
||||
titleRatingDesc: A tua avaliação ajudar-me-á a fazer melhores sugestões no futuro
|
||||
continueBtn: Continua a Jogar
|
||||
menuBtn: Menu
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Autor
|
||||
shortKey: Pequeno Código
|
||||
@ -1047,7 +1048,12 @@ settings:
|
||||
title: Tamanho de Recursos no Mapa
|
||||
description: Controla o tamanho das formas na visão geral do mapa (aplicando
|
||||
zoom out).
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
rangeSliderPercentage: <amount> %
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: Atalhos
|
||||
hint: "Dica: Utiliza o CTRL, o SHIFT e o ALT! Eles permitem diferentes opções de
|
||||
@ -1129,6 +1135,7 @@ keybindings:
|
||||
goal_acceptor: Recetor de Objetivo
|
||||
block: Bloqueador
|
||||
massSelectClear: Limpar tapetes rolante
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: Sobre o Jogo
|
||||
body: >-
|
||||
@ -1268,8 +1275,23 @@ puzzleMenu:
|
||||
easy: Fácil
|
||||
medium: Médio
|
||||
hard: Difícil
|
||||
unknown: Unrated
|
||||
dlcHint: Purchased the DLC already? Make sure it is activated by right clicking
|
||||
shapez.io in your library, selecting Properties > DLCs.
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: Estás a realizar as tuas ações demasiado rápido. Aguarda um pouco.
|
||||
invalid-api-key: Falha ao cominucar com o backend, por favor tenta
|
||||
|
||||
@ -466,6 +466,7 @@ ingame:
|
||||
titleRatingDesc: Your rating will help me to make you better suggestions in the future
|
||||
continueBtn: Keep Playing
|
||||
menuBtn: Menu
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Author
|
||||
shortKey: Short Key
|
||||
@ -1024,7 +1025,12 @@ settings:
|
||||
title: Map Resources Size
|
||||
description: Controls the size of the shapes on the map overview (when zooming
|
||||
out).
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
rangeSliderPercentage: <amount> %
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: Tastele setate
|
||||
hint: "Indiciu: Asigură-te că foloseșto CTRL, SHIFT și ALT! Ele activează
|
||||
@ -1106,6 +1112,7 @@ keybindings:
|
||||
goal_acceptor: Goal Acceptor
|
||||
block: Block
|
||||
massSelectClear: Clear belts
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: Despre acest joc
|
||||
body: >-
|
||||
@ -1233,8 +1240,23 @@ puzzleMenu:
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
unknown: Unrated
|
||||
dlcHint: Purchased the DLC already? Make sure it is activated by right clicking
|
||||
shapez.io in your library, selecting Properties > DLCs.
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: You are performing your actions too frequent. Please wait a bit.
|
||||
invalid-api-key: Failed to communicate with the backend, please try to
|
||||
|
||||
@ -468,6 +468,7 @@ ingame:
|
||||
titleRatingDesc: Ваша оценка поможет мне в будущем делать вам лучшие предложения
|
||||
continueBtn: Продолжить игру
|
||||
menuBtn: Меню
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Автор
|
||||
shortKey: Короткий ключ
|
||||
@ -1031,6 +1032,11 @@ settings:
|
||||
mapResourcesScale:
|
||||
title: Размер ресурсов на карте
|
||||
description: Устанавливает размер фигур на карте (когда вид достаточно отдалён).
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: Настройки управления
|
||||
hint: "Подсказка: Обязательно используйте CTRL, SHIFT и ALT! Они дают разные
|
||||
@ -1108,10 +1114,11 @@ keybindings:
|
||||
placementDisableAutoOrientation: Отключить автоопределение направления
|
||||
placeMultiple: Оставаться в режиме размещения
|
||||
placeInverse: Инвертировать автоопределение направления конвейеров
|
||||
constant_producer: Constant Producer
|
||||
goal_acceptor: Goal Acceptor
|
||||
block: Block
|
||||
massSelectClear: Clear belts
|
||||
constant_producer: Постоянный генератор
|
||||
goal_acceptor: Приёмник предметов
|
||||
block: Блок
|
||||
massSelectClear: Очистить конвейеры
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: Об игре
|
||||
body: >-
|
||||
@ -1245,11 +1252,26 @@ puzzleMenu:
|
||||
постоянные производители не доставляют фигуры напрямую приемникам
|
||||
цели.
|
||||
difficulties:
|
||||
easy: Лего
|
||||
easy: Легко
|
||||
medium: Средне
|
||||
hard: Сложно
|
||||
dlcHint: Purchased the DLC already? Make sure it is activated by right clicking
|
||||
shapez.io in your library, selecting Properties > DLCs.
|
||||
unknown: Unrated
|
||||
dlcHint: Уже купили DLC? Проверьте, что оно активировано, нажав правый клик на
|
||||
shapez.io в своей библиотеке, и далее Свойства > Доп. Контент
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: Вы слишком часто выполняете свои действия. Подождите немного.
|
||||
invalid-api-key: Не удалось связаться с сервером, попробуйте
|
||||
|
||||
@ -459,6 +459,7 @@ ingame:
|
||||
titleRatingDesc: Your rating will help me to make you better suggestions in the future
|
||||
continueBtn: Keep Playing
|
||||
menuBtn: Menu
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Author
|
||||
shortKey: Short Key
|
||||
@ -1006,7 +1007,12 @@ settings:
|
||||
title: Map Resources Size
|
||||
description: Controls the size of the shapes on the map overview (when zooming
|
||||
out).
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
rangeSliderPercentage: <amount> %
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: Keybindings
|
||||
hint: "Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different
|
||||
@ -1088,6 +1094,7 @@ keybindings:
|
||||
goal_acceptor: Goal Acceptor
|
||||
block: Block
|
||||
massSelectClear: Clear belts
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: About this Game
|
||||
body: >-
|
||||
@ -1215,8 +1222,23 @@ puzzleMenu:
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
unknown: Unrated
|
||||
dlcHint: Purchased the DLC already? Make sure it is activated by right clicking
|
||||
shapez.io in your library, selecting Properties > DLCs.
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: You are performing your actions too frequent. Please wait a bit.
|
||||
invalid-api-key: Failed to communicate with the backend, please try to
|
||||
|
||||
@ -463,6 +463,7 @@ ingame:
|
||||
titleRatingDesc: Your rating will help me to make you better suggestions in the future
|
||||
continueBtn: Keep Playing
|
||||
menuBtn: Menu
|
||||
nextPuzzle: Next Puzzle
|
||||
puzzleMetadata:
|
||||
author: Author
|
||||
shortKey: Short Key
|
||||
@ -1014,7 +1015,12 @@ settings:
|
||||
title: Map Resources Size
|
||||
description: Controls the size of the shapes on the map overview (when zooming
|
||||
out).
|
||||
shapeTooltipAlwaysOn:
|
||||
title: Shape Tooltip - Show Always
|
||||
description: Whether to always show the shape tooltip when hovering buildings,
|
||||
instead of having to hold 'ALT'.
|
||||
rangeSliderPercentage: <amount> %
|
||||
tickrateHz: <amount> Hz
|
||||
keybindings:
|
||||
title: Snabbtangenter
|
||||
hint: "Tips: Se till att använda CTRL, SKIFT, och ALT! De låter dig använda
|
||||
@ -1096,6 +1102,7 @@ keybindings:
|
||||
goal_acceptor: Goal Acceptor
|
||||
block: Block
|
||||
massSelectClear: Clear belts
|
||||
showShapeTooltip: Show shape output tooltip
|
||||
about:
|
||||
title: Om detta spel
|
||||
body: >-
|
||||
@ -1223,8 +1230,23 @@ puzzleMenu:
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
unknown: Unrated
|
||||
dlcHint: Purchased the DLC already? Make sure it is activated by right clicking
|
||||
shapez.io in your library, selecting Properties > DLCs.
|
||||
search:
|
||||
action: Search
|
||||
placeholder: Enter a puzzle or author name
|
||||
includeCompleted: Include Completed
|
||||
difficulties:
|
||||
any: Any Difficulty
|
||||
easy: Easy
|
||||
medium: Medium
|
||||
hard: Hard
|
||||
durations:
|
||||
any: Any Duration
|
||||
short: Short (< 2 min)
|
||||
medium: Normal
|
||||
long: Long (> 10 min)
|
||||
backendErrors:
|
||||
ratelimit: You are performing your actions too frequent. Please wait a bit.
|
||||
invalid-api-key: Failed to communicate with the backend, please try to
|
||||
|
||||