Compare commits

..

No commits in common. "59c7f62814bd70ffe73e24e3f9a1679b88e66950" and "c5743a4a791c76093dc52054a9b3e34b40a4dcc2" have entirely different histories.

3 changed files with 260 additions and 267 deletions

View File

@ -3,7 +3,6 @@ import { MessageService, MessageFileName } from '../utils/MessageService'
import { CommentPoster } from '../rdrama/services/CommentPoster';
import { RidersPhase } from './phases/riders';
import { HuntPhase } from './phases/hunt';
import { HandleSetup } from './phases/setup';
class GameFlow {
gameState: GameState;
@ -18,7 +17,7 @@ class GameFlow {
switch (this.gameState.phase) {
case PHASE_ENUM.SETUP:
// Handle the setup phase, e.g., initial purchases
await HandleSetup.handleSetupPhase(this.gameState, this, userInput);
await this.handleSetupPhase(userInput);
break;
case PHASE_ENUM.START_TURN:
await this.startTurn();
@ -32,7 +31,7 @@ class GameFlow {
break;
case PHASE_ENUM.FORT:
// Handle interactions at the fort
await HandleSetup.handleSetupPhase(this.gameState, this, userInput);
await this.handleSetupPhase(userInput);
break;
case PHASE_ENUM.HUNT:
// Handle hunting logic
@ -121,6 +120,243 @@ class GameFlow {
return 'Unknown Quality';
}
private async handleSetupPhase(userInput?: string): Promise<void> {
userInput = userInput?.toLowerCase()
let responseMessage = "";
// Logic to handle initial setup
switch (this.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 = this.handleWeaponPurchase(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
this.gameState.subPhase++;
return this.handleSetupPhase();
} 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 = this.handleGenericPurchase(PurchaseOption.OXEN, userInput, 200, 300);
if (purchaseResult.success) {
this.gameState.subPhase++;
return this.handleSetupPhase(); // 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 = this.handleGenericPurchase(PurchaseOption.FOOD, userInput);
if (purchaseResult.success) {
this.gameState.subPhase++;
return this.handleSetupPhase(); // 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 = this.handleGenericPurchase(PurchaseOption.AMMO, userInput);
if (purchaseResult.success) {
this.gameState.subPhase++;
return this.handleSetupPhase(); // 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 = this.handleGenericPurchase(PurchaseOption.CLOTHING, userInput);
if (purchaseResult.success) {
this.gameState.subPhase++;
return this.handleSetupPhase(); // 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 = this.handleGenericPurchase(PurchaseOption.MISC, userInput);
if (purchaseResult.success) {
this.gameState.subPhase++;
return this.handleSetupPhase(); // Call setup phase again for next subphase
} else {
responseMessage = purchaseResult.errorMessage || '';
responseMessage += `\n\n${MessageService.getRandomMessage(
MessageFileName.Oregon_MiscSuppliesPurchase,
{}
)}`
}
}
break;
case 6:
//Advance Phase
this.gameState.subPhase = 0;
this.gameState.phase === PHASE_ENUM.SETUP ? this.gameState.phase = PHASE_ENUM.START_TURN : this.gameState.phase = PHASE_ENUM.ACTION_CHOICE;
await this.gameState.save()
this.executeCurrentPhase()
break;
default:
responseMessage = `@J something went wrong come and fix it.\n\n ${JSON.stringify(this.gameState, null, 4)}`
break;
}
await this.statusUpdate(responseMessage)
return;
}
handleWeaponPurchase(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 (this.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 $${this.gameState.cashLeftAfterInitialPurchases} remaining.`
};
}
// Update gameState with the selected weapon and deduct the cost
this.gameState.shootingExpertiseLevelChoice = parseInt(userInput);
this.gameState.cashLeftAfterInitialPurchases -= selectedWeapon.cost;
// Return a success object, indicating the purchase was successful
return {
success: true
};
}
handleGenericPurchase(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 (this.gameState.cashLeftAfterInitialPurchases < totalCost) {
return {
success: false,
errorMessage: `⚠️ You do not have enough money to purchase ${amount} units of ${itemType}. You have $${this.gameState.cashLeftAfterInitialPurchases} remaining.`
};
}
let modifier: number
this.gameState.phase !== PHASE_ENUM.FORT ? modifier = 1 : modifier = 2 / 3;
// Update gameState based on itemType
switch (itemType) {
case PurchaseOption.OXEN:
//Round down after multiplication
this.gameState.amountSpentOnAnimals += Math.floor(totalCost * modifier);
break;
case PurchaseOption.FOOD:
this.gameState.amountSpentOnFood += Math.floor(totalCost * modifier);
break;
case PurchaseOption.AMMO:
this.gameState.amountSpentOnAmmunition += Math.floor(totalCost * 50 * modifier);
break;
case PurchaseOption.CLOTHING:
this.gameState.amountSpentOnClothing += Math.floor(totalCost * modifier);
break;
case PurchaseOption.MISC:
this.gameState.amountSpentOnMiscellaneousSupplies += Math.floor(totalCost * modifier);
break;
// Add cases for other item types
}
this.gameState.cashLeftAfterInitialPurchases -= totalCost;
// Optionally, return a success message
return {
success: true
};
}
private cleanupGameState(): void {
// Ensure all expenditures are non-negative
@ -330,3 +566,23 @@ class GameFlow {
export default GameFlow;
interface WeaponOption {
name: string;
cost: number;
}
const weaponOptions: Record<string, WeaponOption> = {
"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',
};

View File

@ -1,264 +0,0 @@
import GameState, { PHASE_ENUM } from '../gameState';
import GameFlow from '../gameFlow';
import { MessageService, MessageFileName } from '../../utils/MessageService'
export class HandleSetup {
static async handleSetupPhase(gameState: GameState, gameFlow: GameFlow, userInput?: string): Promise<void> {
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, gameFlow);
} 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, gameFlow); // 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, gameFlow); // 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, gameFlow); // 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, gameFlow); // 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, gameFlow); // 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()
break;
default:
responseMessage = `@J something went wrong come and fix it.\n\n ${JSON.stringify(gameState, null, 4)}`
break;
}
await gameFlow.statusUpdate(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<string, WeaponOption> = {
"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',
};

View File

@ -1,4 +1,5 @@
import GameState from '../gameState';
import GameFlow from '../gameFlow';
export class HandleShooting {
private static shootingWordVariations: string[] = [