2020-06-26 15:02:52 +00:00
|
|
|
import { DrawParameters } from "../core/draw_parameters";
|
|
|
|
import { Loader } from "../core/loader";
|
|
|
|
import { createLogger } from "../core/logging";
|
|
|
|
import { Vector } from "../core/vector";
|
|
|
|
import { Entity } from "./entity";
|
2020-06-28 17:34:10 +00:00
|
|
|
import { GameRoot, enumLayer } from "./root";
|
2020-06-26 15:02:52 +00:00
|
|
|
import { findNiceIntegerValue } from "../core/utils";
|
|
|
|
import { blueprintShape } from "./upgrades";
|
|
|
|
import { globalConfig } from "../core/config";
|
2020-05-27 12:30:59 +00:00
|
|
|
|
|
|
|
const logger = createLogger("blueprint");
|
|
|
|
|
|
|
|
export class Blueprint {
|
|
|
|
/**
|
|
|
|
* @param {Array<Entity>} entities
|
|
|
|
*/
|
|
|
|
constructor(entities) {
|
|
|
|
this.entities = entities;
|
|
|
|
}
|
|
|
|
|
2020-06-28 17:34:10 +00:00
|
|
|
/**
|
|
|
|
* Returns the layer of this blueprint
|
|
|
|
* @returns {enumLayer}
|
|
|
|
*/
|
|
|
|
get layer() {
|
|
|
|
if (this.entities.length === 0) {
|
|
|
|
return enumLayer.regular;
|
|
|
|
}
|
|
|
|
return this.entities[0].layer;
|
|
|
|
}
|
|
|
|
|
2020-05-27 12:30:59 +00:00
|
|
|
/**
|
2020-05-27 13:03:36 +00:00
|
|
|
* Creates a new blueprint from the given entity uids
|
2020-05-27 12:30:59 +00:00
|
|
|
* @param {GameRoot} root
|
|
|
|
* @param {Array<number>} uids
|
|
|
|
*/
|
|
|
|
static fromUids(root, uids) {
|
|
|
|
const newEntities = [];
|
|
|
|
|
|
|
|
let averagePosition = new Vector();
|
|
|
|
|
|
|
|
// First, create a copy
|
|
|
|
for (let i = 0; i < uids.length; ++i) {
|
|
|
|
const entity = root.entityMgr.findByUid(uids[i]);
|
|
|
|
assert(entity, "Entity for blueprint not found:" + uids[i]);
|
|
|
|
|
|
|
|
const clone = entity.duplicateWithoutContents();
|
|
|
|
newEntities.push(clone);
|
|
|
|
|
|
|
|
const pos = entity.components.StaticMapEntity.getTileSpaceBounds().getCenter();
|
|
|
|
averagePosition.addInplace(pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
averagePosition.divideScalarInplace(uids.length);
|
2020-07-05 14:56:01 +00:00
|
|
|
const blueprintOrigin = averagePosition.subScalars(0.5, 0.5).floor();
|
|
|
|
|
2020-05-27 12:30:59 +00:00
|
|
|
for (let i = 0; i < uids.length; ++i) {
|
|
|
|
newEntities[i].components.StaticMapEntity.origin.subInplace(blueprintOrigin);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now, make sure the origin is 0,0
|
|
|
|
return new Blueprint(newEntities);
|
|
|
|
}
|
|
|
|
|
2020-05-28 16:07:57 +00:00
|
|
|
/**
|
|
|
|
* Returns the cost of this blueprint in shapes
|
|
|
|
*/
|
|
|
|
getCost() {
|
2020-05-30 15:50:29 +00:00
|
|
|
if (G_IS_DEV && globalConfig.debug.blueprintsNoCost) {
|
|
|
|
return 0;
|
|
|
|
}
|
2020-06-27 08:51:52 +00:00
|
|
|
return findNiceIntegerValue(4 * Math.pow(this.entities.length, 1.1));
|
2020-05-28 16:07:57 +00:00
|
|
|
}
|
|
|
|
|
2020-05-27 12:30:59 +00:00
|
|
|
/**
|
2020-05-27 13:03:36 +00:00
|
|
|
* Draws the blueprint at the given origin
|
2020-05-27 12:30:59 +00:00
|
|
|
* @param {DrawParameters} parameters
|
|
|
|
*/
|
|
|
|
draw(parameters, tile) {
|
|
|
|
parameters.context.globalAlpha = 0.8;
|
|
|
|
for (let i = 0; i < this.entities.length; ++i) {
|
|
|
|
const entity = this.entities[i];
|
|
|
|
const staticComp = entity.components.StaticMapEntity;
|
|
|
|
const newPos = staticComp.origin.add(tile);
|
|
|
|
|
|
|
|
const rect = staticComp.getTileSpaceBounds();
|
|
|
|
rect.moveBy(tile.x, tile.y);
|
|
|
|
|
2020-07-05 15:56:54 +00:00
|
|
|
if (!parameters.root.logic.checkCanPlaceEntity(entity, tile)) {
|
2020-05-27 12:30:59 +00:00
|
|
|
parameters.context.globalAlpha = 0.3;
|
|
|
|
} else {
|
|
|
|
parameters.context.globalAlpha = 1;
|
|
|
|
}
|
|
|
|
|
2020-08-10 20:13:26 +00:00
|
|
|
staticComp.drawSpriteOnFullEntityBounds(parameters, staticComp.getBlueprintSprite(), 0, newPos);
|
2020-05-27 12:30:59 +00:00
|
|
|
}
|
|
|
|
parameters.context.globalAlpha = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-05-27 13:03:36 +00:00
|
|
|
* Rotates the blueprint clockwise
|
|
|
|
*/
|
|
|
|
rotateCw() {
|
|
|
|
for (let i = 0; i < this.entities.length; ++i) {
|
|
|
|
const entity = this.entities[i];
|
|
|
|
const staticComp = entity.components.StaticMapEntity;
|
|
|
|
|
|
|
|
staticComp.rotation = (staticComp.rotation + 90) % 360;
|
|
|
|
staticComp.originalRotation = (staticComp.originalRotation + 90) % 360;
|
|
|
|
staticComp.origin = staticComp.origin.rotateFastMultipleOf90(90);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Rotates the blueprint counter clock wise
|
|
|
|
*/
|
|
|
|
rotateCcw() {
|
|
|
|
// Well ...
|
|
|
|
for (let i = 0; i < 3; ++i) {
|
|
|
|
this.rotateCw();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if the blueprint can be placed at the given tile
|
2020-05-27 12:30:59 +00:00
|
|
|
* @param {GameRoot} root
|
|
|
|
* @param {Vector} tile
|
|
|
|
*/
|
|
|
|
canPlace(root, tile) {
|
|
|
|
let anyPlaceable = false;
|
|
|
|
|
|
|
|
for (let i = 0; i < this.entities.length; ++i) {
|
|
|
|
const entity = this.entities[i];
|
2020-07-05 15:56:54 +00:00
|
|
|
if (root.logic.checkCanPlaceEntity(entity, tile)) {
|
2020-05-27 12:30:59 +00:00
|
|
|
anyPlaceable = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return anyPlaceable;
|
|
|
|
}
|
|
|
|
|
2020-05-28 16:07:57 +00:00
|
|
|
/**
|
|
|
|
* @param {GameRoot} root
|
|
|
|
*/
|
|
|
|
canAfford(root) {
|
|
|
|
return root.hubGoals.getShapesStoredByKey(blueprintShape) >= this.getCost();
|
|
|
|
}
|
|
|
|
|
2020-05-27 12:30:59 +00:00
|
|
|
/**
|
2020-05-27 13:03:36 +00:00
|
|
|
* Attempts to place the blueprint at the given tile
|
2020-05-27 12:30:59 +00:00
|
|
|
* @param {GameRoot} root
|
|
|
|
* @param {Vector} tile
|
|
|
|
*/
|
|
|
|
tryPlace(root, tile) {
|
2020-05-27 13:03:36 +00:00
|
|
|
return root.logic.performBulkOperation(() => {
|
|
|
|
let anyPlaced = false;
|
|
|
|
for (let i = 0; i < this.entities.length; ++i) {
|
|
|
|
const entity = this.entities[i];
|
2020-07-05 15:56:54 +00:00
|
|
|
if (!root.logic.checkCanPlaceEntity(entity, tile)) {
|
|
|
|
continue;
|
2020-05-27 12:30:59 +00:00
|
|
|
}
|
|
|
|
|
2020-07-05 15:56:54 +00:00
|
|
|
const clone = entity.duplicateWithoutContents();
|
|
|
|
clone.components.StaticMapEntity.origin.addInplace(tile);
|
|
|
|
root.logic.freeEntityAreaBeforeBuild(clone);
|
|
|
|
root.map.placeStaticEntity(clone);
|
|
|
|
root.entityMgr.registerEntity(clone);
|
|
|
|
anyPlaced = true;
|
2020-05-27 12:30:59 +00:00
|
|
|
}
|
2020-05-27 13:03:36 +00:00
|
|
|
return anyPlaced;
|
|
|
|
});
|
2020-05-27 12:30:59 +00:00
|
|
|
}
|
|
|
|
}
|