Introduce cost for blueprints

This commit is contained in:
tobspr 2020-05-28 18:07:57 +02:00
parent 955cba74aa
commit 37685d64bd
8 changed files with 135 additions and 6 deletions

View 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);
// }
}
}

View File

@ -47,6 +47,7 @@
@import "ingame_hud/entity_debugger"; @import "ingame_hud/entity_debugger";
@import "ingame_hud/tutorial_hints"; @import "ingame_hud/tutorial_hints";
@import "ingame_hud/watermark"; @import "ingame_hud/watermark";
@import "ingame_hud/blueprint_placer";
// prettier-ignore // prettier-ignore
$elements: $elements:
@ -68,6 +69,7 @@ ingame_HUD_DebugInfo,
ingame_HUD_EntityDebugger, ingame_HUD_EntityDebugger,
ingame_HUD_TutorialHints, ingame_HUD_TutorialHints,
ingame_HUD_buildings_toolbar, ingame_HUD_buildings_toolbar,
ingame_HUD_BlueprintPlacer,
ingame_HUD_Watermark, ingame_HUD_Watermark,
// Overlays // Overlays

View File

@ -83,7 +83,7 @@ export const globalConfig = {
debug: { debug: {
/* dev:start */ /* dev:start */
// fastGameEnter: true, fastGameEnter: true,
// noArtificialDelays: true, // noArtificialDelays: true,
// disableSavegameWrite: true, // disableSavegameWrite: true,
// showEntityBounds: true, // showEntityBounds: true,

View File

@ -8,7 +8,7 @@ import { enumItemProcessorTypes } from "./components/item_processor";
import { GameRoot } from "./root"; import { GameRoot } from "./root";
import { enumSubShape, ShapeDefinition } from "./shape_definition"; import { enumSubShape, ShapeDefinition } from "./shape_definition";
import { enumHubGoalRewards, tutorialGoals } from "./tutorial_goals"; import { enumHubGoalRewards, tutorialGoals } from "./tutorial_goals";
import { UPGRADES } from "./upgrades"; import { UPGRADES, blueprintShape } from "./upgrades";
export class HubGoals extends BasicSerializableObject { export class HubGoals extends BasicSerializableObject {
static getId() { static getId() {
@ -53,6 +53,10 @@ export class HubGoals extends BasicSerializableObject {
} }
this.upgradeImprovements[upgradeId] = totalImprovement; this.upgradeImprovements[upgradeId] = totalImprovement;
} }
if (G_IS_DEV) {
this.storedShapes[blueprintShape] = 1000;
}
} }
/** /**
@ -77,6 +81,10 @@ export class HubGoals extends BasicSerializableObject {
*/ */
this.storedShapes = {}; this.storedShapes = {};
if (G_IS_DEV) {
this.storedShapes[blueprintShape] = 1000;
}
/** /**
* Stores the levels for all upgrades * Stores the levels for all upgrades
* @type {Object<string, number>} * @type {Object<string, number>}
@ -113,6 +121,19 @@ export class HubGoals extends BasicSerializableObject {
getShapesStored(definition) { getShapesStored(definition) {
return this.storedShapes[definition.getHash()] || 0; 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 * Returns how much of the current shape is stored
* @param {string} key * @param {string} key

View File

@ -4,6 +4,9 @@ import { createLogger } from "../../../core/logging";
import { Vector } from "../../../core/vector"; import { Vector } from "../../../core/vector";
import { Entity } from "../../entity"; import { Entity } from "../../entity";
import { GameRoot } from "../../root"; import { GameRoot } from "../../root";
import { findNiceIntegerValue } from "../../../core/utils";
import { Math_pow } from "../../../core/builtins";
import { blueprintShape } from "../../upgrades";
const logger = createLogger("blueprint"); const logger = createLogger("blueprint");
@ -47,6 +50,13 @@ export class Blueprint {
return new Blueprint(newEntities); 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 * Draws the blueprint at the given origin
* @param {DrawParameters} parameters * @param {DrawParameters} parameters
@ -147,6 +157,13 @@ export class Blueprint {
return anyPlaceable; return anyPlaceable;
} }
/**
* @param {GameRoot} root
*/
canAfford(root) {
return root.hubGoals.getShapesStoredByKey(blueprintShape) >= this.getCost();
}
/** /**
* Attempts to place the blueprint at the given tile * Attempts to place the blueprint at the given tile
* @param {GameRoot} root * @param {GameRoot} root

View File

@ -6,9 +6,23 @@ import { enumMouseButton } from "../../camera";
import { KEYMAPPINGS } from "../../key_action_mapper"; import { KEYMAPPINGS } from "../../key_action_mapper";
import { BaseHUDPart } from "../base_hud_part"; import { BaseHUDPart } from "../base_hud_part";
import { Blueprint } from "./blueprint"; 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 { 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() { initialize() {
this.root.hud.signals.buildingsSelectedForCopy.add(this.onBuildingsSelected, this); 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.camera.movePreHandler.add(this.onMouseMove, this);
this.root.hud.signals.selectedPlacementBuildingChanged.add(this.abortPlacement, 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() { 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 * mouse down pre handler
@ -55,9 +90,17 @@ export class HUDBlueprintPlacer extends BaseHUDPart {
return; return;
} }
if (!blueprint.canAfford(this.root)) {
this.root.soundProxy.playUiError();
return;
}
const worldPos = this.root.camera.screenToWorld(pos); const worldPos = this.root.camera.screenToWorld(pos);
const tile = worldPos.toTileSpace(); const tile = worldPos.toTileSpace();
if (blueprint.tryPlace(this.root, tile)) { if (blueprint.tryPlace(this.root, tile)) {
const cost = blueprint.getCost();
this.root.hubGoals.takeShapeByKey(blueprintShape, cost);
// This actually feels weird // This actually feels weird
// if (!this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.placeMultiple).isCurrentlyPressed()) { // if (!this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.placeMultiple).isCurrentlyPressed()) {
// this.currentBlueprint.set(null); // this.currentBlueprint.set(null);

View File

@ -77,7 +77,7 @@ export class HUDPinnedShapes extends BaseHUDPart {
this.internalPinShape(currentKey, currentGoal.required, false); this.internalPinShape(currentKey, currentGoal.required, false);
if (this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_blueprints)) { 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) { 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 amountLabel = makeDiv(element, null, ["amountLabel"], "");
const goalLabel = makeDiv(element, null, ["goalLabel"], "/" + formatBigNumber(goal));
if (goal) {
makeDiv(element, null, ["goalLabel"], "/" + formatBigNumber(goal));
}
this.handles.push({ this.handles.push({
key, key,

View File

@ -298,6 +298,10 @@ ingame:
showHint: Show hint showHint: Show hint
hideHint: Close hideHint: Close
# When placing a blueprint
blueprintPlacer:
cost: Cost
# All shop upgrades # All shop upgrades
shopUpgrades: shopUpgrades:
belt: belt: