Puzzle mode, part 2
@ -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");
|
||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
42
res/ui/languages/he.svg
Normal file
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<rect style="fill:#41479B;" width="512" height="512"/>
|
||||
<rect y="93.86" style="fill:#F5F5F5;" width="512" height="324.28"/>
|
||||
<path style="fill:#41479B;" d="M317.474,256l30.734-53.234h-61.469L256,149.523l-30.739,53.243h-61.469L194.526,256l-30.734,53.234
|
||||
h61.469L256,362.477l30.739-53.243h61.469L317.474,256z M318.054,220.176l-10.632,18.415l-10.632-18.415H318.054z M297.371,256
|
||||
l-20.683,35.824h-41.376L214.629,256l20.683-35.824h41.376L297.371,256z M256,184.344l10.636,18.422h-21.272L256,184.344z
|
||||
M193.946,220.176h21.264l-10.632,18.415L193.946,220.176z M193.946,291.824l10.632-18.415l10.632,18.415H193.946z M256,327.656
|
||||
l-10.636-18.422h21.272L256,327.656z M307.423,273.409l10.632,18.415h-21.264L307.423,273.409z"/>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 15 KiB |
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ingame_HUD_ModeMenuNext {
|
||||
position: absolute;
|
||||
@include S(top, 10px);
|
||||
@include S(top, 15px);
|
||||
@include S(right, 10px);
|
||||
|
||||
display: flex;
|
||||
|
@ -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 */
|
||||
|
26
src/css/ingame_hud/puzzle_editor_controls.scss
Normal file
@ -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;
|
||||
}
|
@ -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,
|
||||
|
@ -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}"] {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -123,4 +123,6 @@ function catchErrors(message, source, lineno, colno, error) {
|
||||
return true;
|
||||
}
|
||||
|
||||
window.onerror = catchErrors;
|
||||
if (!G_IS_DEV) {
|
||||
window.onerror = catchErrors;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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";
|
||||
|
@ -183,7 +183,7 @@ export class GameSystemManager {
|
||||
|
||||
add("goalAcceptor", GoalAcceptorSystem);
|
||||
|
||||
if (this.root.gameMode.hasZone()) {
|
||||
if (this.root.gameMode.getBuildableZones()) {
|
||||
add("zone", ZoneSystem);
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
21
src/js/game/hud/parts/puzzle_editor_controls.js
Normal file
@ -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 = `
|
||||
|
||||
<span>1. Build constant producers to generate resources.</span>
|
||||
<span>2. Build goal acceptors the capture shapes.</span>
|
||||
<span>3. Produce your desired shape(s) within the puzzle area and deliver it to the goal acceptors, which will capture it.</span>
|
||||
<span>4. Once you are done, press 'Playtest' to validate your puzzle.</span>
|
||||
`;
|
||||
|
||||
this.titleElement = makeDiv(parent, "ingame_HUD_PuzzleEditorTitle");
|
||||
this.titleElement.innerText = "Puzzle Editor";
|
||||
}
|
||||
|
||||
initialize() {}
|
||||
}
|
@ -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) ||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)"
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -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)"
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -184,4 +184,12 @@ export const LANGUAGES = {
|
||||
code: "uk",
|
||||
region: "",
|
||||
},
|
||||
|
||||
"he": {
|
||||
// hebrew
|
||||
name: "עברית",
|
||||
data: require("./built-temp/base-he.json"),
|
||||
code: "he",
|
||||
region: "",
|
||||
},
|
||||
};
|
||||
|
@ -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;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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() {
|
||||
|
@ -248,6 +248,10 @@ dialogs:
|
||||
Choose a pre-defined item:
|
||||
descShortKey: ... or enter the <strong>short key</strong> of a shape (Which you can generate <link>here</link>)
|
||||
|
||||
editGoalAcceptor:
|
||||
title: Set Goal
|
||||
desc: Enter the <strong>short key</strong> of a shape (Which you can generate <link>here</link>). 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!
|
||||
|
||||
|
@ -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: יוצר המשחק: <author-link>
|
||||
madeBy: >-
|
||||
יוצר המשחק: <author-link>
|
||||
|
||||
# This is shown when using firefox and other browsers which are not supported.
|
||||
browserWarning: >-
|
||||
@ -1205,4 +1206,4 @@ tips:
|
||||
- בשביל לנקות מסוע, חתוך את האיזור ואז תדביק באותו מקום.
|
||||
- לחץ F4 בשביל להציג את הFPS ואת הTickRate.
|
||||
- לחץ F4 פעמיים בשביל להציג את המשבצת שהעכבר והמצלמה בהם.
|
||||
- אתה יכול ללחוץ על צורה מוצמדת בצד שמאל בשביל לבטל את ההצמדה.
|
||||
- אתה יכול ללחוץ על צורה מוצמדת בצד שמאל בשביל לבטל את ההצמדה.
|