Feat : allow buying cards

This commit is contained in:
2024-07-05 11:26:51 +02:00
parent d56abe3693
commit 9d0cdca6e9
6 changed files with 70 additions and 30 deletions
+2 -1
View File
@@ -79,7 +79,7 @@ export class CardsService {
if (json.effects) { if (json.effects) {
createdCard.effects = await this.createEffects(json.effects, createdCard); createdCard.effects = await this.createEffects(json.effects, createdCard);
} }
createdCard.save(); await createdCard.save();
} }
private async createEffects( private async createEffects(
@@ -95,6 +95,7 @@ export class CardsService {
times: e.times ?? 1, times: e.times ?? 1,
per: e.per, per: e.per,
faction: e.faction, faction: e.faction,
mutex: e.mutex?.toString(),
} as Effect; } as Effect;
if (e.sub_effects) { if (e.sub_effects) {
createdEffect.subEffects = await this.createEffects( createdEffect.subEffects = await this.createEffects(
+1 -13
View File
@@ -56,7 +56,7 @@ export class Effect extends Types.ObjectId {
// }, // },
// ], // ],
// }) // })
mutex?: Effect[]; mutex?: string;
// @Prop({ // @Prop({
// type: mongoose.Schema.Types.ObjectId, // type: mongoose.Schema.Types.ObjectId,
@@ -77,15 +77,3 @@ EffectSchema.add({
autopopulate: true, autopopulate: true,
}, },
}); });
EffectSchema.add({
mutex: {
type: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Effect',
autopopulate: true,
},
],
},
});
+13 -5
View File
@@ -32,9 +32,9 @@ export class TurnController {
@UseGuards(AuthGuard) @UseGuards(AuthGuard)
async lockCard( async lockCard(
@Param('gameId') _gameId: string, @Param('gameId') _gameId: string,
@Param('cardId') cardId: string, @Param('cardId') _cardId: string,
@Param('gameId', GameStartedPipe) game: Document<Game> & Game, @Param('gameId', GameStartedPipe) game: Document<Game> & Game,
@Param('gameId', CardPipe) card: Document<Card> & Card, @Param('cardId', CardPipe) card: Document<Card> & Card,
@Session() session: Record<string, string>, @Session() session: Record<string, string>,
) { ) {
const currentPlayer = getPlayer(session, game); const currentPlayer = getPlayer(session, game);
@@ -45,10 +45,17 @@ export class TurnController {
HttpStatus.FORBIDDEN, HttpStatus.FORBIDDEN,
); );
} }
if (game.currentTurn.cardsLocked.some((c) => c._id.equals(cardId))) { if (game.currentTurn.cardsLocked.some((c) => c._id.equals(card._id))) {
throw new HttpException('Card already locked', HttpStatus.BAD_REQUEST); throw new HttpException('Card already locked', HttpStatus.BAD_REQUEST);
} }
this.turnService.lockCard(game, currentPlayer, cardId); if (!currentPlayer.board.cards.some((c) => c._id.equals(card._id))) {
throw new HttpException(
'Card not found in player board',
HttpStatus.NOT_FOUND,
);
}
await this.turnService.lockCard(game, currentPlayer, card);
} }
@Post('buyCard/:cardId') @Post('buyCard/:cardId')
@@ -76,7 +83,8 @@ export class TurnController {
); );
} }
if (game.currentTurn.gold < card.cost) { if (game.currentTurn.gold < card.cost) {
this.turnService.buyCard(game, currentPlayer, card); throw new HttpException('Not enough gold', HttpStatus.BAD_REQUEST);
} }
await this.turnService.buyCard(game, currentPlayer, card);
} }
} }
+31 -1
View File
@@ -2,9 +2,20 @@ import { EventEmitter2 } from '@nestjs/event-emitter';
import { Game, Player } from '../schemas/game.schema'; import { Game, Player } from '../schemas/game.schema';
import { Document } from 'mongoose'; import { Document } from 'mongoose';
import { Card } from 'src/cards/schemas/cards.schema'; import { Card } from 'src/cards/schemas/cards.schema';
import { CardEffects } from 'src/cards/schemas/cards.types'; import { CardEffects, EffectType } from 'src/cards/schemas/cards.types';
import { Effect } from 'src/cards/schemas/effect.schema'; import { Effect } from 'src/cards/schemas/effect.schema';
export function isAutoActivable(effect: Effect) {
if (
!effect.mutex &&
(!effect.condition ||
effect.condition.effectId == EffectType.CHAMPION_ACTION)
) {
return true;
}
return false;
}
export const effectMappings = { export const effectMappings = {
[CardEffects.GOLD]: ( [CardEffects.GOLD]: (
game: Document<Game> & Game, game: Document<Game> & Game,
@@ -35,6 +46,25 @@ export const effectMappings = {
operation: effect.amount, operation: effect.amount,
}); });
}, },
[CardEffects.HEAL]: (
game: Document<Game> & Game,
effect: Effect,
player: Player,
_card: Card,
eventEmitter: EventEmitter2,
) => {
const team = game.teams.find((t) =>
t.players.some((p) => p._id.equals(player._id)),
);
team.health += effect.amount;
eventEmitter.emit('sse.game.' + game._id.toHexString(), {
type: 'team.updateHealth',
team: team._id,
health: team.health,
operation: effect.amount,
});
},
} as Record< } as Record<
CardEffects, CardEffects,
( (
+1 -1
View File
@@ -185,7 +185,7 @@ export class GameService {
game: Document<Game> & Game, game: Document<Game> & Game,
session?: mongoose.mongo.ClientSession, session?: mongoose.mongo.ClientSession,
) { ) {
if (cards.some((c) => !from.cards.includes(c))) { if (cards.some((c) => !from.cards.some((cc) => cc._id.equals(c._id)))) {
throw new HttpException( throw new HttpException(
'Card not found in container', 'Card not found in container',
HttpStatus.NOT_FOUND, HttpStatus.NOT_FOUND,
+22 -9
View File
@@ -8,11 +8,13 @@ import { CardEffects, EffectType } from 'src/cards/schemas/cards.types';
import { WithTransaction } from '../utils'; import { WithTransaction } from '../utils';
import { effectMappings } from './effect.functions'; import { effectMappings } from './effect.functions';
import { InjectConnection, InjectModel } from '@nestjs/mongoose'; import { InjectConnection, InjectModel } from '@nestjs/mongoose';
import { GameService } from './games.service';
@Injectable() @Injectable()
export class TurnService { export class TurnService {
constructor( constructor(
private eventEmitter: EventEmitter2, private eventEmitter: EventEmitter2,
private readonly gamesService: GameService,
@InjectModel(Game.name) private gameModel: Model<Game>, @InjectModel(Game.name) private gameModel: Model<Game>,
@InjectConnection() private readonly connection: mongoose.Connection, @InjectConnection() private readonly connection: mongoose.Connection,
) {} ) {}
@@ -21,16 +23,9 @@ export class TurnService {
async lockCard( async lockCard(
game: Document<Game> & Game, game: Document<Game> & Game,
player: Player, player: Player,
cardId: string, card: Card,
session?: mongoose.mongo.ClientSession, session?: mongoose.mongo.ClientSession,
) { ) {
const card = player.board.cards.find((c) => c._id.equals(cardId));
if (!card) {
throw new HttpException(
'Card not found in player board',
HttpStatus.NOT_FOUND,
);
}
game.currentTurn.cardsLocked.push(card); game.currentTurn.cardsLocked.push(card);
this.eventEmitter.emit('sse.game.' + game._id.toHexString(), { this.eventEmitter.emit('sse.game.' + game._id.toHexString(), {
type: 'lockCard', type: 'lockCard',
@@ -38,7 +33,7 @@ export class TurnService {
}); });
for (const effect of card.effects) { for (const effect of card.effects) {
if ( if (
[, CardEffects.HEAL, CardEffects.GOLD, CardEffects.DAMAGE].includes( [CardEffects.HEAL, CardEffects.GOLD, CardEffects.DAMAGE].includes(
effect.effect, effect.effect,
) && ) &&
!effect.mutex && !effect.mutex &&
@@ -93,6 +88,24 @@ export class TurnService {
card: Card, card: Card,
session?: mongoose.mongo.ClientSession, session?: mongoose.mongo.ClientSession,
) { ) {
if (!card.cost) {
throw new TypeError('Card cost is null or undefined');
}
game.currentTurn.gold -= card.cost;
this.eventEmitter.emit('sse.game.' + game._id.toHexString(), {
type: 'currentTurn.updateGold',
gold: game.currentTurn.gold,
operation: -card.cost,
});
await this.gamesService.distributeCards(
[card],
game.market,
player.discard,
game,
session,
);
await this.gamesService.fillMarket(game, session);
await game.save({ session });
return; return;
} }
} }