diff --git a/src/js/game/hud/hud.js b/src/js/game/hud/hud.js index a9edffd0..5f1bd226 100644 --- a/src/js/game/hud/hud.js +++ b/src/js/game/hud/hud.js @@ -47,6 +47,7 @@ import { HUDMinerHighlight } from "./parts/miner_highlight"; import { HUDBetaOverlay } from "./parts/beta_overlay"; import { HUDStandaloneAdvantages } from "./parts/standalone_advantages"; import { HUDCatMemes } from "./parts/cat_memes"; +import { HUDTutorialVideoOffer } from "./parts/tutorial_video_offer"; export class GameHUD { /** @@ -60,6 +61,18 @@ export class GameHUD { * Initializes the hud parts */ initialize() { + this.signals = { + buildingSelectedForPlacement: /** @type {TypedSignal<[MetaBuilding|null]>} */ (new Signal()), + selectedPlacementBuildingChanged: /** @type {TypedSignal<[MetaBuilding|null]>} */ (new Signal()), + shapePinRequested: /** @type {TypedSignal<[ShapeDefinition]>} */ (new Signal()), + shapeUnpinRequested: /** @type {TypedSignal<[string]>} */ (new Signal()), + notification: /** @type {TypedSignal<[string, enumNotificationType]>} */ (new Signal()), + buildingsSelectedForCopy: /** @type {TypedSignal<[Array]>} */ (new Signal()), + pasteBlueprintRequested: /** @type {TypedSignal<[]>} */ (new Signal()), + viewShapeDetailsRequested: /** @type {TypedSignal<[ShapeDefinition]>} */ (new Signal()), + unlockNotificationFinished: /** @type {TypedSignal<[]>} */ (new Signal()), + }; + this.parts = { buildingsToolbar: new HUDBuildingsToolbar(this.root), wiresToolbar: new HUDWiresToolbar(this.root), @@ -87,6 +100,7 @@ export class GameHUD { layerPreview: new HUDLayerPreview(this.root), minerHighlight: new HUDMinerHighlight(this.root), + tutorialVideoOffer: new HUDTutorialVideoOffer(this.root), // Typing hints /* typehints:start */ @@ -95,17 +109,6 @@ export class GameHUD { /* typehints:end */ }; - this.signals = { - buildingSelectedForPlacement: /** @type {TypedSignal<[MetaBuilding|null]>} */ (new Signal()), - selectedPlacementBuildingChanged: /** @type {TypedSignal<[MetaBuilding|null]>} */ (new Signal()), - shapePinRequested: /** @type {TypedSignal<[ShapeDefinition]>} */ (new Signal()), - shapeUnpinRequested: /** @type {TypedSignal<[string]>} */ (new Signal()), - notification: /** @type {TypedSignal<[string, enumNotificationType]>} */ (new Signal()), - buildingsSelectedForCopy: /** @type {TypedSignal<[Array]>} */ (new Signal()), - pasteBlueprintRequested: /** @type {TypedSignal<[]>} */ (new Signal()), - viewShapeDetailsRequested: /** @type {TypedSignal<[ShapeDefinition]>} */ (new Signal()), - }; - if (!IS_MOBILE) { this.parts.keybindingOverlay = new HUDKeybindingOverlay(this.root); } diff --git a/src/js/game/hud/parts/tutorial_video_offer.js b/src/js/game/hud/parts/tutorial_video_offer.js new file mode 100644 index 00000000..3cd2cb90 --- /dev/null +++ b/src/js/game/hud/parts/tutorial_video_offer.js @@ -0,0 +1,34 @@ +import { THIRDPARTY_URLS } from "../../../core/config"; +import { T } from "../../../translations"; +import { BaseHUDPart } from "../base_hud_part"; + +/** + * Offers to open the tutorial video after completing a level + */ +export class HUDTutorialVideoOffer extends BaseHUDPart { + createElements() {} + + initialize() { + this.root.hud.signals.unlockNotificationFinished.add(() => { + const level = this.root.hubGoals.level; + const tutorialVideoLink = THIRDPARTY_URLS.levelTutorialVideos[level]; + if (tutorialVideoLink) { + const isForeign = this.root.app.settings.getLanguage() !== "en"; + const dialogData = isForeign + ? T.dialogs.tutorialVideoAvailableForeignLanguage + : T.dialogs.tutorialVideoAvailable; + + const { ok } = this.root.hud.parts.dialogs.showInfo(dialogData.title, dialogData.desc, [ + "cancel:bad", + "ok:good", + ]); + + this.root.app.analytics.trackUiClick("ingame_video_link_show_" + level); + ok.add(() => { + this.root.app.platformWrapper.openExternalLink(tutorialVideoLink); + this.root.app.analytics.trackUiClick("ingame_video_link_open_" + level); + }); + } + }); + } +} diff --git a/src/js/game/hud/parts/unlock_notification.js b/src/js/game/hud/parts/unlock_notification.js index 5fa0e3e2..98549784 100644 --- a/src/js/game/hud/parts/unlock_notification.js +++ b/src/js/game/hud/parts/unlock_notification.js @@ -129,6 +129,8 @@ export class HUDUnlockNotification extends BaseHUDPart { this.root.app.adProvider.showVideoAd().then(() => { this.close(); + this.root.hud.signals.unlockNotificationFinished.dispatch(); + if (!this.root.app.settings.getAllSettings().offerHints) { return; } diff --git a/translations/base-en.yaml b/translations/base-en.yaml index 45cace79..7459e3f5 100644 --- a/translations/base-en.yaml +++ b/translations/base-en.yaml @@ -28,7 +28,7 @@ steamPage: discordLinkShort: Official Discord intro: >- - You like automation games? Then you are in the right place! + Do you like automation games? Then you are in the right place! shapez.io is a relaxed game in which you have to build factories for the automated production of geometric shapes. As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map. @@ -272,6 +272,14 @@ dialogs: title: Rename Savegame desc: You can rename your savegame here. + tutorialVideoAvailable: + title: Tutorial Available + desc: There is a tutorial video available for this level! Would you like to watch it? + + tutorialVideoAvailableForeignLanguage: + title: Tutorial Available + desc: There is a tutorial video available for this level, but it is only available in English. Would you like to watch it? + ingame: # This is shown in the top left corner and displays useful keybindings in # every situation