mirror of
https://github.com/tobspr/shapez.io.git
synced 2026-03-02 03:39:21 +00:00
Initial support for translations
This commit is contained in:
@@ -39,6 +39,13 @@
|
||||
.hotkey {
|
||||
color: lighten($colorGreenBright, 10);
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
.keybinding {
|
||||
position: relative;
|
||||
@include S(margin-left, 5px);
|
||||
}
|
||||
}
|
||||
|
||||
.buildingImage {
|
||||
|
||||
@@ -66,17 +66,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
.keybinding.shift {
|
||||
.keybinding.builtinKey {
|
||||
transition: all 0.1s ease-in-out;
|
||||
transition-property: background-color, color, border-color;
|
||||
background: $colorRedBright;
|
||||
border-color: $colorRedBright;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&.shiftDown .keybinding.shift {
|
||||
border-color: darken($colorRedBright, 40);
|
||||
}
|
||||
}
|
||||
|
||||
body.uiHidden #ingame_HUD_KeybindingOverlay .binding:not(.hudToggle) {
|
||||
|
||||
@@ -251,9 +251,9 @@
|
||||
|
||||
@include S(padding, 15px);
|
||||
> a {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
display: grid;
|
||||
align-items: center;
|
||||
grid-template-columns: 1fr auto;
|
||||
|
||||
justify-content: center;
|
||||
background: #fafafa;
|
||||
@@ -280,8 +280,8 @@
|
||||
|
||||
.thirdpartyLogo {
|
||||
display: inline-block;
|
||||
width: 80%;
|
||||
height: 80%;
|
||||
@include S(width, 50px);
|
||||
@include S(height, 50px);
|
||||
background: center center / 80% no-repeat;
|
||||
&.githubLogo {
|
||||
background-image: uiResource("main_menu/github.png");
|
||||
|
||||
1
src/js/.gitignore
vendored
Normal file
1
src/js/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
translations-built
|
||||
@@ -76,7 +76,7 @@ export const globalConfig = {
|
||||
|
||||
debug: {
|
||||
/* dev:start */
|
||||
// fastGameEnter: true,
|
||||
fastGameEnter: true,
|
||||
noArtificialDelays: true,
|
||||
// disableSavegameWrite: true,
|
||||
showEntityBounds: false,
|
||||
@@ -90,6 +90,7 @@ export const globalConfig = {
|
||||
allBuildingsUnlocked: true,
|
||||
upgradesNoCost: true,
|
||||
disableUnlockDialog: false,
|
||||
testTranslations: true,
|
||||
/* dev:end */
|
||||
},
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import { FormElement } from "./modal_dialog_forms";
|
||||
import { globalConfig } from "./config";
|
||||
import { getStringForKeyCode } from "../game/key_action_mapper";
|
||||
import { createLogger } from "./logging";
|
||||
import { T } from "../translations";
|
||||
|
||||
const kbEnter = 13;
|
||||
const kbCancel = 27;
|
||||
@@ -146,8 +147,7 @@ export class Dialog {
|
||||
button.classList.add("button");
|
||||
button.classList.add("styledButton");
|
||||
button.classList.add(buttonStyle);
|
||||
// button.innerText = T.dialog_buttons[buttonId];
|
||||
button.innerText = buttonId;
|
||||
button.innerText = T.dialogs.buttons[buttonId];
|
||||
|
||||
const params = (rawParams || "").split("/");
|
||||
const useTimeout = params.indexOf("timeout") >= 0;
|
||||
@@ -277,7 +277,7 @@ export class DialogLoading extends Dialog {
|
||||
const loader = document.createElement("div");
|
||||
loader.classList.add("prefab_LoadingTextWithAnim");
|
||||
loader.classList.add("loadingIndicator");
|
||||
loader.innerText = "Loading";
|
||||
loader.innerText = T.global.loading;
|
||||
elem.appendChild(loader);
|
||||
|
||||
this.app.inputMgr.pushReciever(this.inputReciever);
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
performanceNow,
|
||||
} from "./builtins";
|
||||
import { Vector } from "./vector";
|
||||
import { T } from "../translations";
|
||||
|
||||
// Constants
|
||||
export const TOP = new Vector(0, -1);
|
||||
@@ -421,7 +422,7 @@ export function formatBigNumber(num, divider = ".") {
|
||||
num = Math_abs(num);
|
||||
|
||||
if (num > 1e54) {
|
||||
return sign + "inf";
|
||||
return sign + T.global.infinite;
|
||||
}
|
||||
|
||||
if (num < 10 && !Number.isInteger(num)) {
|
||||
@@ -459,7 +460,7 @@ export function formatBigNumberFull(num, divider = ",") {
|
||||
return num + "";
|
||||
}
|
||||
if (num > 1e54) {
|
||||
return "infinite";
|
||||
return T.global.infinite;
|
||||
}
|
||||
let rest = num;
|
||||
let out = "";
|
||||
@@ -831,24 +832,47 @@ export function formatSecondsToTimeAgo(secs) {
|
||||
|
||||
if (seconds <= 60) {
|
||||
if (seconds <= 1) {
|
||||
return "one second ago";
|
||||
return T.global.time.oneSecondAgo;
|
||||
}
|
||||
return seconds + " seconds ago";
|
||||
return T.global.time.xSecondsAgo.replace("<x>", "" + seconds);
|
||||
} else if (minutes <= 60) {
|
||||
if (minutes <= 1) {
|
||||
return "one minute ago";
|
||||
return T.global.time.oneMinuteAgo;
|
||||
}
|
||||
return minutes + " minutes ago";
|
||||
return T.global.time.xMinutesAgo.replace("<x>", "" + minutes);
|
||||
} else if (hours <= 60) {
|
||||
if (hours <= 1) {
|
||||
return "one hour ago";
|
||||
return T.global.time.oneHourAgo;
|
||||
}
|
||||
return hours + " hours ago";
|
||||
return T.global.time.xHoursAgo.replace("<x>", "" + hours);
|
||||
} else {
|
||||
if (days <= 1) {
|
||||
return "one day ago";
|
||||
return T.global.time.oneDayAgo;
|
||||
}
|
||||
return days + " days ago";
|
||||
return T.global.time.xDaysAgo.replace("<x>", "" + days);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats seconds into a readable string like "5h 23m"
|
||||
* @param {number} secs Seconds
|
||||
* @returns {string}
|
||||
*/
|
||||
export function formatSeconds(secs) {
|
||||
const trans = T.global.time;
|
||||
secs = Math_ceil(secs);
|
||||
if (secs < 60) {
|
||||
return trans.secondsShort.replace("<seconds>", "" + secs);
|
||||
} else if (secs < 60 * 60) {
|
||||
const minutes = Math_floor(secs / 60);
|
||||
const seconds = secs % 60;
|
||||
return trans.minutesAndSecondsShort
|
||||
.replace("<seconds>", "" + seconds)
|
||||
.replace("<minutes>", "" + minutes);
|
||||
} else {
|
||||
const hours = Math_floor(secs / 3600);
|
||||
const minutes = Math_floor(secs / 60) % 60;
|
||||
return trans.hoursAndMinutesShort.replace("<minutes>", "" + minutes).replace("<hours>", "" + hours);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -868,3 +892,11 @@ export function generateFileDownload(filename, text) {
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Capitalizes the first letter
|
||||
* @param {string} str
|
||||
*/
|
||||
export function capitalizeFirstLetter(str) {
|
||||
return str.substr(0, 1).toUpperCase() + str.substr(1).toLowerCase();
|
||||
}
|
||||
|
||||
@@ -20,14 +20,6 @@ export class MetaBeltBaseBuilding extends MetaBuilding {
|
||||
return "#777";
|
||||
}
|
||||
|
||||
getName() {
|
||||
return "Belt";
|
||||
}
|
||||
|
||||
getDescription() {
|
||||
return "Transports items, hold and drag to place multiple.";
|
||||
}
|
||||
|
||||
getPreviewSprite(rotationVariant) {
|
||||
switch (arrayBeltVariantToRotation[rotationVariant]) {
|
||||
case enumDirection.top: {
|
||||
|
||||
@@ -30,14 +30,6 @@ export class MetaCutterBuilding extends MetaBuilding {
|
||||
}
|
||||
}
|
||||
|
||||
getName() {
|
||||
return "Cut Half";
|
||||
}
|
||||
|
||||
getDescription() {
|
||||
return "Cuts shapes from top to bottom and outputs both halfs. <strong>If you use only one part, be sure to destroy the other part or it will stall!</strong>";
|
||||
}
|
||||
|
||||
getAvailableVariants(root) {
|
||||
return [defaultBuildingVariant, enumCutterVariants.quad];
|
||||
}
|
||||
|
||||
@@ -20,14 +20,6 @@ export class MetaHubBuilding extends MetaBuilding {
|
||||
return "#eb5555";
|
||||
}
|
||||
|
||||
getName() {
|
||||
return "Hub";
|
||||
}
|
||||
|
||||
getDescription() {
|
||||
return "Your central hub, deliver shapes to it to unlock new buildings.";
|
||||
}
|
||||
|
||||
isRotateable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -13,18 +13,10 @@ export class MetaMinerBuilding extends MetaBuilding {
|
||||
super("miner");
|
||||
}
|
||||
|
||||
getName() {
|
||||
return "Extract";
|
||||
}
|
||||
|
||||
getSilhouetteColor() {
|
||||
return "#b37dcd";
|
||||
}
|
||||
|
||||
getDescription() {
|
||||
return "Place over a shape or color to extract it. Six extractors fill exactly one belt.";
|
||||
}
|
||||
|
||||
getAvailableVariants(root) {
|
||||
return [defaultBuildingVariant, enumMinerVariants.chainable];
|
||||
}
|
||||
|
||||
@@ -17,14 +17,6 @@ export class MetaMixerBuilding extends MetaBuilding {
|
||||
return new Vector(2, 1);
|
||||
}
|
||||
|
||||
getName() {
|
||||
return "Mix Colors";
|
||||
}
|
||||
|
||||
getDescription() {
|
||||
return "Mixes two colors using additive blending.";
|
||||
}
|
||||
|
||||
getSilhouetteColor() {
|
||||
return "#cdbb7d";
|
||||
}
|
||||
|
||||
@@ -29,14 +29,6 @@ export class MetaPainterBuilding extends MetaBuilding {
|
||||
}
|
||||
}
|
||||
|
||||
getName() {
|
||||
return "Dye";
|
||||
}
|
||||
|
||||
getDescription() {
|
||||
return "Colors the whole shape on the left input with the color from the right input.";
|
||||
}
|
||||
|
||||
getSilhouetteColor() {
|
||||
return "#cd9b7d";
|
||||
}
|
||||
|
||||
@@ -16,14 +16,6 @@ export class MetaRotaterBuilding extends MetaBuilding {
|
||||
super("rotater");
|
||||
}
|
||||
|
||||
getName() {
|
||||
return "Rotate";
|
||||
}
|
||||
|
||||
getDescription() {
|
||||
return "Rotates shapes clockwise by 90 degrees.";
|
||||
}
|
||||
|
||||
getSilhouetteColor() {
|
||||
return "#7dc6cd";
|
||||
}
|
||||
|
||||
@@ -27,18 +27,10 @@ export class MetaSplitterBuilding extends MetaBuilding {
|
||||
}
|
||||
}
|
||||
|
||||
getName() {
|
||||
return "Balancer";
|
||||
}
|
||||
|
||||
getSilhouetteColor() {
|
||||
return "#444";
|
||||
}
|
||||
|
||||
getDescription() {
|
||||
return "Multifunctional - Evenly distributes all inputs onto all outputs.";
|
||||
}
|
||||
|
||||
getAvailableVariants(root) {
|
||||
return [defaultBuildingVariant, enumSplitterVariants.compact];
|
||||
}
|
||||
|
||||
@@ -13,18 +13,10 @@ export class MetaStackerBuilding extends MetaBuilding {
|
||||
super("stacker");
|
||||
}
|
||||
|
||||
getName() {
|
||||
return "Combine";
|
||||
}
|
||||
|
||||
getSilhouetteColor() {
|
||||
return "#9fcd7d";
|
||||
}
|
||||
|
||||
getDescription() {
|
||||
return "Combines both items. If they can not be merged, the right item is placed above the left item.";
|
||||
}
|
||||
|
||||
getDimensions() {
|
||||
return new Vector(2, 1);
|
||||
}
|
||||
|
||||
@@ -12,14 +12,6 @@ export class MetaTrashBuilding extends MetaBuilding {
|
||||
super("trash");
|
||||
}
|
||||
|
||||
getName() {
|
||||
return "Destroyer";
|
||||
}
|
||||
|
||||
getDescription() {
|
||||
return "Accepts inputs from all sides and destroys them. Forever.";
|
||||
}
|
||||
|
||||
isRotateable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -28,18 +28,10 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
|
||||
super("underground_belt");
|
||||
}
|
||||
|
||||
getName() {
|
||||
return "Tunnel";
|
||||
}
|
||||
|
||||
getSilhouetteColor() {
|
||||
return "#555";
|
||||
}
|
||||
|
||||
getDescription() {
|
||||
return "Allows to tunnel resources under buildings and belts.";
|
||||
}
|
||||
|
||||
getFlipOrientationAfterPlacement() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* typehints:start */
|
||||
import { Application } from "../application";
|
||||
/* typehints:end */
|
||||
import { T } from "../translations";
|
||||
|
||||
export class GameLoadingOverlay {
|
||||
/**
|
||||
@@ -51,7 +52,7 @@ export class GameLoadingOverlay {
|
||||
internalAddSpinnerAndText(element) {
|
||||
const inner = document.createElement("span");
|
||||
inner.classList.add("prefab_LoadingTextWithAnim");
|
||||
inner.innerText = "Loading";
|
||||
inner.innerText = T.global.loading;
|
||||
element.appendChild(inner);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { MetaBuilding, defaultBuildingVariant } from "../../meta_building";
|
||||
import { DrawParameters } from "../../../core/draw_parameters";
|
||||
import { Math_abs, Math_degrees, Math_radians } from "../../../core/builtins";
|
||||
import { globalConfig } from "../../../core/config";
|
||||
import { StaticMapEntityComponent } from "../../components/static_map_entity";
|
||||
import { STOP_PROPAGATION, Signal } from "../../../core/signal";
|
||||
import {
|
||||
Vector,
|
||||
enumDirectionToAngle,
|
||||
enumInvertedDirections,
|
||||
enumDirectionToVector,
|
||||
} from "../../../core/vector";
|
||||
import { pulseAnimation, makeDiv, removeAllChildren } from "../../../core/utils";
|
||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||
import { TrackedState } from "../../../core/tracked_state";
|
||||
import { Math_abs, Math_radians, Math_degrees } from "../../../core/builtins";
|
||||
import { Loader } from "../../../core/loader";
|
||||
import { DrawParameters } from "../../../core/draw_parameters";
|
||||
import { drawRotatedSprite } from "../../../core/draw_utils";
|
||||
import { Entity } from "../../entity";
|
||||
import { Loader } from "../../../core/loader";
|
||||
import { STOP_PROPAGATION } from "../../../core/signal";
|
||||
import { TrackedState } from "../../../core/tracked_state";
|
||||
import { makeDiv, removeAllChildren } from "../../../core/utils";
|
||||
import {
|
||||
enumDirectionToAngle,
|
||||
enumDirectionToVector,
|
||||
enumInvertedDirections,
|
||||
Vector,
|
||||
} from "../../../core/vector";
|
||||
import { enumMouseButton } from "../../camera";
|
||||
import { StaticMapEntityComponent } from "../../components/static_map_entity";
|
||||
import { Entity } from "../../entity";
|
||||
import { defaultBuildingVariant, MetaBuilding } from "../../meta_building";
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||
import { T } from "../../../translations";
|
||||
|
||||
export class HUDBuildingPlacer extends BaseHUDPart {
|
||||
initialize() {
|
||||
@@ -231,13 +232,16 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
||||
this.abortDragging();
|
||||
this.root.hud.signals.selectedPlacementBuildingChanged.dispatch(metaBuilding);
|
||||
if (metaBuilding) {
|
||||
this.buildingInfoElements.label.innerHTML = metaBuilding.getName();
|
||||
this.buildingInfoElements.descText.innerHTML = metaBuilding.getDescription();
|
||||
this.buildingInfoElements.label.innerHTML = T.buildings[metaBuilding.id].name;
|
||||
this.buildingInfoElements.descText.innerHTML = T.buildings[metaBuilding.id].description;
|
||||
|
||||
const binding = this.root.gameState.keyActionMapper.getBinding(
|
||||
"building_" + metaBuilding.getId()
|
||||
);
|
||||
this.buildingInfoElements.hotkey.innerHTML = "Hotkey: " + binding.getKeyCodeString();
|
||||
this.buildingInfoElements.hotkey.innerHTML = T.ingame.buildingPlacement.hotkeyLabel.replace(
|
||||
"<key>",
|
||||
"<code class='keybinding'>" + binding.getKeyCodeString() + "</code>"
|
||||
);
|
||||
|
||||
const variant = this.preferredVariants[metaBuilding.getId()] || defaultBuildingVariant;
|
||||
this.currentVariant.set(variant);
|
||||
@@ -283,11 +287,12 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
||||
this.variantsElement,
|
||||
null,
|
||||
["explanation"],
|
||||
`
|
||||
Press <code class='keybinding'>${this.root.gameState.keyActionMapper
|
||||
.getBinding("cycle_variants")
|
||||
.getKeyCodeString()}</code> to cycle variants.
|
||||
`
|
||||
T.ingame.buildingPlacement.cycleBuildingVariants.replace(
|
||||
"<key>",
|
||||
"<code class='keybinding'>" +
|
||||
this.root.gameState.keyActionMapper.getBinding("cycle_variants").getKeyCodeString() +
|
||||
"</code>"
|
||||
)
|
||||
);
|
||||
|
||||
for (let i = 0; i < availableVariants.length; ++i) {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { BaseHUDPart } from "../base_hud_part";
|
||||
import { makeDiv, randomInt } from "../../../core/utils";
|
||||
import { SOUNDS } from "../../../platform/sound";
|
||||
import { enumNotificationType } from "./notifications";
|
||||
import { T } from "../../../translations";
|
||||
|
||||
export class HUDGameMenu extends BaseHUDPart {
|
||||
initialize() {}
|
||||
@@ -16,7 +17,7 @@ export class HUDGameMenu extends BaseHUDPart {
|
||||
keybinding: "menu_open_shop",
|
||||
badge: () => this.root.hubGoals.getAvailableUpgradeCount(),
|
||||
notification: /** @type {[string, enumNotificationType]} */ ([
|
||||
"A new upgrade is available!",
|
||||
T.ingame.notifications.newUpgrade,
|
||||
enumNotificationType.upgrade,
|
||||
]),
|
||||
},
|
||||
|
||||
@@ -3,6 +3,7 @@ import { makeDiv } from "../../../core/utils";
|
||||
import { getStringForKeyCode } from "../../key_action_mapper";
|
||||
import { TrackedState } from "../../../core/tracked_state";
|
||||
import { queryParamOptions } from "../../../core/query_parameters";
|
||||
import { T } from "../../../translations";
|
||||
|
||||
export class HUDKeybindingOverlay extends BaseHUDPart {
|
||||
initialize() {
|
||||
@@ -32,7 +33,7 @@ export class HUDKeybindingOverlay extends BaseHUDPart {
|
||||
`
|
||||
<div class="binding">
|
||||
<code class="keybinding">${getKeycode("center_map")}</code>
|
||||
<label>Center</label>
|
||||
<label>${T.ingame.keybindingsOverlay.centerMap}</label>
|
||||
</div>
|
||||
|
||||
<div class="binding">
|
||||
@@ -41,48 +42,48 @@ export class HUDKeybindingOverlay extends BaseHUDPart {
|
||||
<code class="keybinding">${getKeycode("map_move_left")}</code>
|
||||
<code class="keybinding">${getKeycode("map_move_down")}</code>
|
||||
<code class="keybinding">${getKeycode("map_move_right")}</code>
|
||||
<label>Move</label>
|
||||
<label>${T.ingame.keybindingsOverlay.moveMap}</label>
|
||||
</div>
|
||||
|
||||
<div class="binding noPlacementOnly">
|
||||
<code class="keybinding rightMouse"></code><i></i>
|
||||
<code class="keybinding shift">CTRL</code>+
|
||||
<code class="keybinding builtinKey">${T.global.keys.control}</code>+
|
||||
<code class="keybinding leftMouse"></code>
|
||||
<label>Delete</label>
|
||||
<label>${T.ingame.keybindingsOverlay.removeBuildings}</label>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="binding placementOnly">
|
||||
<code class="keybinding rightMouse"></code> <i></i>
|
||||
<code class="keybinding rightMouse"></code><i></i>
|
||||
<code class="keybinding">${getKeycode("building_abort_placement")}</code>
|
||||
<label>Stop placement</label>
|
||||
<label>${T.ingame.keybindingsOverlay.stopPlacement}</label>
|
||||
</div>
|
||||
|
||||
<div class="binding placementOnly">
|
||||
<code class="keybinding">${getKeycode("rotate_while_placing")}</code>
|
||||
<label>Rotate Building</label>
|
||||
<label>${T.ingame.keybindingsOverlay.rotateBuilding}</label>
|
||||
</div>
|
||||
|
||||
<div class="binding placementOnly">
|
||||
<code class="keybinding shift">⇧ SHIFT</code>
|
||||
<label>Place Multiple</label>
|
||||
<code class="keybinding builtinKey shift">⇧ ${T.global.keys.shift}</code>
|
||||
<label>${T.ingame.keybindingsOverlay.placeMultiple}</label>
|
||||
</div>
|
||||
|
||||
<div class="binding placementOnly">
|
||||
<code class="keybinding shift">ALT</code>
|
||||
<label>Reverse orientation</label>
|
||||
<code class="keybinding builtinKey">${T.global.keys.alt}</code>
|
||||
<label>${T.ingame.keybindingsOverlay.reverseOrientation}</label>
|
||||
</div>
|
||||
|
||||
<div class="binding placementOnly">
|
||||
<code class="keybinding shift">CTRL</code>
|
||||
<label>Disable auto orientation</label>
|
||||
<code class="keybinding builtinKey">${T.global.keys.control}</code>
|
||||
<label>${T.ingame.keybindingsOverlay.disableAutoOrientation}</label>
|
||||
</div>
|
||||
` +
|
||||
(queryParamOptions.betaMode
|
||||
? `
|
||||
<div class="binding hudToggle">
|
||||
<code class="keybinding">F2</code>
|
||||
<label>Toggle HUD</label>
|
||||
<label>${T.ingame.keybindingsOverlay.toggleHud}</label>
|
||||
</div>
|
||||
`
|
||||
: "")
|
||||
|
||||
@@ -9,6 +9,7 @@ import { makeDiv } from "../../../core/utils";
|
||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||
import { createLogger } from "../../../core/logging";
|
||||
import { enumMouseButton } from "../../camera";
|
||||
import { T } from "../../../translations";
|
||||
|
||||
const logger = createLogger("hud/mass_selector");
|
||||
|
||||
@@ -23,10 +24,9 @@ export class HUDMassSelector extends BaseHUDPart {
|
||||
parent,
|
||||
"ingame_HUD_MassSelector",
|
||||
[],
|
||||
`
|
||||
Press <code class="keybinding">${removalKeybinding}</code> to remove selected buildings
|
||||
and <code class="keybinding">${abortKeybinding}</code> to cancel.
|
||||
`
|
||||
T.ingame.massDelete.infoText
|
||||
.replace("<keyDelete>", removalKeybinding)
|
||||
.replace("<keyCancel>", abortKeybinding)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -80,22 +80,6 @@ export class HUDModalDialogs extends BaseHUDPart {
|
||||
return dialog.buttonSignals;
|
||||
}
|
||||
|
||||
showVideoTutorial(title, text, videoUrl) {
|
||||
const dialog = new DialogVideoTutorial({
|
||||
app: this.app,
|
||||
title: title,
|
||||
contentHTML: text,
|
||||
videoUrl,
|
||||
});
|
||||
this.internalShowDialog(dialog);
|
||||
|
||||
if (this.app) {
|
||||
this.app.sound.playUiSound(SOUNDS.dialogOk);
|
||||
}
|
||||
|
||||
return dialog.buttonSignals;
|
||||
}
|
||||
|
||||
showOptionChooser(title, options) {
|
||||
const dialog = new DialogOptionChooser({
|
||||
app: this.app,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { makeDiv } from "../../../core/utils";
|
||||
import { T } from "../../../translations";
|
||||
|
||||
/** @enum {string} */
|
||||
export const enumNotificationType = {
|
||||
@@ -23,7 +24,7 @@ export class HUDNotifications extends BaseHUDPart {
|
||||
|
||||
// Automatic notifications
|
||||
this.root.signals.gameSaved.add(() =>
|
||||
this.onNotification("Your game has been saved.", enumNotificationType.saved)
|
||||
this.onNotification(T.ingame.notifications.gameSaved, enumNotificationType.saved)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { makeDiv } from "../../../core/utils";
|
||||
import { makeDiv, formatSeconds } from "../../../core/utils";
|
||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||
import { InputReceiver } from "../../../core/input_receiver";
|
||||
import { KeyActionMapper } from "../../key_action_mapper";
|
||||
import { T } from "../../../translations";
|
||||
|
||||
export class HUDSettingsMenu extends BaseHUDPart {
|
||||
createElements(parent) {
|
||||
@@ -14,18 +15,18 @@ export class HUDSettingsMenu extends BaseHUDPart {
|
||||
this.background,
|
||||
null,
|
||||
["timePlayed"],
|
||||
`<strong>Playtime</strong><span class="playtime"></span>`
|
||||
`<strong>${T.ingame.settingsMenu.playtime}</strong><span class="playtime"></span>`
|
||||
);
|
||||
|
||||
this.buttonContainer = makeDiv(this.menuElement, null, ["buttons"]);
|
||||
|
||||
const buttons = [
|
||||
{
|
||||
title: "Continue",
|
||||
title: T.ingame.settingsMenu.buttons.continue,
|
||||
action: () => this.close(),
|
||||
},
|
||||
{
|
||||
title: "Return to menu",
|
||||
title: T.ingame.settingsMenu.buttons.menu,
|
||||
action: () => this.returnToMenu(),
|
||||
},
|
||||
];
|
||||
@@ -79,9 +80,8 @@ export class HUDSettingsMenu extends BaseHUDPart {
|
||||
// this.background.classList.add("visible");
|
||||
this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever);
|
||||
|
||||
const totalMinutesPlayed = Math.ceil(this.root.time.now() / 60.0);
|
||||
const playtimeString = totalMinutesPlayed === 1 ? "1 minute" : totalMinutesPlayed + " minutes";
|
||||
this.timePlayed.querySelector(".playtime").innerText = playtimeString;
|
||||
const totalSecondsPlayed = Math.ceil(this.root.time.now());
|
||||
this.timePlayed.querySelector(".playtime").innerText = formatSeconds(totalSecondsPlayed);
|
||||
}
|
||||
|
||||
close() {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { makeDiv, removeAllChildren, formatBigNumber } from "../../../core/utils";
|
||||
import { UPGRADES, TIER_LABELS } from "../../upgrades";
|
||||
import { ShapeDefinition } from "../../shape_definition";
|
||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||
import { InputReceiver } from "../../../core/input_receiver";
|
||||
import { KeyActionMapper } from "../../key_action_mapper";
|
||||
import { Math_min } from "../../../core/builtins";
|
||||
import { ClickDetector } from "../../../core/click_detector";
|
||||
import { InputReceiver } from "../../../core/input_receiver";
|
||||
import { formatBigNumber, makeDiv } from "../../../core/utils";
|
||||
import { T } from "../../../translations";
|
||||
import { KeyActionMapper } from "../../key_action_mapper";
|
||||
import { UPGRADES } from "../../upgrades";
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||
|
||||
export class HUDShop extends BaseHUDPart {
|
||||
createElements(parent) {
|
||||
@@ -14,7 +14,7 @@ export class HUDShop extends BaseHUDPart {
|
||||
|
||||
// DIALOG Inner / Wrapper
|
||||
this.dialogInner = makeDiv(this.background, null, ["dialogInner"]);
|
||||
this.title = makeDiv(this.dialogInner, null, ["title"], `Upgrades`);
|
||||
this.title = makeDiv(this.dialogInner, null, ["title"], T.ingame.shop.title);
|
||||
this.closeButton = makeDiv(this.title, null, ["closeButton"]);
|
||||
this.trackClicks(this.closeButton, this.close);
|
||||
this.contentDiv = makeDiv(this.dialogInner, null, ["content"]);
|
||||
@@ -23,7 +23,6 @@ export class HUDShop extends BaseHUDPart {
|
||||
|
||||
// Upgrades
|
||||
for (const upgradeId in UPGRADES) {
|
||||
const { label } = UPGRADES[upgradeId];
|
||||
const handle = {};
|
||||
handle.requireIndexToElement = [];
|
||||
|
||||
@@ -32,10 +31,10 @@ export class HUDShop extends BaseHUDPart {
|
||||
handle.elem.setAttribute("data-upgrade-id", upgradeId);
|
||||
|
||||
// Title
|
||||
const title = makeDiv(handle.elem, null, ["title"], label);
|
||||
const title = makeDiv(handle.elem, null, ["title"], T.shopUpgrades[upgradeId].name);
|
||||
|
||||
// Title > Tier
|
||||
handle.elemTierLabel = makeDiv(title, null, ["tier"], "Tier ?");
|
||||
handle.elemTierLabel = makeDiv(title, null, ["tier"]);
|
||||
|
||||
// Icon
|
||||
handle.icon = makeDiv(handle.elem, null, ["icon"]);
|
||||
@@ -48,7 +47,7 @@ export class HUDShop extends BaseHUDPart {
|
||||
// Buy button
|
||||
handle.buyButton = document.createElement("button");
|
||||
handle.buyButton.classList.add("buy", "styledButton");
|
||||
handle.buyButton.innerText = "Upgrade";
|
||||
handle.buyButton.innerText = T.ingame.shop.buttonUnlock;
|
||||
handle.elem.appendChild(handle.buyButton);
|
||||
|
||||
this.trackClicks(handle.buyButton, () => this.tryUnlockNextTier(upgradeId));
|
||||
@@ -61,13 +60,17 @@ export class HUDShop extends BaseHUDPart {
|
||||
rerenderFull() {
|
||||
for (const upgradeId in this.upgradeToElements) {
|
||||
const handle = this.upgradeToElements[upgradeId];
|
||||
const { description, tiers } = UPGRADES[upgradeId];
|
||||
const { tiers } = UPGRADES[upgradeId];
|
||||
|
||||
const currentTier = this.root.hubGoals.getUpgradeLevel(upgradeId);
|
||||
const tierHandle = tiers[currentTier];
|
||||
|
||||
// Set tier
|
||||
handle.elemTierLabel.innerText = "Tier " + TIER_LABELS[currentTier];
|
||||
handle.elemTierLabel.innerText = T.ingame.shop.tier.replace(
|
||||
"<x>",
|
||||
"" + T.ingame.shop.tierLabels[currentTier]
|
||||
);
|
||||
|
||||
handle.elemTierLabel.setAttribute("data-tier", currentTier);
|
||||
|
||||
// Cleanup detectors
|
||||
@@ -84,12 +87,15 @@ export class HUDShop extends BaseHUDPart {
|
||||
|
||||
if (!tierHandle) {
|
||||
// Max level
|
||||
handle.elemDescription.innerText = "Maximum level";
|
||||
handle.elemDescription.innerText = T.ingame.shop.maximumLevel;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Set description
|
||||
handle.elemDescription.innerText = description(tierHandle.improvement);
|
||||
handle.elemDescription.innerText = T.shopUpgrades[upgradeId].description.replace(
|
||||
"<gain>",
|
||||
Math.floor(tierHandle.improvement * 100.0)
|
||||
);
|
||||
|
||||
tierHandle.required.forEach(({ shape, amount }) => {
|
||||
const container = makeDiv(handle.elemRequirements, null, ["requirement"]);
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
import { Math_min } from "../../../core/builtins";
|
||||
import { InputReceiver } from "../../../core/input_receiver";
|
||||
import { makeButton, makeDiv, removeAllChildren } from "../../../core/utils";
|
||||
import { makeButton, makeDiv, removeAllChildren, capitalizeFirstLetter } from "../../../core/utils";
|
||||
import { KeyActionMapper } from "../../key_action_mapper";
|
||||
import { enumAnalyticsDataSource } from "../../production_analytics";
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||
import { enumDisplayMode, HUDShapeStatisticsHandle } from "./statistics_handle";
|
||||
|
||||
const enumDataSourceToText = {
|
||||
[enumAnalyticsDataSource.stored]: "Displaying amount of stored shapes in your central building.",
|
||||
[enumAnalyticsDataSource.produced]:
|
||||
"Displaying all shapes your whole factory produces, including intermediate products.",
|
||||
[enumAnalyticsDataSource.delivered]: "Displaying shapes which are delivered to your central building.",
|
||||
};
|
||||
import { T } from "../../../translations";
|
||||
|
||||
export class HUDStatistics extends BaseHUDPart {
|
||||
createElements(parent) {
|
||||
@@ -20,7 +14,7 @@ export class HUDStatistics extends BaseHUDPart {
|
||||
|
||||
// DIALOG Inner / Wrapper
|
||||
this.dialogInner = makeDiv(this.background, null, ["dialogInner"]);
|
||||
this.title = makeDiv(this.dialogInner, null, ["title"], `statistics`);
|
||||
this.title = makeDiv(this.dialogInner, null, ["title"], T.ingame.statistics.title);
|
||||
this.closeButton = makeDiv(this.title, null, ["closeButton"]);
|
||||
this.trackClicks(this.closeButton, this.close);
|
||||
|
||||
@@ -30,13 +24,21 @@ export class HUDStatistics extends BaseHUDPart {
|
||||
this.filtersDataSource = makeDiv(this.filterHeader, null, ["filtersDataSource"]);
|
||||
this.filtersDisplayMode = makeDiv(this.filterHeader, null, ["filtersDisplayMode"]);
|
||||
|
||||
const buttonModeProduced = makeButton(this.filtersDataSource, ["modeProduced"], "Produced");
|
||||
const buttonModeDelivered = makeButton(this.filtersDataSource, ["modeDelivered"], "Delivered");
|
||||
const buttonModeStored = makeButton(this.filtersDataSource, ["modeStored"], "Stored");
|
||||
const dataSources = [
|
||||
enumAnalyticsDataSource.produced,
|
||||
enumAnalyticsDataSource.delivered,
|
||||
enumAnalyticsDataSource.stored,
|
||||
];
|
||||
|
||||
this.trackClicks(buttonModeProduced, () => this.setDataSource(enumAnalyticsDataSource.produced));
|
||||
this.trackClicks(buttonModeStored, () => this.setDataSource(enumAnalyticsDataSource.stored));
|
||||
this.trackClicks(buttonModeDelivered, () => this.setDataSource(enumAnalyticsDataSource.delivered));
|
||||
for (let i = 0; i < dataSources.length; ++i) {
|
||||
const dataSource = dataSources[i];
|
||||
const button = makeButton(
|
||||
this.filtersDataSource,
|
||||
["mode" + capitalizeFirstLetter(dataSource)],
|
||||
T.ingame.statistics.dataSources[dataSource].title
|
||||
);
|
||||
this.trackClicks(button, () => this.setDataSource(dataSource));
|
||||
}
|
||||
|
||||
const buttonDisplayDetailed = makeButton(this.filtersDisplayMode, ["displayDetailed"]);
|
||||
const buttonDisplayIcons = makeButton(this.filtersDisplayMode, ["displayIcons"]);
|
||||
@@ -54,7 +56,7 @@ export class HUDStatistics extends BaseHUDPart {
|
||||
this.dataSource = source;
|
||||
this.dialogInner.setAttribute("data-datasource", source);
|
||||
|
||||
this.sourceExplanation.innerText = enumDataSourceToText[source];
|
||||
this.sourceExplanation.innerText = T.ingame.statistics.dataSources[source].title;
|
||||
if (this.visible) {
|
||||
this.rerenderFull();
|
||||
}
|
||||
@@ -204,7 +206,7 @@ export class HUDStatistics extends BaseHUDPart {
|
||||
|
||||
if (entries.length === 0) {
|
||||
this.contentDiv.innerHTML = `
|
||||
<strong class="noEntries">No shapes have been produced so far.</strong>`;
|
||||
<strong class="noEntries">${T.ingame.statistics.noShapesProduced}</strong>`;
|
||||
}
|
||||
|
||||
this.contentDiv.classList.toggle("hasEntries", entries.length > 0);
|
||||
|
||||
@@ -4,6 +4,7 @@ import { enumAnalyticsDataSource } from "../../production_analytics";
|
||||
import { formatBigNumber, clamp } from "../../../core/utils";
|
||||
import { globalConfig } from "../../../core/config";
|
||||
import { makeOffscreenBuffer } from "../../../core/buffer_utils";
|
||||
import { T } from "../../../translations";
|
||||
|
||||
/** @enum {string} */
|
||||
export const enumDisplayMode = {
|
||||
@@ -86,7 +87,10 @@ export class HUDShapeStatisticsHandle {
|
||||
(this.root.productionAnalytics.getCurrentShapeRate(dataSource, this.definition) /
|
||||
globalConfig.analyticsSliceDurationSeconds) *
|
||||
60;
|
||||
this.counter.innerText = formatBigNumber(rate) + " / m";
|
||||
this.counter.innerText = T.ingame.statistics.shapesPerMinute.replace(
|
||||
"<shapes>",
|
||||
formatBigNumber(rate)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,9 +10,10 @@ import { MetaSplitterBuilding } from "../../buildings/splitter";
|
||||
import { MetaStackerBuilding } from "../../buildings/stacker";
|
||||
import { MetaTrashBuilding } from "../../buildings/trash";
|
||||
import { MetaUndergroundBeltBuilding } from "../../buildings/underground_belt";
|
||||
import { enumHubGoalRewards, enumHubGoalRewardToString } from "../../tutorial_goals";
|
||||
import { enumHubGoalRewards } from "../../tutorial_goals";
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||
import { T } from "../../../translations";
|
||||
|
||||
export class HUDUnlockNotification extends BaseHUDPart {
|
||||
initialize() {
|
||||
@@ -36,17 +37,10 @@ export class HUDUnlockNotification extends BaseHUDPart {
|
||||
|
||||
const dialog = makeDiv(this.element, null, ["dialog"]);
|
||||
|
||||
this.elemTitle = makeDiv(dialog, null, ["title"], ``);
|
||||
this.elemSubTitle = makeDiv(dialog, null, ["subTitle"], `Completed`);
|
||||
this.elemTitle = makeDiv(dialog, null, ["title"]);
|
||||
this.elemSubTitle = makeDiv(dialog, null, ["subTitle"], T.ingame.levelCompleteNotification.completed);
|
||||
|
||||
this.elemContents = makeDiv(
|
||||
dialog,
|
||||
null,
|
||||
["contents"],
|
||||
`
|
||||
Ready for the next one?
|
||||
`
|
||||
);
|
||||
this.elemContents = makeDiv(dialog, null, ["contents"]);
|
||||
|
||||
this.btnClose = document.createElement("button");
|
||||
this.btnClose.classList.add("close", "styledButton");
|
||||
@@ -61,9 +55,17 @@ export class HUDUnlockNotification extends BaseHUDPart {
|
||||
* @param {enumHubGoalRewards} reward
|
||||
*/
|
||||
showForLevel(level, reward) {
|
||||
this.elemTitle.innerText = "Level " + ("" + level).padStart(2, "0");
|
||||
this.elemTitle.innerText = T.ingame.levelCompleteNotification.levelTitle.replace(
|
||||
"<level>",
|
||||
("" + level).padStart(2, "0")
|
||||
);
|
||||
|
||||
let html = `<span class='reward'>Unlocked ${enumHubGoalRewardToString[reward]}!</span>`;
|
||||
const rewardText = T.storyRewards[reward];
|
||||
|
||||
let html =
|
||||
"<span class='reward'>" +
|
||||
T.ingame.levelCompleteNotification.unlockText.replace("<reward>", rewardText) +
|
||||
"</span>";
|
||||
|
||||
const addBuildingExplanation = metaBuildingClass => {
|
||||
const metaBuilding = gMetaBuildingRegistry.findByClass(metaBuildingClass);
|
||||
|
||||
@@ -6,6 +6,7 @@ import { Application } from "../application";
|
||||
|
||||
import { Signal, STOP_PROPAGATION } from "../core/signal";
|
||||
import { IS_MOBILE } from "../core/config";
|
||||
import { T } from "../translations";
|
||||
|
||||
function key(str) {
|
||||
return str.toUpperCase().charCodeAt(0);
|
||||
@@ -65,23 +66,23 @@ export function getStringForKeyCode(code) {
|
||||
case 8:
|
||||
return "⌫";
|
||||
case 9:
|
||||
return "TAB";
|
||||
return T.global.keys.tab;
|
||||
case 13:
|
||||
return "⏎";
|
||||
case 16:
|
||||
return "⇪";
|
||||
case 17:
|
||||
return "CTRL";
|
||||
return T.global.keys.control;
|
||||
case 18:
|
||||
return "ALT";
|
||||
return T.global.keys.alt;
|
||||
case 19:
|
||||
return "PAUSE";
|
||||
case 20:
|
||||
return "CAPS";
|
||||
case 27:
|
||||
return "ESC";
|
||||
return T.global.keys.escape;
|
||||
case 32:
|
||||
return "SPACE";
|
||||
return T.global.keys.space;
|
||||
case 33:
|
||||
return "PGUP";
|
||||
case 34:
|
||||
|
||||
@@ -31,20 +31,6 @@ export class MetaBuilding {
|
||||
return new Vector(1, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Should return the name of this building
|
||||
*/
|
||||
getName() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should return the description of this building
|
||||
*/
|
||||
getDescription() {
|
||||
return "No Description";
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to stay in placement mode after having placed a building
|
||||
*/
|
||||
|
||||
@@ -3,8 +3,8 @@ import { HubComponent } from "../components/hub";
|
||||
import { DrawParameters } from "../../core/draw_parameters";
|
||||
import { Entity } from "../entity";
|
||||
import { formatBigNumber } from "../../core/utils";
|
||||
import { enumHubGoalRewardToString } from "../tutorial_goals";
|
||||
import { Loader } from "../../core/loader";
|
||||
import { T } from "../../translations";
|
||||
|
||||
export class HubSystem extends GameSystemWithFilter {
|
||||
constructor(root) {
|
||||
@@ -84,7 +84,7 @@ export class HubSystem extends GameSystemWithFilter {
|
||||
context.font = "bold 11px GameFont";
|
||||
context.fillStyle = "#fd0752";
|
||||
context.textAlign = "center";
|
||||
context.fillText(enumHubGoalRewardToString[goals.reward].toUpperCase(), pos.x, pos.y + 46);
|
||||
context.fillText(T.storyRewards[goals.reward].toUpperCase(), pos.x, pos.y + 46);
|
||||
|
||||
// Level
|
||||
context.font = "bold 11px GameFont";
|
||||
|
||||
@@ -15,21 +15,6 @@ export const enumHubGoalRewards = {
|
||||
no_reward: "no_reward",
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
export const enumHubGoalRewardToString = {
|
||||
[enumHubGoalRewards.reward_cutter_and_trash]: "Cutting Shapes",
|
||||
[enumHubGoalRewards.reward_rotater]: "Rotating",
|
||||
[enumHubGoalRewards.reward_painter]: "Painting",
|
||||
[enumHubGoalRewards.reward_mixer]: "Color Mixing",
|
||||
[enumHubGoalRewards.reward_stacker]: "Combiner",
|
||||
[enumHubGoalRewards.reward_splitter]: "Splitter/Merger",
|
||||
[enumHubGoalRewards.reward_tunnel]: "Tunnel",
|
||||
|
||||
[enumHubGoalRewards.no_reward]: "Next level",
|
||||
};
|
||||
|
||||
export const tutorialGoals = [
|
||||
// Circle
|
||||
{
|
||||
|
||||
@@ -1,33 +1,8 @@
|
||||
import { findNiceIntegerValue } from "../core/utils";
|
||||
import { ShapeDefinition } from "./shape_definition";
|
||||
|
||||
export const TIER_LABELS = [
|
||||
"I",
|
||||
"II",
|
||||
"III",
|
||||
"IV",
|
||||
"V",
|
||||
"VI",
|
||||
"VII",
|
||||
"VIII",
|
||||
"IX",
|
||||
"X",
|
||||
"XI",
|
||||
"XII",
|
||||
"XIII",
|
||||
"XIV",
|
||||
"XV",
|
||||
"XVI",
|
||||
"XVII",
|
||||
"XVIII",
|
||||
"XIX",
|
||||
"XX",
|
||||
];
|
||||
|
||||
export const UPGRADES = {
|
||||
belt: {
|
||||
label: "Belts, Distributer & Tunnels",
|
||||
description: improvement => "Speed +" + Math.floor(improvement * 100.0) + "%",
|
||||
tiers: [
|
||||
{
|
||||
required: [{ shape: "CuCuCuCu", amount: 80 }],
|
||||
@@ -49,8 +24,6 @@ export const UPGRADES = {
|
||||
},
|
||||
|
||||
miner: {
|
||||
label: "Extraction",
|
||||
description: improvement => "Speed +" + Math.floor(improvement * 100.0) + "%",
|
||||
tiers: [
|
||||
{
|
||||
required: [{ shape: "RuRuRuRu", amount: 200 }],
|
||||
@@ -72,8 +45,6 @@ export const UPGRADES = {
|
||||
},
|
||||
|
||||
processors: {
|
||||
label: "Shape Processing",
|
||||
description: improvement => "Speed +" + Math.floor(improvement * 100.0) + "%",
|
||||
tiers: [
|
||||
{
|
||||
required: [{ shape: "SuSuSuSu", amount: 200 }],
|
||||
@@ -95,8 +66,6 @@ export const UPGRADES = {
|
||||
},
|
||||
|
||||
painting: {
|
||||
label: "Mixing & Painting",
|
||||
description: improvement => "Speed +" + Math.floor(improvement * 100.0) + "%",
|
||||
tiers: [
|
||||
{
|
||||
required: [{ shape: "WuWuWuWu", amount: 200 }],
|
||||
|
||||
@@ -7,6 +7,7 @@ import { createLogger } from "../../core/logging";
|
||||
import { ClickDetector } from "../../core/click_detector";
|
||||
import { performanceNow } from "../../core/builtins";
|
||||
import { clamp } from "../../core/utils";
|
||||
import { T } from "../../translations";
|
||||
|
||||
const logger = createLogger("adprovider/adinplay");
|
||||
|
||||
@@ -111,7 +112,7 @@ export class AdinplayAdProvider extends AdProviderInterface {
|
||||
AD_HEIGHT: h,
|
||||
AD_FULLSCREEN: false,
|
||||
AD_CENTERPLAYER: false,
|
||||
LOADING_TEXT: "Loading",
|
||||
LOADING_TEXT: T.global.loading,
|
||||
PREROLL_ELEM: function () {
|
||||
return videoElement;
|
||||
},
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
} from "../core/utils";
|
||||
import { ReadWriteProxy } from "../core/read_write_proxy";
|
||||
import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs";
|
||||
import { T } from "../translations";
|
||||
|
||||
export class MainMenuState extends GameState {
|
||||
constructor() {
|
||||
@@ -18,14 +19,12 @@ export class MainMenuState extends GameState {
|
||||
|
||||
getInnerHTML() {
|
||||
const bannerHtml = `
|
||||
<h3>This is a Demo Version</h3>
|
||||
<h3>${T.demoBanners.title}</h3>
|
||||
|
||||
<p>Get <strong>shapez.io on steam</strong> for:</p>
|
||||
<p>${T.demoBanners.intro}</p>
|
||||
|
||||
<ul>
|
||||
<li>No advertisements and demo banners.</li>
|
||||
<li>Unlimited savegame slots.</li>
|
||||
<li>Supporting the developer ❤️</li>
|
||||
${T.demoBanners.advantages.map(advantage => `<li>${advantage}</li>`).join("")}
|
||||
</ul>
|
||||
|
||||
<a href="https://steam.shapez.io" class="steamLink" target="_blank">Get shapez.io on steam!</a>
|
||||
@@ -65,12 +64,12 @@ export class MainMenuState extends GameState {
|
||||
isSupportedBrowser()
|
||||
? ""
|
||||
: `
|
||||
<div class="browserWarning">This game is optimized for Google Chrome. Your browser is not supported or slow!</div>
|
||||
<div class="browserWarning">${T.mainMenu.browserWarning}</div>
|
||||
`
|
||||
}
|
||||
|
||||
<button class="playButton styledButton">Play</button>
|
||||
<button class="importButton styledButton">Import savegame</button>
|
||||
<button class="playButton styledButton">${T.mainMenu.play}</button>
|
||||
<button class="importButton styledButton">${T.mainMenu.importSavegame}</button>
|
||||
</div>
|
||||
|
||||
${
|
||||
@@ -86,13 +85,13 @@ export class MainMenuState extends GameState {
|
||||
<div class="footer">
|
||||
|
||||
<a href="https://github.com/tobspr/shapez.io" target="_blank">
|
||||
This game is open source!
|
||||
${T.mainMenu.openSourceHint}
|
||||
<span class="thirdpartyLogo githubLogo"></span>
|
||||
</a>
|
||||
|
||||
</a>
|
||||
|
||||
<a href="https://discord.gg/HN7EVzV" target="_blank">
|
||||
Official discord server
|
||||
<span class="thirdpartyLogo discordLogo"></span>
|
||||
${T.mainMenu.discordLink}
|
||||
<span class="thirdpartyLogo discordLogo"></span>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
@@ -112,7 +111,6 @@ export class MainMenuState extends GameState {
|
||||
const reader = new FileReader();
|
||||
reader.addEventListener("load", event => {
|
||||
const contents = event.target.result;
|
||||
|
||||
let realContent;
|
||||
|
||||
try {
|
||||
@@ -120,8 +118,8 @@ export class MainMenuState extends GameState {
|
||||
} catch (err) {
|
||||
closeLoader();
|
||||
this.dialogs.showWarning(
|
||||
"Import error",
|
||||
"Failed to import your savegame:<br><br>" + err
|
||||
T.dialogs.importSavegameError.title,
|
||||
T.dialogs.importSavegameError.text + "<br><br>" + err
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -129,22 +127,27 @@ export class MainMenuState extends GameState {
|
||||
this.app.savegameMgr.importSavegame(realContent).then(
|
||||
() => {
|
||||
closeLoader();
|
||||
this.dialogs.showWarning("Imported", "Your savegame has been imported.");
|
||||
this.dialogs.showWarning(
|
||||
T.dialogs.importSavegameSuccess.title,
|
||||
T.dialogs.importSavegameSuccess.text
|
||||
);
|
||||
|
||||
this.renderSavegames();
|
||||
},
|
||||
err => {
|
||||
closeLoader();
|
||||
this.dialogs.showWarning(
|
||||
"Import error",
|
||||
"Failed to import savegame. Please check the console output."
|
||||
T.dialogs.importSavegameError.title,
|
||||
T.dialogs.importSavegameError.text + ":<br><br>" + err
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
reader.addEventListener("error", error => {
|
||||
console.error(error);
|
||||
alert("Failed to read file: " + error);
|
||||
this.dialogs.showWarning(
|
||||
T.dialogs.importSavegameError.title,
|
||||
T.dialogs.importSavegameError.text + ":<br><br>" + error
|
||||
);
|
||||
});
|
||||
reader.readAsText(file, "utf-8");
|
||||
});
|
||||
@@ -159,7 +162,10 @@ export class MainMenuState extends GameState {
|
||||
|
||||
onEnter(payload) {
|
||||
if (payload.loadError) {
|
||||
alert("Error while loading game: " + payload.loadError);
|
||||
this.dialogs.showWarning(
|
||||
T.dialogs.gameLoadFailure.title,
|
||||
T.dialogs.gameLoadFailure.text + "<br><br>" + payload.loadError
|
||||
);
|
||||
}
|
||||
|
||||
this.dialogs = new HUDModalDialogs(null, this.app);
|
||||
@@ -244,8 +250,8 @@ export class MainMenuState extends GameState {
|
||||
*/
|
||||
deleteGame(game) {
|
||||
const signals = this.dialogs.showWarning(
|
||||
"Confirm Deletion",
|
||||
"Are you sure you want to delete the game?",
|
||||
T.dialogs.confirmSavegameDelete.title,
|
||||
T.dialogs.confirmSavegameDelete.text,
|
||||
["delete:bad", "cancel:good"]
|
||||
);
|
||||
|
||||
@@ -255,7 +261,10 @@ export class MainMenuState extends GameState {
|
||||
this.renderSavegames();
|
||||
},
|
||||
err => {
|
||||
this.dialogs.showWarning("Failed to delete", "Error: " + err);
|
||||
this.dialogs.showWarning(
|
||||
T.dialogs.savegameDeletionError.title,
|
||||
T.dialogs.savegameDeletionError.text + "<br><br>" + err
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
20
src/js/translations.js
Normal file
20
src/js/translations.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import { globalConfig } from "./core/config";
|
||||
|
||||
const baseTranslations = require("./translations-built/base-en.json");
|
||||
|
||||
export const T = baseTranslations;
|
||||
|
||||
if (G_IS_DEV && globalConfig.debug.testTranslations) {
|
||||
// Replaces all translations by fake translations to see whats translated and what not
|
||||
const mapTranslations = obj => {
|
||||
for (const key in obj) {
|
||||
const value = obj[key];
|
||||
if (typeof value === "string") {
|
||||
obj[key] = value.replace(/[a-z]/gi, "x");
|
||||
} else {
|
||||
mapTranslations(value);
|
||||
}
|
||||
}
|
||||
};
|
||||
mapTranslations(T);
|
||||
}
|
||||
Reference in New Issue
Block a user