271 lines
11 KiB
TypeScript
271 lines
11 KiB
TypeScript
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<string> = 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;
|
|
}
|
|
}
|
|
});
|