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,
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;
}
/**
* @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,
};
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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();

View File

@ -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");

View File

@ -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<UpgradeRequirement>
* improvement?: number,
* excludePrevious?: boolean
@ -52,11 +54,14 @@ import { MetaItemProducerBuilding } from "../buildings/item_producer";
/** @typedef {Array<TierRequirement>} 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<LevelDefinition>}
*/
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);
}
});
});
}

View File

@ -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) {

View File

@ -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(
"<shapes>",
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(
"<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 {
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({