import { getAtkTarget } from "./atkTarget"; import { getSkillConf, randNumber } from "./fightFun"; import { FightObj, fightResult, joinFightData, recordDataType, roleDataType } from "./fightType"; import { Player } from "./Player"; import { Role } from "./Role"; export class FightControl { startTime: number = Date.now(); //所有战斗成员,包含双方的所有“伙伴” fightRoles: k_v = {}; //所有战斗对象,包含了双方的“伙伴”和“主角” fightRolesArr: FightObj[] = []; fightOver = false; roundNums = 0; recordData: recordDataType[] = []; event = new G.getEvent(999); // event = new myEventEmitter(); initial: joinFightData[]; winSide: number; totalDamage = { "0": 0, "1": 0 }; //战斗统计 fightStatistics: { [k: string]: { [k: string]: number; }; } = {}; player_0: FightObj = null; player_1: FightObj = null; recordSkillDps: { [key: string]: number } = {}; constructor(public DATA: joinFightData[], public maxRoundNums: number = 30, public fightType: 'pvp' | 'pve' = 'pve') { this.initial = JSON.parse(JSON.stringify(DATA)); this.initControl(); this.addFightObj(); this.startTurnRound(); } /** * 释放内存资源 */ release(){ this.fightRolesArr.map( obj =>{ obj?.release(); }); this.fightRoles = null; this.fightRolesArr = null; this.recordData = null; this.event.removeAllListeners(); this.event = null; this.initial = null; this.fightStatistics = null; this.player_0 = null; this.player_1 = null; this.recordSkillDps = null; this.DATA = null; } initControl() { // this.event.setMaxListeners(1000); } addFightObj() { for (let side = 0; side < this.DATA.length; side++) { this.DATA[side].player.side = side.toString(); this.DATA[side].player.pos = 7; let _data = this.DATA[side]; let _joindataRole = _data.roles; for (let key in _joindataRole) { let d = _joindataRole[key]; d.pos = key; d.side = side.toString(); this.addRole(_joindataRole[key]); } this.addPlyer(_data.player); }; } addRole(data: roleDataType) { if (data.attr.hp <= 0) return; let role = new Role(this, data); this.fightRoles[role.rid] = role; this.fightRolesArr.push(role); } addPlyer(data: joinFightData['player']) { let player = new Player(this, data); this.fightRolesArr.push(player); this['player_' + data.side] = player; } /** * 战斗循环 */ startTurnRound() { while (!this.fightOver) { this._tunrRound(); } } /** * 每轮次战斗具体实现 */ _tunrRound() { if (this.roundNums == 0) this.beforeSkill(); this.roundNums += 1; this.record({ act: 'trun', roundNums: this.roundNums }); this.event.emit('fightEvent_roundNums', { "turn": this.roundNums }); this.fightRolesArr.sort((a, b) => { let aSeep = a.getData('speed') * (1 + a.getDataPro('speed')); let bSeep = b.getData('speed') * (1 + b.getDataPro('speed')); if (aSeep != bSeep) { return bSeep - aSeep; } else { return parseInt(a.roleData.side) - parseInt(b.roleData.side) } }); // if(G.config.debug) console.log(this.roundNums) this.fightRolesArr.map(role => role.addpkNum = 0); for (var i = 0; i < this.fightRolesArr.length; i++) { this.checkEnd(); if (this.fightOver) break; let role = this.fightRolesArr[i]; if (role.isDead || !role.isHasFightSkills) continue; this.record({ act: 'startAct', fromRole: role.rid }); role.atk(); this.record({ act: 'stopAct', fromRole: role.rid }); //判断是否能两次行动 if (this.atkAgain(role)) { i--; } if (role.hasbuff("addpk") && role.addpkNum == 0) { i--; role.clearBuff("addpk"); role.addpkNum += 1 } } this.checkEnd(); } atkAgain(role: FightObj) { let rid = role.rid; if (rid.indexOf('player') != -1) return false; let shiqi = role.getData('shiqi') * (1 + role.getDataPro('shiqi')); let randnum = 1 + shiqi / (shiqi + 100 + role.getData('lv') * 100); return randNumber() > randnum; } /** 战前技能检查 */ beforeSkill() { this.eachLiveRoles((role) => { let heroId = role.roleData.heroId; // let shiwu = role.roleData?.shiwu || {}; // let talent = role.roleData?.talent || {}; let skills = G.gc.heroskill[heroId][role.roleData.jieji || 0].bdskill || []; skills = skills.concat(role.roleData.attr.skillArr); // for (let key in shiwu) { // let zhushuan = shiwu[key]?.zhuanshu; // if (!zhushuan) continue; // if (zhushuan.skill) skills.push(zhushuan.skill); // }; // const hero_tf = G.gc.hero_tf; // for (let key in talent) { // let cdata = hero_tf[key][talent[key]]; // if (cdata && cdata.skill_effect) skills.push(cdata.skill_effect); // } // skills.push('tx06309'); // if (!skills) return; skills.forEach(_skill => { let askillconf = getSkillConf(_skill); if (!askillconf) return console.log('没有技能配置-->', _skill); let randnum = askillconf.randnum; if (randnum == '' || randNumber() > randnum) return; let targets = getAtkTarget(role.fightControl, role , askillconf); targets.forEach(_target => { _target.runAfterSkill({ fromRole: role, toRole: _target, fromSkill: null, skillConf: askillconf, targetCount: targets.length }, 'beforeSkill'); }); }); }); } checkEnd() { if (this.fightOver) return; if (this.roundNums > this.maxRoundNums) this.fightOver = true; let side0Arr = [], side1Arr = []; this.eachLiveRoles((role) => { if (role.roleData.side == '0') { side0Arr.push(role); } else { side1Arr.push(role); } }); if (side0Arr.length == 0 || side1Arr.length == 0) { this.fightOver = true; } if (this.fightOver) this.stopFight(side0Arr, side1Arr); } stopFight(side0Arr: Role[], side1Arr: Role[]) { /* 获胜条件判断: 数量相同,人数多的获胜 人数一致,战力低的获胜 战力一直, 随机获胜 */ let winside = 0; if (this.fightType == "pve") { winside = side1Arr.length != 0 ? 1 : 0; } else { let power0 = this.DATA[0].player.power, power1 = this.DATA[1].player.power; if (side0Arr.length > side1Arr.length) { winside = 0; } else if (side0Arr.length < side1Arr.length) { winside = 1; } else if (power0 < power1) { winside = 0; } else if (power0 > power1) { winside = 1; } else { winside = [0, 1].random(); } } this.winSide = winside as 1 | 0; this.record({ act: 'fightEnd', winSide: this.winSide }); this.event.removeAllListeners() } eachLiveRoles(callback: (role: Role) => void) { for (let rid in this.fightRoles) { // if (this.fightOver) return; if (!this.fightRoles[rid]) continue; // 排除死亡 if (this.fightRoles[rid].isDead) continue; callback && callback(this.fightRoles[rid]); } } eachDeadRoles(callback: (role: Role) => void) { for (let rid in this.fightRoles) { if (this.fightOver) return; if (!this.fightRoles[rid]) continue; if (!this.fightRoles[rid].isDead) continue; callback && callback(this.fightRoles[rid]); } } record(data: recordDataType) { this.recordData.push(data); } getRecordIdx() { return this.recordData.length - 1; } fixRecordByIdx(idx: number, data: k_v) { this.recordData[idx] = Object.assign(this.recordData[idx], data); // this.recordData[idx].targets = targets; } recordStatistics(role: FightObj, key: 'hit' | 'def', val: number) { if (!this.fightStatistics[role.rid]) this.fightStatistics[role.rid] = {}; if (!this.fightStatistics[role.rid][key]) this.fightStatistics[role.rid][key] = 0; this.fightStatistics[role.rid][key] += val; } debug(callback: () => void) { // callback(); } getResult(): fightResult { return { winSide: this.winSide, fightLog: this.recordData, initData: this.initial, fightData: this.DATA, totalDamage: this.totalDamage, fightStatistics: this.fightStatistics }; } }