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:
parent
cc044e2547
commit
596fe59425
@ -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,
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
@ -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 (
|
||||
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.definition
|
||||
this.currentGoal.definitions[i]
|
||||
) / globalConfig.analyticsSliceDurationSeconds
|
||||
);
|
||||
} else {
|
||||
currentGoalDeliverd.push(this.getShapesStored(this.currentGoal.definitions[i]));
|
||||
}
|
||||
}
|
||||
return currentGoalDeliverd;
|
||||
}
|
||||
|
||||
return this.getShapesStored(this.currentGoal.definition);
|
||||
/**
|
||||
* 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 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];
|
||||
const { shapes, requires, reward } = levels[storyIndex];
|
||||
if (shapes) {
|
||||
this.currentGoal = {
|
||||
/** @type {ShapeDefinition} */
|
||||
definition: this.root.shapeDefinitionMgr.getShapeFromShortKey(shape),
|
||||
required,
|
||||
definitions: shapes.map(code => this.root.shapeDefinitionMgr.getShapeFromShortKey(code)),
|
||||
requires: requires,
|
||||
reward,
|
||||
throughputOnly,
|
||||
};
|
||||
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,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
for (let i = 0; i < currentGoal.definitions.length; i++) {
|
||||
console.log(currentGoal);
|
||||
this.internalPinShape({
|
||||
key: currentKey,
|
||||
key: currentGoal.definitions[i].getHash(),
|
||||
canUnpin: false,
|
||||
className: "goal",
|
||||
throughputOnly: currentGoal.throughputOnly,
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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,
|
||||
/**
|
||||
* @typedef {{
|
||||
* shapes: String[],
|
||||
* requires: Array<{
|
||||
* throughputOnly?: Boolean,
|
||||
* amount: Number,
|
||||
* }>,
|
||||
* reward: enumHubGoalRewards,
|
||||
* throughputOnly?: boolean
|
||||
* }} 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,123 +410,174 @@ 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
|
||||
shapes: [
|
||||
chinaShapes
|
||||
? "Su----Su:RwRwRwRw:Cu----Cu:CwCwCwCw"
|
||||
: "CcRcCcRc:RwCwRwCw:Sr--Sw--:CyCyCyCy",
|
||||
required: 25000,
|
||||
],
|
||||
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 }) => {
|
||||
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);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return levelDefinitions;
|
||||
|
||||
@ -75,12 +75,14 @@ export class ConstantSignalSystem extends GameSystemWithFilter {
|
||||
}
|
||||
|
||||
if (this.root.gameMode.hasHub()) {
|
||||
for (let i = 0; i < this.root.hubGoals.currentGoal.definitions.length; i++) {
|
||||
items.push(
|
||||
this.root.shapeDefinitionMgr.getShapeItemFromDefinition(
|
||||
this.root.hubGoals.currentGoal.definition
|
||||
this.root.hubGoals.currentGoal.definitions[i]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.root.hud.parts.pinnedShapes) {
|
||||
items.push(
|
||||
|
||||
@ -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 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
|
||||
);
|
||||
|
||||
const textOffsetX = 70;
|
||||
const textOffsetY = 61;
|
||||
const textOffsetX = 0;
|
||||
const textOffsetY = 24;
|
||||
|
||||
if (goals.throughputOnly) {
|
||||
if (goals.requires[i].throughputOnly) {
|
||||
// Throughput
|
||||
const deliveredText = T.ingame.statistics.shapesDisplayUnits.second.replace(
|
||||
"<shapes>",
|
||||
formatBigNumber(goals.required)
|
||||
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";
|
||||
context.fillText(deliveredText, textOffsetX, textOffsetY);
|
||||
const offset = context.measureText(deliveredText).width;
|
||||
context.fillText(deliveredText, textOffsetX + 86 - offset / 2, textOffsetY + 40);
|
||||
}
|
||||
} else {
|
||||
// Deliver count
|
||||
const delivered = this.root.hubGoals.getCurrentGoalDelivered();
|
||||
const deliveredText = "" + formatBigNumber(delivered);
|
||||
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;
|
||||
|
||||
if (delivered > 9999) {
|
||||
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 > 999) {
|
||||
} else if (delivered[i] > 999) {
|
||||
context.font = "bold 20px GameFont";
|
||||
} else {
|
||||
context.font = "bold 25px GameFont";
|
||||
}
|
||||
context.fillStyle = "#64666e";
|
||||
context.textAlign = "left";
|
||||
context.fillText(deliveredText, textOffsetX, textOffsetY);
|
||||
context.fillText(textDelivered, textOffsetX + 70, textOffsetY + 37);
|
||||
|
||||
// Required
|
||||
context.font = "13px GameFont";
|
||||
context.fillStyle = "#a4a6b0";
|
||||
context.fillText("/ " + formatBigNumber(goals.required), textOffsetX, textOffsetY + 13);
|
||||
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({
|
||||
|
||||
Loading…
Reference in New Issue
Block a user