473 lines
14 KiB
TypeScript
473 lines
14 KiB
TypeScript
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 } 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 { SkillInfoMsg } from "message/SkillInfo";
|
||
import { PetInfo } from "message/PetInfo";
|
||
|
||
|
||
export class BattleHandler {
|
||
private _cs: CardGameState;
|
||
|
||
private _players: Map<Player, PlayerHandler> = 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(players: PlayerHandler[], apet: PetHandler, ct: GameUnitType,
|
||
checktaunt: boolean=false): PetHandler
|
||
{
|
||
let pet = apet;
|
||
let 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;
|
||
}
|
||
}
|
||
}
|
||
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(players, param.dstpet, 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;
|
||
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 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------------------------------------------------
|
||
}
|