348 lines
14 KiB
TypeScript
348 lines
14 KiB
TypeScript
/**
|
||
* 体力系统
|
||
*/
|
||
|
||
import { HERO_SYSTEM_TYPE, ABI_TYPE } from '../consts';
|
||
|
||
import { deepCopy } from './util';
|
||
import { HeroModel, HeroType } from '../db/Hero';
|
||
import { RoleModel } from '../db/Role';
|
||
import { CeAttrData, CeAttr } from '../db/generalField';
|
||
import { getAttrNameByJobStage, getAttrCeRatio, getAtrrNameById, ABI_TYPE_TO_STAGE, ABI_STAGE, SEID_TYPE, HERO_ATTR} from '../consts';
|
||
import { gameData, getJobByGradeAndClass, getHeroWakeByQuality, getHeroStarByQuality, getFriendShipById } from './data';
|
||
import { Attributes } from './interface';
|
||
import { DicSe } from './dictionary/DicSe';
|
||
import { EquipType } from '../db/Equip';
|
||
|
||
const HERO_CE_RATIO = 100;
|
||
const _ = require('underscore');
|
||
//战力计算TODO
|
||
export function calPlayerCe(hero: HeroType, type: number, args: Array<number>) {
|
||
let incCe = 0;
|
||
let incArr: Attributes = {};
|
||
let reIncAttr: CeAttr = {}; // {"hp": {"base": number, "fixUp": number, "ratioUp": number}}
|
||
|
||
let addSeidList = new Array<number>();
|
||
let removeSeidList = new Array<number>();
|
||
|
||
if (type == HERO_SYSTEM_TYPE.STAR) {
|
||
reIncAttr = calHeroStarIncAttr(hero, args, addSeidList); // args: 升的星盘
|
||
} else if (type == HERO_SYSTEM_TYPE.TRAIN) {
|
||
reIncAttr = calHeroTrainIncAttr(hero);
|
||
} else if (type == HERO_SYSTEM_TYPE.STAGEUP) {
|
||
reIncAttr = calHeroJobStageUpIncAttr(hero, args, addSeidList, removeSeidList )
|
||
} else if (type == HERO_SYSTEM_TYPE.SKIN) {
|
||
reIncAttr = calWaerHeroSkinIncAttr(hero, args);
|
||
} else if (type == HERO_SYSTEM_TYPE.FAVOUR) {
|
||
reIncAttr = calHeroFavourUpIncAttr(hero, args);
|
||
} else if (type == HERO_SYSTEM_TYPE.CONNECT) {
|
||
reIncAttr = calHeroConectIncAttr(hero, args);
|
||
} else if (type == HERO_SYSTEM_TYPE.EQUIP) {
|
||
reIncAttr = calHeroEquipIncAttr(hero);
|
||
}
|
||
|
||
addSeidEffect(reIncAttr, addSeidList, removeSeidList); // 处理加值
|
||
if(!hero.ceAttr) hero.ceAttr = new CeAttr();
|
||
for (let attrName in reIncAttr) {
|
||
let originalAttrData: CeAttrData = hero.ceAttr[attrName]||new CeAttrData();
|
||
let oldCe = (originalAttrData.fixUp + originalAttrData.equipUp||0) * HERO_CE_RATIO + originalAttrData.base *(HERO_CE_RATIO + originalAttrData.ratioUp);
|
||
if(!hero.ceAttr[attrName]) hero.ceAttr[attrName] = new CeAttrData();
|
||
for (let attrKey in reIncAttr[attrName]) {
|
||
hero.ceAttr[attrName][attrKey] = parseInt(reIncAttr[attrName][attrKey]||0);
|
||
}
|
||
incArr[attrName] = (reIncAttr[attrName].fixUp + reIncAttr[attrName].equipUp||0) * HERO_CE_RATIO + reIncAttr[attrName].base *(HERO_CE_RATIO + reIncAttr[attrName].ratioUp) - oldCe; //计算属性
|
||
incCe += incArr[attrName] * getAttrCeRatio(attrName);
|
||
}
|
||
hero.ce += incCe;
|
||
return incCe;
|
||
}
|
||
|
||
//修改并下发战力
|
||
export async function calPlayerCeAndSave(roleId: string, heros: Array<HeroType>, type?: number, args?: Array<number>) {
|
||
let incPlayerCe = 0;
|
||
let pushHeros = new Array<{hid: number, ce: number, incHeroCe: number}>();
|
||
|
||
for (let hero of heros) {
|
||
let incHeroCe = calPlayerCe(hero, type, args);
|
||
incPlayerCe += incHeroCe;
|
||
|
||
await HeroModel.updateHeroInfo(roleId, hero.hid, hero );
|
||
pushHeros.push({
|
||
hid: hero.hid,
|
||
ce: hero.ce,
|
||
incHeroCe : incHeroCe,
|
||
});
|
||
}
|
||
let role = await RoleModel.findByRoleId(roleId);
|
||
role.ce += incPlayerCe;
|
||
await RoleModel.updateRoleInfo(roleId, role);
|
||
return {pushHeros, role}
|
||
}
|
||
|
||
export function calHeroStarIncAttr (hero: HeroType, args: Array<number>, addSeidList: Array<number>) {
|
||
let {star, starStage, quality, colorStar, colorStarStage, ceAttr} = hero;
|
||
let res: CeAttr = {};
|
||
const dicHero = gameData.hero.get(hero.hid);
|
||
|
||
const isWake = colorStar > 0; // 是否觉醒,只要激活了觉醒,彩星就会 > 1
|
||
if(isWake) {
|
||
if(colorStarStage == ABI_STAGE.START) colorStar = colorStar -1;
|
||
} else {
|
||
if(starStage == ABI_STAGE.START) star = star -1;
|
||
}
|
||
const dicStar = isWake? getHeroWakeByQuality(quality, colorStar): getHeroStarByQuality(quality, star); // 星级表
|
||
|
||
for(let stage of args) {
|
||
|
||
let targetAttrId = getFieldByStage(stage, hero.job); // 转换为17维的属性id
|
||
let heroAttr = dicHero.baseAbilityArr.get(targetAttrId); // 武将表hp等
|
||
let heroUpAttr = dicHero.baseAbilityUpArr.get(targetAttrId); // 武将表hp_up等
|
||
|
||
let starUp = dicStar.ceAttr.get(stage);
|
||
let newBase = (heroAttr + hero.lv * (heroUpAttr + starUp)) * HERO_CE_RATIO;
|
||
let field = getAtrrNameById(targetAttrId);
|
||
let ceAttrData: CeAttrData = ceAttr[field]||new CeAttrData(); // 存表中的属性下的base,fixup,ratioup
|
||
let {ratioUp = 0, fixUp = 0} = ceAttrData;
|
||
res[field] = { base: newBase, ratioUp, fixUp}; // base变动,增量为△base * ratio + 0
|
||
}
|
||
|
||
// 解锁技能
|
||
if(dicHero.skill){
|
||
let {starSeidArr, colorStarSeidArr} = gameData.heroSkill.get(dicHero.skill);
|
||
if(isWake) {
|
||
for(let {star, value} of starSeidArr){
|
||
if(hero.star == star){
|
||
addSeidList.push(value);
|
||
}
|
||
}
|
||
} else {
|
||
for(let {star, value} of colorStarSeidArr){
|
||
if(hero.colorStar == star){
|
||
addSeidList.push(value);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return res;//属性增量可以是多个
|
||
}
|
||
|
||
export function getAllAttrStage () {
|
||
let attrs = new Array<number>(); // 有升级的属性 1-hp 2-atk 3-def 4-mdef 5-agi 6-luk
|
||
for(let stage = ABI_STAGE.START + 1; stage <= ABI_STAGE.END; stage++) {
|
||
attrs.push(stage)
|
||
};
|
||
return attrs;
|
||
}
|
||
//训练
|
||
export function calHeroTrainIncAttr(hero: HeroType) {
|
||
let res: CeAttr = {};
|
||
let attrName: string = getAttrNameByJobStage(hero.jobStage);
|
||
res[attrName] = {fixUp: hero.ceAttr[attrName].fixUp, base: hero.ceAttr[attrName].base, ratioUp: hero.ceAttr[attrName].ratioUp};
|
||
let currentJob = gameData.job.get(hero.job);
|
||
if (currentJob.grade > 1) {
|
||
let jobGradeAndClass = getJobByGradeAndClass(currentJob.job_class, currentJob.grade - 1);
|
||
let lastJob = gameData.job.get(jobGradeAndClass.jobid);
|
||
res[attrName].fixUp += (currentJob[attrName] - lastJob[attrName]) * HERO_CE_RATIO;
|
||
} else {
|
||
res[attrName].fixUp += currentJob[attrName] * HERO_CE_RATIO;
|
||
}
|
||
return res;
|
||
}
|
||
//进阶
|
||
export function calHeroJobStageUpIncAttr(hero: HeroType, args: Array<number>, addSeidList: Array<number>, removeSeidList: Array<number> ) {
|
||
let res: CeAttr = {};
|
||
let lastJob = gameData.job.get(args[0]);
|
||
let currentJob = gameData.job.get(hero.job);
|
||
addSeidList.concat(deepCopy(currentJob.seid));
|
||
for (let seid of lastJob.seid) {
|
||
let index = _.findIndex(currentJob.seid, seid);
|
||
if (index > 0) {
|
||
addSeidList.splice(index, 1);
|
||
} else {
|
||
removeSeidList.push(seid);
|
||
}
|
||
}
|
||
return res;
|
||
}
|
||
//穿戴时装
|
||
export function calWaerHeroSkinIncAttr(hero: HeroType, args: Array<number>) {
|
||
let res: CeAttr = {};
|
||
let addSkin = gameData.fashion.get(args[0]);
|
||
let delSkin = gameData.fashion.get(args[1]);
|
||
let attrName: string;
|
||
for (let attr of delSkin.actorAttr) {
|
||
attrName = getAtrrNameById(attr.id);
|
||
res[attrName] = {fixUp: hero.ceAttr[attrName].fixUp, base: hero.ceAttr[attrName].base, ratioUp: hero.ceAttr[attrName].ratioUp};
|
||
res[attrName].fixUp += attr.number * HERO_CE_RATIO;
|
||
}
|
||
for (let attr of addSkin.actorAttr) {
|
||
attrName = getAtrrNameById(attr.id);
|
||
res[attrName] = {fixUp: hero.ceAttr[attrName].fixUp, base: hero.ceAttr[attrName].base, ratioUp: hero.ceAttr[attrName].ratioUp};
|
||
res[attrName].fixUp -= attr.number * HERO_CE_RATIO;
|
||
}
|
||
return res;
|
||
}
|
||
|
||
//羁绊解锁
|
||
export function calHeroConectIncAttr(hero: HeroType, args: Array<number>) {
|
||
let res: CeAttr = {};
|
||
let fiendShipLevel = gameData.friendShipLevelMap.get(hero.favourLv);
|
||
let shipId = args[0];//当前升级的羁绊序号
|
||
let level = args[1];//当前升级的羁绊等级
|
||
let attrName: string;
|
||
let currentShip = getFriendShipById(shipId, level);
|
||
for (let attr of currentShip.attributes) {
|
||
attrName = getAtrrNameById(attr.id);
|
||
res[attrName] = {fixUp: hero.ceAttr[attrName].fixUp, base: hero.ceAttr[attrName].base, ratioUp: hero.ceAttr[attrName].ratioUp};
|
||
res[attrName].fixUp += attr.number * (HERO_CE_RATIO + fiendShipLevel.add);
|
||
}
|
||
if (level > 1) {
|
||
let lastShip = getFriendShipById(shipId, level - 1);
|
||
for (let attr of lastShip.attributes) {
|
||
attrName = getAtrrNameById(attr.id);
|
||
res[attrName] = {fixUp: hero.ceAttr[attrName].fixUp, base: hero.ceAttr[attrName].base, ratioUp: hero.ceAttr[attrName].ratioUp};
|
||
res[attrName].fixUp -= attr.number * (HERO_CE_RATIO + fiendShipLevel.add);
|
||
}
|
||
}
|
||
return res;
|
||
}
|
||
|
||
//好感升级
|
||
export function calHeroFavourUpIncAttr(hero: HeroType, args: Array<number>) {
|
||
let res: CeAttr = {};
|
||
let currentFiendShipLevel = gameData.friendShipLevelMap.get(hero.favourLv);
|
||
let difAdd = currentFiendShipLevel.add;
|
||
if (!!args[0]) {
|
||
let lastFiendShipLevel = gameData.friendShipLevelMap.get(args[0]);
|
||
difAdd -= lastFiendShipLevel.add;
|
||
}
|
||
let attrName: string;
|
||
for (let connect of hero.connections) {
|
||
let heroShip = getFriendShipById(connect.shipId, connect.level);
|
||
for (let attr of heroShip.attributes) {
|
||
attrName = getAtrrNameById(attr.id);
|
||
res[attrName] = {fixUp: hero.ceAttr[attrName].fixUp, base: hero.ceAttr[attrName].base, ratioUp: hero.ceAttr[attrName].ratioUp};
|
||
res[attrName].fixUp += attr.number * (HERO_CE_RATIO + difAdd);
|
||
}
|
||
}
|
||
return res;
|
||
}
|
||
|
||
export function calHeroEquipIncAttr(hero: HeroType) {
|
||
let res: CeAttr = {};
|
||
let {ePlace} = hero;
|
||
|
||
for(let {equip, lv, refineLv} of ePlace) {
|
||
if(equip) {
|
||
let e = <EquipType>equip;
|
||
let dicGoods = gameData.goods.get(e.id);
|
||
let {goodsAbility, goodsAbilityUp} = dicGoods;
|
||
let dicRefine = gameData.refine.get(refineLv);
|
||
|
||
let jewel = new Map<number, number>();
|
||
for(let {jewel: jewelId} of e.holes) {
|
||
if(jewelId > 0) {
|
||
let g = gameData.goods.get(jewelId);
|
||
if(g) {
|
||
let jGoods = g.goodsAbility;
|
||
jGoods.forEach((value, key) => {
|
||
if(jewel.has(key)) {
|
||
jewel.set(key, value);
|
||
} else {
|
||
jewel.set(key, jewel.get(key) + value);
|
||
}
|
||
})
|
||
}
|
||
}
|
||
}
|
||
|
||
for(let i = ABI_TYPE.ABI_HP; i < ABI_TYPE.ABI_MAX; i++) {
|
||
if(i == ABI_TYPE.ABI_SPEED || i == ABI_TYPE.ABI_AP) continue;
|
||
let attrName = getAtrrNameById(i);
|
||
// console.log('***', i, attrName);
|
||
let value1 = goodsAbility.get(i)||0 * (HERO_CE_RATIO + e.randRange);
|
||
// console.log('基础值', value1);
|
||
let valueup = goodsAbilityUp.get(i)||0;
|
||
// console.log('成长', lv, valueup);
|
||
let valueRefine = dicRefine?dicRefine.upPercent:0;
|
||
// console.log('refine', dicRefine?dicRefine.upPercent:0 );
|
||
let valueJewel = jewel.get(i)||0;
|
||
// console.log('jewel', valueJewel);
|
||
let attr = (value1 + lv * valueup) * ( HERO_CE_RATIO + valueRefine) + valueJewel * HERO_CE_RATIO;
|
||
|
||
|
||
let originalCe = hero.ceAttr[attrName].equipUp||0;
|
||
|
||
if(attr != originalCe) {
|
||
console.log('装备战力:', attr, originalCe);
|
||
|
||
res[attrName] = {fixUp: hero.ceAttr[attrName].fixUp, base: hero.ceAttr[attrName].base, ratioUp: hero.ceAttr[attrName].ratioUp, equipUp: originalCe};
|
||
console.log(attr, originalCe)
|
||
res[attrName].equipUp += attr * HERO_CE_RATIO - originalCe;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return res;
|
||
}
|
||
|
||
// 根据存在升星表等的stage字段的id对应17维id
|
||
function getFieldByStage(stage: number, jobid: number) {
|
||
let targetAttrId = ABI_TYPE_TO_STAGE.get(stage);
|
||
if(typeof targetAttrId === 'number') {
|
||
return targetAttrId
|
||
} else {
|
||
const dicJob = gameData.job.get(jobid);
|
||
return targetAttrId(dicJob.type);
|
||
}
|
||
}
|
||
|
||
|
||
// 添加技能增加的被动属性
|
||
function addSeidEffect(reIncAttr: CeAttr, addSeidList: Array<number>, removeSeidList: Array<number>) {
|
||
|
||
let otiginalSeidList = [
|
||
{list: addSeidList, multi: 1},
|
||
{list: removeSeidList, multi: -1}
|
||
];
|
||
for(let {list, multi} of otiginalSeidList) {
|
||
let effectList = new Array<DicSe>(); // any: dic_zyz_se表内容
|
||
for(let seid of list) {
|
||
let dicSeid = gameData.se.get(seid);
|
||
if(dicSeid && dicSeid.id > 0){
|
||
addSeid(effectList, dicSeid.id, dicSeid.gainValueArr)
|
||
}
|
||
}
|
||
|
||
for(let {type, gainValueArr: [ability, value]} of effectList) {
|
||
if(type == SEID_TYPE.TYPE101) { // 加值
|
||
if(!reIncAttr[HERO_ATTR[ability]]) {
|
||
reIncAttr[HERO_ATTR[ability]] = new CeAttrData();
|
||
}
|
||
reIncAttr[HERO_ATTR[ability]].fixUp += value * multi * HERO_CE_RATIO;
|
||
} else if (type == SEID_TYPE.TYPE102) { // 加百分比
|
||
if(!reIncAttr[HERO_ATTR[ability]]) {
|
||
reIncAttr[HERO_ATTR[ability]] = new CeAttrData();
|
||
}
|
||
reIncAttr[HERO_ATTR[ability]].ratioUp += value * multi;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 获取dic_zyz_se内容
|
||
function addSeid(effectList: Array<any>, seidId:number, seidValue = new Array<number>()){
|
||
// console.log('addSeidEffect', seidId, seidValue)
|
||
let curSeid = gameData.se.get(seidId);
|
||
if(!curSeid) {console.log("seidId not found:"+seidId);return;}
|
||
if(!seidValue) seidValue = curSeid.gainValueArr;
|
||
|
||
if(curSeid.type === 999){
|
||
for(let i = 0;i < seidValue.length;i++){
|
||
addSeid(effectList, seidValue[i]);
|
||
}
|
||
return;
|
||
}
|
||
effectList.push(curSeid);
|
||
} |