1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2025-06-13 13:04:03 +00:00

Added up to four hub goals at one time

This commit is contained in:
DJ1TJOO 2021-06-29 00:21:09 +02:00
parent cc044e2547
commit 596fe59425
9 changed files with 393 additions and 165 deletions

View File

@ -57,6 +57,21 @@ export class MetaHubBuilding extends MetaBuilding {
type: enumPinSlotType.logicalEjector, type: enumPinSlotType.logicalEjector,
direction: enumDirection.left, direction: enumDirection.left,
}, },
{
pos: new Vector(3, 2),
type: enumPinSlotType.logicalEjector,
direction: enumDirection.right,
},
{
pos: new Vector(0, 3),
type: enumPinSlotType.logicalEjector,
direction: enumDirection.left,
},
{
pos: new Vector(3, 3),
type: enumPinSlotType.logicalEjector,
direction: enumDirection.right,
},
], ],
}) })
); );

View File

@ -105,6 +105,18 @@ export class HubGoals extends BasicSerializableObject {
this.upgradeImprovements[key] = 1; this.upgradeImprovements[key] = 1;
} }
/**
* @type {{
* definitions: ShapeDefinition[],
* requires: Array<{
* throughputOnly?: Boolean,
* amount: Number,
* }>,
* reward: enumHubGoalRewards,
* }}
*/
this.currentGoal = null;
this.computeNextGoal(); this.computeNextGoal();
// Allow quickly switching goals in dev mode // Allow quickly switching goals in dev mode
@ -167,16 +179,34 @@ export class HubGoals extends BasicSerializableObject {
* Returns how much of the current goal was already delivered * Returns how much of the current goal was already delivered
*/ */
getCurrentGoalDelivered() { getCurrentGoalDelivered() {
if (this.currentGoal.throughputOnly) { const currentGoalDeliverd = [];
return (
this.root.productionAnalytics.getCurrentShapeRateRaw( for (let i = 0; i < this.currentGoal.definitions.length; i++) {
enumAnalyticsDataSource.delivered, if (this.currentGoal.requires[i].throughputOnly) {
this.currentGoal.definition currentGoalDeliverd.push(
) / globalConfig.analyticsSliceDurationSeconds this.root.productionAnalytics.getCurrentShapeRateRaw(
); enumAnalyticsDataSource.delivered,
this.currentGoal.definitions[i]
) / globalConfig.analyticsSliceDurationSeconds
);
} else {
currentGoalDeliverd.push(this.getShapesStored(this.currentGoal.definitions[i]));
}
}
return currentGoalDeliverd;
}
/**
* Returns if the current goal is completed
*/
isGoalCompleted() {
const delivered = this.getCurrentGoalDelivered();
for (let i = 0; i < delivered.length; i++) {
if (delivered[i] < this.currentGoal.requires[i].amount) return false;
} }
return this.getShapesStored(this.currentGoal.definition); return true;
} }
/** /**
@ -214,10 +244,7 @@ export class HubGoals extends BasicSerializableObject {
this.root.signals.shapeDelivered.dispatch(definition); this.root.signals.shapeDelivered.dispatch(definition);
// Check if we have enough for the next level // Check if we have enough for the next level
if ( if (this.isGoalCompleted() || (G_IS_DEV && globalConfig.debug.rewardsInstant)) {
this.getCurrentGoalDelivered() >= this.currentGoal.required ||
(G_IS_DEV && globalConfig.debug.rewardsInstant)
) {
if (!this.isEndOfDemoReached()) { if (!this.isEndOfDemoReached()) {
this.onGoalCompleted(); this.onGoalCompleted();
} }
@ -231,24 +258,23 @@ export class HubGoals extends BasicSerializableObject {
const storyIndex = this.level - 1; const storyIndex = this.level - 1;
const levels = this.root.gameMode.getLevelDefinitions(); const levels = this.root.gameMode.getLevelDefinitions();
if (storyIndex < levels.length) { if (storyIndex < levels.length) {
const { shape, required, reward, throughputOnly } = levels[storyIndex]; const { shapes, requires, reward } = levels[storyIndex];
this.currentGoal = { if (shapes) {
/** @type {ShapeDefinition} */ this.currentGoal = {
definition: this.root.shapeDefinitionMgr.getShapeFromShortKey(shape), definitions: shapes.map(code => this.root.shapeDefinitionMgr.getShapeFromShortKey(code)),
required, requires: requires,
reward, reward,
throughputOnly, };
}; return;
return; }
} }
//Floor Required amount to remove confusion //Floor Required amount to remove confusion
const required = Math.min(200, Math.floor(4 + (this.level - 27) * 0.25)); const required = Math.min(200, Math.floor(4 + (this.level - 27) * 0.25));
this.currentGoal = { this.currentGoal = {
definition: this.computeFreeplayShape(this.level), definitions: [this.computeFreeplayShape(this.level)],
required, requires: [{ throughputOnly: true, amount: required }],
reward: enumHubGoalRewards.no_reward_freeplay, reward: enumHubGoalRewards.no_reward_freeplay,
throughputOnly: true,
}; };
} }

