From ff5cce11da1e6f9f5e0748ed45249b92022c961b Mon Sep 17 00:00:00 2001 From: zhl Date: Mon, 22 Feb 2021 17:53:48 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E4=BB=A3=E7=A0=81,=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=80=E4=BA=9B=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/DataParser.ts | 143 ++++--- src/global.d.ts | 515 +++++++++++++------------ src/index.ts | 1 - src/rooms/RankedLobbyRoom.ts | 43 ++- src/rooms/commands/SelectPetCommand.ts | 171 ++++---- 5 files changed, 450 insertions(+), 423 deletions(-) diff --git a/src/common/DataParser.ts b/src/common/DataParser.ts index 32eeb1e..8b18506 100644 --- a/src/common/DataParser.ts +++ b/src/common/DataParser.ts @@ -1,84 +1,83 @@ -import * as jetpack from "fs-jetpack"; -import {singleton} from "./Singleton"; -import {GameEnv} from "../cfg/GameEnv"; -import {BaseConst} from "../constants/BaseConst"; -import {error} from "./Debug"; +import * as jetpack from 'fs-jetpack' +import { GameEnv } from '../cfg/GameEnv' +import { BaseConst } from '../constants/BaseConst' +import { error } from './Debug' -const $cfg = new Map(); -const jsonPath = 'config'; -export var DataParser = (function (){ - const parsers: { [index: string]: ConfigDataParser } = {}; +const $cfg = new Map() +const jsonPath = 'config' +export var DataParser = (function () { + const parsers: { [index: string]: ConfigDataParser } = {} - return { - regParser, - regCommonParser(key: string, CfgCreator: { new (): Cfg }, idkey = "id") { - regParser(key, (data: any[]): any => { - if (!data) return; - let dict = new Map(); - for (let i = 0, len = data.length; i < len; i++) { - let obj = data[i]; - if (!obj[idkey]) { - error(`配置${key}的数据有误,唯一标识 ${idkey} 值为0或者没有${idkey}`); - continue; - } - let to = new CfgCreator(); - to.decode(obj); - if (dict.has(to.id)) { - error(`配置${key}的数据有误,唯一标识 id 有重复值:${to.id}`) - process.abort(); - } - dict.set(to.id, to); - } - return dict; - }); - }, - loadAll() { - let fileArr = jetpack.list(jsonPath); - for (let f of fileArr) { - let key = f.replace('_tbl.json', ''); - let parser = parsers[key]; - let json = jetpack.read(`${jsonPath}/${f}`, 'json'); - if (parser && json){ - if (Array.isArray(json)) { - let data = parser(json); - if (data) { // 支持一些void的情况 - $cfg.set(key, data); - } - } else { - $cfg.set(key, json); - } - } + return { + regParser, + regCommonParser(key: string, CfgCreator: { new(): Cfg }, idkey = 'id') { + regParser(key, (data: any[]): any => { + if (!data) return + let dict = new Map() + for (let i = 0, len = data.length; i < len; i++) { + let obj = data[i] + if (!obj[idkey]) { + error(`配置${ key }的数据有误,唯一标识 ${ idkey } 值为0或者没有${ idkey }`) + continue + } + let to = new CfgCreator() + to.decode(obj) + if (dict.has(to.id)) { + error(`配置${ key }的数据有误,唯一标识 id 有重复值:${ to.id }`) + process.abort() + } + dict.set(to.id, to) + } + return dict + }) + }, + loadAll() { + let fileArr = jetpack.list(jsonPath) + for (let f of fileArr) { + let key = f.replace('_tbl.json', '') + let parser = parsers[key] + let json = jetpack.read(`${ jsonPath }/${ f }`, 'json') + if (parser && json) { + if (Array.isArray(json)) { + let data = parser(json) + if (data) { // 支持一些void的情况 + $cfg.set(key, data) } - new GameEnv().init($cfg.get(BaseConst.COMPOUND)); - Object.assign(global, { - $cfg: $cfg - }) - }, + } else { + $cfg.set(key, json) + } + } + } + new GameEnv().init($cfg.get(BaseConst.COMPOUND)) + Object.assign(global, { + $cfg: $cfg + }) } - /** - * 注册配置解析 - * @param key 配置的标识 - * @param parser 解析器 - */ - function regParser(key: string, parser: ConfigDataParser) { - parsers[key] = parser; - } -})(); + } + + /** + * 注册配置解析 + * @param key 配置的标识 + * @param parser 解析器 + */ + function regParser(key: string, parser: ConfigDataParser) { + parsers[key] = parser + } +})() /** * 配置数据解析函数 */ export interface ConfigDataParser { - (data: any): any; + (data: any): any; } -export interface Cfg -{ - /** - * 解析配置 - * @param {*} data - * @param {*} [local] 没有接口,但是需要本地赋值的数据 - */ - decode?: { (local?: any):void }; - id?: number; +export interface Cfg { + /** + * 解析配置 + * @param {*} data + * @param {*} [local] 没有接口,但是需要本地赋值的数据 + */ + decode?: { (local?: any): void }; + id?: number; } diff --git a/src/global.d.ts b/src/global.d.ts index 469d432..fbdd22c 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -1,299 +1,308 @@ -import {IMsg} from "./message/IMsg"; -import {Client, Room} from "colyseus"; -import {PetInfo, PetInfoMsg} from "./message/PetInfo"; -import {BattleHandler} from "./rooms/logic/Handler/BattleHandler"; -import {SkillInfoMsg} from "./message/SkillInfo"; -import {PartResultMsg} from "./message/PartResult"; -import {RemovePetMsg} from "./message/RemovePetMsg"; -import {Dispatcher} from "@colyseus/command"; -import {Delayed} from "@gamestdio/timer/lib/Delayed"; -import {Player} from "./rooms/schema/Player"; -import {RobotClient} from "./robot/RobotClient"; +import { IMsg } from './message/IMsg' +import { Client } from 'colyseus' +import { PetInfo, PetInfoMsg } from './message/PetInfo' +import { BattleHandler } from './rooms/logic/Handler/BattleHandler' +import { SkillInfoMsg } from './message/SkillInfo' +import { PartResultMsg } from './message/PartResult' +import { RemovePetMsg } from './message/RemovePetMsg' +import { Dispatcher } from '@colyseus/command' +import { Delayed } from '@gamestdio/timer/lib/Delayed' +import { Player } from './rooms/schema/Player' +import { RobotClient } from './robot/RobotClient' -export {}; +export {} declare global { - namespace NodeJS { - interface Global { - NODE_ENV: string - ROOT_PATH: string - $cfg: any - isProd: boolean - } + namespace NodeJS { + interface Global { + NODE_ENV: string + ROOT_PATH: string + $cfg: any + isProd: boolean } + } } /** * GeneralRoom 扩展方法 */ -declare module "colyseus" { - interface Room { - battleMan: BattleHandler; - dispatcher: Dispatcher; - mainClock: Delayed; - robotCount: number; - match: string | undefined ; - score: number; - /** - * 根据sessionId获取client - * @param player 玩家id或者玩家的对象 - */ - getClient(player: string | Player): Client; +declare module 'colyseus' { + interface Room { + battleMan: BattleHandler; + dispatcher: Dispatcher; + mainClock: Delayed; + robotCount: number; + match: string | undefined; + score: number; - /** - * 获取当前room的client数量 - */ - clientCount(): number; - // >>>>>>>>> Begin of extend send message <<<<<<<<<<<<< - /** - * 广播玩家加入房间 - * @param data - * @param options - */ - bUserJoin(data?: any, options?: any): void; + /** + * 根据sessionId获取client + * @param player 玩家id或者玩家的对象 + */ + getClient(player: string | Player): Client; - /** - * 广播玩家离开 - * @param data - */ - bUserLeft(data?: any): void; + /** + * 获取当前room的client数量 + */ + clientCount(): number; - /** - * 给指定用户下发英雄选择结果 - * @param client - * @param data - */ - sSelectHero(client: Client, data?: any):void; + // >>>>>>>>> Begin of extend send message <<<<<<<<<<<<< + /** + * 广播玩家加入房间 + * @param data + * @param options + */ + bUserJoin(data?: any, options?: any): void; - /** - * 广播英雄选择结果 - * @param data - */ - bSelectHero(data?: any):void; + /** + * 广播玩家离开 + * @param data + */ + bUserLeft(data?: any): void; - /** - * 下发抽牌信息 - * @param client - * @param data - */ - sDrawCard(client: Client, data?: any):void; + /** + * 给指定用户下发英雄选择结果 + * @param client + * @param data + */ + sSelectHero(client: Client, data?: any): void; + + /** + * 广播英雄选择结果 + * @param data + */ + bSelectHero(data?: any): void; + + /** + * 下发抽牌信息 + * @param client + * @param data + */ + sDrawCard(client: Client, data?: any): void; - /** - * 增加一个随从 - * @param data - */ - bAddPet(data?: PetInfoMsg): void; + /** + * 增加一个随从 + * @param data + */ + bAddPet(data?: PetInfoMsg): void; - /** - * 施放一个技能 - * @param data - */ - bCastSkill(data?: SkillInfoMsg): void; + /** + * 施放一个技能 + * @param data + */ + bCastSkill(data?: SkillInfoMsg): void; - /** - * 广播偷卡信息 - * @param data - * @param options - */ - bStealCard(data?: any, options?: any):void; + /** + * 广播偷卡信息 + * @param data + * @param options + */ + bStealCard(data?: any, options?: any): void; - /** - * 单独下发一个偷卡信息 - * @param data - */ - sStealCard(data?: any):void; + /** + * 单独下发一个偷卡信息 + * @param data + */ + sStealCard(data?: any): void; - /** - * 广播一个抽卡信息 - * @param data - * @param options - */ - bDrawCard(data?: any, options?: any):void; + /** + * 广播一个抽卡信息 + * @param data + * @param options + */ + bDrawCard(data?: any, options?: any): void; - /** - * 广播一个弃卡信息 - * @param data - * @param options - */ - bRemoveCard(data?: any, options?: any):void; + /** + * 广播一个弃卡信息 + * @param data + * @param options + */ + bRemoveCard(data?: any, options?: any): void; - /** - * 移除随从 - * @param data - * @param options - */ - bRemovePet(data?: RemovePetMsg, options?: any): void; - /** - * 广播游戏进行中的决斗结果 - * @param data - * @param options - */ - bPartResult(data?: PartResultMsg, options?: any): void; + /** + * 移除随从 + * @param data + * @param options + */ + bRemovePet(data?: RemovePetMsg, options?: any): void; - /** - * 广播游戏最终结果 - * @param data - * @param options - */ - bGameResult(data?: any, options?: any): void; + /** + * 广播游戏进行中的决斗结果 + * @param data + * @param options + */ + bPartResult(data?: PartResultMsg, options?: any): void; - /** - * 发送换卡消息 - * @param client - * @param data - */ - sChangeCard(client: Client, data?: any):void; + /** + * 广播游戏最终结果 + * @param data + * @param options + */ + bGameResult(data?: any, options?: any): void; - /** - * 发需要替换随从的消息给客户端 - * @param player - * @param data - */ - sNeedChangePet(player: string | Player, data?: any): void; + /** + * 发送换卡消息 + * @param client + * @param data + */ + sChangeCard(client: Client, data?: any): void; - /** - * 发送给个人的消息列表 - * @param client - * @param data - */ - sMsgQueue(client: Client, data: IMsg[]): void; + /** + * 发需要替换随从的消息给客户端 + * @param player + * @param data + */ + sNeedChangePet(player: string | Player, data?: any): void; + + /** + * 发送给个人的消息列表 + * @param client + * @param data + */ + sMsgQueue(client: Client, data: IMsg[]): void; - /** - * 广播的消息列表 - * 例: - * let datas:IMsg[] = []; - * datas.push({errcode: 0, type: '消息类型', data: {pid: 1}}); - * this.room.bMsgQueue(datas); - * @param datas - * @param options - */ - bMsgQueue(datas: IMsg[], options?: any): void; + /** + * 广播的消息列表 + * 例: + * let datas:IMsg[] = []; + * datas.push({errcode: 0, type: '消息类型', data: {pid: 1}}); + * this.room.bMsgQueue(datas); + * @param datas + * @param options + */ + bMsgQueue(datas: IMsg[], options?: any): void; - send(client: Client, type: string, data?: any): void; + send(client: Client, type: string, data?: any): void; - // >>>>>>>>> End of extend send message <<<<<<<<<<<<< + // >>>>>>>>> End of extend send message <<<<<<<<<<<<< - // >>>>>>>>> Begin of extend functions <<<<<<<<<<<<< + // >>>>>>>>> Begin of extend functions <<<<<<<<<<<<< - /** - * 随机从一个玩家那里抽一定数量的卡, 并将抽卡信息广播出去 - * @param srcplayer - * @param dstplayer 目标玩家 - * @param count 抽卡数量 - */ - drawCardFromPlayer(srcplayer: string, dstplayer: string, count: number) :number; + /** + * 随机从一个玩家那里抽一定数量的卡, 并将抽卡信息广播出去 + * @param srcplayer + * @param dstplayer 目标玩家 + * @param count 抽卡数量 + */ + drawCardFromPlayer(srcplayer: string, dstplayer: string, count: number): number; - /** - * 弃卡, 并广播消息 - * @param dstplayer 目标玩家 - * @param count - * @param fromplayer - */ - giveUpCard(dstplayer: string, count: number, fromplayer?: string): number; + /** + * 弃卡, 并广播消息 + * @param dstplayer 目标玩家 + * @param count + * @param fromplayer + */ + giveUpCard(dstplayer: string, count: number, fromplayer?: string): number; - /** - * 补卡, 并广播消息 - * @param dstplayer 目标玩家 - * @param count 补多少张, 该值和max_count至少一个不为0 - * @param max_count 补到多少张, 如果count和max_count都不为0, 则抽 Math.min(count, (max_count - 当前手牌数)) - * @param source 0: 正常抽卡, 1: 技能, 2: gm命令抽的卡 - * @param fromplayer - * @param extData 将抽到的卡变成特定的效果 - */ - addCard(dstplayer: string, count: number, max_count: number, source?: number, fromplayer?: string, extData?: {}): number; + /** + * 补卡, 并广播消息 + * @param dstplayer 目标玩家 + * @param count 补多少张, 该值和max_count至少一个不为0 + * @param max_count 补到多少张, 如果count和max_count都不为0, 则抽 Math.min(count, (max_count - 当前手牌数)) + * @param source 0: 正常抽卡, 1: 技能, 2: gm命令抽的卡 + * @param fromplayer + * @param extData 将抽到的卡变成特定的效果 + */ + addCard(dstplayer: string, count: number, max_count: number, source?: number, fromplayer?: string, extData?: {}): number; - /** - * 更新玩家血量 - * @param dstplayer - * @param hp - * @param reason - * @param fromplayer - */ - updateHp(dstplayer: string, hp: number, reason?: string, fromplayer?: string): number; + /** + * 更新玩家血量 + * @param dstplayer + * @param hp + * @param reason + * @param fromplayer + */ + updateHp(dstplayer: string, hp: number, reason?: string, fromplayer?: string): number; - /** - * 更新随从信息 - * @param datas - * @param fromplayer - */ - updatePet(datas: PetInfo[], fromplayer?: string): void; - /** - * 更新随从信息, 统计用 - * @param datas - * @param fromplayer - */ - updatePetStat(datas: PetInfo[], fromplayer?: string): void; + /** + * 更新随从信息 + * @param datas + * @param fromplayer + */ + updatePet(datas: PetInfo[], fromplayer?: string): void; - /** - * 给room.mainClock设定任务 - * mainClock任何时候只有一个可执行的任务 - * @param millisecond - * @param handler - * @param name - */ - beginSchedule(millisecond: number, handler: Function, name: string): void; + /** + * 更新随从信息, 统计用 + * @param datas + * @param fromplayer + */ + updatePetStat(datas: PetInfo[], fromplayer?: string): void; - /** - * 取消当前room.mainClock的任务 - * mainClock任何时候只有一个可执行的任务 - * 返回当前剩余的毫秒数 - * @param name - */ - stopSchedule(name: string): number; - /** - * 给room.mainClock增加n秒 - * @param name - * @param millisecond - * @param reason - */ - addScheduleTime(millisecond: number, reason?: string, name?: string, ): void; + /** + * 给room.mainClock设定任务 + * mainClock任何时候只有一个可执行的任务 + * @param millisecond + * @param handler + * @param name + */ + beginSchedule(millisecond: number, handler: Function, name: string): void; - /** - * 为一个玩家生产n张指定效果id的卡 - * @param effectId - * @param count - * @param player - * @param fromplayer - */ - generateCard({player, count, effectId, fromplayer, options} - : {player: string | Player, - count: number, - effectId: number, - fromplayer?: string | Player, - options?: any}): number; - /** - * 添加一个机器人 - * @param playerId - */ - addRobot(playerId?: string):void; + /** + * 取消当前room.mainClock的任务 + * mainClock任何时候只有一个可执行的任务 + * 返回当前剩余的毫秒数 + * @param name + */ + stopSchedule(name: string): number; - /** - * 添加一个辅助机器人 - * @param sessionId - */ - addAssistClient(sessionId: string): void; - /** - * 获取当前session的辅助机器人 - * @param sessionId - */ - getAssistClient(sessionId: string): RobotClient; + /** + * 给room.mainClock增加n秒 + * @param name + * @param millisecond + * @param reason + */ + addScheduleTime(millisecond: number, reason?: string, name?: string): void; - /** - * 获取对位玩家 - * @param srcPlayer - */ - getOppositePlayer(srcPlayer: string|Player): Player; + /** + * 为一个玩家生产n张指定效果id的卡 + * @param effectId + * @param count + * @param player + * @param fromplayer + */ + generateCard({ player, count, effectId, fromplayer, options } + : { + player: string | Player, + count: number, + effectId: number, + fromplayer?: string | Player, + options?: any + }): number; - /** - * 根据index获取玩家 - * @param {number} idx - * @return {Player} - */ - getPlayerByIdx(idx: number): Player; - } + /** + * 添加一个机器人 + * @param playerId + */ + addRobot(playerId?: string): void; + + /** + * 添加一个辅助机器人 + * @param sessionId + */ + addAssistClient(sessionId: string): void; + + /** + * 获取当前session的辅助机器人 + * @param sessionId + */ + getAssistClient(sessionId: string): RobotClient; + + /** + * 获取对位玩家 + * @param srcPlayer + */ + getOppositePlayer(srcPlayer: string | Player): Player; + + /** + * 根据index获取玩家 + * @param {number} idx + * @return {Player} + */ + getPlayerByIdx(idx: number): Player; + } } diff --git a/src/index.ts b/src/index.ts index 70b505f..ef847d5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,7 +4,6 @@ import cors from 'cors' import { RedisPresence, Server } from 'colyseus' import { monitor } from '@colyseus/monitor' import rateLimit from 'express-rate-limit' -// import socialRoutes from "@colyseus/social/express" import { GeneralRoom } from './rooms/GeneralRoom' import { initData } from './common/GConfig' import { Config } from './cfg/Config' diff --git a/src/rooms/RankedLobbyRoom.ts b/src/rooms/RankedLobbyRoom.ts index 0c3d6d8..91488bc 100644 --- a/src/rooms/RankedLobbyRoom.ts +++ b/src/rooms/RankedLobbyRoom.ts @@ -2,7 +2,7 @@ import { Client, generateId, matchMaker, Room, ServerError } from 'colyseus' import { BaseConst } from '../constants/BaseConst' import { IncomingMessage } from 'http' import { checkMatchTicket } from '../common/WebApi' -import { error, matchlog } from '../common/Debug' +import { matchlog } from '../common/Debug' import { retry } from 'colyseus/lib/Utils' import { RoomListingData } from 'colyseus/lib/matchmaker/drivers/Driver' @@ -30,15 +30,12 @@ interface ClientStat { export class RankedLobbyRoom extends Room { /** - * If `allowUnmatchedGroups` is true, players inside an unmatched group (that - * did not reached `numClientsToMatch`, and `maxWaitingTime` has been - * reached) will be matched together. Your room should fill the remaining - * spots with "bots" on this case. + * 如果该值为true, 而且玩家所在组的等待时间已经达到maxWaitingTime, 那么系统就会匹配机器人给该组 */ allowUnmatchedGroups: boolean = true /** - * Evaluate groups for each client at interval + * 检查是否满足匹配条件的间隔时间 */ evaluateGroupsInterval = 1000 @@ -48,12 +45,12 @@ export class RankedLobbyRoom extends Room { groups: MatchmakingGroup[] = [] /** - * name of the room to create + * 匹配成功后创建的房间 */ roomToCreate = 'general_room' /** - * 最大匹配时间 + * 最大匹配时间, 在房间建立时, 会从配置文件中获取 */ maxWaitingTime = 15 * 1000 /** @@ -62,28 +59,34 @@ export class RankedLobbyRoom extends Room { */ groupAddOneTime = 10 * 1000 - /** - * after this time, try to fit this client with a not-so-compatible group - */ - maxWaitingTimeForPriority?: number = 10 * 1000 - /** * number of players on each match */ numClientsToMatch = 4 - // /** - // * after a group is ready, clients have this amount of milliseconds to confirm - // * connection to the created room - // */ - // cancelConfirmationAfter = 5000; /** * rank and group cache per-player */ stats: ClientStat[] = [] + /** + * 组队成员匹配分增值幅度 + * @type {number} + */ rank_mpa = 0.2 + /** + * 同分高于平均分幅度 + * @type {number} + */ fair_ir = 1.2 + /** + * 跨分高于平均分幅度 + * @type {number} + */ step_ir = 1.3 + /** + * 匹配比赛的id + * @type {string} + */ matchid = '100001' async onAuth(client: Client, options: any, request: IncomingMessage) { @@ -94,7 +97,7 @@ export class RankedLobbyRoom extends Room { try { await checkMatchTicket(accountid, this.matchid) } catch (err) { - let code = isNaN(err.message) ? 9: parseInt(err.message) + let code = isNaN(err.message) ? 9 : parseInt(err.message) throw new ServerError(code, 'not enough ticket') } return true @@ -410,7 +413,7 @@ export class RankedLobbyRoom extends Room { Object.assign(options, matchData) data.client.send('match_success', options) const mdata = data.options - matchlog(`${mdata.accountid}:${mdata.score}:${mdata.rank}:${data.seat}:${client.waitingTime}`) + matchlog(`${ mdata.accountid }:${ mdata.score }:${ mdata.rank }:${ data.seat }:${ client.waitingTime }`) } })) diff --git a/src/rooms/commands/SelectPetCommand.ts b/src/rooms/commands/SelectPetCommand.ts index 7249e72..3813e1c 100644 --- a/src/rooms/commands/SelectPetCommand.ts +++ b/src/rooms/commands/SelectPetCommand.ts @@ -1,83 +1,100 @@ -import {Command} from "@colyseus/command"; -import {CardGameState} from "../schema/CardGameState"; -import {Client} from "colyseus"; -import {TurnEndCommand} from "./TurnEndCommand"; -import {GameEnv} from "../../cfg/GameEnv"; -import gameUtil from "../../utils/game.util"; +import { Command } from '@colyseus/command' +import { CardGameState } from '../schema/CardGameState' +import { Client } from 'colyseus' +import { TurnEndCommand } from './TurnEndCommand' +import { GameEnv } from '../../cfg/GameEnv' +import gameUtil from '../../utils/game.util' /** * 选择随从或者法术 */ -export class SelectPetCommand extends Command { - async execute({client, cardId, playerId, pos, effCards, oldpos} = this.payload) { - let sessionId = client.sessionId; - let player = this.state.players.get(sessionId); - let ap = 0; - let moreAp = 0; - let count = 0; - let targetCard; - let effectRate = this.room.battleMan.getTransEffCardRate(player); - // 检查效果卡, 并从玩家手牌中移除 - let eff_cnt = 0; // 效果卡数量 - let dbpt_cnt = 0; // 点数翻倍卡数量 - let transCount = 0; - for (let eCardId of effCards) { - if (!player.cards.has(eCardId + '')) { - continue; - } - let card = player.cards.get(eCardId + '').clone(); - player.cardQueue.push(card); - if (card.type === 3) { - dbpt_cnt ++; - } else if (card.type === 2){ - eff_cnt ++; - } else { - transCount ++; - } - } - gameUtil.deleteCardFromPlayer(player, effCards); - if (effectRate && transCount) { - eff_cnt += (transCount / effectRate | 0); - } - for (let card of this.state.cards.values()) { - ap += card.number; - count ++; - if (count === 3) { - moreAp += new GameEnv().baseAddScore; - } else if (count > 3) { - moreAp += new GameEnv().extraAddScore; - } - if (card.id == cardId) { - targetCard = card; - } - } - if (!targetCard) { - return; - } - //停止选随从计时, 并更新player.extraTime; - let elapsedTime = this.room.stopSchedule('select_pet'); - if (elapsedTime >= 0) { - let count = elapsedTime - new GameEnv().playerActTime * 1000; - let newCount = player.extraTime - Math.min(count, 0); - player.extraTime = Math.max(newCount, 0); - } - - let dstplayer = this.state.players.get(playerId); - let dstpet; - if (dstplayer && pos != undefined) { - dstpet = dstplayer.pets.get(pos+''); - } - let cardpoint = moreAp + ap; - let data = {srcplayer: player, card: targetCard.effect, cardpoint, eff_cnt, dstplayer, dstpet, dbpt_cnt, oldpos} - let time = this.room.battleMan.useCard(data); - await this.delay(time); - return [new TurnEndCommand()]; - +export class SelectPetCommand extends Command { + async execute({ + client, + cardId, + playerId, + pos, + effCards, + oldpos + } = this.payload) { + let sessionId = client.sessionId + let player = this.state.players.get(sessionId) + let ap = 0 + let moreAp = 0 + let count = 0 + let targetCard + let effectRate = this.room.battleMan.getTransEffCardRate(player) + // 检查效果卡, 并从玩家手牌中移除 + let eff_cnt = 0 // 效果卡数量 + let dbpt_cnt = 0 // 点数翻倍卡数量 + let transCount = 0 + for (let eCardId of effCards) { + if (!player.cards.has(eCardId + '')) { + continue + } + let card = player.cards.get(eCardId + '').clone() + player.cardQueue.push(card) + if (card.type === 3) { + dbpt_cnt++ + } else if (card.type === 2) { + eff_cnt++ + } else { + transCount++ + } } + gameUtil.deleteCardFromPlayer(player, effCards) + if (effectRate && transCount) { + eff_cnt += (transCount / effectRate | 0) + } + for (let card of this.state.cards.values()) { + ap += card.number + count++ + if (count === 3) { + moreAp += new GameEnv().baseAddScore + } else if (count > 3) { + moreAp += new GameEnv().extraAddScore + } + if (card.id == cardId) { + targetCard = card + } + } + if (!targetCard) { + return + } + //停止选随从计时, 并更新player.extraTime; + let elapsedTime = this.room.stopSchedule('select_pet') + if (elapsedTime >= 0) { + let count = elapsedTime - new GameEnv().playerActTime * 1000 + let newCount = player.extraTime - Math.min(count, 0) + player.extraTime = Math.max(newCount, 0) + } + + let dstplayer = this.state.players.get(playerId) + let dstpet + if (dstplayer && pos != undefined) { + dstpet = dstplayer.pets.get(pos + '') + } + let cardpoint = moreAp + ap + let data = { + srcplayer: player, + card: targetCard.effect, + cardpoint, + eff_cnt, + dstplayer, + dstpet, + dbpt_cnt, + oldpos + } + let time = this.room.battleMan.useCard(data) + await this.delay(time) + return [new TurnEndCommand()] + + } }