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,
 | 
			
		||||
    underground_belt-tier2, miner, miner-chainable, cutter, cutter-quad, rotater, rotater-ccw, stacker, mixer,
 | 
			
		||||
    painter, painter-double, painter-quad, trash, trash-storage;
 | 
			
		||||
    underground_belt-tier2, miner, miner-chainable, cutter, cutter-quad, rotater, rotater-ccw, rotater-fl,
 | 
			
		||||
    stacker, mixer, painter, painter-double, painter-quad, trash, trash-storage;
 | 
			
		||||
@each $building in $buildingsAndVariants {
 | 
			
		||||
    [data-icon="building_tutorials/#{$building}.png"] {
 | 
			
		||||
        background-image: uiResource("res/ui/building_tutorials/#{$building}.png") !important;
 | 
			
		||||
 | 
			
		||||
@ -67,6 +67,7 @@ export const globalConfig = {
 | 
			
		||||
        cutterQuad: 1 / 4,
 | 
			
		||||
        rotater: 1 / 1,
 | 
			
		||||
        rotaterCCW: 1 / 1,
 | 
			
		||||
        rotaterFL: 1 / 1,
 | 
			
		||||
        painter: 1 / 6,
 | 
			
		||||
        painterDouble: 1 / 8,
 | 
			
		||||
        painterQuad: 1 / 8,
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@ import { enumHubGoalRewards } from "../tutorial_goals";
 | 
			
		||||
import { enumItemType } from "../base_item";
 | 
			
		||||
 | 
			
		||||
/** @enum {string} */
 | 
			
		||||
export const enumRotaterVariants = { ccw: "ccw" };
 | 
			
		||||
export const enumRotaterVariants = { ccw: "ccw", fl: "fl" };
 | 
			
		||||
 | 
			
		||||
export class MetaRotaterBuilding extends MetaBuilding {
 | 
			
		||||
    constructor() {
 | 
			
		||||
@ -28,12 +28,20 @@ export class MetaRotaterBuilding extends MetaBuilding {
 | 
			
		||||
     * @returns {Array<[string, string]>}
 | 
			
		||||
     */
 | 
			
		||||
    getAdditionalStatistics(root, variant) {
 | 
			
		||||
        const speed = root.hubGoals.getProcessorBaseSpeed(
 | 
			
		||||
            variant === enumRotaterVariants.ccw
 | 
			
		||||
                ? enumItemProcessorTypes.rotaterCCW
 | 
			
		||||
                : enumItemProcessorTypes.rotater
 | 
			
		||||
        );
 | 
			
		||||
        return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
 | 
			
		||||
        switch (variant) {
 | 
			
		||||
            case defaultBuildingVariant: {
 | 
			
		||||
                const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.rotater);
 | 
			
		||||
                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)]];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -41,10 +49,14 @@ export class MetaRotaterBuilding extends MetaBuilding {
 | 
			
		||||
     * @param {GameRoot} root
 | 
			
		||||
     */
 | 
			
		||||
    getAvailableVariants(root) {
 | 
			
		||||
        let variants = [defaultBuildingVariant];
 | 
			
		||||
        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;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case enumRotaterVariants.fl: {
 | 
			
		||||
                entity.components.ItemProcessor.type = enumItemProcessorTypes.rotaterFL;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            default:
 | 
			
		||||
                assertAlways(false, "Unknown rotater variant: " + variant);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -11,6 +11,7 @@ export const enumItemProcessorTypes = {
 | 
			
		||||
    cutterQuad: "cutterQuad",
 | 
			
		||||
    rotater: "rotater",
 | 
			
		||||
    rotaterCCW: "rotaterCCW",
 | 
			
		||||
    rotaterFL: "rotaterFL",
 | 
			
		||||
    stacker: "stacker",
 | 
			
		||||
    trash: "trash",
 | 
			
		||||
    mixer: "mixer",
 | 
			
		||||
 | 
			
		||||
@ -431,6 +431,7 @@ export class HubGoals extends BasicSerializableObject {
 | 
			
		||||
            case enumItemProcessorTypes.cutterQuad:
 | 
			
		||||
            case enumItemProcessorTypes.rotater:
 | 
			
		||||
            case enumItemProcessorTypes.rotaterCCW:
 | 
			
		||||
            case enumItemProcessorTypes.rotaterFL:
 | 
			
		||||
            case enumItemProcessorTypes.stacker: {
 | 
			
		||||
                assert(
 | 
			
		||||
                    globalConfig.buildingSpeeds[processorType],
 | 
			
		||||
 | 
			
		||||
@ -495,6 +495,19 @@ export class ShapeDefinition extends BasicSerializableObject {
 | 
			
		||||
        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.
 | 
			
		||||
     * @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
 | 
			
		||||
     * @param {ShapeDefinition} lowerDefinition
 | 
			
		||||
 | 
			
		||||
@ -185,7 +185,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // ROTATER ( CCW)
 | 
			
		||||
            // ROTATER (CCW)
 | 
			
		||||
            case enumItemProcessorTypes.rotaterCCW: {
 | 
			
		||||
                const inputItem = /** @type {ShapeItem} */ (items[0].item);
 | 
			
		||||
                assert(inputItem instanceof ShapeItem, "Input for rotation is not a shape");
 | 
			
		||||
@ -198,6 +198,19 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
 | 
			
		||||
                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
 | 
			
		||||
 | 
			
		||||
            case enumItemProcessorTypes.stacker: {
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,7 @@ export const enumHubGoalRewards = {
 | 
			
		||||
    reward_tunnel: "reward_tunnel",
 | 
			
		||||
 | 
			
		||||
    reward_rotater_ccw: "reward_rotater_ccw",
 | 
			
		||||
    reward_rotater_fl: "reward_rotater_fl",
 | 
			
		||||
    reward_miner_chainable: "reward_miner_chainable",
 | 
			
		||||
    reward_underground_belt_tier_2: "reward_underground_belt_tier_2",
 | 
			
		||||
    reward_splitter_compact: "reward_splitter_compact",
 | 
			
		||||
 | 
			
		||||
@ -33,6 +33,7 @@ export const enumHubGoalRewardsToContentUnlocked = {
 | 
			
		||||
    [enumHubGoalRewards.reward_tunnel]: typed([[MetaUndergroundBeltBuilding, defaultBuildingVariant]]),
 | 
			
		||||
 | 
			
		||||
    [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_underground_belt_tier_2]: typed([
 | 
			
		||||
        [MetaUndergroundBeltBuilding, enumUndergroundBeltVariants.tier2],
 | 
			
		||||
 | 
			
		||||
@ -503,6 +503,9 @@ buildings:
 | 
			
		||||
        ccw:
 | 
			
		||||
            name: Rotate (CCW)
 | 
			
		||||
            description: Rotates shapes counter-clockwise by 90 degrees.
 | 
			
		||||
        fl:
 | 
			
		||||
            name: Rotate (180)
 | 
			
		||||
            description: Rotates shapes by 180 degrees.
 | 
			
		||||
 | 
			
		||||
    stacker:
 | 
			
		||||
        default:
 | 
			
		||||
 | 
			
		||||