From 596fe59425236563986971bc19c60672b00fdaeb Mon Sep 17 00:00:00 2001 From: DJ1TJOO Date: Tue, 29 Jun 2021 00:21:09 +0200 Subject: [PATCH] Added up to four hub goals at one time --- src/js/game/buildings/hub.js | 15 ++ src/js/game/hub_goals.js | 74 ++++-- src/js/game/hud/parts/interactive_tutorial.js | 4 +- src/js/game/hud/parts/pinned_shapes.js | 39 ++-- src/js/game/hud/parts/sandbox_controller.js | 4 +- src/js/game/hud/parts/shop.js | 6 +- src/js/game/modes/regular.js | 213 +++++++++++------- src/js/game/systems/constant_signal.js | 12 +- src/js/game/systems/hub.js | 191 ++++++++++++---- 9 files changed, 393 insertions(+), 165 deletions(-) diff --git a/src/js/game/buildings/hub.js b/src/js/game/buildings/hub.js index b9929b31..35ee5862 100644 --- a/src/js/game/buildings/hub.js +++ b/src/js/game/buildings/hub.js @@ -57,6 +57,21 @@ export class MetaHubBuilding extends MetaBuilding { type: enumPinSlotType.logicalEjector, 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, + }, ], }) ); diff --git a/src/js/game/hub_goals.js b/src/js/game/hub_goals.js index 8351775e..adea22de 100644 --- a/src/js/game/hub_goals.js +++ b/src/js/game/hub_goals.js @@ -105,6 +105,18 @@ export class HubGoals extends BasicSerializableObject { this.upgradeImprovements[key] = 1; } + /** + * @type {{ + * definitions: ShapeDefinition[], + * requires: Array<{ + * throughputOnly?: Boolean, + * amount: Number, + * }>, + * reward: enumHubGoalRewards, + * }} + */ + this.currentGoal = null; + this.computeNextGoal(); // 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 */ getCurrentGoalDelivered() { - if (this.currentGoal.throughputOnly) { - return ( - this.root.productionAnalytics.getCurrentShapeRateRaw( - enumAnalyticsDataSource.delivered, - this.currentGoal.definition - ) / globalConfig.analyticsSliceDurationSeconds - ); + const currentGoalDeliverd = []; + + for (let i = 0; i < this.currentGoal.definitions.length; i++) { + if (this.currentGoal.requires[i].throughputOnly) { + currentGoalDeliverd.push( + 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); // Check if we have enough for the next level - if ( - this.getCurrentGoalDelivered() >= this.currentGoal.required || - (G_IS_DEV && globalConfig.debug.rewardsInstant) - ) { + if (this.isGoalCompleted() || (G_IS_DEV && globalConfig.debug.rewardsInstant)) { if (!this.isEndOfDemoReached()) { this.onGoalCompleted(); } @@ -231,24 +258,23 @@ export class HubGoals extends BasicSerializableObject { const storyIndex = this.level - 1; const levels = this.root.gameMode.getLevelDefinitions(); if (storyIndex < levels.length) { - const { shape, required, reward, throughputOnly } = levels[storyIndex]; - this.currentGoal = { - /** @type {ShapeDefinition} */ - definition: this.root.shapeDefinitionMgr.getShapeFromShortKey(shape), - required, - reward, - throughputOnly, - }; - return; + const { shapes, requires, reward } = levels[storyIndex]; + if (shapes) { + this.currentGoal = { + definitions: shapes.map(code => this.root.shapeDefinitionMgr.getShapeFromShortKey(code)), + requires: requires, + reward, + }; + return; + } } //Floor Required amount to remove confusion const required = Math.min(200, Math.floor(4 + (this.level - 27) * 0.25)); this.currentGoal = { - definition: this.computeFreeplayShape(this.level), - required, + definitions: [this.computeFreeplayShape(this.level)], + requires: [{ throughputOnly: true, amount: required }], reward: enumHubGoalRewards.no_reward_freeplay, - throughputOnly: true, }; } diff --git a/src/js/game/hud/parts/interactive_tutorial.js b/src/js/game/hud/parts/interactive_tutorial.js index e48a77fb..ec0ffacc 100644 --- a/src/js/game/hud/parts/interactive_tutorial.js +++ b/src/js/game/hud/parts/interactive_tutorial.js @@ -24,7 +24,7 @@ const tutorialsByLevel = [ // 1.2. connect to hub { 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 { @@ -70,7 +70,7 @@ const tutorialsByLevel = [ id: "3_1_rectangles", condition: /** @param {GameRoot} root */ root => // 4 miners placed above rectangles and 10 delivered - root.hubGoals.getCurrentGoalDelivered() < 10 || + root.hubGoals.getCurrentGoalDelivered()[0] < 10 || root.entityMgr.getAllWithComponent(MinerComponent).filter(entity => { const tile = entity.components.StaticMapEntity.origin; const below = root.map.getLowerLayerContentXY(tile.x, tile.y); diff --git a/src/js/game/hud/parts/pinned_shapes.js b/src/js/game/hud/parts/pinned_shapes.js index a53ecbe5..2323f5dd 100644 --- a/src/js/game/hud/parts/pinned_shapes.js +++ b/src/js/game/hud/parts/pinned_shapes.js @@ -103,8 +103,11 @@ export class HUDPinnedShapes extends BaseHUDPart { * @param {string} key */ findGoalValueForShape(key) { - if (key === this.root.hubGoals.currentGoal.definition.getHash()) { - return this.root.hubGoals.currentGoal.required; + const goalIndex = this.root.hubGoals.currentGoal.definitions.findIndex( + shape => shape.getHash() === key + ); + if (goalIndex > -1) { + return this.root.hubGoals.currentGoal.requires[goalIndex].amount; } if (key === this.root.gameMode.getBlueprintShapeKey()) { return null; @@ -138,10 +141,10 @@ export class HUDPinnedShapes extends BaseHUDPart { * @param {string} key */ isShapePinned(key) { - if ( - key === this.root.hubGoals.currentGoal.definition.getHash() || - key === this.root.gameMode.getBlueprintShapeKey() - ) { + const goalIndex = this.root.hubGoals.currentGoal.definitions.findIndex( + shape => shape.getHash() === key + ); + if (goalIndex > -1 || key === this.root.gameMode.getBlueprintShapeKey()) { // This is a "special" shape which is always pinned return true; } @@ -154,7 +157,6 @@ export class HUDPinnedShapes extends BaseHUDPart { */ rerenderFull() { const currentGoal = this.root.hubGoals.currentGoal; - const currentKey = currentGoal.definition.getHash(); // First, remove all old shapes for (let i = 0; i < this.handles.length; ++i) { @@ -171,12 +173,15 @@ export class HUDPinnedShapes extends BaseHUDPart { this.handles = []; // Pin story goal - this.internalPinShape({ - key: currentKey, - canUnpin: false, - className: "goal", - throughputOnly: currentGoal.throughputOnly, - }); + for (let i = 0; i < currentGoal.definitions.length; i++) { + console.log(currentGoal); + this.internalPinShape({ + key: currentGoal.definitions[i].getHash(), + canUnpin: false, + className: "goal", + throughputOnly: currentGoal.requires[i].throughputOnly, + }); + } // Pin blueprint shape as well if (this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_blueprints)) { @@ -190,7 +195,8 @@ export class HUDPinnedShapes extends BaseHUDPart { // Pin manually pinned shapes for (let i = 0; i < this.pinnedShapes.length; ++i) { const key = this.pinnedShapes[i]; - if (key !== currentKey) { + const goalIndex = currentGoal.definitions.findIndex(shape => shape.getHash() === key); + if (goalIndex < 0) { this.internalPinShape({ key }); } } @@ -308,7 +314,10 @@ export class HUDPinnedShapes extends BaseHUDPart { */ pinNewShape(definition) { 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 return; } diff --git a/src/js/game/hud/parts/sandbox_controller.js b/src/js/game/hud/parts/sandbox_controller.js index 3689fa36..3436b59d 100644 --- a/src/js/game/hud/parts/sandbox_controller.js +++ b/src/js/game/hud/parts/sandbox_controller.js @@ -116,7 +116,9 @@ export class HUDSandboxController extends BaseHUDPart { hubGoals.computeNextGoal(); // 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) { this.root.hud.parts.pinnedShapes.rerenderFull(); diff --git a/src/js/game/hud/parts/shop.js b/src/js/game/hud/parts/shop.js index 96521898..0b8a64ec 100644 --- a/src/js/game/hud/parts/shop.js +++ b/src/js/game/hud/parts/shop.js @@ -123,8 +123,10 @@ export class HUDShop extends BaseHUDPart { viewInfoButton.classList.add("showInfo"); container.appendChild(viewInfoButton); - const currentGoalShape = this.root.hubGoals.currentGoal.definition.getHash(); - if (shape === currentGoalShape) { + const goalIndex = this.root.hubGoals.currentGoal.definitions.findIndex( + goal => goal.getHash() === shape + ); + if (goalIndex > -1) { pinButton.classList.add("isGoal"); } else if (this.root.hud.parts.pinnedShapes.isShapePinned(shape)) { pinButton.classList.add("alreadyPinned"); diff --git a/src/js/game/modes/regular.js b/src/js/game/modes/regular.js index ca0e8672..ca102819 100644 --- a/src/js/game/modes/regular.js +++ b/src/js/game/modes/regular.js @@ -39,12 +39,14 @@ import { queryParamOptions } from "../../core/query_parameters"; import { MetaBlockBuilding } from "../buildings/block"; import { MetaItemProducerBuilding } from "../buildings/item_producer"; -/** @typedef {{ +/** + * @typedef {{ * shape: string, * amount: number * }} UpgradeRequirement */ -/** @typedef {{ +/** + * @typedef {{ * required: Array * improvement?: number, * excludePrevious?: boolean @@ -52,11 +54,14 @@ import { MetaItemProducerBuilding } from "../buildings/item_producer"; /** @typedef {Array} UpgradeTiers */ -/** @typedef {{ - * shape: string, - * required: number, - * reward: enumHubGoalRewards, - * throughputOnly?: boolean +/** + * @typedef {{ + * shapes: String[], + * requires: Array<{ + * throughputOnly?: Boolean, + * amount: Number, + * }>, + * reward: enumHubGoalRewards, * }} LevelDefinition */ export const rocketShape = "CbCuCbCu:Sr------:--CrSrCr:CwCwCwCw"; @@ -287,105 +292,108 @@ function generateUpgrades(limitedVersion = false) { * @param {boolean} limitedVersion */ export function generateLevelDefinitions(limitedVersion = false) { + /** + * @type {Array} + */ const levelDefinitions = [ // 1 // Circle { - shape: "CuCuCuCu", // belts t1 - required: 30, + shapes: ["CuCuCuCu"], // belts t1 + requires: [{ amount: 30 }], reward: enumHubGoalRewards.reward_cutter_and_trash, }, // 2 // Cutter { - shape: "----CuCu", // - required: 40, + shapes: ["----CuCu"], // + requires: [{ amount: 40 }], reward: enumHubGoalRewards.no_reward, }, // 3 // Rectangle { - shape: "RuRuRuRu", // miners t1 - required: 70, + shapes: ["RuRuRuRu"], // miners t1 + requires: [{ amount: 70 }], reward: enumHubGoalRewards.reward_balancer, }, // 4 { - shape: "RuRu----", // processors t2 - required: 70, + shapes: ["RuRu----"], // processors t2 + requires: [{ amount: 70 }], reward: enumHubGoalRewards.reward_rotater, }, // 5 // Rotater { - shape: "Cu----Cu", // belts t2 - required: 170, + shapes: ["Cu----Cu"], // belts t2 + requires: [{ amount: 170 }], reward: enumHubGoalRewards.reward_tunnel, }, // 6 { - shape: "Cu------", // miners t2 - required: 270, + shapes: ["Cu------"], // miners t2 + requires: [{ amount: 270 }], reward: enumHubGoalRewards.reward_painter, }, // 7 // Painter { - shape: "CrCrCrCr", // unused - required: 300, + shapes: ["CrCrCrCr"], // unused + requires: [{ amount: 300 }], reward: enumHubGoalRewards.reward_rotater_ccw, }, // 8 { - shape: "RbRb----", // painter t2 - required: 480, + shapes: ["RbRb----"], // painter t2 + requires: [{ amount: 480 }], reward: enumHubGoalRewards.reward_mixer, }, // 9 // Mixing (purple) { - shape: "CpCpCpCp", // belts t3 - required: 600, + shapes: ["CpCpCpCp"], // belts t3 + requires: [{ amount: 600 }], reward: enumHubGoalRewards.reward_merger, }, // 10 - // STACKER: Star shape + cyan + // STACKER: Star shapes + cyan { - shape: "ScScScSc", // miners t3 - required: 800, + shapes: ["ScScScSc"], // miners t3 + requires: [{ amount: 800 }], reward: enumHubGoalRewards.reward_stacker, }, // 11 // Chainable miner { - shape: "CgScScCg", // processors t3 - required: 1000, + shapes: ["CgScScCg"], // processors t3 + requires: [{ amount: 1000 }], reward: enumHubGoalRewards.reward_miner_chainable, }, // 12 // Blueprints { - shape: "CbCbCbRb:CwCwCwCw", - required: 1000, + shapes: ["CbCbCbRb:CwCwCwCw"], + requires: [{ amount: 1000 }], reward: enumHubGoalRewards.reward_blueprints, }, // 13 // Tunnel Tier 2 { - shape: chinaShapes ? "CuCuCuCu:CwCwCwCw:Sb--Sr--" : "RpRpRpRp:CwCwCwCw", // painting t3 - required: 3800, + shapes: [chinaShapes ? "CuCuCuCu:CwCwCwCw:Sb--Sr--" : "RpRpRpRp:CwCwCwCw"], // painting t3 + requires: [{ amount: 3800 }], reward: enumHubGoalRewards.reward_underground_belt_tier_2, }, @@ -393,8 +401,8 @@ export function generateLevelDefinitions(limitedVersion = false) { ...(limitedVersion ? [ { - shape: chinaShapes ? "CuCuCuCu:CwCwCwCw:Sb--Sr--" : "RpRpRpRp:CwCwCwCw", - required: 0, + shapes: [chinaShapes ? "CuCuCuCu:CwCwCwCw:Sb--Sr--" : "RpRpRpRp:CwCwCwCw"], + requires: [{ amount: 0 }], reward: enumHubGoalRewards.reward_demo_end, }, ] @@ -402,122 +410,173 @@ export function generateLevelDefinitions(limitedVersion = false) { // 14 // Belt reader { - shape: "--Cg----:--Cr----", // unused - required: 8, // Per second! + shapes: ["--Cg----:--Cr----"], // unused + requires: [{ amount: 8, throughputOnly: true }], // Per second! reward: enumHubGoalRewards.reward_belt_reader, - throughputOnly: true, }, // 15 // Storage { - shape: "SrSrSrSr:CyCyCyCy", // unused - required: 10000, + shapes: ["SrSrSrSr:CyCyCyCy"], // unused + requires: [{ amount: 10000 }], reward: enumHubGoalRewards.reward_storage, }, // 16 // Quad Cutter { - shape: "SrSrSrSr:CyCyCyCy:SwSwSwSw", // belts t4 (two variants) - required: 6000, + shapes: ["SrSrSrSr:CyCyCyCy:SwSwSwSw"], // belts t4 (two variants) + requires: [{ amount: 6000 }], reward: enumHubGoalRewards.reward_cutter_quad, }, // 17 // Double painter { - shape: chinaShapes - ? "CyCyCyCy:CyCyCyCy:RyRyRyRy:RuRuRuRu" - : "CbRbRbCb:CwCwCwCw:WbWbWbWb", // miner t4 (two variants) - required: 20000, + shapes: [ + chinaShapes ? "CyCyCyCy:CyCyCyCy:RyRyRyRy:RuRuRuRu" : "CbRbRbCb:CwCwCwCw:WbWbWbWb", + ], // miner t4 (two variants) + requires: [{ amount: 20000 }], reward: enumHubGoalRewards.reward_painter_double, }, // 18 // Rotater (180deg) { - shape: "Sg----Sg:CgCgCgCg:--CyCy--", // unused - required: 20000, + shapes: ["Sg----Sg:CgCgCgCg:--CyCy--"], // unused + requires: [{ amount: 20000 }], reward: enumHubGoalRewards.reward_rotater_180, }, // 19 // Compact splitter { - shape: "CpRpCp--:SwSwSwSw", - required: 25000, + shapes: ["CpRpCp--:SwSwSwSw"], + requires: [{ amount: 25000 }], reward: enumHubGoalRewards.reward_splitter, }, // 20 // WIRES { - shape: finalGameShape, - required: 25000, + shapes: [finalGameShape], + requires: [{ amount: 25000 }], reward: enumHubGoalRewards.reward_wires_painter_and_levers, }, // 21 // Filter { - shape: "CrCwCrCw:CwCrCwCr:CrCwCrCw:CwCrCwCr", - required: 25000, + shapes: ["CrCwCrCw:CwCrCwCr:CrCwCrCw:CwCrCwCr"], + requires: [{ amount: 25000 }], reward: enumHubGoalRewards.reward_filter, }, // 22 // Constant signal { - shape: chinaShapes - ? "RrSySrSy:RyCrCwCr:CyCyRyCy" - : "Cg----Cr:Cw----Cw:Sy------:Cy----Cy", - required: 25000, + shapes: [ + chinaShapes ? "RrSySrSy:RyCrCwCr:CyCyRyCy" : "Cg----Cr:Cw----Cw:Sy------:Cy----Cy", + ], + requires: [{ amount: 25000 }], reward: enumHubGoalRewards.reward_constant_signal, }, // 23 // Display { - shape: chinaShapes - ? "CrCrCrCr:CwCwCwCw:WwWwWwWw:CrCrCrCr" - : "CcSyCcSy:SyCcSyCc:CcSyCcSy", - required: 25000, + shapes: [ + chinaShapes ? "CrCrCrCr:CwCwCwCw:WwWwWwWw:CrCrCrCr" : "CcSyCcSy:SyCcSyCc:CcSyCcSy", + ], + requires: [{ amount: 25000 }], reward: enumHubGoalRewards.reward_display, }, // 24 Logic gates { - shape: chinaShapes - ? "Su----Su:RwRwRwRw:Cu----Cu:CwCwCwCw" - : "CcRcCcRc:RwCwRwCw:Sr--Sw--:CyCyCyCy", - required: 25000, + shapes: [ + chinaShapes + ? "Su----Su:RwRwRwRw:Cu----Cu:CwCwCwCw" + : "CcRcCcRc:RwCwRwCw:Sr--Sw--:CyCyCyCy", + ], + requires: [{ amount: 25000 }], reward: enumHubGoalRewards.reward_logic_gates, }, // 25 Virtual Processing { - shape: "Rg--Rg--:CwRwCwRw:--Rg--Rg", - required: 25000, + shapes: ["Rg--Rg--:CwRwCwRw:--Rg--Rg"], + requires: [{ amount: 25000 }], reward: enumHubGoalRewards.reward_virtual_processing, }, // 26 Freeplay { - shape: "CbCuCbCu:Sr------:--CrSrCr:CwCwCwCw", - required: 50000, + shapes: ["CbCuCbCu:Sr------:--CrSrCr:CwCwCwCw"], + 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, }, ]), ]; if (G_IS_DEV) { - levelDefinitions.forEach(({ shape }) => { - try { - ShapeDefinition.fromShortKey(shape); - } catch (ex) { - throw new Error("Invalid tutorial goal: '" + ex + "' for shape" + shape); - } + levelDefinitions.forEach(({ shapes }) => { + if (!shapes) return; + + shapes.forEach(shape => { + try { + ShapeDefinition.fromShortKey(shape); + } catch (ex) { + throw new Error("Invalid tutorial goal: '" + ex + "' for shape" + shape); + } + }); }); } diff --git a/src/js/game/systems/constant_signal.js b/src/js/game/systems/constant_signal.js index 5fabb80e..47637330 100644 --- a/src/js/game/systems/constant_signal.js +++ b/src/js/game/systems/constant_signal.js @@ -75,11 +75,13 @@ export class ConstantSignalSystem extends GameSystemWithFilter { } if (this.root.gameMode.hasHub()) { - items.push( - this.root.shapeDefinitionMgr.getShapeItemFromDefinition( - this.root.hubGoals.currentGoal.definition - ) - ); + for (let i = 0; i < this.root.hubGoals.currentGoal.definitions.length; i++) { + items.push( + this.root.shapeDefinitionMgr.getShapeItemFromDefinition( + this.root.hubGoals.currentGoal.definitions[i] + ) + ); + } } if (this.root.hud.parts.pinnedShapes) { diff --git a/src/js/game/systems/hub.js b/src/js/game/systems/hub.js index 2002b66e..03c85429 100644 --- a/src/js/game/systems/hub.js +++ b/src/js/game/systems/hub.js @@ -35,13 +35,20 @@ export class HubSystem extends GameSystemWithFilter { // Set hub goal const entity = this.allEntities[i]; const pinsComp = entity.components.WiredPins; - pinsComp.slots[0].value = this.root.shapeDefinitionMgr.getShapeItemFromDefinition( - this.root.hubGoals.currentGoal.definition - ); + for (let i = 0; i < pinsComp.slots.length; i++) { + 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 {CanvasRenderingContext2D} context * @param {number} w @@ -49,7 +56,7 @@ export class HubSystem extends GameSystemWithFilter { * @param {number} 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); @@ -76,45 +83,151 @@ export class HubSystem extends GameSystemWithFilter { return; } - const definition = this.root.hubGoals.currentGoal.definition; - definition.drawCentered(45, 58, parameters, 36); - const goals = this.root.hubGoals.currentGoal; - - const textOffsetX = 70; - const textOffsetY = 61; - - if (goals.throughputOnly) { - // Throughput - const deliveredText = T.ingame.statistics.shapesDisplayUnits.second.replace( - "", - formatBigNumber(goals.required) + const delivered = this.root.hubGoals.getCurrentGoalDelivered(); + for (let i = 0; i < goals.definitions.length; i++) { + const x = + 45 + + (goals.definitions.length > 3 + ? 22 * i - 14 + : goals.definitions.length > 2 + ? 28 * i - 8 + : 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"; - context.fillStyle = "#64666e"; - context.textAlign = "left"; - context.fillText(deliveredText, textOffsetX, textOffsetY); - } else { - // Deliver count - const delivered = this.root.hubGoals.getCurrentGoalDelivered(); - const deliveredText = "" + formatBigNumber(delivered); + const textOffsetX = 0; + const textOffsetY = 24; - if (delivered > 9999) { - context.font = "bold 16px GameFont"; - } else if (delivered > 999) { - context.font = "bold 20px GameFont"; + if (goals.requires[i].throughputOnly) { + // Throughput + const deliveredText = T.ingame.statistics.shapesDisplayUnits.second.replace( + "", + 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 { - context.font = "bold 25px GameFont"; - } - context.fillStyle = "#64666e"; - context.textAlign = "left"; - context.fillText(deliveredText, textOffsetX, textOffsetY); + const textRequired = "/" + formatBigNumber(goals.requires[i].amount); + const textDelivered = formatBigNumber(delivered[i]); + if (goals.definitions.length > 3) { + context.font = "6px GameFont"; + const offsetRequired = context.measureText(textRequired).width; - // Required - context.font = "13px GameFont"; - context.fillStyle = "#a4a6b0"; - context.fillText("/ " + formatBigNumber(goals.required), textOffsetX, textOffsetY + 13); + 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 - 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 @@ -169,7 +282,7 @@ export class HubSystem extends GameSystemWithFilter { // Deliver count 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 canvas = parameters.root.buffers.getForKey({