mirror of
https://github.com/tobspr/shapez.io.git
synced 2025-06-13 13:04:03 +00:00
Add building, HUD exclusion, building exclusion, and refactor
- [WIP] Add ConstantProducer building that combines ConstantSignal and ItemProducer functionality. Currently using temp assets. - Add pre-placement check to the zone - Use Rectangles for zone and boundary - Simplify zone drawing - Account for exclusion in savegame data - [WIP] Add puzzle play and edit buttons in puzzle mode menu
This commit is contained in:
parent
47abc24436
commit
dae1ad3687
BIN
res/ui/building_icons/constant_producer.png
Normal file
BIN
res/ui/building_icons/constant_producer.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.9 KiB |
BIN
res/ui/building_tutorials/constant_producer.png
Normal file
BIN
res/ui/building_tutorials/constant_producer.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 271 KiB |
BIN
res_raw/sprites/blueprints/constant_producer.png
Normal file
BIN
res_raw/sprites/blueprints/constant_producer.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.4 KiB |
BIN
res_raw/sprites/buildings/constant_producer.png
Normal file
BIN
res_raw/sprites/buildings/constant_producer.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.7 KiB |
@ -1,6 +1,6 @@
|
|||||||
$buildings: belt, cutter, miner, mixer, painter, rotater, balancer, stacker, trash, underground_belt, wire,
|
$buildings: belt, cutter, miner, mixer, painter, rotater, balancer, stacker, trash, underground_belt, wire,
|
||||||
constant_signal, logic_gate, lever, filter, wire_tunnel, display, virtual_processor, reader, storage,
|
constant_signal, logic_gate, lever, filter, wire_tunnel, display, virtual_processor, reader, storage,
|
||||||
transistor, analyzer, comparator, item_producer;
|
transistor, analyzer, comparator, item_producer, constant_producer;
|
||||||
|
|
||||||
@each $building in $buildings {
|
@each $building in $buildings {
|
||||||
[data-icon="building_icons/#{$building}.png"] {
|
[data-icon="building_icons/#{$building}.png"] {
|
||||||
@ -13,7 +13,8 @@ $buildingsAndVariants: belt, balancer, underground_belt, underground_belt-tier2,
|
|||||||
cutter, cutter-quad, rotater, rotater-ccw, stacker, mixer, painter-double, painter-quad, trash, storage,
|
cutter, cutter-quad, rotater, rotater-ccw, stacker, mixer, painter-double, painter-quad, trash, storage,
|
||||||
reader, rotater-rotate180, display, constant_signal, wire, wire_tunnel, logic_gate-or, logic_gate-not,
|
reader, rotater-rotate180, display, constant_signal, wire, wire_tunnel, logic_gate-or, logic_gate-not,
|
||||||
logic_gate-xor, analyzer, virtual_processor-rotater, virtual_processor-unstacker, item_producer,
|
logic_gate-xor, analyzer, virtual_processor-rotater, virtual_processor-unstacker, item_producer,
|
||||||
virtual_processor-stacker, virtual_processor-painter, wire-second, painter, painter-mirrored, comparator;
|
constant_producer, virtual_processor-stacker, virtual_processor-painter, wire-second, painter,
|
||||||
|
painter-mirrored, comparator;
|
||||||
@each $building in $buildingsAndVariants {
|
@each $building in $buildingsAndVariants {
|
||||||
[data-icon="building_tutorials/#{$building}.png"] {
|
[data-icon="building_tutorials/#{$building}.png"] {
|
||||||
/* @load-async */
|
/* @load-async */
|
||||||
|
@ -242,6 +242,16 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modeButtons {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
@include S(grid-column-gap, 10px);
|
||||||
|
align-items: start;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
.browserWarning {
|
.browserWarning {
|
||||||
@include S(margin-bottom, 10px);
|
@include S(margin-bottom, 10px);
|
||||||
background-color: $colorRedBright;
|
background-color: $colorRedBright;
|
||||||
@ -285,6 +295,18 @@
|
|||||||
@include S(margin-left, 15px);
|
@include S(margin-left, 15px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.playModeButton {
|
||||||
|
@include IncreasedClickArea(0px);
|
||||||
|
@include S(margin-top, 15px);
|
||||||
|
@include S(margin-left, 15px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.editModeButton {
|
||||||
|
@include IncreasedClickArea(0px);
|
||||||
|
@include S(margin-top, 15px);
|
||||||
|
@include S(margin-left, 15px);
|
||||||
|
}
|
||||||
|
|
||||||
.savegames {
|
.savegames {
|
||||||
@include S(max-height, 105px);
|
@include S(max-height, 105px);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
@ -452,7 +474,7 @@
|
|||||||
.buttons {
|
.buttons {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
grid-column-gap: 10px;
|
@include S(grid-column-gap, 10px);
|
||||||
align-items: start;
|
align-items: start;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
35
src/js/game/buildings/constant_producer.js
Normal file
35
src/js/game/buildings/constant_producer.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/* typehints:start */
|
||||||
|
import { Entity } from "../entity";
|
||||||
|
/* typehints:end */
|
||||||
|
|
||||||
|
import { enumDirection, Vector } from "../../core/vector";
|
||||||
|
import { ItemEjectorComponent } from "../components/item_ejector";
|
||||||
|
import { enumItemProducerType, ItemProducerComponent } from "../components/item_producer";
|
||||||
|
import { MetaBuilding } from "../meta_building";
|
||||||
|
|
||||||
|
export class MetaConstantProducerBuilding extends MetaBuilding {
|
||||||
|
constructor() {
|
||||||
|
super("constant_producer");
|
||||||
|
}
|
||||||
|
|
||||||
|
getSilhouetteColor() {
|
||||||
|
return "#bfd630";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the entity at the given location
|
||||||
|
* @param {Entity} entity
|
||||||
|
*/
|
||||||
|
setupEntityComponents(entity) {
|
||||||
|
entity.addComponent(
|
||||||
|
new ItemEjectorComponent({
|
||||||
|
slots: [{ pos: new Vector(0, 0), direction: enumDirection.top }],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
entity.addComponent(
|
||||||
|
new ItemProducerComponent({
|
||||||
|
type: enumItemProducerType.wireless,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -39,6 +39,6 @@ export class MetaItemProducerBuilding extends MetaBuilding {
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
entity.addComponent(new ItemProducerComponent());
|
entity.addComponent(new ItemProducerComponent({}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -711,7 +711,6 @@ export class Camera extends BasicSerializableObject {
|
|||||||
|
|
||||||
this.didMoveSinceTouchStart = this.didMoveSinceTouchStart || delta.length() > 0;
|
this.didMoveSinceTouchStart = this.didMoveSinceTouchStart || delta.length() > 0;
|
||||||
this.center = this.center.add(delta);
|
this.center = this.center.add(delta);
|
||||||
this.clampPosition(this.center);
|
|
||||||
|
|
||||||
this.touchPostMoveVelocity = this.touchPostMoveVelocity
|
this.touchPostMoveVelocity = this.touchPostMoveVelocity
|
||||||
.multiplyScalar(velocitySmoothing)
|
.multiplyScalar(velocitySmoothing)
|
||||||
@ -763,16 +762,15 @@ export class Camera extends BasicSerializableObject {
|
|||||||
* Clamps x, y position within set boundaries
|
* Clamps x, y position within set boundaries
|
||||||
* @param {Vector} vector
|
* @param {Vector} vector
|
||||||
*/
|
*/
|
||||||
clampPosition(vector) {
|
clampToBounds(vector) {
|
||||||
if (!this.root.gameMode.hasBoundaries()) {
|
if (!this.root.gameMode.hasBounds()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const width = this.root.gameMode.getBoundaryWidth();
|
const bounds = this.root.gameMode.getBounds().allScaled(globalConfig.tileSize);
|
||||||
const height = this.root.gameMode.getBoundaryHeight();
|
|
||||||
|
|
||||||
vector.x = clamp(vector.x, -width, width);
|
vector.x = clamp(vector.x, bounds.x, bounds.x + bounds.w);
|
||||||
vector.y = clamp(vector.y, -height, height);
|
vector.y = clamp(vector.y, bounds.y, bounds.y + bounds.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -878,6 +876,7 @@ export class Camera extends BasicSerializableObject {
|
|||||||
// Panning
|
// Panning
|
||||||
this.currentPan = mixVector(this.currentPan, this.desiredPan, 0.06);
|
this.currentPan = mixVector(this.currentPan, this.desiredPan, 0.06);
|
||||||
this.center = this.center.add(this.currentPan.multiplyScalar((0.5 * dt) / this.zoomLevel));
|
this.center = this.center.add(this.currentPan.multiplyScalar((0.5 * dt) / this.zoomLevel));
|
||||||
|
this.clampToBounds(this.center);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -943,7 +942,7 @@ export class Camera extends BasicSerializableObject {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
this.clampPosition(this.center);
|
this.clampToBounds(this.center);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1029,6 +1028,8 @@ export class Camera extends BasicSerializableObject {
|
|||||||
|
|
||||||
this.center.x += moveAmount * forceX * movementSpeed;
|
this.center.x += moveAmount * forceX * movementSpeed;
|
||||||
this.center.y += moveAmount * forceY * movementSpeed;
|
this.center.y += moveAmount * forceY * movementSpeed;
|
||||||
|
|
||||||
|
this.clampToBounds(this.center);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,22 @@
|
|||||||
import { Component } from "../component";
|
import { Component } from "../component";
|
||||||
|
|
||||||
|
/** @enum {string} */
|
||||||
|
export const enumItemProducerType = {
|
||||||
|
wired: "wired",
|
||||||
|
wireless: "wireless",
|
||||||
|
};
|
||||||
|
|
||||||
export class ItemProducerComponent extends Component {
|
export class ItemProducerComponent extends Component {
|
||||||
static getId() {
|
static getId() {
|
||||||
return "ItemProducer";
|
return "ItemProducer";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {object} options
|
||||||
|
* @prop {type=} options.type
|
||||||
|
*/
|
||||||
|
constructor({ type = enumItemProducerType.wired }) {
|
||||||
|
super();
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/* typehints:start */
|
/* typehints:start */
|
||||||
import { GameRoot } from "./root";
|
import { GameRoot } from "./root";
|
||||||
|
import { Rectangle } from "../core/rectangle";
|
||||||
/* typehints:end */
|
/* typehints:end */
|
||||||
|
|
||||||
import { gGameModeRegistry } from "../core/global_registries";
|
import { gGameModeRegistry } from "../core/global_registries";
|
||||||
@ -44,6 +45,8 @@ export class GameMode extends BasicSerializableObject {
|
|||||||
constructor(root) {
|
constructor(root) {
|
||||||
super();
|
super();
|
||||||
this.root = root;
|
this.root = root;
|
||||||
|
this.hudParts = {};
|
||||||
|
this.buildings = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {object} */
|
/** @returns {object} */
|
||||||
@ -71,12 +74,12 @@ export class GameMode extends BasicSerializableObject {
|
|||||||
return this.constructor.getType();
|
return this.constructor.getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
setBuildings(buildings) {
|
||||||
* @param {string} name - Class name of HUD Part
|
Object.assign(this.buildings, buildings);
|
||||||
* @returns {boolean}
|
}
|
||||||
*/
|
|
||||||
isHudPartHidden(name) {
|
setHudParts(parts) {
|
||||||
return false;
|
Object.assign(this.hudParts, parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,7 +87,15 @@ export class GameMode extends BasicSerializableObject {
|
|||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
isHudPartExcluded(name) {
|
isHudPartExcluded(name) {
|
||||||
return false;
|
return this.hudParts[name] === false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} name - Class name of building
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
isBuildingExcluded(name) {
|
||||||
|
return this.buildings[name] === false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {boolean} */
|
/** @returns {boolean} */
|
||||||
@ -92,11 +103,6 @@ export class GameMode extends BasicSerializableObject {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {boolean} */
|
|
||||||
hasHints() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @returns {boolean} */
|
/** @returns {boolean} */
|
||||||
hasHub() {
|
hasHub() {
|
||||||
return true;
|
return true;
|
||||||
@ -108,7 +114,7 @@ export class GameMode extends BasicSerializableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {boolean} */
|
/** @returns {boolean} */
|
||||||
hasBoundaries() {
|
hasBounds() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,29 +128,24 @@ export class GameMode extends BasicSerializableObject {
|
|||||||
return 3.5;
|
return 3.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {object} */
|
/** @returns {Object<string, Array>} */
|
||||||
getUpgrades() {
|
getUpgrades() {
|
||||||
return {};
|
return {
|
||||||
|
belt: [],
|
||||||
|
miner: [],
|
||||||
|
processors: [],
|
||||||
|
painting: [],
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {number} */
|
/** @returns {?Rectangle} */
|
||||||
getZoneWidth() {
|
getZone() {
|
||||||
return 0;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {number} */
|
/** @returns {?Rectangle} */
|
||||||
getZoneHeight() {
|
getBounds() {
|
||||||
return 0;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
/** @returns {number} */
|
|
||||||
getBoundaryWidth() {
|
|
||||||
return Infinity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @returns {number} */
|
|
||||||
getBoundaryHeight() {
|
|
||||||
return Infinity;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {array} */
|
/** @returns {array} */
|
||||||
|
@ -6,7 +6,6 @@ import { createLogger } from "../core/logging";
|
|||||||
import { BeltSystem } from "./systems/belt";
|
import { BeltSystem } from "./systems/belt";
|
||||||
import { ItemEjectorSystem } from "./systems/item_ejector";
|
import { ItemEjectorSystem } from "./systems/item_ejector";
|
||||||
import { MapResourcesSystem } from "./systems/map_resources";
|
import { MapResourcesSystem } from "./systems/map_resources";
|
||||||
import { MapZoneSystem } from "./systems/map_zone";
|
|
||||||
import { MinerSystem } from "./systems/miner";
|
import { MinerSystem } from "./systems/miner";
|
||||||
import { ItemProcessorSystem } from "./systems/item_processor";
|
import { ItemProcessorSystem } from "./systems/item_processor";
|
||||||
import { UndergroundBeltSystem } from "./systems/underground_belt";
|
import { UndergroundBeltSystem } from "./systems/underground_belt";
|
||||||
@ -25,6 +24,7 @@ import { ItemProcessorOverlaysSystem } from "./systems/item_processor_overlays";
|
|||||||
import { BeltReaderSystem } from "./systems/belt_reader";
|
import { BeltReaderSystem } from "./systems/belt_reader";
|
||||||
import { FilterSystem } from "./systems/filter";
|
import { FilterSystem } from "./systems/filter";
|
||||||
import { ItemProducerSystem } from "./systems/item_producer";
|
import { ItemProducerSystem } from "./systems/item_producer";
|
||||||
|
import { ZoneSystem } from "./systems/zone";
|
||||||
|
|
||||||
const logger = createLogger("game_system_manager");
|
const logger = createLogger("game_system_manager");
|
||||||
|
|
||||||
@ -47,9 +47,6 @@ export class GameSystemManager {
|
|||||||
/** @type {MapResourcesSystem} */
|
/** @type {MapResourcesSystem} */
|
||||||
mapResources: null,
|
mapResources: null,
|
||||||
|
|
||||||
/** @type {MapZoneSystem} */
|
|
||||||
mapZone: null,
|
|
||||||
|
|
||||||
/** @type {MinerSystem} */
|
/** @type {MinerSystem} */
|
||||||
miner: null,
|
miner: null,
|
||||||
|
|
||||||
@ -104,6 +101,9 @@ export class GameSystemManager {
|
|||||||
/** @type {ItemProducerSystem} */
|
/** @type {ItemProducerSystem} */
|
||||||
itemProducer: null,
|
itemProducer: null,
|
||||||
|
|
||||||
|
/** @type {ZoneSystem} */
|
||||||
|
zone: null,
|
||||||
|
|
||||||
/* typehints:end */
|
/* typehints:end */
|
||||||
};
|
};
|
||||||
this.systemUpdateOrder = [];
|
this.systemUpdateOrder = [];
|
||||||
@ -142,9 +142,9 @@ export class GameSystemManager {
|
|||||||
|
|
||||||
add("itemEjector", ItemEjectorSystem);
|
add("itemEjector", ItemEjectorSystem);
|
||||||
|
|
||||||
|
if (this.root.gameMode.hasResources()) {
|
||||||
add("mapResources", MapResourcesSystem);
|
add("mapResources", MapResourcesSystem);
|
||||||
|
}
|
||||||
add("mapZone", MapZoneSystem);
|
|
||||||
|
|
||||||
add("hub", HubSystem);
|
add("hub", HubSystem);
|
||||||
|
|
||||||
@ -171,6 +171,10 @@ export class GameSystemManager {
|
|||||||
|
|
||||||
add("itemProcessorOverlays", ItemProcessorOverlaysSystem);
|
add("itemProcessorOverlays", ItemProcessorOverlaysSystem);
|
||||||
|
|
||||||
|
if (this.root.gameMode.hasZone()) {
|
||||||
|
add("zone", ZoneSystem);
|
||||||
|
}
|
||||||
|
|
||||||
logger.log("📦 There are", this.systemUpdateOrder.length, "game systems");
|
logger.log("📦 There are", this.systemUpdateOrder.length, "game systems");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,10 +129,15 @@ export class GameHUD {
|
|||||||
this.parts.changesDebugger = new HUDChangesDebugger(this.root);
|
this.parts.changesDebugger = new HUDChangesDebugger(this.root);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.root.gameMode.hasHints() && this.root.app.settings.getAllSettings().offerHints) {
|
if (this.root.app.settings.getAllSettings().offerHints) {
|
||||||
|
if (!this.root.gameMode.isHudPartExcluded(HUDPartTutorialHints.name)) {
|
||||||
this.parts.tutorialHints = new HUDPartTutorialHints(this.root);
|
this.parts.tutorialHints = new HUDPartTutorialHints(this.root);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.root.gameMode.isHudPartExcluded(HUDInteractiveTutorial.name)) {
|
||||||
this.parts.interactiveTutorial = new HUDInteractiveTutorial(this.root);
|
this.parts.interactiveTutorial = new HUDInteractiveTutorial(this.root);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this.root.app.settings.getAllSettings().vignette) {
|
if (this.root.app.settings.getAllSettings().vignette) {
|
||||||
this.parts.vignetteOverlay = new HUDVignetteOverlay(this.root);
|
this.parts.vignetteOverlay = new HUDVignetteOverlay(this.root);
|
||||||
@ -177,7 +182,7 @@ export class GameHUD {
|
|||||||
for (let key in parts) {
|
for (let key in parts) {
|
||||||
const Part = parts[key];
|
const Part = parts[key];
|
||||||
|
|
||||||
if (!Part || this.root.gameMode.isHudPartExcluded(Part)) {
|
if (!Part || this.root.gameMode.isHudPartExcluded(Part.name)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,8 +23,8 @@ export class HUDBaseToolbar extends BaseHUDPart {
|
|||||||
) {
|
) {
|
||||||
super(root);
|
super(root);
|
||||||
|
|
||||||
this.primaryBuildings = primaryBuildings;
|
this.primaryBuildings = this.filterBuildings(primaryBuildings);
|
||||||
this.secondaryBuildings = secondaryBuildings;
|
this.secondaryBuildings = this.filterBuildings(secondaryBuildings);
|
||||||
this.visibilityCondition = visibilityCondition;
|
this.visibilityCondition = visibilityCondition;
|
||||||
this.htmlElementId = htmlElementId;
|
this.htmlElementId = htmlElementId;
|
||||||
this.layer = layer;
|
this.layer = layer;
|
||||||
@ -47,6 +47,24 @@ export class HUDBaseToolbar extends BaseHUDPart {
|
|||||||
this.element = makeDiv(parent, this.htmlElementId, ["ingame_buildingsToolbar"], "");
|
this.element = makeDiv(parent, this.htmlElementId, ["ingame_buildingsToolbar"], "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array<typeof MetaBuilding>} buildings
|
||||||
|
* @returns {Array<typeof MetaBuilding>}
|
||||||
|
*/
|
||||||
|
filterBuildings(buildings) {
|
||||||
|
const filtered = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < buildings.length; i++) {
|
||||||
|
if (this.root.gameMode.isBuildingExcluded(buildings[i].name)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
filtered.push(buildings[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all buildings
|
* Returns all buildings
|
||||||
* @returns {Array<typeof MetaBuilding>}
|
* @returns {Array<typeof MetaBuilding>}
|
||||||
|
@ -15,12 +15,13 @@ import { MetaUndergroundBeltBuilding } from "../../buildings/underground_belt";
|
|||||||
import { HUDBaseToolbar } from "./base_toolbar";
|
import { HUDBaseToolbar } from "./base_toolbar";
|
||||||
import { MetaStorageBuilding } from "../../buildings/storage";
|
import { MetaStorageBuilding } from "../../buildings/storage";
|
||||||
import { MetaItemProducerBuilding } from "../../buildings/item_producer";
|
import { MetaItemProducerBuilding } from "../../buildings/item_producer";
|
||||||
import { queryParamOptions } from "../../../core/query_parameters";
|
import { MetaConstantProducerBuilding } from "../../buildings/constant_producer";
|
||||||
|
|
||||||
export class HUDBuildingsToolbar extends HUDBaseToolbar {
|
export class HUDBuildingsToolbar extends HUDBaseToolbar {
|
||||||
constructor(root) {
|
constructor(root) {
|
||||||
super(root, {
|
super(root, {
|
||||||
primaryBuildings: [
|
primaryBuildings: [
|
||||||
|
MetaConstantProducerBuilding,
|
||||||
MetaBeltBuilding,
|
MetaBeltBuilding,
|
||||||
MetaBalancerBuilding,
|
MetaBalancerBuilding,
|
||||||
MetaUndergroundBeltBuilding,
|
MetaUndergroundBeltBuilding,
|
||||||
@ -31,7 +32,7 @@ export class HUDBuildingsToolbar extends HUDBaseToolbar {
|
|||||||
MetaMixerBuilding,
|
MetaMixerBuilding,
|
||||||
MetaPainterBuilding,
|
MetaPainterBuilding,
|
||||||
MetaTrashBuilding,
|
MetaTrashBuilding,
|
||||||
...(queryParamOptions.sandboxMode || G_IS_DEV ? [MetaItemProducerBuilding] : []),
|
MetaItemProducerBuilding,
|
||||||
],
|
],
|
||||||
secondaryBuildings: [
|
secondaryBuildings: [
|
||||||
MetaStorageBuilding,
|
MetaStorageBuilding,
|
||||||
|
@ -153,10 +153,6 @@ export class HUDPinnedShapes extends BaseHUDPart {
|
|||||||
* Rerenders the whole component
|
* Rerenders the whole component
|
||||||
*/
|
*/
|
||||||
rerenderFull() {
|
rerenderFull() {
|
||||||
if (this.root.gameMode.isHudPartHidden(this.constructor.name)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentGoal = this.root.hubGoals.currentGoal;
|
const currentGoal = this.root.hubGoals.currentGoal;
|
||||||
const currentKey = currentGoal.definition.getHash();
|
const currentKey = currentGoal.definition.getHash();
|
||||||
|
|
||||||
|
@ -102,14 +102,12 @@ export class HUDWaypoints extends BaseHUDPart {
|
|||||||
|
|
||||||
/** @type {Array<Waypoint>} */
|
/** @type {Array<Waypoint>} */
|
||||||
this.waypoints = [];
|
this.waypoints = [];
|
||||||
if (this.root.gameMode.hasHub()) {
|
|
||||||
this.waypoints.push({
|
this.waypoints.push({
|
||||||
label: null,
|
label: null,
|
||||||
center: { x: 0, y: 0 },
|
center: { x: 0, y: 0 },
|
||||||
zoomLevel: 3,
|
zoomLevel: 3,
|
||||||
layer: gMetaBuildingRegistry.findByClass(MetaHubBuilding).getLayer(),
|
layer: gMetaBuildingRegistry.findByClass(MetaHubBuilding).getLayer(),
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
// Create a buffer we can use to measure text
|
// Create a buffer we can use to measure text
|
||||||
this.dummyBuffer = makeOffscreenBuffer(1, 1, {
|
this.dummyBuffer = makeOffscreenBuffer(1, 1, {
|
||||||
|
@ -49,6 +49,9 @@ export const KEYMAPPINGS = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
buildings: {
|
buildings: {
|
||||||
|
// Puzzle
|
||||||
|
constant_producer: { keyCode: 192 }, // "`"
|
||||||
|
|
||||||
// Primary Toolbar
|
// Primary Toolbar
|
||||||
belt: { keyCode: key("1") },
|
belt: { keyCode: key("1") },
|
||||||
balancer: { keyCode: key("2") },
|
balancer: { keyCode: key("2") },
|
||||||
@ -262,6 +265,8 @@ export function getStringForKeyCode(code) {
|
|||||||
return ".";
|
return ".";
|
||||||
case 191:
|
case 191:
|
||||||
return "/";
|
return "/";
|
||||||
|
case 192:
|
||||||
|
return "`";
|
||||||
case 219:
|
case 219:
|
||||||
return "[";
|
return "[";
|
||||||
case 220:
|
case 220:
|
||||||
|
@ -42,7 +42,7 @@ export class MapChunkView extends MapChunk {
|
|||||||
drawBackgroundLayer(parameters) {
|
drawBackgroundLayer(parameters) {
|
||||||
const systems = this.root.systemMgr.systems;
|
const systems = this.root.systemMgr.systems;
|
||||||
if (this.root.gameMode.hasZone()) {
|
if (this.root.gameMode.hasZone()) {
|
||||||
systems.mapZone.drawChunk(parameters, this);
|
systems.zone.drawChunk(parameters, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.root.gameMode.hasResources()) {
|
if (this.root.gameMode.hasResources()) {
|
||||||
|
@ -5,6 +5,7 @@ import { MetaAnalyzerBuilding } from "./buildings/analyzer";
|
|||||||
import { enumBalancerVariants, MetaBalancerBuilding } from "./buildings/balancer";
|
import { enumBalancerVariants, MetaBalancerBuilding } from "./buildings/balancer";
|
||||||
import { MetaBeltBuilding } from "./buildings/belt";
|
import { MetaBeltBuilding } from "./buildings/belt";
|
||||||
import { MetaComparatorBuilding } from "./buildings/comparator";
|
import { MetaComparatorBuilding } from "./buildings/comparator";
|
||||||
|
import { MetaConstantProducerBuilding } from "./buildings/constant_producer";
|
||||||
import { MetaConstantSignalBuilding } from "./buildings/constant_signal";
|
import { MetaConstantSignalBuilding } from "./buildings/constant_signal";
|
||||||
import { enumCutterVariants, MetaCutterBuilding } from "./buildings/cutter";
|
import { enumCutterVariants, MetaCutterBuilding } from "./buildings/cutter";
|
||||||
import { MetaDisplayBuilding } from "./buildings/display";
|
import { MetaDisplayBuilding } from "./buildings/display";
|
||||||
@ -59,6 +60,7 @@ export function initMetaBuildingRegistry() {
|
|||||||
gMetaBuildingRegistry.register(MetaAnalyzerBuilding);
|
gMetaBuildingRegistry.register(MetaAnalyzerBuilding);
|
||||||
gMetaBuildingRegistry.register(MetaComparatorBuilding);
|
gMetaBuildingRegistry.register(MetaComparatorBuilding);
|
||||||
gMetaBuildingRegistry.register(MetaItemProducerBuilding);
|
gMetaBuildingRegistry.register(MetaItemProducerBuilding);
|
||||||
|
gMetaBuildingRegistry.register(MetaConstantProducerBuilding);
|
||||||
|
|
||||||
// Belt
|
// Belt
|
||||||
registerBuildingVariant(1, MetaBeltBuilding, defaultBuildingVariant, 0);
|
registerBuildingVariant(1, MetaBeltBuilding, defaultBuildingVariant, 0);
|
||||||
@ -165,6 +167,9 @@ export function initMetaBuildingRegistry() {
|
|||||||
// Item producer
|
// Item producer
|
||||||
registerBuildingVariant(61, MetaItemProducerBuilding);
|
registerBuildingVariant(61, MetaItemProducerBuilding);
|
||||||
|
|
||||||
|
// Constant producer
|
||||||
|
registerBuildingVariant(62, MetaConstantProducerBuilding);
|
||||||
|
|
||||||
// Propagate instances
|
// Propagate instances
|
||||||
for (const key in gBuildingVariants) {
|
for (const key in gBuildingVariants) {
|
||||||
gBuildingVariants[key].metaInstance = gMetaBuildingRegistry.findByClass(
|
gBuildingVariants[key].metaInstance = gMetaBuildingRegistry.findByClass(
|
||||||
|
@ -2,19 +2,22 @@
|
|||||||
import { GameRoot } from "../root";
|
import { GameRoot } from "../root";
|
||||||
/* typehints:end */
|
/* typehints:end */
|
||||||
|
|
||||||
import { globalConfig } from "../../core/config";
|
import { Rectangle } from "../../core/rectangle";
|
||||||
import { types } from "../../savegame/serialization";
|
import { types } from "../../savegame/serialization";
|
||||||
import { HUDPinnedShapes } from "../hud/parts/pinned_shapes";
|
|
||||||
import { enumGameModeTypes, GameMode } from "../game_mode";
|
import { enumGameModeTypes, GameMode } from "../game_mode";
|
||||||
|
import { HUDInteractiveTutorial } from "../hud/parts/interactive_tutorial";
|
||||||
|
import { HUDPinnedShapes } from "../hud/parts/pinned_shapes";
|
||||||
|
import { HUDPartTutorialHints } from "../hud/parts/tutorial_hints";
|
||||||
|
import { HUDWaypoints } from "../hud/parts/waypoints";
|
||||||
|
|
||||||
export class PuzzleGameMode extends GameMode {
|
export class PuzzleGameMode extends GameMode {
|
||||||
static getType() {
|
static getType() {
|
||||||
return enumGameModeTypes.puzzle;
|
return enumGameModeTypes.puzzle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @returns {object} */
|
||||||
static getSchema() {
|
static getSchema() {
|
||||||
return {
|
return {
|
||||||
hiddenHudParts: types.keyValueMap(types.bool),
|
|
||||||
zoneHeight: types.uint,
|
zoneHeight: types.uint,
|
||||||
zoneWidth: types.uint,
|
zoneWidth: types.uint,
|
||||||
};
|
};
|
||||||
@ -23,18 +26,24 @@ export class PuzzleGameMode extends GameMode {
|
|||||||
/** @param {GameRoot} root */
|
/** @param {GameRoot} root */
|
||||||
constructor(root) {
|
constructor(root) {
|
||||||
super(root);
|
super(root);
|
||||||
}
|
|
||||||
|
|
||||||
initialize() {
|
|
||||||
const data = this.getSaveData();
|
const data = this.getSaveData();
|
||||||
|
|
||||||
this.type = this.getType();
|
this.setHudParts({
|
||||||
this.hiddenHudParts = data.hiddenHudParts || this.getDefaultHiddenHudParts();
|
[HUDInteractiveTutorial.name]: false,
|
||||||
// this.excludedHudParts = data.hiddenHudParts || this.getDefaultHiddenHudParts();
|
[HUDPartTutorialHints.name]: false,
|
||||||
this.zoneHeight = data.zoneHeight || 3 * globalConfig.tileSize;
|
[HUDPinnedShapes.name]: false,
|
||||||
this.zoneWidth = data.zoneWidth || 4 * globalConfig.tileSize;
|
[HUDWaypoints.name]: false,
|
||||||
this.boundaryHeight = this.zoneHeight * 2;
|
});
|
||||||
this.boundaryWidth = this.zoneWidth * 2;
|
|
||||||
|
this.setDimensions(data.zoneWidth, data.zoneHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
getSaveData() {
|
||||||
@ -47,24 +56,52 @@ export class PuzzleGameMode extends GameMode {
|
|||||||
return save.gameMode.data;
|
return save.gameMode.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
getDefaultHiddenHudParts() {
|
createCenteredRectangle(width, height) {
|
||||||
return {
|
return new Rectangle(-Math.ceil(width / 2), -Math.ceil(height / 2), width, height);
|
||||||
[HUDPinnedShapes.name]: true,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isHudPartHidden(name) {
|
getBounds() {
|
||||||
return this.hiddenHudParts[name];
|
if (this.bounds) {
|
||||||
|
return this.bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.bounds = this.createCenteredRectangle(this.boundsWidth, this.boundsHeight);
|
||||||
|
|
||||||
|
return this.bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
hasZone() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
hasHints() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
hasHub() {
|
hasHub() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -73,27 +110,11 @@ export class PuzzleGameMode extends GameMode {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
hasBoundaries() {
|
hasBounds() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
getMinimumZoom() {
|
getMinimumZoom() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
getBoundaryWidth() {
|
|
||||||
return this.boundaryWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
getBoundaryHeight() {
|
|
||||||
return this.boundaryHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
getZoneWidth() {
|
|
||||||
return this.zoneWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
getZoneHeight() {
|
|
||||||
return this.zoneHeight;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,9 @@
|
|||||||
import { GameRoot } from "../root";
|
import { GameRoot } from "../root";
|
||||||
/* typehints:end */
|
/* typehints:end */
|
||||||
|
|
||||||
import { PuzzleGameMode } from "./puzzle";
|
import { MetaConstantProducerBuilding } from "../buildings/constant_producer";
|
||||||
import { enumGameModeIds } from "../game_mode";
|
import { enumGameModeIds } from "../game_mode";
|
||||||
|
import { PuzzleGameMode } from "./puzzle";
|
||||||
|
|
||||||
export class PuzzleEditGameMode extends PuzzleGameMode {
|
export class PuzzleEditGameMode extends PuzzleGameMode {
|
||||||
static getId() {
|
static getId() {
|
||||||
@ -13,5 +14,9 @@ export class PuzzleEditGameMode extends PuzzleGameMode {
|
|||||||
/** @param {GameRoot} root */
|
/** @param {GameRoot} root */
|
||||||
constructor(root) {
|
constructor(root) {
|
||||||
super(root);
|
super(root);
|
||||||
|
|
||||||
|
this.setBuildings({
|
||||||
|
[MetaConstantProducerBuilding.name]: true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,5 @@ export class PuzzlePlayGameMode extends PuzzleGameMode {
|
|||||||
/** @param {GameRoot} root */
|
/** @param {GameRoot} root */
|
||||||
constructor(root) {
|
constructor(root) {
|
||||||
super(root);
|
super(root);
|
||||||
this.initialize();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,13 @@
|
|||||||
import { GameRoot } from "../root";
|
import { GameRoot } from "../root";
|
||||||
/* typehints:end */
|
/* typehints:end */
|
||||||
|
|
||||||
|
import { queryParamOptions } from "../../core/query_parameters";
|
||||||
import { findNiceIntegerValue } from "../../core/utils";
|
import { findNiceIntegerValue } from "../../core/utils";
|
||||||
|
import { MetaConstantProducerBuilding } from "../buildings/constant_producer";
|
||||||
|
import { MetaItemProducerBuilding } from "../buildings/item_producer";
|
||||||
import { enumGameModeIds, enumGameModeTypes, GameMode } from "../game_mode";
|
import { enumGameModeIds, enumGameModeTypes, GameMode } from "../game_mode";
|
||||||
import { ShapeDefinition } from "../shape_definition";
|
import { ShapeDefinition } from "../shape_definition";
|
||||||
import { enumHubGoalRewards } from "../tutorial_goals";
|
import { enumHubGoalRewards } from "../tutorial_goals";
|
||||||
import { types } from "../../savegame/serialization";
|
|
||||||
|
|
||||||
/** @typedef {{
|
/** @typedef {{
|
||||||
* shape: string,
|
* shape: string,
|
||||||
@ -489,6 +491,11 @@ export class RegularGameMode extends GameMode {
|
|||||||
/** @param {GameRoot} root */
|
/** @param {GameRoot} root */
|
||||||
constructor(root) {
|
constructor(root) {
|
||||||
super(root);
|
super(root);
|
||||||
|
|
||||||
|
this.setBuildings({
|
||||||
|
[MetaConstantProducerBuilding.name]: false,
|
||||||
|
[MetaItemProducerBuilding.name]: queryParamOptions.sandboxMode || G_IS_DEV,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
import { ItemProducerComponent } from "../components/item_producer";
|
/* typehints:start */
|
||||||
|
import { GameRoot } from "../root";
|
||||||
|
/* typehints:end */
|
||||||
|
|
||||||
|
import { enumItemProducerType, ItemProducerComponent } from "../components/item_producer";
|
||||||
import { GameSystemWithFilter } from "../game_system_with_filter";
|
import { GameSystemWithFilter } from "../game_system_with_filter";
|
||||||
|
|
||||||
export class ItemProducerSystem extends GameSystemWithFilter {
|
export class ItemProducerSystem extends GameSystemWithFilter {
|
||||||
|
/** @param {GameRoot} root */
|
||||||
constructor(root) {
|
constructor(root) {
|
||||||
super(root, [ItemProducerComponent]);
|
super(root, [ItemProducerComponent]);
|
||||||
}
|
}
|
||||||
@ -9,6 +14,8 @@ export class ItemProducerSystem extends GameSystemWithFilter {
|
|||||||
update() {
|
update() {
|
||||||
for (let i = 0; i < this.allEntities.length; ++i) {
|
for (let i = 0; i < this.allEntities.length; ++i) {
|
||||||
const entity = this.allEntities[i];
|
const entity = this.allEntities[i];
|
||||||
|
|
||||||
|
if (entity.components.ItemProducer.type === enumItemProducerType.wired) {
|
||||||
const pinsComp = entity.components.WiredPins;
|
const pinsComp = entity.components.WiredPins;
|
||||||
const pin = pinsComp.slots[0];
|
const pin = pinsComp.slots[0];
|
||||||
const network = pin.linkedNetwork;
|
const network = pin.linkedNetwork;
|
||||||
@ -19,6 +26,9 @@ export class ItemProducerSystem extends GameSystemWithFilter {
|
|||||||
|
|
||||||
const ejectorComp = entity.components.ItemEjector;
|
const ejectorComp = entity.components.ItemEjector;
|
||||||
ejectorComp.tryEject(0, network.currentValue);
|
ejectorComp.tryEject(0, network.currentValue);
|
||||||
|
} else {
|
||||||
|
// TODO: entity w/ wireless item producer (e.g. ConstantProducer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
/* typehints:start */
|
|
||||||
import { DrawParameters } from "../../core/draw_parameters";
|
|
||||||
import { MapChunkView } from "../map_chunk_view";
|
|
||||||
/* typehints:end */
|
|
||||||
|
|
||||||
import { globalConfig } from "../../core/config";
|
|
||||||
import { drawSpriteClipped } from "../../core/draw_utils";
|
|
||||||
import { GameSystem } from "../game_system";
|
|
||||||
import { THEME } from "../theme";
|
|
||||||
|
|
||||||
export class MapZoneSystem extends GameSystem {
|
|
||||||
/**
|
|
||||||
* Draws the map resources
|
|
||||||
* @param {DrawParameters} parameters
|
|
||||||
* @param {MapChunkView} chunk
|
|
||||||
*/
|
|
||||||
drawChunk(parameters, chunk) {
|
|
||||||
const width = this.root.gameMode.getZoneWidth();
|
|
||||||
const height = this.root.gameMode.getZoneHeight();
|
|
||||||
|
|
||||||
const zoneChunkBackground = this.root.buffers.getForKey({
|
|
||||||
key: "mapzonebg",
|
|
||||||
subKey: chunk.renderKey,
|
|
||||||
w: width,
|
|
||||||
h: height,
|
|
||||||
dpi: 1,
|
|
||||||
redrawMethod: this.generateChunkBackground.bind(this, chunk),
|
|
||||||
});
|
|
||||||
|
|
||||||
parameters.context.imageSmoothingEnabled = false;
|
|
||||||
drawSpriteClipped({
|
|
||||||
parameters,
|
|
||||||
sprite: zoneChunkBackground,
|
|
||||||
x: -width,
|
|
||||||
y: -height,
|
|
||||||
w: this.root.gameMode.getBoundaryWidth(),
|
|
||||||
h: this.root.gameMode.getBoundaryHeight(),
|
|
||||||
originalW: width,
|
|
||||||
originalH: height,
|
|
||||||
});
|
|
||||||
parameters.context.imageSmoothingEnabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {MapChunkView} chunk
|
|
||||||
* @param {HTMLCanvasElement} canvas
|
|
||||||
* @param {CanvasRenderingContext2D} context
|
|
||||||
* @param {number} w
|
|
||||||
* @param {number} h
|
|
||||||
* @param {number} dpi
|
|
||||||
*/
|
|
||||||
generateChunkBackground(chunk, canvas, context, w, h, dpi) {
|
|
||||||
context.clearRect(0, 0, w, h);
|
|
||||||
|
|
||||||
context.fillStyle = THEME.map.zone.background;
|
|
||||||
context.strokeStyle = THEME.map.zone.border;
|
|
||||||
context.fillRect(0, 0, w, h);
|
|
||||||
context.strokeRect(0, 0, w, h);
|
|
||||||
}
|
|
||||||
}
|
|
53
src/js/game/systems/zone.js
Normal file
53
src/js/game/systems/zone.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/* typehints:start */
|
||||||
|
import { DrawParameters } from "../../core/draw_parameters";
|
||||||
|
import { MapChunkView } from "../map_chunk_view";
|
||||||
|
import { GameRoot } from "../root";
|
||||||
|
/* typehints:end */
|
||||||
|
|
||||||
|
import { globalConfig } from "../../core/config";
|
||||||
|
import { STOP_PROPAGATION } from "../../core/signal";
|
||||||
|
import { GameSystem } from "../game_system";
|
||||||
|
import { THEME } from "../theme";
|
||||||
|
|
||||||
|
export class ZoneSystem extends GameSystem {
|
||||||
|
/** @param {GameRoot} root */
|
||||||
|
constructor(root) {
|
||||||
|
super(root);
|
||||||
|
|
||||||
|
this.root.signals.prePlacementCheck.add(this.prePlacementCheck, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
prePlacementCheck(entity, tile = null) {
|
||||||
|
const staticComp = entity.components.StaticMapEntity;
|
||||||
|
|
||||||
|
if (!staticComp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const zone = this.root.gameMode.getZone().expandedInAllDirections(-1);
|
||||||
|
const transformed = staticComp.getTileSpaceBounds();
|
||||||
|
|
||||||
|
if (zone.containsRect(transformed)) {
|
||||||
|
return STOP_PROPAGATION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the zone
|
||||||
|
* @param {DrawParameters} parameters
|
||||||
|
* @param {MapChunkView} chunk
|
||||||
|
*/
|
||||||
|
drawChunk(parameters, chunk) {
|
||||||
|
const zone = this.root.gameMode.getZone().allScaled(globalConfig.tileSize);
|
||||||
|
|
||||||
|
parameters.context.globalAlpha = 0.1;
|
||||||
|
parameters.context.fillStyle = THEME.map.zone.background;
|
||||||
|
parameters.context.fillRect(zone.x, zone.y, zone.w, zone.h);
|
||||||
|
|
||||||
|
parameters.context.globalAlpha = 0.9;
|
||||||
|
parameters.context.strokeStyle = THEME.map.zone.border;
|
||||||
|
parameters.context.strokeRect(zone.x, zone.y, zone.w, zone.h);
|
||||||
|
|
||||||
|
parameters.context.globalAlpha = 1;
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,8 @@ import { ExplainedResult } from "../core/explained_result";
|
|||||||
import { createLogger } from "../core/logging";
|
import { createLogger } from "../core/logging";
|
||||||
import { gComponentRegistry } from "../core/global_registries";
|
import { gComponentRegistry } from "../core/global_registries";
|
||||||
import { SerializerInternal } from "./serializer_internal";
|
import { SerializerInternal } from "./serializer_internal";
|
||||||
|
import { HUDPinnedShapes } from "../game/hud/parts/pinned_shapes";
|
||||||
|
import { HUDWaypoints } from "../game/hud/parts/waypoints";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import("../game/component").Component} Component
|
* @typedef {import("../game/component").Component} Component
|
||||||
@ -36,10 +38,14 @@ export class SavegameSerializer {
|
|||||||
gameMode: root.gameMode.serialize(),
|
gameMode: root.gameMode.serialize(),
|
||||||
entityMgr: root.entityMgr.serialize(),
|
entityMgr: root.entityMgr.serialize(),
|
||||||
hubGoals: root.hubGoals.serialize(),
|
hubGoals: root.hubGoals.serialize(),
|
||||||
pinnedShapes: root.hud.parts.pinnedShapes.serialize(),
|
|
||||||
waypoints: root.hud.parts.waypoints.serialize(),
|
|
||||||
entities: this.internal.serializeEntityArray(root.entityMgr.entities),
|
entities: this.internal.serializeEntityArray(root.entityMgr.entities),
|
||||||
beltPaths: root.systemMgr.systems.belt.serializePaths(),
|
beltPaths: root.systemMgr.systems.belt.serializePaths(),
|
||||||
|
pinnedShapes: root.gameMode.isHudPartExcluded(HUDPinnedShapes.name)
|
||||||
|
? null
|
||||||
|
: root.hud.parts.pinnedShapes.serialize(),
|
||||||
|
waypoints: root.gameMode.isHudPartExcluded(HUDWaypoints.name)
|
||||||
|
? null
|
||||||
|
: root.hud.parts.waypoints.serialize(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (G_IS_DEV) {
|
if (G_IS_DEV) {
|
||||||
@ -133,11 +139,17 @@ export class SavegameSerializer {
|
|||||||
errorReason = errorReason || root.map.deserialize(savegame.map);
|
errorReason = errorReason || root.map.deserialize(savegame.map);
|
||||||
errorReason = errorReason || root.gameMode.deserialize(savegame.gameMode);
|
errorReason = errorReason || root.gameMode.deserialize(savegame.gameMode);
|
||||||
errorReason = errorReason || root.hubGoals.deserialize(savegame.hubGoals, root);
|
errorReason = errorReason || root.hubGoals.deserialize(savegame.hubGoals, root);
|
||||||
errorReason = errorReason || root.hud.parts.pinnedShapes.deserialize(savegame.pinnedShapes);
|
|
||||||
errorReason = errorReason || root.hud.parts.waypoints.deserialize(savegame.waypoints);
|
|
||||||
errorReason = errorReason || this.internal.deserializeEntityArray(root, savegame.entities);
|
errorReason = errorReason || this.internal.deserializeEntityArray(root, savegame.entities);
|
||||||
errorReason = errorReason || root.systemMgr.systems.belt.deserializePaths(savegame.beltPaths);
|
errorReason = errorReason || root.systemMgr.systems.belt.deserializePaths(savegame.beltPaths);
|
||||||
|
|
||||||
|
if (!root.gameMode.isHudPartExcluded(HUDPinnedShapes.name)) {
|
||||||
|
errorReason = errorReason || root.hud.parts.pinnedShapes.deserialize(savegame.pinnedShapes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!root.gameMode.isHudPartExcluded(HUDWaypoints.name)) {
|
||||||
|
errorReason = errorReason || root.hud.parts.waypoints.deserialize(savegame.waypoints);
|
||||||
|
}
|
||||||
|
|
||||||
// Check for errors
|
// Check for errors
|
||||||
if (errorReason) {
|
if (errorReason) {
|
||||||
return ExplainedResult.bad(errorReason);
|
return ExplainedResult.bad(errorReason);
|
||||||
|
@ -333,10 +333,13 @@ export class MainMenuState extends GameState {
|
|||||||
const buttonContainer = this.htmlElement.querySelector(".mainContainer .buttons");
|
const buttonContainer = this.htmlElement.querySelector(".mainContainer .buttons");
|
||||||
removeAllChildren(buttonContainer);
|
removeAllChildren(buttonContainer);
|
||||||
|
|
||||||
const playButtonElement = makeButtonElement(["playButton", "styledButton"], T.mainMenu.play);
|
const playButtonElement = makeButtonElement(["playModeButton", "styledButton"], T.puzzleMenu.play);
|
||||||
|
const editButtonElement = makeButtonElement(["editModeButton", "styledButton"], T.puzzleMenu.edit);
|
||||||
|
|
||||||
buttonContainer.appendChild(playButtonElement);
|
buttonContainer.appendChild(playButtonElement);
|
||||||
this.trackClicks(playButtonElement, this.onPuzzlePlayButtonClicked);
|
this.trackClicks(playButtonElement, this.onPuzzlePlayButtonClicked);
|
||||||
|
buttonContainer.appendChild(editButtonElement);
|
||||||
|
this.trackClicks(editButtonElement, this.onPuzzleEditButtonClicked);
|
||||||
|
|
||||||
const bottomButtonContainer = this.htmlElement.querySelector(".bottomContainer .buttons");
|
const bottomButtonContainer = this.htmlElement.querySelector(".bottomContainer .buttons");
|
||||||
removeAllChildren(bottomButtonContainer);
|
removeAllChildren(bottomButtonContainer);
|
||||||
@ -356,6 +359,15 @@ export class MainMenuState extends GameState {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onPuzzleEditButtonClicked() {
|
||||||
|
const savegame = this.app.savegameMgr.createNewSavegame();
|
||||||
|
|
||||||
|
this.moveToState("InGameState", {
|
||||||
|
gameModeId: enumGameModeIds.puzzleEdit,
|
||||||
|
savegame,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
onPuzzleModeButtonClicked() {
|
onPuzzleModeButtonClicked() {
|
||||||
this.renderPuzzleModeMenu();
|
this.renderPuzzleModeMenu();
|
||||||
}
|
}
|
||||||
|
@ -119,6 +119,10 @@ mainMenu:
|
|||||||
puzzleMode: Puzzle Mode
|
puzzleMode: Puzzle Mode
|
||||||
back: Back
|
back: Back
|
||||||
|
|
||||||
|
puzzleMenu:
|
||||||
|
play: Play
|
||||||
|
edit: Edit
|
||||||
|
|
||||||
dialogs:
|
dialogs:
|
||||||
buttons:
|
buttons:
|
||||||
ok: OK
|
ok: OK
|
||||||
@ -703,6 +707,11 @@ buildings:
|
|||||||
name: Item Producer
|
name: Item Producer
|
||||||
description: Available in sandbox mode only, outputs the given signal from the wires layer on the regular layer.
|
description: Available in sandbox mode only, outputs the given signal from the wires layer on the regular layer.
|
||||||
|
|
||||||
|
constant_producer:
|
||||||
|
default:
|
||||||
|
name: &constant_producer Constant Producer
|
||||||
|
description: Outputs a shape, color or boolean (1 or 0) as specified.
|
||||||
|
|
||||||
storyRewards:
|
storyRewards:
|
||||||
# Those are the rewards gained from completing the store
|
# Those are the rewards gained from completing the store
|
||||||
reward_cutter_and_trash:
|
reward_cutter_and_trash:
|
||||||
@ -1130,6 +1139,7 @@ keybindings:
|
|||||||
analyzer: *analyzer
|
analyzer: *analyzer
|
||||||
comparator: *comparator
|
comparator: *comparator
|
||||||
item_producer: Item Producer (Sandbox)
|
item_producer: Item Producer (Sandbox)
|
||||||
|
constant_producer: *constant_producer
|
||||||
# ---
|
# ---
|
||||||
|
|
||||||
pipette: Pipette
|
pipette: Pipette
|
||||||
|
Loading…
Reference in New Issue
Block a user