import GameState, { PHASE_ENUM } from '../game/gameState'; import GameFlow from '../game/gameFlow'; import { MessageService, MessageFileName } from '../utils/MessageService' export class HandleSetup { static async handleSetupPhase(gameState: GameState, userInput?: string): Promise { userInput = userInput?.toLowerCase() let responseMessage = ""; // Logic to handle initial setup switch (gameState.subPhase) { case 0: // Weapons Purchase Subphase if (!userInput || userInput === 'start' || userInput === 'restart') { // Send instructions to the user for the current subphase responseMessage = `${MessageService.getRandomMessage( MessageFileName.Oregon_WeaponPurchase, {} )}`; // The lack of userInput argument triggers a request for input. } else { // Process user input here and decide whether to advance subphase or send an error message const purchaseResult = HandleSetup.handleWeaponPurchase(gameState, userInput); if (purchaseResult.success) { // If the purchase was successful, advance to the next subphase and recursively call handleSetupPhase without userInput to get the next set of instructions gameState.subPhase++; return HandleSetup.handleSetupPhase(gameState); } else { // If there was an error, include the error message in responseMessage responseMessage = `${purchaseResult.errorMessage}`; responseMessage += `\n\n${MessageService.getRandomMessage( MessageFileName.Oregon_WeaponPurchase, {} )}` // Do not advance subphase; possibly prompt the same instructions with an error message } } break; case 1: //OXEN TEAM Purchase if (!userInput) { responseMessage = `${MessageService.getRandomMessage( MessageFileName.Oregon_OxenPurchase, {} )}`; } else { const purchaseResult = HandleSetup.handleGenericPurchase(gameState, PurchaseOption.OXEN, userInput, 200, 300); if (purchaseResult.success) { gameState.subPhase++; return HandleSetup.handleSetupPhase(gameState); // Call setup phase again for next subphase } else { responseMessage = purchaseResult.errorMessage || ''; responseMessage += `\n\n${MessageService.getRandomMessage( MessageFileName.Oregon_OxenPurchase, {} )}` } } break; case 2: //FOOD Purchase if (!userInput) { responseMessage = `${MessageService.getRandomMessage( MessageFileName.Oregon_FoodPurchase, {} )}`; } else { const purchaseResult = HandleSetup.handleGenericPurchase(gameState, PurchaseOption.FOOD, userInput); if (purchaseResult.success) { gameState.subPhase++; return HandleSetup.handleSetupPhase(gameState); // Call setup phase again for next subphase } else { responseMessage = purchaseResult.errorMessage || ''; responseMessage += `\n\n${MessageService.getRandomMessage( MessageFileName.Oregon_FoodPurchase, {} )}` } } break; case 3: //AMMUNITION Purchase if (!userInput) { responseMessage = `${MessageService.getRandomMessage( MessageFileName.Oregon_AmmoPurchase, {} )}`; } else { const purchaseResult = HandleSetup.handleGenericPurchase(gameState, PurchaseOption.AMMO, userInput); if (purchaseResult.success) { gameState.subPhase++; return HandleSetup.handleSetupPhase(gameState); // Call setup phase again for next subphase } else { responseMessage = purchaseResult.errorMessage || ''; responseMessage += `\n\n${MessageService.getRandomMessage( MessageFileName.Oregon_AmmoPurchase, {} )}` } } break; case 4: //CLOTHING Purchase if (!userInput) { responseMessage = `${MessageService.getRandomMessage( MessageFileName.Oregon_ClothingPurchase, {} )}`; } else { const purchaseResult = HandleSetup.handleGenericPurchase(gameState, PurchaseOption.CLOTHING, userInput); if (purchaseResult.success) { gameState.subPhase++; return HandleSetup.handleSetupPhase(gameState); // Call setup phase again for next subphase } else { responseMessage = purchaseResult.errorMessage || ''; responseMessage += `\n\n${MessageService.getRandomMessage( MessageFileName.Oregon_ClothingPurchase, {} )}` } } break; case 5: //MISCELLANEOUS SUPPLIES Purchase if (!userInput) { responseMessage = `${MessageService.getRandomMessage( MessageFileName.Oregon_MiscSuppliesPurchase, {} )}`; } else { const purchaseResult = HandleSetup.handleGenericPurchase(gameState, PurchaseOption.MISC, userInput); if (purchaseResult.success) { gameState.subPhase++; return HandleSetup.handleSetupPhase(gameState); // Call setup phase again for next subphase } else { responseMessage = purchaseResult.errorMessage || ''; responseMessage += `\n\n${MessageService.getRandomMessage( MessageFileName.Oregon_MiscSuppliesPurchase, {} )}` } } break; case 6: //Advance Phase gameState.subPhase = 0; gameState.phase === PHASE_ENUM.SETUP ? gameState.phase = PHASE_ENUM.START_TURN : gameState.phase = PHASE_ENUM.ACTION_CHOICE; await gameState.save() GameFlow.executeCurrentPhase(gameState) break; default: responseMessage = `@J something went wrong come and fix it.\n\n ${JSON.stringify(gameState, null, 4)}` break; } await gameState.save() await MessageService.statusUpdate(gameState, responseMessage) return; } static handleWeaponPurchase(gameState: GameState, userInput: string): { success: boolean; errorMessage?: string } { // Check if the userInput is one of the valid choices if (!Object.keys(weaponOptions).includes(userInput)) { // If the input is not valid, return an error message return { success: false, errorMessage: "⚠️ Invalid choice. Please select a valid weapon option by replying with !!Oregon [choice]." }; } // Check if the user has enough money for the selected weapon const selectedWeapon = weaponOptions[userInput]; if (gameState.cashLeftAfterInitialPurchases < selectedWeapon.cost) { // If not enough money, return an error message return { success: false, errorMessage: `⚠️ You do not have enough money for the ${selectedWeapon.name}. You have $${gameState.cashLeftAfterInitialPurchases} remaining.` }; } // Update gameState with the selected weapon and deduct the cost gameState.shootingExpertiseLevelChoice = parseInt(userInput); gameState.cashLeftAfterInitialPurchases -= selectedWeapon.cost; // Return a success object, indicating the purchase was successful return { success: true }; } static handleGenericPurchase(gameState: GameState, itemType: PurchaseOption, userInput: string, minAmount?: number, maxAmount?: number): { success: boolean; errorMessage?: string; responseMessage?: string } { const amount = parseInt(userInput); if (isNaN(amount) || amount < 0) { return { success: false, errorMessage: "⚠️ Invalid input. Please enter a positive number." }; } if ((maxAmount && amount > maxAmount) || (minAmount && amount < minAmount)) { return { success: false, errorMessage: `⚠️ Invalid input. Please enter a number between ${minAmount} and ${maxAmount}.` }; } const totalCost = amount if (gameState.cashLeftAfterInitialPurchases < totalCost) { return { success: false, errorMessage: `⚠️ You do not have enough money to purchase ${amount} units of ${itemType}. You have $${gameState.cashLeftAfterInitialPurchases} remaining.` }; } let modifier: number gameState.phase !== PHASE_ENUM.FORT ? modifier = 1 : modifier = 2 / 3; // Update gameState based on itemType switch (itemType) { case PurchaseOption.OXEN: //Round down after multiplication gameState.amountSpentOnAnimals += Math.floor(totalCost * modifier); break; case PurchaseOption.FOOD: gameState.amountSpentOnFood += Math.floor(totalCost * modifier); break; case PurchaseOption.AMMO: gameState.amountSpentOnAmmunition += Math.floor(totalCost * 50 * modifier); break; case PurchaseOption.CLOTHING: gameState.amountSpentOnClothing += Math.floor(totalCost * modifier); break; case PurchaseOption.MISC: gameState.amountSpentOnMiscellaneousSupplies += Math.floor(totalCost * modifier); break; // Add cases for other item types } gameState.cashLeftAfterInitialPurchases -= totalCost; // Optionally, return a success message return { success: true }; } } interface WeaponOption { name: string; cost: number; } const weaponOptions: Record = { "1": { name: "Frontiersman's Sharpshooter Rifle", cost: 200 }, "2": { name: "Pioneer's Long Rifle", cost: 150 }, "3": { name: "Settler's Carbine", cost: 100 }, "4": { name: "Homesteader's Musket", cost: 50 }, "5": { name: "Grandpa's Rusty Shotgun", cost: 0 } }; enum PurchaseOption { OXEN = 'oxen', FOOD = 'food', AMMO = 'ammo', CLOTHING = 'clothing', MISC = 'misc', };