184 lines
6.7 KiB
TypeScript
184 lines
6.7 KiB
TypeScript
import { Command } from '@colyseus/command'
|
|
import { CardGameState } from '../schema/CardGameState'
|
|
import gameUtil from '../../utils/game.util'
|
|
import { Client } from 'colyseus'
|
|
import { GameStateConst } from '../../constants/GameStateConst'
|
|
import { GameEnv } from '../../cfg/GameEnv'
|
|
import { debugRoom, error } from '../../common/Debug'
|
|
import { TurnEndCommand } from './TurnEndCommand'
|
|
import { Card } from '../schema/Card'
|
|
import { Wait } from './Wait'
|
|
import { StateTypeEnum } from '../enums/StateTypeEnum'
|
|
import { RULE_CANEAT, RULE_SINGLEEAT } from '../../cfg/RoomOptions'
|
|
import { ClockNameConst } from '../../constants/ClockNameConst'
|
|
import { stopDrawCardClock } from '../../utils/clock.util'
|
|
import { CardType } from '../../cfg/enums/CardType'
|
|
|
|
/**
|
|
* 出牌
|
|
* target: 如果是吃牌, 则带上此字段
|
|
* type: 0, 正常的抽牌
|
|
* type: 1, 到时间后, 自动的抽牌
|
|
*/
|
|
export class DiscardCommand extends Command<CardGameState, { client: Client, cards: [string], target?: string, dtype: number, nums?: [number] }> {
|
|
// validate({ client, cards } = this.payload) {
|
|
// const player = this.state.players.get(client.sessionId);
|
|
// return player !== undefined && gameUtil.checkCardsExists(player.cards, cards);
|
|
// }
|
|
|
|
async execute({ client, cards, target, dtype , nums} = this.payload) {
|
|
const player = this.state.players.get(client.sessionId)
|
|
if (!player) {
|
|
this.room.send(client, 'discard_card_s2c', {
|
|
errcode: 1,
|
|
errmsg: 'player不存在'
|
|
})
|
|
return
|
|
}
|
|
let tmpCards = []
|
|
for (let id of cards) {
|
|
if (player.cards.has(id + '')) {
|
|
if (!player.cards.get(id + '').number) {
|
|
error(`${ player.id } 的手牌 ${ id } 数据有问题`)
|
|
continue
|
|
}
|
|
tmpCards.push(player.cards.get(id + '').clone())
|
|
} else {
|
|
error(`${ player.id } 出的牌 ${ id } 在手牌中不存在`)
|
|
this.room.send(client, 'discard_card_s2c', {
|
|
errcode: 2,
|
|
errmsg: `要出的牌 ${ id } 在手牌中不存在`
|
|
})
|
|
return
|
|
}
|
|
}
|
|
if (this.state.currentTurn != client.sessionId) {
|
|
this.room.send(client, 'discard_card_s2c', {
|
|
errcode: 3,
|
|
errmsg: '不是当前轮'
|
|
})
|
|
return
|
|
}
|
|
if (player.robot && !!nums) {
|
|
debugRoom(`change card numbers`)
|
|
let i = 0
|
|
for (let card of tmpCards) {
|
|
if (card.type == CardType.double_effect || card.type == CardType.double_point) {
|
|
card.type = CardType.general
|
|
card.effect = gameUtil.randomEffect(this.state.advMode)
|
|
}
|
|
card.number = nums[i ++]
|
|
}
|
|
}
|
|
let targetCard
|
|
if (target) {
|
|
if (!this.state.rules.get(RULE_CANEAT)) {
|
|
this.room.send(client, 'discard_card_s2c', {
|
|
errcode: 7,
|
|
errmsg: '当前游戏不允许吃牌'
|
|
})
|
|
return
|
|
}
|
|
if (this.state.cards.size > 1 || this.state.cards.size == 0) {
|
|
this.room.send(client, 'discard_card_s2c', {
|
|
errcode: 6,
|
|
errmsg: '不符合吃牌规则'
|
|
})
|
|
return
|
|
}
|
|
if (!this.state.cards.has(target + '')) {
|
|
this.room.send(client, 'discard_card_s2c', {
|
|
errcode: 5,
|
|
errmsg: '找不到要吃的牌'
|
|
})
|
|
return
|
|
}
|
|
targetCard = this.state.cards.values().next().value.clone()
|
|
let targetPlayer = this.state.players.get(targetCard.owner)
|
|
targetPlayer?.cardQueue.clear()
|
|
tmpCards.push(targetCard)
|
|
if (!gameUtil.checkDiscard(tmpCards, new GameEnv().otherEatCount)) {
|
|
this.room.send(client, 'discard_card_s2c', {
|
|
errcode: 4,
|
|
errmsg: '出牌不符合规则'
|
|
})
|
|
return
|
|
}
|
|
for (let [key, val] of this.state.cards) {
|
|
this.state.cards.delete(key)
|
|
}
|
|
} else {
|
|
if (!gameUtil.checkDiscard(tmpCards, new GameEnv().selfEatCount)) {
|
|
this.room.send(client, 'discard_card_s2c', {
|
|
errcode: 4,
|
|
errmsg: '出牌不符合规则'
|
|
})
|
|
return
|
|
}
|
|
}
|
|
|
|
|
|
//停止出牌计时, 并更新player.extraTime;
|
|
stopDrawCardClock(this.room, player)
|
|
|
|
for (let card of tmpCards) {
|
|
player.cardQueue.push(card)
|
|
gameUtil.deleteCardFromPlayer(player, card.id)
|
|
}
|
|
// 如果当前出的牌只有一张, 且是法术牌或者随从牌, 则替换state.cards中的牌
|
|
if (tmpCards.length == 1 && (tmpCards[0].type == CardType.general || tmpCards[0].type == CardType.variable_unit)) {
|
|
for (let [key, val] of this.state.cards) {
|
|
this.state.cards.delete(key)
|
|
}
|
|
let card = tmpCards[0]
|
|
this.state.cards.set(card.id + '', card)
|
|
}
|
|
/**
|
|
* 这说明是当前轮正常出牌,
|
|
* 如果出一张牌的话, 进入胡牌轮
|
|
* 否则直接进入选随从轮
|
|
*/
|
|
this.room.send(client, 'discard_card_s2c', {
|
|
errcode: 0,
|
|
cards: cards,
|
|
type: dtype
|
|
})
|
|
const singleEat = !!this.state.rules.get(RULE_SINGLEEAT)
|
|
if (cards.length === 1
|
|
&& !(singleEat && tmpCards.length == 1 && (tmpCards[0].type == CardType.general || tmpCards[0].type == CardType.variable_unit))) {
|
|
let cardArr: Card[] = [...this.state.cards.values()]
|
|
let time = this.room.battleMan.onCardDiscarded(player, cardArr[0])
|
|
await this.delay(time)
|
|
// 20210219 修改: 出单张牌后直接进入下个玩家的出牌时间
|
|
// if (cardArr[0].type == CardType.general || cardArr[0].type == CardType.variable_unit) {
|
|
// return [new NextSubCommand()];
|
|
// } else {
|
|
// return [new Wait().setPayload(new GameEnv().emptyRoundTime), new TurnEndCommand()];
|
|
// }
|
|
return [new Wait().setPayload(new GameEnv().emptyRoundTime), new TurnEndCommand()]
|
|
} else {
|
|
let cardArr: Card[] = [...this.state.cards.values()]
|
|
let self = this
|
|
let cardMsg: any = { player: player.id, errcode: 0, errmsg: '' }
|
|
if (targetCard) {
|
|
cardMsg.target = targetCard.owner
|
|
}
|
|
this.room.broadcast('eat_card_s2c', cardMsg, { except: client })
|
|
cardMsg.cards = cards
|
|
this.room.send(client, 'eat_card_s2c', cardMsg)
|
|
let delay = this.room.battleMan.onCardLinkOver(player, cardArr)
|
|
player.statData.inc(StateTypeEnum.EATCOUNT, 1)
|
|
await this.delay(delay)
|
|
let time = new GameEnv().playerActTime * 1000 + player.extraTime
|
|
this.state.updateGameState(GameStateConst.STATE_PICK_PET)
|
|
// 开启选随从计时, 计时结束后结束当前轮
|
|
let timeOverSelectPet = function () {
|
|
player.extraTime = 0
|
|
debugRoom('选随从或者法术时间到, 自动出牌, 自动进入下一轮')
|
|
self.room.dispatcher.dispatch(new TurnEndCommand())
|
|
}
|
|
this.room.beginSchedule(time, timeOverSelectPet, ClockNameConst.SELECT_PET)
|
|
}
|
|
}
|
|
}
|