diff --git a/res/ui/icons/pin.png b/res/ui/icons/pin.png index 768599f3..004d1e72 100644 Binary files a/res/ui/icons/pin.png and b/res/ui/icons/pin.png differ diff --git a/src/css/ingame_hud/shop.scss b/src/css/ingame_hud/shop.scss index 41834d06..f995cfa8 100644 --- a/src/css/ingame_hud/shop.scss +++ b/src/css/ingame_hud/shop.scss @@ -42,7 +42,7 @@ color: #fff; text-align: center; font-weight: bold; - @include S(width, 45px); + @include S(width, 50px); @include S(padding, 0px, 5px); &[data-tier="0"] { @@ -61,10 +61,10 @@ background-color: rgb(243, 77, 48); } &[data-tier="5"] { - background-color: rgb(219, 184, 29); + background-color: rgb(255, 209, 6); } &[data-tier="6"] { - background-color: rgb(190, 73, 73); + background-color: rgb(44, 41, 46); } } } @@ -105,15 +105,16 @@ display: flex; flex-direction: column; align-items: center; - @include S(width, 75px); + @include S(width, 70px); + overflow: hidden; button.pin { @include S(width, 12px); @include S(height, 12px); background: uiResource("icons/pin.png") center center / 95% no-repeat; position: absolute; - @include S(top, -2px); - @include S(right, -2px); + @include S(top, 2px); + @include S(right, 2px); opacity: 0.6; cursor: pointer; pointer-events: all; diff --git a/src/js/core/config.js b/src/js/core/config.js index 10495e4f..ba851fce 100644 --- a/src/js/core/config.js +++ b/src/js/core/config.js @@ -38,7 +38,7 @@ export const globalConfig = { // Belt speeds // NOTICE: Update webpack.production.config too! - beltSpeedItemsPerSecond: 1, + beltSpeedItemsPerSecond: 5, itemSpacingOnBelts: 0.63, minerSpeedItemsPerSecond: 0, // COMPUTED @@ -76,8 +76,8 @@ export const globalConfig = { debug: { /* dev:start */ - // fastGameEnter: true, - // noArtificialDelays: true, + fastGameEnter: true, + noArtificialDelays: true, // disableSavegameWrite: true, showEntityBounds: false, showAcceptorEjectors: false, @@ -87,9 +87,9 @@ export const globalConfig = { disableZoomLimits: false, showChunkBorders: false, rewardsInstant: false, - allBuildingsUnlocked: true, + // allBuildingsUnlocked: true, upgradesNoCost: true, - disableUnlockDialog: false, + disableUnlockDialog: true, // testTranslations: true, /* dev:end */ }, diff --git a/src/js/game/buildings/cutter.js b/src/js/game/buildings/cutter.js index ce83b8f5..de5c0556 100644 --- a/src/js/game/buildings/cutter.js +++ b/src/js/game/buildings/cutter.js @@ -19,6 +19,7 @@ export class MetaCutterBuilding extends MetaBuilding { getSilhouetteColor() { return "#7dcda2"; } + getDimensions(variant) { switch (variant) { case defaultBuildingVariant: @@ -30,8 +31,14 @@ export class MetaCutterBuilding extends MetaBuilding { } } + /** + * @param {GameRoot} root + */ getAvailableVariants(root) { - return [defaultBuildingVariant, enumCutterVariants.quad]; + if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_cutter_quad)) { + return [defaultBuildingVariant, enumCutterVariants.quad]; + } + return super.getAvailableVariants(root); } /** diff --git a/src/js/game/buildings/miner.js b/src/js/game/buildings/miner.js index 14d41ed5..bc3474bd 100644 --- a/src/js/game/buildings/miner.js +++ b/src/js/game/buildings/miner.js @@ -4,6 +4,7 @@ import { MinerComponent } from "../components/miner"; import { Entity } from "../entity"; import { MetaBuilding, defaultBuildingVariant } from "../meta_building"; import { GameRoot } from "../root"; +import { enumHubGoalRewards } from "../tutorial_goals"; /** @enum {string} */ export const enumMinerVariants = { chainable: "chainable" }; @@ -17,8 +18,15 @@ export class MetaMinerBuilding extends MetaBuilding { return "#b37dcd"; } + /** + * + * @param {GameRoot} root + */ getAvailableVariants(root) { - return [defaultBuildingVariant, enumMinerVariants.chainable]; + if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_miner_chainable)) { + return [defaultBuildingVariant, enumMinerVariants.chainable]; + } + return super.getAvailableVariants(root); } /** diff --git a/src/js/game/buildings/painter.js b/src/js/game/buildings/painter.js index 420b4de1..bdf9b554 100644 --- a/src/js/game/buildings/painter.js +++ b/src/js/game/buildings/painter.js @@ -33,8 +33,18 @@ export class MetaPainterBuilding extends MetaBuilding { return "#cd9b7d"; } + /** + * @param {GameRoot} root + */ getAvailableVariants(root) { - return [defaultBuildingVariant, enumPainterVariants.double, enumPainterVariants.quad]; + let variants = [defaultBuildingVariant]; + if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_painter_double)) { + variants.push(enumPainterVariants.double); + } + if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_painter_quad)) { + variants.push(enumPainterVariants.quad); + } + return variants; } /** diff --git a/src/js/game/buildings/rotater.js b/src/js/game/buildings/rotater.js index 95d3dc7c..ba582766 100644 --- a/src/js/game/buildings/rotater.js +++ b/src/js/game/buildings/rotater.js @@ -20,8 +20,15 @@ export class MetaRotaterBuilding extends MetaBuilding { return "#7dc6cd"; } + /** + * + * @param {GameRoot} root + */ getAvailableVariants(root) { - return [defaultBuildingVariant, enumRotaterVariants.ccw]; + if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_rotater_ccw)) { + return [defaultBuildingVariant, enumRotaterVariants.ccw]; + } + return super.getAvailableVariants(root); } /** diff --git a/src/js/game/buildings/splitter.js b/src/js/game/buildings/splitter.js index 1bc0a779..a48d1d6c 100644 --- a/src/js/game/buildings/splitter.js +++ b/src/js/game/buildings/splitter.js @@ -32,8 +32,18 @@ export class MetaSplitterBuilding extends MetaBuilding { return "#444"; } + /** + * @param {GameRoot} root + */ getAvailableVariants(root) { - return [defaultBuildingVariant, enumSplitterVariants.compact, enumSplitterVariants.compactInverse]; + if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_splitter_compact)) { + return [ + defaultBuildingVariant, + enumSplitterVariants.compact, + enumSplitterVariants.compactInverse, + ]; + } + return super.getAvailableVariants(root); } /** diff --git a/src/js/game/buildings/underground_belt.js b/src/js/game/buildings/underground_belt.js index 6512245e..bdda2ca6 100644 --- a/src/js/game/buildings/underground_belt.js +++ b/src/js/game/buildings/underground_belt.js @@ -40,8 +40,14 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding { return true; } + /** + * @param {GameRoot} root + */ getAvailableVariants(root) { - return [defaultBuildingVariant, enumUndergroundBeltVariants.tier2]; + if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_underground_belt_tier_2)) { + return [defaultBuildingVariant, enumUndergroundBeltVariants.tier2]; + } + return super.getAvailableVariants(root); } getPreviewSprite(rotationVariant, variant) { diff --git a/src/js/game/camera.js b/src/js/game/camera.js index 1fd235e5..c0326fbd 100644 --- a/src/js/game/camera.js +++ b/src/js/game/camera.js @@ -53,7 +53,7 @@ export class Camera extends BasicSerializableObject { this.clampZoomLevel(); /** @type {Vector} */ - this.center = new Vector(2 * globalConfig.tileSize, 2 * globalConfig.tileSize); + this.center = new Vector(0, 0); // Input handling this.currentlyMoving = false; diff --git a/src/js/game/hud/parts/building_placer.js b/src/js/game/hud/parts/building_placer.js index 0f49571e..45ca06c6 100644 --- a/src/js/game/hud/parts/building_placer.js +++ b/src/js/game/hud/parts/building_placer.js @@ -69,6 +69,8 @@ export class HUDBuildingPlacer extends BaseHUDPart { * @type {Vector} */ this.initialDragTile = null; + + this.root.signals.storyGoalCompleted.add(this.rerenderVariants, this); } createElements(parent) { diff --git a/src/js/game/map_chunk.js b/src/js/game/map_chunk.js index a2305991..b56836e8 100644 --- a/src/js/game/map_chunk.js +++ b/src/js/game/map_chunk.js @@ -159,11 +159,11 @@ export class MapChunk { weights = { [enumSubShape.rect]: 100, [enumSubShape.circle]: Math_round(50 + clamp(distanceToOriginInChunks * 2, 0, 50)), - [enumSubShape.star]: Math_round(9 + clamp(distanceToOriginInChunks, 0, 30)), + [enumSubShape.star]: Math_round(20 + clamp(distanceToOriginInChunks, 0, 30)), [enumSubShape.windmill]: Math_round(6 + clamp(distanceToOriginInChunks / 2, 0, 20)), }; - if (distanceToOriginInChunks < 5) { + if (distanceToOriginInChunks < 4) { // Initial chunks can not spawn the good stuff weights[enumSubShape.star] = 0; weights[enumSubShape.windmill] = 0; @@ -188,6 +188,18 @@ export class MapChunk { ]; } + // Makes sure windmills never spawn as whole + let windmillCount = 0; + for (let i = 0; i < subShapes.length; ++i) { + if (subShapes[i] === enumSubShape.windmill) { + ++windmillCount; + } + } + if (windmillCount > 1) { + subShapes[0] = enumSubShape.rect; + subShapes[1] = enumSubShape.rect; + } + const definition = this.root.shapeDefinitionMgr.getDefinitionFromSimpleShapes(subShapes); this.internalGeneratePatch(rng, shapePatchSize, new ShapeItem(definition)); } diff --git a/src/js/game/tutorial_goals.js b/src/js/game/tutorial_goals.js index 42cc2e83..47f9a325 100644 --- a/src/js/game/tutorial_goals.js +++ b/src/js/game/tutorial_goals.js @@ -12,142 +12,122 @@ export const enumHubGoalRewards = { reward_splitter: "reward_splitter", reward_tunnel: "reward_tunnel", + reward_rotater_ccw: "reward_rotater_ccw", + reward_miner_chainable: "reward_miner_chainable", + reward_underground_belt_tier_2: "reward_underground_belt_tier_2", + reward_splitter_compact: "reward_splitter_compact", + reward_cutter_quad: "reward_cutter_quad", + reward_painter_double: "reward_painter_double", + reward_painter_quad: "reward_painter_quad", + + reward_freeplay: "reward_freeplay", + no_reward: "no_reward", }; export const tutorialGoals = [ // Circle { - shape: "CuCuCuCu", - required: 40, + shape: "CuCuCuCu", // belts t1 + required: 60, reward: enumHubGoalRewards.reward_cutter_and_trash, }, // Cutter { - shape: "CuCu----", - required: 150, - reward: enumHubGoalRewards.no_reward, - }, - - { - shape: "----CuCu", - required: 200, - reward: enumHubGoalRewards.reward_splitter, - }, - - // Rectangle - { - shape: "RuRuRuRu", + shape: "----CuCu", // required: 80, reward: enumHubGoalRewards.no_reward, }, + // Rectangle { - shape: "RuRu----", - required: 250, + shape: "RuRuRuRu", // miners t1 + required: 100, + reward: enumHubGoalRewards.reward_splitter, + }, + + { + shape: "RuRu----", // processors t2 + required: 350, reward: enumHubGoalRewards.reward_rotater, }, // Rotater { - shape: "--CuCu--", + shape: "--CuCu--", // belts t2 required: 300, - reward: enumHubGoalRewards.no_reward, - }, - - { - shape: "Ru----Ru", - required: 400, reward: enumHubGoalRewards.reward_tunnel, }, { - shape: "Cu------", - required: 800, - reward: enumHubGoalRewards.no_reward, - }, - - { - shape: "------Ru", + shape: "Cu------", // miners t2 required: 1000, reward: enumHubGoalRewards.reward_painter, }, // Painter { - shape: "CrCrCrCr", + shape: "CrCrCrCr", // unused required: 1500, - reward: enumHubGoalRewards.no_reward, + reward: enumHubGoalRewards.reward_rotater_ccw, }, { - shape: "RbRb----", + shape: "RbRb----", // painter t2 required: 2500, reward: enumHubGoalRewards.reward_mixer, }, // Mixing (purple) { - shape: "CpCpCpCp", + shape: "CpCpCpCp", // belts t3 required: 4000, - reward: enumHubGoalRewards.no_reward, + reward: enumHubGoalRewards.reward_splitter_compact, }, // Star shape + cyan { - shape: "ScScScSc", - required: 500, + shape: "ScScScSc", // miners t3 + required: 5000, reward: enumHubGoalRewards.reward_stacker, }, // Stacker { - shape: "CgScScCg", - required: 3000, - reward: enumHubGoalRewards.no_reward, - }, - - { - shape: "RpRpRpRp:CcCcCcCc", - required: 4000, - reward: enumHubGoalRewards.no_reward, - }, - - { - shape: "RgCwRgCw:CpCpCpCp", + shape: "CgScScCg", // processors t3 required: 6000, - reward: enumHubGoalRewards.no_reward, + reward: enumHubGoalRewards.reward_miner_chainable, }, { - shape: "CwSwCwSw:CpCrCpCr", - required: 6000, - reward: enumHubGoalRewards.no_reward, + shape: "RpRpRpRp:CwCwCwCw", // painting t3 + required: 7000, + reward: enumHubGoalRewards.reward_underground_belt_tier_2, }, { - shape: "WyWyWyWy", - required: 2000, - reward: enumHubGoalRewards.no_reward, + shape: "SrSrSrSr:CyCyCyCy:SwSwSwSw", // belts t4 (two variants) + required: 8000, + reward: enumHubGoalRewards.reward_cutter_quad, }, { - shape: "WyWgWyWg:CbCpCbCp", - required: 4000, - reward: enumHubGoalRewards.no_reward, - }, - - { - shape: "WyRgWyRg:CbCpCbCp:CpCgCpCg", + shape: "CbRbRbCb:CwCwCwCw:WbWbWbWb", // miner t4 (two variants) required: 9000, - reward: enumHubGoalRewards.no_reward, + reward: enumHubGoalRewards.reward_painter_double, }, { - shape: "CwRrCbRy:ScSrSpSb:CwCwCwCw:RgRgRgRg", - required: 15000, - reward: enumHubGoalRewards.no_reward, + shape: "WrRgWrRg:CwCrCwCr:SgSgSgSg", // processors t4 (two varinats) + required: 10000, + reward: enumHubGoalRewards.reward_painter_quad, + }, + + { + shape: "RuCw--Cw:----Ru--", + required: 50000, + reward: enumHubGoalRewards.reward_freeplay, }, ]; diff --git a/src/js/game/upgrades.js b/src/js/game/upgrades.js index 958c917e..1a7b9416 100644 --- a/src/js/game/upgrades.js +++ b/src/js/game/upgrades.js @@ -1,94 +1,132 @@ import { findNiceIntegerValue } from "../core/utils"; import { ShapeDefinition } from "./shape_definition"; +const finalShape = "RuCw--Cw:----Ru--"; + export const UPGRADES = { belt: { tiers: [ { - required: [{ shape: "CuCuCuCu", amount: 80 }], + required: [{ shape: "CuCuCuCu", amount: 150 }], improvement: 1, }, { - required: [{ shape: "Ru----Ru", amount: 4000 }], + required: [{ shape: "--CuCu--", amount: 1500 }], improvement: 2, }, { - required: [{ shape: "CwSwCwSw", amount: 30000 }], + required: [{ shape: "CpCpCpCp", amount: 15000 }], improvement: 4, }, { - required: [{ shape: "RgRgSpSp:CwSwCwSw:Cr--Sw--", amount: 80000 }], + required: [{ shape: "SrSrSrSr:CyCyCyCy", amount: 40000 }], improvement: 4, }, + { + required: [{ shape: "SrSrSrSr:CyCyCyCy:SwSwSwSw", amount: 40000 }], + improvement: 4, + }, + { + required: [{ shape: finalShape, amount: 150000 }], + improvement: 4, + excludePrevious: true, + }, ], }, miner: { tiers: [ { - required: [{ shape: "RuRuRuRu", amount: 200 }], + required: [{ shape: "RuRuRuRu", amount: 400 }], improvement: 1, }, { - required: [{ shape: "Cu------", amount: 4000 }], + required: [{ shape: "Cu------", amount: 5500 }], improvement: 2, }, { - required: [{ shape: "WyWgWyWg:CbCpCbCp", amount: 30000 }], + required: [{ shape: "ScScScSc", amount: 20000 }], improvement: 4, }, { - required: [{ shape: "WyWgWyWg:CbCpCbCp:Rp----Rp", amount: 90000 }], + required: [{ shape: "CwCwCwCw:WbWbWbWb", amount: 40000 }], improvement: 4, }, + { + required: [{ shape: "CbRbRbCb:CwCwCwCw:WbWbWbWb", amount: 40000 }], + improvement: 4, + }, + { + required: [{ shape: finalShape, amount: 150000 }], + improvement: 4, + excludePrevious: true, + }, ], }, processors: { tiers: [ { - required: [{ shape: "SuSuSuSu", amount: 200 }], + required: [{ shape: "SuSuSuSu", amount: 1000 }], improvement: 1, }, { - required: [{ shape: "Cu------", amount: 4000 }], + required: [{ shape: "RuRu----", amount: 2000 }], improvement: 2, }, { - required: [{ shape: "WyWgWyWg:CbCpCbCp", amount: 30000 }], + required: [{ shape: "CgScScCg", amount: 25000 }], improvement: 4, }, { - required: [{ shape: "WyWgWyWg:CbCpCbCp:Rp----Rp", amount: 90000 }], + required: [{ shape: "CwCrCwCr:SgSgSgSg", amount: 40000 }], improvement: 4, }, + { + required: [{ shape: "WrRgWrRg:CwCrCwCr:SgSgSgSg", amount: 40000 }], + improvement: 4, + }, + { + required: [{ shape: finalShape, amount: 150000 }], + improvement: 4, + excludePrevious: true, + }, ], }, painting: { tiers: [ { - required: [{ shape: "WuWuWuWu", amount: 200 }], + required: [{ shape: "WrWrWrWr", amount: 2000 }], improvement: 1, }, { - required: [{ shape: "Cu------", amount: 4000 }], + required: [{ shape: "RbRb----", amount: 4000 }], improvement: 2, }, { - required: [{ shape: "WyWgWyWg:CbCpCbCp", amount: 30000 }], + required: [{ shape: "RpRpRpRp:CwCwCwCw", amount: 30000 }], improvement: 4, }, { - required: [{ shape: "WyWgWyWg:CbCpCbCp:Rp----Rp", amount: 90000 }], + required: [{ shape: "WpWpWpWp:CwCwCwCw:WpWpWpWp", amount: 40000 }], improvement: 4, }, + { + required: [{ shape: "WpWpWpWp:CwCwCwCw:WpWpWpWp:CwCwCwCw", amount: 40000 }], + improvement: 4, + }, + { + required: [{ shape: finalShape, amount: 150000 }], + improvement: 4, + excludePrevious: true, + }, ], }, }; // Tiers need % of the previous tier as requirement too -const tierGrowth = 2; +const tierGrowth = 2.5; // Automatically generate tier levels for (const upgradeId in UPGRADES) { @@ -101,10 +139,12 @@ for (const upgradeId in UPGRADES) { for (let k = currentTierRequirements.length - 1; k >= 0; --k) { const oldTierRequirement = currentTierRequirements[k]; - tierHandle.required.unshift({ - shape: oldTierRequirement.shape, - amount: oldTierRequirement.amount, - }); + if (!tierHandle.excludePrevious) { + tierHandle.required.unshift({ + shape: oldTierRequirement.shape, + amount: oldTierRequirement.amount, + }); + } } currentTierRequirements.push( ...originalRequired.map(req => ({ diff --git a/translations/base-en.yaml b/translations/base-en.yaml index 9d3bac7c..82e3fb72 100644 --- a/translations/base-en.yaml +++ b/translations/base-en.yaml @@ -266,6 +266,16 @@ storyRewards: reward_splitter: Splitter/Merger reward_tunnel: Tunnel + reward_rotater_ccw: CCW Rotating + reward_miner_chainable: Chaining Extractor + reward_underground_belt_tier_2: Tunnel Tier II + reward_splitter_compact: Compact Balancer + reward_cutter_quad: Quad Cutting + reward_painter_double: Double Painting + reward_painter_quad: Quad Painting + + reward_freeplay: Freeplay + # Special reward, which is shown when there is no reward actually no_reward: Next level