gamecloud
Version:
game logic server over cloud
274 lines (245 loc) • 9.23 kB
JavaScript
let {BattleBuffEnum, NotifyEnum, EmitType,OperationType,PeriodTypeEnum,AttackMode,ActionTypeEnum} = require('./enum')
let EventEmitter = require('events').EventEmitter; //事件管理
let BattleUser = require('./player');
let {ActionObject,ActionOfUserControl} = require('./Action');
let {OperationItem} = require('./util')
/**
* 战场管理类,负责战场初始化、战斗进程控制和计算、输出流式战斗指令序列
*/
class BattleRoom extends EventEmitter
{
/**
* 构造函数
*/
constructor(){
super();
//输出指令序列
this.OperationList = [];
//事务堆栈,按照先进后出原则执行
this.WorldTransActionList = [];
//上一个执行过的事务,包含一些执行状态以便查询
this.LastAction = null;
//功方
this.Attacker = null;
//守方
this.Defenser = null;
//行动令牌拥有者
this.Controler = null;
/**
* 事件句柄
*/
this.EventIndex = 0;
/**
* 全局的时间轴
*/
this.GlobalFrame = 0;
this.on(EmitType.Action, (...params)=>{
this.PushAction(params[0]);
});
}
lockFrame($idx){
if(this.GlobalFrame < $idx){
this.GlobalFrame = $idx;
}
return this;
}
/**
* 添加系统行为记录(开始、结束等)
* @param {*} $operType 记录类型
* @param {Object} $params 记录参数
* @return {int} 所创建记录的流水号
*/
record($operType, $params = {}){
let rec = new OperationItem($operType, $params);
rec.PreCondition = this.EventIndex;
rec.EventIndex = this.GetEventHandle();
this.OperationList.push(rec);
return rec.EventIndex;
}
/**
* 创建战场
* @param {Object} $me {player, id, lv, skill}
* @param {Object} $enemy {player, id, lv, skill}
* @return {BattleRoom}
*/
static CreateRoom($me, $enemy){
let $_battle = new BattleRoom();
$_battle.Attacker = new BattleUser($me, $_battle);
$_battle.Defenser = new BattleUser($enemy, $_battle);
return $_battle;
}
/**
* 根据分组信息,以及用户对象,构造英雄的技能列表
* @param {*} loc
* @param {*} user
*/
static getSkills(loc, user){
return loc.reduce((sofar, cur)=>{
let cfg = user.core.ConfigMgr.PetList()[cur];
if(cfg.profession == 0){ //法术卡,将其包含的技能填充到主角的技能列表中,等级取自法术卡自身的等级,受星级限制开放
//升星解锁新的技能
let $ev = user.getPotentialMgr().GetHero(cur).getEnLevel() || 1;
cfg.ActionList[$ev-1].map(it=>{
let fc = parseInt(it);
if(!sofar.find(fo=>fo[0]==fc)){//去重
sofar.push([fc, user.getPotentialMgr().GetHero(cur).getCardLevel()]);
}
});
}
else{//英雄卡,将其对应的召唤技追加到主角的技能列表中,所召唤英雄的等级取自英雄卡自身的等级
sofar.push([cfg.boot, user.getPotentialMgr().GetHero(cur).getCardLevel()]);
}
return sofar;
}, []);
}
/**
* 获取事件唯一句柄
*/
GetEventHandle(){
return ++this.EventIndex;
};
/**
* 计算生成并输出战斗指令序列
* @return {OperationItem[]}
*/
QuickBattle(){
if (this.Attacker == null || this.Defenser == null){
return [];
}
//为玩家颁发行动令牌(控方)
if (this.Attacker.Power >= this.Defenser.Power){
this.Controler = this.Attacker;
}
else{
this.Controler = this.Defenser;
}
//为控方英雄颁发行动令牌(拥有控牌权的英雄)
let $hi = this.Controler.NextHero(true);
if ($hi != null){
this.emit(EmitType.Action, new ActionOfUserControl($hi));
}
//记录开始指令
this.record(OperationType.Start, {me:this.Attacker.id, enemy:this.Defenser.id, a: this.Attacker.Power, b: this.Defenser.Power});
for (let $hi of this.Defenser.getTargetHeros(null, AttackMode.All)){
let $bid = $hi.lockFrame(this.GlobalFrame).record(OperationType.Enter, {value:$hi.Attributes});
//发动降临技,锁定到出生帧
$hi.lockBornFrame($bid).Notify(NotifyEnum.PeriodEnter, null);
};
for (let $hi of this.Attacker.getTargetHeros(null, AttackMode.All)){
let $bid = $hi.lockFrame(this.GlobalFrame).record(OperationType.Enter, {value:$hi.Attributes});
//发动降临技,锁定到出生帧
$hi.lockBornFrame($bid).Notify(NotifyEnum.PeriodEnter, null);
};
let recy = 0; //避免死循环
while (this.ActionCount > 0 && recy++ < 5000){
let $CurAction = this.PeekAction();
if ($CurAction.isEnd) { //当前事务执行完毕,准备出栈
this.LastAction = this.PopAction();
}
else{
$CurAction.Execute();
}
}
console.log(`本次战斗经历${recy}手,剩余事务${this.ActionCount}`);
//记录结束指令
this.lockFrame(this.GlobalFrame).record(OperationType.End, {victory:this.Attacker.TotalLife > this.Defenser.TotalLife, a:this.Attacker.TotalLife, b:this.Defenser.TotalLife});
return this.OperationList;
}
/**
* 寻找下一个控方
* @return {BattleUser}
*/
NextControl(){
if (this.Controler.enemy.CountVersion <= this.Controler.CountVersion){
//如果当前敌方回合数小于等于控方,则切换到敌方
this.Controler = this.Controler.enemy;
}
return this.Controler;
}
/**
* 战局是否有效
* @return {Boolean}
*/
isValid(){
return this.Attacker.TotalLife > 0 && this.Defenser.TotalLife > 0;
}
/**
* 攻方是否获胜
*/
get victory(){
return this.Attacker.TotalLife > 0;
}
/**
* 向堆栈顶部增加一个事务
* @param {ActionObject} $ao
*/
PushAction($ao){
if ($ao != null){
$ao.ParentAction = this.PeekAction(); //将当前栈顶事物设置为父节点
this.WorldTransActionList.push($ao);
//特殊事务入栈时,要执行一些特殊处理
switch($ao.type){
case ActionTypeEnum.PeriodOfUserControl:
this.Controler.CurrentPeriod = PeriodTypeEnum.PeriodOfUserControl;
break;
}
}
}
/**
* 从堆栈顶部弹出一个事务
* @return {ActionObject}
*/
PopAction(){
let ret = null;
if (this.WorldTransActionList.length > 0) {
ret = this.WorldTransActionList.pop();
ret.AfterExecute(); //后续操作
//特殊事务出栈时,要执行一些特殊处理
switch (ret.type) {
case ActionTypeEnum.PeriodOfUserControl:
if (this.isValid()) {
if(this.Controler.CurHero.checkBuff(BattleBuffEnum.WindFury)){//风怒 连续行动
this.Controler.CurHero.removeBuff(BattleBuffEnum.WindFury);
this.emit(EmitType.Action, new ActionOfUserControl(this.Controler.CurHero));
}
else{//下一位控制者进入自身回合
this.Controler.CurrentPeriod = PeriodTypeEnum.None; //当前控制者离开自身回合
let $hi = this.NextControl().NextHero(true);
if ($hi != null){
this.emit(EmitType.Action, new ActionOfUserControl($hi));
}
}
}
break;
default:
break;
}
}
return ret;
}
/// <summary>
/// 清空堆栈
/// </summary>
ClearAction(){
this.WorldTransActionList = [];
}
/**
* 获取栈顶事务对象(不出栈)
* @return {ActionObject}
*/
PeekAction(){
if (this.WorldTransActionList.length > 0){
return this.WorldTransActionList[this.WorldTransActionList.length-1];
}
else{
return null;
}
}
/**
* 返回事务记录数
*/
get ActionCount(){
return this.WorldTransActionList.length;
}
}
exports = module.exports = BattleRoom;