From a5824cd510139f9c7ae56a72035f0f50f5cd2d46 Mon Sep 17 00:00:00 2001 From: xangelo Date: Mon, 11 Mar 2024 23:21:50 -0400 Subject: [PATCH] feat: add class stats to professions When you select a profession, there are a certain number of stats that are considered "class stats". They may automatically increases on level up. For example: Warrior class stats: Strength, Constitution. On even level up, you gain +2 strength, +1 constitution On odd level up, you gain +1 strength, +2 constitution Class stats only cost a single stat point to increase, and non-class stats cost 2 stat points. You only ever gain 1 stat point on level up. Wanderers are a special profession that do not gain any stats on level up.. but all stats are considered "class stats" --- src/server/fight.ts | 23 +++++-- src/server/routes/locations/recruiter.ts | 33 ++++----- src/server/routes/profile.ts | 16 ++++- src/shared/profession.ts | 85 ++++++++++++++++++------ 4 files changed, 107 insertions(+), 50 deletions(-) diff --git a/src/server/fight.ts b/src/server/fight.ts index 4515c30..93e9b3c 100644 --- a/src/server/fight.ts +++ b/src/server/fight.ts @@ -12,6 +12,7 @@ import { SkillID, Skills } from '../shared/skills'; import { Request, Response } from 'express'; import * as Alert from './views/alert'; import { addEvent } from './events'; +import { Professions } from '../shared/profession'; export async function blockPlayerInFight(req: Request, res: Response, next: any) { const fight = await loadMonsterFromFight(req.player.id); @@ -186,10 +187,24 @@ export async function fightRound(player: Player, monster: Fight, data: {action: to_level: player.level }); roundData.rewards.levelIncrease = true; - let statPointsGained = 1; - - if(player.profession !== 'Wanderer') { - statPointsGained = 2; + const statPointsGained = 1; + const prof = Professions.get(player.profession); + + if(player.level%2) { + if(prof.levelUpStatIncrease.odd) { + for(let stat in prof.levelUpStatIncrease.odd) { + player[stat] += prof.levelUpStatIncrease.odd[stat]; + roundData.roundDetails.push(`You gained +${prof.levelUpStatIncrease.odd[stat]} ${stat}`); + } + } + } + else { + if(prof.levelUpStatIncrease.even) { + for(let stat in prof.levelUpStatIncrease.even) { + player[stat] += prof.levelUpStatIncrease.even[stat]; + roundData.roundDetails.push(`You gained +${prof.levelUpStatIncrease.even[stat]} ${stat}`); + } + } } player.stat_points += statPointsGained; diff --git a/src/server/routes/locations/recruiter.ts b/src/server/routes/locations/recruiter.ts index 73a3c1a..fd2c816 100644 --- a/src/server/routes/locations/recruiter.ts +++ b/src/server/routes/locations/recruiter.ts @@ -7,6 +7,7 @@ import { changeProfession } from "../../player"; import { renderPlayerBar } from "../../views/player-bar"; import { BackToTown } from "../../views/components/button"; import { MIN_LEVEL_TO_CHANGE_PROFESSIONS } from "../../../shared/constants"; +import { Profession, Professions } from "../../../shared/profession"; function p(str: string) { return `

${str}

`; @@ -38,9 +39,9 @@ recruiterRouter.get('/city/services/profession_recruitor/:location_id', authEndp html.push(`
- - - + + +
`); @@ -87,29 +88,19 @@ recruiterRouter.post('/city/services/profession_change/:location_id', authEndpoi res.sendStatus(400); } - let update: {level: number, exp: number}; + const potentialProfession: Profession = req.body.profession; - switch(req.body.profession.toLowerCase()) { - case 'warrior': - update = await changeProfession(req.player.id, 'Warrior'); - req.player.profession = 'Warrior'; - break; - case 'mage': - update = await changeProfession(req.player.id, 'Mage'); - req.player.profession = 'Mage'; - break; - case 'rogue': - update = await changeProfession(req.player.id, 'Rogue'); - req.player.profession = 'Rogue'; - break; - default: - res.send(Alert.ErrorAlert(`Invalid profession`)); - break; + if(!Professions.has(potentialProfession)) { + res.send(Alert.ErrorAlert(`Invalid profession`)); } + else { + const prof = Professions.get(potentialProfession); + const update = await changeProfession(req.player.id, prof.id); - if(update) { + req.player.profession = prof.id; req.player.level = update.level; req.player.exp = update.exp; + res.send(renderPlayerBar(req.player) + `
Congrats! You are now a ${req.player.profession}
`); } diff --git a/src/server/routes/profile.ts b/src/server/routes/profile.ts index da86864..79b0bd5 100644 --- a/src/server/routes/profile.ts +++ b/src/server/routes/profile.ts @@ -6,6 +6,8 @@ import {maxHp, maxVigor } from '../../shared/player'; import * as Alert from '../views/alert'; import { renderPlayerBar } from '../views/player-bar' import { renderProfilePage } from '../views/profile'; +import { Professions } from '../../shared/profession'; +import { Stat } from '../../shared/stats'; export const profileRouter = Router(); @@ -16,18 +18,26 @@ profileRouter.get('/player', authEndpoint, async (req: Request, res: Response) = profileRouter.post('/player/stat/:stat', authEndpoint, async (req: Request, res: Response) => { const equipment = await getEquippedItems(req.player.id); - const stat = req.params.stat; + const profession = Professions.get(req.player.profession); + const stat = req.params.stat as Stat; + let statIncreaseCost = 2; if(!['strength', 'constitution', 'dexterity', 'intelligence'].includes(stat)) { res.send(Alert.ErrorAlert(`Sorry, that's not a valid stat to increase`)); return; } - if(req.player.stat_points <= 0) { + + // class stats cost 1 + if(profession.classStats.includes(stat)) { + statIncreaseCost = 1; + } + + if(req.player.stat_points < statIncreaseCost) { res.send(Alert.ErrorAlert(`Sorry, you don't have enough stat points`)); return; } - req.player.stat_points -= 1; + req.player.stat_points -= statIncreaseCost; req.player[stat]++; req.player.hp = maxHp(req.player.constitution, req.player.level); diff --git a/src/shared/profession.ts b/src/shared/profession.ts index ed8097a..3a7f488 100644 --- a/src/shared/profession.ts +++ b/src/shared/profession.ts @@ -2,31 +2,72 @@ import { Stat } from './stats'; export type Profession = 'Wanderer' | 'Warrior' | 'Mage' | 'Rogue'; +export type ProfessionStatBoost = { + [key in Stat]?: number +}; + export type ProfessionDefinition = { id: Profession; name: string; - classStats: Stat[] + classStats: Stat[]; + levelUpStatIncrease: { + even?: ProfessionStatBoost, + odd?: ProfessionStatBoost + } } -export const professionList: Record = { - 'Wanderer': { - id: 'Wanderer', - name: 'Wanderer', - classStats: [Stat.strength, Stat.constitution, Stat.dexterity, Stat.intelligence] - }, - 'Warrior': { - id: 'Warrior', - name: 'Warrior', - classStats: [Stat.strength, Stat.constitution] - }, - 'Mage': { - id: 'Mage', - name: 'Mage', - classStats: [Stat.intelligence, Stat.constitution] - }, - 'Rogue': { - id: 'Rogue', - name: 'Rogue', - classStats: [Stat.dexterity, Stat.constitution] +export const Professions: Map = new Map(); + +Professions.set('Wanderer', { + id: 'Wanderer', + name: 'Wanderer', + classStats: [Stat.strength, Stat.constitution, Stat.dexterity, Stat.intelligence], + levelUpStatIncrease: {} +}); + +Professions.set('Warrior', { + id: 'Warrior', + name: 'Warrior', + classStats: [Stat.strength, Stat.constitution], + levelUpStatIncrease: { + even: { + [Stat.strength]: 2, + [Stat.constitution]: 1 + }, + odd: { + [Stat.strength]: 1, + [Stat.constitution]: 1 + } } -}; +}); + +Professions.set('Mage', { + id: 'Mage', + name: 'Mage', + classStats: [Stat.intelligence, Stat.constitution], + levelUpStatIncrease: { + even: { + [Stat.intelligence]: 2, + [Stat.constitution]: 1 + }, + odd: { + [Stat.intelligence]: 2 + } + } +}); + +Professions.set('Rogue', { + id: 'Rogue', + name: 'Rogue', + classStats: [Stat.dexterity, Stat.strength], + levelUpStatIncrease: { + even: { + [Stat.dexterity]: 2, + [Stat.strength]: 1 + }, + odd: { + [Stat.dexterity]: 1, + [Stat.strength]: 2 + } + } +}); -- 2.25.1