You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tobspr_shapez.io/src/js/game/hud/parts/shop.js

180 lines
6.7 KiB

import { BaseHUDPart } from "../base_hud_part";
import { makeDiv, removeAllChildren, formatBigNumber } from "../../../core/utils";
import { UPGRADES, TIER_LABELS } from "../../upgrades";
import { ShapeDefinition } from "../../shape_definition";
import { DynamicDomAttach } from "../dynamic_dom_attach";
import { InputReceiver } from "../../../core/input_receiver";
import { KeyActionMapper } from "../../key_action_mapper";
import { Math_min } from "../../../core/builtins";
export class HUDShop extends BaseHUDPart {
createElements(parent) {
this.background = makeDiv(parent, "ingame_HUD_Shop", ["ingameDialog"]);
// DIALOG Inner / Wrapper
this.dialogInner = makeDiv(this.background, null, ["dialogInner"]);
this.title = makeDiv(this.dialogInner, null, ["title"], `Upgrades`);
this.closeButton = makeDiv(this.title, null, ["closeButton"]);
this.trackClicks(this.closeButton, this.close);
this.contentDiv = makeDiv(this.dialogInner, null, ["content"]);
this.upgradeToElements = {};
// Upgrades
for (const upgradeId in UPGRADES) {
const { label } = UPGRADES[upgradeId];
const handle = {};
handle.requireIndexToElement = [];
// Wrapper
handle.elem = makeDiv(this.contentDiv, null, ["upgrade"]);
handle.elem.setAttribute("data-upgrade-id", upgradeId);
// Title
const title = makeDiv(handle.elem, null, ["title"], label);
// Title > Tier
handle.elemTierLabel = makeDiv(title, null, ["tier"], "Tier ?");
// Icon
handle.icon = makeDiv(handle.elem, null, ["icon"]);
handle.icon.setAttribute("data-icon", "upgrades/" + upgradeId + ".png");
// Description
handle.elemDescription = makeDiv(handle.elem, null, ["description"], "??");
handle.elemRequirements = makeDiv(handle.elem, null, ["requirements"]);
// Buy button
handle.buyButton = document.createElement("button");
handle.buyButton.classList.add("buy", "styledButton");
handle.buyButton.innerText = "Upgrade";
handle.elem.appendChild(handle.buyButton);
this.trackClicks(handle.buyButton, () => this.tryUnlockNextTier(upgradeId));
// Assign handle
this.upgradeToElements[upgradeId] = handle;
}
}
rerenderFull() {
for (const upgradeId in this.upgradeToElements) {
const handle = this.upgradeToElements[upgradeId];
const { description, tiers } = UPGRADES[upgradeId];
// removeAllChildren(handle.elem);
const currentTier = this.root.hubGoals.getUpgradeLevel(upgradeId);
const tierHandle = tiers[currentTier];
// Set tier
handle.elemTierLabel.innerText = "Tier " + TIER_LABELS[currentTier];
handle.elemTierLabel.setAttribute("data-tier", currentTier);
// Cleanup
handle.requireIndexToElement = [];
removeAllChildren(handle.elemRequirements);
handle.elem.classList.toggle("maxLevel", !tierHandle);
if (!tierHandle) {
// Max level
handle.elemDescription.innerText = "Maximum level";
continue;
}
// Set description
handle.elemDescription.innerText = description(tierHandle.improvement);
tierHandle.required.forEach(({ shape, amount }) => {
const requireDiv = makeDiv(handle.elemRequirements, null, ["requirement"]);
const shapeDef = this.root.shapeDefinitionMgr.getShapeFromShortKey(shape);
const shapeCanvas = shapeDef.generateAsCanvas(120);
shapeCanvas.classList.add();
requireDiv.appendChild(shapeCanvas);
const progressContainer = makeDiv(requireDiv, null, ["amount"]);
const progressBar = document.createElement("label");
progressBar.classList.add("progressBar");
progressContainer.appendChild(progressBar);
const progressLabel = document.createElement("label");
progressContainer.appendChild(progressLabel);
handle.requireIndexToElement.push({
progressLabel,
progressBar,
definition: shapeDef,
required: amount,
});
});
}
}
renderCountsAndStatus() {
for (const upgradeId in this.upgradeToElements) {
const handle = this.upgradeToElements[upgradeId];
for (let i = 0; i < handle.requireIndexToElement.length; ++i) {
const { progressLabel, progressBar, definition, required } = handle.requireIndexToElement[i];
const haveAmount = this.root.hubGoals.getShapesStored(definition);
const progress = Math_min(haveAmount / required, 1.0);
progressLabel.innerText = formatBigNumber(haveAmount) + " / " + formatBigNumber(required);
progressBar.style.width = progress * 100.0 + "%";
progressBar.classList.toggle("complete", progress >= 1.0);
}
handle.buyButton.classList.toggle("buyable", this.root.hubGoals.canUnlockUpgrade(upgradeId));
}
}
initialize() {
this.domAttach = new DynamicDomAttach(this.root, this.background, {
attachClass: "visible",
});
this.inputReciever = new InputReceiver("shop");
this.keyActionMapper = new KeyActionMapper(this.root, this.inputReciever);
this.keyActionMapper.getBinding("back").add(this.close, this);
this.keyActionMapper.getBinding("menu_open_shop").add(this.close, this);
this.close();
this.rerenderFull();
this.root.signals.upgradePurchased.add(this.rerenderFull, this);
}
cleanup() {
document.body.classList.remove("ingameDialogOpen");
}
show() {
this.visible = true;
document.body.classList.add("ingameDialogOpen");
// this.background.classList.add("visible");
this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever);
this.update();
}
close() {
this.visible = false;
document.body.classList.remove("ingameDialogOpen");
this.root.app.inputMgr.makeSureDetached(this.inputReciever);
this.update();
}
update() {
this.domAttach.update(this.visible);
if (this.visible) {
this.renderCountsAndStatus();
}
}
tryUnlockNextTier(upgradeId) {
// Nothing
this.root.hubGoals.tryUnlockUgprade(upgradeId);
}
}