mirror of
https://github.com/tobspr/shapez.io.git
synced 2025-06-13 13:04:03 +00:00
Add unstacker building
This commit is contained in:
parent
c6bf070287
commit
c23e4ff50b
@ -1,15 +1,17 @@
|
||||
import { globalConfig } from "../../core/config";
|
||||
import { enumDirection, Vector } from "../../core/vector";
|
||||
import { ItemAcceptorComponent, enumItemAcceptorItemFilter } from "../components/item_acceptor";
|
||||
import { ItemEjectorComponent } from "../components/item_ejector";
|
||||
import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor";
|
||||
import { Entity } from "../entity";
|
||||
import { MetaBuilding } from "../meta_building";
|
||||
import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
|
||||
import { GameRoot } from "../root";
|
||||
import { enumHubGoalRewards } from "../tutorial_goals";
|
||||
import { formatItemsPerSecond } from "../../core/utils";
|
||||
import { T } from "../../translations";
|
||||
|
||||
/** @enum {string} */
|
||||
export const enumStackerVariants = { unstacker: "unstacker" };
|
||||
|
||||
export class MetaStackerBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
super("stacker");
|
||||
@ -29,10 +31,24 @@ export class MetaStackerBuilding extends MetaBuilding {
|
||||
* @returns {Array<[string, string]>}
|
||||
*/
|
||||
getAdditionalStatistics(root, variant) {
|
||||
const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.stacker);
|
||||
const speed = root.hubGoals.getProcessorBaseSpeed(
|
||||
variant === enumStackerVariants.unstacker
|
||||
? enumItemProcessorTypes.unstacker
|
||||
: enumItemProcessorTypes.stacker
|
||||
);
|
||||
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GameRoot} root
|
||||
*/
|
||||
getAvailableVariants(root) {
|
||||
if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_unstacker)) {
|
||||
return [defaultBuildingVariant, enumStackerVariants.unstacker];
|
||||
}
|
||||
return super.getAvailableVariants(root);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GameRoot} root
|
||||
*/
|
||||
@ -74,4 +90,54 @@ export class MetaStackerBuilding extends MetaBuilding {
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Entity} entity
|
||||
* @param {number} rotationVariant
|
||||
* @param {string} variant
|
||||
*/
|
||||
updateVariants(entity, rotationVariant, variant) {
|
||||
switch (variant) {
|
||||
case defaultBuildingVariant: {
|
||||
entity.components.ItemEjector.setSlots([
|
||||
{ pos: new Vector(0, 0), direction: enumDirection.top },
|
||||
]);
|
||||
entity.components.ItemAcceptor.setSlots([
|
||||
{
|
||||
pos: new Vector(0, 0),
|
||||
directions: [enumDirection.bottom],
|
||||
filter: enumItemAcceptorItemFilter.shape,
|
||||
},
|
||||
{
|
||||
pos: new Vector(1, 0),
|
||||
directions: [enumDirection.bottom],
|
||||
filter: enumItemAcceptorItemFilter.shape,
|
||||
},
|
||||
]);
|
||||
entity.components.ItemProcessor.type = enumItemProcessorTypes.stacker;
|
||||
entity.components.ItemProcessor.inputsPerCharge = 2;
|
||||
break;
|
||||
}
|
||||
case enumStackerVariants.unstacker: {
|
||||
entity.components.ItemEjector.setSlots([
|
||||
{ pos: new Vector(0, 0), direction: enumDirection.top },
|
||||
{ pos: new Vector(1, 0), direction: enumDirection.top },
|
||||
]);
|
||||
entity.components.ItemAcceptor.setSlots([
|
||||
{
|
||||
pos: new Vector(0, 0),
|
||||
directions: [enumDirection.bottom],
|
||||
filter: enumItemAcceptorItemFilter.shape,
|
||||
},
|
||||
]);
|
||||
entity.components.ItemProcessor.type = enumItemProcessorTypes.unstacker;
|
||||
entity.components.ItemProcessor.inputsPerCharge = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assertAlways(false, "Unknown stacker variant: " + variant);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ export const enumItemProcessorTypes = {
|
||||
rotater: "rotater",
|
||||
rotaterCCW: "rotaterCCW",
|
||||
stacker: "stacker",
|
||||
unstacker: "unstacker",
|
||||
trash: "trash",
|
||||
mixer: "mixer",
|
||||
painter: "painter",
|
||||
|
@ -407,7 +407,8 @@ export class HubGoals extends BasicSerializableObject {
|
||||
case enumItemProcessorTypes.cutterQuad:
|
||||
case enumItemProcessorTypes.rotater:
|
||||
case enumItemProcessorTypes.rotaterCCW:
|
||||
case enumItemProcessorTypes.stacker: {
|
||||
case enumItemProcessorTypes.stacker:
|
||||
case enumItemProcessorTypes.unstacker: {
|
||||
assert(
|
||||
globalConfig.buildingSpeeds[processorType],
|
||||
"Processor type has no speed set in globalConfig.buildingSpeeds: " + processorType
|
||||
|
@ -465,6 +465,43 @@ export class ShapeDefinition extends BasicSerializableObject {
|
||||
return new ShapeDefinition({ layers: newLayers });
|
||||
}
|
||||
|
||||
/**
|
||||
* Stacks the given shape definition on top.
|
||||
*/
|
||||
cloneAndUnstack() {
|
||||
const lowerLayers = this.internalCloneLayers();
|
||||
|
||||
if (this.isEntirelyEmpty()) {
|
||||
assert(false, "Can not stack entirely empty definition");
|
||||
}
|
||||
|
||||
// Check if there is only one layer
|
||||
if (this.layers.length === 1) {
|
||||
return [new ShapeDefinition({ layers: lowerLayers })];
|
||||
}
|
||||
|
||||
let upperLayers = [];
|
||||
|
||||
layerCheck:
|
||||
for (let i = lowerLayers.length - 1; i >= 0; --i) {
|
||||
const layerToCheck = lowerLayers[i];
|
||||
|
||||
for (let quadrantIndex = 0; quadrantIndex < 4; ++quadrantIndex) {
|
||||
// Check for a layer with items on it to remove
|
||||
if (layerToCheck[quadrantIndex]) {
|
||||
upperLayers.push(layerToCheck);
|
||||
lowerLayers[i] = [null, null, null, null];
|
||||
break layerCheck;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
new ShapeDefinition({ layers: lowerLayers }),
|
||||
new ShapeDefinition({ layers: upperLayers }),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones the shape and colors everything in the given color
|
||||
* @param {enumColors} color
|
||||
|
@ -144,6 +144,21 @@ export class ShapeDefinitionManager extends BasicSerializableObject {
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a definition for stacking the upper definition onto the lower one
|
||||
* @param {ShapeDefinition} definition
|
||||
* @returns {[ShapeDefinition, ShapeDefinition]}
|
||||
*/
|
||||
shapeActionUnstack(definition) {
|
||||
const key = "unstack:" + definition.getHash();
|
||||
if (this.operationCache[key]) {
|
||||
return /** @type {[ShapeDefinition, ShapeDefinition]} */ (this.operationCache[key]);
|
||||
}
|
||||
|
||||
const unstacked = definition.cloneAndUnstack();
|
||||
return /** @type {[ShapeDefinition, ShapeDefinition]} */ (this.operationCache[key] = unstacked);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a definition for painting it with the given color
|
||||
* @param {ShapeDefinition} definition
|
||||
|
@ -23,7 +23,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
// First of all, process the current recipe
|
||||
processorComp.secondsUntilEject = Math_max(
|
||||
0,
|
||||
processorComp.secondsUntilEject - this.root.dynamicTickrate.deltaSeconds
|
||||
processorComp.secondsUntilEject - this.root.dynamicTickrate.deltaSeconds,
|
||||
);
|
||||
|
||||
// Check if we have any finished items we can eject
|
||||
@ -196,7 +196,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
|
||||
const stackedDefinition = this.root.shapeDefinitionMgr.shapeActionStack(
|
||||
lowerItem.definition,
|
||||
upperItem.definition
|
||||
upperItem.definition,
|
||||
);
|
||||
outItems.push({
|
||||
item: new ShapeItem(stackedDefinition),
|
||||
@ -204,6 +204,23 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
break;
|
||||
}
|
||||
|
||||
// UNSTACKER
|
||||
|
||||
case enumItemProcessorTypes.unstacker: {
|
||||
const item = /** @type {ShapeItem} */ (itemsBySlot[0].item);
|
||||
assert(item instanceof ShapeItem, "Input for unstack is not a shape");
|
||||
|
||||
const unstackedDefinitions = this.root.shapeDefinitionMgr.shapeActionUnstack(item.definition);
|
||||
|
||||
for (let i = 0; i < unstackedDefinitions.length; ++i) {
|
||||
outItems.push({
|
||||
item: new ShapeItem(unstackedDefinitions[i]),
|
||||
requiredSlot: i,
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// TRASH
|
||||
|
||||
case enumItemProcessorTypes.trash: {
|
||||
@ -244,7 +261,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
|
||||
const colorizedDefinition = this.root.shapeDefinitionMgr.shapeActionPaintWith(
|
||||
shapeItem.definition,
|
||||
colorItem.color
|
||||
colorItem.color,
|
||||
);
|
||||
|
||||
outItems.push({
|
||||
@ -267,12 +284,12 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
|
||||
const colorizedDefinition1 = this.root.shapeDefinitionMgr.shapeActionPaintWith(
|
||||
shapeItem1.definition,
|
||||
colorItem.color
|
||||
colorItem.color,
|
||||
);
|
||||
|
||||
const colorizedDefinition2 = this.root.shapeDefinitionMgr.shapeActionPaintWith(
|
||||
shapeItem2.definition,
|
||||
colorItem.color
|
||||
colorItem.color,
|
||||
);
|
||||
outItems.push({
|
||||
item: new ShapeItem(colorizedDefinition1),
|
||||
@ -302,7 +319,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
|
||||
const colorizedDefinition = this.root.shapeDefinitionMgr.shapeActionPaintWith4Colors(
|
||||
shapeItem.definition,
|
||||
[colorItem2.color, colorItem3.color, colorItem4.color, colorItem1.color]
|
||||
[colorItem2.color, colorItem3.color, colorItem4.color, colorItem1.color],
|
||||
);
|
||||
|
||||
outItems.push({
|
||||
|
@ -11,6 +11,7 @@ export const enumHubGoalRewards = {
|
||||
reward_painter: "reward_painter",
|
||||
reward_mixer: "reward_mixer",
|
||||
reward_stacker: "reward_stacker",
|
||||
reward_unstacker: "reward_unstacker",
|
||||
reward_splitter: "reward_splitter",
|
||||
reward_tunnel: "reward_tunnel",
|
||||
|
||||
|
@ -341,6 +341,9 @@ buildings:
|
||||
default:
|
||||
name: &stacker Stacker
|
||||
description: Stacks both items. If they can not be merged, the right item is placed above the left item.
|
||||
unstacker:
|
||||
name: Unstacker
|
||||
description: Takes the top most shape off of a stack and outputs it onto the right.
|
||||
|
||||
mixer:
|
||||
default:
|
||||
|
Loading…
Reference in New Issue
Block a user