diff --git a/gulp/bundle-loader.js b/gulp/bundle-loader.js
index d8bb8c24..16db26fa 100644
--- a/gulp/bundle-loader.js
+++ b/gulp/bundle-loader.js
@@ -54,8 +54,11 @@
document.documentElement.appendChild(element);
}
- window.addEventListener("error", errorHandler);
- window.addEventListener("unhandledrejection", errorHandler);
+
+ if (window.location.host.indexOf("localhost") < 0) {
+ window.addEventListener("error", errorHandler);
+ window.addEventListener("unhandledrejection", errorHandler);
+ }
function makeJsTag(src, integrity) {
var script = document.createElement("script");
diff --git a/res/ui/building_icons/constant_producer.png b/res/ui/building_icons/constant_producer.png
index 887a3ae6..f7ac8afa 100644
Binary files a/res/ui/building_icons/constant_producer.png and b/res/ui/building_icons/constant_producer.png differ
diff --git a/res/ui/building_icons/goal_acceptor.png b/res/ui/building_icons/goal_acceptor.png
index 81451757..9087c155 100644
Binary files a/res/ui/building_icons/goal_acceptor.png and b/res/ui/building_icons/goal_acceptor.png differ
diff --git a/res/ui/languages/he.svg b/res/ui/languages/he.svg
new file mode 100644
index 00000000..aaa64e98
--- /dev/null
+++ b/res/ui/languages/he.svg
@@ -0,0 +1,42 @@
+
+
+
diff --git a/res_raw/sprites/buildings/goal_acceptor.png b/res_raw/sprites/buildings/goal_acceptor.png
index 9e5f0808..2ebf879a 100644
Binary files a/res_raw/sprites/buildings/goal_acceptor.png and b/res_raw/sprites/buildings/goal_acceptor.png differ
diff --git a/src/css/ingame_hud/mode_menu_back.scss b/src/css/ingame_hud/mode_menu_back.scss
index 56a489db..9f0a6c81 100644
--- a/src/css/ingame_hud/mode_menu_back.scss
+++ b/src/css/ingame_hud/mode_menu_back.scss
@@ -11,7 +11,6 @@
> .button {
@include PlainText;
- @include IncreasedClickArea(0px);
pointer-events: all;
cursor: pointer;
position: relative;
@@ -20,6 +19,8 @@
transition-property: opacity, transform;
text-transform: uppercase;
@include PlainText;
+ @include S(width, 30px);
+ @include S(height, 30px);
opacity: 1;
&:hover {
@@ -30,11 +31,9 @@
transform: scale(0.95) !important;
}
- @include S(padding-left, 25px);
-
& {
/* @load-async */
- background: uiResource("icons/state_back_button.png") left center / D(15px) no-repeat;
+ background: uiResource("icons/state_back_button.png") center center / D(15px) no-repeat;
}
}
}
diff --git a/src/css/ingame_hud/mode_menu_next.scss b/src/css/ingame_hud/mode_menu_next.scss
index 7c0cfb4b..2deb4965 100644
--- a/src/css/ingame_hud/mode_menu_next.scss
+++ b/src/css/ingame_hud/mode_menu_next.scss
@@ -1,6 +1,6 @@
#ingame_HUD_ModeMenuNext {
position: absolute;
- @include S(top, 10px);
+ @include S(top, 15px);
@include S(right, 10px);
display: flex;
diff --git a/src/css/ingame_hud/puzzle_dlc_logo.scss b/src/css/ingame_hud/puzzle_dlc_logo.scss
index 921e853c..fc3b4c76 100644
--- a/src/css/ingame_hud/puzzle_dlc_logo.scss
+++ b/src/css/ingame_hud/puzzle_dlc_logo.scss
@@ -2,8 +2,8 @@
position: absolute;
@include S(width, 150px);
@include S(height, 40px);
- @include S(bottom, 10px);
- @include S(right, 15px);
+ @include S(left, 50px);
+ @include S(top, 10px);
& {
/* @load-async */
diff --git a/src/css/ingame_hud/puzzle_editor_controls.scss b/src/css/ingame_hud/puzzle_editor_controls.scss
new file mode 100644
index 00000000..eb402aa2
--- /dev/null
+++ b/src/css/ingame_hud/puzzle_editor_controls.scss
@@ -0,0 +1,26 @@
+#ingame_HUD_PuzzleEditorControls {
+ position: absolute;
+
+ @include S(top, 70px);
+ @include S(left, 10px);
+
+ display: flex;
+ flex-direction: column;
+ @include SuperDuperSmallText;
+ @include S(width, 200px);
+
+ > span {
+ @include S(margin-bottom, 10px);
+ }
+}
+
+#ingame_HUD_PuzzleEditorTitle {
+ position: absolute;
+
+ @include S(top, 23px);
+ left: 50%;
+ transform: translateX(-50%);
+ text-transform: uppercase;
+ @include Heading;
+ text-align: center;
+}
diff --git a/src/css/main.scss b/src/css/main.scss
index 89ebbb10..d703663c 100644
--- a/src/css/main.scss
+++ b/src/css/main.scss
@@ -61,6 +61,7 @@
@import "ingame_hud/mode_menu";
@import "ingame_hud/mode_settings";
@import "ingame_hud/puzzle_dlc_logo";
+@import "ingame_hud/puzzle_editor_controls";
// prettier-ignore
$elements:
@@ -80,6 +81,8 @@ ingame_HUD_GameMenu,
ingame_HUD_KeybindingOverlay,
ingame_HUD_ModeMenuBack,
ingame_HUD_ModeMenuNext,
+ingame_HUD_PuzzleEditorControls,
+ingame_HUD_PuzzleEditorTitle,
ingame_HUD_ModeMenu,
ingame_HUD_ModeSettings,
ingame_HUD_Notifications,
diff --git a/src/css/resources.scss b/src/css/resources.scss
index 769829f6..158db23d 100644
--- a/src/css/resources.scss
+++ b/src/css/resources.scss
@@ -68,7 +68,7 @@ $icons: notification_saved, notification_success, notification_upgrade;
}
$languages: en, de, cs, da, et, es-419, fr, it, pt-BR, sv, tr, el, ru, uk, zh-TW, zh-CN, nb, mt-MT, ar, nl, vi,
- th, hu, pl, ja, kor, no, pt-PT, fi, ro;
+ th, hu, pl, ja, kor, no, pt-PT, fi, ro, he;
@each $language in $languages {
[data-languageicon="#{$language}"] {
diff --git a/src/css/states/puzzle_menu.scss b/src/css/states/puzzle_menu.scss
index e3c139a8..75541d8d 100644
--- a/src/css/states/puzzle_menu.scss
+++ b/src/css/states/puzzle_menu.scss
@@ -124,16 +124,17 @@
@include SuperSmallText;
grid-column: 2 / 3;
grid-row: 3 / 4;
- color: $accentColorDark;
+ color: #444;
align-self: end;
justify-self: end;
font-weight: bold;
@include S(padding-right, 12px);
+ opacity: 0.89;
& {
/* @load-async */
background: uiResource("icons/puzzle_upvotes.png") calc(100% - #{D(2px)}) #{D(
- 3.3px
+ 3.5px
)} / #{D(8px)} #{D(8px)} no-repeat;
}
}
diff --git a/src/js/core/animation_frame.js b/src/js/core/animation_frame.js
index eeefb4b0..6aa629a5 100644
--- a/src/js/core/animation_frame.js
+++ b/src/js/core/animation_frame.js
@@ -51,9 +51,12 @@ export class AnimationFrame {
dt = resetDtMs;
}
- this.frameEmitted.dispatch(dt);
+ try {
+ this.frameEmitted.dispatch(dt);
+ } catch (ex) {
+ console.error(ex);
+ }
this.lastTime = time;
-
window.requestAnimationFrame(this.boundMethod);
}
}
diff --git a/src/js/core/error_handler.js b/src/js/core/error_handler.js
index 686e4e4e..c149ba76 100644
--- a/src/js/core/error_handler.js
+++ b/src/js/core/error_handler.js
@@ -123,4 +123,6 @@ function catchErrors(message, source, lineno, colno, error) {
return true;
}
-window.onerror = catchErrors;
+if (!G_IS_DEV) {
+ window.onerror = catchErrors;
+}
diff --git a/src/js/game/camera.js b/src/js/game/camera.js
index 68968d6b..d59f1059 100644
--- a/src/js/game/camera.js
+++ b/src/js/game/camera.js
@@ -763,13 +763,14 @@ export class Camera extends BasicSerializableObject {
* Clamps the center within set boundaries
*/
clampToBounds() {
- if (!this.root.gameMode.hasBounds()) {
+ const bounds = this.root.gameMode.getCameraBounds();
+ if (!bounds) {
return;
}
- const bounds = this.root.gameMode.getBounds().allScaled(globalConfig.tileSize);
- this.center.x = clamp(this.center.x, bounds.x, bounds.x + bounds.w);
- this.center.y = clamp(this.center.y, bounds.y, bounds.y + bounds.h);
+ const tileScaleBounds = this.root.gameMode.getCameraBounds().allScaled(globalConfig.tileSize);
+ this.center.x = clamp(this.center.x, tileScaleBounds.x, tileScaleBounds.x + tileScaleBounds.w);
+ this.center.y = clamp(this.center.y, tileScaleBounds.y, tileScaleBounds.y + tileScaleBounds.h);
}
/**
diff --git a/src/js/game/components/goal_acceptor.js b/src/js/game/components/goal_acceptor.js
index 72c157d7..869dd3f6 100644
--- a/src/js/game/components/goal_acceptor.js
+++ b/src/js/game/components/goal_acceptor.js
@@ -14,9 +14,7 @@ export class GoalAcceptorComponent extends Component {
constructor({ item = null, rate = null }) {
super();
this.item = item;
- this.rate = rate;
this.achieved = false;
- this.achievedOnce = false;
}
}
diff --git a/src/js/game/core.js b/src/js/game/core.js
index d9d73cae..3333d1da 100644
--- a/src/js/game/core.js
+++ b/src/js/game/core.js
@@ -83,6 +83,8 @@ export class GameCore {
* @param {Savegame} savegame
*/
initializeRoot(parentState, savegame, gameModeId) {
+ logger.log("initializing root");
+
// Construct the root element, this is the data representation of the game
this.root = new GameRoot(this.app);
this.root.gameState = parentState;
@@ -157,6 +159,8 @@ export class GameCore {
}
});
}
+
+ logger.log("root initialized");
}
/**
diff --git a/src/js/game/game_mode.js b/src/js/game/game_mode.js
index 31189306..b9d830d3 100644
--- a/src/js/game/game_mode.js
+++ b/src/js/game/game_mode.js
@@ -5,6 +5,8 @@ import { Rectangle } from "../core/rectangle";
import { gGameModeRegistry } from "../core/global_registries";
import { types, BasicSerializableObject } from "../savegame/serialization";
+import { MetaBuilding } from "./meta_building";
+import { MetaItemProducerBuilding } from "./buildings/item_producer";
/** @enum {string} */
export const enumGameModeIds = {
@@ -45,8 +47,10 @@ export class GameMode extends BasicSerializableObject {
constructor(root) {
super();
this.root = root;
- this.hudParts = {};
- this.buildings = {};
+ this.hiddenHurtParts = {};
+
+ /** @type {typeof MetaBuilding[]} */
+ this.hiddenBuildings = [MetaItemProducerBuilding];
}
/** @returns {object} */
@@ -74,33 +78,30 @@ export class GameMode extends BasicSerializableObject {
return this.constructor.getType();
}
- setBuildings(buildings) {
- Object.assign(this.buildings, buildings);
- }
-
- setHudParts(parts) {
- Object.assign(this.hudParts, parts);
- }
-
/**
* @param {string} name - Class name of HUD Part
* @returns {boolean}
*/
isHudPartExcluded(name) {
- return this.hudParts[name] === false;
+ return this.hiddenHurtParts[name] === false;
}
/**
- * @param {string} name - Class name of building
+ * @param {typeof MetaBuilding} building - Class name of building
* @returns {boolean}
*/
- isBuildingExcluded(name) {
- return this.buildings[name] === false;
+ isBuildingExcluded(building) {
+ return this.hiddenBuildings.indexOf(building) >= 0;
}
- /** @returns {boolean} */
- hasZone() {
- return false;
+ /** @returns {undefined|Rectangle[]} */
+ getBuildableZones() {
+ return;
+ }
+
+ /** @returns {Rectangle|undefined} */
+ getCameraBounds() {
+ return;
}
/** @returns {boolean} */
@@ -113,21 +114,6 @@ export class GameMode extends BasicSerializableObject {
return true;
}
- /** @returns {boolean} */
- hasBounds() {
- return false;
- }
-
- /** @returns {boolean} */
- isZoneRestricted() {
- return false;
- }
-
- /** @returns {boolean} */
- isBoundaryRestricted() {
- return false;
- }
-
/** @returns {number} */
getMinimumZoom() {
return 0.1;
@@ -148,9 +134,8 @@ export class GameMode extends BasicSerializableObject {
};
}
- /** @returns {?Rectangle} */
- getZone() {
- return null;
+ throughputDoesNotMatter() {
+ return false;
}
/**
@@ -162,11 +147,6 @@ export class GameMode extends BasicSerializableObject {
return;
}
- /** @returns {?Rectangle} */
- getBounds() {
- return null;
- }
-
/** @returns {array} */
getLevelDefinitions() {
return [];
@@ -187,6 +167,11 @@ export class GameMode extends BasicSerializableObject {
return true;
}
+ /** @returns {boolean} */
+ getSupportsWires() {
+ return true;
+ }
+
/** @returns {string} */
getBlueprintShapeKey() {
return "CbCbCbRb:CwCwCwCw";
diff --git a/src/js/game/game_system_manager.js b/src/js/game/game_system_manager.js
index 9220acaa..08609f89 100644
--- a/src/js/game/game_system_manager.js
+++ b/src/js/game/game_system_manager.js
@@ -183,7 +183,7 @@ export class GameSystemManager {
add("goalAcceptor", GoalAcceptorSystem);
- if (this.root.gameMode.hasZone()) {
+ if (this.root.gameMode.getBuildableZones()) {
add("zone", ZoneSystem);
}
diff --git a/src/js/game/hub_goals.js b/src/js/game/hub_goals.js
index b3536a3c..fee1bd79 100644
--- a/src/js/game/hub_goals.js
+++ b/src/js/game/hub_goals.js
@@ -184,6 +184,10 @@ export class HubGoals extends BasicSerializableObject {
* @param {string} upgradeId
*/
getUpgradeLevel(upgradeId) {
+ if (this.root.gameMode.throughputDoesNotMatter()) {
+ return 10;
+ }
+
return this.upgradeLevels[upgradeId] || 0;
}
@@ -195,6 +199,10 @@ export class HubGoals extends BasicSerializableObject {
if (G_IS_DEV && globalConfig.debug.allBuildingsUnlocked) {
return true;
}
+ if (this.root.gameMode.getLevelDefinitions().length < 1) {
+ // no story, so always unlocked
+ return true;
+ }
return !!this.gainedRewards[reward];
}
@@ -472,6 +480,9 @@ export class HubGoals extends BasicSerializableObject {
* @returns {number} items / sec
*/
getBeltBaseSpeed() {
+ if (this.root.gameMode.throughputDoesNotMatter()) {
+ return globalConfig.beltSpeedItemsPerSecond * 5;
+ }
return globalConfig.beltSpeedItemsPerSecond * this.upgradeImprovements.belt;
}
@@ -480,6 +491,9 @@ export class HubGoals extends BasicSerializableObject {
* @returns {number} items / sec
*/
getUndergroundBeltBaseSpeed() {
+ if (this.root.gameMode.throughputDoesNotMatter()) {
+ return globalConfig.beltSpeedItemsPerSecond * 5;
+ }
return globalConfig.beltSpeedItemsPerSecond * this.upgradeImprovements.belt;
}
@@ -488,6 +502,9 @@ export class HubGoals extends BasicSerializableObject {
* @returns {number} items / sec
*/
getMinerBaseSpeed() {
+ if (this.root.gameMode.throughputDoesNotMatter()) {
+ return globalConfig.minerSpeedItemsPerSecond * 5;
+ }
return globalConfig.minerSpeedItemsPerSecond * this.upgradeImprovements.miner;
}
@@ -497,6 +514,10 @@ export class HubGoals extends BasicSerializableObject {
* @returns {number} items / sec
*/
getProcessorBaseSpeed(processorType) {
+ if (this.root.gameMode.throughputDoesNotMatter()) {
+ return 10;
+ }
+
switch (processorType) {
case enumItemProcessorTypes.trash:
case enumItemProcessorTypes.hub:
diff --git a/src/js/game/hud/hud.js b/src/js/game/hud/hud.js
index 8f4257b9..7d0646f4 100644
--- a/src/js/game/hud/hud.js
+++ b/src/js/game/hud/hud.js
@@ -32,6 +32,7 @@ import { HUDModeSettings } from "./parts/mode_settings";
import { enumNotificationType, HUDNotifications } from "./parts/notifications";
import { HUDPinnedShapes } from "./parts/pinned_shapes";
import { HUDPuzzleDLCLogo } from "./parts/puzzle_dlc_logo";
+import { HUDPuzzleEditorControls } from "./parts/puzzle_editor_controls";
import { HUDSandboxController } from "./parts/sandbox_controller";
import { HUDScreenshotExporter } from "./parts/screenshot_exporter";
import { HUDSettingsMenu } from "./parts/settings_menu";
@@ -95,6 +96,7 @@ export class GameHUD {
modeMenu: HUDModeMenu,
modeSettings: HUDModeSettings,
puzzleDlcLogo: HUDPuzzleDLCLogo,
+ puzzleEditorControls: HUDPuzzleEditorControls,
// Must always exist
pinnedShapes: HUDPinnedShapes,
diff --git a/src/js/game/hud/parts/base_toolbar.js b/src/js/game/hud/parts/base_toolbar.js
index 01e9fafa..9df362f3 100644
--- a/src/js/game/hud/parts/base_toolbar.js
+++ b/src/js/game/hud/parts/base_toolbar.js
@@ -55,7 +55,7 @@ export class HUDBaseToolbar extends BaseHUDPart {
const filtered = [];
for (let i = 0; i < buildings.length; i++) {
- if (this.root.gameMode.isBuildingExcluded(buildings[i].name)) {
+ if (this.root.gameMode.isBuildingExcluded(buildings[i])) {
continue;
}
diff --git a/src/js/game/hud/parts/mode_menu_back.js b/src/js/game/hud/parts/mode_menu_back.js
index 9eae74cc..ebe8b1e6 100644
--- a/src/js/game/hud/parts/mode_menu_back.js
+++ b/src/js/game/hud/parts/mode_menu_back.js
@@ -1,6 +1,5 @@
-import { BaseHUDPart } from "../base_hud_part";
import { makeDiv } from "../../../core/utils";
-import { T } from "../../../translations";
+import { BaseHUDPart } from "../base_hud_part";
export class HUDModeMenuBack extends BaseHUDPart {
createElements(parent) {
@@ -9,7 +8,6 @@ export class HUDModeMenuBack extends BaseHUDPart {
this.element = makeDiv(parent, "ingame_HUD_ModeMenuBack");
this.button = document.createElement("button");
this.button.classList.add("button");
- this.button.textContent = T.ingame.modeMenu[key].back.title;
this.element.appendChild(this.button);
this.trackClicks(this.button, this.back);
diff --git a/src/js/game/hud/parts/mode_settings.js b/src/js/game/hud/parts/mode_settings.js
index a1dd220a..48e4defe 100644
--- a/src/js/game/hud/parts/mode_settings.js
+++ b/src/js/game/hud/parts/mode_settings.js
@@ -8,7 +8,8 @@ export class HUDModeSettings extends BaseHUDPart {
const bind = (selector, handler) => this.trackClicks(this.element.querySelector(selector), handler);
- if (this.root.gameMode.hasZone()) {
+ // @fixme
+ if (this.root.gameMode.getBuildableZones()) {
this.zone = makeDiv(
this.element,
null,
@@ -52,7 +53,12 @@ export class HUDModeSettings extends BaseHUDPart {
}
updateZoneValues() {
- const zone = this.root.gameMode.getZone();
+ const zones = this.root.gameMode.getBuildableZones();
+ if (!zones || zones.length === 0) {
+ return;
+ }
+
+ const zone = zones[0];
this.element.querySelector(".zoneWidth > .value").textContent = String(zone.w);
this.element.querySelector(".zoneHeight > .value").textContent = String(zone.h);
}
diff --git a/src/js/game/hud/parts/puzzle_editor_controls.js b/src/js/game/hud/parts/puzzle_editor_controls.js
new file mode 100644
index 00000000..77d609b7
--- /dev/null
+++ b/src/js/game/hud/parts/puzzle_editor_controls.js
@@ -0,0 +1,21 @@
+import { makeDiv } from "../../../core/utils";
+import { BaseHUDPart } from "../base_hud_part";
+
+export class HUDPuzzleEditorControls extends BaseHUDPart {
+ createElements(parent) {
+ this.element = makeDiv(parent, "ingame_HUD_PuzzleEditorControls");
+
+ this.element.innerHTML = `
+
+ 1. Build constant producers to generate resources.
+ 2. Build goal acceptors the capture shapes.
+ 3. Produce your desired shape(s) within the puzzle area and deliver it to the goal acceptors, which will capture it.
+ 4. Once you are done, press 'Playtest' to validate your puzzle.
+ `;
+
+ this.titleElement = makeDiv(parent, "ingame_HUD_PuzzleEditorTitle");
+ this.titleElement.innerText = "Puzzle Editor";
+ }
+
+ initialize() {}
+}
diff --git a/src/js/game/hud/parts/wires_overlay.js b/src/js/game/hud/parts/wires_overlay.js
index 2fd3092c..328d6689 100644
--- a/src/js/game/hud/parts/wires_overlay.js
+++ b/src/js/game/hud/parts/wires_overlay.js
@@ -28,6 +28,9 @@ export class HUDWiresOverlay extends BaseHUDPart {
* Switches between layers
*/
switchLayers() {
+ if (!this.root.gameMode.getSupportsWires()) {
+ return;
+ }
if (this.root.currentLayer === "regular") {
if (
this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_wires_painter_and_levers) ||
diff --git a/src/js/game/map_chunk_view.js b/src/js/game/map_chunk_view.js
index 06ff7337..59bff340 100644
--- a/src/js/game/map_chunk_view.js
+++ b/src/js/game/map_chunk_view.js
@@ -41,7 +41,7 @@ export class MapChunkView extends MapChunk {
*/
drawBackgroundLayer(parameters) {
const systems = this.root.systemMgr.systems;
- if (this.root.gameMode.hasZone()) {
+ if (systems.zone) {
systems.zone.drawChunk(parameters, this);
}
diff --git a/src/js/game/modes/puzzle.js b/src/js/game/modes/puzzle.js
index 31cfcb3d..15b0c868 100644
--- a/src/js/game/modes/puzzle.js
+++ b/src/js/game/modes/puzzle.js
@@ -32,7 +32,7 @@ export class PuzzleGameMode extends GameMode {
const data = this.getSaveData();
- this.setHudParts({
+ this.hiddenHurtParts = {
[HUDGameMenu.name]: false,
[HUDMassSelector.name]: false,
[HUDInteractiveTutorial.name]: false,
@@ -40,7 +40,7 @@ export class PuzzleGameMode extends GameMode {
[HUDPartTutorialHints.name]: false,
[HUDPinnedShapes.name]: false,
[HUDWaypoints.name]: false,
- });
+ };
this.setDimensions(data.zoneWidth, data.zoneHeight);
}
@@ -48,17 +48,13 @@ export class PuzzleGameMode extends GameMode {
setDimensions(w = 16, h = 9) {
this.zoneWidth = w < 2 ? 2 : w;
this.zoneHeight = h < 2 ? 2 : h;
- this.boundsHeight = this.zoneHeight < 8 ? 8 : this.zoneHeight;
- this.boundsWidth = this.zoneWidth < 8 ? 8 : this.zoneWidth;
}
getSaveData() {
const save = this.root.savegame.getCurrentDump();
-
if (!save) {
return {};
}
-
return save.gameMode.data;
}
@@ -66,46 +62,12 @@ export class PuzzleGameMode extends GameMode {
return new Rectangle(-Math.ceil(width / 2), -Math.ceil(height / 2), width, height);
}
- getBounds() {
- if (this.bounds) {
- return this.bounds;
- }
-
- this.bounds = this.createCenteredRectangle(this.boundsWidth, this.boundsHeight);
-
- return this.bounds;
+ getCameraBounds() {
+ return this.createCenteredRectangle(this.zoneWidth + 20, this.zoneHeight + 20);
}
- getZone() {
- if (this.zone) {
- return this.zone;
- }
-
- this.zone = this.createCenteredRectangle(this.zoneWidth, this.zoneHeight);
-
- return this.zone;
- }
-
- /**
- * Overrides GameMode's implementation to treat buildings like a whitelist
- * instead of a blacklist by default.
- * @param {string} name - Class name of building
- * @returns {boolean}
- */
- isBuildingExcluded(name) {
- return this.buildings[name] !== true;
- }
-
- isInBounds(x, y) {
- return this.bounds.containsPoint(x, y);
- }
-
- isInZone(x, y) {
- return this.zone.containsPoint(x, y);
- }
-
- hasZone() {
- return true;
+ getBuildableZones() {
+ return [this.createCenteredRectangle(this.zoneWidth, this.zoneHeight)];
}
hasHub() {
@@ -116,10 +78,6 @@ export class PuzzleGameMode extends GameMode {
return false;
}
- hasBounds() {
- return true;
- }
-
getMinimumZoom() {
return 1;
}
@@ -132,6 +90,14 @@ export class PuzzleGameMode extends GameMode {
return false;
}
+ throughputDoesNotMatter() {
+ return true;
+ }
+
+ getSupportsWires() {
+ return false;
+ }
+
/** @returns {boolean} */
getIsFreeplayAvailable() {
return true;
diff --git a/src/js/game/modes/puzzle_edit.js b/src/js/game/modes/puzzle_edit.js
index f927b001..680778aa 100644
--- a/src/js/game/modes/puzzle_edit.js
+++ b/src/js/game/modes/puzzle_edit.js
@@ -2,12 +2,23 @@
import { GameRoot } from "../root";
/* typehints:end */
-// import { MetaBeltBuilding } from "../buildings/belt";
-import { MetaConstantProducerBuilding } from "../buildings/constant_producer";
-import { MetaGoalAcceptorBuilding } from "../buildings/goal_acceptor";
-// import { MetaItemProducerBuilding } from "../buildings/item_producer";
import { enumGameModeIds } from "../game_mode";
import { PuzzleGameMode } from "./puzzle";
+import { MetaStorageBuilding } from "../buildings/storage";
+import { MetaReaderBuilding } from "../buildings/reader";
+import { MetaFilterBuilding } from "../buildings/filter";
+import { MetaDisplayBuilding } from "../buildings/display";
+import { MetaLeverBuilding } from "../buildings/lever";
+import { MetaItemProducerBuilding } from "../buildings/item_producer";
+import { MetaMinerBuilding } from "../buildings/miner";
+import { MetaWireBuilding } from "../buildings/wire";
+import { MetaWireTunnelBuilding } from "../buildings/wire_tunnel";
+import { MetaConstantSignalBuilding } from "../buildings/constant_signal";
+import { MetaLogicGateBuilding } from "../buildings/logic_gate";
+import { MetaVirtualProcessorBuilding } from "../buildings/virtual_processor";
+import { MetaAnalyzerBuilding } from "../buildings/analyzer";
+import { MetaComparatorBuilding } from "../buildings/comparator";
+import { MetaTransistorBuilding } from "../buildings/transistor";
export class PuzzleEditGameMode extends PuzzleGameMode {
static getId() {
@@ -24,18 +35,24 @@ export class PuzzleEditGameMode extends PuzzleGameMode {
this.playtest = false;
- this.setBuildings({
- [MetaConstantProducerBuilding.name]: true,
- [MetaGoalAcceptorBuilding.name]: true,
- });
- }
+ this.hiddenBuildings = [
+ MetaStorageBuilding,
+ MetaReaderBuilding,
+ MetaFilterBuilding,
+ MetaDisplayBuilding,
+ MetaLeverBuilding,
+ MetaItemProducerBuilding,
+ MetaMinerBuilding,
- isZoneRestricted() {
- return !this.playtest;
- }
-
- isBoundaryRestricted() {
- return this.playtest;
+ MetaWireBuilding,
+ MetaWireTunnelBuilding,
+ MetaConstantSignalBuilding,
+ MetaLogicGateBuilding,
+ MetaVirtualProcessorBuilding,
+ MetaAnalyzerBuilding,
+ MetaComparatorBuilding,
+ MetaTransistorBuilding,
+ ];
}
expandZone(w = 0, h = 0) {
diff --git a/src/js/game/modes/regular.js b/src/js/game/modes/regular.js
index 4f8e9ec2..1e84a115 100644
--- a/src/js/game/modes/regular.js
+++ b/src/js/game/modes/regular.js
@@ -518,19 +518,15 @@ export class RegularGameMode extends GameMode {
constructor(root) {
super(root);
- this.setHudParts({
+ this.hiddenHurtParts = {
[HUDModeMenuBack.name]: false,
[HUDModeMenuNext.name]: false,
[HUDModeMenu.name]: false,
[HUDModeSettings.name]: false,
[HUDPuzzleDLCLogo.name]: false,
- });
+ };
- this.setBuildings({
- [MetaConstantProducerBuilding.name]: false,
- [MetaGoalAcceptorBuilding.name]: false,
- [MetaItemProducerBuilding.name]: queryParamOptions.sandboxMode || G_IS_DEV,
- });
+ this.hiddenBuildings = [MetaConstantProducerBuilding, MetaGoalAcceptorBuilding];
}
/**
diff --git a/src/js/game/systems/goal_acceptor.js b/src/js/game/systems/goal_acceptor.js
index e24eb80b..6fcb479e 100644
--- a/src/js/game/systems/goal_acceptor.js
+++ b/src/js/game/systems/goal_acceptor.js
@@ -49,25 +49,17 @@ export class GoalAcceptorSystem extends GameSystemWithFilter {
const itemInput = new FormElementInput({
id: "goalItemInput",
- label: fillInLinkIntoTranslation(T.dialogs.editSignal.descShortKey, THIRDPARTY_URLS.shapeViewer),
+ label: fillInLinkIntoTranslation(T.dialogs.editGoalAcceptor.desc, THIRDPARTY_URLS.shapeViewer),
placeholder: "CuCuCuCu",
defaultValue: "CuCuCuCu",
validator: val => this.parseItem(val),
});
- const rateInput = new FormElementInput({
- id: "goalRateInput",
- label: "Rate:",
- placeholder: "0",
- defaultValue: "0",
- validator: val => !isNaN(Number(val)),
- });
-
const dialog = new DialogWithForm({
app: this.root.app,
- title: "Set Goal",
+ title: T.dialogs.editGoalAcceptor.title,
desc: "",
- formElements: [itemInput, rateInput],
+ formElements: [itemInput],
buttons: ["cancel:bad:escape", "ok:good:enter"],
closeButton: false,
});
@@ -79,7 +71,6 @@ export class GoalAcceptorSystem extends GameSystemWithFilter {
}
goalComp.item = this.parseItem(itemInput.getValue());
- goalComp.rate = this.parseRate(rateInput.getValue());
};
dialog.buttonSignals.ok.add(closeHandler);
diff --git a/src/js/game/systems/zone.js b/src/js/game/systems/zone.js
index 3dd68804..7e977438 100644
--- a/src/js/game/systems/zone.js
+++ b/src/js/game/systems/zone.js
@@ -13,8 +13,12 @@ export class ZoneSystem extends GameSystem {
/** @param {GameRoot} root */
constructor(root) {
super(root);
-
+ this.drawn = false;
this.root.signals.prePlacementCheck.add(this.prePlacementCheck, this);
+
+ this.root.signals.gameFrameStarted.add(() => {
+ this.drawn = false;
+ });
}
prePlacementCheck(entity, tile = null) {
@@ -25,18 +29,24 @@ export class ZoneSystem extends GameSystem {
}
const mode = this.root.gameMode;
- const zone = mode.getZone().expandedInAllDirections(-1);
+
+ const zones = mode.getBuildableZones();
+ if (!zones) {
+ return;
+ }
+
const transformed = staticComp.getTileSpaceBounds();
- if (zone.containsRect(transformed)) {
- if (mode.isZoneRestricted()) {
- return STOP_PROPAGATION;
- }
- } else {
- if (mode.isBoundaryRestricted()) {
- return STOP_PROPAGATION;
+ let withinAnyZone = false;
+ for (const zone of zones) {
+ if (zone.expandedInAllDirections(-1).containsRect(transformed)) {
+ withinAnyZone = true;
}
}
+
+ if (!withinAnyZone) {
+ return STOP_PROPAGATION;
+ }
}
/**
@@ -45,18 +55,46 @@ export class ZoneSystem extends GameSystem {
* @param {MapChunkView} chunk
*/
drawChunk(parameters, chunk) {
+ if (this.drawn) {
+ // oof
+ return;
+ }
+ this.drawn = true;
+
const mode = this.root.gameMode;
- const zone = mode.getZone().allScaled(globalConfig.tileSize);
+
+ const zones = mode.getBuildableZones();
+ if (!zones) {
+ return;
+ }
+
+ const zone = zones[0].allScaled(globalConfig.tileSize);
const context = parameters.context;
- context.globalAlpha = 0.1;
- context.fillStyle = THEME.map.zone.background;
- context.fillRect(zone.x, zone.y, zone.w, zone.h);
-
- context.globalAlpha = 1;
- context.strokeStyle = THEME.map.zone.border;
context.lineWidth = 2;
- context.strokeRect(zone.x, zone.y, zone.w, zone.h);
+ context.strokeStyle = THEME.map.zone.borderSolid;
+ context.beginPath();
+ context.rect(zone.x, zone.y, zone.w, zone.h);
+
+ context.stroke();
+
+ const outer = zone;
+ const padding = 40 * globalConfig.tileSize;
+ context.fillStyle = THEME.map.zone.outerColor;
+ context.fillRect(outer.x + outer.w, outer.y, padding, outer.h);
+ context.fillRect(outer.x - padding, outer.y, padding, outer.h);
+ context.fillRect(
+ outer.x - padding - globalConfig.tileSize,
+ outer.y - padding,
+ 2 * padding + zone.w + 2 * globalConfig.tileSize,
+ padding
+ );
+ context.fillRect(
+ outer.x - padding - globalConfig.tileSize,
+ outer.y + outer.h,
+ 2 * padding + zone.w + 2 * globalConfig.tileSize,
+ padding
+ );
context.globalAlpha = 1;
}
diff --git a/src/js/game/themes/dark.json b/src/js/game/themes/dark.json
index 02ff6ae3..010f9251 100644
--- a/src/js/game/themes/dark.json
+++ b/src/js/game/themes/dark.json
@@ -50,8 +50,10 @@
},
"zone": {
- "background": "#3e3f47",
- "border": "#667964"
+ "background": "#fff",
+ "border": "rgba(23, 192, 255, 0.1)",
+ "borderSolid": "rgba(23, 192, 255, 0.7)",
+ "outerColor": "rgba(240, 240, 255, 0.5)"
}
},
diff --git a/src/js/game/themes/light.json b/src/js/game/themes/light.json
index 4aa367fd..c39e19f0 100644
--- a/src/js/game/themes/light.json
+++ b/src/js/game/themes/light.json
@@ -52,7 +52,9 @@
"zone": {
"background": "#fff",
- "border": "#cbffc4"
+ "border": "rgba(23, 192, 255, 0.1)",
+ "borderSolid": "rgba(23, 192, 255, 0.7)",
+ "outerColor": "rgba(240, 240, 255, 0.5)"
}
},
diff --git a/src/js/languages.js b/src/js/languages.js
index 6899ef09..4dfb15d4 100644
--- a/src/js/languages.js
+++ b/src/js/languages.js
@@ -184,4 +184,12 @@ export const LANGUAGES = {
code: "uk",
region: "",
},
+
+ "he": {
+ // hebrew
+ name: "עברית",
+ data: require("./built-temp/base-he.json"),
+ code: "he",
+ region: "",
+ },
};
diff --git a/src/js/states/ingame.js b/src/js/states/ingame.js
index 32ef3edc..a872b6f6 100644
--- a/src/js/states/ingame.js
+++ b/src/js/states/ingame.js
@@ -370,7 +370,13 @@ export class InGameState extends GameState {
// Remove unneded default element
document.body.querySelector(".modalDialogParent").remove();
- this.asyncChannel.watch(waitNextFrame()).then(() => this.stage3CreateCore());
+ this.asyncChannel
+ .watch(waitNextFrame())
+ .then(() => this.stage3CreateCore())
+ .catch(ex => {
+ logger.error(ex);
+ throw ex;
+ });
}
/**
diff --git a/src/js/states/puzzle_menu.js b/src/js/states/puzzle_menu.js
index d6465627..8b6c8fcb 100644
--- a/src/js/states/puzzle_menu.js
+++ b/src/js/states/puzzle_menu.js
@@ -1,3 +1,4 @@
+import { globalConfig } from "../core/config";
import { TextualGameState } from "../core/textual_game_state";
import { formatBigNumberFull } from "../core/utils";
import { enumGameModeIds } from "../game/game_mode";
@@ -206,6 +207,10 @@ export class PuzzleMenuState extends TextualGameState {
}
this.trackClicks(this.htmlElement.querySelector("button.createPuzzle"), this.createNewPuzzle);
+
+ if (G_IS_DEV && globalConfig.debug.testPuzzleMode) {
+ this.createNewPuzzle();
+ }
}
createNewPuzzle() {
diff --git a/translations/base-en.yaml b/translations/base-en.yaml
index 29c610a7..f02b8335 100644
--- a/translations/base-en.yaml
+++ b/translations/base-en.yaml
@@ -248,6 +248,10 @@ dialogs:
Choose a pre-defined item:
descShortKey: ... or enter the short key of a shape (Which you can generate here)
+ editGoalAcceptor:
+ title: Set Goal
+ desc: Enter the short key of a shape (Which you can generate here). The goal will count as completed once 1 item /s is delivered.
+
markerDemoLimit:
desc: You can only create two custom markers in the demo. Get the standalone for unlimited markers!
diff --git a/translations/base-he.yml b/translations/base-he.yaml
similarity index 97%
rename from translations/base-he.yml
rename to translations/base-he.yaml
index d0e80e99..40b458c7 100644
--- a/translations/base-he.yml
+++ b/translations/base-he.yaml
@@ -7,13 +7,13 @@ steamPage:
intro: >-
אתה אוהב משחקי אוטומציה? אתה במקום הנכון!
-
+
shapez.io הוא משחק שלווה שבו אתה בונה מפעל בשביל ליצור צורות גאומטריות אוטומטית. ככל שמתקדמים השלבים, הצורות נהיות יותר ויותר מסובכות, ואתה צריך להפתח על המפה האין סופית.
-
+
ואם זה לא היה מספיק, אתה צריך ליצור יותר ויותר צורות בשביל לספק את הדרישה - הדבר היחיד שיכול לעזור זה להגדיל את המפעל! בזמן שבהתחלה אתה רק צריך לערוך צורות, בהמשך אתה צריך לצבוע אותם בעזרת צבעים שאתה מערבב.
-
+
קניית המשחק בsteam תתן לך גישה למשחק המלא, אבל אתה יכול לשחק משחק דמו בhttps://shapez.io/ ולהחליט אחר כך.
-
+
what_others_say: What people say about shapez.io
nothernlion_comment: >-
@@ -85,7 +85,8 @@ mainMenu:
openSourceHint: המשחק הזה הוא עם קוד פתוח!
discordLink: שרת הדסקורד הרשמי
helpTranslate: תעזור לתרגם!
- madeBy: יוצר המשחק:
+ madeBy: >-
+ יוצר המשחק:
# This is shown when using firefox and other browsers which are not supported.
browserWarning: >-
@@ -1205,4 +1206,4 @@ tips:
- בשביל לנקות מסוע, חתוך את האיזור ואז תדביק באותו מקום.
- לחץ F4 בשביל להציג את הFPS ואת הTickRate.
- לחץ F4 פעמיים בשביל להציג את המשבצת שהעכבר והמצלמה בהם.
- - אתה יכול ללחוץ על צורה מוצמדת בצד שמאל בשביל לבטל את ההצמדה.
\ No newline at end of file
+ - אתה יכול ללחוץ על צורה מוצמדת בצד שמאל בשביל לבטל את ההצמדה.