Improve unlock notification
Before Width: | Height: | Size: 3.1 MiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 76 KiB |
BIN
artwork/logo.png
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 26 KiB |
BIN
artwork/logo.psd
BIN
res/logo.png
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 26 KiB |
|
@ -9,6 +9,7 @@
|
|||
justify-content: center;
|
||||
align-items: center;
|
||||
pointer-events: all;
|
||||
|
||||
@include InlineAnimation(0.1s ease-in-out) {
|
||||
0% {
|
||||
opacity: 0;
|
||||
|
@ -16,7 +17,7 @@
|
|||
}
|
||||
|
||||
.dialog {
|
||||
background: rgba(#222428, 0.5);
|
||||
// background: rgba(#222428, 0.5);
|
||||
@include S(border-radius, $globalBorderRadius);
|
||||
@include S(padding, 30px);
|
||||
|
||||
|
@ -32,7 +33,7 @@
|
|||
.subTitle {
|
||||
@include SuperHeading;
|
||||
text-transform: uppercase;
|
||||
@include S(font-size, 50px);
|
||||
@include S(font-size, 40px);
|
||||
|
||||
@include InlineAnimation(0.5s ease-in-out) {
|
||||
0% {
|
||||
|
@ -48,11 +49,10 @@
|
|||
}
|
||||
|
||||
.subTitle {
|
||||
@include Heading;
|
||||
background: $colorGreenBright;
|
||||
@include PlainText;
|
||||
display: inline-block;
|
||||
@include S(padding, 1px, 6px);
|
||||
@include S(margin, 20px, 0, 20px);
|
||||
@include S(margin, 0px, 0, 20px);
|
||||
color: $colorGreenBright;
|
||||
|
||||
@include S(border-radius, $globalBorderRadius);
|
||||
@include InlineAnimation(0.5s ease-in-out) {
|
||||
|
@ -82,14 +82,15 @@
|
|||
transform: translateX(-2vw);
|
||||
}
|
||||
}
|
||||
display: grid;
|
||||
grid-template-columns: auto auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@include S(grid-gap, 10px);
|
||||
|
||||
.reward {
|
||||
.rewardName {
|
||||
grid-column: 1 / 3;
|
||||
display: none;
|
||||
@include InlineAnimation(0.5s ease-in-out) {
|
||||
0% {
|
||||
transform: translateX(200vw);
|
||||
|
@ -104,29 +105,63 @@
|
|||
}
|
||||
}
|
||||
|
||||
.buildingExplanation {
|
||||
@include S(width, 200px);
|
||||
@include S(height, 200px);
|
||||
display: inline-block;
|
||||
background-position: center center;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
@include S(border-radius, $globalBorderRadius);
|
||||
box-shadow: #{D(2px)} #{D(3px)} 0 0 rgba(0, 0, 0, 0.15);
|
||||
.rewardDesc {
|
||||
grid-column: 1 / 3;
|
||||
@include PlainText;
|
||||
@include S(margin-bottom, 15px);
|
||||
color: #aaacaf;
|
||||
@include S(width, 400px);
|
||||
text-align: left;
|
||||
strong {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.images {
|
||||
display: flex;
|
||||
.buildingExplanation {
|
||||
@include S(width, 200px);
|
||||
@include S(height, 200px);
|
||||
display: inline-block;
|
||||
background-position: center center;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
@include S(border-radius, $globalBorderRadius);
|
||||
box-shadow: #{D(2px)} #{D(3px)} 0 0 rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button.close {
|
||||
border: 0;
|
||||
@include InlineAnimation(2s ease-in-out) {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
95% {
|
||||
opacity: 0;
|
||||
position: relative;
|
||||
@include S(margin-top, 30px);
|
||||
|
||||
&:not(.unlocked) {
|
||||
pointer-events: none;
|
||||
opacity: 0.8;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: " ";
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 100%;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 10, 20, 0.8);
|
||||
|
||||
@include InlineAnimation(10s linear) {
|
||||
0% {
|
||||
left: 0;
|
||||
}
|
||||
100% {
|
||||
left: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
@include S(margin-top, 30px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,18 +2,11 @@ import { globalConfig } from "../../../core/config";
|
|||
import { gMetaBuildingRegistry } from "../../../core/global_registries";
|
||||
import { makeDiv } from "../../../core/utils";
|
||||
import { SOUNDS } from "../../../platform/sound";
|
||||
import { MetaCutterBuilding } from "../../buildings/cutter";
|
||||
import { MetaMixerBuilding } from "../../buildings/mixer";
|
||||
import { MetaPainterBuilding } from "../../buildings/painter";
|
||||
import { MetaRotaterBuilding } from "../../buildings/rotater";
|
||||
import { MetaSplitterBuilding } from "../../buildings/splitter";
|
||||
import { MetaStackerBuilding } from "../../buildings/stacker";
|
||||
import { MetaTrashBuilding } from "../../buildings/trash";
|
||||
import { MetaUndergroundBeltBuilding } from "../../buildings/underground_belt";
|
||||
import { enumHubGoalRewards } from "../../tutorial_goals";
|
||||
import { T } from "../../../translations";
|
||||
import { defaultBuildingVariant } from "../../meta_building";
|
||||
import { enumHubGoalRewards, enumHubGoalRewardsToContentUnlocked } from "../../tutorial_goals";
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||
import { T } from "../../../translations";
|
||||
|
||||
export class HUDUnlockNotification extends BaseHUDPart {
|
||||
initialize() {
|
||||
|
@ -26,6 +19,8 @@ export class HUDUnlockNotification extends BaseHUDPart {
|
|||
if (!(G_IS_DEV && globalConfig.debug.disableUnlockDialog)) {
|
||||
this.root.signals.storyGoalCompleted.add(this.showForLevel, this);
|
||||
}
|
||||
|
||||
this.buttonShowTimeout = null;
|
||||
}
|
||||
|
||||
shouldPauseGame() {
|
||||
|
@ -60,63 +55,50 @@ export class HUDUnlockNotification extends BaseHUDPart {
|
|||
("" + level).padStart(2, "0")
|
||||
);
|
||||
|
||||
const rewardText = T.storyRewards[reward];
|
||||
const rewardName = T.storyRewards[reward].title;
|
||||
|
||||
let html =
|
||||
"<span class='reward'>" +
|
||||
T.ingame.levelCompleteNotification.unlockText.replace("<reward>", rewardText) +
|
||||
"</span>";
|
||||
let html = `
|
||||
<div class="rewardName">
|
||||
${T.ingame.levelCompleteNotification.unlockText.replace("<reward>", rewardName)}
|
||||
</div>
|
||||
|
||||
const addBuildingExplanation = metaBuildingClass => {
|
||||
const metaBuilding = gMetaBuildingRegistry.findByClass(metaBuildingClass);
|
||||
html += `<div class="buildingExplanation" data-icon="building_tutorials/${metaBuilding.getId()}.png"></div>`;
|
||||
};
|
||||
<div class="rewardDesc">
|
||||
${T.storyRewards[reward].desc}
|
||||
</div>
|
||||
|
||||
switch (reward) {
|
||||
case enumHubGoalRewards.reward_cutter_and_trash: {
|
||||
addBuildingExplanation(MetaCutterBuilding);
|
||||
addBuildingExplanation(MetaTrashBuilding);
|
||||
break;
|
||||
}
|
||||
case enumHubGoalRewards.reward_mixer: {
|
||||
addBuildingExplanation(MetaMixerBuilding);
|
||||
break;
|
||||
}
|
||||
`;
|
||||
|
||||
case enumHubGoalRewards.reward_painter: {
|
||||
addBuildingExplanation(MetaPainterBuilding);
|
||||
break;
|
||||
}
|
||||
|
||||
case enumHubGoalRewards.reward_rotater: {
|
||||
addBuildingExplanation(MetaRotaterBuilding);
|
||||
break;
|
||||
}
|
||||
|
||||
case enumHubGoalRewards.reward_splitter: {
|
||||
addBuildingExplanation(MetaSplitterBuilding);
|
||||
break;
|
||||
}
|
||||
|
||||
case enumHubGoalRewards.reward_stacker: {
|
||||
addBuildingExplanation(MetaStackerBuilding);
|
||||
break;
|
||||
}
|
||||
|
||||
case enumHubGoalRewards.reward_tunnel: {
|
||||
addBuildingExplanation(MetaUndergroundBeltBuilding);
|
||||
break;
|
||||
}
|
||||
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>`;
|
||||
});
|
||||
}
|
||||
|
||||
// addBuildingExplanation(MetaSplitterBuilding);
|
||||
// addBuildingExplanation(MetaCutterBuilding);
|
||||
html += "</div>";
|
||||
|
||||
this.elemContents.innerHTML = html;
|
||||
|
||||
this.visible = true;
|
||||
|
||||
this.root.soundProxy.playUi(SOUNDS.levelComplete);
|
||||
|
||||
if (this.buttonShowTimeout) {
|
||||
clearTimeout(this.buttonShowTimeout);
|
||||
}
|
||||
|
||||
this.buttonShowTimeout = setTimeout(
|
||||
() => this.element.querySelector("button.close").classList.add("unlocked"),
|
||||
G_IS_DEV ? 1000 : 10000
|
||||
);
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
if (this.buttonShowTimeout) {
|
||||
clearTimeout(this.buttonShowTimeout);
|
||||
this.buttonShowTimeout = null;
|
||||
}
|
||||
}
|
||||
|
||||
requestClose() {
|
||||
|
@ -126,10 +108,18 @@ export class HUDUnlockNotification extends BaseHUDPart {
|
|||
}
|
||||
|
||||
close() {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ export class HubSystem extends GameSystemWithFilter {
|
|||
context.font = "bold 11px GameFont";
|
||||
context.fillStyle = "#fd0752";
|
||||
context.textAlign = "center";
|
||||
context.fillText(T.storyRewards[goals.reward].toUpperCase(), pos.x, pos.y + 46);
|
||||
context.fillText(T.storyRewards[goals.reward].title.toUpperCase(), pos.x, pos.y + 46);
|
||||
|
||||
// Level
|
||||
context.font = "bold 11px GameFont";
|
||||
|
|
|
@ -1,7 +1,18 @@
|
|||
import { ShapeDefinition } from "./shape_definition";
|
||||
import { finalGameShape } from "./upgrades";
|
||||
import { MetaBuilding, defaultBuildingVariant } from "./meta_building";
|
||||
import { MetaCutterBuilding, enumCutterVariants } from "./buildings/cutter";
|
||||
import { MetaRotaterBuilding, enumRotaterVariants } from "./buildings/rotater";
|
||||
import { MetaPainterBuilding, enumPainterVariants } from "./buildings/painter";
|
||||
import { MetaMixerBuilding } from "./buildings/mixer";
|
||||
import { MetaStackerBuilding } from "./buildings/stacker";
|
||||
import { MetaSplitterBuilding, enumSplitterVariants } from "./buildings/splitter";
|
||||
import { MetaUndergroundBeltBuilding, enumUndergroundBeltVariants } from "./buildings/underground_belt";
|
||||
import { MetaMinerBuilding, enumMinerVariants } from "./buildings/miner";
|
||||
import { MetaTrashBuilding, enumTrashVariants } from "./buildings/trash";
|
||||
|
||||
/**
|
||||
* Don't forget to also update unlock_notification.js as well as the translations!
|
||||
* @enum {string}
|
||||
*/
|
||||
export const enumHubGoalRewards = {
|
||||
|
@ -27,6 +38,44 @@ export const enumHubGoalRewards = {
|
|||
no_reward: "no_reward",
|
||||
};
|
||||
|
||||
/** @typedef {Array<[typeof MetaBuilding, string]>} TutorialGoalReward */
|
||||
|
||||
/**
|
||||
* Helper method for proper types
|
||||
* @returns {TutorialGoalReward}
|
||||
*/
|
||||
const typed = x => x;
|
||||
|
||||
/**
|
||||
* Stores which reward unlocks what
|
||||
* @enum {TutorialGoalReward?}
|
||||
*/
|
||||
export const enumHubGoalRewardsToContentUnlocked = {
|
||||
[enumHubGoalRewards.reward_cutter_and_trash]: typed([[MetaCutterBuilding, defaultBuildingVariant]]),
|
||||
[enumHubGoalRewards.reward_rotater]: typed([[MetaRotaterBuilding, defaultBuildingVariant]]),
|
||||
[enumHubGoalRewards.reward_painter]: typed([[MetaPainterBuilding, defaultBuildingVariant]]),
|
||||
[enumHubGoalRewards.reward_mixer]: typed([[MetaMixerBuilding, defaultBuildingVariant]]),
|
||||
[enumHubGoalRewards.reward_stacker]: typed([[MetaStackerBuilding, defaultBuildingVariant]]),
|
||||
[enumHubGoalRewards.reward_splitter]: typed([[MetaSplitterBuilding, defaultBuildingVariant]]),
|
||||
[enumHubGoalRewards.reward_tunnel]: typed([[MetaUndergroundBeltBuilding, defaultBuildingVariant]]),
|
||||
|
||||
[enumHubGoalRewards.reward_rotater_ccw]: typed([[MetaRotaterBuilding, enumRotaterVariants.ccw]]),
|
||||
[enumHubGoalRewards.reward_miner_chainable]: typed([[MetaMinerBuilding, enumMinerVariants.chainable]]),
|
||||
[enumHubGoalRewards.reward_underground_belt_tier_2]: typed([
|
||||
[MetaUndergroundBeltBuilding, enumUndergroundBeltVariants.tier2],
|
||||
]),
|
||||
[enumHubGoalRewards.reward_splitter_compact]: typed([
|
||||
[MetaSplitterBuilding, enumSplitterVariants.compact],
|
||||
]),
|
||||
[enumHubGoalRewards.reward_cutter_quad]: typed([[MetaCutterBuilding, enumCutterVariants.quad]]),
|
||||
[enumHubGoalRewards.reward_painter_double]: typed([[MetaPainterBuilding, enumPainterVariants.double]]),
|
||||
[enumHubGoalRewards.reward_painter_quad]: typed([[MetaPainterBuilding, enumPainterVariants.quad]]),
|
||||
[enumHubGoalRewards.reward_storage]: typed([[MetaTrashBuilding, enumTrashVariants.storage]]),
|
||||
|
||||
[enumHubGoalRewards.reward_freeplay]: null,
|
||||
[enumHubGoalRewards.no_reward]: null,
|
||||
};
|
||||
|
||||
export const tutorialGoals = [
|
||||
// Circle
|
||||
{
|
||||
|
|
|
@ -352,27 +352,77 @@ buildings:
|
|||
|
||||
storyRewards:
|
||||
# Those are the rewards gained from completing the store
|
||||
reward_cutter_and_trash: Cutting Shapes
|
||||
reward_rotater: Rotating
|
||||
reward_painter: Painting
|
||||
reward_mixer: Color Mixing
|
||||
reward_stacker: Combiner
|
||||
reward_splitter: Splitter/Merger
|
||||
reward_tunnel: Tunnel
|
||||
reward_cutter_and_trash:
|
||||
title: Cutting Shapes
|
||||
desc: You just unlocked the <strong>cutter</strong> - it cuts shapes half from <strong>top to bottom</strong> regardless of its orientation!<br><br>Be sure to get rid of the waste, or otherwise <strong>it will stall</strong> - For this purpose I gave you a trash, which destroys everything you put into it!
|
||||
|
||||
reward_rotater_ccw: CCW Rotating
|
||||
reward_miner_chainable: Chaining Extractor
|
||||
reward_underground_belt_tier_2: Tunnel Tier II
|
||||
reward_splitter_compact: Compact Balancer
|
||||
reward_cutter_quad: Quad Cutting
|
||||
reward_painter_double: Double Painting
|
||||
reward_painter_quad: Quad Painting
|
||||
reward_storage: Storage Buffer
|
||||
reward_rotater:
|
||||
title: Rotating
|
||||
desc: The <strong>rotater</strong> has been unlocked! It rotates shapes clockwise by 90 degrees.
|
||||
|
||||
reward_freeplay: Freeplay
|
||||
reward_painter:
|
||||
title: Painting
|
||||
desc: >-
|
||||
The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, I'm working on a solution already!
|
||||
|
||||
reward_mixer:
|
||||
title: Color Mixing
|
||||
desc: The <strong>mixer</strong> has been unlocked - Combine two colors using <strong>additive blending</strong> with this building!
|
||||
|
||||
reward_stacker:
|
||||
title: Combiner
|
||||
desc: You can now combine shapes with the <strong>combiner</strong>! Both inputs are combined, and if they can be put next to each other, they will be <strong>fused</strong>. If not, the right input is <strong>stacked on top</strong> of the left input!
|
||||
|
||||
reward_splitter:
|
||||
title: Splitter/Merger
|
||||
desc: The multifunctional <strong>balancer</strong> has been unlocked - It can be used to build bigger factories by <strong>splitting and merging items</strong> onto multiple belts!<br><br>
|
||||
|
||||
reward_tunnel:
|
||||
title: Tunnel
|
||||
desc: The <strong>tunnel</strong> has been unlocked - You can now pipe items through belts and buildings with it!
|
||||
|
||||
reward_rotater_ccw:
|
||||
title: CCW Rotating
|
||||
desc: You have unlocked a variant of the <strong>rotater</strong> - It allows to rotate counter clockwise! To build it, select the rotater and <strong>press 'T' to cycle its variants</strong>!
|
||||
|
||||
reward_miner_chainable:
|
||||
title: Chaining Extractor
|
||||
desc: You have unlocked the <strong>chaining extractor</strong>! It can <strong>forward its resources</strong> to other extractors so you can more efficiently extract resources!
|
||||
|
||||
reward_underground_belt_tier_2:
|
||||
title: Tunnel Tier II
|
||||
desc: You have unlocked a new variant of the <strong>tunnel</strong> - It has a <strong>bigger range</strong>, and you can also mix-n-match those tunnels now!
|
||||
|
||||
reward_splitter_compact:
|
||||
title: Compact Balancer
|
||||
desc: >-
|
||||
You have unlocked a compact variant of the <strong>balancer</strong> - It accepts two inputs and merges them into one!
|
||||
|
||||
reward_cutter_quad:
|
||||
title: Quad Cutting
|
||||
desc: You have unlocked a variant of the <strong>cutter</strong> - It allows you to cut shapes in <strong>four parts</strong> instead of just two!
|
||||
|
||||
reward_painter_double:
|
||||
title: Double Painting
|
||||
desc: You have unlocked a variant of the <strong>painter</strong> - It works as the regular painter but processes <strong>two shapes at once</strong> consuming just one color instead of two!
|
||||
|
||||
reward_painter_quad:
|
||||
title: Quad Painting
|
||||
desc: You have unlocked a variant of the <strong>painter</strong> - It allows to paint each part of the shape individually!
|
||||
|
||||
reward_storage:
|
||||
title: Storage Buffer
|
||||
desc: You have unlocked a variant of the <strong>trash</strong> - It allows to store items up to a given capacity!
|
||||
|
||||
reward_freeplay:
|
||||
title: Freeplay
|
||||
desc: You did it! You unlocked the <strong>free-play mode</strong>! This means that shapes are now randomly generated! (No worries, more content is planned for the standalone!)
|
||||
|
||||
# Special reward, which is shown when there is no reward actually
|
||||
no_reward: Next level
|
||||
no_reward:
|
||||
title: Next level
|
||||
desc: >-
|
||||
This level gave you no reward, but the next one will! <br><br> PS: Better don't destroy your existing factory - You need <strong>all</strong> those shapes later again to <strong>unlock upgrades</strong>!
|
||||
|
||||
settings:
|
||||
title: Settings
|
||||
|
|