1023 lines
32 KiB
TypeScript
1023 lines
32 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, 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);
|
||
}
|
||
}
|
||
}
|