1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2026-03-02 03:39:21 +00:00
This commit is contained in:
tobspr
2021-06-24 18:46:49 +02:00
19 changed files with 228 additions and 130 deletions

View File

@@ -57,6 +57,15 @@
}
}
}
> .buildingsButton {
display: grid;
align-items: center;
@include S(margin-top, 4px);
> button {
@include SuperSmallText;
}
}
}
}
}

View File

@@ -13,7 +13,7 @@
> .section {
display: grid;
@include S(grid-gap, 10px);
@include S(grid-gap, 5px);
grid-auto-flow: row;
> button {

View File

@@ -72,8 +72,8 @@ export const globalConfig = {
readerAnalyzeIntervalSeconds: 10,
goalAcceptorMinimumDurationSeconds: 5,
goalAcceptorsPerProducer: 4.5,
goalAcceptorItemsRequired: 10,
goalAcceptorsPerProducer: 5,
puzzleModeSpeed: 3,
puzzleMinBoundsSize: 2,
puzzleMaxBoundsSize: 20,

View File

@@ -101,8 +101,11 @@ export class Blueprint {
const entity = this.entities[i];
const staticComp = entity.components.StaticMapEntity;
staticComp.rotation = (staticComp.rotation + 90) % 360;
staticComp.originalRotation = (staticComp.originalRotation + 90) % 360;
if (staticComp.getMetaBuilding().getIsRotateable()) {
staticComp.rotation = (staticComp.rotation + 90) % 360;
staticComp.originalRotation = (staticComp.originalRotation + 90) % 360;
}
staticComp.origin = staticComp.origin.rotateFastMultipleOf90(90);
}
}

View File

@@ -31,19 +31,26 @@ export class GoalAcceptorComponent extends Component {
clear() {
// the last items we delivered
/** @type {{ item: BaseItem; time: number; }[]} */
this.deliveryHistory = [];
/** @type {{ item: BaseItem; time: number; }} */
this.lastDelivery = null;
this.currentDeliveredItems = 0;
// Used for animations
this.displayPercentage = 0;
}
getRequiredDeliveryHistorySize() {
// clears items but doesn't instantly reset the progress bar
clearItems() {
this.lastDelivery = null;
this.currentDeliveredItems = 0;
}
getRequiredSecondsPerItem() {
return (
(globalConfig.puzzleModeSpeed *
globalConfig.goalAcceptorMinimumDurationSeconds *
globalConfig.beltSpeedItemsPerSecond) /
globalConfig.goalAcceptorsPerProducer
globalConfig.goalAcceptorsPerProducer /
(globalConfig.puzzleModeSpeed * globalConfig.beltSpeedItemsPerSecond)
);
}
}

View File

@@ -166,8 +166,8 @@ export class GameMode extends BasicSerializableObject {
}
/** @returns {boolean} */
getSupportsCopyPaste() {
return true;
getHasFreeCopyPaste() {
return false;
}
/** @returns {boolean} */

View File

@@ -27,6 +27,8 @@ export class HUDBlueprintPlacer extends BaseHUDPart {
}
initialize() {
this.isCopyPasteFree = this.root.gameMode.getHasFreeCopyPaste();
this.root.hud.signals.buildingsSelectedForCopy.add(this.createBlueprintFromBuildings, this);
/** @type {TypedTrackedState<Blueprint?>} */
@@ -82,7 +84,7 @@ export class HUDBlueprintPlacer extends BaseHUDPart {
update() {
const currentBlueprint = this.currentBlueprint.get();
this.domAttach.update(currentBlueprint && currentBlueprint.getCost() > 0);
this.domAttach.update(!this.isCopyPasteFree && currentBlueprint && currentBlueprint.getCost() > 0);
this.trackedCanAfford.set(currentBlueprint && currentBlueprint.canAfford(this.root));
}
@@ -114,7 +116,7 @@ export class HUDBlueprintPlacer extends BaseHUDPart {
return;
}
if (!blueprint.canAfford(this.root)) {
if (!this.isCopyPasteFree && !blueprint.canAfford(this.root)) {
this.root.soundProxy.playUiError();
return;
}
@@ -122,8 +124,10 @@ export class HUDBlueprintPlacer extends BaseHUDPart {
const worldPos = this.root.camera.screenToWorld(pos);
const tile = worldPos.toTileSpace();
if (blueprint.tryPlace(this.root, tile)) {
const cost = blueprint.getCost();
this.root.hubGoals.takeShapeByKey(this.root.gameMode.getBlueprintShapeKey(), cost);
if (!this.isCopyPasteFree) {
const cost = blueprint.getCost();
this.root.hubGoals.takeShapeByKey(this.root.gameMode.getBlueprintShapeKey(), cost);
}
this.root.soundProxy.playUi(SOUNDS.placeBuilding);
}
return STOP_PROPAGATION;
@@ -131,7 +135,7 @@ export class HUDBlueprintPlacer extends BaseHUDPart {
}
/**
* Mose move handler
* Mouse move handler
*/
onMouseMove() {
// Prevent movement while blueprint is selected

View File

@@ -1,5 +1,6 @@
import { globalConfig } from "../../../core/config";
import { DrawParameters } from "../../../core/draw_parameters";
import { gMetaBuildingRegistry } from "../../../core/global_registries";
import { createLogger } from "../../../core/logging";
import { STOP_PROPAGATION } from "../../../core/signal";
import { formatBigNumberFull } from "../../../core/utils";
@@ -7,6 +8,8 @@ import { Vector } from "../../../core/vector";
import { ACHIEVEMENTS } from "../../../platform/achievement_provider";
import { T } from "../../../translations";
import { Blueprint } from "../../blueprint";
import { MetaBlockBuilding } from "../../buildings/block";
import { MetaConstantProducerBuilding } from "../../buildings/constant_producer";
import { enumMouseButton } from "../../camera";
import { Component } from "../../component";
import { Entity } from "../../entity";
@@ -260,7 +263,14 @@ export class HUDMassSelector extends BaseHUDPart {
for (let x = realTileStart.x; x <= realTileEnd.x; ++x) {
for (let y = realTileStart.y; y <= realTileEnd.y; ++y) {
const contents = this.root.map.getLayerContentXY(x, y, this.root.currentLayer);
if (contents && this.root.logic.canDeleteBuilding(contents)) {
const staticComp = contents.components.StaticMapEntity;
if (!staticComp.getMetaBuilding().getIsRemovable(this.root)) {
continue;
}
this.selectedUids.add(contents.uid);
}
}
@@ -320,6 +330,11 @@ export class HUDMassSelector extends BaseHUDPart {
renderedUids.add(uid);
const staticComp = contents.components.StaticMapEntity;
if (!staticComp.getMetaBuilding().getIsRemovable(this.root)) {
continue;
}
const bounds = staticComp.getTileSpaceBounds();
parameters.context.beginRoundedRect(
bounds.x * globalConfig.tileSize + boundsBorder,

View File

@@ -216,8 +216,8 @@ export class HUDPuzzleEditorReview extends BaseHUDPart {
if (!goalComp.item) {
return T.puzzleMenu.validation.goalAcceptorNoItem;
}
const required = goalComp.getRequiredDeliveryHistorySize();
if (goalComp.deliveryHistory.length < required) {
const required = globalConfig.goalAcceptorItemsRequired;
if (goalComp.currentDeliveredItems < required) {
return T.puzzleMenu.validation.goalAcceptorRateNotMet;
}
}

View File

@@ -9,6 +9,8 @@ import { makeDiv } from "../../../core/utils";
import { T } from "../../../translations";
import { StaticMapEntityComponent } from "../../components/static_map_entity";
import { BaseHUDPart } from "../base_hud_part";
import { gMetaBuildingRegistry } from "../../../core/global_registries";
import { MetaBlockBuilding } from "../../buildings/block";
const logger = createLogger("puzzle-editor");
@@ -43,8 +45,13 @@ export class HUDPuzzleEditorSettings extends BaseHUDPart {
<div class="buttonBar">
<button class="styledButton trim">${T.ingame.puzzleEditorSettings.trimZone}</button>
<button class="styledButton clear">${T.ingame.puzzleEditorSettings.clearItems}</button>
<button class="styledButton clearItems">${T.ingame.puzzleEditorSettings.clearItems}</button>
</div>
<div class="buildingsButton">
<button class="styledButton clearBuildings">${T.ingame.puzzleEditorSettings.clearBuildings}</button>
</div>
</div>`
);
@@ -53,14 +60,35 @@ export class HUDPuzzleEditorSettings extends BaseHUDPart {
bind(".zoneHeight .minus", () => this.modifyZone(0, -1));
bind(".zoneHeight .plus", () => this.modifyZone(0, 1));
bind("button.trim", this.trim);
bind("button.clear", this.clear);
bind("button.clearItems", this.clearItems);
bind("button.clearBuildings", this.clearBuildings);
}
}
clear() {
clearItems() {
this.root.logic.clearAllBeltsAndItems();
}
clearBuildings() {
for (const entity of this.root.entityMgr.getAllWithComponent(StaticMapEntityComponent)) {
const staticComp = entity.components.StaticMapEntity;
const signalComp = entity.components.ConstantSignal;
const goalComp = entity.components.GoalAcceptor;
if (
signalComp ||
goalComp ||
staticComp.getMetaBuilding().id === gMetaBuildingRegistry.findByClass(MetaBlockBuilding).id
) {
continue;
}
this.root.map.removeStaticEntity(entity);
this.root.entityMgr.destroyEntity(entity);
}
this.root.entityMgr.processDestroyList();
}
trim() {
// Now, find the center
const buildings = this.root.entityMgr.entities.slice();

View File

@@ -1,6 +1,9 @@
import { gMetaBuildingRegistry } from "../../../core/global_registries";
import { createLogger } from "../../../core/logging";
import { makeDiv } from "../../../core/utils";
import { T } from "../../../translations";
import { MetaBlockBuilding } from "../../buildings/block";
import { StaticMapEntityComponent } from "../../components/static_map_entity";
import { BaseHUDPart } from "../base_hud_part";
const logger = createLogger("puzzle-play");
@@ -17,19 +20,41 @@ export class HUDPuzzlePlaySettings extends BaseHUDPart {
null,
["section"],
`
<button class="styledButton clear">${T.ingame.puzzleEditorSettings.clearItems}</button>
<button class="styledButton clearItems">${T.ingame.puzzleEditorSettings.clearItems}</button>
<button class="styledButton clearBuildings">${T.ingame.puzzleEditorSettings.clearBuildings}</button>
`
);
bind("button.clear", this.clear);
bind("button.clearItems", this.clearItems);
bind("button.clearBuildings", this.clearBuildings);
}
}
clear() {
clearItems() {
this.root.logic.clearAllBeltsAndItems();
}
clearBuildings() {
for (const entity of this.root.entityMgr.getAllWithComponent(StaticMapEntityComponent)) {
const staticComp = entity.components.StaticMapEntity;
const signalComp = entity.components.ConstantSignal;
const goalComp = entity.components.GoalAcceptor;
if (
signalComp ||
goalComp ||
staticComp.getMetaBuilding().id === gMetaBuildingRegistry.findByClass(MetaBlockBuilding).id
) {
continue;
}
this.root.map.removeStaticEntity(entity);
this.root.entityMgr.destroyEntity(entity);
}
this.root.entityMgr.processDestroyList();
}
initialize() {
this.visible = true;
}

View File

@@ -158,10 +158,9 @@ export class MetaBuilding {
/**
* Returns whether this building is rotateable
* @param {string} variant
* @returns {boolean}
*/
getIsRotateable(variant) {
getIsRotateable() {
return true;
}
@@ -243,7 +242,7 @@ export class MetaBuilding {
* @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array<Entity> }}
*/
computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) {
if (!this.getIsRotateable(variant)) {
if (!this.getIsRotateable()) {
return {
rotation: 0,
rotationVariant: 0,

View File

@@ -7,6 +7,8 @@ import { types } from "../../savegame/serialization";
import { enumGameModeTypes, GameMode } from "../game_mode";
import { HUDPuzzleBackToMenu } from "../hud/parts/puzzle_back_to_menu";
import { HUDPuzzleDLCLogo } from "../hud/parts/puzzle_dlc_logo";
import { HUDBlueprintPlacer } from "../hud/parts/blueprint_placer";
import { HUDMassSelector } from "../hud/parts/mass_selector";
export class PuzzleGameMode extends GameMode {
static getType() {
@@ -30,6 +32,8 @@ export class PuzzleGameMode extends GameMode {
this.additionalHudParts = {
puzzleBackToMenu: HUDPuzzleBackToMenu,
puzzleDlcLogo: HUDPuzzleDLCLogo,
blueprintPlacer: HUDBlueprintPlacer,
massSelector: HUDMassSelector,
};
this.zoneWidth = data.zoneWidth || 8;
@@ -79,8 +83,8 @@ export class PuzzleGameMode extends GameMode {
return false;
}
getSupportsCopyPaste() {
return false;
getHasFreeCopyPaste() {
return true;
}
throughputDoesNotMatter() {

View File

@@ -24,13 +24,15 @@ export class GoalAcceptorSystem extends GameSystemWithFilter {
const entity = this.allEntities[i];
const goalComp = entity.components.GoalAcceptor;
// filter the ones which are no longer active, or which are not the same
goalComp.deliveryHistory = goalComp.deliveryHistory.filter(
d =>
now - d.time < globalConfig.goalAcceptorMinimumDurationSeconds && d.item === goalComp.item
);
if (!goalComp.lastDelivery) {
continue;
}
if (goalComp.deliveryHistory.length < goalComp.getRequiredDeliveryHistorySize()) {
if (now - goalComp.lastDelivery.time > goalComp.getRequiredSecondsPerItem()) {
goalComp.clearItems();
}
if (goalComp.currentDeliveredItems < globalConfig.goalAcceptorItemsRequired) {
allAccepted = false;
}
}
@@ -64,8 +66,8 @@ export class GoalAcceptorSystem extends GameSystemWithFilter {
const staticComp = contents[i].components.StaticMapEntity;
const item = goalComp.item;
const requiredItemsForSuccess = goalComp.getRequiredDeliveryHistorySize();
const percentage = clamp(goalComp.deliveryHistory.length / requiredItemsForSuccess, 0, 1);
const requiredItemsForSuccess = globalConfig.goalAcceptorItemsRequired;
const percentage = clamp(goalComp.currentDeliveredItems / requiredItemsForSuccess, 0, 1);
const center = staticComp.getTileSpaceBounds().getCenter().toWorldSpace();
if (item) {
@@ -78,7 +80,7 @@ export class GoalAcceptorSystem extends GameSystemWithFilter {
);
}
const isValid = item && goalComp.deliveryHistory.length >= requiredItemsForSuccess;
const isValid = item && goalComp.currentDeliveredItems >= requiredItemsForSuccess;
parameters.context.translate(center.x, center.y);
parameters.context.rotate((staticComp.rotation / 180) * Math.PI);
@@ -90,7 +92,7 @@ export class GoalAcceptorSystem extends GameSystemWithFilter {
// progress arc
goalComp.displayPercentage = lerp(goalComp.displayPercentage, percentage, 0.3);
goalComp.displayPercentage = lerp(goalComp.displayPercentage, percentage, 0.2);
const startAngle = Math.PI * 0.595;
const maxAngle = Math.PI * 1.82;

View File

@@ -1,3 +1,4 @@
import { globalConfig } from "../../core/config";
import { BaseItem } from "../base_item";
import { enumColorMixingResults, enumColors } from "../colors";
import {
@@ -572,23 +573,23 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
const item = payload.items[0].item;
const now = this.root.time.now();
if (goalComp.item && !item.equals(goalComp.item)) {
goalComp.clearItems();
} else {
goalComp.currentDeliveredItems = Math.min(
goalComp.currentDeliveredItems + 1,
globalConfig.goalAcceptorItemsRequired
);
}
if (this.root.gameMode.getIsEditor()) {
// while playing in editor, assign the item
goalComp.item = payload.items[0].item;
goalComp.deliveryHistory.push({
item,
time: now,
});
} else {
// otherwise, make sure it is the same, otherwise reset
if (item.equals(goalComp.item)) {
goalComp.deliveryHistory.push({
item,
time: now,
});
} else {
goalComp.deliveryHistory = [];
}
}
goalComp.lastDelivery = {
item,
time: now,
};
}
}