mirror of
https://github.com/tobspr/shapez.io.git
synced 2025-12-13 18:21:51 +00:00
Direction lock now indicates when there is a building inbetween
This commit is contained in:
parent
f3a939b071
commit
4a76135d57
@ -65,10 +65,10 @@ class Mod extends shapez.Mod {
|
||||
// Only allow placing an entity when there is enough currency
|
||||
this.modInterface.replaceMethod(shapez.GameLogic, "checkCanPlaceEntity", function (
|
||||
$original,
|
||||
[entity, offset]
|
||||
[entity, options]
|
||||
) {
|
||||
const storedCurrency = this.root.hubGoals.storedShapes[CURRENCY] || 0;
|
||||
return storedCurrency > 0 && $original(entity, offset);
|
||||
return storedCurrency > 0 && $original(entity, options);
|
||||
});
|
||||
|
||||
// Take shapes when placing a building
|
||||
|
||||
@ -40,6 +40,10 @@ const RESOURCES = {
|
||||
color: "rgb(74, 237, 134)",
|
||||
background: "rgba(74, 237, 134, 0.2)",
|
||||
},
|
||||
error: {
|
||||
color: "rgb(255, 137, 137)",
|
||||
background: "rgba(255, 137, 137, 0.2)",
|
||||
},
|
||||
},
|
||||
|
||||
colorBlindPickerTile: "rgba(50, 50, 50, 0.4)",
|
||||
|
||||
@ -82,7 +82,7 @@ export class Blueprint {
|
||||
const rect = staticComp.getTileSpaceBounds();
|
||||
rect.moveBy(tile.x, tile.y);
|
||||
|
||||
if (!parameters.root.logic.checkCanPlaceEntity(entity, tile)) {
|
||||
if (!parameters.root.logic.checkCanPlaceEntity(entity, { offset: tile })) {
|
||||
parameters.context.globalAlpha = 0.3;
|
||||
} else {
|
||||
parameters.context.globalAlpha = 1;
|
||||
@ -131,7 +131,7 @@ export class Blueprint {
|
||||
|
||||
for (let i = 0; i < this.entities.length; ++i) {
|
||||
const entity = this.entities[i];
|
||||
if (root.logic.checkCanPlaceEntity(entity, tile)) {
|
||||
if (root.logic.checkCanPlaceEntity(entity, { offset: tile })) {
|
||||
anyPlaceable = true;
|
||||
}
|
||||
}
|
||||
@ -160,7 +160,7 @@ export class Blueprint {
|
||||
let count = 0;
|
||||
for (let i = 0; i < this.entities.length; ++i) {
|
||||
const entity = this.entities[i];
|
||||
if (!root.logic.checkCanPlaceEntity(entity, tile)) {
|
||||
if (!root.logic.checkCanPlaceEntity(entity, { offset: tile })) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@ -61,7 +61,7 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic {
|
||||
this.currentInterpolatedCornerTile = new Vector();
|
||||
|
||||
this.lockIndicatorSprites = {};
|
||||
layers.forEach(layer => {
|
||||
[...layers, "error"].forEach(layer => {
|
||||
this.lockIndicatorSprites[layer] = this.makeLockIndicatorSprite(layer);
|
||||
});
|
||||
|
||||
@ -76,7 +76,7 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic {
|
||||
|
||||
/**
|
||||
* Makes the lock indicator sprite for the given layer
|
||||
* @param {Layer} layer
|
||||
* @param {string} layer
|
||||
*/
|
||||
makeLockIndicatorSprite(layer) {
|
||||
const dims = 48;
|
||||
@ -358,7 +358,7 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic {
|
||||
rotationVariant
|
||||
);
|
||||
|
||||
const canBuild = this.root.logic.checkCanPlaceEntity(this.fakeEntity);
|
||||
const canBuild = this.root.logic.checkCanPlaceEntity(this.fakeEntity, {});
|
||||
|
||||
// Fade in / out
|
||||
parameters.context.lineWidth = 1;
|
||||
@ -397,6 +397,42 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there are any entities in the way, returns true if there are
|
||||
* @param {Vector} from
|
||||
* @param {Vector} to
|
||||
* @returns
|
||||
*/
|
||||
checkForObstales(from, to) {
|
||||
assert(from.x === to.x || from.y === to.y, "Must be a straight line");
|
||||
|
||||
const prop = from.x === to.x ? "y" : "x";
|
||||
const current = from.copy();
|
||||
|
||||
const metaBuilding = this.currentMetaBuilding.get();
|
||||
this.fakeEntity.layer = metaBuilding.getLayer();
|
||||
const staticComp = this.fakeEntity.components.StaticMapEntity;
|
||||
staticComp.origin = current;
|
||||
staticComp.rotation = 0;
|
||||
metaBuilding.updateVariants(this.fakeEntity, 0, this.currentVariant.get());
|
||||
staticComp.code = getCodeFromBuildingData(
|
||||
this.currentMetaBuilding.get(),
|
||||
this.currentVariant.get(),
|
||||
0
|
||||
);
|
||||
|
||||
const start = Math.min(from[prop], to[prop]);
|
||||
const end = Math.max(from[prop], to[prop]);
|
||||
|
||||
for (let i = start; i <= end; i++) {
|
||||
current[prop] = i;
|
||||
if (!this.root.logic.checkCanPlaceEntity(this.fakeEntity, { allowReplaceBuildings: false })) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DrawParameters} parameters
|
||||
*/
|
||||
@ -407,55 +443,73 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic {
|
||||
return;
|
||||
}
|
||||
|
||||
const applyStyles = look => {
|
||||
parameters.context.fillStyle = THEME.map.directionLock[look].color;
|
||||
parameters.context.strokeStyle = THEME.map.directionLock[look].background;
|
||||
parameters.context.lineWidth = 10;
|
||||
};
|
||||
|
||||
if (!this.lastDragTile) {
|
||||
// Not dragging yet
|
||||
applyStyles(this.root.currentLayer);
|
||||
const mouseWorld = this.root.camera.screenToWorld(mousePosition);
|
||||
parameters.context.beginCircle(mouseWorld.x, mouseWorld.y, 4);
|
||||
parameters.context.fill();
|
||||
return;
|
||||
}
|
||||
|
||||
const mouseWorld = this.root.camera.screenToWorld(mousePosition);
|
||||
const mouseTile = mouseWorld.toTileSpace();
|
||||
parameters.context.fillStyle = THEME.map.directionLock[this.root.currentLayer].color;
|
||||
parameters.context.strokeStyle = THEME.map.directionLock[this.root.currentLayer].background;
|
||||
parameters.context.lineWidth = 10;
|
||||
const startLine = this.lastDragTile.toWorldSpaceCenterOfTile();
|
||||
const endLine = mouseTile.toWorldSpaceCenterOfTile();
|
||||
const midLine = this.currentDirectionLockCorner.toWorldSpaceCenterOfTile();
|
||||
const anyObstacle =
|
||||
this.checkForObstales(this.lastDragTile, this.currentDirectionLockCorner) ||
|
||||
this.checkForObstales(this.currentDirectionLockCorner, mouseTile);
|
||||
|
||||
if (anyObstacle) {
|
||||
applyStyles("error");
|
||||
} else {
|
||||
applyStyles(this.root.currentLayer);
|
||||
}
|
||||
|
||||
parameters.context.beginCircle(mouseWorld.x, mouseWorld.y, 4);
|
||||
parameters.context.fill();
|
||||
|
||||
if (this.lastDragTile) {
|
||||
const startLine = this.lastDragTile.toWorldSpaceCenterOfTile();
|
||||
const endLine = mouseTile.toWorldSpaceCenterOfTile();
|
||||
const midLine = this.currentDirectionLockCorner.toWorldSpaceCenterOfTile();
|
||||
parameters.context.beginCircle(startLine.x, startLine.y, 8);
|
||||
parameters.context.fill();
|
||||
|
||||
parameters.context.beginCircle(startLine.x, startLine.y, 8);
|
||||
parameters.context.fill();
|
||||
parameters.context.beginPath();
|
||||
parameters.context.moveTo(startLine.x, startLine.y);
|
||||
parameters.context.lineTo(midLine.x, midLine.y);
|
||||
parameters.context.lineTo(endLine.x, endLine.y);
|
||||
parameters.context.stroke();
|
||||
|
||||
parameters.context.beginPath();
|
||||
parameters.context.moveTo(startLine.x, startLine.y);
|
||||
parameters.context.lineTo(midLine.x, midLine.y);
|
||||
parameters.context.lineTo(endLine.x, endLine.y);
|
||||
parameters.context.stroke();
|
||||
parameters.context.beginCircle(endLine.x, endLine.y, 5);
|
||||
parameters.context.fill();
|
||||
|
||||
parameters.context.beginCircle(endLine.x, endLine.y, 5);
|
||||
parameters.context.fill();
|
||||
// Draw arrow
|
||||
const arrowSprite = this.lockIndicatorSprites[anyObstacle ? "error" : this.root.currentLayer];
|
||||
const path = this.computeDirectionLockPath();
|
||||
for (let i = 0; i < path.length - 1; i += 1) {
|
||||
const { rotation, tile } = path[i];
|
||||
const worldPos = tile.toWorldSpaceCenterOfTile();
|
||||
const angle = Math.radians(rotation);
|
||||
|
||||
// Draw arrow
|
||||
const arrowSprite = this.lockIndicatorSprites[this.root.currentLayer];
|
||||
const path = this.computeDirectionLockPath();
|
||||
for (let i = 0; i < path.length - 1; i += 1) {
|
||||
const { rotation, tile } = path[i];
|
||||
const worldPos = tile.toWorldSpaceCenterOfTile();
|
||||
const angle = Math.radians(rotation);
|
||||
|
||||
parameters.context.translate(worldPos.x, worldPos.y);
|
||||
parameters.context.rotate(angle);
|
||||
parameters.context.drawImage(
|
||||
arrowSprite,
|
||||
-6,
|
||||
-globalConfig.halfTileSize -
|
||||
clamp((this.root.time.realtimeNow() * 1.5) % 1.0, 0, 1) * 1 * globalConfig.tileSize +
|
||||
globalConfig.halfTileSize -
|
||||
6,
|
||||
12,
|
||||
12
|
||||
);
|
||||
parameters.context.rotate(-angle);
|
||||
parameters.context.translate(-worldPos.x, -worldPos.y);
|
||||
}
|
||||
parameters.context.translate(worldPos.x, worldPos.y);
|
||||
parameters.context.rotate(angle);
|
||||
parameters.context.drawImage(
|
||||
arrowSprite,
|
||||
-6,
|
||||
-globalConfig.halfTileSize -
|
||||
clamp((this.root.time.realtimeNow() * 1.5) % 1.0, 0, 1) * 1 * globalConfig.tileSize +
|
||||
globalConfig.halfTileSize -
|
||||
6,
|
||||
12,
|
||||
12
|
||||
);
|
||||
parameters.context.rotate(-angle);
|
||||
parameters.context.translate(-worldPos.x, -worldPos.y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -53,10 +53,12 @@ export class GameLogic {
|
||||
/**
|
||||
* Checks if the given entity can be placed
|
||||
* @param {Entity} entity
|
||||
* @param {Vector=} offset Optional, move the entity by the given offset first
|
||||
* @param {Object} param0
|
||||
* @param {boolean=} param0.allowReplaceBuildings
|
||||
* @param {Vector=} param0.offset Optional, move the entity by the given offset first
|
||||
* @returns {boolean} true if the entity could be placed there
|
||||
*/
|
||||
checkCanPlaceEntity(entity, offset = null) {
|
||||
checkCanPlaceEntity(entity, { allowReplaceBuildings = false, offset = null }) {
|
||||
// Compute area of the building
|
||||
const rect = entity.components.StaticMapEntity.getTileSpaceBounds();
|
||||
if (offset) {
|
||||
@ -71,7 +73,7 @@ export class GameLogic {
|
||||
const otherEntity = this.root.map.getLayerContentXY(x, y, entity.layer);
|
||||
if (otherEntity) {
|
||||
const metaClass = otherEntity.components.StaticMapEntity.getMetaBuilding();
|
||||
if (!metaClass.getIsReplaceable()) {
|
||||
if (!allowReplaceBuildings || !metaClass.getIsReplaceable()) {
|
||||
// This one is a direct blocker
|
||||
return false;
|
||||
}
|
||||
@ -116,7 +118,7 @@ export class GameLogic {
|
||||
rotationVariant,
|
||||
variant,
|
||||
});
|
||||
if (this.checkCanPlaceEntity(entity)) {
|
||||
if (this.checkCanPlaceEntity(entity, {})) {
|
||||
this.freeEntityAreaBeforeBuild(entity);
|
||||
this.root.map.placeStaticEntity(entity);
|
||||
this.root.entityMgr.registerEntity(entity);
|
||||
|
||||
@ -18,6 +18,10 @@
|
||||
"wires": {
|
||||
"color": "rgb(74, 237, 134)",
|
||||
"background": "rgba(74, 237, 134, 0.2)"
|
||||
},
|
||||
"error": {
|
||||
"color": "rgb(255, 137, 137)",
|
||||
"background": "rgba(255, 137, 137, 0.2)"
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -18,6 +18,10 @@
|
||||
"wires": {
|
||||
"color": "rgb(74, 237, 134)",
|
||||
"background": "rgba(74, 237, 134, 0.2)"
|
||||
},
|
||||
"error": {
|
||||
"color": "rgb(255, 137, 137)",
|
||||
"background": "rgba(255, 137, 137, 0.2)"
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user