View File

@ -24,7 +24,7 @@ const tutorialsByLevel = [
// 1.2. connect to hub // 1.2. connect to hub
{ {
id: "1_2_conveyor", id: "1_2_conveyor",
condition: /** @param {GameRoot} root */ root => root.hubGoals.getCurrentGoalDelivered() === 0, condition: /** @param {GameRoot} root */ root => root.hubGoals.getCurrentGoalDelivered()[0] === 0,
}, },
// 1.3 wait for completion // 1.3 wait for completion
{ {
@ -70,7 +70,7 @@ const tutorialsByLevel = [
id: "3_1_rectangles", id: "3_1_rectangles",
condition: /** @param {GameRoot} root */ root => condition: /** @param {GameRoot} root */ root =>
// 4 miners placed above rectangles and 10 delivered // 4 miners placed above rectangles and 10 delivered
root.hubGoals.getCurrentGoalDelivered() < 10 || root.hubGoals.getCurrentGoalDelivered()[0] < 10 ||
root.entityMgr.getAllWithComponent(MinerComponent).filter(entity => { root.entityMgr.getAllWithComponent(MinerComponent).filter(entity => {
const tile = entity.components.StaticMapEntity.origin; const tile = entity.components.StaticMapEntity.origin;
const below = root.map.getLowerLayerContentXY(tile.x, tile.y); const below = root.map.getLowerLayerContentXY(tile.x, tile.y);

View File

@ -103,8 +103,11 @@ export class HUDPinnedShapes extends BaseHUDPart {
* @param {string} key * @param {string} key
*/ */
findGoalValueForShape(key) { findGoalValueForShape(key) {
if (key === this.root.hubGoals.currentGoal.definition.getHash()) { const goalIndex = this.root.hubGoals.currentGoal.definitions.findIndex(
return this.root.hubGoals.currentGoal.required; shape => shape.getHash() === key
);
if (goalIndex > -1) {
return this.root.hubGoals.currentGoal.requires[goalIndex].amount;
} }
if (key === this.root.gameMode.getBlueprintShapeKey()) { if (key === this.root.gameMode.getBlueprintShapeKey()) {
return null; return null;
@ -138,10 +141,10 @@ export class HUDPinnedShapes extends BaseHUDPart {
* @param {string} key * @param {string} key
*/ */
isShapePinned(key) { isShapePinned(key) {
if ( const goalIndex = this.root.hubGoals.currentGoal.definitions.findIndex(
key === this.root.hubGoals.currentGoal.definition.getHash() || shape => shape.getHash() === key
key === this.root.gameMode.getBlueprintShapeKey() );
) { if (goalIndex > -1 || key === this.root.gameMode.getBlueprintShapeKey()) {
// This is a "special" shape which is always pinned // This is a "special" shape which is always pinned
return true; return true;
} }
@ -154,7 +157,6 @@ export class HUDPinnedShapes extends BaseHUDPart {
*/ */
rerenderFull() { rerenderFull() {
const currentGoal = this.root.hubGoals.currentGoal; const currentGoal = this.root.hubGoals.currentGoal;
const currentKey = currentGoal.definition.getHash();
// First, remove all old shapes // First, remove all old shapes
for (let i = 0; i < this.handles.length; ++i) { for (let i = 0; i < this.handles.length; ++i) {
@ -171,12 +173,15 @@ export class HUDPinnedShapes extends BaseHUDPart {
this.handles = []; this.handles = [];
// Pin story goal // Pin story goal
this.internalPinShape({ for (let i = 0; i < currentGoal.definitions.length; i++) {
key: currentKey, console.log(currentGoal);
canUnpin: false, this.internalPinShape({
className: "goal", key: currentGoal.definitions[i].getHash(),
throughputOnly: currentGoal.throughputOnly, canUnpin: false,
}); className: "goal",
throughputOnly: currentGoal.requires[i].throughputOnly,
});
}
// Pin blueprint shape as well // Pin blueprint shape as well
if (this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_blueprints)) { if (this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_blueprints)) {
@ -190,7 +195,8 @@ export class HUDPinnedShapes extends BaseHUDPart {
// Pin manually pinned shapes // Pin manually pinned shapes
for (let i = 0; i < this.pinnedShapes.length; ++i) { for (let i = 0; i < this.pinnedShapes.length; ++i) {
const key = this.pinnedShapes[i]; const key = this.pinnedShapes[i];
if (key !== currentKey) { const goalIndex = currentGoal.definitions.findIndex(shape => shape.getHash() === key);
if (goalIndex < 0) {
this.internalPinShape({ key }); this.internalPinShape({ key });
} }
} }
@ -308,7 +314,10 @@ export class HUDPinnedShapes extends BaseHUDPart {
*/ */
pinNewShape(definition) { pinNewShape(definition) {
const key = definition.getHash(); const key = definition.getHash();
if (key === this.root.hubGoals.currentGoal.definition.getHash()) { const goalIndex = this.root.hubGoals.currentGoal.definitions.findIndex(
shape => shape.getHash() === key
);
if (goalIndex > -1) {
// Can not pin current goal // Can not pin current goal
return; return;
} }

View File

@ -116,7 +116,9 @@ export class HUDSandboxController extends BaseHUDPart {
hubGoals.computeNextGoal(); hubGoals.computeNextGoal();
// Clear all shapes of this level // Clear all shapes of this level
hubGoals.storedShapes[hubGoals.currentGoal.definition.getHash()] = 0; for (let i = 0; i < hubGoals.currentGoal.definitions.length; i++) {
hubGoals.storedShapes[hubGoals.currentGoal.definitions[i].getHash()] = 0;
}
if (this.root.hud.parts.pinnedShapes) { if (this.root.hud.parts.pinnedShapes) {
this.root.hud.parts.pinnedShapes.rerenderFull(); this.root.hud.parts.pinnedShapes.rerenderFull();

View File

@ -123,8 +123,10 @@ export class HUDShop extends BaseHUDPart {
viewInfoButton.classList.add("showInfo"); viewInfoButton.classList.add("showInfo");
container.appendChild(viewInfoButton); container.appendChild(viewInfoButton);
const currentGoalShape = this.root.hubGoals.currentGoal.definition.getHash(); const goalIndex = this.root.hubGoals.currentGoal.definitions.findIndex(
if (shape === currentGoalShape) { goal => goal.getHash() === shape
);
if (goalIndex > -1) {
pinButton.classList.add("isGoal"); pinButton.classList.add("isGoal");
} else if (this.root.hud.parts.pinnedShapes.isShapePinned(shape)) { } else if (this.root.hud.parts.pinnedShapes.isShapePinned(shape)) {
pinButton.classList.add("alreadyPinned"); pinButton.classList.add("alreadyPinned");

View File

@ -39,12 +39,14 @@ import { queryParamOptions } from "../../core/query_parameters";
import { MetaBlockBuilding } from "../buildings/block"; import { MetaBlockBuilding } from "../buildings/block";
import { MetaItemProducerBuilding } from "../buildings/item_producer"; import { MetaItemProducerBuilding } from "../buildings/item_producer";
/** @typedef {{ /**
* @typedef {{
* shape: string, * shape: string,
* amount: number * amount: number
* }} UpgradeRequirement */ * }} UpgradeRequirement */
/** @typedef {{ /**
* @typedef {{
* required: Array<UpgradeRequirement> * required: Array<UpgradeRequirement>
* improvement?: number, * improvement?: number,
* excludePrevious?: boolean * excludePrevious?: boolean
@ -52,11 +54,14 @@ import { MetaItemProducerBuilding } from "../buildings/item_producer";
/** @typedef {Array<TierRequirement>} UpgradeTiers */ /** @typedef {Array<TierRequirement>} UpgradeTiers */
/** @typedef {{ /**
* shape: string, * @typedef {{
* required: number, * shapes: String[],
* reward: enumHubGoalRewards, * requires: Array<{
* throughputOnly?: boolean * throughputOnly?: Boolean,
* amount: Number,
* }>,
* reward: enumHubGoalRewards,
* }} LevelDefinition */ * }} LevelDefinition */
export const rocketShape = "CbCuCbCu:Sr------:--CrSrCr:CwCwCwCw"; export const rocketShape = "CbCuCbCu:Sr------:--CrSrCr:CwCwCwCw";
@ -287,105 +292,108 @@ function generateUpgrades(limitedVersion = false) {
* @param {boolean} limitedVersion * @param {boolean} limitedVersion
*/ */
export function generateLevelDefinitions(limitedVersion = false) { export function generateLevelDefinitions(limitedVersion = false) {
/**
* @type {Array<LevelDefinition>}
*/
const levelDefinitions = [ const levelDefinitions = [
// 1 // 1
// Circle // Circle
{ {
shape: "CuCuCuCu", // belts t1 shapes: ["CuCuCuCu"], // belts t1
required: 30, requires: [{ amount: 30 }],
reward: enumHubGoalRewards.reward_cutter_and_trash, reward: enumHubGoalRewards.reward_cutter_and_trash,
}, },
// 2 // 2
// Cutter // Cutter
{ {
shape: "----CuCu", // shapes: ["----CuCu"], //
required: 40, requires: [{ amount: 40 }],
reward: enumHubGoalRewards.no_reward, reward: enumHubGoalRewards.no_reward,
}, },
// 3 // 3
// Rectangle // Rectangle
{ {
shape: "RuRuRuRu", // miners t1 shapes: ["RuRuRuRu"], // miners t1
required: 70, requires: [{ amount: 70 }],
reward: enumHubGoalRewards.reward_balancer, reward: enumHubGoalRewards.reward_balancer,
}, },
// 4 // 4
{ {
shape: "RuRu----", // processors t2 shapes: ["RuRu----"], // processors t2
required: 70, requires: [{ amount: 70 }],
reward: enumHubGoalRewards.reward_rotater, reward: enumHubGoalRewards.reward_rotater,
}, },
// 5 // 5
// Rotater // Rotater
{ {
shape: "Cu----Cu", // belts t2 shapes: ["Cu----Cu"], // belts t2
required: 170, requires: [{ amount: 170 }],
reward: enumHubGoalRewards.reward_tunnel, reward: enumHubGoalRewards.reward_tunnel,
}, },
// 6 // 6
{ {
shape: "Cu------", // miners t2 shapes: ["Cu------"], // miners t2
required: 270, requires: [{ amount: 270 }],
reward: enumHubGoalRewards.reward_painter, reward: enumHubGoalRewards.reward_painter,
}, },
// 7 // 7
// Painter // Painter
{ {
shape: "CrCrCrCr", // unused shapes: ["CrCrCrCr"], // unused
required: 300, requires: [{ amount: 300 }],
reward: enumHubGoalRewards.reward_rotater_ccw, reward: enumHubGoalRewards.reward_rotater_ccw,
}, },
// 8 // 8
{ {
shape: "RbRb----", // painter t2 shapes: ["RbRb----"], // painter t2
required: 480, requires: [{ amount: 480 }],
reward: enumHubGoalRewards.reward_mixer, reward: enumHubGoalRewards.reward_mixer,
}, },
// 9 // 9
// Mixing (purple) // Mixing (purple)
{ {
shape: "CpCpCpCp", // belts t3 shapes: ["CpCpCpCp"], // belts t3
required: 600, requires: [{ amount: 600 }],
reward: enumHubGoalRewards.reward_merger, reward: enumHubGoalRewards.reward_merger,
}, },
// 10 // 10
// STACKER: Star shape + cyan // STACKER: Star shapes + cyan
{ {
shape: "ScScScSc", // miners t3 shapes: ["ScScScSc"], // miners t3
required: 800, requires: [{ amount: 800 }],
reward: enumHubGoalRewards.reward_stacker, reward: enumHubGoalRewards.reward_stacker,
}, },
// 11 // 11
// Chainable miner // Chainable miner
{ {
shape: "CgScScCg", // processors t3 shapes: ["CgScScCg"], // processors t3
required: 1000, requires: [{ amount: 1000 }],
reward: enumHubGoalRewards.reward_miner_chainable, reward: enumHubGoalRewards.reward_miner_chainable,
}, },
// 12 // 12
// Blueprints // Blueprints
{ {
shape: "CbCbCbRb:CwCwCwCw", shapes: ["CbCbCbRb:CwCwCwCw"],
required: 1000, requires: [{ amount: 1000 }],
reward: enumHubGoalRewards.reward_blueprints, reward: enumHubGoalRewards.reward_blueprints,
}, },
// 13 // 13
// Tunnel Tier 2 // Tunnel Tier 2
{ {
shape: chinaShapes ? "CuCuCuCu:CwCwCwCw:Sb--Sr--" : "RpRpRpRp:CwCwCwCw", // painting t3 shapes: [chinaShapes ? "CuCuCuCu:CwCwCwCw:Sb--Sr--" : "RpRpRpRp:CwCwCwCw"], // painting t3
required: 3800, requires: [{ amount: 3800 }],
reward: enumHubGoalRewards.reward_underground_belt_tier_2, reward: enumHubGoalRewards.reward_underground_belt_tier_2,
}, },
@ -393,8 +401,8 @@ export function generateLevelDefinitions(limitedVersion = false) {
...(limitedVersion ...(limitedVersion
? [ ? [
{ {
shape: chinaShapes ? "CuCuCuCu:CwCwCwCw:Sb--Sr--" : "RpRpRpRp:CwCwCwCw", shapes: [chinaShapes ? "CuCuCuCu:CwCwCwCw:Sb--Sr--" : "RpRpRpRp:CwCwCwCw"],
required: 0, requires: [{ amount: 0 }],
reward: enumHubGoalRewards.reward_demo_end, reward: enumHubGoalRewards.reward_demo_end,
}, },
] ]
@ -402,122 +410,173 @@ export function generateLevelDefinitions(limitedVersion = false) {
// 14 // 14
// Belt reader // Belt reader
{ {
shape: "--Cg----:--Cr----", // unused shapes: ["--Cg----:--Cr----"], // unused
required: 8, // Per second! requires: [{ amount: 8, throughputOnly: true }], // Per second!
reward: enumHubGoalRewards.reward_belt_reader, reward: enumHubGoalRewards.reward_belt_reader,
throughputOnly: true,
}, },
// 15 // 15
// Storage // Storage
{ {
shape: "SrSrSrSr:CyCyCyCy", // unused shapes: ["SrSrSrSr:CyCyCyCy"], // unused
required: 10000, requires: [{ amount: 10000 }],
reward: enumHubGoalRewards.reward_storage, reward: enumHubGoalRewards.reward_storage,
}, },
// 16 // 16
// Quad Cutter // Quad Cutter
{ {
shape: "SrSrSrSr:CyCyCyCy:SwSwSwSw", // belts t4 (two variants) shapes: ["SrSrSrSr:CyCyCyCy:SwSwSwSw"], // belts t4 (two variants)
required: 6000, requires: [{ amount: 6000 }],
reward: enumHubGoalRewards.reward_cutter_quad, reward: enumHubGoalRewards.reward_cutter_quad,
}, },
// 17 // 17
// Double painter // Double painter
{ {
shape: chinaShapes shapes: [
? "CyCyCyCy:CyCyCyCy:RyRyRyRy:RuRuRuRu" chinaShapes ? "CyCyCyCy:CyCyCyCy:RyRyRyRy:RuRuRuRu" : "CbRbRbCb:CwCwCwCw:WbWbWbWb",
: "CbRbRbCb:CwCwCwCw:WbWbWbWb", // miner t4 (two variants) ], // miner t4 (two variants)
required: 20000, requires: [{ amount: 20000 }],
reward: enumHubGoalRewards.reward_painter_double, reward: enumHubGoalRewards.reward_painter_double,
}, },
// 18 // 18
// Rotater (180deg) // Rotater (180deg)
{ {
shape: "Sg----Sg:CgCgCgCg:--CyCy--", // unused shapes: ["Sg----Sg:CgCgCgCg:--CyCy--"], // unused
required: 20000, requires: [{ amount: 20000 }],
reward: enumHubGoalRewards.reward_rotater_180, reward: enumHubGoalRewards.reward_rotater_180,
}, },
// 19 // 19
// Compact splitter // Compact splitter
{ {
shape: "CpRpCp--:SwSwSwSw", shapes: ["CpRpCp--:SwSwSwSw"],
required: 25000, requires: [{ amount: 25000 }],
reward: enumHubGoalRewards.reward_splitter, reward: enumHubGoalRewards.reward_splitter,
}, },
// 20 // 20
// WIRES // WIRES
{ {
shape: finalGameShape, shapes: [finalGameShape],
required: 25000, requires: [{ amount: 25000 }],
reward: enumHubGoalRewards.reward_wires_painter_and_levers, reward: enumHubGoalRewards.reward_wires_painter_and_levers,
}, },
// 21 // 21
// Filter // Filter
{ {
shape: "CrCwCrCw:CwCrCwCr:CrCwCrCw:CwCrCwCr", shapes: ["CrCwCrCw:CwCrCwCr:CrCwCrCw:CwCrCwCr"],
required: 25000, requires: [{ amount: 25000 }],
reward: enumHubGoalRewards.reward_filter, reward: enumHubGoalRewards.reward_filter,
}, },
// 22 // 22
// Constant signal // Constant signal
{ {
shape: chinaShapes shapes: [
? "RrSySrSy:RyCrCwCr:CyCyRyCy" chinaShapes ? "RrSySrSy:RyCrCwCr:CyCyRyCy" : "Cg----Cr:Cw----Cw:Sy------:Cy----Cy",
: "Cg----Cr:Cw----Cw:Sy------:Cy----Cy", ],
required: 25000, requires: [{ amount: 25000 }],
reward: enumHubGoalRewards.reward_constant_signal, reward: enumHubGoalRewards.reward_constant_signal,
}, },
// 23 // 23
// Display // Display
{ {
shape: chinaShapes shapes: [
? "CrCrCrCr:CwCwCwCw:WwWwWwWw:CrCrCrCr" chinaShapes ? "CrCrCrCr:CwCwCwCw:WwWwWwWw:CrCrCrCr" : "CcSyCcSy:SyCcSyCc:CcSyCcSy",
: "CcSyCcSy:SyCcSyCc:CcSyCcSy", ],
required: 25000, requires: [{ amount: 25000 }],
reward: enumHubGoalRewards.reward_display, reward: enumHubGoalRewards.reward_display,
}, },
// 24 Logic gates // 24 Logic gates
{ {
shape: chinaShapes shapes: [
? "Su----Su:RwRwRwRw:Cu----Cu:CwCwCwCw" chinaShapes
: "CcRcCcRc:RwCwRwCw:Sr--Sw--:CyCyCyCy", ? "Su----Su:RwRwRwRw:Cu----Cu:CwCwCwCw"
required: 25000, : "CcRcCcRc:RwCwRwCw:Sr--Sw--:CyCyCyCy",
],
requires: [{ amount: 25000 }],
reward: enumHubGoalRewards.reward_logic_gates, reward: enumHubGoalRewards.reward_logic_gates,
}, },
// 25 Virtual Processing // 25 Virtual Processing
{ {
shape: "Rg--Rg--:CwRwCwRw:--Rg--Rg", shapes: ["Rg--Rg--:CwRwCwRw:--Rg--Rg"],
required: 25000, requires: [{ amount: 25000 }],
reward: enumHubGoalRewards.reward_virtual_processing, reward: enumHubGoalRewards.reward_virtual_processing,
}, },
// 26 Freeplay // 26 Freeplay
{ {
shape: "CbCuCbCu:Sr------:--CrSrCr:CwCwCwCw", shapes: ["CbCuCbCu:Sr------:--CrSrCr:CwCwCwCw"],
required: 50000, requires: [{ amount: 50000 }],
reward: enumHubGoalRewards.reward_freeplay,
},
// 27 Random
{
shapes: null,
requires: null,
reward: null,
},
// 28 More shapes
{
shapes: ["CbCuCbCu:Sr------:--CrSrCr:CwCwCwCw", "Rg--Rg--:CwRwCwRw:--Rg--Rg"],
requires: [{ amount: 50000 }, { amount: 30000, throughputOnly: true }],
reward: enumHubGoalRewards.reward_freeplay,
},
// 29 More shapes
{
shapes: [
"CbCuCbCu:Sr------:--CrSrCr:CwCwCwCw",
"Rg--Rg--:CwRwCwRw:--Rg--Rg",
"Su----Su:RwRwRwRw:Cu----Cu:CwCwCwCw",
],
requires: [
{ amount: 50000 },
{ amount: 30000, throughputOnly: true },
{ amount: 70000, throughputOnly: true },
],
reward: enumHubGoalRewards.reward_freeplay,
},
// 30 More shapes
{
shapes: [
"CbCuCbCu:Sr------:--CrSrCr:CwCwCwCw",
"Rg--Rg--:CwRwCwRw:--Rg--Rg",
"Su----Su:RwRwRwRw:Cu----Cu:CwCwCwCw",
"CrCrCrCr:CwCwCwCw:WwWwWwWw:CrCrCrCr",
],
requires: [
{ amount: 50000 },
{ amount: 30000, throughputOnly: true },
{ amount: 70000, throughputOnly: true },
{ amount: 90000 },
],
reward: enumHubGoalRewards.reward_freeplay, reward: enumHubGoalRewards.reward_freeplay,
}, },
]), ]),
]; ];
if (G_IS_DEV) { if (G_IS_DEV) {
levelDefinitions.forEach(({ shape }) => { levelDefinitions.forEach(({ shapes }) => {
try { if (!shapes) return;
ShapeDefinition.fromShortKey(shape);
} catch (ex) { shapes.forEach(shape => {
throw new Error("Invalid tutorial goal: '" + ex + "' for shape" + shape); try {
} ShapeDefinition.fromShortKey(shape);
} catch (ex) {
throw new Error("Invalid tutorial goal: '" + ex + "' for shape" + shape);
}
});
}); });
} }

View File

@ -75,11 +75,13 @@ export class ConstantSignalSystem extends GameSystemWithFilter {
} }
if (this.root.gameMode.hasHub()) { if (this.root.gameMode.hasHub()) {
items.push( for (let i = 0; i < this.root.hubGoals.currentGoal.definitions.length; i++) {
this.root.shapeDefinitionMgr.getShapeItemFromDefinition( items.push(
this.root.hubGoals.currentGoal.definition this.root.shapeDefinitionMgr.getShapeItemFromDefinition(
) this.root.hubGoals.currentGoal.definitions[i]
); )
);
}
} }
if (this.root.hud.parts.pinnedShapes) { if (this.root.hud.parts.pinnedShapes) {

View File

@ -35,13 +35,20 @@ export class HubSystem extends GameSystemWithFilter {
// Set hub goal // Set hub goal
const entity = this.allEntities[i]; const entity = this.allEntities[i];
const pinsComp = entity.components.WiredPins; const pinsComp = entity.components.WiredPins;
pinsComp.slots[0].value = this.root.shapeDefinitionMgr.getShapeItemFromDefinition( for (let i = 0; i < pinsComp.slots.length; i++) {
this.root.hubGoals.currentGoal.definition if (!this.root.hubGoals.currentGoal.definitions[i]) {
); pinsComp.slots[i].value = null;
continue;
}
pinsComp.slots[i].value = this.root.shapeDefinitionMgr.getShapeItemFromDefinition(
this.root.hubGoals.currentGoal.definitions[i]
);
}
} }
} }
/** /**
*
* @param {HTMLCanvasElement} canvas * @param {HTMLCanvasElement} canvas
* @param {CanvasRenderingContext2D} context * @param {CanvasRenderingContext2D} context
* @param {number} w * @param {number} w
@ -49,7 +56,7 @@ export class HubSystem extends GameSystemWithFilter {
* @param {number} dpi * @param {number} dpi
*/ */
redrawHubBaseTexture(canvas, context, w, h, dpi) { redrawHubBaseTexture(canvas, context, w, h, dpi) {
// This method is quite ugly, please ignore it! // This method is quite ugly, please ignore it! It's more ugly now
context.scale(dpi, dpi); context.scale(dpi, dpi);
@ -76,45 +83,151 @@ export class HubSystem extends GameSystemWithFilter {
return; return;
} }
const definition = this.root.hubGoals.currentGoal.definition;
definition.drawCentered(45, 58, parameters, 36);
const goals = this.root.hubGoals.currentGoal; const goals = this.root.hubGoals.currentGoal;
const delivered = this.root.hubGoals.getCurrentGoalDelivered();
const textOffsetX = 70; for (let i = 0; i < goals.definitions.length; i++) {
const textOffsetY = 61; const x =
45 +
if (goals.throughputOnly) { (goals.definitions.length > 3
// Throughput ? 22 * i - 14
const deliveredText = T.ingame.statistics.shapesDisplayUnits.second.replace( : goals.definitions.length > 2
"<shapes>", ? 28 * i - 8
formatBigNumber(goals.required) : goals.definitions.length > 1
? 43 * i
: 0);
const y = 58 + (goals.definitions.length > 1 ? -3 : 0);
goals.definitions[i].drawCentered(
x,
y,
parameters,
goals.definitions.length > 3
? 20
: goals.definitions.length > 2
? 26
: goals.definitions.length > 1
? 32
: 36
); );
context.font = "bold 12px GameFont"; const textOffsetX = 0;
context.fillStyle = "#64666e"; const textOffsetY = 24;
context.textAlign = "left";
context.fillText(deliveredText, textOffsetX, textOffsetY);
} else {
// Deliver count
const delivered = this.root.hubGoals.getCurrentGoalDelivered();
const deliveredText = "" + formatBigNumber(delivered);
if (delivered > 9999) { if (goals.requires[i].throughputOnly) {
context.font = "bold 16px GameFont"; // Throughput
} else if (delivered > 999) { const deliveredText = T.ingame.statistics.shapesDisplayUnits.second.replace(
context.font = "bold 20px GameFont"; "<shapes>",
formatBigNumber(goals.requires[i].amount)
);
if (goals.definitions.length > 3) {
context.font = "bold 6px GameFont";
context.fillStyle = "#64666e";
context.textAlign = "left";
const offset = context.measureText(deliveredText).width;
context.fillText(deliveredText, textOffsetX + x - offset / 2, textOffsetY + y - 6);
} else if (goals.definitions.length > 2) {
context.font = "bold 6px GameFont";
context.fillStyle = "#64666e";
context.textAlign = "left";
const offset = context.measureText(deliveredText).width;
context.fillText(deliveredText, textOffsetX + x - offset / 2, textOffsetY + y - 4);
} else if (goals.definitions.length > 1) {
context.font = "bold 8px GameFont";
context.fillStyle = "#64666e";
context.textAlign = "left";
const offset = context.measureText(deliveredText).width;
context.fillText(deliveredText, textOffsetX + x - offset / 2, textOffsetY + y);
} else {
context.font = "bold 12px GameFont";
context.fillStyle = "#64666e";
context.textAlign = "left";
const offset = context.measureText(deliveredText).width;
context.fillText(deliveredText, textOffsetX + 86 - offset / 2, textOffsetY + 40);
}
} else { } else {
context.font = "bold 25px GameFont"; const textRequired = "/" + formatBigNumber(goals.requires[i].amount);
} const textDelivered = formatBigNumber(delivered[i]);
context.fillStyle = "#64666e"; if (goals.definitions.length > 3) {
context.textAlign = "left"; context.font = "6px GameFont";
context.fillText(deliveredText, textOffsetX, textOffsetY); const offsetRequired = context.measureText(textRequired).width;
// Required context.font = "bold 6px GameFont";
context.font = "13px GameFont"; const offsetDelivered = context.measureText(textDelivered).width;
context.fillStyle = "#a4a6b0";
context.fillText("/ " + formatBigNumber(goals.required), textOffsetX, textOffsetY + 13); const totalOffset = offsetDelivered + offsetRequired;
// Delivered
context.fillStyle = "#64666e";
context.fillText(textDelivered, textOffsetX + x - totalOffset / 2, textOffsetY + y - 6);
// Required
context.font = "6px GameFont";
context.fillStyle = "#64666e";
context.fillText(
textRequired,
textOffsetX + x + offsetDelivered - totalOffset / 2,
textOffsetY + y - 6
);
} else if (goals.definitions.length > 2) {
context.font = "6px GameFont";
const offsetRequired = context.measureText(textRequired).width;
context.font = "bold 6px GameFont";
const offsetDelivered = context.measureText(textDelivered).width;
const totalOffset = offsetDelivered + offsetRequired;
// Delivered
context.fillStyle = "#64666e";
context.fillText(textDelivered, textOffsetX + x - totalOffset / 2, textOffsetY + y - 4);
// Required
context.font = "6px GameFont";
context.fillStyle = "#64666e";
context.fillText(
textRequired,
textOffsetX + x + offsetDelivered - totalOffset / 2,
textOffsetY + y - 4
);
} else if (goals.definitions.length > 1) {
context.font = "8px GameFont";
const offsetRequired = context.measureText(textRequired).width;
context.font = "bold 8px GameFont";
const offsetDelivered = context.measureText(textDelivered).width;
const totalOffset = offsetDelivered + offsetRequired;
// Delivered
context.fillStyle = "#64666e";
context.fillText(textDelivered, textOffsetX + x - totalOffset / 2, textOffsetY + y);
// Required
context.font = "8px GameFont";
context.fillStyle = "#64666e";
context.fillText(
textRequired,
textOffsetX + x + offsetDelivered - totalOffset / 2,
textOffsetY + y
);
} else {
// Delivered
if (delivered[i] > 9999) {
context.font = "bold 16px GameFont";
} else if (delivered[i] > 999) {
context.font = "bold 20px GameFont";
} else {
context.font = "bold 25px GameFont";
}
context.fillStyle = "#64666e";
context.textAlign = "left";
context.fillText(textDelivered, textOffsetX + 70, textOffsetY + 37);
// Required
context.font = "13px GameFont";
context.fillStyle = "#a4a6b0";
context.fillText(textRequired, textOffsetX + 70, textOffsetY + 37 + 13);
}
}
} }
// Reward // Reward
@ -169,7 +282,7 @@ export class HubSystem extends GameSystemWithFilter {
// Deliver count // Deliver count
const delivered = this.root.hubGoals.getCurrentGoalDelivered(); const delivered = this.root.hubGoals.getCurrentGoalDelivered();
const deliveredText = "" + formatBigNumber(delivered); const deliveredText = delivered.map(value => formatBigNumber(value));
const dpi = smoothenDpi(globalConfig.shapesSharpness * parameters.zoomLevel); const dpi = smoothenDpi(globalConfig.shapesSharpness * parameters.zoomLevel);
const canvas = parameters.root.buffers.getForKey({ const canvas = parameters.root.buffers.getForKey({