HJ_Server/src/shared/fightControl/fightCntrol.ts
2023-12-14 20:42:22 +08:00

296 lines
9.5 KiB
TypeScript

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<Role> = {};
//所有战斗对象,包含了双方的“伙伴”和“主角”
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<any>) {
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
};
}
}