import {Room} from "colyseus"; import gameUtil from "../utils/game.util"; import {debugRoom, error} from "../common/Debug"; import {PlayerStateConst} from "../constants/PlayerStateConst"; import {PetInfo} from "../message/PetInfo"; import {PlayDeadCommand} from "./commands/PlayDeadCommand"; import {GameEnv} from "../cfg/GameEnv"; import {Player} from "./schema/Player"; import {StateTypeEnum} from "./enums/StateTypeEnum"; /** * 一些常用的方法 */ Object.defineProperties(Room.prototype, { drawCardFromPlayer: { value: function (srcplayer: string, dstplayer: string, count: number): number { debugRoom(`玩家 ${srcplayer} 从 ${dstplayer} 偷 ${count} 张卡`); let player1 = this.state.players.get(dstplayer); let player0: Player = this.state.players.get(srcplayer); /** * 首先取目标玩家手牌数和偷牌数量的最小值 * 然后取目标玩家的手牌数和配置中玩家手牌数的差值 * 取以上2值的最小值为实际偷牌数量 */ let realCount = Math.min(player1.cards.size, count); let maxCount = new GameEnv().maxCardNum; realCount = Math.min(realCount, maxCount - player0.cards.size); let tmpCards = gameUtil.removeCard(player1, realCount); gameUtil.addCardToPlayer(this, player0, tmpCards, player1); let cardIds = tmpCards.map(card => card.id); let client = this.getClient(player0); player0.statData.inc(StateTypeEnum.SCOUNT, tmpCards.length); //广播一个偷卡成功信息, 并私信一个偷卡详情给当前玩家 let msgData = { srcplayer, dstplayer, cards: cardIds }; this.bStealCard(msgData, {except: client, afterNextPatch: true}); let sMsgData = { srcplayer, dstplayer, cards: tmpCards } this.sStealCard(client, sMsgData); return tmpCards.length; } }, giveUpCard: { value: function (dstplayer: string, count: number, fromplayer?: string){ let player = this.state.players.get(dstplayer); let tmpCards = gameUtil.removeCard(player, count); let time = this.battleMan.onCardDroped(player, tmpCards); debugRoom(`giveUpCard add time: ${time}`); let fromP = this.state.players.get(fromplayer); if (fromP.id != player.id){ fromP.statData.inc(StateTypeEnum.GCOUNT, tmpCards.length); } let cardIds = tmpCards.map(card => card.id); let msgData = { player: dstplayer, cards: cardIds }; this.bRemoveCard(msgData); return tmpCards.length; } }, /** * 补卡, 并广播消息 * @param dstplayer 目标玩家 * @param count 补多少张, 该值和max_count至少一个不为0 * @param max_count 补到多少张, 如果count和max_count都不为0, 则抽 Math.min(count, (max_count - 当前手牌数)) * @param source 0: 正常抽卡, 1: 技能, 9: GM * @param fromplayer */ addCard: { value: function ( dstplayer: string, count: number, max_count: number, source: number = 0, fromplayer?: string, extData?: {}): number { let maxCountCfg = new GameEnv().maxCardNum; let maxCount = Math.min(maxCountCfg, max_count); let player = this.state.players.get(dstplayer); let curCount = player.cards.size; if (count > 0) { if (maxCount > 0) { count = Math.min(count, maxCount - curCount); } else { count = Math.min(count, maxCountCfg - curCount); } } else if (maxCount > 0){ count = maxCount - curCount; } else { error("补卡方法的参数有问题, count和max_count都为0"); return 0; } let player2 = fromplayer ? this.state.players.get(fromplayer) : null; let cards = gameUtil.drawCard(this, this.state.cardQueue, player, count, player2, extData); if (source == 1 && player2 && player2.id != player.id) { player2.statData.inc(StateTypeEnum.ACOUNT, cards.length); } let client = this.getClient(dstplayer); let sData = { player: dstplayer, cards: cards, source: source }; this.sDrawCard(client, sData); let cardIds = cards.map(card => card.id); let bData = { player: dstplayer, cards: cardIds, source: source }; this.bDrawCard(bData, {except: client}); return cardIds.length; } }, updateHp: { value: function (dstplayer: string, hp: number, reason?: string, fromplayer?: string): number { let player = this.state.players.get(dstplayer); if (!player) { error(`updateHp 未找到玩家 ${dstplayer}`); return 0; } if (player.state === PlayerStateConst.PLAYER_DEAD) { return 0; } else { let dstHp = player.hp + (hp | 0); let sourceP = this.state.players.get(fromplayer); if (sourceP && hp < 0) { sourceP.statData.inc(StateTypeEnum.DMG, Math.min(-hp, player.hp)); player.statData.inc(StateTypeEnum.TDMG, Math.min(-hp, player.hp)); } debugRoom(`更新血量: ${player.id} ${player.hp} -> ${hp}, reason: ${reason}`); if (dstHp <= 0) { dstHp = 0; this.dispatcher.dispatch(new PlayDeadCommand(), {player: player}); } player.hp = dstHp; } return player.hp; } }, /** * 更新随从信息 * @param data */ updatePet: { value: function (datas: PetInfo[], fromplayer?: string): void { let playerSet: Set = new Set(); for (let obj of datas) { let pid = obj.player; playerSet.add(pid); let player = this.state.players.get(pid); let pet = player.pets.get(obj.pos + ''); pet.id = obj.id; pet.ap = obj.ap; pet.extAp = obj.extAp; pet.harmReduce = obj.harmReduce; pet.skills.length = 0; pet.state = (obj.ap > 0 || obj.pos == 0) ? 1: 2; pet.effectCount = obj.effectCount; pet.point = obj.point; pet.em = obj.em; pet.silence = obj.silence; pet.hps = obj.hps; if (obj.skills) { pet.skills.length = 0; for (let s of obj.skills) { pet.skills.push(s); } } if (obj.extSkills) { pet.extSkills.length = 0; for (let s of obj.extSkills) { pet.extSkills.push(s); } } if (obj.buffs) { pet.buffs.length = 0; for (let s of obj.buffs) { pet.buffs.push(s); } } } this.broadcast("pet_update_s2c", {data: [...playerSet]}, {afterNextPatch: true}); } }, /** * 更新随从信息, 统计用 * @param datas * @param fromplayer */ updatePetStat: { value: function (datas: PetInfo[], fromplayer?: string): void { let player = this.state.players.get(fromplayer); for (let data of datas) { let targetPlayer = this.state.players.get(data.player); let valOld = targetPlayer.petData.get(data.pos) || 0; let valNew = data.ap + data.extAp; targetPlayer.petData.set(data.pos, valNew); if (!player || !targetPlayer) { error(`updatePetStat, player or targetPlayer is null ${!!player} ${!!targetPlayer}`); } debugRoom(`updatePetStat, val change, old: ${valOld}, new: ${valNew}`); if (valNew < valOld) { player?.statData.inc(StateTypeEnum.DMG, valOld - valNew); targetPlayer?.statData.inc(StateTypeEnum.TDMG, valOld - valNew); } } } }, /** * 为一个玩家生产n张指定效果id的卡, 并加入手牌 * @param effectId * @param count * @param player */ generateCard: { value: function ({player, count, effectId, fromplayer, options} : {player: string | Player, count: number, effectId: number, fromplayer?: string | Player, options?: any}): number { let tmpCards = []; let maxCount = new GameEnv().maxCardNum; let dstplayer; if (typeof player == 'string') { dstplayer = this.state.players.get(player); } else { dstplayer = player; } let realCount = Math.min(count, maxCount - dstplayer.cards.size); for (let i = 0; i < realCount; i++) { let cardId = 1000 + (this.state.maxCardId ++ ); let card = gameUtil.generateCardWithEffect(effectId, cardId, options); if (card) { tmpCards.push(card); } } if (tmpCards.length == 0) { error(`生成卡牌时, 无法获取对应的effect配置, ${dstplayer.id}, ${effectId}, ${realCount}`) return 0; } let sourcePlayer; if (typeof fromplayer == 'string') { sourcePlayer = this.state.players.get(fromplayer); if (sourcePlayer.id !== dstplayer.id) { sourcePlayer.statData.inc(StateTypeEnum.CCOUNT, tmpCards.length); } } else { sourcePlayer = player; } gameUtil.addCardToPlayer(this, dstplayer, tmpCards, sourcePlayer); let client = this.getClient(dstplayer); let sData = { player: dstplayer.id, cards: tmpCards, source: 1 }; this.sDrawCard(client, sData); let cardIds = tmpCards.map(card => card.id); let bData = { player: dstplayer.id, cards: cardIds, source: 1 }; this.bDrawCard(bData, {except: client}); return realCount; } } });