From 68cebfdb7bf979b7ac6bbf3aa82de4d7424c4143 Mon Sep 17 00:00:00 2001 From: zhl Date: Mon, 22 Feb 2021 15:50:35 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/rooms/commands/DiscardCommand.ts | 269 +++++----- src/utils/game.util.ts | 704 +++++++++++++-------------- 2 files changed, 498 insertions(+), 475 deletions(-) diff --git a/src/rooms/commands/DiscardCommand.ts b/src/rooms/commands/DiscardCommand.ts index a02e25c..a79d11e 100644 --- a/src/rooms/commands/DiscardCommand.ts +++ b/src/rooms/commands/DiscardCommand.ts @@ -1,16 +1,14 @@ -import {Command} from "@colyseus/command"; -import {CardGameState} from "../schema/CardGameState"; -import gameUtil from "../../utils/game.util"; -import {Client} from "colyseus"; -import {NextSubCommand} from "./NextSubCommand"; -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 {CardType} from "../../cfg/enums/CardType"; -import {StateTypeEnum} from "../enums/StateTypeEnum"; +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' /** * 出牌 @@ -19,116 +17,141 @@ import {StateTypeEnum} from "../enums/StateTypeEnum"; * type: 1, 到时间后, 自动的抽牌 */ export class DiscardCommand extends Command { - // validate({ client, cards } = this.payload) { - // const player = this.state.players.get(client.sessionId); - // return player !== undefined && gameUtil.checkCardsExists(player.cards, cards); - // } + // 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} = 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; - } - let targetCard - if (target) { - if (this.state.cards.size > 1) { - 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; - } - } else { - if (!gameUtil.checkDiscard(tmpCards, new GameEnv().selfEatCount)) { - this.room.send(client,'discard_card_s2c', {errcode: 4, errmsg: '出牌不符合规则'}); - return; - } - for (let [key, val] of this.state.cards) { - this.state.cards.delete(key); - } - } - - - //停止出牌计时, 并更新player.extraTime; - let elapsedTime = this.room.stopSchedule('draw_card'); - if (elapsedTime >= 0) { - let maxTime = new GameEnv().maxDiscardTime * 1000; - let count = elapsedTime - maxTime; - let newCount = player.extraTime - Math.min(count, 0); - player.extraTime = Math.max(newCount, 0); - } - for (let card of tmpCards) { - this.state.cards.set(card.id + '', card); - player.cardQueue.push(card); - gameUtil.deleteCardFromPlayer(player, card.id); - } - /** - * 这说明是当前轮正常出牌, - * 如果出一张牌的话, 进入胡牌轮 - * 否则直接进入选随从轮 - */ - this.room.send(client,'discard_card_s2c', {errcode: 0, cards: cards, type: dtype}) - if (cards.length === 1) { - 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, `select_pet`); - } + async execute({ client, cards, target, dtype } = 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 + } + let targetCard + if (target) { + if (this.state.cards.size > 1) { + 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 + } + } else { + if (!gameUtil.checkDiscard(tmpCards, new GameEnv().selfEatCount)) { + this.room.send(client, 'discard_card_s2c', { + errcode: 4, + errmsg: '出牌不符合规则' + }) + return + } + for (let [key, val] of this.state.cards) { + this.state.cards.delete(key) + } + } + + + //停止出牌计时, 并更新player.extraTime; + let elapsedTime = this.room.stopSchedule('draw_card') + if (elapsedTime >= 0) { + let maxTime = new GameEnv().maxDiscardTime * 1000 + let count = elapsedTime - maxTime + let newCount = player.extraTime - Math.min(count, 0) + player.extraTime = Math.max(newCount, 0) + } + for (let card of tmpCards) { + this.state.cards.set(card.id + '', card) + player.cardQueue.push(card) + gameUtil.deleteCardFromPlayer(player, card.id) + } + /** + * 这说明是当前轮正常出牌, + * 如果出一张牌的话, 进入胡牌轮 + * 否则直接进入选随从轮 + */ + this.room.send(client, 'discard_card_s2c', { + errcode: 0, + cards: cards, + type: dtype + }) + if (cards.length === 1) { + 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, `select_pet`) + } + } } diff --git a/src/utils/game.util.ts b/src/utils/game.util.ts index 971d56d..2e8eb92 100644 --- a/src/utils/game.util.ts +++ b/src/utils/game.util.ts @@ -1,361 +1,361 @@ -import {Card} from "../rooms/schema/Card"; +import { Card } from '../rooms/schema/Card' -import {Player} from "../rooms/schema/Player"; -import {BaseConst} from "../constants/BaseConst"; -import {SystemCardCfg} from "../cfg/parsers/SystemCardCfg"; -import {EffectCardCfg} from "../cfg/parsers/EffectCardCfg"; +import { Player } from '../rooms/schema/Player' +import { BaseConst } from '../constants/BaseConst' +import { SystemCardCfg } from '../cfg/parsers/SystemCardCfg' +import { EffectCardCfg } from '../cfg/parsers/EffectCardCfg' import { cardLog, debugRoom, error } from '../common/Debug' -import {Room} from "colyseus"; -import {PlayerStateConst} from "../constants/PlayerStateConst"; -import {GameEnv} from "../cfg/GameEnv"; -import {CardGameState} from "../rooms/schema/CardGameState"; -import {CardType} from "../cfg/enums/CardType"; -import {EffectType} from "../cfg/enums/EffectType"; +import { Room } from 'colyseus' +import { PlayerStateConst } from '../constants/PlayerStateConst' +import { GameEnv } from '../cfg/GameEnv' +import { CardGameState } from '../rooms/schema/CardGameState' +import { CardType } from '../cfg/enums/CardType' +import { EffectType } from '../cfg/enums/EffectType' let gameUtil = { - /** - * 游戏开始时, 初始化卡组 - */ - initCardQue(beginNum: number) { - let cards: Card[] = []; - let numCfgMap: Map = global.$cfg.get(BaseConst.SYSTEMCARD); - let effCfgMap: Map = global.$cfg.get(BaseConst.EFFECTCARD); + /** + * 游戏开始时, 初始化卡组 + */ + initCardQue(beginNum: number) { + let cards: Card[] = [] + let numCfgMap: Map = global.$cfg.get(BaseConst.SYSTEMCARD) + let effCfgMap: Map = global.$cfg.get(BaseConst.EFFECTCARD) - let countMap: Map = new Map(); - let localId = beginNum; - for (let [, cfg] of numCfgMap) { - for (let i = 0; i < cfg.count; i++) { - let [effid, effType] = this.getRandomEffect(cfg.weightArr, effCfgMap, countMap); - let type = cfg.type_id; - // 如果效果的type_id为11, 说明是自选随从卡, 则将card的type改为11 - if (effType == EffectType.variable_unit) { - type = CardType.variable_unit; - } - let card = new Card(localId++, cfg.point, type, effid); - cards.push(card); - } + let countMap: Map = new Map() + let localId = beginNum + for (let [, cfg] of numCfgMap) { + for (let i = 0; i < cfg.count; i++) { + let [effid, effType] = this.getRandomEffect(cfg.weightArr, effCfgMap, countMap) + let type = cfg.type_id + // 如果效果的type_id为11, 说明是自选随从卡, 则将card的type改为11 + if (effType == EffectType.variable_unit) { + type = CardType.variable_unit } - - cards.randomSort(); - return cards; - }, - initSampleCards(beginNum: number) { - let cardArr = [[1, 1, 20012, 1], [2, 3, 20102, 11], [3, 4, 20032, 1], [4, 10, 20102, 11], [5, 10, 20042, 1], [6, 1, 20012, 1], [7, 3, 20102, 11], [8, 4, 20032, 1], [9, 5, 20102, 11], [10, 6, 20102, 11], [11, 1, 20012, 1], [12, 5, 20102, 11], [13, 5, 20032, 1], [14, 5, 20102, 11], [15, 5, 20102, 11], [16, 6, 20102, 11], [17, 1, 20012, 1], [18, 3, 20102, 11], [19, 5, 20102, 11], [20, 7, 20102, 11], [21, 8, 20042, 1], [22, 10, 20102, 11], [23, 4, 20102, 11], [24, 7, 20052, 1], [25, 3, 20102, 11], [26, 7, 20052, 1], [27, 6, 20072, 1], [28, 1, 20052, 1], [29, 5, 20102, 11], [30, 4, 20052, 1], [31, 0, 20112, 2], [32, 5, 20102, 11], [33, 5, 20062, 1], [34, 2, 20102, 11], [35, 4, 20062, 1], [36, 1, 20072, 1], [37, 1, 20102, 11], [38, 1, 20062, 1], [39, 9, 20042, 1], [40, 0, 20112, 2], [41, 6, 20102, 11], [42, 8, 20072, 1], [43, 0, 20112, 2], [44, 0, 20112, 2], [45, 0, 20112, 2], [46, 0, 20112, 2], [47, 0, 20112, 2], [48, 0, 20112, 2], [49, 10, 20042, 1], [50, 0, 20112, 2], [51, 5, 20102, 11], [52, 5, 20082, 1], [53, 5, 20102, 11], [54, 5, 20052, 1], [55, 0, 20122, 3], [56, 0, 20122, 3], [57, 0, 20122, 3], [58, 0, 20122, 3], [59, 0, 20122, 3], [60, 0, 20122, 3], [61, 0, 20122, 3], [62, 0, 20122, 3], [63, 0, 20112, 2], [64, 0, 20112, 2], [65, 0, 20112, 2], [66, 0, 20112, 2], [67, 0, 20112, 2], [68, 0, 20112, 2]] - let cards: Card[] = []; - for (let i = cardArr.length - 1; i >=0; i--) { - let subarr = cardArr[i] - let card = new Card(subarr[0], subarr[1], subarr[3], subarr[2]) - cards.push(card) - } - debugRoom(cards) - return cards - }, - /** - * 随机生成一张指定效果的卡 - * @param effectId - * @param preCardId - * @param options - */ - generateCardWithEffect(effectId: number, preCardId: number, options?: any): Card { - let numCfgMap: Map = global.$cfg.get(BaseConst.SYSTEMCARD); - const effectMap = global.$cfg.get(BaseConst.EFFECTCARD); - let cfgs = []; - const effectCfg = effectMap.get(effectId); - if (!effectCfg) { - return null; - } - if (effectCfg.type_id == EffectType.unit) { - let point = Math.random2(1, 11) | 0; - return new Card(preCardId + 1, point, CardType.variable_unit, effectId); - } else { - for (let [, cfg] of numCfgMap) { - if (cfg.weight.indexOf(effectId + '') >= 0) { - cfgs.push(cfg); - } - } - let cfg: SystemCardCfg = cfgs.randomOne(); - return new Card(preCardId + 1, cfg.point, cfg.type_id, effectId); - } - - }, - /** - * 获取随机的随从 - * @param player - */ - getRandomServant(player: Player) { - let total = 0; - let tmpArr: number[][] = []; - for (let [id, weight] of player.unitCfgs) { - total += weight; - tmpArr.push([parseInt(id), total]); - } - let num = Math.random() * total; - let result; - for (let data of tmpArr) { - if (data[1] >= num) { - result = data[0]; - break; - } - } - return result; - }, - /** - * 根据配表中的权重, 获取一个效果卡的id - * @param weightArr 配表中的权重列表 - * @param effCfgMap 配表中的所有效果卡的配置 - * @param countMap 当前已生成的效果卡数量 - */ - getRandomEffect(weightArr: number[][], effCfgMap: Map, countMap: Map): number[] { - let total = 0; - let tmpArr: number[][] = []; - for (let data of weightArr) { - total += data[1]; - tmpArr.push([data[0], total]); - } - let num = Math.random() * total; - let effid; - let effType; - for (let data of tmpArr) { - if (data[1] >= num) { - let count = countMap.has(data[0]) ? countMap.get(data[0]) : 0; - if (count < effCfgMap.get(data[0]).count) { - effid = effCfgMap.get(data[0]).id; - effType = effCfgMap.get(data[0]).type_id; - countMap.set(effid, count + 1); - break; - } - } - } - if (!effid) { - for (let [id, count] of countMap) { - if (count < effCfgMap.get(id).count) { - effid = id; - effType = effCfgMap.get(effid).type_id; - countMap.set(effid, count + 1); - break - } - } - } - if (!effid) { - error('生成卡组时, 无法匹配效果卡, 请确认效果卡的最大数量是否等于点数卡总数') - } - return [effid, effType]; - }, - /** - * 检查目标数组中的卡id是否在存在 - * @param cardMap - * @param cardIds - */ - checkCardsExists(cardMap: Map, cardIds: Array) { - let result = true; - for (let id of cardIds) { - if (!cardMap.has(id + '')) { - result = false; - break; - } - } - return result; - }, - /** - * 抽卡 - * @param room - * @param cardArr - * @param player - * @param count - * @param fromplayer - * @param extData 指定卡的效果 - */ - drawCard(room: Room, cardArr: Card[], player: Player, count: number, fromplayer?: Player, extData?: {}): Card[] { - let cards: Card[] = []; - for (let i = 0; i < count; i++) { - let card = cardArr.pop(); - if (extData) { - // @ts-ignore - extData['effect'] && (card.effect = extData['effect']); - // @ts-ignore - extData['type'] && (card.type = extData['type']); - // @ts-ignore - extData['number'] && (card.number = extData['number']); - } - cards.push(card); - } - this.addCardToPlayer(room, player, cards, fromplayer); - return cards; - }, - /** - * 随机移除n张手牌 - * @param player - * @param count - */ - removeCard(player: Player, count: number): Card[] { - let cards: Card[] = []; - let cardArr: Card[] = [...player.cards.values()]; - cards = cardArr.randomGet(count); - this.deleteCardFromPlayer(player, cards); - return cards; - }, - /** - * 从玩家手牌中删除指定的卡 - * @param player - * @param cards - */ - deleteCardFromPlayer(player: Player, cards: Card[] | string[] | number[] | number | string) { - let deleteOne = function (cardId: string) { - if (player.cards.has(cardId)) { - if (cardLog.enabled) { - let card = player.cards.get(cardId); - cardLog(`delete: ${player.id} ${card.id} ${card.effect} ${card.type} `) - } - player.cards.delete(cardId); - player.cardSet.delete(cardId); - } - } - if (typeof cards == 'number' || typeof cards == 'string') { - const cardId = cards + ''; - deleteOne(cardId); - } else { - for (let card of cards) { - let cardId = ''; - if (typeof card == 'string') { - cardId = card; - } else if (typeof card == 'number') { - cardId = card + ''; - } else { - cardId = (card as Card).id + ''; - } - deleteOne(cardId); - } - } - - }, - pushInPlayerCards(player: Player, cards: Card[]) { - const effectMap = global.$cfg.get(BaseConst.EFFECTCARD); - let realCards: Card[] = [] - for (let card of cards) { - if (!card) { - continue - } - // 如果card的type == 11, 说明是自选随从卡, 则替换成玩家牌组中的卡 - if (card.type == CardType.variable_unit && effectMap.get(card.effect).type_id == EffectType.variable_unit) { - card.effect = this.getRandomServant(player); - } - card.owner = player.id - realCards.push(card) - player.cards.set(card.id + '', card); - player.cardSet.add(card.id + ''); - } - cardLog(`add: ${player.id} ${realCards.map(o => [o.id, o.effect, o.type])}`) - }, - /** - * 往玩家的卡组里添加卡 - * @param room - * @param player - * @param cards - * @param fromplayer - */ - addCardToPlayer(room: Room, player: Player, cards: Card[], fromplayer?: Player) { - this.pushInPlayerCards(player, cards); - player.countTotal += cards.length; - let time = room.battleMan.onCardGetted(player, cards, fromplayer); - cardLog(`addCardToPlayer add time: ${time}`); - }, - /** - * 更换相同数量的卡 - * @param cardArr - * @param player - * @param targetCards - */ - changeCard(cardArr: Card[], player: Player, targetCards: Card[]): Card[] { - const effectMap = global.$cfg.get(BaseConst.EFFECTCARD); - let cards: Card[] = []; - let tmpCards: Card[] = []; - for (let card of targetCards) { - tmpCards.push(card.clone()); - } - this.deleteCardFromPlayer(player, targetCards); - cardArr.randomInsert(tmpCards); - let count = targetCards.length; - for (let i = 0; i < count; i++) { - cards.push(cardArr.pop()); - } - this.pushInPlayerCards(player, cards); - return cards; - }, - /** - * 检查出牌是否符合规则 - * @param cardsLst - * @param maxCount - */ - checkDiscard(cardsLst: Card[], maxCount: number) { - if (cardsLst.length == 0 || cardsLst.length == 2) { - return false - } else if (cardsLst.length == 1) { - return true; - } - let numSet: number[] = []; - cardsLst.forEach(function (value) { - if (value.type == CardType.general || value.type == CardType.variable_unit) { - numSet.push(value.number); - } - }); - if (numSet.length === 1) { - return true; - } - if (numSet.length < maxCount) { - return false; - } - numSet.sort((a, b) => { - return a - b; - }); - let preNum; - let sequence = true; //是否是顺序 - let same = true; //是否是相同 - for (let num of numSet) { - if (preNum) { - if (num !== (preNum + 1) && sequence) { - sequence = false; - } - if (num !== preNum && same) { - same = false; - } - if (!sequence && !same) { - return false; - } - } - preNum = num; - } - - return true; - }, - /** - * 结算时计算总的ap - * @param player - */ - calcTotalAp(player: Player) { - let result = 0; - if (!player) { - return result; - } - for (let [pid, pet] of player.pets) { - result += pet.ap; - } - return result; - }, - - checkGameEnd(state: CardGameState) { - let deadCount0 = 0; - let deadCount1 = 0; - for (let [, player] of state.players) { - if (player.team == 0 && player.state == PlayerStateConst.PLAYER_DEAD ) { - deadCount0 ++; - } else if (player.team == 1 && player.state == PlayerStateConst.PLAYER_DEAD ){ - deadCount1 ++; - } - } - const roundNum = new GameEnv().duelRoundNum; - const totalRound = roundNum * new GameEnv().maxDuelNum; - return (deadCount0 == 2 || deadCount1 == 2) || (state.round >= totalRound - 1); + let card = new Card(localId++, cfg.point, type, effid) + cards.push(card) + } } + cards.randomSort() + return cards + }, + initSampleCards(beginNum: number) { + let cardArr = [[1, 1, 20012, 1], [2, 3, 20102, 11], [3, 4, 20032, 1], [4, 10, 20102, 11], [5, 10, 20042, 1], [6, 1, 20012, 1], [7, 3, 20102, 11], [8, 4, 20032, 1], [9, 5, 20102, 11], [10, 6, 20102, 11], [11, 1, 20012, 1], [12, 5, 20102, 11], [13, 5, 20032, 1], [14, 5, 20102, 11], [15, 5, 20102, 11], [16, 6, 20102, 11], [17, 1, 20012, 1], [18, 3, 20102, 11], [19, 5, 20102, 11], [20, 7, 20102, 11], [21, 8, 20042, 1], [22, 10, 20102, 11], [23, 4, 20102, 11], [24, 7, 20052, 1], [25, 3, 20102, 11], [26, 7, 20052, 1], [27, 6, 20072, 1], [28, 1, 20052, 1], [29, 5, 20102, 11], [30, 4, 20052, 1], [31, 0, 20112, 2], [32, 5, 20102, 11], [33, 5, 20062, 1], [34, 2, 20102, 11], [35, 4, 20062, 1], [36, 1, 20072, 1], [37, 1, 20102, 11], [38, 1, 20062, 1], [39, 9, 20042, 1], [40, 0, 20112, 2], [41, 6, 20102, 11], [42, 8, 20072, 1], [43, 0, 20112, 2], [44, 0, 20112, 2], [45, 0, 20112, 2], [46, 0, 20112, 2], [47, 0, 20112, 2], [48, 0, 20112, 2], [49, 10, 20042, 1], [50, 0, 20112, 2], [51, 5, 20102, 11], [52, 5, 20082, 1], [53, 5, 20102, 11], [54, 5, 20052, 1], [55, 0, 20122, 3], [56, 0, 20122, 3], [57, 0, 20122, 3], [58, 0, 20122, 3], [59, 0, 20122, 3], [60, 0, 20122, 3], [61, 0, 20122, 3], [62, 0, 20122, 3], [63, 0, 20112, 2], [64, 0, 20112, 2], [65, 0, 20112, 2], [66, 0, 20112, 2], [67, 0, 20112, 2], [68, 0, 20112, 2]] + let cards: Card[] = [] + for (let i = cardArr.length - 1; i >= 0; i--) { + let subarr = cardArr[i] + let card = new Card(subarr[0], subarr[1], subarr[3], subarr[2]) + cards.push(card) + } + debugRoom(cards) + return cards + }, + /** + * 随机生成一张指定效果的卡 + * @param effectId + * @param preCardId + * @param options + */ + generateCardWithEffect(effectId: number, preCardId: number, options?: any): Card { + let numCfgMap: Map = global.$cfg.get(BaseConst.SYSTEMCARD) + const effectMap = global.$cfg.get(BaseConst.EFFECTCARD) + let cfgs = [] + const effectCfg = effectMap.get(effectId) + if (!effectCfg) { + return null + } + if (effectCfg.type_id == EffectType.unit) { + let point = Math.random2(1, 11) | 0 + return new Card(preCardId + 1, point, CardType.variable_unit, effectId) + } else { + for (let [, cfg] of numCfgMap) { + if (cfg.weight.indexOf(effectId + '') >= 0) { + cfgs.push(cfg) + } + } + let cfg: SystemCardCfg = cfgs.randomOne() + return new Card(preCardId + 1, cfg.point, cfg.type_id, effectId) + } + + }, + /** + * 获取随机的随从 + * @param player + */ + getRandomServant(player: Player) { + let total = 0 + let tmpArr: number[][] = [] + for (let [id, weight] of player.unitCfgs) { + total += weight + tmpArr.push([parseInt(id), total]) + } + let num = Math.random() * total + let result + for (let data of tmpArr) { + if (data[1] >= num) { + result = data[0] + break + } + } + return result + }, + /** + * 根据配表中的权重, 获取一个效果卡的id + * @param weightArr 配表中的权重列表 + * @param effCfgMap 配表中的所有效果卡的配置 + * @param countMap 当前已生成的效果卡数量 + */ + getRandomEffect(weightArr: number[][], effCfgMap: Map, countMap: Map): number[] { + let total = 0 + let tmpArr: number[][] = [] + for (let data of weightArr) { + total += data[1] + tmpArr.push([data[0], total]) + } + let num = Math.random() * total + let effid + let effType + for (let data of tmpArr) { + if (data[1] >= num) { + let count = countMap.has(data[0]) ? countMap.get(data[0]) : 0 + if (count < effCfgMap.get(data[0]).count) { + effid = effCfgMap.get(data[0]).id + effType = effCfgMap.get(data[0]).type_id + countMap.set(effid, count + 1) + break + } + } + } + if (!effid) { + for (let [id, count] of countMap) { + if (count < effCfgMap.get(id).count) { + effid = id + effType = effCfgMap.get(effid).type_id + countMap.set(effid, count + 1) + break + } + } + } + if (!effid) { + error('生成卡组时, 无法匹配效果卡, 请确认效果卡的最大数量是否等于点数卡总数') + } + return [effid, effType] + }, + /** + * 检查目标数组中的卡id是否在存在 + * @param cardMap + * @param cardIds + */ + checkCardsExists(cardMap: Map, cardIds: Array) { + let result = true + for (let id of cardIds) { + if (!cardMap.has(id + '')) { + result = false + break + } + } + return result + }, + /** + * 抽卡 + * @param room + * @param cardArr + * @param player + * @param count + * @param fromplayer + * @param extData 指定卡的效果 + */ + drawCard(room: Room, cardArr: Card[], player: Player, count: number, fromplayer?: Player, extData?: {}): Card[] { + let cards: Card[] = [] + for (let i = 0; i < count; i++) { + let card = cardArr.pop() + if (extData) { + // @ts-ignore + extData['effect'] && (card.effect = extData['effect']) + // @ts-ignore + extData['type'] && (card.type = extData['type']) + // @ts-ignore + extData['number'] && (card.number = extData['number']) + } + cards.push(card) + } + this.addCardToPlayer(room, player, cards, fromplayer) + return cards + }, + /** + * 随机移除n张手牌 + * @param player + * @param count + */ + removeCard(player: Player, count: number): Card[] { + let cards: Card[] = [] + let cardArr: Card[] = [...player.cards.values()] + cards = cardArr.randomGet(count) + this.deleteCardFromPlayer(player, cards) + return cards + }, + /** + * 从玩家手牌中删除指定的卡 + * @param player + * @param cards + */ + deleteCardFromPlayer(player: Player, cards: Card[] | string[] | number[] | number | string) { + let deleteOne = function (cardId: string) { + if (player.cards.has(cardId)) { + if (cardLog.enabled) { + let card = player.cards.get(cardId) + cardLog(`delete: ${ player.id } ${ card.id } ${ card.effect } ${ card.type } `) + } + player.cards.delete(cardId) + player.cardSet.delete(cardId) + } + } + if (typeof cards == 'number' || typeof cards == 'string') { + const cardId = cards + '' + deleteOne(cardId) + } else { + for (let card of cards) { + let cardId = '' + if (typeof card == 'string') { + cardId = card + } else if (typeof card == 'number') { + cardId = card + '' + } else { + cardId = (card as Card).id + '' + } + deleteOne(cardId) + } + } + + }, + pushInPlayerCards(player: Player, cards: Card[]) { + const effectMap = global.$cfg.get(BaseConst.EFFECTCARD) + let realCards: Card[] = [] + for (let card of cards) { + if (!card) { + continue + } + // 如果card的type == 11, 说明是自选随从卡, 则替换成玩家牌组中的卡 + if (card.type == CardType.variable_unit && effectMap.get(card.effect).type_id == EffectType.variable_unit) { + card.effect = this.getRandomServant(player) + } + card.owner = player.id + realCards.push(card) + player.cards.set(card.id + '', card) + player.cardSet.add(card.id + '') + } + cardLog(`add: ${ player.id } ${ realCards.map(o => [o.id, o.effect, o.type]) }`) + }, + /** + * 往玩家的卡组里添加卡 + * @param room + * @param player + * @param cards + * @param fromplayer + */ + addCardToPlayer(room: Room, player: Player, cards: Card[], fromplayer?: Player) { + this.pushInPlayerCards(player, cards) + player.countTotal += cards.length + let time = room.battleMan.onCardGetted(player, cards, fromplayer) + cardLog(`addCardToPlayer add time: ${ time }`) + }, + /** + * 更换相同数量的卡 + * @param cardArr + * @param player + * @param targetCards + */ + changeCard(cardArr: Card[], player: Player, targetCards: Card[]): Card[] { + const effectMap = global.$cfg.get(BaseConst.EFFECTCARD) + let cards: Card[] = [] + let tmpCards: Card[] = [] + for (let card of targetCards) { + tmpCards.push(card.clone()) + } + this.deleteCardFromPlayer(player, targetCards) + cardArr.randomInsert(tmpCards) + let count = targetCards.length + for (let i = 0; i < count; i++) { + cards.push(cardArr.pop()) + } + this.pushInPlayerCards(player, cards) + return cards + }, + /** + * 检查出牌是否符合规则 + * @param cardsLst + * @param maxCount + */ + checkDiscard(cardsLst: Card[], maxCount: number) { + if (cardsLst.length == 0 || cardsLst.length == 2) { + return false + } else if (cardsLst.length == 1) { + return true + } + let numSet: number[] = [] + cardsLst.forEach(function (value) { + if (value.type == CardType.general || value.type == CardType.variable_unit) { + numSet.push(value.number) + } + }) + if (numSet.length === 1) { + return true + } + if (numSet.length < maxCount) { + return false + } + numSet.sort((a, b) => { + return a - b + }) + let preNum + let sequence = true //是否是顺序 + let same = true //是否是相同 + for (let num of numSet) { + if (preNum) { + if (num !== (preNum + 1) && sequence) { + sequence = false + } + if (num !== preNum && same) { + same = false + } + if (!sequence && !same) { + return false + } + } + preNum = num + } + + return true + }, + /** + * 结算时计算总的ap + * @param player + */ + calcTotalAp(player: Player) { + let result = 0 + if (!player) { + return result + } + for (let [pid, pet] of player.pets) { + result += pet.ap + } + return result + }, + + checkGameEnd(state: CardGameState) { + let deadCount0 = 0 + let deadCount1 = 0 + for (let [, player] of state.players) { + if (player.team == 0 && player.state == PlayerStateConst.PLAYER_DEAD) { + deadCount0++ + } else if (player.team == 1 && player.state == PlayerStateConst.PLAYER_DEAD) { + deadCount1++ + } + } + const roundNum = new GameEnv().duelRoundNum + const totalRound = roundNum * new GameEnv().maxDuelNum + return (deadCount0 == 2 || deadCount1 == 2) || (state.round >= totalRound - 1) + } + } -export default gameUtil; +export default gameUtil