1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2026-03-02 03:39:21 +00:00

1.5.4 update (polishing + minor rebalancing)

This commit is contained in:
tobspr
2022-06-19 17:08:35 +02:00
parent 6a8e519c0a
commit 3ab5ca99fd
56 changed files with 762 additions and 733 deletions

View File

@@ -1,28 +0,0 @@
#ingame_HUD_DemoTimer {
position: absolute;
@include S(top, 10px);
left: 50%;
text-align: center;
color: #fff;
transform: translateX(-50%);
color: rgb(248, 40, 106);
.timer {
@include Heading;
@include S(font-size, 40px);
}
&.expired .timer {
@include InlineAnimation(1s ease-in-out infinite) {
50% {
transform: scale(1.05);
}
}
}
.description {
@include SuperSmallText;
@include S(margin-top, 10px);
text-transform: uppercase;
}
}

View File

@@ -311,6 +311,7 @@
50% {
background-color: lighten($colorGreenBright, 10);
transform: scale(1.02);
}
100% {
}

View File

@@ -1,6 +1,6 @@
#ingame_HUD_StandaloneAdvantages {
.content {
@include S(width, 440px);
@include S(width, 500px);
@include S(min-height, 300px);
}
p {
@@ -10,14 +10,10 @@
.points {
display: grid;
grid-template-columns: 1fr 1fr;
@include S(grid-column-gap, 10px);
@include S(grid-row-gap, 20px);
@include S(margin, 10px, 0, 20px);
grid-template-rows: #{D(30px)};
@include S(grid-column-gap, 5px);
@include S(grid-row-gap, 5px);
@include S(margin, 10px, 0, 10px);
align-items: center;
background: #eef1f4;
@include S(border-radius, $globalBorderRadius);
@include S(padding, 15px, 4px);
}
.title {
@@ -90,20 +86,15 @@
.playtimeDisclaimerDownload {
@include SuperSmallText;
width: 100%;
box-sizing: border-box;
text-align: center;
background: #b3f2c5;
@include S(border-radius, $globalBorderRadius);
@include S(padding, 7px, 10px);
@include S(padding, 4px, 4px);
@include S(margin-bottom, 15px);
pointer-events: all;
transition: background-color 0.12s ease-in-out;
color: rgba(#000, 0.5);
&:hover {
background: darken(#b3f2c5, 3);
}
cursor: pointer;
strong {
@@ -121,6 +112,12 @@
overflow: visible;
@include S(border-radius, $globalBorderRadius);
@include InlineAnimation(1s ease-in-out infinite) {
50% {
transform: scale(1.02, 1.03);
}
}
> .discount {
position: absolute;
@include S(top, -7px);
@@ -143,8 +140,13 @@
.point {
display: grid;
grid-template-columns: #{D(55px)} auto;
grid-template-columns: #{D(50px)} auto;
grid-template-rows: D(20px) D(20px);
background: #eff2f4 #{D(12px)} center / #{D(30px)} no-repeat;
@include S(border-radius, $globalBorderRadius);
@include S(padding, 10px, 4px, 4px);
@include S(height, 40px);
> strong {
grid-column: 2 / 3;
@@ -161,8 +163,6 @@
opacity: 0.8;
}
background: transparent #{D(10px)} center / #{D(30px)} no-repeat;
&.levels {
& {
/* @load-async */

View File

@@ -49,7 +49,6 @@
@import "ingame_hud/entity_debugger";
@import "ingame_hud/tutorial_hints";
@import "ingame_hud/watermark";
@import "ingame_hud/demo_timer";
@import "ingame_hud/blueprint_placer";
@import "ingame_hud/waypoints";
@import "ingame_hud/interactive_tutorial";
@@ -113,7 +112,6 @@ ingame_HUD_BetaOverlay,
ingame_HUD_Shop,
ingame_HUD_Statistics,
ingame_HUD_ShapeViewer,
ingame_HUD_DemoTimer,
ingame_HUD_StandaloneAdvantages,
ingame_HUD_UnlockNotification,
ingame_HUD_PuzzleCompleteNotification,

View File

@@ -58,7 +58,7 @@ export class BackgroundResourcesLoader {
return this.mainMenuPromise;
}
logger.warn("⏰ Loading main menu assets");
logger.log("⏰ Loading main menu assets");
return (this.mainMenuPromise = this.loadAssets(MAIN_MENU_ASSETS));
}
@@ -66,7 +66,7 @@ export class BackgroundResourcesLoader {
if (this.ingamePromise) {
return this.ingamePromise;
}
logger.warn("⏰ Loading ingame assets");
logger.log("⏰ Loading ingame assets");
const promise = this.loadAssets(INGAME_ASSETS).then(() => initSpriteCache());
return (this.ingamePromise = promise);
}

View File

@@ -79,8 +79,8 @@ export class StaleAreaDetector {
*/
update() {
if (this.staleArea) {
logger.log(this.name, "is recomputing", this.staleArea.toString());
if (G_IS_DEV && globalConfig.debug.renderChanges) {
logger.log(this.name, "is recomputing", this.staleArea.toString());
this.root.hud.parts.changesDebugger.renderChange(this.name, this.staleArea, "#fd145b");
}
this.recomputeMethod(this.staleArea);

View File

@@ -13,7 +13,6 @@ import { HUDBuildingPlacer } from "./parts/building_placer";
import { HUDColorBlindHelper } from "./parts/color_blind_helper";
import { HUDChangesDebugger } from "./parts/debug_changes";
import { HUDDebugInfo } from "./parts/debug_info";
import { HUDDemoTimer } from "./parts/demo_timer";
import { HUDEntityDebugger } from "./parts/entity_debugger";
import { HUDModalDialogs } from "./parts/modal_dialogs";
import { enumNotificationType } from "./parts/notifications";
@@ -86,10 +85,6 @@ export class GameHUD {
this.parts.betaOverlay = new HUDBetaOverlay(this.root);
}
if (this.root.app.restrictionMgr.getIsStandaloneMarketingActive()) {
this.parts.demoTimer = new HUDDemoTimer(this.root);
}
const additionalParts = this.root.gameMode.additionalHudParts;
for (const [partId, part] of Object.entries(additionalParts)) {
this.parts[partId] = new part(this.root);
@@ -217,7 +212,7 @@ export class GameHUD {
* @param {DrawParameters} parameters
*/
drawOverlays(parameters) {
const partsOrder = ["waypoints", "wireInfo"];
const partsOrder = ["waypoints", "watermark", "wireInfo"];
for (let i = 0; i < partsOrder.length; ++i) {
if (this.parts[partsOrder[i]]) {

View File

@@ -1,43 +0,0 @@
import { makeDiv } from "../../../core/utils";
import { T } from "../../../translations";
import { BaseHUDPart } from "../base_hud_part";
export class HUDDemoTimer extends BaseHUDPart {
createElements(parent) {
this.mainElement = makeDiv(parent, "ingame_HUD_DemoTimer", [], "");
this.timerElement = makeDiv(this.mainElement, null, ["timer"], "12:00");
this.descElement = makeDiv(this.mainElement, null, ["description"], T.demoBanners.untilEndOfDemo);
this.currentValue = "";
}
get totalTime() {
return G_IS_STEAM_DEMO ? 15 : 30;
}
initialize() {}
update() {
const time = Math.max(0, this.totalTime * 60 - this.root.time.now());
let minutes = Math.floor(time / 60);
let seconds = Math.floor(time % 60);
let displayString = String(minutes).padStart(2, "0") + ":" + String(seconds).padStart(2, "0");
if (displayString !== this.currentValue) {
this.currentValue = displayString;
this.timerElement.innerText = displayString;
if (time === 0) {
this.mainElement.classList.add("expired");
}
}
if (time === 0) {
const advantages = this.root.hud.parts.standaloneAdvantages;
if (advantages && !advantages.visible) {
advantages.show(true);
}
}
}
}

View File

@@ -1,6 +1,7 @@
import { ClickDetector } from "../../../core/click_detector";
import { InputReceiver } from "../../../core/input_receiver";
import { formatBigNumber, getRomanNumber, makeDiv } from "../../../core/utils";
import { SOUNDS } from "../../../platform/sound";
import { T } from "../../../translations";
import { KeyActionMapper, KEYMAPPINGS } from "../../key_action_mapper";
import { BaseHUDPart } from "../base_hud_part";
@@ -243,8 +244,9 @@ export class HUDShop extends BaseHUDPart {
}
tryUnlockNextTier(upgradeId) {
// Nothing
this.root.hubGoals.tryUnlockUpgrade(upgradeId);
if (this.root.hubGoals.tryUnlockUpgrade(upgradeId)) {
this.root.app.sound.playUiSound(SOUNDS.unlockUpgrade);
}
}
isBlockingOverlay() {

View File

@@ -12,8 +12,8 @@ export class HUDStandaloneAdvantages extends BaseHUDPart {
// DIALOG Inner / Wrapper
this.dialogInner = makeDiv(this.background, null, ["dialogInner"]);
this.title = makeDiv(this.dialogInner, null, ["title"], T.ingame.standaloneAdvantages.title_expired);
this.subTitle = makeDiv(this.dialogInner, null, ["subTitle"], T.ingame.standaloneAdvantages.title);
this.title = makeDiv(this.dialogInner, null, ["title"], "");
this.subTitle = makeDiv(this.dialogInner, null, ["subTitle"], T.ingame.standaloneAdvantages.titleV2);
this.contentDiv = makeDiv(
this.dialogInner,
@@ -34,7 +34,6 @@ export class HUDStandaloneAdvantages extends BaseHUDPart {
</div>
<div class="lowerBar">
<div class="playtimeDisclaimer">${T.demoBanners.playtimeDisclaimer}</div>
<div class="playtimeDisclaimerDownload">${T.demoBanners.playtimeDisclaimerDownload}</div>
@@ -75,6 +74,18 @@ export class HUDStandaloneAdvantages extends BaseHUDPart {
return 15 * 60;
}
shouldPauseGame() {
return this.visible;
}
shouldPauseRendering() {
return this.visible;
}
hasBlockingOverlayOpen() {
return this.visible;
}
initialize() {
this.domAttach = new DynamicDomAttach(this.root, this.background, {
attachClass: "visible",
@@ -83,7 +94,8 @@ export class HUDStandaloneAdvantages extends BaseHUDPart {
this.inputReciever = new InputReceiver("standalone-advantages");
this.close();
// On standalone, show popup instant - but don't do so on web
// On standalone, show popup instant - but don't do so on web, since it increases
// the amount of clicks to get into the game
if (G_IS_STEAM_DEMO) {
// show instant
this.lastShown = -1e10;
@@ -91,6 +103,15 @@ export class HUDStandaloneAdvantages extends BaseHUDPart {
// wait for next interval
this.lastShown = 0;
}
this.root.signals.gameRestored.add(() => {
if (
this.root.hubGoals.level >= this.root.gameMode.getLevelDefinitions().length - 1 &&
this.root.app.restrictionMgr.getIsStandaloneMarketingActive()
) {
this.show(true);
}
});
}
show(final = false) {
@@ -98,6 +119,12 @@ export class HUDStandaloneAdvantages extends BaseHUDPart {
this.visible = true;
this.final = final;
this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever);
if (this.final) {
this.title.innerText = T.ingame.standaloneAdvantages.titleExpiredV2;
} else {
this.title.innerText = T.ingame.standaloneAdvantages.titleEnjoyingDemo;
}
}
close() {
@@ -112,6 +139,10 @@ export class HUDStandaloneAdvantages extends BaseHUDPart {
}
update() {
if (!this.visible && this.root.time.now() - this.lastShown > this.showIntervalSeconds) {
this.show();
}
this.domAttach.update(this.visible);
}
}

View File

@@ -31,10 +31,6 @@ export class HUDUnlockNotification extends BaseHUDPart {
this.element = makeDiv(parent, "ingame_HUD_UnlockNotification", ["noBlur"]);
if (G_IS_STEAM_DEMO || !G_IS_STANDALONE) {
this.element.classList.add("withinDemo");
}
const dialog = makeDiv(this.element, null, ["dialog"]);
this.elemTitle = makeDiv(dialog, null, ["title"]);
@@ -135,6 +131,13 @@ export class HUDUnlockNotification extends BaseHUDPart {
this.root.hud.signals.unlockNotificationFinished.dispatch();
if (
this.root.hubGoals.level > this.root.gameMode.getLevelDefinitions().length - 1 &&
this.root.app.restrictionMgr.getIsStandaloneMarketingActive()
) {
this.root.hud.parts.standaloneAdvantages.show(true);
}
if (!this.root.app.settings.getAllSettings().offerHints) {
return;
}

View File

@@ -5,23 +5,6 @@ import { BaseHUDPart } from "../base_hud_part";
export class HUDWatermark extends BaseHUDPart {
createElements(parent) {
// To be continued later
// let linkText = "";
// switch (this.root.app.gameAnalytics.abtVariant) {
// case "0": {
// linkText = "Get on Steam";
// break;
// }
// case "1": {
// linkText = "Play on Steam";
// break;
// }
// case "2": {
// linkText = T.ingame.watermark.get_on_steam;
// break;
// }
// }
let linkText = T.ingame.watermark.get_on_steam;
this.linkElement = makeDiv(
@@ -41,4 +24,23 @@ export class HUDWatermark extends BaseHUDPart {
initialize() {}
update() {}
/**
*
* @param {import("../../../core/draw_utils").DrawParameters} parameters
*/
drawOverlays(parameters) {
const w = this.root.gameWidth;
parameters.context.fillStyle = "rgba(20, 30, 40, 0.25)";
parameters.context.font = "bold " + this.root.app.getEffectiveUiScale() * 40 + "px GameFont";
parameters.context.textAlign = "center";
parameters.context.fillText(
T.demoBanners.title.toUpperCase(),
w / 2,
this.root.app.getEffectiveUiScale() * 50
);
parameters.context.textAlign = "left";
}
}

View File

@@ -22,8 +22,12 @@ export class MapView extends BaseMap {
/**
* The cached background sprite, containing the flat background
* @type {HTMLCanvasElement} */
this.cachedBackgroundCanvas = null;
* @type {Object<string, HTMLCanvasElement | null>}
*/
this.cachedBackgroundCanvases = {
regular: null,
placing: null,
};
/** @type {CanvasRenderingContext2D} */
this.cachedBackgroundContext = null;
@@ -36,8 +40,10 @@ export class MapView extends BaseMap {
}
cleanup() {
freeCanvas(this.cachedBackgroundCanvas);
this.cachedBackgroundCanvas = null;
for (const key in this.cachedBackgroundCanvases) {
freeCanvas(this.cachedBackgroundCanvases[key]);
this.cachedBackgroundCanvases[key] = null;
}
}
/**
@@ -99,28 +105,29 @@ export class MapView extends BaseMap {
* Initializes all canvases used for background rendering
*/
internalInitializeCachedBackgroundCanvases() {
// Background canvas
const dims = globalConfig.tileSize;
const dpi = this.backgroundCacheDPI;
const [canvas, context] = makeOffscreenBuffer(dims * dpi, dims * dpi, {
smooth: false,
label: "map-cached-bg",
});
context.scale(dpi, dpi);
for (const key in this.cachedBackgroundCanvases) {
// Background canvas
const dims = globalConfig.tileSize;
const dpi = this.backgroundCacheDPI;
const [canvas, context] = makeOffscreenBuffer(dims * dpi, dims * dpi, {
smooth: false,
label: "map-cached-bg",
});
context.scale(dpi, dpi);
context.fillStyle = THEME.map.background;
context.fillRect(0, 0, dims, dims);
context.fillStyle = THEME.map.background;
context.fillRect(0, 0, dims, dims);
const borderWidth = THEME.map.gridLineWidth;
context.fillStyle = THEME.map.grid;
context.fillRect(0, 0, dims, borderWidth);
context.fillRect(0, borderWidth, borderWidth, dims);
const borderWidth = THEME.map.gridLineWidth;
context.fillStyle = THEME.map["grid" + key[0].toUpperCase() + key.substring(1)] || "red";
context.fillRect(0, 0, dims, borderWidth);
context.fillRect(0, borderWidth, borderWidth, dims);
context.fillRect(dims - borderWidth, borderWidth, borderWidth, dims - 2 * borderWidth);
context.fillRect(borderWidth, dims - borderWidth, dims, borderWidth);
context.fillRect(dims - borderWidth, borderWidth, borderWidth, dims - 2 * borderWidth);
context.fillRect(borderWidth, dims - borderWidth, dims, borderWidth);
this.cachedBackgroundCanvas = canvas;
this.cachedBackgroundContext = context;
this.cachedBackgroundCanvases[key] = canvas;
}
}
/**
@@ -225,14 +232,19 @@ export class MapView extends BaseMap {
const dpi = this.backgroundCacheDPI;
parameters.context.scale(1 / dpi, 1 / dpi);
// @ts-ignore
if (this.cachedBackgroundCanvas._contextLost) {
freeCanvas(this.cachedBackgroundCanvas);
let key = "regular";
if (this.root.hud.parts.buildingPlacer.currentMetaBuilding.get()) {
key = "placing";
}
// @ts-ignore`
if (this.cachedBackgroundCanvases[key]._contextLost) {
freeCanvas(this.cachedBackgroundCanvases[key]);
this.internalInitializeCachedBackgroundCanvases();
}
parameters.context.fillStyle = parameters.context.createPattern(
this.cachedBackgroundCanvas,
this.cachedBackgroundCanvases[key],
"repeat"
);
parameters.context.fillRect(

View File

@@ -1,249 +1,363 @@
import { enumHubGoalRewards } from "../tutorial_goals";
export const LevelSetVariant = {
NoRestrictions: "NoRestrictions",
LimitedLevel8: "LimitedLevel8",
LimitedLevelBlueprints: "LimitedLevelBlueprints",
};
export const finalGameShape = "RuCw--Cw:----Ru--";
const chinaShapes = G_WEGAME_VERSION || G_CHINA_VERSION;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
const WEB_DEMO_LEVELS = () => [
// 1
// Circle
{
shape: "CuCuCuCu", // belts t1
required: 10,
reward: enumHubGoalRewards.reward_cutter_and_trash,
},
// 2
// Cutter
{
shape: "----CuCu", //
required: 20,
reward: enumHubGoalRewards.no_reward,
},
// 3
// Rectangle
{
shape: "RuRuRuRu", // miners t1
required: 50,
reward: enumHubGoalRewards.reward_balancer,
},
// 4
{
shape: "RuRu----", // processors t2
required: 30,
reward: enumHubGoalRewards.reward_rotater,
},
// 5
// Rotater
{
shape: "Cu----Cu", // belts t2
required: 75,
reward: enumHubGoalRewards.reward_tunnel,
},
// 6
{
shape: "Cu------", // miners t2
required: 75,
reward: enumHubGoalRewards.reward_painter,
},
// 7
// Painter
{
shape: "CrCrCrCr", // unused
required: 120,
reward: enumHubGoalRewards.reward_rotater_ccw,
},
// 8
{
shape: "RbRb----", // painter t2
required: 170,
reward: enumHubGoalRewards.reward_mixer,
},
// End of demo
{
shape: "RbRb----",
required: 0,
reward: enumHubGoalRewards.reward_demo_end,
},
];
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
const STEAM_DEMO_LEVELS = () => [
// 1
// Circle
{
shape: "CuCuCuCu", // belts t1
required: 35,
reward: enumHubGoalRewards.reward_cutter_and_trash,
},
// 2
// Cutter
{
shape: "----CuCu", //
required: 45,
reward: enumHubGoalRewards.no_reward,
},
// 3
// Rectangle
{
shape: "RuRuRuRu", // miners t1
required: 90,
reward: enumHubGoalRewards.reward_balancer,
},
// 4
{
shape: "RuRu----", // processors t2
required: 70,
reward: enumHubGoalRewards.reward_rotater,
},
// 5
// Rotater
{
shape: "Cu----Cu", // belts t2
required: 160,
reward: enumHubGoalRewards.reward_tunnel,
},
// 6
{
shape: "Cu------", // miners t2
required: 160,
reward: enumHubGoalRewards.reward_painter,
},
// 7
// Painter
{
shape: "CrCrCrCr", // unused
required: 140,
reward: enumHubGoalRewards.reward_rotater_ccw,
},
// 8
{
shape: "RbRb----", // painter t2
required: 225,
reward: enumHubGoalRewards.reward_mixer,
},
// End of demo
{
shape: "RbRb----",
required: 0,
reward: enumHubGoalRewards.reward_demo_end,
},
];
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
const STANDALONE_LEVELS = () => [
// 1
// Circle
{
shape: "CuCuCuCu", // belts t1
required: 30,
reward: enumHubGoalRewards.reward_cutter_and_trash,
},
// 2
// Cutter
{
shape: "----CuCu", //
required: 40,
reward: enumHubGoalRewards.no_reward,
},
// 3
// Rectangle
{
shape: "RuRuRuRu", // miners t1
required: 70,
reward: enumHubGoalRewards.reward_balancer,
},
// 4
{
shape: "RuRu----", // processors t2
required: 70,
reward: enumHubGoalRewards.reward_rotater,
},
// 5
// Rotater
{
shape: "Cu----Cu", // belts t2
required: 170,
reward: enumHubGoalRewards.reward_tunnel,
},
// 6
{
shape: "Cu------", // miners t2
required: 270,
reward: enumHubGoalRewards.reward_painter,
},
// 7
// Painter
{
shape: "CrCrCrCr", // unused
required: 300,
reward: enumHubGoalRewards.reward_rotater_ccw,
},
// 8
{
shape: "RbRb----", // painter t2
required: 480,
reward: enumHubGoalRewards.reward_mixer,
},
// 9
// Mixing (purple)
{
shape: "CpCpCpCp", // belts t3
required: 600,
reward: enumHubGoalRewards.reward_merger,
},
// 10
// STACKER: Star shape + cyan
{
shape: "ScScScSc", // miners t3
required: 800,
reward: enumHubGoalRewards.reward_stacker,
},
// 11
// Chainable miner
{
shape: "CgScScCg", // processors t3
required: 1000,
reward: enumHubGoalRewards.reward_miner_chainable,
},
// 12
// Blueprints
{
shape: "CbCbCbRb:CwCwCwCw",
required: 1000,
reward: enumHubGoalRewards.reward_blueprints,
},
// 13
// Tunnel Tier 2
{
shape: chinaShapes ? "CuCuCuCu:CwCwCwCw:Sb--Sr--" : "RpRpRpRp:CwCwCwCw", // painting t3
required: 3800,
reward: enumHubGoalRewards.reward_underground_belt_tier_2,
},
// 14
// Belt reader
{
shape: "--Cg----:--Cr----", // unused
required: 8, // Per second!
reward: enumHubGoalRewards.reward_belt_reader,
throughputOnly: true,
},
// 15
// Storage
{
shape: "SrSrSrSr:CyCyCyCy", // unused
required: 10000,
reward: enumHubGoalRewards.reward_storage,
},
// 16
// Quad Cutter
{
shape: "SrSrSrSr:CyCyCyCy:SwSwSwSw", // belts t4 (two variants)
required: 6000,
reward: enumHubGoalRewards.reward_cutter_quad,
},
// 17
// Double painter
{
shape: chinaShapes ? "CyCyCyCy:CyCyCyCy:RyRyRyRy:RuRuRuRu" : "CbRbRbCb:CwCwCwCw:WbWbWbWb", // miner t4 (two variants)
required: 20000,
reward: enumHubGoalRewards.reward_painter_double,
},
// 18
// Rotater (180deg)
{
shape: "Sg----Sg:CgCgCgCg:--CyCy--", // unused
required: 20000,
reward: enumHubGoalRewards.reward_rotater_180,
},
// 19
// Compact splitter
{
shape: "CpRpCp--:SwSwSwSw",
required: 25000,
reward: enumHubGoalRewards.reward_splitter,
},
// 20
// WIRES
{
shape: finalGameShape,
required: 25000,
reward: enumHubGoalRewards.reward_wires_painter_and_levers,
},
// 21
// Filter
{
shape: "CrCwCrCw:CwCrCwCr:CrCwCrCw:CwCrCwCr",
required: 25000,
reward: enumHubGoalRewards.reward_filter,
},
// 22
// Constant signal
{
shape: chinaShapes ? "RrSySrSy:RyCrCwCr:CyCyRyCy" : "Cg----Cr:Cw----Cw:Sy------:Cy----Cy",
required: 25000,
reward: enumHubGoalRewards.reward_constant_signal,
},
// 23
// Display
{
shape: chinaShapes ? "CrCrCrCr:CwCwCwCw:WwWwWwWw:CrCrCrCr" : "CcSyCcSy:SyCcSyCc:CcSyCcSy",
required: 25000,
reward: enumHubGoalRewards.reward_display,
},
// 24 Logic gates
{
shape: chinaShapes ? "Su----Su:RwRwRwRw:Cu----Cu:CwCwCwCw" : "CcRcCcRc:RwCwRwCw:Sr--Sw--:CyCyCyCy",
required: 25000,
reward: enumHubGoalRewards.reward_logic_gates,
},
// 25 Virtual Processing
{
shape: "Rg--Rg--:CwRwCwRw:--Rg--Rg",
required: 25000,
reward: enumHubGoalRewards.reward_virtual_processing,
},
// 26 Freeplay
{
shape: "CbCuCbCu:Sr------:--CrSrCr:CwCwCwCw",
required: 50000,
reward: enumHubGoalRewards.reward_freeplay,
},
];
/**
* Generates the level definitions
* @param {keyof typeof LevelSetVariant} variant
*/
export function generateLevelsForVariant(variant) {
const levelDefinitions = [
// 1
// Circle
{
shape: "CuCuCuCu", // belts t1
required: 30,
reward: enumHubGoalRewards.reward_cutter_and_trash,
},
// 2
// Cutter
{
shape: "----CuCu", //
required: 40,
reward: enumHubGoalRewards.no_reward,
},
// 3
// Rectangle
{
shape: "RuRuRuRu", // miners t1
required: 70,
reward: enumHubGoalRewards.reward_balancer,
},
// 4
{
shape: "RuRu----", // processors t2
required: 70,
reward: enumHubGoalRewards.reward_rotater,
},
// 5
// Rotater
{
shape: "Cu----Cu", // belts t2
required: 170,
reward: enumHubGoalRewards.reward_tunnel,
},
// 6
{
shape: "Cu------", // miners t2
required: 270,
reward: enumHubGoalRewards.reward_painter,
},
// 7
// Painter
{
shape: "CrCrCrCr", // unused
required: 300,
reward: enumHubGoalRewards.reward_rotater_ccw,
},
];
if (variant === LevelSetVariant.LimitedLevel8) {
// Variant: End of Demo (level 8)
levelDefinitions.push({
shape: "CrCrCrCr",
required: 0,
reward: enumHubGoalRewards.reward_demo_end,
});
return levelDefinitions;
export function generateLevelsForVariant() {
if (G_IS_STEAM_DEMO) {
return STEAM_DEMO_LEVELS();
} else if (G_IS_STANDALONE) {
return STANDALONE_LEVELS();
}
levelDefinitions.push(
// 8
{
shape: "RbRb----", // painter t2
required: 480,
reward: enumHubGoalRewards.reward_mixer,
},
// 9
// Mixing (purple)
{
shape: "CpCpCpCp", // belts t3
required: 600,
reward: enumHubGoalRewards.reward_merger,
},
// 10
// STACKER: Star shape + cyan
{
shape: "ScScScSc", // miners t3
required: 800,
reward: enumHubGoalRewards.reward_stacker,
},
// 11
// Chainable miner
{
shape: "CgScScCg", // processors t3
required: 1000,
reward: enumHubGoalRewards.reward_miner_chainable,
},
// 12
// Blueprints
{
shape: "CbCbCbRb:CwCwCwCw",
required: 1000,
reward: enumHubGoalRewards.reward_blueprints,
}
);
if (variant === LevelSetVariant.LimitedLevelBlueprints) {
// Variant: End of Demo (before blueprints)
levelDefinitions.push({
shape: "CbCbCbRb:CwCwCwCw",
required: 0,
reward: enumHubGoalRewards.reward_demo_end,
});
return levelDefinitions;
}
levelDefinitions.push(
// 13
// Tunnel Tier 2
{
shape: chinaShapes ? "CuCuCuCu:CwCwCwCw:Sb--Sr--" : "RpRpRpRp:CwCwCwCw", // painting t3
required: 3800,
reward: enumHubGoalRewards.reward_underground_belt_tier_2,
},
// 14
// Belt reader
{
shape: "--Cg----:--Cr----", // unused
required: 8, // Per second!
reward: enumHubGoalRewards.reward_belt_reader,
throughputOnly: true,
},
// 15
// Storage
{
shape: "SrSrSrSr:CyCyCyCy", // unused
required: 10000,
reward: enumHubGoalRewards.reward_storage,
},
// 16
// Quad Cutter
{
shape: "SrSrSrSr:CyCyCyCy:SwSwSwSw", // belts t4 (two variants)
required: 6000,
reward: enumHubGoalRewards.reward_cutter_quad,
},
// 17
// Double painter
{
shape: chinaShapes ? "CyCyCyCy:CyCyCyCy:RyRyRyRy:RuRuRuRu" : "CbRbRbCb:CwCwCwCw:WbWbWbWb", // miner t4 (two variants)
required: 20000,
reward: enumHubGoalRewards.reward_painter_double,
},
// 18
// Rotater (180deg)
{
shape: "Sg----Sg:CgCgCgCg:--CyCy--", // unused
required: 20000,
reward: enumHubGoalRewards.reward_rotater_180,
},
// 19
// Compact splitter
{
shape: "CpRpCp--:SwSwSwSw",
required: 25000,
reward: enumHubGoalRewards.reward_splitter,
},
// 20
// WIRES
{
shape: finalGameShape,
required: 25000,
reward: enumHubGoalRewards.reward_wires_painter_and_levers,
},
// 21
// Filter
{
shape: "CrCwCrCw:CwCrCwCr:CrCwCrCw:CwCrCwCr",
required: 25000,
reward: enumHubGoalRewards.reward_filter,
},
// 22
// Constant signal
{
shape: chinaShapes ? "RrSySrSy:RyCrCwCr:CyCyRyCy" : "Cg----Cr:Cw----Cw:Sy------:Cy----Cy",
required: 25000,
reward: enumHubGoalRewards.reward_constant_signal,
},
// 23
// Display
{
shape: chinaShapes ? "CrCrCrCr:CwCwCwCw:WwWwWwWw:CrCrCrCr" : "CcSyCcSy:SyCcSyCc:CcSyCcSy",
required: 25000,
reward: enumHubGoalRewards.reward_display,
},
// 24 Logic gates
{
shape: chinaShapes
? "Su----Su:RwRwRwRw:Cu----Cu:CwCwCwCw"
: "CcRcCcRc:RwCwRwCw:Sr--Sw--:CyCyCyCy",
required: 25000,
reward: enumHubGoalRewards.reward_logic_gates,
},
// 25 Virtual Processing
{
shape: "Rg--Rg--:CwRwCwRw:--Rg--Rg",
required: 25000,
reward: enumHubGoalRewards.reward_virtual_processing,
},
// 26 Freeplay
{
shape: "CbCuCbCu:Sr------:--CrSrCr:CwCwCwCw",
required: 50000,
reward: enumHubGoalRewards.reward_freeplay,
}
);
return levelDefinitions;
return WEB_DEMO_LEVELS();
}

View File

@@ -293,21 +293,17 @@ function generateUpgrades(limitedVersion = false, difficulty = 1) {
return upgrades;
}
const levelDefinitionsCache = {};
let levelDefinitionsCache = null;
/**
* Generates the level definitions
* @param {keyof typeof LevelSetVariant} variant
*/
export function generateLevelDefinitions(variant, difficulty = 1) {
if (levelDefinitionsCache[variant]) {
return levelDefinitionsCache[variant];
export function generateLevelDefinitions() {
if (levelDefinitionsCache) {
return levelDefinitionsCache;
}
const levelDefinitions = generateLevelsForVariant(variant);
const levelDefinitions = generateLevelsForVariant();
MOD_SIGNALS.modifyLevelDefinitions.dispatch(levelDefinitions);
if (G_IS_DEV) {
levelDefinitions.forEach(({ shape }) => {
try {
@@ -317,13 +313,7 @@ export function generateLevelDefinitions(variant, difficulty = 1) {
}
});
}
levelDefinitions.forEach(definition => {
definition.required = Math.round(definition.required * difficulty);
});
levelDefinitionsCache[variant] = levelDefinitions;
levelDefinitionsCache = levelDefinitions;
return levelDefinitions;
}
@@ -412,14 +402,7 @@ export class RegularGameMode extends GameMode {
* @returns {Array<LevelDefinition>}
*/
getLevelDefinitions() {
if (this.root.app.restrictionMgr.isLimitedVersion()) {
return generateLevelDefinitions(
this.root.app.gameAnalytics.abtVariant === "0" ? "LimitedLevel8" : "LimitedLevelBlueprints",
this.difficultyMultiplicator
);
} else {
return generateLevelDefinitions("NoRestrictions", this.difficultyMultiplicator);
}
return generateLevelDefinitions();
}
/**

View File

@@ -1,7 +1,9 @@
{
"map": {
"background": "#3e3f47",
"grid": "rgba(255, 255, 255, 0.02)",
"gridRegular": "rgba(255, 255, 255, 0.02)",
"gridPlacing": "rgba(255, 255, 255, 0.06)",
"gridLineWidth": 0.5,
"selectionOverlay": "rgba(74, 163, 223, 0.7)",

View File

@@ -1,8 +1,11 @@
{
"map": {
"background": "#fff",
"grid": "#fafafa",
"gridLineWidth": 1,
"background": "#eceef6",
"gridRegular": "#e3e7f4",
"gridPlacing": "#dadff0",
"gridLineWidth": 0.5,
"selectionOverlay": "rgba(74, 163, 223, 0.7)",
"selectionOutline": "rgba(74, 163, 223, 0.5)",
@@ -29,9 +32,9 @@
"resources": {
"shape": "#eaebec",
"red": "#ffbfc1",
"green": "#cbffc4",
"blue": "#bfdaff"
"red": "#f3bcb6",
"green": "#ccf7a7",
"blue": "#b2e0fa"
},
"chunkOverview": {

View File

@@ -28,8 +28,8 @@ const analyticsUrl = G_IS_DEV ? "http://localhost:8001" : "https://analytics.sha
// Be sure to increment the ID whenever it changes
const analyticsLocalFile = G_IS_STEAM_DEMO ? "shapez_token_steamdemo.bin" : "shapez_token_123.bin";
const CURRENT_ABT = "abt_unl";
const CURRENT_ABT_COUNT = 2;
const CURRENT_ABT = "abt_bsln";
const CURRENT_ABT_COUNT = 1;
export class ShapezGameAnalytics extends GameAnalyticsInterface {
constructor(app) {

View File

@@ -26,6 +26,7 @@ export const SOUNDS = {
placeBuilding: "place_building",
placeBelt: "place_belt",
copy: "copy",
unlockUpgrade: "unlock_upgrade",
};
export const MUSIC = {
@@ -150,6 +151,9 @@ export class SoundInterface {
* @returns {Promise<void>}
*/
loadSound(key) {
if (!key) {
return Promise.resolve();
}
if (this.sounds[key]) {
return this.sounds[key].load();
} else if (this.music[key]) {
@@ -271,7 +275,7 @@ export class SoundInterface {
*/
playThemeMusic(key) {
const music = this.music[key];
if (key !== null && !music) {
if (key && !music) {
logger.warn("Music", key, "not found");
}
if (this.currentMusic !== music) {

View File

@@ -513,12 +513,6 @@ export class ApplicationSettings extends ReadWriteProxy {
const settings = data.settings;
// MODS
if (!THEMES[settings.theme] || !this.app.restrictionMgr.getHasExtendedSettings()) {
console.warn("Resetting theme because its no longer available: " + settings.theme);
settings.theme = "light";
}
for (let i = 0; i < this.settingHandles.length; ++i) {
const setting = this.settingHandles[i];
const storedValue = settings[setting.id];
@@ -701,7 +695,7 @@ export class ApplicationSettings extends ReadWriteProxy {
// MODS
if (!THEMES[data.settings.theme] || !this.app.restrictionMgr.getHasExtendedSettings()) {
console.warn("Resetting theme because its no longer available: " + data.settings.theme);
console.log("Resetting theme because its no longer available: " + data.settings.theme);
data.settings.theme = "light";
}