X-Git-Url: https://git.xangelo.ca/?p=sketchy-heroes.git;a=blobdiff_plain;f=src%2Froutes%2Ffight%2Ffight.ts;fp=src%2Froutes%2Ffight%2Ffight.ts;h=8c3ca0b51d175601dc4638bf2ea1d5601895df5c;hp=0000000000000000000000000000000000000000;hb=7aa7248bc4f3f59a002beb98fa889a9da3c25866;hpb=9cec2c639563092ed050716db1e7e4657f937bf5 diff --git a/src/routes/fight/fight.ts b/src/routes/fight/fight.ts new file mode 100644 index 0000000..8c3ca0b --- /dev/null +++ b/src/routes/fight/fight.ts @@ -0,0 +1,208 @@ +import { server } from '../../lib/server'; +import { Static, Type } from '@sinclair/typebox'; +import { prisma } from '../../lib/db'; +import { ForbiddenError } from '../../lib/http-errors'; +import {Fight, Player} from '@prisma/client'; +import {maxExp, maxHp} from '../../formulas'; + + +const FightRoundInput = Type.Object({ + params: Type.Object({ + playerId: Type.String(), + fightId: Type.String() + }), + body: Type.Object({ + action: Type.String() + }) +}); + +type FightRoundInputType = Static; + +export type RoundData = { + attacker: string; + defender: string; + damage: number; +} + +export type FightRoundOutput = { + player: Player, + monster: Fight, + winner: 'monster' | 'player' | 'flee', + roundData: RoundData[], + reward: any +} + +function round(player: Player, monster: Fight): FightRoundOutput { + + const roundData: RoundData[] = []; + if(player.stamina <= 0 || player.hp <= 0) { + return { + player: player, + monster: monster, + winner: 'monster', + roundData: roundData, + reward: {} + }; + } + + const first = player.woosh >= monster.woosh ? player : monster; + const second = player.woosh >= monster.woosh ? monster : player; + + + while(first.hp > 0 && second.hp > 0) { + // eventually these will include weapon and skill damage + const firstDamage = first.pow; + const secondDamage = second.pow; + + second.hp -= firstDamage; + roundData.push({ + attacker: first.id, + defender: second.id, + damage: firstDamage + }); + + if(second.hp > 0) { + first.hp -= secondDamage; + roundData.push({ + attacker: second.id, + defender: first.id, + damage: secondDamage + }) + } + } + + + // now we figure out who won! + if(player.hp <= 0) { + // the player lost + player.hp = 0; + + return { + player: player, + monster: monster, + winner: 'monster', + roundData: roundData, + reward: {} + } + } + else { + return { + player: player, + monster: monster, + winner: 'player', + roundData: roundData, + reward: { + exp: monster.exp, + currency: monster.currency + } + } + } + +} + +export const fightRound = server.post('/v1/accounts/:playerId/fight/:fightId/round', { + schema: FightRoundInput, + authenicated: true +}, async req => { + + const [fight, player] = await prisma.$transaction([ + prisma.fight.findUnique({ + where: { + id: req.params.fightId + } + }), + prisma.player.findUnique({ + where: { + id: req.params.playerId + } + }) + ]); + + if(!player) { + throw new ForbiddenError('Not a valid fight'); + } + + if(!fight) { + throw new ForbiddenError('Not a real fight'); + } + + if(fight.playerId !== req.params.playerId) { + throw new ForbiddenError('Not a real fight'); + } + + if(req.body.action === 'Flee') { + await prisma.fight.delete({ + where: { + id: req.params.fightId + } + }); + + return { + player: player, + monster: fight, + winner: 'flee', + reward: {}, + roundData: [] + } + } + + if(req.body.action === 'Fight') { + const output = round(player, fight); + if(output.winner === 'monster') { + await prisma.$transaction([ + prisma.fight.delete({ + where: { + id: fight.id + } + }), + prisma.player.update({ + where: { + id: player.id + }, + data: { + hp: 0 + } + }) + ]); + } + else if(output.winner === 'player') { + player.currency += fight.currency; + player.exp += fight.exp; + while(player.exp >= maxExp(player.level)) { + player.exp -= maxExp(player.level); + player.level++; + player.statPoints++; + player.hp = maxHp(player.level, player.zest); + } + + await prisma.$transaction([ + prisma.fight.delete({ + where: { + id: fight.id + } + }), + prisma.player.update({ + where: { + id: player.id + }, + data: { + hp: player.hp, + exp: player.exp, + level: player.level, + currency: player.currency, + stamina: player.stamina--, + statPoints: player.statPoints + } + }) + ]); + + // update the player with the new data + output.player = player; + } + + return output; + } + + throw new ForbiddenError('You can not do that in a fight'); + +});