diff --git a/src/components/Employee.ts b/src/components/Employee.ts index 1b812e9..194a2e3 100644 --- a/src/components/Employee.ts +++ b/src/components/Employee.ts @@ -5,6 +5,7 @@ import { EmployeeData, EmployeeId, EmployeeType } from "./EmployeeData"; export class Employee extends Button { public employeeId: EmployeeId; + public hasBeenPurchased: boolean; public currentCustomer: Customer | null; public doingCuteThing: boolean; @@ -33,6 +34,9 @@ export class Employee extends Button { this.startX = x; this.startY = y; + // Initially not purchased + this.hasBeenPurchased = false; + /* Sprite */ this.spriteCont = this.scene.add.container(0, this.spriteOffset); this.add(this.spriteCont); @@ -48,13 +52,17 @@ export class Employee extends Button { } update(time: number, delta: number) { - const factor = this.doingCuteThing ? 0.1 : 0.02; + const factor = this.doingCuteThing + ? 0.1 + : this.hasBeenPurchased + ? 0.02 + : 0; const squish = 1.0 + factor * Math.sin((6 * time) / 1000); this.spriteCont.setScale(1.0, squish - 0.2 * this.holdSmooth); } setCustomer(customer: Customer | null) { - if(customer){ + if (customer) { this.scene.sound.play("sqk"); } @@ -95,7 +103,12 @@ export class Employee extends Button { } upgrade() { - if (this.upgradeTo) { + // this.scene.sound.play("upgrade"); + + if (!this.hasBeenPurchased) { + this.hasBeenPurchased = true; + this.setAlpha(1.0); + } else if (this.upgradeTo) { this.employeeId = this.upgradeTo!; this.sprite.setTexture(this.spriteKey); } @@ -140,7 +153,13 @@ export class Employee extends Button { } get upgradeCost(): number { - return EmployeeData[this.employeeId].upgradeCost ?? 0; + if (!this.hasBeenPurchased) { + return EmployeeData[this.employeeId].cost; + } + if (this.upgradeTo) { + return EmployeeData[this.upgradeTo].cost; + } + return 0; } get upgradeTo(): EmployeeId | undefined { diff --git a/src/components/EmployeeData.ts b/src/components/EmployeeData.ts index c31ff2f..1020f22 100644 --- a/src/components/EmployeeData.ts +++ b/src/components/EmployeeData.ts @@ -23,7 +23,7 @@ export interface EmployeeInterface { spriteKey: string; // Employee image key walkSpeed: number; // Speed of the employee walking workSpeed: number; // Speed of the employee working - upgradeCost?: number; // Cost to upgrade the employee + cost: number; // Cost to purchase that tier of employee upgradeTo?: EmployeeId; // Employee to upgrade to } @@ -35,7 +35,7 @@ export const EmployeeData: { [key in EmployeeId]: EmployeeInterface } = { spriteKey: "worker", walkSpeed: 1, workSpeed: 1, - upgradeCost: 100, + cost: 1000, upgradeTo: EmployeeId.RaccoonTier2, }, [EmployeeId.RaccoonTier2]: { @@ -45,7 +45,7 @@ export const EmployeeData: { [key in EmployeeId]: EmployeeInterface } = { spriteKey: "worker", walkSpeed: 2, workSpeed: 2, - upgradeCost: 500, + cost: 400, upgradeTo: EmployeeId.RaccoonTier3, }, [EmployeeId.RaccoonTier3]: { @@ -55,6 +55,7 @@ export const EmployeeData: { [key in EmployeeId]: EmployeeInterface } = { spriteKey: "worker", walkSpeed: 3, workSpeed: 3, + cost: 800, }, [EmployeeId.HumanTier1]: { @@ -64,7 +65,7 @@ export const EmployeeData: { [key in EmployeeId]: EmployeeInterface } = { spriteKey: "player", walkSpeed: 1, workSpeed: 1, - upgradeCost: 100, + cost: 1000, upgradeTo: EmployeeId.HumanTier2, }, [EmployeeId.HumanTier2]: { @@ -74,7 +75,7 @@ export const EmployeeData: { [key in EmployeeId]: EmployeeInterface } = { spriteKey: "player", walkSpeed: 2, workSpeed: 2, - upgradeCost: 500, + cost: 400, upgradeTo: EmployeeId.HumanTier3, }, [EmployeeId.HumanTier3]: { @@ -84,5 +85,6 @@ export const EmployeeData: { [key in EmployeeId]: EmployeeInterface } = { spriteKey: "player", walkSpeed: 3, workSpeed: 3, + cost: 800, }, }; diff --git a/src/components/Levels.ts b/src/components/Levels.ts index ccae925..3680a31 100644 --- a/src/components/Levels.ts +++ b/src/components/Levels.ts @@ -37,10 +37,10 @@ export const LevelData: Level[] = [ cellSize: 190, grid: [ [X, X, X, X, X, X, X, X], + [X, 2, _, 9, 9, _, 4, X], [X, 2, _, 3, 3, _, 4, X], - [X, 2, _, _, _, _, 4, X], - [_, _, _, 5, 5, _, _, X], - [X, 9, 9, _, _, 6, _, _], + [_, _, _, _, _, _, _, X], + [X, _, 5, 5, _, 6, _, _], [X, X, X, X, X, X, X, X], ], customerArrivalTimes: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90], @@ -67,10 +67,10 @@ export const LevelData: Level[] = [ }, { id: LevelId.Level3, - background: "grid3", + background: "grid2", width: 8 + 2, height: 6 + 2, - cellSize: 109, + cellSize: 138, grid: [ [X, X, X, X, X, X, X, X, X, X], [X, 2, _, _, _, _, _, _, _, X], diff --git a/src/components/Station.ts b/src/components/Station.ts index 8473e68..e7d0505 100644 --- a/src/components/Station.ts +++ b/src/components/Station.ts @@ -14,8 +14,8 @@ import { TextEffect } from "./TextEffect"; export class Station extends Button { public stationId: StationId; + public hasBeenPurchased: boolean; public currentCustomer: Customer | null; // The customer using the station - //public taskDuration: number; // Time it takes to complete a task public taskSpeed: number = 1; // For permanent bonuses //temp variables @@ -54,6 +54,9 @@ export class Station extends Button { this.cellSize = cellSize; this.currentCustomer = null; + // Initially not purchased + this.hasBeenPurchased = false; + /* Sprite */ this.spriteCont = this.scene.add.container(0, this.spriteOffset); this.add(this.spriteCont); @@ -109,7 +112,8 @@ export class Station extends Button { } update(time: number, delta: number) { - const squish = 1.0 + 0.02 * Math.sin((6 * time) / 1000); + const amount = this.hasBeenPurchased ? 0.02 : 0; + const squish = 1.0 + amount * Math.sin((6 * time) / 1000); this.spriteCont.setScale(1.0, squish - 0.2 * this.holdSmooth); } @@ -124,7 +128,7 @@ export class Station extends Button { ? (this.taskHaste *= this.currentCustomer.workMultiplier) : (this.taskHaste *= 1); this.parseItems(); - if(this.queueFail) { + if (this.queueFail) { this.scene.sound.play("rip"); } else { this.playJingle(); @@ -222,7 +226,12 @@ export class Station extends Button { } upgrade() { - if (this.upgradeTo) { + // this.scene.sound.play("upgrade"); + + if (!this.hasBeenPurchased) { + this.hasBeenPurchased = true; + this.setAlpha(1.0); + } else if (this.upgradeTo) { this.stationId = this.upgradeTo!; this.sprite.setTexture(this.spriteKey); this.spriteCont.y = this.spriteOffset; @@ -280,15 +289,17 @@ export class Station extends Button { //this.scene.sound.play("meme_explosion_sound"); } - playJingle(){ - switch(this.stationType){ + playJingle() { + switch (this.stationType) { case StationType.ScalePolish: { this.scene.sound.play("polish"); break; - } case StationType.GoldBath: { + } + case StationType.GoldBath: { this.scene.sound.play("goldbath"); break; - } case StationType.HornAndNails: { + } + case StationType.HornAndNails: { this.scene.sound.play("snip"); break; } @@ -334,7 +345,13 @@ export class Station extends Button { } get upgradeCost(): number { - return StationData[this.stationId].upgradeCost ?? 0; + if (!this.hasBeenPurchased) { + return StationData[this.stationId].cost; + } + if (this.upgradeTo) { + return StationData[this.upgradeTo].cost; + } + return 0; } get upgradeTo(): StationId | undefined { diff --git a/src/components/StationData.ts b/src/components/StationData.ts index fa5a0b9..7dd6a2d 100644 --- a/src/components/StationData.ts +++ b/src/components/StationData.ts @@ -62,7 +62,7 @@ export interface StationInterface { spriteScale: number; // Multiplier for sprite size taskDuration?: number; // Time it takes to complete a task admissionFee?: number; // Customer pays this amount to use the station - upgradeCost?: number; // Cost to upgrade the station + cost: number; // Cost to purchase the station upgradeTo?: StationId; // Station to upgrade to } @@ -73,7 +73,7 @@ export const StationData: { [key in StationId]: StationInterface } = { tier: 1, spriteKey: "waitchair_1", spriteScale: 1.0, - upgradeCost: 100, + cost: 100, upgradeTo: StationId.WaitingSeatTier2, }, [StationId.WaitingSeatTier2]: { @@ -82,7 +82,7 @@ export const StationData: { [key in StationId]: StationInterface } = { tier: 2, spriteKey: "waitchair_2", spriteScale: 1.25, - upgradeCost: 500, + cost: 250, upgradeTo: StationId.WaitingSeatTier3, }, [StationId.WaitingSeatTier3]: { @@ -91,6 +91,7 @@ export const StationData: { [key in StationId]: StationInterface } = { tier: 3, spriteKey: "waitchair_3", spriteScale: 1.5, + cost: 500, }, [StationId.HornAndNailsTier1]: { @@ -101,7 +102,7 @@ export const StationData: { [key in StationId]: StationInterface } = { spriteScale: 1.0, taskDuration: 3000, admissionFee: 20, - upgradeCost: 100, + cost: 150, upgradeTo: StationId.HornAndNailsTier2, }, [StationId.HornAndNailsTier2]: { @@ -112,7 +113,7 @@ export const StationData: { [key in StationId]: StationInterface } = { spriteScale: 1.25, taskDuration: 2500, admissionFee: 40, - upgradeCost: 300, + cost: 250, upgradeTo: StationId.HornAndNailsTier3, }, [StationId.HornAndNailsTier3]: { @@ -123,6 +124,7 @@ export const StationData: { [key in StationId]: StationInterface } = { spriteScale: 1.5, taskDuration: 2000, admissionFee: 60, + cost: 400, }, [StationId.ScalePolishTier1]: { @@ -133,7 +135,7 @@ export const StationData: { [key in StationId]: StationInterface } = { spriteScale: 1.0, taskDuration: 2000, admissionFee: 10, - upgradeCost: 150, + cost: 100, upgradeTo: StationId.ScalePolishTier2, }, [StationId.ScalePolishTier2]: { @@ -144,7 +146,7 @@ export const StationData: { [key in StationId]: StationInterface } = { spriteScale: 1.25, taskDuration: 1500, admissionFee: 20, - upgradeCost: 400, + cost: 250, upgradeTo: StationId.ScalePolishTier3, }, [StationId.ScalePolishTier3]: { @@ -155,6 +157,7 @@ export const StationData: { [key in StationId]: StationInterface } = { spriteScale: 1.5, taskDuration: 1000, admissionFee: 30, + cost: 500, }, [StationId.GoldBathTier1]: { @@ -165,7 +168,7 @@ export const StationData: { [key in StationId]: StationInterface } = { spriteScale: 1.0, taskDuration: 4000, admissionFee: 20, - upgradeCost: 200, + cost: 200, upgradeTo: StationId.GoldBathTier2, }, [StationId.GoldBathTier2]: { @@ -176,7 +179,7 @@ export const StationData: { [key in StationId]: StationInterface } = { spriteScale: 1.25, taskDuration: 3000, admissionFee: 30, - upgradeCost: 600, + cost: 350, upgradeTo: StationId.GoldBathTier3, }, [StationId.GoldBathTier3]: { @@ -187,6 +190,7 @@ export const StationData: { [key in StationId]: StationInterface } = { spriteScale: 1.5, taskDuration: 2000, admissionFee: 40, + cost: 600, }, [StationId.CashRegister]: { @@ -196,5 +200,6 @@ export const StationData: { [key in StationId]: StationInterface } = { spriteKey: "checkout", spriteScale: 1.4, taskDuration: 500, + cost: 0, }, }; diff --git a/src/components/UI.ts b/src/components/UI.ts index 55f28db..bb64b9c 100644 --- a/src/components/UI.ts +++ b/src/components/UI.ts @@ -83,6 +83,7 @@ export class UI extends Phaser.GameObjects.Container { this.newLocationButton.on("click", () => { this.emit("nextLevel"); }); + this.newLocationButton.setVisible(false); } update(time: number, delta: number) {} diff --git a/src/components/UpgradeOverlay.ts b/src/components/UpgradeOverlay.ts index 5d99326..4c937d6 100644 --- a/src/components/UpgradeOverlay.ts +++ b/src/components/UpgradeOverlay.ts @@ -102,7 +102,7 @@ export class UpgradeOverlay extends Phaser.GameObjects.Container { } // Upgrade text if there is an upgrade available - if (station.upgradeTo) { + if (station.upgradeTo && station.hasBeenPurchased) { const nextData = StationData[station.upgradeTo]; const durationDiff = nextData.taskDuration! - station.taskDuration; const revenueDiff = nextData.admissionFee! - station.admissionFee; @@ -118,9 +118,6 @@ export class UpgradeOverlay extends Phaser.GameObjects.Container { text += `Revenue: $${station.admissionFee} (+$${revenueDiff})\n`; } this.moneyText.setText(text); - - this.buyButton.setVisible(true); - this.buyButton.setText(`$${station.upgradeCost}`); } // Otherwise, show current stats else { @@ -129,13 +126,13 @@ export class UpgradeOverlay extends Phaser.GameObjects.Container { text += `Duration: ${station.taskDuration / 1000}s\n`; text += `Revenue: $${station.admissionFee}\n`; this.moneyText.setText(text); - - this.buyButton.setVisible(false); } // Enable/disable buy button const canAfford = station.upgradeCost <= this.scene.money; this.buyButton.setEnabled(canAfford); + this.buyButton.setVisible(!!station.upgradeTo || !station.hasBeenPurchased); + this.buyButton.setText(`$${station.upgradeCost}`); this.open(); } @@ -155,7 +152,7 @@ export class UpgradeOverlay extends Phaser.GameObjects.Container { } // Upgrade text if there is an upgrade available - if (employee.upgradeTo) { + if (employee.upgradeTo && employee.hasBeenPurchased) { const nextData = EmployeeData[employee.upgradeTo]; const walkDiff = nextData.walkSpeed! - employee.walkSpeed; const workDiff = nextData.workSpeed! - employee.workSpeed; @@ -167,7 +164,6 @@ export class UpgradeOverlay extends Phaser.GameObjects.Container { this.moneyText.setText(text); this.buyButton.setVisible(true); - this.buyButton.setText(`$${employee.upgradeCost}`); } // Otherwise, show current stats else { @@ -176,13 +172,15 @@ export class UpgradeOverlay extends Phaser.GameObjects.Container { text += `Walk speed: ${employee.walkSpeed}\n`; text += `Work speed: ${employee.workSpeed}\n`; this.moneyText.setText(text); - - this.buyButton.setVisible(false); } // Enable/disable buy button const canAfford = employee.upgradeCost <= this.scene.money; this.buyButton.setEnabled(canAfford); + this.buyButton.setVisible( + !!employee.upgradeTo || !employee.hasBeenPurchased + ); + this.buyButton.setText(`$${employee.upgradeCost}`); this.open(); } diff --git a/src/scenes/GameScene.ts b/src/scenes/GameScene.ts index c85d6fd..d0c2a68 100644 --- a/src/scenes/GameScene.ts +++ b/src/scenes/GameScene.ts @@ -59,6 +59,12 @@ export class GameScene extends BaseScene { angryCustomers: number; }; + // Keeps track of made purchases when starting a level + public savedPurchases: { + stations: StationId[]; + employees: EmployeeId[]; + }; + constructor() { super({ key: "GameScene" }); } @@ -72,6 +78,14 @@ export class GameScene extends BaseScene { // Reset daily stats this.dailyStats = { money: 0, happyCustomers: 0, angryCustomers: 0 }; + this.savedPurchases = { + stations: [ + StationId.WaitingSeatTier1, + StationId.HornAndNailsTier1, + StationId.CashRegister, + ], + employees: [EmployeeId.RaccoonTier1], + }; // Background this.background = this.add.image(0, 0, "grid1"); @@ -92,7 +106,6 @@ export class GameScene extends BaseScene { this.intermission.setDepth(10000); this.intermission.on("close", () => { this.intermission.fadeToGame(); - // this.startLevel(levels[this.levelIndex]); }); this.intermission.on("nextLevel", () => { const nextLevel = { @@ -148,13 +161,15 @@ export class GameScene extends BaseScene { this.money -= station.upgradeCost; this.ui.setMoney(this.money); station.upgrade(); - this.upgradeOverlay.selectStation(station); + this.upgradeOverlay.close(); + // this.upgradeOverlay.selectStation(station); }); this.upgradeOverlay.on("upgradeEmployee", (employee: Employee) => { this.money -= employee.upgradeCost; this.ui.setMoney(this.money); employee.upgrade(); - this.upgradeOverlay.selectEmployee(employee); + // this.upgradeOverlay.selectEmployee(employee); + this.upgradeOverlay.close(); }); this.upgradeOverlay.on("close", () => { this.sortDepth(); @@ -247,11 +262,22 @@ export class GameScene extends BaseScene { this.state = state; const isShopping = state === GameState.Shopping; - - this.stations.forEach((s) => s.setClickable(isShopping)); - this.employees.forEach((e) => e.setClickable(isShopping)); this.ui.setShoppingMode(isShopping); - if (isShopping && this.day > 0) this.summaryOverlay.open(this.dailyStats); + + // Make unpurchased objects are visible only during shopping + const unpurchasedAlpha = 0.2; + this.stations.forEach((s) => { + s.setClickable(isShopping); + s.setAlpha(s.hasBeenPurchased ? 1 : isShopping ? unpurchasedAlpha : 0); + }); + this.employees.forEach((e) => { + e.setClickable(isShopping); + e.setAlpha(e.hasBeenPurchased ? 1 : isShopping ? unpurchasedAlpha : 0); + }); + + if (isShopping && this.day > 0) { + this.summaryOverlay.open(this.dailyStats); + } } // Load level data @@ -303,6 +329,19 @@ export class GameScene extends BaseScene { } } } + + this.savedPurchases.stations.forEach((id) => { + const station = this.stations.find((s) => s.stationId === id); + if (station) { + station.upgrade(); + } + }); + this.savedPurchases.employees.forEach((id) => { + const employee = this.employees.find((e) => e.employeeId === id); + if (employee) { + employee.upgrade(); + } + }); } // Start a new day @@ -496,8 +535,6 @@ export class GameScene extends BaseScene { }); */ - - // Customer leaving the game customer.on("offscreen", () => { this.customers = this.customers.filter((c) => c !== customer); @@ -532,7 +569,10 @@ export class GameScene extends BaseScene { // Get available seat for new customers to go to getAvailableWaitingSeat() { return this.stations.find( - (s) => s.stationType === StationType.WaitingSeat && !s.currentCustomer + (s) => + s.stationType === StationType.WaitingSeat && + s.hasBeenPurchased && + !s.currentCustomer ); } @@ -550,6 +590,7 @@ export class GameScene extends BaseScene { station.y ); if ( + station.hasBeenPurchased && !station.currentCustomer && distance < closestDistance && distance < maxDistance && @@ -579,7 +620,11 @@ export class GameScene extends BaseScene { employee.x, employee.y ); - if (!employee.currentCustomer && distance < closestDistance) { + if ( + employee.hasBeenPurchased && + !employee.currentCustomer && + distance < closestDistance + ) { closestEmployee = employee; closestDistance = distance; } @@ -601,18 +646,28 @@ export class GameScene extends BaseScene { // Generate a list of requests for the customer setCustomerItinerary(customer: Customer) { + // Check availibility of stations + const check = (type: StationType) => { + return this.stations.some( + (s) => s.stationType === type && s.hasBeenPurchased + ); + }; + const hornNailsAvailable = check(StationType.HornAndNails); + const scalePolishAvailable = check(StationType.ScalePolish); + const goldBathAvailable = check(StationType.GoldBath); + function getActivities() { let activities = []; - if (Math.random() < 0.5) { + if (hornNailsAvailable && Math.random() < 0.6) { activities.push(StationType.HornAndNails); } - if (Math.random() < 0.5) { + if (scalePolishAvailable && Math.random() < 0.6) { activities.push(StationType.ScalePolish); } - if (Math.random() < 0.5) { + if (goldBathAvailable && Math.random() < 0.6) { activities.push(StationType.GoldBath); } - //activities.push(StationType.CashRegister); + activities.push(StationType.CashRegister); return activities; }