1 import { server } from '../../lib/server';
2 import { Static, Type } from '@sinclair/typebox';
3 import { prisma } from '../../lib/db';
4 import { ForbiddenError } from '../../lib/http-errors';
5 import {Fight, Player} from '@prisma/client';
6 import {maxExp, maxHp} from '../../formulas';
9 const FightRoundInput = Type.Object({
11 playerId: Type.String(),
12 fightId: Type.String()
19 type FightRoundInputType = Static<typeof FightRoundInput>;
21 export type RoundData = {
27 export type FightRoundOutput = {
30 winner: 'monster' | 'player' | 'flee',
31 roundData: RoundData[],
35 function round(player: Player, monster: Fight): FightRoundOutput {
37 const roundData: RoundData[] = [];
38 if(player.stamina <= 0 || player.hp <= 0) {
48 const first = player.woosh >= monster.woosh ? player : monster;
49 const second = player.woosh >= monster.woosh ? monster : player;
52 while(first.hp > 0 && second.hp > 0) {
53 // eventually these will include weapon and skill damage
54 const firstDamage = first.pow;
55 const secondDamage = second.pow;
57 second.hp -= firstDamage;
65 first.hp -= secondDamage;
75 // now we figure out who won!
96 currency: monster.currency
103 export const fightRound = server.post<FightRoundInputType, FightRoundOutput>('/v1/accounts/:playerId/fight/:fightId/round', {
104 schema: FightRoundInput,
108 const [fight, player] = await prisma.$transaction([
109 prisma.fight.findUnique({
111 id: req.params.fightId
114 prisma.player.findUnique({
116 id: req.params.playerId
122 throw new ForbiddenError('Not a valid fight');
126 throw new ForbiddenError('Not a real fight');
129 if(fight.playerId !== req.params.playerId) {
130 throw new ForbiddenError('Not a real fight');
133 if(req.body.action === 'Flee') {
134 await prisma.fight.delete({
136 id: req.params.fightId
149 if(req.body.action === 'Fight') {
150 const output = round(player, fight);
151 if(output.winner === 'monster') {
152 await prisma.$transaction([
153 prisma.fight.delete({
158 prisma.player.update({
168 else if(output.winner === 'player') {
169 player.currency += fight.currency;
170 player.exp += fight.exp;
171 while(player.exp >= maxExp(player.level)) {
172 player.exp -= maxExp(player.level);
175 player.hp = maxHp(player.level, player.zest);
178 await prisma.$transaction([
179 prisma.fight.delete({
184 prisma.player.update({
192 currency: player.currency,
193 stamina: player.stamina--,
194 statPoints: player.statPoints
199 // update the player with the new data
200 output.player = player;
206 throw new ForbiddenError('You can not do that in a fight');