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, SkillRangeUnitType } from "../skill/SkillConst"; import { Pet } from "rooms/schema/Pet"; import {SkillParam, SkillTarget} from "../skill/SkillParam"; import { 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"; export class BattleHandler { private _cs: CardGameState; private _players: Map = new Map(); _room: Room; private _cardusing: boolean; private _sktime: number; private _gamestart: boolean = false; public init(cs: CardGameState, room: Room){ this._cs = cs; this._room = room; this._gamestart = false; }; 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); return ph; }; public delPlayer(aplayer: Player){ let ph = this.getPlayer(aplayer); this._players.forEach((item: PlayerHandler) =>{ if(item._friend == ph){ item._friend = null; } }); this._players.delete(aplayer); }; 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){ 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[], apet: PetHandler, expet: PetHandler, ct: GameUnitType, checktaunt: boolean=false): PetHandler { let pet = apet; let bok = false; switch(ut){ case SkillRangeUnitType.RANDOM_ONE: if(checktaunt){ let lst:PetHandler[] = []; players.forEach((item:PlayerHandler)=>{ item.findAllTauntPets(lst); }); if(lst.length > 0){ pet = arrUtil.randomOne(lst); bok = true; } } if(!bok){ let lst:PetHandler[] = []; players.forEach((item:PlayerHandler)=>{ item.findAllPets(lst); }); if(lst.length > 0){ pet = arrUtil.randomOne(lst); bok = true; } } break; case SkillRangeUnitType.RANDOM_ONE_EXSELF: if(checktaunt){ let lst:PetHandler[] = []; players.forEach((item:PlayerHandler)=>{ item.findAllTauntPets(lst, expet); }); if(lst.length > 0){ pet = arrUtil.randomOne(lst); bok = true; } } if(!bok){ let lst:PetHandler[] = []; players.forEach((item:PlayerHandler)=>{ item.findAllPets(lst, expet); }); 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 getSkillTargets(skill: Skill, param: SkillParam): SkillTarget[]{ let lst: SkillTarget[] = []; let players = this.getTargetPlayers(skill._data.friendlyid, param.srcplayer, param.dstplayer); if(players.length > 0){ switch(skill._data.targetid){ case GameUnitType.PLAYER: players.forEach((item:PlayerHandler)=>{ lst.push(new SkillTarget(skill, param.srcplayer, param.srcpet, item, GameUnitType.PLAYER)); }); break; case GameUnitType.HERO: players.forEach((item:PlayerHandler)=>{ lst.push(new SkillTarget(skill, param.srcplayer, param.srcpet, item._self, GameUnitType.HERO)); }); break; case GameUnitType.BATTLEUNIT: case GameUnitType.PET: if(skill.isSingleTarget()){ let pet = this.getFinalTarget(skill._data.rangeid, players, param.dstpet, param.srcpet, skill._data.targetid, skill.isHurtPowerSkill()); pet && lst.push(new SkillTarget(skill, param.srcplayer, param.srcpet, pet, pet._isHero? GameUnitType.HERO: GameUnitType.PET)); }else{ if(skill.isAllTarget()){ players.forEach((item: PlayerHandler)=>{ item.exportAllPets(skill, param, null, lst); }); }else{ if(param.srcpet){ players.forEach((item: PlayerHandler)=>{ item.exportAllPets(skill, param, param.srcpet, lst); }); }else{ players.forEach((item: PlayerHandler)=>{ if(item != param.srcplayer){ item.exportAllPets(skill, param, param.srcpet, lst); } }); } } } break; default: break; } } return lst; }; public getTargetPlayers(gct: GameCampType, src:PlayerHandler, dst:PlayerHandler): PlayerHandler[]{ let lst: PlayerHandler[] = []; switch(gct){ case GameCampType.SELF: 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 != src._friend && obj.isAlive()){ lst.push(obj); } } break; case GameCampType.ALL: 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 != src._friend && obj.isAlive()){ tmp.push(obj); } } 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){ lst.push(ph); bfind = true; } } if(!bfind){ return this.getTargetPlayers(GameCampType.RANDOM_ENEMY, src, dst); } } break; default: break; } return lst; }; public beginUseCard(){ this._cardusing = true; this._sktime = 0; }; public endUseCard(){ this._cardusing = false; }; public isUsingCard(){ return this._cardusing; }; //--------------------对外接口(外部调用)---------------------------- /** * 使用卡片 * @param obj */ public useCard(obj: {srcplayer: Player, card: number, cardpoint: number, dbpt_cnt: number, eff_cnt: number, dstplayer: Player, dstpet: Pet}) :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.beginUseCard(); 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); this.onUseCardEnd(ps); this.endUseCard(); return this._sktime*1000; }; /** * 使用技能 * @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 aplayer : 玩家 * @param fromplayer : 吃别人的牌,自己胡牌时此参数传空 */ public onCardLinkReady(aplayer: Player, fromplayer?: Player){ let ph = this.getPlayer(aplayer); let fromph = this.getPlayer(fromplayer); ph && ph.onCardLinkReady(fromph); }; /** * 吃牌/胡牌结束 * @param aplayer :玩家 * @param linkcards :吃到的牌组信息 */ public onCardLinkOver(aplayer: Player, linkcards: Card[], fromplayer?: Player){ let ph = this.getPlayer(aplayer); let fromph = this.getPlayer(fromplayer); ph && ph.onCardLinkEnd(linkcards, fromph); }; /** * 出牌结束(出单张牌) * @param aplayer : 玩家 * @param card : 单张牌 */ public onCardDiscarded(aplayer: Player, card: Card){ let ph = this.getPlayer(aplayer); ph && ph.onCardDiscarded(card); }; /** * 使用卡牌结束(暂时自动回调,无需外部触发) * @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); ph && ph.onCardDroped(dropcards, fromph); }; /** * 获取牌完成 * @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); ph && ph.onCardGetted(getcards, fromph); }; /** * 玩家回合开始 * @param aplayer */ public onPlayerRoundStart(aplayer: Player){ if(!this._gamestart){ this._gamestart = true; } let ph = this.getPlayer(aplayer); ph && ph.onRoundStart(); }; /** * 玩家回合结束 * @param aplayer */ public onPlayerRoundEnd(aplayer: Player){ let ph = this.getPlayer(aplayer); ph && ph.onRoundEnd(); }; /** * 玩家死亡 * @param aplayer */ public onPlayerDead(aplayer: Player){ let ph = this.getPlayer(aplayer); ph && ph.die(); this.delPlayer(aplayer); }; // end-------------------------------------------------- // --------------------调用外部接口函数-------------------------- public onAddPetNotify(apet: PetHandler){ return this._room.bAddPet(apet.exportInfoMsg()); }; public onDelPetNotify(apet: PetHandler){ return this._room.bRemovePet(apet.exportRemoveMsg()); }; public onUpdatePetNotify(apet: PetHandler){ return this._room.updatePet([apet.exportInfo()]); }; public onUpdatePetsNotify(pets: PetHandler[]){ if(!pets || pets.length <= 0){ return; } let lst: PetInfo[] = []; pets.forEach((item: PetHandler)=>{ lst.push(item.exportInfo()); }); return this._room.updatePet(lst); }; 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 onSkillResultNotify(skillres: SkillTarget[]){ if(!skillres || skillres.length <= 0){ return; } let lst: SkillInfoMsg[] = []; let difflst: SkillTarget[] = []; skillres.forEach((item: SkillTarget)=>{ lst.push(item.exportData()); if(!difflst.includes(item)){ difflst.push(item); } }); let skid = ''; let tm = 0; difflst.forEach((item: SkillTarget) =>{ tm += item.getLastTime(); skid += item.srcskillid + '|'; }); if(this.isUsingCard()){ this._sktime += tm; }else{ this._room.addScheduleTime(tm*1000, skid); } this._room.bMsgQueue(lst); }; public onPlayerAddHPNotify(aplayer: PlayerHandler, addhp: number){ return this._room.updateHp(aplayer.getId(), addhp); } //end------------------------------------------------ }