mirror of
https://github.com/tobspr/shapez.io.git
synced 2024-10-27 20:34:29 +00:00
Introduce cost for blueprints
This commit is contained in:
parent
955cba74aa
commit
37685d64bd
39
src/css/ingame_hud/blueprint_placer.scss
Normal file
39
src/css/ingame_hud/blueprint_placer.scss
Normal file
@ -0,0 +1,39 @@
|
||||
#ingame_HUD_BlueprintPlacer {
|
||||
position: absolute;
|
||||
@include S(top, 50px);
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
color: #333;
|
||||
z-index: 9999;
|
||||
background: rgba(0, 10, 20, 0.5);
|
||||
@include S(padding, 5px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: #fff;
|
||||
@include S(width, 120px);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.label {
|
||||
@include PlainText;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.costContainer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@include Heading;
|
||||
|
||||
> canvas {
|
||||
@include S(margin-left, 5px);
|
||||
@include S(width, 30px);
|
||||
@include S(height, 30px);
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.canAfford) {
|
||||
background: rgba(98, 27, 41, 0.8);
|
||||
// .costContainer {
|
||||
color: rgb(255, 97, 128);
|
||||
// }
|
||||
}
|
||||
}
|
@ -47,6 +47,7 @@
|
||||
@import "ingame_hud/entity_debugger";
|
||||
@import "ingame_hud/tutorial_hints";
|
||||
@import "ingame_hud/watermark";
|
||||
@import "ingame_hud/blueprint_placer";
|
||||
|
||||
// prettier-ignore
|
||||
$elements:
|
||||
@ -68,6 +69,7 @@ ingame_HUD_DebugInfo,
|
||||
ingame_HUD_EntityDebugger,
|
||||
ingame_HUD_TutorialHints,
|
||||
ingame_HUD_buildings_toolbar,
|
||||
ingame_HUD_BlueprintPlacer,
|
||||
ingame_HUD_Watermark,
|
||||
|
||||
// Overlays
|
||||
|
@ -83,7 +83,7 @@ export const globalConfig = {
|
||||
|
||||
debug: {
|
||||
/* dev:start */
|
||||
// fastGameEnter: true,
|
||||
fastGameEnter: true,
|
||||
// noArtificialDelays: true,
|
||||
// disableSavegameWrite: true,
|
||||
// showEntityBounds: true,
|
||||
|
@ -8,7 +8,7 @@ import { enumItemProcessorTypes } from "./components/item_processor";
|
||||
import { GameRoot } from "./root";
|
||||
import { enumSubShape, ShapeDefinition } from "./shape_definition";
|
||||
import { enumHubGoalRewards, tutorialGoals } from "./tutorial_goals";
|
||||
import { UPGRADES } from "./upgrades";
|
||||
import { UPGRADES, blueprintShape } from "./upgrades";
|
||||
|
||||
export class HubGoals extends BasicSerializableObject {
|
||||
static getId() {
|
||||
@ -53,6 +53,10 @@ export class HubGoals extends BasicSerializableObject {
|
||||
}
|
||||
this.upgradeImprovements[upgradeId] = totalImprovement;
|
||||
}
|
||||
|
||||
if (G_IS_DEV) {
|
||||
this.storedShapes[blueprintShape] = 1000;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -77,6 +81,10 @@ export class HubGoals extends BasicSerializableObject {
|
||||
*/
|
||||
this.storedShapes = {};
|
||||
|
||||
if (G_IS_DEV) {
|
||||
this.storedShapes[blueprintShape] = 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the levels for all upgrades
|
||||
* @type {Object<string, number>}
|
||||
@ -113,6 +121,19 @@ export class HubGoals extends BasicSerializableObject {
|
||||
getShapesStored(definition) {
|
||||
return this.storedShapes[definition.getHash()] || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} key
|
||||
* @param {number} amount
|
||||
*/
|
||||
takeShapeByKey(key, amount) {
|
||||
assert(this.getShapesStoredByKey(key) >= amount, "Can not afford: " + key + " x " + amount);
|
||||
assert(amount > 0, "Amount <= 0 for " + key);
|
||||
assert(Number.isInteger(amount), "Invalid amount: " + amount);
|
||||
this.storedShapes[key] -= amount;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns how much of the current shape is stored
|
||||
* @param {string} key
|
||||
|
@ -4,6 +4,9 @@ import { createLogger } from "../../../core/logging";
|
||||
import { Vector } from "../../../core/vector";
|
||||
import { Entity } from "../../entity";
|
||||
import { GameRoot } from "../../root";
|
||||
import { findNiceIntegerValue } from "../../../core/utils";
|
||||
import { Math_pow } from "../../../core/builtins";
|
||||
import { blueprintShape } from "../../upgrades";
|
||||
|
||||
const logger = createLogger("blueprint");
|
||||
|
||||
@ -47,6 +50,13 @@ export class Blueprint {
|
||||
return new Blueprint(newEntities);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cost of this blueprint in shapes
|
||||
*/
|
||||
getCost() {
|
||||
return findNiceIntegerValue(4 * Math_pow(this.entities.length, 1.1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the blueprint at the given origin
|
||||
* @param {DrawParameters} parameters
|
||||
@ -147,6 +157,13 @@ export class Blueprint {
|
||||
return anyPlaceable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GameRoot} root
|
||||
*/
|
||||
canAfford(root) {
|
||||
return root.hubGoals.getShapesStoredByKey(blueprintShape) >= this.getCost();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to place the blueprint at the given tile
|
||||
* @param {GameRoot} root
|
||||
|
@ -6,9 +6,23 @@ import { enumMouseButton } from "../../camera";
|
||||
import { KEYMAPPINGS } from "../../key_action_mapper";
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { Blueprint } from "./blueprint";
|
||||
import { makeDiv } from "../../../core/utils";
|
||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||
import { blueprintShape } from "../../upgrades";
|
||||
import { T } from "../../../translations";
|
||||
|
||||
export class HUDBlueprintPlacer extends BaseHUDPart {
|
||||
createElements(parent) {}
|
||||
createElements(parent) {
|
||||
const blueprintCostShape = this.root.shapeDefinitionMgr.getShapeFromShortKey(blueprintShape);
|
||||
const blueprintCostShapeCanvas = blueprintCostShape.generateAsCanvas(80);
|
||||
|
||||
this.costDisplayParent = makeDiv(parent, "ingame_HUD_BlueprintPlacer", [], ``);
|
||||
|
||||
makeDiv(this.costDisplayParent, null, ["label"], T.ingame.blueprintPlacer.cost);
|
||||
const costContainer = makeDiv(this.costDisplayParent, null, ["costContainer"], "");
|
||||
this.costDisplayText = makeDiv(costContainer, null, ["costText"], "");
|
||||
costContainer.appendChild(blueprintCostShapeCanvas);
|
||||
}
|
||||
|
||||
initialize() {
|
||||
this.root.hud.signals.buildingsSelectedForCopy.add(this.onBuildingsSelected, this);
|
||||
@ -27,6 +41,9 @@ export class HUDBlueprintPlacer extends BaseHUDPart {
|
||||
this.root.camera.movePreHandler.add(this.onMouseMove, this);
|
||||
|
||||
this.root.hud.signals.selectedPlacementBuildingChanged.add(this.abortPlacement, this);
|
||||
|
||||
this.domAttach = new DynamicDomAttach(this.root, this.costDisplayParent);
|
||||
this.trackedCanAfford = new TrackedState(this.onCanAffordChanged, this);
|
||||
}
|
||||
|
||||
abortPlacement() {
|
||||
@ -37,7 +54,25 @@ export class HUDBlueprintPlacer extends BaseHUDPart {
|
||||
}
|
||||
}
|
||||
|
||||
onBlueprintChanged(blueprint) {}
|
||||
onCanAffordChanged(canAfford) {
|
||||
this.costDisplayParent.classList.toggle("canAfford", canAfford);
|
||||
}
|
||||
|
||||
update() {
|
||||
this.domAttach.update(this.currentBlueprint.get());
|
||||
this.trackedCanAfford.set(
|
||||
this.currentBlueprint.get() && this.currentBlueprint.get().canAfford(this.root)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Blueprint} blueprint
|
||||
*/
|
||||
onBlueprintChanged(blueprint) {
|
||||
if (blueprint) {
|
||||
this.costDisplayText.innerText = "" + blueprint.getCost();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mouse down pre handler
|
||||
@ -55,9 +90,17 @@ export class HUDBlueprintPlacer extends BaseHUDPart {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!blueprint.canAfford(this.root)) {
|
||||
this.root.soundProxy.playUiError();
|
||||
return;
|
||||
}
|
||||
|
||||
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(blueprintShape, cost);
|
||||
|
||||
// This actually feels weird
|
||||
// if (!this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.placeMultiple).isCurrentlyPressed()) {
|
||||
// this.currentBlueprint.set(null);
|
||||
|
@ -77,7 +77,7 @@ export class HUDPinnedShapes extends BaseHUDPart {
|
||||
this.internalPinShape(currentKey, currentGoal.required, false);
|
||||
|
||||
if (this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_blueprints)) {
|
||||
this.internalPinShape(blueprintShape, currentGoal.required, false);
|
||||
this.internalPinShape(blueprintShape, null, false);
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.pinnedShapes.length; ++i) {
|
||||
@ -114,7 +114,10 @@ export class HUDPinnedShapes extends BaseHUDPart {
|
||||
}
|
||||
|
||||
const amountLabel = makeDiv(element, null, ["amountLabel"], "");
|
||||
const goalLabel = makeDiv(element, null, ["goalLabel"], "/" + formatBigNumber(goal));
|
||||
|
||||
if (goal) {
|
||||
makeDiv(element, null, ["goalLabel"], "/" + formatBigNumber(goal));
|
||||
}
|
||||
|
||||
this.handles.push({
|
||||
key,
|
||||
|
@ -298,6 +298,10 @@ ingame:
|
||||
showHint: Show hint
|
||||
hideHint: Close
|
||||
|
||||
# When placing a blueprint
|
||||
blueprintPlacer:
|
||||
cost: Cost
|
||||
|
||||
# All shop upgrades
|
||||
shopUpgrades:
|
||||
belt:
|
||||
|
Loading…
Reference in New Issue
Block a user