Feat : add most token effects
This commit is contained in:
@@ -28,8 +28,11 @@ import { Card } from 'src/cards/schemas/cards.schema';
|
||||
import { EffectPipe } from '../pipe/effect.pipe';
|
||||
import { Effect } from 'src/cards/schemas/effect.schema';
|
||||
import { GameService } from '../services/games.service';
|
||||
import { CardEffects } from 'src/cards/schemas/cards.types';
|
||||
import { CardEffects, CardType } from 'src/cards/schemas/cards.types';
|
||||
import { UseTokenDTO } from '../dto/use-token-dto';
|
||||
import { DamagePlayerDTO } from '../dto/damage-player-dto';
|
||||
import { DamageChampionDTO } from '../dto/damage-champion-dto';
|
||||
import { equal } from 'assert';
|
||||
|
||||
@ApiTags('turn')
|
||||
@Controller('games/:gameId/turn')
|
||||
@@ -228,18 +231,27 @@ export class TurnController {
|
||||
throw new HttpException('Token not found', HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
const targetPlayer = findPlayer(useTokenDto.playerId, game);
|
||||
|
||||
const enemyTargetToken = [
|
||||
const enemyTargetTokens = [
|
||||
CardEffects.STUN,
|
||||
CardEffects.CONTROL_OPPOSING_CHAMPION_PASSIVE,
|
||||
];
|
||||
|
||||
const marketTokens = [
|
||||
CardEffects.STACK_NEXT_ACTION_BOUGHT,
|
||||
CardEffects.STACK_NEXT_CARD_BOUGHT,
|
||||
];
|
||||
|
||||
let targetCard: Card;
|
||||
if (enemyTargetToken.includes(token.effect)) {
|
||||
let targetPlayer = currentPlayer;
|
||||
if (enemyTargetTokens.includes(token.effect)) {
|
||||
targetPlayer = findPlayer(useTokenDto.playerId, game);
|
||||
targetCard = targetPlayer.board.cards.find((c) =>
|
||||
c._id.equals(useTokenDto.cardId),
|
||||
);
|
||||
} else if (marketTokens.includes(token.effect)) {
|
||||
targetCard =
|
||||
game.market.cards.find((c) => c._id.equals(useTokenDto.cardId)) ??
|
||||
game.fireGems.cards.find((c) => c._id.equals(useTokenDto.cardId));
|
||||
} else {
|
||||
targetCard = currentPlayer.board.cards.find((c) =>
|
||||
c._id.equals(useTokenDto.cardId),
|
||||
@@ -249,6 +261,82 @@ export class TurnController {
|
||||
if (!targetCard) {
|
||||
throw new HttpException('Card not found', HttpStatus.NOT_FOUND);
|
||||
}
|
||||
await this.turnService.useToken(game, currentPlayer, token, targetCard);
|
||||
await this.turnService.useToken(game, targetPlayer, token, targetCard);
|
||||
}
|
||||
|
||||
@Post('damagePlayer/:playerId')
|
||||
@ApiOperation({ summary: 'Consume damage points to damage a player' })
|
||||
@UseGuards(AuthGuard)
|
||||
async damagePlayer(
|
||||
@Param('gameId') _gameId: string,
|
||||
@Param('playerId') playerId: string,
|
||||
@Param('gameId', GameStartedPipe) game: Document<Game> & Game,
|
||||
@Body() damagePlayerDTO: DamagePlayerDTO,
|
||||
@Session() session: Record<string, string>,
|
||||
) {
|
||||
const currentPlayer = getPlayer(session, game);
|
||||
const currentTeam = getCurrentTeam(game);
|
||||
if (!isInTeam(currentTeam, currentPlayer)) {
|
||||
throw new HttpException(
|
||||
'It is not your turn to play',
|
||||
HttpStatus.FORBIDDEN,
|
||||
);
|
||||
}
|
||||
if (damagePlayerDTO.amount > game.currentTurn.damage) {
|
||||
throw new HttpException(
|
||||
'You cannot deal more damage than what your current damage points',
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
|
||||
const targetPlayer = findPlayer(playerId, game);
|
||||
await this.turnService.damagePlayer(
|
||||
game,
|
||||
damagePlayerDTO.amount,
|
||||
currentPlayer,
|
||||
targetPlayer,
|
||||
);
|
||||
}
|
||||
|
||||
@Post('damageChampion/:cardId')
|
||||
@ApiOperation({ summary: 'Consume damage points to stun a champion' })
|
||||
@UseGuards(AuthGuard)
|
||||
async damageChampion(
|
||||
@Param('gameId') _gameId: string,
|
||||
@Param('cardId') _cardId: string,
|
||||
@Param('gameId', GameStartedPipe) game: Document<Game> & Game,
|
||||
@Param('cardId', CardPipe) card: Document<Card> & Card,
|
||||
@Body() damageChampion: DamageChampionDTO,
|
||||
@Session() session: Record<string, string>,
|
||||
) {
|
||||
const currentPlayer = getPlayer(session, game);
|
||||
const currentTeam = getCurrentTeam(game);
|
||||
if (!isInTeam(currentTeam, currentPlayer)) {
|
||||
throw new HttpException(
|
||||
'It is not your turn to play',
|
||||
HttpStatus.FORBIDDEN,
|
||||
);
|
||||
}
|
||||
if (card.defense > game.currentTurn.damage) {
|
||||
throw new HttpException(
|
||||
'You cannot deal more damage than what your current damage points',
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
|
||||
const targetPlayer = findPlayer(damageChampion.player, game);
|
||||
if (!targetPlayer) {
|
||||
throw new HttpException('Player not found', HttpStatus.NOT_FOUND);
|
||||
}
|
||||
if (card.cardType != CardType.CHAMPION) {
|
||||
throw new HttpException('Card is not a champion', HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
if (!targetPlayer.board.cards.some((c) => c._id.equals(card._id))) {
|
||||
throw new HttpException(
|
||||
'Champion not found in player board',
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class DamageChampionDTO {
|
||||
@ApiProperty()
|
||||
player: string;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class DamagePlayerDTO {
|
||||
@ApiProperty()
|
||||
amount: number;
|
||||
}
|
||||
@@ -309,7 +309,7 @@ export const tokenMappings = {
|
||||
eventEmitter: EventEmitter2,
|
||||
session: mongoose.mongo.ClientSession,
|
||||
) => {
|
||||
if (card.cardType != CardType.CHAMPION) {
|
||||
if (card.cardType != CardType.ACTION) {
|
||||
throw new HttpException(
|
||||
'Cannot stack : Card is not an action',
|
||||
HttpStatus.BAD_REQUEST,
|
||||
@@ -322,6 +322,7 @@ export const tokenMappings = {
|
||||
player.stack,
|
||||
session,
|
||||
);
|
||||
await gameService.fillMarket(game);
|
||||
},
|
||||
[CardEffects.STACK_NEXT_CARD_BOUGHT]: async (
|
||||
game: Document<Game> & Game,
|
||||
@@ -345,6 +346,7 @@ export const tokenMappings = {
|
||||
player.stack,
|
||||
session,
|
||||
);
|
||||
await gameService.fillMarket(game);
|
||||
},
|
||||
[CardEffects.PLAY_NEXT_CARD_BOUGHT]: async (
|
||||
game: Document<Game> & Game,
|
||||
@@ -368,6 +370,7 @@ export const tokenMappings = {
|
||||
player.board,
|
||||
session,
|
||||
);
|
||||
await gameService.fillMarket(game);
|
||||
},
|
||||
[CardEffects.DRAW_AND_DISCARD]: async (
|
||||
game: Document<Game> & Game,
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
Injectable,
|
||||
} from '@nestjs/common';
|
||||
import { InjectModel, InjectConnection } from '@nestjs/mongoose';
|
||||
import { Container, Game, Player } from '../schemas/game.schema';
|
||||
import { Container, Game, Player, Team } from '../schemas/game.schema';
|
||||
import mongoose, { Document, Model } from 'mongoose';
|
||||
import { Card } from 'src/cards/schemas/cards.schema';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
@@ -248,4 +248,33 @@ export class GameService {
|
||||
|
||||
await game.save({ session });
|
||||
}
|
||||
|
||||
@WithTransaction
|
||||
async killTeam(
|
||||
game: Document<Game> & Game,
|
||||
team: Team,
|
||||
session?: mongoose.mongo.ClientSession,
|
||||
) {
|
||||
const index = game.teams.findIndex((t) => t._id.equals(team._id));
|
||||
game.teams.splice(index, 1);
|
||||
if (game.teams.length <= 1) {
|
||||
await this.endGame(game, session);
|
||||
}
|
||||
this.eventEmitter.emit('sse.game.' + game._id.toHexString(), {
|
||||
type: 'killTeam',
|
||||
teamId: team._id,
|
||||
});
|
||||
await game.save({ session });
|
||||
}
|
||||
|
||||
@WithTransaction
|
||||
async endGame(
|
||||
game: Document<Game> & Game,
|
||||
session?: mongoose.mongo.ClientSession,
|
||||
) {
|
||||
this.eventEmitter.emit('sse.game.' + game._id.toHexString(), {
|
||||
type: 'endGame',
|
||||
});
|
||||
await game.deleteOne({ session });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
Inject,
|
||||
Injectable,
|
||||
} from '@nestjs/common';
|
||||
import { Container, Game, Player } from '../schemas/game.schema';
|
||||
import { Container, Game, Player, Team } from '../schemas/game.schema';
|
||||
import mongoose, { Document, Model } from 'mongoose';
|
||||
import { Card } from 'src/cards/schemas/cards.schema';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
CardType,
|
||||
EffectType,
|
||||
} from 'src/cards/schemas/cards.types';
|
||||
import { WithTransaction } from '../utils';
|
||||
import { getPlayerTeam, WithTransaction } from '../utils';
|
||||
import {
|
||||
conditionsMappings,
|
||||
effectMappings,
|
||||
@@ -275,4 +275,36 @@ export class TurnService {
|
||||
});
|
||||
await game.save({ session });
|
||||
}
|
||||
|
||||
@WithTransaction
|
||||
async damagePlayer(
|
||||
game: Document<Game> & Game,
|
||||
amount: number,
|
||||
player: Player,
|
||||
targetPlayer: Player,
|
||||
session?: mongoose.mongo.ClientSession,
|
||||
) {
|
||||
const team = getPlayerTeam(game, targetPlayer);
|
||||
team.health -= amount;
|
||||
game.currentTurn.damage -= amount;
|
||||
|
||||
this.eventEmitter.emit('sse.game.' + game._id.toHexString(), {
|
||||
type: 'currentTurn.updateDamage',
|
||||
damage: game.currentTurn.damage,
|
||||
operation: -amount,
|
||||
});
|
||||
|
||||
this.eventEmitter.emit('sse.game.' + game._id.toHexString(), {
|
||||
type: 'team.updateHealth',
|
||||
team: team._id,
|
||||
health: team.health,
|
||||
operation: -amount,
|
||||
});
|
||||
|
||||
if (team.health <= 0) {
|
||||
this.gamesService.killTeam(game, team, session);
|
||||
}
|
||||
|
||||
await game.save({ session });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,11 @@ export function isInTeam(team: Team, player: Player) {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getPlayerTeam(game: Game, player: Player) {
|
||||
return game.teams.find((t) =>
|
||||
t.players.some((p) => p._id.equals(player._id)),
|
||||
);
|
||||
}
|
||||
export function WithTransaction(
|
||||
target: any,
|
||||
propertyKey: string,
|
||||
@@ -66,6 +71,7 @@ export function WithTransaction(
|
||||
|
||||
descriptor.value = function (...args: any[]) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
if (args.at(-1) instanceof mongoose.mongo.ClientSession) {
|
||||
const data = await originalFunc.apply(this, args).catch((e) => {
|
||||
if (e instanceof HttpException) {
|
||||
@@ -99,6 +105,9 @@ export function WithTransaction(
|
||||
);
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user