card_svr/src/rooms/logic/Handler/BattleHandler.ts
2021-01-18 12:08:42 +08:00

1023 lines
32 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {Player} from "../../schema/Player";
import {Card} from "../../schema/Card";
import {CardGameState} from "../../schema/CardGameState";
import { PlayerHandler } from "./PlayerHandler";
import CfgMan from "../CfgMan";
import { EffectCardType, GameCampType, GameUnitType, SkillEffectType, SkillRangeUnitType } from "../skill/SkillConst";
import { Pet } from "rooms/schema/Pet";
import {PetUpdateProcess, SkillParam, SkillResult, SkillTarget} from "../skill/SkillParam";
import { nosync, Room } from "colyseus";
import { Skill } from "../skill/Skill";
import { PetHandler } from "./PetHandler";
import { SKillEffectData, SkillInfoMsg } from "message/SkillInfo";
import { PetInfo } from "message/PetInfo";
import arrUtil from "../../../utils/array.util";
import { debugRoom } from "../../../common/Debug";
export class BattleHandler {
private _cs: CardGameState;
private _players: Map<Player, PlayerHandler> = new Map();
private _playerids: Map<string, Player> = new Map();
_room: Room;
private _flowcount: number = 0;
private _sktime: number;
private _gamestart: boolean = false;
private _cacheSkills: SkillTarget[] = [];
private _cachePets: PetHandler[] = [];
private _lastlinkph: PlayerHandler;
//--------------------对外接口--player相关---(外部调用)----------------------------
public init(cs: CardGameState, room: Room){
this._cs = cs;
this._room = room;
this._gamestart = false;
};
public delPlayer(aplayer: Player){
let id = aplayer.id + '';
let ph = this.getPlayer(aplayer);
this._players.forEach((item: PlayerHandler) => {
if(item._friend == ph){
item._friend = null;
}
});
this._players.delete(aplayer);
this._playerids.delete(id);
};
public updatePlayer(aplayerid: string, newplayer: Player){
let oldplayer = this._playerids.get(aplayerid + '');
let ph: PlayerHandler = null;
if(oldplayer){
this._players.forEach((item: PlayerHandler) => {
if(item._player == oldplayer){
item._player = newplayer;
ph = item;
}
});
this._players.delete(oldplayer);
if(ph){
this._players.set(newplayer, ph);
this._playerids.set(aplayerid + '', newplayer);
}
}
if(!ph){
this.addPlayer(newplayer);
}
};
public updatePlayerHero(aplayer: Player){
let ph = this.getPlayer(aplayer);
if(!ph){
return false;
}
return ph.updateHero();
};
//----------------------------------------------------------------------------
public addPlayer(aplayer: Player): PlayerHandler{
let ph = new PlayerHandler();
ph.init(aplayer, this);
this._players.forEach((item: PlayerHandler) => {
if(item._player.team == aplayer.team && item._player != aplayer){
item._friend = ph;
ph._friend = item;
}
});
this._players.set(aplayer, ph);
this._playerids.set(aplayer.id + '', aplayer);
return ph;
};
public getPlayer(aplayer: Player): PlayerHandler{
return aplayer? this._players.get(aplayer): null;
};
public getFriend(aplayer: PlayerHandler): PlayerHandler{
if(aplayer && aplayer._friend){
return aplayer._friend;
}
// 防止出错冗余处理
let res;
for(let [key, obj] of this._players){
if(obj._friend == aplayer){
aplayer._friend = obj;
res = obj;
break;
}
}
return res;
};
public petIsValid(pet: PetHandler, players: PlayerHandler[], ct: GameUnitType): boolean{
if(!players || players.length == 0 || !pet || !pet.isAlive()){
return false;
}
let obj = players.find( (item: PlayerHandler) =>{
return item.isMyPet(pet);
});
if(!obj){
return false;
}
switch(ct){
case GameUnitType.BATTLEUNIT:
return true;
case GameUnitType.HERO:
return pet._isHero;
case GameUnitType.PET:
return !pet._isHero;
default:
return false;
}
};
public getFinalTarget(ut: SkillRangeUnitType, players: PlayerHandler[], dstpet: PetHandler, srcpet: PetHandler,
senderpet: PetHandler, ct: GameUnitType,
checktaunt: boolean, isonlypet: boolean): PetHandler
{
let pet = dstpet;
let bok = false;
switch(ut){
case SkillRangeUnitType.SELF:
if(!pet){
pet = srcpet;
}
bok = !!pet;
break;
case SkillRangeUnitType.RANDOM_ONE:
case SkillRangeUnitType.RANDOM_ONE_EXOWNER:
case SkillRangeUnitType.RANDOM_ONE_EXSELF:
{
let expet:PetHandler = null;
if(ut == SkillRangeUnitType.RANDOM_ONE_EXOWNER){
expet = senderpet;
}else if(ut == SkillRangeUnitType.RANDOM_ONE_EXSELF){
expet = srcpet;
}
if(checktaunt){
let lst:PetHandler[] = [];
players.forEach((item:PlayerHandler)=>{
item.findAllTauntPets(lst, isonlypet, expet);
});
if(lst.length > 0){
pet = arrUtil.randomOne(lst);
bok = true;
}
}
if(!bok){
let lst:PetHandler[] = [];
players.forEach((item:PlayerHandler)=>{
item.findAllPets(lst, isonlypet, expet);
});
if(lst.length > 0){
pet = arrUtil.randomOne(lst);
bok = true;
}
}
}
break;
case SkillRangeUnitType.RANDOM_ONE_NOSHIELD:
{
let lst:PetHandler[] = [];
players.forEach((item:PlayerHandler)=>{
item.findAllNoShieldPets(lst, isonlypet);
});
if(lst.length > 0){
pet = arrUtil.randomOne(lst);
bok = true;
}
}
break;
case SkillRangeUnitType.OWNER:
pet = senderpet;
bok = !!pet;
break;
case SkillRangeUnitType.MAXAP_ONE:
{
let lst:PetHandler[] = [];
players.forEach((item:PlayerHandler)=>{
lst.push(item.getMaxAPPet(isonlypet));
});
pet = null;
if(lst.length > 0){
lst.forEach(element => {
if(!pet){
pet = element;
}else if(pet.totalAP() < element.totalAP()){
pet = element;
}
});
}
bok = !!pet;
}
break;
case SkillRangeUnitType.MINAP_ONE:
{
let lst:PetHandler[] = [];
players.forEach((item:PlayerHandler)=>{
lst.push(item.getMinAPPet(isonlypet));
});
pet = null;
if(lst.length > 0){
lst.forEach(element => {
if(!pet){
pet = element;
}else if(pet.totalAP() > element.totalAP()){
pet = element;
}
});
}
bok = !!pet;
}
break;
case SkillRangeUnitType.PET_LAST:
{
let lst:PetHandler[] = [];
players.forEach((item:PlayerHandler)=>{
let obj = item.getLastPet();
obj && lst.push(obj);
});
if(lst.length > 0){
pet = arrUtil.randomOne(lst);
bok = true;
}
}break;
default:
{
bok = this.petIsValid(pet, players, ct);
if(checktaunt && (!bok || !pet.isTaunt())){
for(let i = 0; i < players.length;i++){
let obj = players[i].findTauntPet();
if(obj){
pet = obj;
bok = true;
break;
}
}
}
}
break;
}
return bok? pet: null;
};
public buildSkillTarget(sk: Skill, src: PetHandler, dst: PetHandler | PlayerHandler): SkillTarget{
if(!dst){
return null;
}
let ut = GameUnitType.NONE;
if(dst instanceof PetHandler){
ut = (dst as PetHandler)._isHero? GameUnitType.HERO: GameUnitType.PET;
}else if(dst instanceof PlayerHandler){
ut = GameUnitType.PLAYER;
}
let owner = sk? sk._owner: null;
return new SkillTarget(sk, src? src._owner: owner, src, dst, ut);
};
public singleSkillTargets(sk: Skill, src: PetHandler, dst: PetHandler | PlayerHandler): SkillTarget[]{
let tgt = this.buildSkillTarget(sk, src, dst);
if(this.isFlowing() && tgt){
this._cacheSkills.push(tgt);
}
return tgt? [tgt]: null;
};
public singleSkillTarget(sk: Skill, src: PetHandler, dst: PetHandler | PlayerHandler): SkillTarget{
let tgt = this.buildSkillTarget(sk, src, dst);
if(this.isFlowing() && tgt){
this._cacheSkills.push(tgt);
}
return tgt;
};
public getSkillOppTargets(st: SkillTarget): SkillTarget[]{
let lst: SkillTarget[] = [];
lst.push(st.oppClone());
if(this.isFlowing()){
this._cacheSkills.push(...lst);
}
return lst;
};
public getSkillTargets(skill: Skill, param: SkillParam, lastph: PlayerHandler): SkillTarget[]{
let lst: SkillTarget[] = [];
let players = this.getTargetPlayers(skill._data.friendlyid, param.srcplayer, param.dstplayer, lastph);
if(players.length > 0){
switch(skill._data.targetid){
case GameUnitType.PLAYER:
if(skill._data.rangeid == SkillRangeUnitType.PLAYER_BELINKED){
this._lastlinkph && lst.push(
this.buildSkillTarget(skill, param.srcpet, this._lastlinkph)
);
}else{
players.forEach((item:PlayerHandler)=>{
lst.push(
this.buildSkillTarget(skill, param.srcpet, item)
);
});
}
break;
case GameUnitType.HERO:
players.forEach((item:PlayerHandler)=>{
lst.push(
this.buildSkillTarget(skill, param.srcpet, item._self)
);
});
break;
case GameUnitType.BATTLEUNIT:
case GameUnitType.PET:
if(skill.isSingleTarget()){
let pet = this.getFinalTarget(skill._data.rangeid, players, param.dstpet, param.srcpet, skill._petowner,
skill._data.targetid, !!skill._data.ridicule, skill._data.targetid == GameUnitType.PET);
pet && lst.push(
this.buildSkillTarget(skill, param.srcpet, pet)
);
}else{
let expet = skill.getExPet(param.srcpet);
players.forEach((item: PlayerHandler)=>{
item.exportAllPets(skill, param, expet, lst);
});
}
break;
default:
break;
}
}
if(this.isFlowing() && lst.length > 0){
this._cacheSkills.push(...lst);
}
return lst;
};
public getTargetPlayers(gct: GameCampType, src:PlayerHandler, dst:PlayerHandler, last: PlayerHandler): PlayerHandler[]{
let lst: PlayerHandler[] = [];
switch(gct){
case GameCampType.SELFPLAYER:
if(src && src.isAlive()){
lst.push(src);
}
break;
case GameCampType.FRIEND:
{
let obj = this.getFriend(src);
if(obj && obj.isAlive()){
lst.push(obj);
}
}
break;
case GameCampType.MYTEAM:
if(src){
src.isAlive() && lst.push(src);
let obj = this.getFriend(src);
obj && obj.isAlive() && lst.push(obj);
}
break;
case GameCampType.ENEMY:
if(dst && dst != src && dst._friend != src && dst.isAlive()){
lst.push(dst);
}
break;
case GameCampType.ENEMYTEAM:
for(let [key, obj] of this._players){
if(obj != src && obj.isAlive()){
if(src && obj != src._friend){
lst.push(obj);
}
}
}
break;
case GameCampType.ALLPLAYER:
for(let [key, obj] of this._players){
if(obj && obj.isAlive()){
lst.push(obj);
}
}
break;
case GameCampType.RANDOM_ENEMY:
{
let tmp: PlayerHandler[] = [];
for(let [key, obj] of this._players){
if(obj != src && obj.isAlive()){
if(src && obj != src._friend){
tmp.push(obj);
}
}
}
(tmp.length > 0) && lst.push(arrUtil.randomOne(tmp));
}
break;
case GameCampType.RANDOM_US:
{
let tmp: PlayerHandler[] = [];
if(src){
src.isAlive() && tmp.push(src);
let obj = this.getFriend(src);
obj && obj.isAlive() && tmp.push(obj);
}
(tmp.length > 0) && lst.push(arrUtil.randomOne(tmp));
}
break;
case GameCampType.FACE_ENEMY:
{
let bfind = false;
let player = this._room.getOppositePlayer(src.getId());
if(player){
let ph = this.getPlayer(player);
if(ph && ph.isAlive()){
lst.push(ph);
bfind = true;
}
}
if(!bfind){
return this.getTargetPlayers(GameCampType.RANDOM_ENEMY, src, dst, last);
}
}
break;
case GameCampType.ALLPLAYER_EXSELF:
for(let [key, obj] of this._players){
if(obj && obj.isAlive() && obj != src){
lst.push(obj);
}
}
break;
case GameCampType.LAST_HURT:
if(last && last != src && last.isAlive()){
lst.push(last);
}
break;
default:
break;
}
return lst;
};
public checkPets(pets: PetHandler[]){
pets.forEach((item: PetHandler) =>{
if(!item.isAlive()){
item.destroy();
}else{
item.resetBakAP();
}
});
};
public isFlowing(){
return this._flowcount > 0;
};
public beginFlow(step: string){
if(this._flowcount < 0){
debugRoom(`[beginFlow]${step}[error flowcount]${this._flowcount}`);
this._flowcount = 0;
};
if(this._flowcount == 0){
this._sktime = 0;
this._cacheSkills.length = 0;
this._cachePets.length = 0;
}
this._flowcount++;
debugRoom(`[beginFlow]${step}|${this._flowcount}`);
};
public endFlow(step: string){
let res = this._flowcount - 1;
if(res < 0){
debugRoom(`[endFlow]${step}[error flowcount]${this._flowcount}`);
res = 0;
}
debugRoom(`[endFlow]${step}|${res}`);
if(res == 0){
if(this._cacheSkills.length > 0){
this.onSkillResultNotify(this._cacheSkills);
this._cacheSkills.length = 0;
}
let nt = this._sktime * 1000;
if(this._cachePets.length > 0){
if(nt > 0){
this._room.clock.setTimeout(()=>{
this.onUpdatePets(this._cachePets, null);
this.checkPets(this._cachePets);
this._cachePets.length = 0;
}, nt);
nt += 100;
}else{
this.onUpdatePets(this._cachePets, null);
this.checkPets(this._cachePets);
this._cachePets.length = 0;
}
}
this._flowcount = res;
return nt;
}
this._flowcount = res;
return 0;
};
public onPlayerCardChanged(player: PlayerHandler){
this._players.forEach((item: PlayerHandler) => {
item.onCardChanged(player);
});
};
//--------------------对外接口(外部调用)----------------------------
/**
* 使用卡片
* @param obj
*/
public useCard(obj:
{srcplayer: Player, card: number, cardpoint: number, dbpt_cnt: number, eff_cnt: number, dstplayer: Player, dstpet: Pet,
oldpos?: number})
:number{
if(!obj || !obj.card){
return 0;
}
let ph = this.getPlayer(obj.srcplayer);
let dstph = this.getPlayer(obj.dstplayer);
let dstpt = dstph? dstph.getPet(obj.dstpet): null;
if(!ph){
return 0;
}
if(!dstpt && dstph){
dstpt = dstph._self;
}
this.beginFlow('useCard');
let pt = obj.cardpoint;
let cfg = CfgMan.findEffCardCfg(obj.card);
if(cfg && cfg.followdouble && obj.dbpt_cnt){
pt *= (obj.dbpt_cnt + 1);
}
if(!dstph){
dstph = ph;
}
let ps = new SkillParam(obj.card, pt, obj.eff_cnt, ph, null, dstph, dstpt);
ph.useCard(ps, obj.oldpos);
this.onUseCardEnd(ps);
return this.endFlow('useCard');
};
/**
* 使用技能
* @param obj
*/
public useSkill(obj:{
srcplayer: Player, skillid: number, dstplayer: Player, dstpet: Pet
}){
};
/**
* 确认玩家是否有换效果牌技能
* @param aplayer
*/
public hasTransEffCardSkill(aplayer: Player): boolean{
let ph = this.getPlayer(aplayer);
return ph && ph.hasTransEffCardSkill();
};
/**
* 获得玩家效果牌转换比率(几张普通卡转一张效果卡)
* @param aplayer
*/
public getTransEffCardRate(aplayer: Player): number{
let ph = this.getPlayer(aplayer);
return ph? ph.getTransEffCardRate(): 0;
};
/**
* 替换随从操作
* @param playerid
* @param petpos
* @param petid
*/
public replacePet(playerid: string, petpos: number, petid: string){
};
/**
* 吃牌/胡牌确认[暂不用]
* @param aplayer : 玩家
* @param fromplayer 吃别人的牌,自己胡牌时此参数传空
*/
public onCardLinkReady(aplayer: Player, fromplayer?: Player){
let ph = this.getPlayer(aplayer);
let fromph = this.getPlayer(fromplayer);
if(!ph){
return 0;
}
this.beginFlow('onCardLinkReady');
ph.onCardLinkReady(fromph);
return this.endFlow('onCardLinkReady');
};
/**
* 吃牌/胡牌结束
* @param aplayer :玩家
* @param linkcards :吃到的牌组信息
*/
public onCardLinkOver(aplayer: Player, linkcards: Card[], fromplayer?: Player){
let ph = this.getPlayer(aplayer);
let fromph = this.getPlayer(fromplayer);
if(!ph){
return 0;
}
this.beginFlow('onCardLinkOver');
this._lastlinkph = fromph;
ph.onCardLinkEnd(linkcards, fromph);
this._lastlinkph = null;
return this.endFlow('onCardLinkOver');
};
/**
* 出牌结束(出单张牌)
* @param aplayer : 玩家
* @param card : 单张牌
*/
public onCardDiscarded(aplayer: Player, card: Card){
let ph = this.getPlayer(aplayer);
if(!ph){
return 0;
}
this.beginFlow('onCardDiscarded');
ph.onCardDiscarded(card);
return this.endFlow('onCardDiscarded');
};
/**
* 使用卡牌结束(暂时自动回调,无需外部触发)
* @param sp :使用卡牌相关操作
*/
public onUseCardEnd(sp: SkillParam){
if(!sp){
return;
}
sp.srcplayer && sp.srcplayer.onUseCardEnd(sp);
};
/**
* 弃牌完成 //TODO:: 弃卡实装后须调用
* @param aplayer :玩家
* @param fromplayer : 谁使玩家弃牌的(自己主动弃牌的传空)
* @param dropcards : 弃掉的牌组
*/
public onCardDroped(aplayer: Player, dropcards: Card[], fromplayer?: Player){
let ph = this.getPlayer(aplayer);
let fromph = this.getPlayer(fromplayer);
if(!ph){
return 0;
}
// this.beginFlow('onCardDroped');
ph.onCardDroped(dropcards, fromph);
// return this.endFlow('onCardDroped');
return 0;
};
/**
* 获取牌完成
* @param aplayer :玩家
* @param fromplayer : 谁使玩家获得牌的(自己主动获得牌的传空)
* @param dropcards : 获得的牌组
*/
public onCardGetted(aplayer: Player, getcards: Card[], fromplayer?: Player){
if(!this._gamestart){
return;
}
let ph = this.getPlayer(aplayer);
let fromph = this.getPlayer(fromplayer);
if(!ph){
return 0;
}
// this.beginFlow('onCardGetted');
ph.onCardGetted(getcards, fromph);
// return this.endFlow('onCardGetted');
return 0;
};
/**
* 玩家回合开始
* @param aplayer
*/
public onPlayerRoundStart(aplayer: Player){
if(!this._gamestart){
this._gamestart = true;
}
let ph = this.getPlayer(aplayer);
if(!ph){
return 0;
}
this.beginFlow('onPlayerRoundStart');
ph.onRoundStart();
return this.endFlow('onPlayerRoundStart');
};
/**
* 玩家回合结束
* @param aplayer
*/
public onPlayerRoundEnd(aplayer: Player){
let ph = this.getPlayer(aplayer);
if(!ph){
return 0;
}
this.beginFlow('onPlayerRoundEnd');
ph.onRoundEnd();
// this.checkPets();
return this.endFlow('onPlayerRoundEnd');
};
/**
* 玩家死亡
* @param aplayer
*/
public onPlayerDead(aplayer: Player){
let ph = this.getPlayer(aplayer);
ph && ph.die();
this._players.forEach((item: PlayerHandler) => {
(item != ph) && item.onPlayerDie(ph);
});
this.delPlayer(aplayer);
};
/**
* 一局游戏开始
*/
public onGameStart(){
this._players.forEach((item: PlayerHandler) => {
item.onGameStart();
});
};
/**
* 一局游戏结束
*/
public onGameEnd(){
this._players.forEach((item: PlayerHandler) => {
item.clear();
});
this._players.clear();
this._playerids.clear();
this._gamestart = false;
};
// end--------------------------------------------------
// --------------------调用外部接口函数--------------------------
public onAddPetNotify(apet: PetHandler){
return this._room.bAddPet(apet.exportInfoMsg());
};
public onDelPetNotify(apet: PetHandler){
return this._room.bRemovePet(apet.exportRemoveMsg());
};
public onAskReplacePetNotify(aplayer: PlayerHandler){
return this._room.sNeedChangePet(aplayer.getId());
};
public onUpdatePetNotify(apet: PetHandler, from: PetHandler){
this.onUpdatePets([apet], from, true);
if(this.isFlowing()){
if(!this._cachePets.includes(apet)){
this._cachePets.push(apet);
}
}else{
let lst = [apet];
this.onUpdatePets(lst, from);
this.checkPets(lst);
}
};
public onUpdatePetsNotify(pets: PetHandler[], from: PetHandler){
if(!pets || pets.length <= 0){
return;
}
this.onUpdatePets(pets, from, true);
if(this.isFlowing()){
pets.forEach((item: PetHandler) =>{
if(!this._cachePets.includes(item)){
this._cachePets.push(item);
}
});
}else{
this.onUpdatePets(pets, from);
this.checkPets(pets);
}
};
public onUpdatePets(pets: PetHandler[], from: PetHandler, isstat: boolean = false){
if(!pets || pets.length <= 0){
return;
}
let lst: PetInfo[] = [];
pets.forEach((item: PetHandler) =>{
lst.push(item.exportInfo());
});
if(isstat){
this._room.updatePetStat(lst, from? from._owner.getId(): null);
}else{
this._room.updatePet(lst, from? from._owner.getId(): null);
}
};
public onPlayerAddCardNotify(aplayer: PlayerHandler, count: number, maxcount: number,
from?: PlayerHandler): number{
return this._room.addCard(aplayer.getId(), count, maxcount, 1, from? from.getId(): null);
};
public onPlayerStealCardNotify(srcplayer: PlayerHandler,
dstplayer: PlayerHandler, count: number): number{
return this._room.drawCardFromPlayer(srcplayer.getId(), dstplayer.getId(), count);
};
public onPlayerAddDirectCardNotify(aplayer: PlayerHandler, count: number, cardid: number,
from?: PlayerHandler){
return this._room.generateCard({player: aplayer.getId(), count, effectId: cardid,
fromplayer: from? from.getId(): null});
};
public onPlayerDropCardNotify(aplayer: PlayerHandler, count: number, from?: PlayerHandler): number{
return this._room.giveUpCard(aplayer.getId(), count, from? from.getId(): null);
};
public onSkillResultNotify(skillres: SkillTarget[]){
/**
* indexOfAttack
start: number: number*/
let __indexOfAttack = function(start: number): number {
for(let i = start; i < skillres.length;i++){
if(skillres[i].bresok && skillres[i].isAttackSkill()){
return i;
}
}
return -1;
};
let __indexOfAttackBk = function(start: number, atkres: SkillTarget): number{
for(let i = start; i < skillres.length;i++){
let obj = skillres[i];
if(obj.bresok && obj.isAttackBackSkill()
&& atkres.dst == obj.srcPet() && obj.dst == atkres.srcPet()){
return i;
}
}
return -1;
};
if(!skillres || skillres.length <= 0){
return;
}
// 合并冲锋/反击
let nstart = 0;
while(true){
if(nstart >= skillres.length){
break;
}
let natk = __indexOfAttack(nstart);
if(natk < 0){
break;
}
nstart = natk + 1;
let atkobj = skillres[natk];
let natkbk = __indexOfAttackBk(nstart, atkobj);
if(natkbk){
let atkbkobj = skillres[natkbk];
atkbkobj.res && atkbkobj.res.forEach((item: SkillResult) => {
if(item.bsuccess){
if(item.effect_type == SkillEffectType.CHG_AP || item.effect_type == SkillEffectType.CHG_HP){
atkobj.success(item.effect_type, item.effect_res, true);
}
}
});
skillres.splice(natkbk, 1);
}
}
let checklst: PlayerHandler[] = [];
let lst: SkillInfoMsg[] = [];
let resmap: Map<string, SkillTarget[]> = new Map;
let lastkey = '';
let cnt = 0;
skillres.forEach((item: SkillTarget)=>{
let key = item.srcskillid + '|' + item.srcplayer.getId();
if(item.srcpet){
key += '|' + item.srcpet._idx;
}
if(lastkey != key && lastkey != ''){
cnt++;
}
lastkey = key;
let realkey = key + '|' + cnt;
let tmplst = resmap.get(realkey);
if(!tmplst){
tmplst = [item];
resmap.set(realkey, tmplst);
}else{
tmplst.push(item);
}
});
let skid = '';
let tm = 0;
resmap.forEach((item: SkillTarget[]) =>{
let st = item[0];
lst.push(st.exportMsg(item));
tm += st.getLastTime();
skid += st.srcskillid + '|';
// st.isHurtSkill() && item.forEach((v: SkillTarget)=>{
// if(v.targetIsPet()){
// let ph = v.targetPlayer();
// if(!checklst.includes(ph)){
// checklst.push(ph);
// }
// }
// })
});
if(this.isFlowing()){
this._sktime += tm;
}else{
this._room.addScheduleTime(tm*1000, skid);
}
this._room.bMsgQueue(lst);
// checklst.forEach((item: PlayerHandler) => {
// item.checkPets();
// });
};
public onPlayerAddHPNotify(aplayer: PlayerHandler, addhp: number, from: PlayerHandler){
return this._room.updateHp(aplayer.getId(), addhp, from? from.getId(): null);
};
//end------------------------------------------------
public onSkillResult(skillres: SkillTarget[]){
if(this.isFlowing()){ //已处理过
// this._cacheSkills.push(...skillres);
}else{
this.onSkillResultNotify(skillres);
}
}
}