Merge pull request #471 from RogiJAG/180_deg_rotater
180 Degree Rotater Variant
BIN
res/ui/building_tutorials/rotater-fl.png
Normal file
After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 216 KiB After Width: | Height: | Size: 226 KiB |
Before Width: | Height: | Size: 515 KiB After Width: | Height: | Size: 527 KiB |
Before Width: | Height: | Size: 976 KiB After Width: | Height: | Size: 1.0 MiB |
BIN
res_raw/sprites/blueprints/rotater-fl.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
res_raw/sprites/buildings/rotater-fl.png
Normal file
After Width: | Height: | Size: 13 KiB |
@ -8,8 +8,8 @@ $buildings: belt, cutter, miner, mixer, painter, rotater, splitter, stacker, tra
|
|||||||
}
|
}
|
||||||
|
|
||||||
$buildingsAndVariants: belt, splitter, splitter-compact, splitter-compact-inverse, underground_belt,
|
$buildingsAndVariants: belt, splitter, splitter-compact, splitter-compact-inverse, underground_belt,
|
||||||
underground_belt-tier2, miner, miner-chainable, cutter, cutter-quad, rotater, rotater-ccw, stacker, mixer,
|
underground_belt-tier2, miner, miner-chainable, cutter, cutter-quad, rotater, rotater-ccw, rotater-fl,
|
||||||
painter, painter-double, painter-quad, trash, trash-storage;
|
stacker, mixer, painter, painter-double, painter-quad, trash, trash-storage;
|
||||||
@each $building in $buildingsAndVariants {
|
@each $building in $buildingsAndVariants {
|
||||||
[data-icon="building_tutorials/#{$building}.png"] {
|
[data-icon="building_tutorials/#{$building}.png"] {
|
||||||
background-image: uiResource("res/ui/building_tutorials/#{$building}.png") !important;
|
background-image: uiResource("res/ui/building_tutorials/#{$building}.png") !important;
|
||||||
|
@ -67,6 +67,7 @@ export const globalConfig = {
|
|||||||
cutterQuad: 1 / 4,
|
cutterQuad: 1 / 4,
|
||||||
rotater: 1 / 1,
|
rotater: 1 / 1,
|
||||||
rotaterCCW: 1 / 1,
|
rotaterCCW: 1 / 1,
|
||||||
|
rotaterFL: 1 / 1,
|
||||||
painter: 1 / 6,
|
painter: 1 / 6,
|
||||||
painterDouble: 1 / 8,
|
painterDouble: 1 / 8,
|
||||||
painterQuad: 1 / 8,
|
painterQuad: 1 / 8,
|
||||||
|
@ -11,7 +11,7 @@ import { enumHubGoalRewards } from "../tutorial_goals";
|
|||||||
import { enumItemType } from "../base_item";
|
import { enumItemType } from "../base_item";
|
||||||
|
|
||||||
/** @enum {string} */
|
/** @enum {string} */
|
||||||
export const enumRotaterVariants = { ccw: "ccw" };
|
export const enumRotaterVariants = { ccw: "ccw", fl: "fl" };
|
||||||
|
|
||||||
export class MetaRotaterBuilding extends MetaBuilding {
|
export class MetaRotaterBuilding extends MetaBuilding {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -28,23 +28,35 @@ export class MetaRotaterBuilding extends MetaBuilding {
|
|||||||
* @returns {Array<[string, string]>}
|
* @returns {Array<[string, string]>}
|
||||||
*/
|
*/
|
||||||
getAdditionalStatistics(root, variant) {
|
getAdditionalStatistics(root, variant) {
|
||||||
const speed = root.hubGoals.getProcessorBaseSpeed(
|
switch (variant) {
|
||||||
variant === enumRotaterVariants.ccw
|
case defaultBuildingVariant: {
|
||||||
? enumItemProcessorTypes.rotaterCCW
|
const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.rotater);
|
||||||
: enumItemProcessorTypes.rotater
|
|
||||||
);
|
|
||||||
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
|
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
|
||||||
}
|
}
|
||||||
|
case enumRotaterVariants.ccw: {
|
||||||
|
const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.rotaterCCW);
|
||||||
|
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
|
||||||
|
}
|
||||||
|
case enumRotaterVariants.fl: {
|
||||||
|
const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.rotaterFL);
|
||||||
|
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {GameRoot} root
|
* @param {GameRoot} root
|
||||||
*/
|
*/
|
||||||
getAvailableVariants(root) {
|
getAvailableVariants(root) {
|
||||||
|
let variants = [defaultBuildingVariant];
|
||||||
if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_rotater_ccw)) {
|
if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_rotater_ccw)) {
|
||||||
return [defaultBuildingVariant, enumRotaterVariants.ccw];
|
variants.push(enumRotaterVariants.ccw);
|
||||||
}
|
}
|
||||||
return super.getAvailableVariants(root);
|
if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_rotater_fl)) {
|
||||||
|
variants.push(enumRotaterVariants.fl);
|
||||||
|
}
|
||||||
|
return variants;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -100,6 +112,10 @@ export class MetaRotaterBuilding extends MetaBuilding {
|
|||||||
entity.components.ItemProcessor.type = enumItemProcessorTypes.rotaterCCW;
|
entity.components.ItemProcessor.type = enumItemProcessorTypes.rotaterCCW;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case enumRotaterVariants.fl: {
|
||||||
|
entity.components.ItemProcessor.type = enumItemProcessorTypes.rotaterFL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
assertAlways(false, "Unknown rotater variant: " + variant);
|
assertAlways(false, "Unknown rotater variant: " + variant);
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ export const enumItemProcessorTypes = {
|
|||||||
cutterQuad: "cutterQuad",
|
cutterQuad: "cutterQuad",
|
||||||
rotater: "rotater",
|
rotater: "rotater",
|
||||||
rotaterCCW: "rotaterCCW",
|
rotaterCCW: "rotaterCCW",
|
||||||
|
rotaterFL: "rotaterFL",
|
||||||
stacker: "stacker",
|
stacker: "stacker",
|
||||||
trash: "trash",
|
trash: "trash",
|
||||||
mixer: "mixer",
|
mixer: "mixer",
|
||||||
|
@ -431,6 +431,7 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
case enumItemProcessorTypes.cutterQuad:
|
case enumItemProcessorTypes.cutterQuad:
|
||||||
case enumItemProcessorTypes.rotater:
|
case enumItemProcessorTypes.rotater:
|
||||||
case enumItemProcessorTypes.rotaterCCW:
|
case enumItemProcessorTypes.rotaterCCW:
|
||||||
|
case enumItemProcessorTypes.rotaterFL:
|
||||||
case enumItemProcessorTypes.stacker: {
|
case enumItemProcessorTypes.stacker: {
|
||||||
assert(
|
assert(
|
||||||
globalConfig.buildingSpeeds[processorType],
|
globalConfig.buildingSpeeds[processorType],
|
||||||
|
@ -495,6 +495,19 @@ export class ShapeDefinition extends BasicSerializableObject {
|
|||||||
return new ShapeDefinition({ layers: newLayers });
|
return new ShapeDefinition({ layers: newLayers });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a definition which was rotated 180 degrees (flipped)
|
||||||
|
* @returns {ShapeDefinition}
|
||||||
|
*/
|
||||||
|
cloneRotateFL() {
|
||||||
|
const newLayers = this.internalCloneLayers();
|
||||||
|
for (let layerIndex = 0; layerIndex < newLayers.length; ++layerIndex) {
|
||||||
|
const quadrants = newLayers[layerIndex];
|
||||||
|
quadrants.push(quadrants.shift(), quadrants.shift());
|
||||||
|
}
|
||||||
|
return new ShapeDefinition({ layers: newLayers });
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stacks the given shape definition on top.
|
* Stacks the given shape definition on top.
|
||||||
* @param {ShapeDefinition} definition
|
* @param {ShapeDefinition} definition
|
||||||
|
@ -127,6 +127,24 @@ export class ShapeDefinitionManager extends BasicSerializableObject {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a definition for rotating a shape counter clockwise
|
||||||
|
* @param {ShapeDefinition} definition
|
||||||
|
* @returns {ShapeDefinition}
|
||||||
|
*/
|
||||||
|
shapeActionRotateFL(definition) {
|
||||||
|
const key = "rotate-fl:" + definition.getHash();
|
||||||
|
if (this.operationCache[key]) {
|
||||||
|
return /** @type {ShapeDefinition} */ (this.operationCache[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const rotated = definition.cloneRotateFL();
|
||||||
|
|
||||||
|
return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle(
|
||||||
|
rotated
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a definition for stacking the upper definition onto the lower one
|
* Generates a definition for stacking the upper definition onto the lower one
|
||||||
* @param {ShapeDefinition} lowerDefinition
|
* @param {ShapeDefinition} lowerDefinition
|
||||||
|
@ -185,7 +185,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ROTATER ( CCW)
|
// ROTATER (CCW)
|
||||||
case enumItemProcessorTypes.rotaterCCW: {
|
case enumItemProcessorTypes.rotaterCCW: {
|
||||||
const inputItem = /** @type {ShapeItem} */ (items[0].item);
|
const inputItem = /** @type {ShapeItem} */ (items[0].item);
|
||||||
assert(inputItem instanceof ShapeItem, "Input for rotation is not a shape");
|
assert(inputItem instanceof ShapeItem, "Input for rotation is not a shape");
|
||||||
@ -198,6 +198,19 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ROTATER (FL)
|
||||||
|
case enumItemProcessorTypes.rotaterFL: {
|
||||||
|
const inputItem = /** @type {ShapeItem} */ (items[0].item);
|
||||||
|
assert(inputItem instanceof ShapeItem, "Input for rotation is not a shape");
|
||||||
|
const inputDefinition = inputItem.definition;
|
||||||
|
|
||||||
|
const rotatedDefinition = this.root.shapeDefinitionMgr.shapeActionRotateFL(inputDefinition);
|
||||||
|
outItems.push({
|
||||||
|
item: new ShapeItem(rotatedDefinition),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// STACKER
|
// STACKER
|
||||||
|
|
||||||
case enumItemProcessorTypes.stacker: {
|
case enumItemProcessorTypes.stacker: {
|
||||||
|
@ -15,6 +15,7 @@ export const enumHubGoalRewards = {
|
|||||||
reward_tunnel: "reward_tunnel",
|
reward_tunnel: "reward_tunnel",
|
||||||
|
|
||||||
reward_rotater_ccw: "reward_rotater_ccw",
|
reward_rotater_ccw: "reward_rotater_ccw",
|
||||||
|
reward_rotater_fl: "reward_rotater_fl",
|
||||||
reward_miner_chainable: "reward_miner_chainable",
|
reward_miner_chainable: "reward_miner_chainable",
|
||||||
reward_underground_belt_tier_2: "reward_underground_belt_tier_2",
|
reward_underground_belt_tier_2: "reward_underground_belt_tier_2",
|
||||||
reward_splitter_compact: "reward_splitter_compact",
|
reward_splitter_compact: "reward_splitter_compact",
|
||||||
|
@ -33,6 +33,7 @@ export const enumHubGoalRewardsToContentUnlocked = {
|
|||||||
[enumHubGoalRewards.reward_tunnel]: typed([[MetaUndergroundBeltBuilding, defaultBuildingVariant]]),
|
[enumHubGoalRewards.reward_tunnel]: typed([[MetaUndergroundBeltBuilding, defaultBuildingVariant]]),
|
||||||
|
|
||||||
[enumHubGoalRewards.reward_rotater_ccw]: typed([[MetaRotaterBuilding, enumRotaterVariants.ccw]]),
|
[enumHubGoalRewards.reward_rotater_ccw]: typed([[MetaRotaterBuilding, enumRotaterVariants.ccw]]),
|
||||||
|
[enumHubGoalRewards.reward_rotater_fl]: typed([[MetaRotaterBuilding, enumRotaterVariants.fl]]),
|
||||||
[enumHubGoalRewards.reward_miner_chainable]: typed([[MetaMinerBuilding, enumMinerVariants.chainable]]),
|
[enumHubGoalRewards.reward_miner_chainable]: typed([[MetaMinerBuilding, enumMinerVariants.chainable]]),
|
||||||
[enumHubGoalRewards.reward_underground_belt_tier_2]: typed([
|
[enumHubGoalRewards.reward_underground_belt_tier_2]: typed([
|
||||||
[MetaUndergroundBeltBuilding, enumUndergroundBeltVariants.tier2],
|
[MetaUndergroundBeltBuilding, enumUndergroundBeltVariants.tier2],
|
||||||
|
@ -503,6 +503,9 @@ buildings:
|
|||||||
ccw:
|
ccw:
|
||||||
name: Rotate (CCW)
|
name: Rotate (CCW)
|
||||||
description: Rotates shapes counter-clockwise by 90 degrees.
|
description: Rotates shapes counter-clockwise by 90 degrees.
|
||||||
|
fl:
|
||||||
|
name: Rotate (180)
|
||||||
|
description: Rotates shapes by 180 degrees.
|
||||||
|
|
||||||
stacker:
|
stacker:
|
||||||
default:
|
default:
|
||||||
|