mirror of
https://github.com/tobspr/shapez.io.git
synced 2024-10-27 20:34:29 +00:00
Fix mouse panning
This commit is contained in:
parent
ed32238412
commit
24eb060000
@ -872,6 +872,10 @@ export class Camera extends BasicSerializableObject {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.root.hud.shouldPauseGame() || this.root.hud.hasBlockingOverlayOpen()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.desiredCenter || this.desiredZoom || this.currentlyMoving || this.currentlyPinching) {
|
||||
// Performing another method of movement right now
|
||||
return;
|
||||
|
@ -194,9 +194,6 @@ export class GameHUD {
|
||||
* Returns true if the rendering can be paused
|
||||
*/
|
||||
hasBlockingOverlayOpen() {
|
||||
if (this.root.camera.getIsMapOverlayActive()) {
|
||||
return true;
|
||||
}
|
||||
for (const key in this.parts) {
|
||||
if (this.parts[key].isBlockingOverlay()) {
|
||||
return true;
|
||||
|
@ -1,211 +1,215 @@
|
||||
/* typehints:start */
|
||||
import { Application } from "../../../application";
|
||||
/* typehints:end */
|
||||
|
||||
import { SOUNDS } from "../../../platform/sound";
|
||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { Dialog, DialogLoading, DialogOptionChooser } from "../../../core/modal_dialog_elements";
|
||||
import { makeDiv } from "../../../core/utils";
|
||||
import { T } from "../../../translations";
|
||||
import { THIRDPARTY_URLS } from "../../../core/config";
|
||||
|
||||
export class HUDModalDialogs extends BaseHUDPart {
|
||||
constructor(root, app) {
|
||||
// Important: Root is not always available here! Its also used in the main menu
|
||||
super(root);
|
||||
|
||||
/** @type {Application} */
|
||||
this.app = root ? root.app : app;
|
||||
|
||||
this.dialogParent = null;
|
||||
this.dialogStack = [];
|
||||
}
|
||||
|
||||
// For use inside of the game, implementation of base hud part
|
||||
initialize() {
|
||||
this.dialogParent = document.getElementById("ingame_HUD_ModalDialogs");
|
||||
this.domWatcher = new DynamicDomAttach(this.root, this.dialogParent);
|
||||
}
|
||||
|
||||
shouldPauseRendering() {
|
||||
return this.dialogStack.length > 0;
|
||||
}
|
||||
|
||||
shouldPauseGame() {
|
||||
return this.shouldPauseRendering();
|
||||
}
|
||||
|
||||
createElements(parent) {
|
||||
return makeDiv(parent, "ingame_HUD_ModalDialogs");
|
||||
}
|
||||
|
||||
// For use outside of the game
|
||||
initializeToElement(element) {
|
||||
assert(element, "No element for dialogs given");
|
||||
this.dialogParent = element;
|
||||
}
|
||||
|
||||
// Methods
|
||||
|
||||
/**
|
||||
* @param {string} title
|
||||
* @param {string} text
|
||||
* @param {Array<string>} buttons
|
||||
*/
|
||||
showInfo(title, text, buttons = ["ok:good"]) {
|
||||
const dialog = new Dialog({
|
||||
app: this.app,
|
||||
title: title,
|
||||
contentHTML: text,
|
||||
buttons: buttons,
|
||||
type: "info",
|
||||
});
|
||||
this.internalShowDialog(dialog);
|
||||
|
||||
if (this.app) {
|
||||
this.app.sound.playUiSound(SOUNDS.dialogOk);
|
||||
}
|
||||
|
||||
return dialog.buttonSignals;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} title
|
||||
* @param {string} text
|
||||
* @param {Array<string>} buttons
|
||||
*/
|
||||
showWarning(title, text, buttons = ["ok:good"]) {
|
||||
const dialog = new Dialog({
|
||||
app: this.app,
|
||||
title: title,
|
||||
contentHTML: text,
|
||||
buttons: buttons,
|
||||
type: "warning",
|
||||
});
|
||||
this.internalShowDialog(dialog);
|
||||
|
||||
if (this.app) {
|
||||
this.app.sound.playUiSound(SOUNDS.dialogError);
|
||||
}
|
||||
|
||||
return dialog.buttonSignals;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} feature
|
||||
* @param {string} textPrefab
|
||||
*/
|
||||
showFeatureRestrictionInfo(feature, textPrefab = T.dialogs.featureRestriction.desc) {
|
||||
const dialog = new Dialog({
|
||||
app: this.app,
|
||||
title: T.dialogs.featureRestriction.title,
|
||||
contentHTML: textPrefab.replace("<feature>", feature),
|
||||
buttons: ["cancel:bad", "getStandalone:good"],
|
||||
type: "warning",
|
||||
});
|
||||
this.internalShowDialog(dialog);
|
||||
|
||||
if (this.app) {
|
||||
this.app.sound.playUiSound(SOUNDS.dialogOk);
|
||||
}
|
||||
|
||||
this.app.analytics.trackUiClick("demo_dialog_show");
|
||||
|
||||
dialog.buttonSignals.cancel.add(() => {
|
||||
this.app.analytics.trackUiClick("demo_dialog_cancel");
|
||||
});
|
||||
|
||||
dialog.buttonSignals.getStandalone.add(() => {
|
||||
this.app.analytics.trackUiClick("demo_dialog_click");
|
||||
window.open(THIRDPARTY_URLS.standaloneStorePage);
|
||||
});
|
||||
|
||||
return dialog.buttonSignals;
|
||||
}
|
||||
|
||||
showOptionChooser(title, options) {
|
||||
const dialog = new DialogOptionChooser({
|
||||
app: this.app,
|
||||
title,
|
||||
options,
|
||||
});
|
||||
this.internalShowDialog(dialog);
|
||||
return dialog.buttonSignals;
|
||||
}
|
||||
|
||||
// Returns method to be called when laoding finishd
|
||||
showLoadingDialog() {
|
||||
const dialog = new DialogLoading(this.app);
|
||||
this.internalShowDialog(dialog);
|
||||
return this.closeDialog.bind(this, dialog);
|
||||
}
|
||||
|
||||
internalShowDialog(dialog) {
|
||||
const elem = dialog.createElement();
|
||||
dialog.setIndex(this.dialogStack.length);
|
||||
|
||||
// Hide last dialog in queue
|
||||
if (this.dialogStack.length > 0) {
|
||||
this.dialogStack[this.dialogStack.length - 1].hide();
|
||||
}
|
||||
|
||||
this.dialogStack.push(dialog);
|
||||
|
||||
// Append dialog
|
||||
dialog.show();
|
||||
dialog.closeRequested.add(this.closeDialog.bind(this, dialog));
|
||||
|
||||
// Append to HTML
|
||||
this.dialogParent.appendChild(elem);
|
||||
|
||||
document.body.classList.toggle("modalDialogActive", this.dialogStack.length > 0);
|
||||
|
||||
// IMPORTANT: Attach element directly, otherwise double submit is possible
|
||||
this.update();
|
||||
}
|
||||
|
||||
update() {
|
||||
if (this.domWatcher) {
|
||||
this.domWatcher.update(this.dialogStack.length > 0);
|
||||
}
|
||||
}
|
||||
|
||||
closeDialog(dialog) {
|
||||
dialog.destroy();
|
||||
|
||||
let index = -1;
|
||||
for (let i = 0; i < this.dialogStack.length; ++i) {
|
||||
if (this.dialogStack[i] === dialog) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(index >= 0, "Dialog not in dialog stack");
|
||||
this.dialogStack.splice(index, 1);
|
||||
|
||||
if (this.dialogStack.length > 0) {
|
||||
// Show the dialog which was previously open
|
||||
this.dialogStack[this.dialogStack.length - 1].show();
|
||||
}
|
||||
|
||||
document.body.classList.toggle("modalDialogActive", this.dialogStack.length > 0);
|
||||
}
|
||||
|
||||
close() {
|
||||
for (let i = 0; i < this.dialogStack.length; ++i) {
|
||||
const dialog = this.dialogStack[i];
|
||||
dialog.destroy();
|
||||
}
|
||||
this.dialogStack = [];
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
super.cleanup();
|
||||
for (let i = 0; i < this.dialogStack.length; ++i) {
|
||||
this.dialogStack[i].destroy();
|
||||
}
|
||||
this.dialogStack = [];
|
||||
this.dialogParent = null;
|
||||
}
|
||||
}
|
||||
/* typehints:start */
|
||||
import { Application } from "../../../application";
|
||||
/* typehints:end */
|
||||
|
||||
import { SOUNDS } from "../../../platform/sound";
|
||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { Dialog, DialogLoading, DialogOptionChooser } from "../../../core/modal_dialog_elements";
|
||||
import { makeDiv } from "../../../core/utils";
|
||||
import { T } from "../../../translations";
|
||||
import { THIRDPARTY_URLS } from "../../../core/config";
|
||||
|
||||
export class HUDModalDialogs extends BaseHUDPart {
|
||||
constructor(root, app) {
|
||||
// Important: Root is not always available here! Its also used in the main menu
|
||||
super(root);
|
||||
|
||||
/** @type {Application} */
|
||||
this.app = root ? root.app : app;
|
||||
|
||||
this.dialogParent = null;
|
||||
this.dialogStack = [];
|
||||
}
|
||||
|
||||
// For use inside of the game, implementation of base hud part
|
||||
initialize() {
|
||||
this.dialogParent = document.getElementById("ingame_HUD_ModalDialogs");
|
||||
this.domWatcher = new DynamicDomAttach(this.root, this.dialogParent);
|
||||
}
|
||||
|
||||
shouldPauseRendering() {
|
||||
return this.dialogStack.length > 0;
|
||||
}
|
||||
|
||||
shouldPauseGame() {
|
||||
return this.shouldPauseRendering();
|
||||
}
|
||||
|
||||
createElements(parent) {
|
||||
return makeDiv(parent, "ingame_HUD_ModalDialogs");
|
||||
}
|
||||
|
||||
// For use outside of the game
|
||||
initializeToElement(element) {
|
||||
assert(element, "No element for dialogs given");
|
||||
this.dialogParent = element;
|
||||
}
|
||||
|
||||
isBlockingOverlay() {
|
||||
return this.dialogStack.length > 0;
|
||||
}
|
||||
|
||||
// Methods
|
||||
|
||||
/**
|
||||
* @param {string} title
|
||||
* @param {string} text
|
||||
* @param {Array<string>} buttons
|
||||
*/
|
||||
showInfo(title, text, buttons = ["ok:good"]) {
|
||||
const dialog = new Dialog({
|
||||
app: this.app,
|
||||
title: title,
|
||||
contentHTML: text,
|
||||
buttons: buttons,
|
||||
type: "info",
|
||||
});
|
||||
this.internalShowDialog(dialog);
|
||||
|
||||
if (this.app) {
|
||||
this.app.sound.playUiSound(SOUNDS.dialogOk);
|
||||
}
|
||||
|
||||
return dialog.buttonSignals;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} title
|
||||
* @param {string} text
|
||||
* @param {Array<string>} buttons
|
||||
*/
|
||||
showWarning(title, text, buttons = ["ok:good"]) {
|
||||
const dialog = new Dialog({
|
||||
app: this.app,
|
||||
title: title,
|
||||
contentHTML: text,
|
||||
buttons: buttons,
|
||||
type: "warning",
|
||||
});
|
||||
this.internalShowDialog(dialog);
|
||||
|
||||
if (this.app) {
|
||||
this.app.sound.playUiSound(SOUNDS.dialogError);
|
||||
}
|
||||
|
||||
return dialog.buttonSignals;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} feature
|
||||
* @param {string} textPrefab
|
||||
*/
|
||||
showFeatureRestrictionInfo(feature, textPrefab = T.dialogs.featureRestriction.desc) {
|
||||
const dialog = new Dialog({
|
||||
app: this.app,
|
||||
title: T.dialogs.featureRestriction.title,
|
||||
contentHTML: textPrefab.replace("<feature>", feature),
|
||||
buttons: ["cancel:bad", "getStandalone:good"],
|
||||
type: "warning",
|
||||
});
|
||||
this.internalShowDialog(dialog);
|
||||
|
||||
if (this.app) {
|
||||
this.app.sound.playUiSound(SOUNDS.dialogOk);
|
||||
}
|
||||
|
||||
this.app.analytics.trackUiClick("demo_dialog_show");
|
||||
|
||||
dialog.buttonSignals.cancel.add(() => {
|
||||
this.app.analytics.trackUiClick("demo_dialog_cancel");
|
||||
});
|
||||
|
||||
dialog.buttonSignals.getStandalone.add(() => {
|
||||
this.app.analytics.trackUiClick("demo_dialog_click");
|
||||
window.open(THIRDPARTY_URLS.standaloneStorePage);
|
||||
});
|
||||
|
||||
return dialog.buttonSignals;
|
||||
}
|
||||
|
||||
showOptionChooser(title, options) {
|
||||
const dialog = new DialogOptionChooser({
|
||||
app: this.app,
|
||||
title,
|
||||
options,
|
||||
});
|
||||
this.internalShowDialog(dialog);
|
||||
return dialog.buttonSignals;
|
||||
}
|
||||
|
||||
// Returns method to be called when laoding finishd
|
||||
showLoadingDialog() {
|
||||
const dialog = new DialogLoading(this.app);
|
||||
this.internalShowDialog(dialog);
|
||||
return this.closeDialog.bind(this, dialog);
|
||||
}
|
||||
|
||||
internalShowDialog(dialog) {
|
||||
const elem = dialog.createElement();
|
||||
dialog.setIndex(this.dialogStack.length);
|
||||
|
||||
// Hide last dialog in queue
|
||||
if (this.dialogStack.length > 0) {
|
||||
this.dialogStack[this.dialogStack.length - 1].hide();
|
||||
}
|
||||
|
||||
this.dialogStack.push(dialog);
|
||||
|
||||
// Append dialog
|
||||
dialog.show();
|
||||
dialog.closeRequested.add(this.closeDialog.bind(this, dialog));
|
||||
|
||||
// Append to HTML
|
||||
this.dialogParent.appendChild(elem);
|
||||
|
||||
document.body.classList.toggle("modalDialogActive", this.dialogStack.length > 0);
|
||||
|
||||
// IMPORTANT: Attach element directly, otherwise double submit is possible
|
||||
this.update();
|
||||
}
|
||||
|
||||
update() {
|
||||
if (this.domWatcher) {
|
||||
this.domWatcher.update(this.dialogStack.length > 0);
|
||||
}
|
||||
}
|
||||
|
||||
closeDialog(dialog) {
|
||||
dialog.destroy();
|
||||
|
||||
let index = -1;
|
||||
for (let i = 0; i < this.dialogStack.length; ++i) {
|
||||
if (this.dialogStack[i] === dialog) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(index >= 0, "Dialog not in dialog stack");
|
||||
this.dialogStack.splice(index, 1);
|
||||
|
||||
if (this.dialogStack.length > 0) {
|
||||
// Show the dialog which was previously open
|
||||
this.dialogStack[this.dialogStack.length - 1].show();
|
||||
}
|
||||
|
||||
document.body.classList.toggle("modalDialogActive", this.dialogStack.length > 0);
|
||||
}
|
||||
|
||||
close() {
|
||||
for (let i = 0; i < this.dialogStack.length; ++i) {
|
||||
const dialog = this.dialogStack[i];
|
||||
dialog.destroy();
|
||||
}
|
||||
this.dialogStack = [];
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
super.cleanup();
|
||||
for (let i = 0; i < this.dialogStack.length; ++i) {
|
||||
this.dialogStack[i].destroy();
|
||||
}
|
||||
this.dialogStack = [];
|
||||
this.dialogParent = null;
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +54,10 @@ export class HUDSettingsMenu extends BaseHUDPart {
|
||||
}
|
||||
}
|
||||
|
||||
isBlockingOverlay() {
|
||||
return this.visible;
|
||||
}
|
||||
|
||||
returnToMenu() {
|
||||
this.root.gameState.goBackToMenu();
|
||||
}
|
||||
|
@ -1,251 +1,255 @@
|
||||
import { ClickDetector } from "../../../core/click_detector";
|
||||
import { InputReceiver } from "../../../core/input_receiver";
|
||||
import { formatBigNumber, makeDiv } from "../../../core/utils";
|
||||
import { T } from "../../../translations";
|
||||
import { KeyActionMapper, KEYMAPPINGS } from "../../key_action_mapper";
|
||||
import { UPGRADES } from "../../upgrades";
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||
|
||||
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"], T.ingame.shop.title);
|
||||
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 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"], T.shopUpgrades[upgradeId].name);
|
||||
|
||||
// Title > Tier
|
||||
handle.elemTierLabel = makeDiv(title, null, ["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 = T.ingame.shop.buttonUnlock;
|
||||
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 { tiers } = UPGRADES[upgradeId];
|
||||
|
||||
const currentTier = this.root.hubGoals.getUpgradeLevel(upgradeId);
|
||||
const currentTierMultiplier = this.root.hubGoals.upgradeImprovements[upgradeId];
|
||||
const tierHandle = tiers[currentTier];
|
||||
|
||||
// Set tier
|
||||
handle.elemTierLabel.innerText = T.ingame.shop.tier.replace(
|
||||
"<x>",
|
||||
"" + T.ingame.shop.tierLabels[currentTier]
|
||||
);
|
||||
|
||||
handle.elemTierLabel.setAttribute("data-tier", currentTier);
|
||||
|
||||
// Cleanup detectors
|
||||
for (let i = 0; i < handle.requireIndexToElement.length; ++i) {
|
||||
const requiredHandle = handle.requireIndexToElement[i];
|
||||
requiredHandle.container.remove();
|
||||
requiredHandle.pinDetector.cleanup();
|
||||
requiredHandle.infoDetector.cleanup();
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
handle.requireIndexToElement = [];
|
||||
|
||||
handle.elem.classList.toggle("maxLevel", !tierHandle);
|
||||
|
||||
if (!tierHandle) {
|
||||
// Max level
|
||||
handle.elemDescription.innerText = T.ingame.shop.maximumLevel.replace(
|
||||
"<currentMult>",
|
||||
currentTierMultiplier.toString()
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Set description
|
||||
handle.elemDescription.innerText = T.shopUpgrades[upgradeId].description
|
||||
.replace("<currentMult>", currentTierMultiplier.toString())
|
||||
.replace("<newMult>", (currentTierMultiplier + tierHandle.improvement).toString())
|
||||
// Backwards compatibility
|
||||
.replace("<gain>", (tierHandle.improvement * 100.0).toString());
|
||||
|
||||
tierHandle.required.forEach(({ shape, amount }) => {
|
||||
const container = makeDiv(handle.elemRequirements, null, ["requirement"]);
|
||||
|
||||
const shapeDef = this.root.shapeDefinitionMgr.getShapeFromShortKey(shape);
|
||||
const shapeCanvas = shapeDef.generateAsCanvas(120);
|
||||
shapeCanvas.classList.add();
|
||||
container.appendChild(shapeCanvas);
|
||||
|
||||
const progressContainer = makeDiv(container, null, ["amount"]);
|
||||
const progressBar = document.createElement("label");
|
||||
progressBar.classList.add("progressBar");
|
||||
progressContainer.appendChild(progressBar);
|
||||
|
||||
const progressLabel = document.createElement("label");
|
||||
progressContainer.appendChild(progressLabel);
|
||||
|
||||
const pinButton = document.createElement("button");
|
||||
pinButton.classList.add("pin");
|
||||
container.appendChild(pinButton);
|
||||
|
||||
const viewInfoButton = document.createElement("button");
|
||||
viewInfoButton.classList.add("showInfo");
|
||||
container.appendChild(viewInfoButton);
|
||||
|
||||
const currentGoalShape = this.root.hubGoals.currentGoal.definition.getHash();
|
||||
if (shape === currentGoalShape) {
|
||||
pinButton.classList.add("isGoal");
|
||||
} else if (this.root.hud.parts.pinnedShapes.isShapePinned(shape)) {
|
||||
pinButton.classList.add("alreadyPinned");
|
||||
}
|
||||
|
||||
const pinDetector = new ClickDetector(pinButton, {
|
||||
consumeEvents: true,
|
||||
preventDefault: true,
|
||||
});
|
||||
pinDetector.click.add(() => {
|
||||
if (this.root.hud.parts.pinnedShapes.isShapePinned(shape)) {
|
||||
this.root.hud.signals.shapeUnpinRequested.dispatch(shape);
|
||||
pinButton.classList.add("unpinned");
|
||||
pinButton.classList.remove("pinned", "alreadyPinned");
|
||||
} else {
|
||||
this.root.hud.signals.shapePinRequested.dispatch(shapeDef);
|
||||
pinButton.classList.add("pinned");
|
||||
pinButton.classList.remove("unpinned");
|
||||
}
|
||||
});
|
||||
|
||||
const infoDetector = new ClickDetector(viewInfoButton, {
|
||||
consumeEvents: true,
|
||||
preventDefault: true,
|
||||
});
|
||||
infoDetector.click.add(() =>
|
||||
this.root.hud.signals.viewShapeDetailsRequested.dispatch(shapeDef)
|
||||
);
|
||||
|
||||
handle.requireIndexToElement.push({
|
||||
container,
|
||||
progressLabel,
|
||||
progressBar,
|
||||
definition: shapeDef,
|
||||
required: amount,
|
||||
pinDetector,
|
||||
infoDetector,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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(KEYMAPPINGS.general.back).add(this.close, this);
|
||||
this.keyActionMapper.getBinding(KEYMAPPINGS.ingame.menuClose).add(this.close, this);
|
||||
this.keyActionMapper.getBinding(KEYMAPPINGS.ingame.menuOpenShop).add(this.close, this);
|
||||
|
||||
this.close();
|
||||
|
||||
this.rerenderFull();
|
||||
this.root.signals.upgradePurchased.add(this.rerenderFull, this);
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
document.body.classList.remove("ingameDialogOpen");
|
||||
|
||||
// Cleanup detectors
|
||||
for (const upgradeId in this.upgradeToElements) {
|
||||
const handle = this.upgradeToElements[upgradeId];
|
||||
for (let i = 0; i < handle.requireIndexToElement.length; ++i) {
|
||||
const requiredHandle = handle.requireIndexToElement[i];
|
||||
requiredHandle.container.remove();
|
||||
requiredHandle.pinDetector.cleanup();
|
||||
requiredHandle.infoDetector.cleanup();
|
||||
}
|
||||
handle.requireIndexToElement = [];
|
||||
}
|
||||
}
|
||||
|
||||
show() {
|
||||
this.visible = true;
|
||||
document.body.classList.add("ingameDialogOpen");
|
||||
// this.background.classList.add("visible");
|
||||
this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever);
|
||||
this.rerenderFull();
|
||||
}
|
||||
|
||||
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.tryUnlockUpgrade(upgradeId);
|
||||
}
|
||||
}
|
||||
import { ClickDetector } from "../../../core/click_detector";
|
||||
import { InputReceiver } from "../../../core/input_receiver";
|
||||
import { formatBigNumber, makeDiv } from "../../../core/utils";
|
||||
import { T } from "../../../translations";
|
||||
import { KeyActionMapper, KEYMAPPINGS } from "../../key_action_mapper";
|
||||
import { UPGRADES } from "../../upgrades";
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||
|
||||
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"], T.ingame.shop.title);
|
||||
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 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"], T.shopUpgrades[upgradeId].name);
|
||||
|
||||
// Title > Tier
|
||||
handle.elemTierLabel = makeDiv(title, null, ["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 = T.ingame.shop.buttonUnlock;
|
||||
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 { tiers } = UPGRADES[upgradeId];
|
||||
|
||||
const currentTier = this.root.hubGoals.getUpgradeLevel(upgradeId);
|
||||
const currentTierMultiplier = this.root.hubGoals.upgradeImprovements[upgradeId];
|
||||
const tierHandle = tiers[currentTier];
|
||||
|
||||
// Set tier
|
||||
handle.elemTierLabel.innerText = T.ingame.shop.tier.replace(
|
||||
"<x>",
|
||||
"" + T.ingame.shop.tierLabels[currentTier]
|
||||
);
|
||||
|
||||
handle.elemTierLabel.setAttribute("data-tier", currentTier);
|
||||
|
||||
// Cleanup detectors
|
||||
for (let i = 0; i < handle.requireIndexToElement.length; ++i) {
|
||||
const requiredHandle = handle.requireIndexToElement[i];
|
||||
requiredHandle.container.remove();
|
||||
requiredHandle.pinDetector.cleanup();
|
||||
requiredHandle.infoDetector.cleanup();
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
handle.requireIndexToElement = [];
|
||||
|
||||
handle.elem.classList.toggle("maxLevel", !tierHandle);
|
||||
|
||||
if (!tierHandle) {
|
||||
// Max level
|
||||
handle.elemDescription.innerText = T.ingame.shop.maximumLevel.replace(
|
||||
"<currentMult>",
|
||||
currentTierMultiplier.toString()
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Set description
|
||||
handle.elemDescription.innerText = T.shopUpgrades[upgradeId].description
|
||||
.replace("<currentMult>", currentTierMultiplier.toString())
|
||||
.replace("<newMult>", (currentTierMultiplier + tierHandle.improvement).toString())
|
||||
// Backwards compatibility
|
||||
.replace("<gain>", (tierHandle.improvement * 100.0).toString());
|
||||
|
||||
tierHandle.required.forEach(({ shape, amount }) => {
|
||||
const container = makeDiv(handle.elemRequirements, null, ["requirement"]);
|
||||
|
||||
const shapeDef = this.root.shapeDefinitionMgr.getShapeFromShortKey(shape);
|
||||
const shapeCanvas = shapeDef.generateAsCanvas(120);
|
||||
shapeCanvas.classList.add();
|
||||
container.appendChild(shapeCanvas);
|
||||
|
||||
const progressContainer = makeDiv(container, null, ["amount"]);
|
||||
const progressBar = document.createElement("label");
|
||||
progressBar.classList.add("progressBar");
|
||||
progressContainer.appendChild(progressBar);
|
||||
|
||||
const progressLabel = document.createElement("label");
|
||||
progressContainer.appendChild(progressLabel);
|
||||
|
||||
const pinButton = document.createElement("button");
|
||||
pinButton.classList.add("pin");
|
||||
container.appendChild(pinButton);
|
||||
|
||||
const viewInfoButton = document.createElement("button");
|
||||
viewInfoButton.classList.add("showInfo");
|
||||
container.appendChild(viewInfoButton);
|
||||
|
||||
const currentGoalShape = this.root.hubGoals.currentGoal.definition.getHash();
|
||||
if (shape === currentGoalShape) {
|
||||
pinButton.classList.add("isGoal");
|
||||
} else if (this.root.hud.parts.pinnedShapes.isShapePinned(shape)) {
|
||||
pinButton.classList.add("alreadyPinned");
|
||||
}
|
||||
|
||||
const pinDetector = new ClickDetector(pinButton, {
|
||||
consumeEvents: true,
|
||||
preventDefault: true,
|
||||
});
|
||||
pinDetector.click.add(() => {
|
||||
if (this.root.hud.parts.pinnedShapes.isShapePinned(shape)) {
|
||||
this.root.hud.signals.shapeUnpinRequested.dispatch(shape);
|
||||
pinButton.classList.add("unpinned");
|
||||
pinButton.classList.remove("pinned", "alreadyPinned");
|
||||
} else {
|
||||
this.root.hud.signals.shapePinRequested.dispatch(shapeDef);
|
||||
pinButton.classList.add("pinned");
|
||||
pinButton.classList.remove("unpinned");
|
||||
}
|
||||
});
|
||||
|
||||
const infoDetector = new ClickDetector(viewInfoButton, {
|
||||
consumeEvents: true,
|
||||
preventDefault: true,
|
||||
});
|
||||
infoDetector.click.add(() =>
|
||||
this.root.hud.signals.viewShapeDetailsRequested.dispatch(shapeDef)
|
||||
);
|
||||
|
||||
handle.requireIndexToElement.push({
|
||||
container,
|
||||
progressLabel,
|
||||
progressBar,
|
||||
definition: shapeDef,
|
||||
required: amount,
|
||||
pinDetector,
|
||||
infoDetector,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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(KEYMAPPINGS.general.back).add(this.close, this);
|
||||
this.keyActionMapper.getBinding(KEYMAPPINGS.ingame.menuClose).add(this.close, this);
|
||||
this.keyActionMapper.getBinding(KEYMAPPINGS.ingame.menuOpenShop).add(this.close, this);
|
||||
|
||||
this.close();
|
||||
|
||||
this.rerenderFull();
|
||||
this.root.signals.upgradePurchased.add(this.rerenderFull, this);
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
document.body.classList.remove("ingameDialogOpen");
|
||||
|
||||
// Cleanup detectors
|
||||
for (const upgradeId in this.upgradeToElements) {
|
||||
const handle = this.upgradeToElements[upgradeId];
|
||||
for (let i = 0; i < handle.requireIndexToElement.length; ++i) {
|
||||
const requiredHandle = handle.requireIndexToElement[i];
|
||||
requiredHandle.container.remove();
|
||||
requiredHandle.pinDetector.cleanup();
|
||||
requiredHandle.infoDetector.cleanup();
|
||||
}
|
||||
handle.requireIndexToElement = [];
|
||||
}
|
||||
}
|
||||
|
||||
show() {
|
||||
this.visible = true;
|
||||
document.body.classList.add("ingameDialogOpen");
|
||||
// this.background.classList.add("visible");
|
||||
this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever);
|
||||
this.rerenderFull();
|
||||
}
|
||||
|
||||
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.tryUnlockUpgrade(upgradeId);
|
||||
}
|
||||
|
||||
isBlockingOverlay() {
|
||||
return this.visible;
|
||||
}
|
||||
}
|
||||
|
@ -155,6 +155,10 @@ export class HUDStatistics extends BaseHUDPart {
|
||||
document.body.classList.remove("ingameDialogOpen");
|
||||
}
|
||||
|
||||
isBlockingOverlay() {
|
||||
return this.visible;
|
||||
}
|
||||
|
||||
show() {
|
||||
this.visible = true;
|
||||
document.body.classList.add("ingameDialogOpen");
|
||||
|
@ -1,156 +1,160 @@
|
||||
import { globalConfig } from "../../../core/config";
|
||||
import { gMetaBuildingRegistry } from "../../../core/global_registries";
|
||||
import { makeDiv } from "../../../core/utils";
|
||||
import { SOUNDS } from "../../../platform/sound";
|
||||
import { T } from "../../../translations";
|
||||
import { defaultBuildingVariant } from "../../meta_building";
|
||||
import { enumHubGoalRewards } from "../../tutorial_goals";
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||
import { enumHubGoalRewardsToContentUnlocked } from "../../tutorial_goals_mappings";
|
||||
import { InputReceiver } from "../../../core/input_receiver";
|
||||
|
||||
export class HUDUnlockNotification extends BaseHUDPart {
|
||||
initialize() {
|
||||
this.visible = false;
|
||||
|
||||
this.domAttach = new DynamicDomAttach(this.root, this.element, {
|
||||
timeToKeepSeconds: 0,
|
||||
});
|
||||
|
||||
if (!(G_IS_DEV && globalConfig.debug.disableUnlockDialog)) {
|
||||
this.root.signals.storyGoalCompleted.add(this.showForLevel, this);
|
||||
}
|
||||
|
||||
this.buttonShowTimeout = null;
|
||||
}
|
||||
|
||||
createElements(parent) {
|
||||
this.inputReciever = new InputReceiver("unlock-notification");
|
||||
|
||||
this.element = makeDiv(parent, "ingame_HUD_UnlockNotification", ["noBlur"]);
|
||||
|
||||
const dialog = makeDiv(this.element, null, ["dialog"]);
|
||||
|
||||
this.elemTitle = makeDiv(dialog, null, ["title"]);
|
||||
this.elemSubTitle = makeDiv(dialog, null, ["subTitle"], T.ingame.levelCompleteNotification.completed);
|
||||
|
||||
this.elemContents = makeDiv(dialog, null, ["contents"]);
|
||||
|
||||
this.btnClose = document.createElement("button");
|
||||
this.btnClose.classList.add("close", "styledButton");
|
||||
this.btnClose.innerText = T.ingame.levelCompleteNotification.buttonNextLevel;
|
||||
dialog.appendChild(this.btnClose);
|
||||
|
||||
this.trackClicks(this.btnClose, this.requestClose);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} level
|
||||
* @param {enumHubGoalRewards} reward
|
||||
*/
|
||||
showForLevel(level, reward) {
|
||||
this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever);
|
||||
this.elemTitle.innerText = T.ingame.levelCompleteNotification.levelTitle.replace(
|
||||
"<level>",
|
||||
("" + level).padStart(2, "0")
|
||||
);
|
||||
|
||||
const rewardName = T.storyRewards[reward].title;
|
||||
|
||||
let html = `
|
||||
<div class="rewardName">
|
||||
${T.ingame.levelCompleteNotification.unlockText.replace("<reward>", rewardName)}
|
||||
</div>
|
||||
|
||||
<div class="rewardDesc">
|
||||
${T.storyRewards[reward].desc}
|
||||
</div>
|
||||
|
||||
`;
|
||||
|
||||
html += "<div class='images'>";
|
||||
const gained = enumHubGoalRewardsToContentUnlocked[reward];
|
||||
if (gained) {
|
||||
gained.forEach(([metaBuildingClass, variant]) => {
|
||||
const metaBuilding = gMetaBuildingRegistry.findByClass(metaBuildingClass);
|
||||
html += `<div class="buildingExplanation" data-icon="building_tutorials/${
|
||||
metaBuilding.getId() + (variant === defaultBuildingVariant ? "" : "-" + variant)
|
||||
}.png"></div>`;
|
||||
});
|
||||
}
|
||||
html += "</div>";
|
||||
|
||||
this.elemContents.innerHTML = html;
|
||||
this.visible = true;
|
||||
this.root.soundProxy.playUi(SOUNDS.levelComplete);
|
||||
|
||||
if (this.buttonShowTimeout) {
|
||||
clearTimeout(this.buttonShowTimeout);
|
||||
}
|
||||
|
||||
this.element.querySelector("button.close").classList.remove("unlocked");
|
||||
|
||||
if (this.root.app.settings.getAllSettings().offerHints) {
|
||||
this.buttonShowTimeout = setTimeout(
|
||||
() => this.element.querySelector("button.close").classList.add("unlocked"),
|
||||
G_IS_DEV ? 100 : 5000
|
||||
);
|
||||
} else {
|
||||
this.element.querySelector("button.close").classList.add("unlocked");
|
||||
}
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
this.root.app.inputMgr.makeSureDetached(this.inputReciever);
|
||||
if (this.buttonShowTimeout) {
|
||||
clearTimeout(this.buttonShowTimeout);
|
||||
this.buttonShowTimeout = null;
|
||||
}
|
||||
}
|
||||
|
||||
requestClose() {
|
||||
this.root.app.adProvider.showVideoAd().then(() => {
|
||||
this.close();
|
||||
|
||||
if (!this.root.app.settings.getAllSettings().offerHints) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.root.hubGoals.level === 3) {
|
||||
const { showUpgrades } = this.root.hud.parts.dialogs.showInfo(
|
||||
T.dialogs.upgradesIntroduction.title,
|
||||
T.dialogs.upgradesIntroduction.desc,
|
||||
["showUpgrades:good:timeout"]
|
||||
);
|
||||
showUpgrades.add(() => this.root.hud.parts.shop.show());
|
||||
}
|
||||
|
||||
if (this.root.hubGoals.level === 5) {
|
||||
const { showKeybindings } = this.root.hud.parts.dialogs.showInfo(
|
||||
T.dialogs.keybindingsIntroduction.title,
|
||||
T.dialogs.keybindingsIntroduction.desc,
|
||||
["showKeybindings:misc", "ok:good:timeout"]
|
||||
);
|
||||
showKeybindings.add(() => this.root.gameState.goToKeybindings());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
close() {
|
||||
this.root.app.inputMgr.makeSureDetached(this.inputReciever);
|
||||
if (this.buttonShowTimeout) {
|
||||
clearTimeout(this.buttonShowTimeout);
|
||||
this.buttonShowTimeout = null;
|
||||
}
|
||||
this.visible = false;
|
||||
}
|
||||
|
||||
update() {
|
||||
this.domAttach.update(this.visible);
|
||||
if (!this.visible && this.buttonShowTimeout) {
|
||||
clearTimeout(this.buttonShowTimeout);
|
||||
this.buttonShowTimeout = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
import { globalConfig } from "../../../core/config";
|
||||
import { gMetaBuildingRegistry } from "../../../core/global_registries";
|
||||
import { makeDiv } from "../../../core/utils";
|
||||
import { SOUNDS } from "../../../platform/sound";
|
||||
import { T } from "../../../translations";
|
||||
import { defaultBuildingVariant } from "../../meta_building";
|
||||
import { enumHubGoalRewards } from "../../tutorial_goals";
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||
import { enumHubGoalRewardsToContentUnlocked } from "../../tutorial_goals_mappings";
|
||||
import { InputReceiver } from "../../../core/input_receiver";
|
||||
|
||||
export class HUDUnlockNotification extends BaseHUDPart {
|
||||
initialize() {
|
||||
this.visible = false;
|
||||
|
||||
this.domAttach = new DynamicDomAttach(this.root, this.element, {
|
||||
timeToKeepSeconds: 0,
|
||||
});
|
||||
|
||||
if (!(G_IS_DEV && globalConfig.debug.disableUnlockDialog)) {
|
||||
this.root.signals.storyGoalCompleted.add(this.showForLevel, this);
|
||||
}
|
||||
|
||||
this.buttonShowTimeout = null;
|
||||
}
|
||||
|
||||
createElements(parent) {
|
||||
this.inputReciever = new InputReceiver("unlock-notification");
|
||||
|
||||
this.element = makeDiv(parent, "ingame_HUD_UnlockNotification", ["noBlur"]);
|
||||
|
||||
const dialog = makeDiv(this.element, null, ["dialog"]);
|
||||
|
||||
this.elemTitle = makeDiv(dialog, null, ["title"]);
|
||||
this.elemSubTitle = makeDiv(dialog, null, ["subTitle"], T.ingame.levelCompleteNotification.completed);
|
||||
|
||||
this.elemContents = makeDiv(dialog, null, ["contents"]);
|
||||
|
||||
this.btnClose = document.createElement("button");
|
||||
this.btnClose.classList.add("close", "styledButton");
|
||||
this.btnClose.innerText = T.ingame.levelCompleteNotification.buttonNextLevel;
|
||||
dialog.appendChild(this.btnClose);
|
||||
|
||||
this.trackClicks(this.btnClose, this.requestClose);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} level
|
||||
* @param {enumHubGoalRewards} reward
|
||||
*/
|
||||
showForLevel(level, reward) {
|
||||
this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever);
|
||||
this.elemTitle.innerText = T.ingame.levelCompleteNotification.levelTitle.replace(
|
||||
"<level>",
|
||||
("" + level).padStart(2, "0")
|
||||
);
|
||||
|
||||
const rewardName = T.storyRewards[reward].title;
|
||||
|
||||
let html = `
|
||||
<div class="rewardName">
|
||||
${T.ingame.levelCompleteNotification.unlockText.replace("<reward>", rewardName)}
|
||||
</div>
|
||||
|
||||
<div class="rewardDesc">
|
||||
${T.storyRewards[reward].desc}
|
||||
</div>
|
||||
|
||||
`;
|
||||
|
||||
html += "<div class='images'>";
|
||||
const gained = enumHubGoalRewardsToContentUnlocked[reward];
|
||||
if (gained) {
|
||||
gained.forEach(([metaBuildingClass, variant]) => {
|
||||
const metaBuilding = gMetaBuildingRegistry.findByClass(metaBuildingClass);
|
||||
html += `<div class="buildingExplanation" data-icon="building_tutorials/${
|
||||
metaBuilding.getId() + (variant === defaultBuildingVariant ? "" : "-" + variant)
|
||||
}.png"></div>`;
|
||||
});
|
||||
}
|
||||
html += "</div>";
|
||||
|
||||
this.elemContents.innerHTML = html;
|
||||
this.visible = true;
|
||||
this.root.soundProxy.playUi(SOUNDS.levelComplete);
|
||||
|
||||
if (this.buttonShowTimeout) {
|
||||
clearTimeout(this.buttonShowTimeout);
|
||||
}
|
||||
|
||||
this.element.querySelector("button.close").classList.remove("unlocked");
|
||||
|
||||
if (this.root.app.settings.getAllSettings().offerHints) {
|
||||
this.buttonShowTimeout = setTimeout(
|
||||
() => this.element.querySelector("button.close").classList.add("unlocked"),
|
||||
G_IS_DEV ? 100 : 5000
|
||||
);
|
||||
} else {
|
||||
this.element.querySelector("button.close").classList.add("unlocked");
|
||||
}
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
this.root.app.inputMgr.makeSureDetached(this.inputReciever);
|
||||
if (this.buttonShowTimeout) {
|
||||
clearTimeout(this.buttonShowTimeout);
|
||||
this.buttonShowTimeout = null;
|
||||
}
|
||||
}
|
||||
|
||||
isBlockingOverlay() {
|
||||
return this.visible;
|
||||
}
|
||||
|
||||
requestClose() {
|
||||
this.root.app.adProvider.showVideoAd().then(() => {
|
||||
this.close();
|
||||
|
||||
if (!this.root.app.settings.getAllSettings().offerHints) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.root.hubGoals.level === 3) {
|
||||
const { showUpgrades } = this.root.hud.parts.dialogs.showInfo(
|
||||
T.dialogs.upgradesIntroduction.title,
|
||||
T.dialogs.upgradesIntroduction.desc,
|
||||
["showUpgrades:good:timeout"]
|
||||
);
|
||||
showUpgrades.add(() => this.root.hud.parts.shop.show());
|
||||
}
|
||||
|
||||
if (this.root.hubGoals.level === 5) {
|
||||
const { showKeybindings } = this.root.hud.parts.dialogs.showInfo(
|
||||
T.dialogs.keybindingsIntroduction.title,
|
||||
T.dialogs.keybindingsIntroduction.desc,
|
||||
["showKeybindings:misc", "ok:good:timeout"]
|
||||
);
|
||||
showKeybindings.add(() => this.root.gameState.goToKeybindings());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
close() {
|
||||
this.root.app.inputMgr.makeSureDetached(this.inputReciever);
|
||||
if (this.buttonShowTimeout) {
|
||||
clearTimeout(this.buttonShowTimeout);
|
||||
this.buttonShowTimeout = null;
|
||||
}
|
||||
this.visible = false;
|
||||
}
|
||||
|
||||
update() {
|
||||
this.domAttach.update(this.visible);
|
||||
if (!this.visible && this.buttonShowTimeout) {
|
||||
clearTimeout(this.buttonShowTimeout);
|
||||
this.buttonShowTimeout = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user