1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2025-06-13 13:04:03 +00:00

Puzzle mode, part 2

This commit is contained in:
tobspr 2021-04-29 22:31:06 +02:00
parent 752503d892
commit 46e0c1494a
39 changed files with 332 additions and 178 deletions

View File

@ -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");

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

42
res/ui/languages/he.svg Normal file
View 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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -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;
}
}
}

View File

@ -1,6 +1,6 @@
#ingame_HUD_ModeMenuNext {
position: absolute;
@include S(top, 10px);
@include S(top, 15px);
@include S(right, 10px);
display: flex;

View File

@ -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 */

View 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;
}

View File

@ -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,

View File

@ -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}"] {

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -123,4 +123,6 @@ function catchErrors(message, source, lineno, colno, error) {
return true;
}
window.onerror = catchErrors;
if (!G_IS_DEV) {
window.onerror = catchErrors;
}

View File

@ -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);
}
/**

View File

@ -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;
}
}

View File

@ -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");
}
/**

View File

@ -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";

View File

@ -183,7 +183,7 @@ export class GameSystemManager {
add("goalAcceptor", GoalAcceptorSystem);
if (this.root.gameMode.hasZone()) {
if (this.root.gameMode.getBuildableZones()) {
add("zone", ZoneSystem);
}

View File

@ -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:

View File

@ -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,

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
}

View 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() {}
}

View File

@ -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) ||

View File

@ -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);
}

View File

@ -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;

View File

@ -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) {

View File

@ -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];
}
/**

View File

@ -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);

View File

@ -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;
}

View File

@ -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)"
}
},

View File

@ -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)"
}
},

View File

@ -184,4 +184,12 @@ export const LANGUAGES = {
code: "uk",
region: "",
},
"he": {
// hebrew
name: "עברית",
data: require("./built-temp/base-he.json"),
code: "he",
region: "",
},
};

View File

@ -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;
});
}
/**

View File

@ -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() {

View File

@ -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!

View File

@ -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 פעמיים בשביל להציג את המשבצת שהעכבר והמצלמה בהם.
- אתה יכול ללחוץ על צורה מוצמדת בצד שמאל בשביל לבטל את ההצמדה.
- אתה יכול ללחוץ על צורה מוצמדת בצד שמאל בשביל לבטל את ההצמדה.