@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:a7931a4ba2104bbf7de3a1332617d5a056e34c55bab751821a168a83e0b91793
|
oid sha256:9d8a4254944d83882513a062e77406419d94c3058a7ad657a5a318d45cc5443f
|
||||||
size 683910
|
size 902131
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:037d27409bf78b828470e553ee0f29304eda24c46598151bb4b9c69c66a6c6c1
|
oid sha256:27c8d1eaa48beb7187e37244bd6ef7f43429be84ac88fffa96a4d72eb0e6565b
|
||||||
size 146363
|
size 158809
|
||||||
|
After Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 776 KiB After Width: | Height: | Size: 822 KiB |
Before Width: | Height: | Size: 166 KiB After Width: | Height: | Size: 169 KiB |
Before Width: | Height: | Size: 397 KiB After Width: | Height: | Size: 404 KiB |
Before Width: | Height: | Size: 780 KiB After Width: | Height: | Size: 788 KiB |
After Width: | Height: | Size: 9.3 KiB |
After Width: | Height: | Size: 8.5 KiB |
@ -0,0 +1,107 @@
|
|||||||
|
import { enumDirection, Vector } from "../../core/vector";
|
||||||
|
import { ItemAcceptorComponent, enumItemAcceptorItemFilter } from "../components/item_acceptor";
|
||||||
|
import { Entity } from "../entity";
|
||||||
|
import { MetaBuilding } from "../meta_building";
|
||||||
|
import { GameRoot } from "../root";
|
||||||
|
import { enumHubGoalRewards } from "../tutorial_goals";
|
||||||
|
import { EnergyGeneratorComponent } from "../components/energy_generator";
|
||||||
|
import { WiredPinsComponent, enumPinSlotType } from "../components/wired_pins";
|
||||||
|
|
||||||
|
export class MetaEnergyGenerator extends MetaBuilding {
|
||||||
|
constructor() {
|
||||||
|
super("energy_generator");
|
||||||
|
}
|
||||||
|
|
||||||
|
isRotateable(variant) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
getSilhouetteColor() {
|
||||||
|
return "#c425d7";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {GameRoot} root
|
||||||
|
* @param {string} variant
|
||||||
|
* @returns {Array<[string, string]>}
|
||||||
|
*/
|
||||||
|
getAdditionalStatistics(root, variant) {
|
||||||
|
// TODO
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
getDimensions(variant) {
|
||||||
|
return new Vector(2, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {GameRoot} root
|
||||||
|
*/
|
||||||
|
getIsUnlocked(root) {
|
||||||
|
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_cutter_and_trash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the entity at the given location
|
||||||
|
* @param {Entity} entity
|
||||||
|
*/
|
||||||
|
setupEntityComponents(entity) {
|
||||||
|
entity.addComponent(
|
||||||
|
new ItemAcceptorComponent({
|
||||||
|
slots: [
|
||||||
|
{
|
||||||
|
pos: new Vector(0, 0),
|
||||||
|
directions: [enumDirection.top],
|
||||||
|
filter: enumItemAcceptorItemFilter.shape,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
pos: new Vector(1, 0),
|
||||||
|
directions: [enumDirection.top],
|
||||||
|
filter: enumItemAcceptorItemFilter.shape,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pos: new Vector(0, 1),
|
||||||
|
directions: [enumDirection.bottom],
|
||||||
|
filter: enumItemAcceptorItemFilter.shape,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pos: new Vector(1, 1),
|
||||||
|
directions: [enumDirection.bottom],
|
||||||
|
filter: enumItemAcceptorItemFilter.shape,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
entity.addComponent(
|
||||||
|
new EnergyGeneratorComponent({
|
||||||
|
// Set by the energy generator system later
|
||||||
|
requiredKey: null,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
entity.addComponent(
|
||||||
|
new WiredPinsComponent({
|
||||||
|
slots: [
|
||||||
|
{
|
||||||
|
pos: new Vector(0, 0),
|
||||||
|
type: enumPinSlotType.energyEjector,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pos: new Vector(1, 0),
|
||||||
|
type: enumPinSlotType.energyEjector,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pos: new Vector(0, 1),
|
||||||
|
type: enumPinSlotType.energyEjector,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pos: new Vector(1, 1),
|
||||||
|
type: enumPinSlotType.energyEjector,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
import { types } from "../../savegame/serialization";
|
||||||
|
import { BaseItem } from "../base_item";
|
||||||
|
import { Component } from "../component";
|
||||||
|
import { ShapeItem } from "../items/shape_item";
|
||||||
|
|
||||||
|
const maxQueueSize = 10;
|
||||||
|
|
||||||
|
export class EnergyGeneratorComponent extends Component {
|
||||||
|
static getId() {
|
||||||
|
return "EnergyGenerator";
|
||||||
|
}
|
||||||
|
|
||||||
|
static getSchema() {
|
||||||
|
return {
|
||||||
|
requiredKey: types.string,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {object} param0
|
||||||
|
* @param {string} param0.requiredKey Which shape this generator needs, can be null if not computed yet
|
||||||
|
*/
|
||||||
|
constructor({ requiredKey }) {
|
||||||
|
super();
|
||||||
|
this.requiredKey = requiredKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores how many items are ready to be converted to energy
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
this.itemsInQueue = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {BaseItem} item
|
||||||
|
*/
|
||||||
|
tryTakeItem(item) {
|
||||||
|
if (!(item instanceof ShapeItem)) {
|
||||||
|
// Not a shape
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.definition.getHash() !== this.requiredKey) {
|
||||||
|
// Not our shape
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.itemsInQueue >= maxQueueSize) {
|
||||||
|
// Queue is full
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Take item and put it into the queue
|
||||||
|
++this.itemsInQueue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
import { Component } from "../component";
|
||||||
|
import { Vector } from "../../core/vector";
|
||||||
|
import { types } from "../../savegame/serialization";
|
||||||
|
|
||||||
|
/** @enum {string} */
|
||||||
|
export const enumPinSlotType = {
|
||||||
|
energyEjector: "energyEjector",
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @typedef {{
|
||||||
|
* pos: Vector,
|
||||||
|
* type: enumPinSlotType
|
||||||
|
* }} WirePinSlotDefinition */
|
||||||
|
|
||||||
|
/** @typedef {{
|
||||||
|
* pos: Vector,
|
||||||
|
* type: enumPinSlotType,
|
||||||
|
* value: number
|
||||||
|
* }} WirePinSlot */
|
||||||
|
|
||||||
|
export class WiredPinsComponent extends Component {
|
||||||
|
static getId() {
|
||||||
|
return "WiredPins";
|
||||||
|
}
|
||||||
|
|
||||||
|
static getSchema() {
|
||||||
|
return {
|
||||||
|
slots: types.array(
|
||||||
|
types.structured({
|
||||||
|
pos: types.vector,
|
||||||
|
type: types.enum(enumPinSlotType),
|
||||||
|
value: types.float,
|
||||||
|
})
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {object} param0
|
||||||
|
* @param {Array<WirePinSlotDefinition>} param0.slots
|
||||||
|
*/
|
||||||
|
constructor({ slots }) {
|
||||||
|
super();
|
||||||
|
this.setSlots(slots);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the slots of this building
|
||||||
|
* @param {Array<WirePinSlotDefinition>} slots
|
||||||
|
*/
|
||||||
|
setSlots(slots) {
|
||||||
|
/** @type {Array<WirePinSlot>} */
|
||||||
|
this.slots = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < slots.length; ++i) {
|
||||||
|
const slotData = slots[i];
|
||||||
|
this.slots.push({
|
||||||
|
pos: slotData.pos,
|
||||||
|
type: slotData.type,
|
||||||
|
value: 0.0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,172 @@
|
|||||||
|
import { gMetaBuildingRegistry } from "../../../core/global_registries";
|
||||||
|
import { Signal } from "../../../core/signal";
|
||||||
|
import { TrackedState } from "../../../core/tracked_state";
|
||||||
|
import { makeDiv } from "../../../core/utils";
|
||||||
|
import { KEYMAPPINGS } from "../../key_action_mapper";
|
||||||
|
import { MetaBuilding } from "../../meta_building";
|
||||||
|
import { BaseHUDPart } from "../base_hud_part";
|
||||||
|
import { GameRoot } from "../../root";
|
||||||
|
|
||||||
|
export class HUDBaseToolbar extends BaseHUDPart {
|
||||||
|
/**
|
||||||
|
* @param {GameRoot} root
|
||||||
|
* @param {Array<typeof MetaBuilding>} supportedBuildings
|
||||||
|
* @param {function} visibilityCondition
|
||||||
|
*/
|
||||||
|
constructor(root, supportedBuildings, visibilityCondition) {
|
||||||
|
super(root);
|
||||||
|
|
||||||
|
this.supportedBuildings = supportedBuildings;
|
||||||
|
this.visibilityCondition = visibilityCondition;
|
||||||
|
|
||||||
|
/** @type {Object.<string, {
|
||||||
|
* metaBuilding: MetaBuilding,
|
||||||
|
* unlocked: boolean,
|
||||||
|
* selected: boolean,
|
||||||
|
* element: HTMLElement,
|
||||||
|
* index: number
|
||||||
|
* }>} */
|
||||||
|
this.buildingHandles = {};
|
||||||
|
|
||||||
|
this.sigBuildingSelected = new Signal();
|
||||||
|
this.trackedIsVisisible = new TrackedState(this.onVisibilityChanged, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the visibility of the toolbar changed
|
||||||
|
* @param {boolean} visible
|
||||||
|
*/
|
||||||
|
onVisibilityChanged(visible) {
|
||||||
|
this.element.classList.toggle("visible", visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should create all require elements
|
||||||
|
* @param {HTMLElement} parent
|
||||||
|
*/
|
||||||
|
createElements(parent) {
|
||||||
|
this.element = makeDiv(parent, "ingame_HUD_buildings_toolbar", ["ingame_buildingsToolbar"], "");
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize() {
|
||||||
|
const actionMapper = this.root.keyMapper;
|
||||||
|
|
||||||
|
const items = makeDiv(this.element, null, ["buildings"]);
|
||||||
|
|
||||||
|
for (let i = 0; i < this.supportedBuildings.length; ++i) {
|
||||||
|
const metaBuilding = gMetaBuildingRegistry.findByClass(this.supportedBuildings[i]);
|
||||||
|
const binding = actionMapper.getBinding(KEYMAPPINGS.buildings[metaBuilding.getId()]);
|
||||||
|
|
||||||
|
const itemContainer = makeDiv(items, null, ["building"]);
|
||||||
|
itemContainer.setAttribute("data-icon", "building_icons/" + metaBuilding.getId() + ".png");
|
||||||
|
|
||||||
|
binding.add(() => this.selectBuildingForPlacement(metaBuilding));
|
||||||
|
|
||||||
|
this.trackClicks(itemContainer, () => this.selectBuildingForPlacement(metaBuilding), {
|
||||||
|
clickSound: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.buildingHandles[metaBuilding.id] = {
|
||||||
|
metaBuilding,
|
||||||
|
element: itemContainer,
|
||||||
|
unlocked: false,
|
||||||
|
selected: false,
|
||||||
|
index: i,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.root.hud.signals.selectedPlacementBuildingChanged.add(
|
||||||
|
this.onSelectedPlacementBuildingChanged,
|
||||||
|
this
|
||||||
|
);
|
||||||
|
|
||||||
|
this.lastSelectedIndex = 0;
|
||||||
|
actionMapper.getBinding(KEYMAPPINGS.placement.cycleBuildings).add(this.cycleBuildings, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the toolbar
|
||||||
|
*/
|
||||||
|
update() {
|
||||||
|
this.trackedIsVisisible.set(this.visibilityCondition());
|
||||||
|
|
||||||
|
if (!this.trackedIsVisisible.get()) {
|
||||||
|
// Currently not active
|
||||||
|
} else {
|
||||||
|
for (const buildingId in this.buildingHandles) {
|
||||||
|
const handle = this.buildingHandles[buildingId];
|
||||||
|
const newStatus = handle.metaBuilding.getIsUnlocked(this.root);
|
||||||
|
if (handle.unlocked !== newStatus) {
|
||||||
|
handle.unlocked = newStatus;
|
||||||
|
handle.element.classList.toggle("unlocked", newStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cycles through all buildings
|
||||||
|
*/
|
||||||
|
cycleBuildings() {
|
||||||
|
let newIndex = this.lastSelectedIndex;
|
||||||
|
for (let i = 0; i < this.supportedBuildings.length; ++i, ++newIndex) {
|
||||||
|
newIndex %= this.supportedBuildings.length;
|
||||||
|
const metaBuilding = gMetaBuildingRegistry.findByClass(this.supportedBuildings[newIndex]);
|
||||||
|
const handle = this.buildingHandles[metaBuilding.id];
|
||||||
|
if (!handle.selected && handle.unlocked) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const metaBuildingClass = this.supportedBuildings[newIndex];
|
||||||
|
const metaBuilding = gMetaBuildingRegistry.findByClass(metaBuildingClass);
|
||||||
|
this.selectBuildingForPlacement(metaBuilding);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the selected building got changed
|
||||||
|
* @param {MetaBuilding} metaBuilding
|
||||||
|
*/
|
||||||
|
onSelectedPlacementBuildingChanged(metaBuilding) {
|
||||||
|
for (const buildingId in this.buildingHandles) {
|
||||||
|
const handle = this.buildingHandles[buildingId];
|
||||||
|
const newStatus = handle.metaBuilding === metaBuilding;
|
||||||
|
if (handle.selected !== newStatus) {
|
||||||
|
handle.selected = newStatus;
|
||||||
|
handle.element.classList.toggle("selected", newStatus);
|
||||||
|
}
|
||||||
|
if (handle.selected) {
|
||||||
|
this.lastSelectedIndex = handle.index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.element.classList.toggle("buildingSelected", !!metaBuilding);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {MetaBuilding} metaBuilding
|
||||||
|
*/
|
||||||
|
selectBuildingForPlacement(metaBuilding) {
|
||||||
|
if (!this.visibilityCondition()) {
|
||||||
|
// Not active
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!metaBuilding.getIsUnlocked(this.root)) {
|
||||||
|
this.root.soundProxy.playUiError();
|
||||||
|
return STOP_PROPAGATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow clicking an item again to deselect it
|
||||||
|
for (const buildingId in this.buildingHandles) {
|
||||||
|
const handle = this.buildingHandles[buildingId];
|
||||||
|
if (handle.selected && handle.metaBuilding === metaBuilding) {
|
||||||
|
metaBuilding = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.root.soundProxy.playUiClick();
|
||||||
|
this.sigBuildingSelected.dispatch(metaBuilding);
|
||||||
|
this.onSelectedPlacementBuildingChanged(metaBuilding);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
import { makeOffscreenBuffer } from "../../../core/buffer_utils";
|
||||||
|
import { globalConfig } from "../../../core/config";
|
||||||
|
import { DrawParameters } from "../../../core/draw_parameters";
|
||||||
|
import { KEYMAPPINGS } from "../../key_action_mapper";
|
||||||
|
import { enumEditMode } from "../../root";
|
||||||
|
import { THEME } from "../../theme";
|
||||||
|
import { BaseHUDPart } from "../base_hud_part";
|
||||||
|
|
||||||
|
const wiresBackgroundDpi = 3;
|
||||||
|
|
||||||
|
export class HUDWiresOverlay extends BaseHUDPart {
|
||||||
|
createElements(parent) {}
|
||||||
|
|
||||||
|
initialize() {
|
||||||
|
// Probably not the best location, but the one which makes most sense
|
||||||
|
this.root.keyMapper.getBinding(KEYMAPPINGS.ingame.switchLayers).add(this.switchLayers, this);
|
||||||
|
|
||||||
|
this.generateTilePattern();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switches between layers
|
||||||
|
*/
|
||||||
|
switchLayers() {
|
||||||
|
if (this.root.editMode === enumEditMode.regular) {
|
||||||
|
this.root.editMode = enumEditMode.wires;
|
||||||
|
} else {
|
||||||
|
this.root.editMode = enumEditMode.regular;
|
||||||
|
}
|
||||||
|
this.root.signals.editModeChanged.dispatch(this.root.editMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the background pattern for the wires overlay
|
||||||
|
*/
|
||||||
|
generateTilePattern() {
|
||||||
|
const dims = globalConfig.tileSize * wiresBackgroundDpi;
|
||||||
|
const [canvas, context] = makeOffscreenBuffer(dims, dims, {
|
||||||
|
smooth: false,
|
||||||
|
reusable: false,
|
||||||
|
label: "wires-tile-pattern",
|
||||||
|
});
|
||||||
|
|
||||||
|
context.scale(wiresBackgroundDpi, wiresBackgroundDpi);
|
||||||
|
context.fillStyle = THEME.map.wires.overlay;
|
||||||
|
context.fillRect(0, 0, globalConfig.tileSize, globalConfig.tileSize);
|
||||||
|
|
||||||
|
const lineWidth = 1;
|
||||||
|
|
||||||
|
context.fillRect(0, 0, globalConfig.tileSize, lineWidth);
|
||||||
|
context.fillRect(0, lineWidth, lineWidth, globalConfig.tileSize);
|
||||||
|
|
||||||
|
this.tilePatternCanvas = canvas;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {DrawParameters} parameters
|
||||||
|
*/
|
||||||
|
draw(parameters) {
|
||||||
|
if (this.root.editMode !== enumEditMode.wires) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.cachedPatternBackground) {
|
||||||
|
this.cachedPatternBackground = parameters.context.createPattern(this.tilePatternCanvas, "repeat");
|
||||||
|
}
|
||||||
|
|
||||||
|
const bounds = parameters.visibleRect;
|
||||||
|
|
||||||
|
const scaleFactor = 1 / wiresBackgroundDpi;
|
||||||
|
|
||||||
|
parameters.context.scale(scaleFactor, scaleFactor);
|
||||||
|
parameters.context.fillStyle = this.cachedPatternBackground;
|
||||||
|
parameters.context.fillRect(
|
||||||
|
bounds.x / scaleFactor,
|
||||||
|
bounds.y / scaleFactor,
|
||||||
|
bounds.w / scaleFactor,
|
||||||
|
bounds.h / scaleFactor
|
||||||
|
);
|
||||||
|
parameters.context.scale(1 / scaleFactor, 1 / scaleFactor);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
import { DrawParameters } from "../../core/draw_parameters";
|
||||||
|
import { T } from "../../translations";
|
||||||
|
import { EnergyGeneratorComponent } from "../components/energy_generator";
|
||||||
|
import { Entity } from "../entity";
|
||||||
|
import { GameSystemWithFilter } from "../game_system_with_filter";
|
||||||
|
import { ShapeDefinition } from "../shape_definition";
|
||||||
|
|
||||||
|
export class EnergyGeneratorSystem extends GameSystemWithFilter {
|
||||||
|
constructor(root) {
|
||||||
|
super(root, [EnergyGeneratorComponent]);
|
||||||
|
}
|
||||||
|
|
||||||
|
draw(parameters) {
|
||||||
|
this.forEachMatchingEntityOnScreen(parameters, this.drawEntity.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns which shape is required for a given generator
|
||||||
|
* @param {Entity} entity
|
||||||
|
*/
|
||||||
|
getShapeRequiredForGenerator(entity) {
|
||||||
|
return "CuCuCuCu";
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
for (let i = 0; i < this.allEntities.length; ++i) {
|
||||||
|
const entity = this.allEntities[i];
|
||||||
|
const energyGenComp = entity.components.EnergyGenerator;
|
||||||
|
|
||||||
|
if (!energyGenComp.requiredKey) {
|
||||||
|
// Compute required key for this generator
|
||||||
|
energyGenComp.requiredKey = this.getShapeRequiredForGenerator(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {DrawParameters} parameters
|
||||||
|
* @param {Entity} entity
|
||||||
|
*/
|
||||||
|
drawEntity(parameters, entity) {
|
||||||
|
const context = parameters.context;
|
||||||
|
const staticComp = entity.components.StaticMapEntity;
|
||||||
|
|
||||||
|
if (!staticComp.shouldBeDrawn(parameters)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const energyGenComp = entity.components.EnergyGenerator;
|
||||||
|
if (!energyGenComp.requiredKey) {
|
||||||
|
// Not initialized yet
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pos = staticComp.getTileSpaceBounds().getCenter().toWorldSpace();
|
||||||
|
|
||||||
|
// TESTING
|
||||||
|
const definition = ShapeDefinition.fromShortKey(energyGenComp.requiredKey);
|
||||||
|
definition.draw(pos.x, pos.y, parameters, 30);
|
||||||
|
|
||||||
|
const energyGenerated = 5;
|
||||||
|
|
||||||
|
// deliver: Deliver
|
||||||
|
// toGenerateEnergy: For <x> energy
|
||||||
|
context.font = "bold 7px GameFont";
|
||||||
|
context.fillStyle = "#64666e";
|
||||||
|
context.textAlign = "left";
|
||||||
|
context.fillText(T.buildings.energy_generator.deliver.toUpperCase(), pos.x - 25, pos.y - 18);
|
||||||
|
|
||||||
|
context.fillText(
|
||||||
|
T.buildings.energy_generator.toGenerateEnergy.replace("<x>", "" + energyGenerated).toUpperCase(),
|
||||||
|
pos.x - 25,
|
||||||
|
pos.y + 28
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
import { GameSystemWithFilter } from "../game_system_with_filter";
|
||||||
|
import { WiredPinsComponent } from "../components/wired_pins";
|
||||||
|
import { DrawParameters } from "../../core/draw_parameters";
|
||||||
|
import { Entity } from "../entity";
|
||||||
|
import { THEME } from "../theme";
|
||||||
|
|
||||||
|
export class WiredPinsSystem extends GameSystemWithFilter {
|
||||||
|
constructor(root) {
|
||||||
|
super(root, [WiredPinsComponent]);
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
drawWiresLayer(parameters) {
|
||||||
|
this.forEachMatchingEntityOnScreen(parameters, this.drawEntityPins.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {DrawParameters} parameters
|
||||||
|
* @param {Entity} entity
|
||||||
|
*/
|
||||||
|
drawEntityPins(parameters, entity) {
|
||||||
|
const staticComp = entity.components.StaticMapEntity;
|
||||||
|
|
||||||
|
if (!staticComp.shouldBeDrawn(parameters)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pinsComp = entity.components.WiredPins;
|
||||||
|
|
||||||
|
const slots = pinsComp.slots;
|
||||||
|
|
||||||
|
for (let i = 0; i < slots.length; ++i) {
|
||||||
|
const slot = slots[i];
|
||||||
|
const tile = staticComp.localTileToWorld(slot.pos);
|
||||||
|
|
||||||
|
const worldPos = tile.toWorldSpaceCenterOfTile();
|
||||||
|
|
||||||
|
parameters.context.fillStyle = THEME.map.wires.pins[slot.type];
|
||||||
|
parameters.context.beginCircle(worldPos.x, worldPos.y, 5);
|
||||||
|
parameters.context.fill();
|
||||||
|
|
||||||
|
parameters.context.lineWidth = 2;
|
||||||
|
parameters.context.fillStyle = "rgba(0, 0, 0, 0.1)";
|
||||||
|
parameters.context.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|