mirror of
https://github.com/tobspr/shapez.io.git
synced 2025-06-13 13:04:03 +00:00
Fixed Branch
This commit is contained in:
parent
0146aa91bb
commit
b94f60c5d9
BIN
res_raw/sprites/blueprints/wireless_display-remote_control.png
Normal file
BIN
res_raw/sprites/blueprints/wireless_display-remote_control.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.6 KiB |
BIN
res_raw/sprites/blueprints/wireless_display.png
Normal file
BIN
res_raw/sprites/blueprints/wireless_display.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
BIN
res_raw/sprites/buildings/wireless_display-remote_control.png
Normal file
BIN
res_raw/sprites/buildings/wireless_display-remote_control.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.5 KiB |
BIN
res_raw/sprites/buildings/wireless_display.png
Normal file
BIN
res_raw/sprites/buildings/wireless_display.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
@ -1,5 +1,5 @@
|
||||
$buildings: belt, cutter, miner, mixer, painter, rotater, balancer, stacker, trash, underground_belt, wire,
|
||||
constant_signal, logic_gate, lever, filter, wire_tunnel, display, virtual_processor, reader, storage,
|
||||
constant_signal, logic_gate, lever, filter, wire_tunnel, display, wireless_display, virtual_processor, reader, storage,
|
||||
transistor, analyzer, comparator, item_producer;
|
||||
|
||||
@each $building in $buildings {
|
||||
@ -11,7 +11,7 @@ $buildings: belt, cutter, miner, mixer, painter, rotater, balancer, stacker, tra
|
||||
|
||||
$buildingsAndVariants: belt, balancer, underground_belt, underground_belt-tier2, miner, miner-chainable,
|
||||
cutter, cutter-quad, rotater, rotater-ccw, stacker, mixer, painter-double, painter-quad, trash, storage,
|
||||
reader, rotater-rotate180, display, constant_signal, wire, wire_tunnel, logic_gate-or, logic_gate-not,
|
||||
reader, rotater-rotate180, display, wireless_display, wireless_display-remote_control, constant_signal, wire, wire_tunnel, logic_gate-or, logic_gate-not,
|
||||
logic_gate-xor, analyzer, virtual_processor-rotater, virtual_processor-unstacker, item_producer,
|
||||
virtual_processor-stacker, virtual_processor-painter, wire-second, painter, painter-mirrored, comparator;
|
||||
@each $building in $buildingsAndVariants {
|
||||
|
||||
87
src/js/game/buildings/wireless_display.js
Normal file
87
src/js/game/buildings/wireless_display.js
Normal file
@ -0,0 +1,87 @@
|
||||
import { enumDirection, Vector } from "../../core/vector";
|
||||
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
|
||||
import { Entity } from "../entity";
|
||||
import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
|
||||
import { GameRoot } from "../root";
|
||||
import { WirelessDisplayComponent } from "../components/wireless_display";
|
||||
import { enumHubGoalRewards } from "../tutorial_goals";
|
||||
import { formatItemsPerSecond, generateMatrixRotations } from "../../core/utils";
|
||||
|
||||
|
||||
/** @enum {string} */
|
||||
export const enumWirelessDisplayVariants = {
|
||||
remote_control: "remote_control",
|
||||
};
|
||||
|
||||
const overlayMatrices = {
|
||||
[defaultBuildingVariant]: null,
|
||||
[enumWirelessDisplayVariants.remote_control]: generateMatrixRotations([0, 1, 0, 0, 1, 1, 0, 1, 0]),
|
||||
};
|
||||
|
||||
export class MetaWirelessDisplayBuilding extends MetaBuilding {
|
||||
constructor() {
|
||||
super("wireless_display");
|
||||
}
|
||||
|
||||
getSilhouetteColor() {
|
||||
return "#aaaaaa";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GameRoot} root
|
||||
*/
|
||||
getIsUnlocked(root) {
|
||||
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_display);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GameRoot} root
|
||||
*/
|
||||
getAvailableVariants(root) {
|
||||
let available = [defaultBuildingVariant];
|
||||
|
||||
if (true || root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_display)) {
|
||||
available.push(enumWirelessDisplayVariants.remote_control);
|
||||
}
|
||||
|
||||
return available;
|
||||
}
|
||||
|
||||
getDimensions() {
|
||||
return new Vector(1, 1);
|
||||
}
|
||||
|
||||
getShowWiresLayerPreview() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the entity at the given location
|
||||
* @param {Entity} entity
|
||||
*/
|
||||
setupEntityComponents(entity) {
|
||||
entity.addComponent(new WirelessDisplayComponent({}));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Entity} entity
|
||||
* @param {number} rotationVariant
|
||||
* @param {string} variant
|
||||
*/
|
||||
updateVariants(entity, rotationVariant, variant) {
|
||||
if (variant == enumWirelessDisplayVariants.remote_control && !entity.components.WiredPins) {
|
||||
entity.addComponent(
|
||||
new WiredPinsComponent({
|
||||
slots: [
|
||||
{
|
||||
pos: new Vector(0, 0),
|
||||
direction: enumDirection.bottom,
|
||||
type: enumPinSlotType.logicalAcceptor,
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -19,6 +19,8 @@ import { DisplayComponent } from "./components/display";
|
||||
import { BeltReaderComponent } from "./components/belt_reader";
|
||||
import { FilterComponent } from "./components/filter";
|
||||
import { ItemProducerComponent } from "./components/item_producer";
|
||||
import { WirelessDisplayComponent } from "./components/wireless_display";
|
||||
import { WirelessCodeComponent } from "./components/wireless_code";
|
||||
|
||||
export function initComponentRegistry() {
|
||||
gComponentRegistry.register(StaticMapEntityComponent);
|
||||
@ -38,9 +40,11 @@ export function initComponentRegistry() {
|
||||
gComponentRegistry.register(LeverComponent);
|
||||
gComponentRegistry.register(WireTunnelComponent);
|
||||
gComponentRegistry.register(DisplayComponent);
|
||||
gComponentRegistry.register(WirelessDisplayComponent);
|
||||
gComponentRegistry.register(BeltReaderComponent);
|
||||
gComponentRegistry.register(FilterComponent);
|
||||
gComponentRegistry.register(ItemProducerComponent);
|
||||
gComponentRegistry.register(WirelessCodeComponent);
|
||||
|
||||
// IMPORTANT ^^^^^ UPDATE ENTITY COMPONENT STORAGE AFTERWARDS
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
|
||||
import { Component } from "../component";
|
||||
|
||||
export class WireTunnelComponent extends Component {
|
||||
|
||||
23
src/js/game/components/wireless_code.js
Normal file
23
src/js/game/components/wireless_code.js
Normal file
@ -0,0 +1,23 @@
|
||||
import { Component } from "../component";
|
||||
import { types } from "../../savegame/serialization";
|
||||
|
||||
export class WirelessCodeComponent extends Component {
|
||||
static getId() {
|
||||
return "WirelessCode";
|
||||
}
|
||||
|
||||
static getSchema() {
|
||||
return {
|
||||
wireless_code: types.string
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {object} id
|
||||
*/
|
||||
constructor(id) {
|
||||
super();
|
||||
this.wireless_code = id;
|
||||
}
|
||||
}
|
||||
36
src/js/game/components/wireless_display.js
Normal file
36
src/js/game/components/wireless_display.js
Normal file
@ -0,0 +1,36 @@
|
||||
import { Component } from "../component";
|
||||
import { types } from "../../savegame/serialization";
|
||||
import { BaseItem } from "../base_item";
|
||||
import { typeItemSingleton } from "../item_resolver";
|
||||
|
||||
export class WirelessDisplayComponent extends Component {
|
||||
static getId() {
|
||||
return "WirelessDisplay";
|
||||
}
|
||||
|
||||
static getSchema() {
|
||||
return {
|
||||
signal: types.nullable(typeItemSingleton),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the current state to another component
|
||||
* @param {WirelessDisplayComponent} otherComponent
|
||||
*/
|
||||
copyAdditionalStateTo(otherComponent) {
|
||||
otherComponent.signal = this.signal;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {object} param0
|
||||
* @param {BaseItem=} param0.signal The signal to store
|
||||
*/
|
||||
constructor({ signal = null }) {
|
||||
super();
|
||||
this.signal = signal;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -89,7 +89,6 @@ export class GameCore {
|
||||
this.root.savegame = savegame;
|
||||
this.root.gameWidth = this.app.screenWidth;
|
||||
this.root.gameHeight = this.app.screenHeight;
|
||||
|
||||
// Initialize canvas element & context
|
||||
this.internalInitCanvas();
|
||||
|
||||
|
||||
@ -96,6 +96,7 @@ export class Entity extends BasicSerializableObject {
|
||||
rotation: staticComp.rotation,
|
||||
rotationVariant: buildingData.rotationVariant,
|
||||
variant: buildingData.variant,
|
||||
wireless_code: this.components.WirelessCode,
|
||||
});
|
||||
|
||||
for (const key in this.components) {
|
||||
|
||||
@ -19,6 +19,8 @@ import { DisplayComponent } from "./components/display";
|
||||
import { BeltReaderComponent } from "./components/belt_reader";
|
||||
import { FilterComponent } from "./components/filter";
|
||||
import { ItemProducerComponent } from "./components/item_producer";
|
||||
import { WirelessDisplayComponent } from "./components/wireless_display";
|
||||
import { WirelessCodeComponent } from "./components/wireless_code";
|
||||
/* typehints:end */
|
||||
|
||||
/**
|
||||
@ -80,6 +82,9 @@ export class EntityComponentStorage {
|
||||
/** @type {DisplayComponent} */
|
||||
this.Display;
|
||||
|
||||
/** @type {WirelessDisplayComponent} */
|
||||
this.WirelessDisplay;
|
||||
|
||||
/** @type {BeltReaderComponent} */
|
||||
this.BeltReader;
|
||||
|
||||
@ -89,6 +94,9 @@ export class EntityComponentStorage {
|
||||
/** @type {ItemProducerComponent} */
|
||||
this.ItemProducer;
|
||||
|
||||
/** @type {WirelessCodeComponent} */
|
||||
this.WirelessCode;
|
||||
|
||||
/* typehints:end */
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@ import { ConstantSignalSystem } from "./systems/constant_signal";
|
||||
import { LogicGateSystem } from "./systems/logic_gate";
|
||||
import { LeverSystem } from "./systems/lever";
|
||||
import { DisplaySystem } from "./systems/display";
|
||||
import { WirelessDisplaySystem } from "./systems/wireless_display";
|
||||
import { ItemProcessorOverlaysSystem } from "./systems/item_processor_overlays";
|
||||
import { BeltReaderSystem } from "./systems/belt_reader";
|
||||
import { FilterSystem } from "./systems/filter";
|
||||
@ -88,6 +89,9 @@ export class GameSystemManager {
|
||||
/** @type {DisplaySystem} */
|
||||
display: null,
|
||||
|
||||
/** @type {WirelessDisplaySystem} */
|
||||
wirelessDisplay: null,
|
||||
|
||||
/** @type {ItemProcessorOverlaysSystem} */
|
||||
itemProcessorOverlays: null,
|
||||
|
||||
@ -162,6 +166,7 @@ export class GameSystemManager {
|
||||
add("beltReader", BeltReaderSystem);
|
||||
|
||||
add("display", DisplaySystem);
|
||||
add("wirelessDisplay", WirelessDisplaySystem);
|
||||
|
||||
add("itemProcessorOverlays", ItemProcessorOverlaysSystem);
|
||||
|
||||
|
||||
@ -238,7 +238,8 @@ export class HubGoals extends BasicSerializableObject {
|
||||
return;
|
||||
}
|
||||
|
||||
const required = Math.min(200, 4 + (this.level - 27) * 0.25);
|
||||
//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,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { MetaBeltBuilding } from "../../buildings/belt";
|
||||
import { MetaCutterBuilding } from "../../buildings/cutter";
|
||||
import { MetaDisplayBuilding } from "../../buildings/display";
|
||||
import { MetaWirelessDisplayBuilding } from "../../buildings/wireless_display";
|
||||
import { MetaFilterBuilding } from "../../buildings/filter";
|
||||
import { MetaLeverBuilding } from "../../buildings/lever";
|
||||
import { MetaMinerBuilding } from "../../buildings/miner";
|
||||
@ -39,6 +40,7 @@ export class HUDBuildingsToolbar extends HUDBaseToolbar {
|
||||
MetaLeverBuilding,
|
||||
MetaFilterBuilding,
|
||||
MetaDisplayBuilding,
|
||||
MetaWirelessDisplayBuilding,
|
||||
],
|
||||
visibilityCondition: () =>
|
||||
!this.root.camera.getIsMapOverlayActive() && this.root.currentLayer === "regular",
|
||||
|
||||
@ -14,6 +14,7 @@ import { KEYMAPPINGS } from "../../key_action_mapper";
|
||||
import { THEME } from "../../theme";
|
||||
import { enumHubGoalRewards } from "../../tutorial_goals";
|
||||
import { Blueprint } from "../../blueprint";
|
||||
import { drawRotatedSprite } from "../../../core/draw_utils";
|
||||
|
||||
const logger = createLogger("hud/mass_selector");
|
||||
|
||||
@ -304,16 +305,9 @@ export class HUDMassSelector extends BaseHUDPart {
|
||||
renderedUids.add(uid);
|
||||
|
||||
const staticComp = contents.components.StaticMapEntity;
|
||||
const bounds = staticComp.getTileSpaceBounds();
|
||||
parameters.context.beginRoundedRect(
|
||||
bounds.x * globalConfig.tileSize + boundsBorder,
|
||||
bounds.y * globalConfig.tileSize + boundsBorder,
|
||||
bounds.w * globalConfig.tileSize - 2 * boundsBorder,
|
||||
bounds.h * globalConfig.tileSize - 2 * boundsBorder,
|
||||
2
|
||||
);
|
||||
parameters.context.fill();
|
||||
staticComp.drawSpriteOnBoundsClipped(parameters, staticComp.getBlueprintSprite(), 0);
|
||||
}
|
||||
parameters.context.globalAlpha = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -322,15 +316,8 @@ export class HUDMassSelector extends BaseHUDPart {
|
||||
this.selectedUids.forEach(uid => {
|
||||
const entity = this.root.entityMgr.findByUid(uid);
|
||||
const staticComp = entity.components.StaticMapEntity;
|
||||
const bounds = staticComp.getTileSpaceBounds();
|
||||
parameters.context.beginRoundedRect(
|
||||
bounds.x * globalConfig.tileSize + boundsBorder,
|
||||
bounds.y * globalConfig.tileSize + boundsBorder,
|
||||
bounds.w * globalConfig.tileSize - 2 * boundsBorder,
|
||||
bounds.h * globalConfig.tileSize - 2 * boundsBorder,
|
||||
2
|
||||
);
|
||||
parameters.context.fill();
|
||||
|
||||
staticComp.drawSpriteOnBoundsClipped(parameters, staticComp.getBlueprintSprite(), 0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import { MetaComparatorBuilding } from "../../buildings/comparator";
|
||||
import { MetaReaderBuilding } from "../../buildings/reader";
|
||||
import { MetaFilterBuilding } from "../../buildings/filter";
|
||||
import { MetaDisplayBuilding } from "../../buildings/display";
|
||||
import { MetaWirelessDisplayBuilding } from "../../buildings/wireless_display";
|
||||
import { MetaStorageBuilding } from "../../buildings/storage";
|
||||
|
||||
export class HUDWiresToolbar extends HUDBaseToolbar {
|
||||
@ -32,6 +33,7 @@ export class HUDWiresToolbar extends HUDBaseToolbar {
|
||||
MetaLeverBuilding,
|
||||
MetaFilterBuilding,
|
||||
MetaDisplayBuilding,
|
||||
MetaWirelessDisplayBuilding,
|
||||
],
|
||||
visibilityCondition: () =>
|
||||
!this.root.camera.getIsMapOverlayActive() && this.root.currentLayer === "wires",
|
||||
|
||||
@ -65,6 +65,7 @@ export const KEYMAPPINGS = {
|
||||
lever: { keyCode: key("I") },
|
||||
filter: { keyCode: key("O") },
|
||||
display: { keyCode: key("P") },
|
||||
wireless_display: { keyCode: key("K") },
|
||||
|
||||
// Wires toolbar
|
||||
wire: { keyCode: key("1") },
|
||||
|
||||
@ -193,6 +193,9 @@ export class GameLogic {
|
||||
* @param {enumDirection} param0.edge The edge to check for
|
||||
*/
|
||||
computeWireEdgeStatus({ wireVariant, tile, edge }) {
|
||||
/**
|
||||
* @type {Vector}
|
||||
*/
|
||||
const offset = enumDirectionToVector[edge];
|
||||
const targetTile = tile.add(offset);
|
||||
|
||||
@ -240,10 +243,10 @@ export class GameLogic {
|
||||
|
||||
const targetStaticComp = targetEntity.components.StaticMapEntity;
|
||||
|
||||
// Check if its a crossing
|
||||
// Check if its a tunnel
|
||||
const wireTunnelComp = targetEntity.components.WireTunnel;
|
||||
if (wireTunnelComp) {
|
||||
return true;
|
||||
return wireTunnelComp.CanConnectWorld(targetStaticComp, offset);
|
||||
}
|
||||
|
||||
// Check if its a wire
|
||||
|
||||
@ -68,6 +68,7 @@ export class MapChunkView extends MapChunk {
|
||||
systems.staticMapEntities.drawChunk(parameters, this);
|
||||
systems.lever.drawChunk(parameters, this);
|
||||
systems.display.drawChunk(parameters, this);
|
||||
systems.wirelessDisplay.drawChunk(parameters, this);
|
||||
systems.storage.drawChunk(parameters, this);
|
||||
systems.itemProcessorOverlays.drawChunk(parameters, this);
|
||||
}
|
||||
|
||||
@ -199,7 +199,7 @@ export class MetaBuilding {
|
||||
* @param {number} param0.rotationVariant Rotation variant
|
||||
* @param {string} param0.variant
|
||||
*/
|
||||
createEntity({ root, origin, rotation, originalRotation, rotationVariant, variant }) {
|
||||
createEntity({ root, origin, rotation, originalRotation, rotationVariant, variant, wireless_code }) {
|
||||
const entity = new Entity(root);
|
||||
entity.layer = this.getLayer();
|
||||
entity.addComponent(
|
||||
@ -213,6 +213,11 @@ export class MetaBuilding {
|
||||
);
|
||||
this.setupEntityComponents(entity, root);
|
||||
this.updateVariants(entity, rotationVariant, variant);
|
||||
if (entity.components.WirelessDisplay && wireless_code) {
|
||||
if (!entity.components.WirelessCode) {
|
||||
entity.components.WirelessCode = wireless_code;
|
||||
}
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
||||
@ -26,6 +26,7 @@ import { enumUndergroundBeltVariants, MetaUndergroundBeltBuilding } from "./buil
|
||||
import { enumVirtualProcessorVariants, MetaVirtualProcessorBuilding } from "./buildings/virtual_processor";
|
||||
import { MetaWireBuilding } from "./buildings/wire";
|
||||
import { MetaWireTunnelBuilding } from "./buildings/wire_tunnel";
|
||||
import { MetaWirelessDisplayBuilding, enumWirelessDisplayVariants } from "./buildings/wireless_display";
|
||||
import { buildBuildingCodeCache, gBuildingVariants, registerBuildingVariant } from "./building_codes";
|
||||
import { enumWireVariant } from "./components/wire";
|
||||
import { KEYMAPPINGS } from "./key_action_mapper";
|
||||
@ -59,6 +60,7 @@ export function initMetaBuildingRegistry() {
|
||||
gMetaBuildingRegistry.register(MetaAnalyzerBuilding);
|
||||
gMetaBuildingRegistry.register(MetaComparatorBuilding);
|
||||
gMetaBuildingRegistry.register(MetaItemProducerBuilding);
|
||||
gMetaBuildingRegistry.register(MetaWirelessDisplayBuilding);
|
||||
|
||||
// Belt
|
||||
registerBuildingVariant(1, MetaBeltBuilding, defaultBuildingVariant, 0);
|
||||
@ -165,6 +167,10 @@ export function initMetaBuildingRegistry() {
|
||||
// Item producer
|
||||
registerBuildingVariant(61, MetaItemProducerBuilding);
|
||||
|
||||
// Wireless Display
|
||||
registerBuildingVariant(62, MetaWirelessDisplayBuilding);
|
||||
registerBuildingVariant(63, MetaWirelessDisplayBuilding, enumWirelessDisplayVariants.remote_control);
|
||||
|
||||
// Propagate instances
|
||||
for (const key in gBuildingVariants) {
|
||||
gBuildingVariants[key].metaInstance = gMetaBuildingRegistry.findByClass(
|
||||
|
||||
@ -99,7 +99,6 @@ export class ConstantSignalSystem extends GameSystemWithFilter {
|
||||
}
|
||||
|
||||
if (itemInput.chosenItem) {
|
||||
console.log(itemInput.chosenItem);
|
||||
constantComp.signal = itemInput.chosenItem;
|
||||
} else {
|
||||
constantComp.signal = this.parseSignalCode(signalValueInput.getValue());
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { globalConfig } from "../../core/config";
|
||||
import { Loader } from "../../core/loader";
|
||||
import { smoothPulse } from "../../core/utils";
|
||||
import { round1DigitLocalized, smoothPulse } from "../../core/utils";
|
||||
import { enumItemProcessorRequirements, enumItemProcessorTypes } from "../components/item_processor";
|
||||
import { Entity } from "../entity";
|
||||
import { GameSystem } from "../game_system";
|
||||
@ -92,7 +92,7 @@ export class ItemProcessorOverlaysSystem extends GameSystem {
|
||||
parameters.context.textAlign = "center";
|
||||
parameters.context.font = "bold 10px GameFont";
|
||||
parameters.context.fillText(
|
||||
"" + Math.round(readerComp.lastThroughput * 10) / 10,
|
||||
round1DigitLocalized(readerComp.lastThroughput),
|
||||
(staticComp.origin.x + 0.5) * globalConfig.tileSize,
|
||||
(staticComp.origin.y + 0.62) * globalConfig.tileSize
|
||||
);
|
||||
|
||||
@ -316,6 +316,11 @@ export class WireSystem extends GameSystemWithFilter {
|
||||
}
|
||||
}
|
||||
|
||||
const tunnelComp = nextEntity.components.WireTunnel;
|
||||
if (tunnelComp) {
|
||||
//const outputDir = tunnelComp.GetOutputDirection(staticComp, offset);
|
||||
}
|
||||
|
||||
if (newSearchTile) {
|
||||
// Find new surrounding wire targets
|
||||
const newTargets = this.findSurroundingWireTargets(
|
||||
@ -364,7 +369,7 @@ export class WireSystem extends GameSystemWithFilter {
|
||||
* @param {Vector} initialTile
|
||||
* @param {Array<enumDirection>} directions
|
||||
* @param {WireNetwork} network
|
||||
* @param {enumWireVariant=} variantMask Only accept connections to this mask
|
||||
* @param {enumWireVariant} variantMask Only accept connections to this mask
|
||||
* @returns {Array<any>}
|
||||
*/
|
||||
findSurroundingWireTargets(initialTile, directions, network, variantMask = null) {
|
||||
@ -386,9 +391,6 @@ export class WireSystem extends GameSystemWithFilter {
|
||||
const offset = enumDirectionToVector[direction];
|
||||
const initialSearchTile = initialTile.add(offset);
|
||||
|
||||
// Store which tunnels we already visited to avoid infinite loops
|
||||
const visitedTunnels = new Set();
|
||||
|
||||
// First, find the initial connected entities
|
||||
const initialContents = this.root.map.getLayersContentsMultipleXY(
|
||||
initialSearchTile.x,
|
||||
@ -396,17 +398,18 @@ export class WireSystem extends GameSystemWithFilter {
|
||||
);
|
||||
|
||||
// Link the initial tile to the initial entities, since it may change
|
||||
/** @type {Array<{entity: Entity, tile: Vector}>} */
|
||||
/** @type {Array<{entity: Entity, tile: Vector, dir: Vector}>} */
|
||||
const contents = [];
|
||||
for (let j = 0; j < initialContents.length; ++j) {
|
||||
contents.push({
|
||||
entity: initialContents[j],
|
||||
tile: initialSearchTile,
|
||||
dir: offset,
|
||||
});
|
||||
}
|
||||
|
||||
for (let k = 0; k < contents.length; ++k) {
|
||||
const { entity, tile } = contents[k];
|
||||
const { entity, tile, dir } = contents[k];
|
||||
const wireComp = entity.components.Wire;
|
||||
|
||||
// Check for wire
|
||||
@ -438,8 +441,17 @@ export class WireSystem extends GameSystemWithFilter {
|
||||
}
|
||||
|
||||
// Check if the direction (inverted) matches
|
||||
const pinDirection = staticComp.localDirectionToWorld(slot.direction);
|
||||
if (pinDirection !== enumInvertedDirections[direction]) {
|
||||
// const pinDirection = staticComp.localDirectionToWorld(slot.direction);
|
||||
// if (pinDirection !== enumInvertedDirections[direction]) {
|
||||
// continue;
|
||||
// }
|
||||
// /**
|
||||
// * @type {Vector}
|
||||
// */
|
||||
const worldDir = staticComp.localDirectionToWorld(slot.direction);
|
||||
const invDir = enumInvertedDirections[worldDir];
|
||||
const pinDirection = enumDirectionToVector[invDir];
|
||||
if (!pinDirection.equals(dir)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -458,14 +470,20 @@ export class WireSystem extends GameSystemWithFilter {
|
||||
// Check if it's a tunnel, if so, go to the forwarded item
|
||||
const tunnelComp = entity.components.WireTunnel;
|
||||
if (tunnelComp) {
|
||||
if (visitedTunnels.has(entity.uid)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const staticComp = entity.components.StaticMapEntity;
|
||||
|
||||
//const localDir = staticComp.worldToLocalTile(tile.sub(offset));
|
||||
//staticComp.localDirectionToWorld();
|
||||
const outputDir = tunnelComp.GetOutputDirection(staticComp, dir);
|
||||
if (!outputDir) {
|
||||
continue;
|
||||
}
|
||||
const forwardedTile = staticComp.origin.add(outputDir);
|
||||
|
||||
//TODO: Alter to Allow for different tunnel Types
|
||||
// Compute where this tunnel connects to
|
||||
const forwardedTile = staticComp.origin.add(offset);
|
||||
//const forwardedTile = staticComp.origin.add(offset);
|
||||
VERBOSE_WIRES &&
|
||||
logger.log(
|
||||
" Found tunnel",
|
||||
@ -487,6 +505,7 @@ export class WireSystem extends GameSystemWithFilter {
|
||||
contents.push({
|
||||
entity: connectedContents[h],
|
||||
tile: forwardedTile,
|
||||
dir: outputDir,
|
||||
});
|
||||
}
|
||||
|
||||
@ -497,9 +516,6 @@ export class WireSystem extends GameSystemWithFilter {
|
||||
if (network.tunnels.indexOf(entity) < 0) {
|
||||
network.tunnels.push(entity);
|
||||
}
|
||||
|
||||
// Remember this tunnel
|
||||
visitedTunnels.add(entity.uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,9 +189,10 @@ export class WiredPinsSystem extends GameSystemWithFilter {
|
||||
);
|
||||
|
||||
if (staticComp.getMetaBuilding().getRenderPins()) {
|
||||
this.sprite = this.pinSprites[slot.type];
|
||||
drawRotatedSprite({
|
||||
parameters,
|
||||
sprite: this.pinSprites[slot.type],
|
||||
sprite: this.sprite,
|
||||
x: worldPos.x,
|
||||
y: worldPos.y,
|
||||
angle: effectiveRotation,
|
||||
|
||||
273
src/js/game/systems/wireless_display.js
Normal file
273
src/js/game/systems/wireless_display.js
Normal file
@ -0,0 +1,273 @@
|
||||
import { globalConfig } from "../../core/config";
|
||||
import { Loader } from "../../core/loader";
|
||||
import { BaseItem } from "../base_item";
|
||||
import { enumColors } from "../colors";
|
||||
import { WirelessDisplayComponent } from "../components/wireless_display";
|
||||
import { GameSystemWithFilter } from "../game_system_with_filter";
|
||||
import { isTrueItem } from "../items/boolean_item";
|
||||
import { ColorItem, COLOR_ITEM_SINGLETONS } from "../items/color_item";
|
||||
import { MapChunkView } from "../map_chunk_view";
|
||||
import { THIRDPARTY_URLS } from "../../core/config";
|
||||
import { DialogWithForm } from "../../core/modal_dialog_elements";
|
||||
import { FormElementInput, FormElementItemChooser } from "../../core/modal_dialog_forms";
|
||||
import { fillInLinkIntoTranslation } from "../../core/utils";
|
||||
import { T } from "../../translations";
|
||||
import { Entity } from "../entity";
|
||||
import { WirelessCodeComponent } from "../components/wireless_code";
|
||||
import { THEME} from "../theme";
|
||||
|
||||
export class WirelessDisplaySystem extends GameSystemWithFilter {
|
||||
constructor(root) {
|
||||
super(root, [WirelessDisplayComponent]);
|
||||
|
||||
this.root.signals.entityManuallyPlaced.add(this.channelSignalValue, this);
|
||||
|
||||
/** @type {Object<string, import("../../core/draw_utils").AtlasSprite>} */
|
||||
this.displaySprites = {};
|
||||
|
||||
for (const colorId in enumColors) {
|
||||
if (colorId === enumColors.uncolored) {
|
||||
continue;
|
||||
}
|
||||
this.displaySprites[colorId] = Loader.getSprite("sprites/wires/display/" + colorId + ".png");
|
||||
}
|
||||
|
||||
this.wirelessMachineList = {};
|
||||
|
||||
this.displayNumber = 0;
|
||||
this.entityCount = 0;
|
||||
}
|
||||
|
||||
update() {
|
||||
if (this.entityCount != this.allEntities.length) {
|
||||
for (let i = 0; i < this.allEntities.length; i++) {
|
||||
const entity = this.allEntities[i];
|
||||
if (entity.components.WirelessDisplay && entity.components.WiredPins && entity.components.WirelessCode && !this.wirelessMachineList[entity.components.WirelessCode]) {
|
||||
this.wirelessMachineList[entity.components.WirelessCode["wireless_code"]] = entity;
|
||||
}
|
||||
}
|
||||
this.entityCount = this.allEntities.length;
|
||||
}
|
||||
const mousePos = this.root.app.mousePosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks the entity to enter a valid signal code
|
||||
* @param {Entity} entity
|
||||
*/
|
||||
channelSignalValue(entity) {
|
||||
if (entity.components.WirelessDisplay) {
|
||||
// Ok, query, but also save the uid because it could get stale
|
||||
const uid = entity.uid;
|
||||
|
||||
const signalValueInput = new FormElementInput({
|
||||
id: "channelValue",
|
||||
label: fillInLinkIntoTranslation(T.dialogs.editChannel.descShortKey, THIRDPARTY_URLS.shapeViewer),
|
||||
placeholder: "",
|
||||
defaultValue: "",
|
||||
validator: val => val,
|
||||
});
|
||||
|
||||
const channeldialog = new DialogWithForm({
|
||||
app: this.root.app,
|
||||
title: T.dialogs.editChannel.title,
|
||||
desc: T.dialogs.editChannel.descItems,
|
||||
formElements: [signalValueInput],
|
||||
buttons: ["cancel:bad:escape", "ok:good:enter"],
|
||||
closeButton: false,
|
||||
});
|
||||
this.root.hud.parts.dialogs.internalShowDialog(channeldialog);
|
||||
|
||||
// When confirmed, set the signal
|
||||
const closeHandler = () => {
|
||||
if (!this.root || !this.root.entityMgr) {
|
||||
// Game got stopped
|
||||
return;
|
||||
}
|
||||
|
||||
const entityRef = this.root.entityMgr.findByUid(uid, false);
|
||||
if (!entityRef) {
|
||||
// outdated
|
||||
return;
|
||||
}
|
||||
|
||||
const constantComp = entityRef.components.WirelessDisplay;
|
||||
if (!constantComp) {
|
||||
// no longer interesting
|
||||
return;
|
||||
}
|
||||
|
||||
if (signalValueInput.getValue() && !entity.components.WiredPins) {
|
||||
entity.addComponent(new WirelessCodeComponent(signalValueInput.getValue()));
|
||||
} else if (signalValueInput.getValue() && entity.components.WiredPins) {
|
||||
entity.addComponent(new WirelessCodeComponent(signalValueInput.getValue()));
|
||||
this.wirelessMachineList[entity.components.WirelessCode["wireless_code"]] = entity;
|
||||
}
|
||||
};
|
||||
|
||||
channeldialog.buttonSignals.ok.add(closeHandler);
|
||||
channeldialog.valueChosen.add(closeHandler);
|
||||
|
||||
// When cancelled, destroy the entity again
|
||||
channeldialog.buttonSignals.cancel.add(() => {
|
||||
if (!this.root || !this.root.entityMgr) {
|
||||
// Game got stopped
|
||||
return;
|
||||
}
|
||||
|
||||
const entityRef = this.root.entityMgr.findByUid(uid, false);
|
||||
if (!entityRef) {
|
||||
// outdated
|
||||
return;
|
||||
}
|
||||
|
||||
const constantComp = entityRef.components.WirelessDisplay;
|
||||
if (!constantComp) {
|
||||
// no longer interesting
|
||||
return;
|
||||
}
|
||||
|
||||
this.root.logic.tryDeleteBuilding(entityRef);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the color / value a display should show
|
||||
* @param {BaseItem} value
|
||||
* @returns {BaseItem}
|
||||
*/
|
||||
getDisplayItem(value) {
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (value.getItemType()) {
|
||||
case "boolean": {
|
||||
return isTrueItem(value) ? COLOR_ITEM_SINGLETONS[enumColors.white] : null;
|
||||
}
|
||||
|
||||
case "color": {
|
||||
const item = /**@type {ColorItem} */ (value);
|
||||
return item.color === enumColors.uncolored ? null : item;
|
||||
}
|
||||
|
||||
case "shape": {
|
||||
return value;
|
||||
}
|
||||
|
||||
default:
|
||||
assertAlways(false, "Unknown item type: " + value.getItemType());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the color below the current tile
|
||||
* @returns {number}
|
||||
*/
|
||||
computeColorBelowTile() {
|
||||
const mousePosition = this.root.app.mousePosition;
|
||||
if (!mousePosition) {
|
||||
// Not on screen
|
||||
return null;
|
||||
}
|
||||
|
||||
const worldPos = this.root.camera.screenToWorld(mousePosition);
|
||||
const tile = worldPos.toTileSpace();
|
||||
const contents = this.root.map.getTileContent(tile, "regular");
|
||||
|
||||
if (contents && contents.components.WirelessDisplay) {
|
||||
// We hovered a lower layer, show the color there
|
||||
if (contents && contents.components.WirelessCode && contents.components.WirelessCode.wireless_code) {
|
||||
return contents.components.WirelessCode.wireless_code;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws Text Storked
|
||||
* @param {string} text
|
||||
* @param {number} y
|
||||
* @param {number} x
|
||||
* @param {number=} width
|
||||
*/
|
||||
drawStroked(ctx, text, x, y, width = undefined) {
|
||||
ctx.font = '15px Sans-serif';
|
||||
ctx.strokeStyle = 'black';
|
||||
ctx.lineWidth = 1;
|
||||
ctx.miterLimit=2
|
||||
ctx.strokeText(text, x, y, width);
|
||||
ctx.fillStyle = 'white';
|
||||
ctx.fillText(text, x, y, width);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a given chunk
|
||||
* @param {import("../../core/draw_utils").DrawParameters} parameters
|
||||
* @param {MapChunkView} chunk
|
||||
*/
|
||||
drawChunk(parameters, chunk) {
|
||||
const contents = chunk.containedEntitiesByLayer.regular;
|
||||
for (let i = 0; i < contents.length; ++i) {
|
||||
const entity_a = contents[i];
|
||||
if (entity_a && entity_a.components.WirelessDisplay) {
|
||||
const below = this.computeColorBelowTile();
|
||||
if (below) {
|
||||
// We have something below our tile
|
||||
const mousePosition = this.root.app.mousePosition;
|
||||
const worldPos = this.root.camera.screenToWorld(mousePosition);
|
||||
const tile = worldPos.toTileSpace().toWorldSpace();
|
||||
|
||||
this.drawStroked(parameters.context, below.toString(), worldPos.x + 5, worldPos.y + 5)
|
||||
parameters.context.strokeStyle = THEME.map.colorBlindPickerTile;
|
||||
parameters.context.beginPath();
|
||||
parameters.context.rect(tile.x, tile.y, globalConfig.tileSize, globalConfig.tileSize);
|
||||
parameters.context.stroke();
|
||||
}
|
||||
if (!entity_a.components.WiredPins) {
|
||||
const entity_b = this.wirelessMachineList[entity_a.components.WirelessCode["wireless_code"]];
|
||||
if (entity_b) {
|
||||
if (!this.allEntities.includes(entity_b)) {
|
||||
this.wirelessMachineList[entity_b] = undefined;
|
||||
return;
|
||||
}
|
||||
const origin = entity_a.components.StaticMapEntity.origin;
|
||||
const pinsComp = entity_b.components.WiredPins;
|
||||
const network = pinsComp.slots[0].linkedNetwork;
|
||||
|
||||
if (!network) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const value = this.getDisplayItem(network.currentValue);
|
||||
|
||||
if (!value) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value.getItemType()) {
|
||||
if (value.getItemType() === "color") {
|
||||
this.displaySprites[/** @type {ColorItem} */ (value).color].drawCachedCentered(
|
||||
parameters,
|
||||
(origin.x + 0.5) * globalConfig.tileSize,
|
||||
(origin.y + 0.5) * globalConfig.tileSize,
|
||||
globalConfig.tileSize
|
||||
);
|
||||
} else if (value.getItemType() === "shape") {
|
||||
value.drawItemCenteredClipped(
|
||||
(origin.x + 0.5) * globalConfig.tileSize,
|
||||
(origin.y + 0.5) * globalConfig.tileSize,
|
||||
parameters,
|
||||
30
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
#
|
||||
# Contributing:
|
||||
#
|
||||
# If you want to contribute, please make a pull request on this respository
|
||||
# If you want to contribute, please make a pull request on this repository
|
||||
# and I will have a look.
|
||||
#
|
||||
# Placeholders:
|
||||
@ -30,9 +30,11 @@ steamPage:
|
||||
intro: >-
|
||||
Do you like automation games? Then you are in the right place!
|
||||
|
||||
shapez.io is a relaxed game in which you have to build factories for the automated production of geometric shapes. As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map.
|
||||
shapez.io is a relaxed game in which you have to build factories for the automated production of geometric shapes. As the level increases, the shapes become more and more complex, and you
|
||||
have to spread out on the infinite map.
|
||||
|
||||
And as if that wasn't enough, you also have to produce exponentially more to satisfy the demands - the only thing that helps is scaling! While you only have to process shapes at the beginning, you will later have to color them - by extracting and mixing colors!
|
||||
And as if that wasn't enough, you also have to produce exponentially more to satisfy the demands - the only thing that helps is scaling! While you only have to process shapes at the
|
||||
beginning, you will later have to color them - by extracting and mixing colors!
|
||||
|
||||
Buying the game on Steam gives you access to the full version, but you can also play a demo at shapez.io first and decide later!
|
||||
|
||||
@ -40,7 +42,7 @@ steamPage:
|
||||
advantages:
|
||||
- <b>12 New Levels</b> for a total of 26 levels
|
||||
- <b>18 New Buildings</b> for a fully automated factory!
|
||||
- <b>20 Upgrade Tiers</b> for many hours of fun!
|
||||
- <b>Unlimited Upgrade Tiers</b> for many hours of fun!
|
||||
- <b>Wires Update</b> for an entirely new dimension!
|
||||
- <b>Dark Mode</b>!
|
||||
- Unlimited Savegames
|
||||
@ -79,7 +81,7 @@ global:
|
||||
# How big numbers are rendered, e.g. "10,000"
|
||||
thousandsDivider: ","
|
||||
|
||||
# What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4"
|
||||
# What symbol to use to separate the integer part from the fractional part of a number, e.g. "0.4"
|
||||
decimalSeparator: "."
|
||||
|
||||
# The suffix for large numbers, e.g. 1.3k, 400.2M, etc.
|
||||
@ -255,6 +257,12 @@ dialogs:
|
||||
titleEdit: Edit Marker
|
||||
desc: Give it a meaningful name, you can also include a <strong>short key</strong> of a shape (Which you can generate <link>here</link>)
|
||||
|
||||
editChannel:
|
||||
title: Set Channel
|
||||
descItems: >-
|
||||
Enter used <strong>channel name</strong>
|
||||
descShortKey: or enter new <strong>channel name</strong>
|
||||
|
||||
editSignal:
|
||||
title: Set Signal
|
||||
descItems: >-
|
||||
@ -402,7 +410,9 @@ ingame:
|
||||
waypoints:
|
||||
waypoints: Markers
|
||||
hub: HUB
|
||||
description: Left-click a marker to jump to it, right-click to delete it.<br><br>Press <keybinding> to create a marker from the current view, or <strong>right-click</strong> to create a marker at the selected location.
|
||||
description: >-
|
||||
Left-click a marker to jump to it, right-click to delete it.<br><br>Press <keybinding> to create a marker from the current view, or <strong>right-click</strong> to create a marker at the
|
||||
selected location.
|
||||
creationSuccessNotification: Marker has been created.
|
||||
|
||||
# Shape viewer
|
||||
@ -420,7 +430,8 @@ ingame:
|
||||
Connect the extractor with a <strong>conveyor belt</strong> to your hub!<br><br>Tip: <strong>Click and drag</strong> the belt with your mouse!
|
||||
|
||||
1_3_expand: >-
|
||||
This is <strong>NOT</strong> an idle game! Build more extractors and belts to finish the goal quicker.<br><br>Tip: Hold <strong>SHIFT</strong> to place multiple extractors, and use <strong>R</strong> to rotate them.
|
||||
This is <strong>NOT</strong> an idle game! Build more extractors and belts to finish the goal quicker.<br><br>Tip: Hold <strong>SHIFT</strong> to place multiple extractors, and use
|
||||
<strong>R</strong> to rotate them.
|
||||
|
||||
2_1_place_cutter: >-
|
||||
Now place a <strong>Cutter</strong> to cut the circles in two halves!<br><br>
|
||||
@ -482,7 +493,7 @@ ingame:
|
||||
desc: As many as your heart desires!
|
||||
|
||||
upgrades:
|
||||
title: 20 Upgrade Tiers
|
||||
title: ∞ Upgrade Tiers
|
||||
desc: This demo version has only 5!
|
||||
|
||||
markers:
|
||||
@ -499,7 +510,7 @@ ingame:
|
||||
|
||||
support:
|
||||
title: Support me
|
||||
desc: I develop it in my spare time!
|
||||
desc: I develop the game in my spare time!
|
||||
|
||||
# All shop upgrades
|
||||
shopUpgrades:
|
||||
@ -581,13 +592,13 @@ buildings:
|
||||
|
||||
rotater:
|
||||
default:
|
||||
name: &rotater Rotate
|
||||
name: &rotater Rotator
|
||||
description: Rotates shapes clockwise by 90 degrees.
|
||||
ccw:
|
||||
name: Rotate (CCW)
|
||||
name: Rotator (CCW)
|
||||
description: Rotates shapes counter-clockwise by 90 degrees.
|
||||
rotate180:
|
||||
name: Rotate (180°)
|
||||
name: Rotator (180°)
|
||||
description: Rotates shapes by 180 degrees.
|
||||
|
||||
stacker:
|
||||
@ -636,10 +647,23 @@ buildings:
|
||||
name: *wire
|
||||
description: *wire_desc
|
||||
|
||||
third:
|
||||
name: *wire
|
||||
description: *wire_desc
|
||||
|
||||
wire_tunnel:
|
||||
default:
|
||||
name: &wire_tunnel Wire Crossing
|
||||
name: &wire_tunnel Wire Tunnel
|
||||
description: Allows two wires to cross without connecting to each other.
|
||||
elbow:
|
||||
name: Elbow Tunnel
|
||||
description: Allows a wire to turn a corner without connecting to anything else
|
||||
straight:
|
||||
name: Straight tunnel
|
||||
description: Allows a wire to go straight without connecting to anything else
|
||||
double_elbow:
|
||||
name: Double Elbow Tunnel
|
||||
description: Allows two wires to turn corners without connecting to each other.
|
||||
|
||||
constant_signal:
|
||||
default:
|
||||
@ -684,6 +708,14 @@ buildings:
|
||||
name: &display Display
|
||||
description: Connect a signal to show it on the display - It can be a shape, color or boolean.
|
||||
|
||||
wireless_display:
|
||||
default:
|
||||
name: &wireless_display Wireless Display
|
||||
description: Connect to a channel and if channel connects, it receives the signal coming from Remote Control - Signal can be a shape, color or boolean.
|
||||
remote_control:
|
||||
name: Remote Control
|
||||
description: Connect to a channel and if channel connects, it emits signal to Wireless Control - Signal can be a shape, color or boolean.
|
||||
|
||||
reader:
|
||||
default:
|
||||
name: &reader Belt Reader
|
||||
@ -705,7 +737,7 @@ buildings:
|
||||
description: Virtually cuts the shape into two halves.
|
||||
|
||||
rotater:
|
||||
name: Virtual Rotater
|
||||
name: Virtual Rotator
|
||||
description: Virtually rotates the shape clockwise.
|
||||
|
||||
unstacker:
|
||||
@ -729,16 +761,19 @@ storyRewards:
|
||||
# Those are the rewards gained from completing the store
|
||||
reward_cutter_and_trash:
|
||||
title: Cutting Shapes
|
||||
desc: You just unlocked the <strong>cutter</strong>, which cuts shapes in half from top to bottom <strong>regardless of its orientation</strong>!<br><br>Be sure to get rid of the waste, or otherwise <strong>it will clog and stall</strong> - For this purpose I have given you the <strong>trash</strong>, which destroys everything you put into it!
|
||||
desc: >-
|
||||
You just unlocked the <strong>cutter</strong>, which cuts shapes in half from top to bottom <strong>regardless of its orientation</strong>!<br><br>Be sure to get rid of the waste, or
|
||||
otherwise <strong>it will clog and stall</strong> - For this purpose I have given you the <strong>trash</strong>, which destroys everything you put into it!
|
||||
|
||||
reward_rotater:
|
||||
title: Rotating
|
||||
desc: The <strong>rotater</strong> has been unlocked! It rotates shapes clockwise by 90 degrees.
|
||||
desc: The <strong>rotator</strong> has been unlocked! It rotates shapes clockwise by 90 degrees.
|
||||
|
||||
reward_painter:
|
||||
title: Painting
|
||||
desc: >-
|
||||
The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>colorblind mode</strong> in the settings!
|
||||
The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are
|
||||
colorblind, there is a <strong>colorblind mode</strong> in the settings!
|
||||
|
||||
reward_mixer:
|
||||
title: Color Mixing
|
||||
@ -746,7 +781,9 @@ storyRewards:
|
||||
|
||||
reward_stacker:
|
||||
title: Stacker
|
||||
desc: You can now combine shapes with the <strong>stacker</strong>! Both inputs are combined, and if they can be put next to each other, they will be <strong>fused</strong>. If not, the right input is <strong>stacked on top</strong> of the left input!
|
||||
desc: >-
|
||||
You can now combine shapes with the <strong>stacker</strong>! Both inputs are combined, and if they can be put next to each other, they will be <strong>fused</strong>. If not, the right
|
||||
input is <strong>stacked on top</strong> of the left input!
|
||||
|
||||
reward_balancer:
|
||||
title: Balancer
|
||||
@ -758,7 +795,9 @@ storyRewards:
|
||||
|
||||
reward_rotater_ccw:
|
||||
title: CCW Rotating
|
||||
desc: You have unlocked a variant of the <strong>rotater</strong> - It allows you to rotate shapes counter-clockwise! To build it, select the rotater and <strong>press 'T' to cycle through its variants</strong>!
|
||||
desc: >-
|
||||
You have unlocked a variant of the <strong>rotator</strong> - It allows you to rotate shapes counter-clockwise! To build it, select the rotator and
|
||||
<strong>press 'T' to cycle through its variants</strong>!
|
||||
|
||||
reward_miner_chainable:
|
||||
title: Chaining Extractor
|
||||
@ -791,7 +830,9 @@ storyRewards:
|
||||
|
||||
reward_painter_double:
|
||||
title: Double Painting
|
||||
desc: You have unlocked a variant of the <strong>painter</strong> - It works similar to the regular painter but processes <strong>two shapes at once</strong>, consuming just one color instead of two!
|
||||
desc: >-
|
||||
You have unlocked a variant of the <strong>painter</strong> - It works similar to the regular painter but processes <strong>two shapes at once</strong>, consuming just one color
|
||||
instead of two!
|
||||
|
||||
reward_storage:
|
||||
title: Storage
|
||||
@ -801,11 +842,13 @@ storyRewards:
|
||||
|
||||
reward_blueprints:
|
||||
title: Blueprints
|
||||
desc: You can now <strong>copy and paste</strong> parts of your factory! Select an area (Hold CTRL, then drag with your mouse), and press 'C' to copy it.<br><br>Pasting it is <strong>not free</strong>, you need to produce <strong>blueprint shapes</strong> to afford it! (Those you just delivered).
|
||||
desc: >-
|
||||
You can now <strong>copy and paste</strong> parts of your factory! Select an area (Hold CTRL, then drag with your mouse), and press 'C' to copy it.<br><br>Pasting it is
|
||||
<strong>not free</strong>, you need to produce <strong>blueprint shapes</strong> to afford it! (Those you just delivered).
|
||||
|
||||
reward_rotater_180:
|
||||
title: Rotater (180°)
|
||||
desc: You just unlocked the 180 degrees <strong>rotater</strong>! - It allows you to rotate a shape by 180 degress (Surprise! :D)
|
||||
title: Rotator (180°)
|
||||
desc: You just unlocked the 180 degrees <strong>rotator</strong>! - It allows you to rotate a shape by 180 degrees (Surprise! :D)
|
||||
|
||||
reward_wires_painter_and_levers:
|
||||
title: >-
|
||||
@ -846,18 +889,19 @@ storyRewards:
|
||||
title: Virtual Processing
|
||||
desc: >-
|
||||
I just gave a whole bunch of new buildings which allow you to <strong>simulate the processing of shapes</strong>!<br><br>
|
||||
You can now simulate a cutter, rotater, stacker and more on the wires layer!
|
||||
You can now simulate a cutter, rotator, stacker and more on the wires layer!
|
||||
With this you now have three options to continue the game:<br><br>
|
||||
- Build an <strong>automated machine</strong> to create any possible shape requested by the HUB (I recommend to try it!).<br><br>
|
||||
- Build something cool with wires.<br><br>
|
||||
- Continue to play regulary.<br><br>
|
||||
- Continue to play normally.<br><br>
|
||||
Whatever you choose, remember to have fun!
|
||||
|
||||
# Special reward, which is shown when there is no reward actually
|
||||
no_reward:
|
||||
title: Next level
|
||||
desc: >-
|
||||
This level gave you no reward, but the next one will! <br><br> PS: Better not destroy your existing factory - You'll need <strong>all</strong> those shapes later to <strong>unlock upgrades</strong>!
|
||||
This level gave you no reward, but the next one will! <br><br> PS: Better not destroy your existing factory - You'll need <strong>all</strong> those shapes later to
|
||||
<strong>unlock upgrades</strong>!
|
||||
|
||||
no_reward_freeplay:
|
||||
title: Next level
|
||||
@ -986,7 +1030,8 @@ settings:
|
||||
refreshRate:
|
||||
title: Tick Rate
|
||||
description: >-
|
||||
This determines how many game ticks happen per second. In general, a higher tick rate means better precision but also worse performance. On lower tickrates, the throughput may not be exact.
|
||||
This determines how many game ticks happen per second. In general, a higher tick rate means better precision but also worse performance. On lower tickrates, the throughput may not be
|
||||
exact.
|
||||
|
||||
alwaysMultiplace:
|
||||
title: Multiplace
|
||||
@ -1037,7 +1082,8 @@ settings:
|
||||
clearCursorOnDeleteWhilePlacing:
|
||||
title: Clear Cursor on Right Click
|
||||
description: >-
|
||||
Enabled by default, clears the cursor whenever you right click while you have a building selected for placement. If disabled, you can delete buildings by right-clicking while placing a building.
|
||||
Enabled by default, clears the cursor whenever you right click while you have a building selected for placement. If disabled, you can delete buildings by right-clicking while placing
|
||||
a building.
|
||||
|
||||
lowQualityTextures:
|
||||
title: Low quality textures (Ugly)
|
||||
@ -1132,6 +1178,7 @@ keybindings:
|
||||
filter: *filter
|
||||
wire_tunnel: *wire_tunnel
|
||||
display: *display
|
||||
wireless_display: *wireless_display
|
||||
reader: *reader
|
||||
virtual_processor: *virtual_processor
|
||||
transistor: *transistor
|
||||
@ -1211,7 +1258,7 @@ tips:
|
||||
- Cutters always cut vertically, regardless of their orientation.
|
||||
- The storage buffer prioritises the left output.
|
||||
- Invest time to build repeatable designs - it's worth it!
|
||||
- Holding <b>SHIFT</b> lets you place multiple buildings in one click.
|
||||
- Holding <b>SHIFT</b> lets you place multiple buildings at a time.
|
||||
- You can hold <b>ALT</b> to invert the direction of placed belts.
|
||||
- Efficiency is key!
|
||||
- Shape patches that are further away from the hub are more complex.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user