From 569921b51a0d52efef703242066a6b3cbf4ddd50 Mon Sep 17 00:00:00 2001 From: tobspr Date: Fri, 30 Apr 2021 17:36:23 +0200 Subject: [PATCH] Puzzle mode, part 4 --- src/js/game/buildings/goal_acceptor.js | 1 + src/js/game/hud/parts/mode_puzzle_review.js | 10 +++++ src/js/game/systems/zone.js | 15 ++++++- src/js/savegame/puzzle_serializer.js | 45 ++++++++++++++++++++- translations/base-en.yaml | 3 ++ 5 files changed, 71 insertions(+), 3 deletions(-) diff --git a/src/js/game/buildings/goal_acceptor.js b/src/js/game/buildings/goal_acceptor.js index 7e89f74a..2f9df765 100644 --- a/src/js/game/buildings/goal_acceptor.js +++ b/src/js/game/buildings/goal_acceptor.js @@ -30,6 +30,7 @@ export class MetaGoalAcceptorBuilding extends MetaBuilding { { pos: new Vector(0, 0), directions: [enumDirection.bottom], + filter: "shape", }, ], }) diff --git a/src/js/game/hud/parts/mode_puzzle_review.js b/src/js/game/hud/parts/mode_puzzle_review.js index 293ed74b..cb2989cb 100644 --- a/src/js/game/hud/parts/mode_puzzle_review.js +++ b/src/js/game/hud/parts/mode_puzzle_review.js @@ -2,11 +2,13 @@ import { globalConfig, THIRDPARTY_URLS } from "../../../core/config"; import { createLogger } from "../../../core/logging"; import { DialogWithForm } from "../../../core/modal_dialog_elements"; import { FormElementInput, FormElementItemChooser } from "../../../core/modal_dialog_forms"; +import { STOP_PROPAGATION } from "../../../core/signal"; import { fillInLinkIntoTranslation, makeDiv } from "../../../core/utils"; import { PuzzleSerializer } from "../../../savegame/puzzle_serializer"; import { T } from "../../../translations"; import { ConstantSignalComponent } from "../../components/constant_signal"; import { GoalAcceptorComponent } from "../../components/goal_acceptor"; +import { StaticMapEntityComponent } from "../../components/static_map_entity"; import { ShapeItem } from "../../items/shape_item"; import { ShapeDefinition } from "../../shape_definition"; import { BaseHUDPart } from "../base_hud_part"; @@ -163,5 +165,13 @@ export class HUDPuzzleReview extends BaseHUDPart { return T.puzzleMenu.validation.goalAcceptorRateNotMet; } } + + // Check if all buildings are within the area + const entities = this.root.entityMgr.getAllWithComponent(StaticMapEntityComponent); + for (const entity of entities) { + if (this.root.systemMgr.systems.zone.prePlacementCheck(entity) === STOP_PROPAGATION) { + return T.puzzleMenu.validation.buildingOutOfBounds; + } + } } } diff --git a/src/js/game/systems/zone.js b/src/js/game/systems/zone.js index 7e977438..2dc36849 100644 --- a/src/js/game/systems/zone.js +++ b/src/js/game/systems/zone.js @@ -8,6 +8,8 @@ import { globalConfig } from "../../core/config"; import { STOP_PROPAGATION } from "../../core/signal"; import { GameSystem } from "../game_system"; import { THEME } from "../theme"; +import { Entity } from "../entity"; +import { Vector } from "../../core/vector"; export class ZoneSystem extends GameSystem { /** @param {GameRoot} root */ @@ -21,6 +23,12 @@ export class ZoneSystem extends GameSystem { }); } + /** + * + * @param {Entity} entity + * @param {Vector | undefined} tile + * @returns + */ prePlacementCheck(entity, tile = null) { const staticComp = entity.components.StaticMapEntity; @@ -36,10 +44,15 @@ export class ZoneSystem extends GameSystem { } const transformed = staticComp.getTileSpaceBounds(); + if (tile) { + transformed.x += tile.x; + transformed.y += tile.y; + } let withinAnyZone = false; for (const zone of zones) { - if (zone.expandedInAllDirections(-1).containsRect(transformed)) { + const intersection = zone.getIntersection(transformed); + if (intersection && intersection.w * intersection.h === transformed.w * transformed.h) { withinAnyZone = true; } } diff --git a/src/js/savegame/puzzle_serializer.js b/src/js/savegame/puzzle_serializer.js index 94d9cbc3..f75226b3 100644 --- a/src/js/savegame/puzzle_serializer.js +++ b/src/js/savegame/puzzle_serializer.js @@ -1,3 +1,6 @@ +import { enumConstantSignalType } from "../game/components/constant_signal"; +import { StaticMapEntityComponent } from "../game/components/static_map_entity"; +import { ShapeItem } from "../game/items/shape_item"; import { GameRoot } from "../game/root"; export class PuzzleSerializer { @@ -10,9 +13,47 @@ export class PuzzleSerializer { generateDumpFromGameRoot(root, sanityChecks = true) { console.log("serializing", root); + let buildings = []; + + for (const entity of root.entityMgr.getAllWithComponent(StaticMapEntityComponent)) { + const staticComp = entity.components.StaticMapEntity; + const signalComp = entity.components.ConstantSignal; + + if (signalComp) { + assert(signalComp.type === enumConstantSignalType.wireless, "not a wireless signal"); + assert(signalComp.signal.getItemType() === "shape", "not a shape signal"); + buildings.push({ + type: "emitter", + item: /** @type {ShapeItem} */ (signalComp.signal).definition.getHash(), + pos: { + x: staticComp.origin.x, + y: staticComp.origin.y, + r: staticComp.rotation, + }, + }); + continue; + } + + const goalComp = entity.components.GoalAcceptor; + if (goalComp) { + assert(goalComp.item, "goals is missing item"); + assert(goalComp.item.getItemType() === "shape", "goal is not an item"); + buildings.push({ + type: "goal", + item: /** @type {ShapeItem} */ (goalComp.item).definition.getHash(), + pos: { + x: staticComp.origin.x, + y: staticComp.origin.y, + r: staticComp.rotation, + }, + }); + continue; + } + } + return { - type: "puzzle", - contents: "foo", + buildings, + bounds: root.gameMode.getBuildableZones()[0], }; } } diff --git a/translations/base-en.yaml b/translations/base-en.yaml index 31000014..f889cd8d 100644 --- a/translations/base-en.yaml +++ b/translations/base-en.yaml @@ -142,6 +142,9 @@ puzzleMenu: One or more Goal Acceptors have not yet assigned an item. Deliver a shape to them to set a goal. goalAcceptorRateNotMet: >- One or more Goal Acceptors are not getting enough items. Make sure that the indicators are green for all acceptors. + buildingOutOfBounds: >- + One ore more buildings are outside of the buildable area. Either increase the area or remove them. + dialogs: buttons: ok: OK