/** * 体力系统 */ import { HERO_SYSTEM_TYPE, ABI_TYPE, JEWEL_ATTR } from '../consts'; import { deepCopy, getAllAttrStage, reduceCe } from './util'; import { HeroModel, HeroType } from '../db/Hero'; import { RoleModel, RoleType } from '../db/Role'; import { CeAttrData, CeAttr, CeAttrRole, CeAttrNumber, CeAttrDataRole } from '../db/generalField'; import { getAttrNameByJobStage, getAttrCeRatio, getAtrrNameById, ABI_STAGE, SEID_TYPE } from '../consts'; import { gameData, getJobByGradeAndClass, getHeroWakeByQuality, getHeroStarByQuality, getFriendShipById, getSchoolRateByStar, getScollByStar, getFieldByStage } from './data'; import { DicSe } from './dictionary/DicSe'; import { EquipType } from '../db/Equip'; import { DicRandomEffectPool } from './dictionary/DicRandomEffectPool'; import { getGoodById } from './gamedata'; import { SchoolModel } from '../db/School'; import { getTeraphAttr, HEROTARIN } from '../consts/constModules/abilityConst' import { PvpDefenseModel } from '../db/PvpDefense'; const HERO_CE_RATIO = 100; const _ = require('underscore'); //战力计算TODO export function calPlayerCe(globalCeAttr: CeAttrRole, hero: HeroType, type: number, args: Array = []) { let heroCe = 0; let reIncAttr: CeAttr = {}; // {"hp": {"base": number, "fixUp": number, "ratioUp": number}} let addSeidList = new Array(); let removeSeidList = new Array(); switch (type) { case HERO_SYSTEM_TYPE.INIT: reIncAttr = calHeroInitIncAttr(hero, addSeidList, removeSeidList); // args: 升的星盘 break; case HERO_SYSTEM_TYPE.STAR: case HERO_SYSTEM_TYPE.LVUP: case HERO_SYSTEM_TYPE.COLORSTAR: case HERO_SYSTEM_TYPE.QUALITY: reIncAttr = calHeroStarIncAttr(hero, type, args.shift(), args, addSeidList, removeSeidList); // args: 升的星盘 break; case HERO_SYSTEM_TYPE.TRAIN: reIncAttr = calHeroTrainIncAttr(hero); break; case HERO_SYSTEM_TYPE.STAGEUP: reIncAttr = calHeroJobStageUpIncAttr(hero, args, addSeidList, removeSeidList); break; case HERO_SYSTEM_TYPE.SKIN: reIncAttr = calHeroWearSkinIncAttr(hero, args, addSeidList, removeSeidList); break; case HERO_SYSTEM_TYPE.FAVOUR: reIncAttr = calHeroFavourUpIncAttr(hero, args); break; case HERO_SYSTEM_TYPE.CONNECT: reIncAttr = calHeroConectIncAttr(hero, args); break; case HERO_SYSTEM_TYPE.EQUIP: reIncAttr = calEquipPutOnOffIncAttr(hero, args, addSeidList, removeSeidList); break; case HERO_SYSTEM_TYPE.EQUIP_BASE: reIncAttr = calHeroEquipIncAttr(hero); break; case HERO_SYSTEM_TYPE.RESTRENGTHEN: reIncAttr = calRestrengthenIncAttr(hero, args.shift(), args, addSeidList, removeSeidList); break; case HERO_SYSTEM_TYPE.JEWEL_ON: reIncAttr = calHeroCeWhenJewelOn(hero, args); break; case HERO_SYSTEM_TYPE.JEWEL_OFF: reIncAttr = calHeroCeWhenJewelOff(hero, args); break; case HERO_SYSTEM_TYPE.SCROLL: reIncAttr = calHeroCeScrollIncAttr(hero, args[0], args[1]); break; default: break; } addSeidEffect(reIncAttr, hero.ceAttr, addSeidList, removeSeidList); // 处理加值 if (!hero.ceAttr) hero.ceAttr = new CeAttr(); for (let attrName in hero.ceAttr) { if (attrName == '_id') continue; let globalAttrData: CeAttrDataRole = globalCeAttr[attrName] || new CeAttrDataRole(); if (!hero.ceAttr[attrName]) hero.ceAttr[attrName] = new CeAttrData(); if (!!reIncAttr[attrName]) { for (let attrKey in reIncAttr[attrName]) { hero.ceAttr[attrName][attrKey] = parseInt(reIncAttr[attrName][attrKey] || 0); } } let attrNumber = (hero.ceAttr[attrName].fixUp + (hero.ceAttr[attrName].equipUp || 0) + globalAttrData.fixUp) * HERO_CE_RATIO + hero.ceAttr[attrName].base * (HERO_CE_RATIO + hero.ceAttr[attrName].ratioUp + globalAttrData.ratioUp); // console.log(hero.hid, attrNumber, attrName, getAttrCeRatio(attrName)) heroCe += attrNumber * getAttrCeRatio(attrName); } let incCe = heroCe - hero.ce; hero.ce = heroCe > 0 ? heroCe : 1; if (hero.historyCe < hero.ce) hero.historyCe = hero.ce; return incCe; } //修改并下发战力 export async function calPlayerCeAndSave(roleId: string, heros: Array, type?: number, args?: Array) { if (!heros.length) heros = await HeroModel.findByRole(roleId); let incPlayerCe = 0; let pushHeros = new Array<{ hid: number, ce: number, incHeroCe: number }>(); let role = await RoleModel.findByRoleId(roleId); if (!role.globalCeAttr) role.globalCeAttr = new CeAttr(); await reCalRoleAttr(heros, role.globalCeAttr, type, args); for (let hero of heros) { let incHeroCe = calPlayerCe(role.globalCeAttr, hero, type, args); incPlayerCe += incHeroCe; await calculateTopFive(role, hero.hid, hero.ce); // 计算更新最强五人战力 await HeroModel.updateHeroInfo(roleId, hero.hid, hero); await PvpDefenseModel.updateCe(roleId, hero.hid, hero.ce); // 更新pvp防守阵最强五人战力 pushHeros.push({ hid: hero.hid, ce: reduceCe(hero.ce), incHeroCe: reduceCe(incHeroCe), }); } role.ce += incPlayerCe; let { topFive, topFiveCe } = role; await RoleModel.updateRoleInfo(roleId, { globalCeAttr: role.globalCeAttr, ce: role.ce, topFive, topFiveCe }); return { pushHeros, role, topFiveCe } } async function calculateTopFive(role: RoleType, hid: number, ce: number) { let topFive = role?.topFive || new Array(); topFive.sort((a, b) => { return b.ce - a.ce }); // 0-5,最大-最小 let index = topFive.findIndex(cur => cur.hid == hid); if (index == -1) { // 不在最强列表 if (topFive.length < 5) { // 不满5人 topFive.push({ hid, ce }); } else if (topFive.length == 5) { if (ce > topFive[topFive.length - 1].ce) { // 跻身最强5人 topFive.pop(); topFive.push({ hid, ce }); } } else { topFive.splice(5, topFive.length - 5); } } else { // 原来就是最强5人 if (ce < topFive[topFive.length - 1].ce) { // 滑出最强 let heroes = await HeroModel.getTopHero(role.roleId, 5); topFive = heroes.map(cur => { return { hid: cur.hid, ce: cur.ce } }); } else { topFive[index].ce = ce; } } let topFiveCe = topFive.reduce((pre, cur) => { return pre + cur.ce }, 0); role.topFive = topFive; role.topFiveCe = topFiveCe; return role; } // 初始战力 export function calHeroInitIncAttr(hero: HeroType, addSeidList: Array, removeSeidList: Array) { let res = calHeroStarIncAttr(hero, HERO_SYSTEM_TYPE.INIT, hero.hid, [], addSeidList, removeSeidList); let curSkin = hero.skins.find(cur => cur.enable); calHeroWearSkinIncAttr(hero, [curSkin ? curSkin.id : 0, 0], addSeidList, removeSeidList, true, res); calHeroJobAttr(hero, res, addSeidList, removeSeidList); return res; } export function calRoleInitIncAttr(heros: HeroType[], globalCeAttr: CeAttrRole) { let args = new Array(); for (let hero of heros) { for (let skin of hero.skins) { args.push(skin.id); } } let res = calHeroAddSkin(args, globalCeAttr); return res; } /** * * @param hero HeroType 武将更新后的值 * @param type number 类型 * @param hid number 当前武将id * @param args number[] 当升星时,一个参数,0-是否升了一星;当觉醒时,两个参数,0-是否升了一星,1-是否初次觉醒 * @param addSeidList number[] 用于更新被动 * @param removeSeidList number[] 用于更新被动 */ export function calHeroStarIncAttr(hero: HeroType, type: number, hid: number, args: number[], addSeidList: Array, removeSeidList: Array) { let isInit = type == HERO_SYSTEM_TYPE.INIT; let { star, starStage, quality, colorStar, colorStarStage, ceAttr, skins } = hero; let originStar = star, originColorStar = colorStar; let res: CeAttr = {}; if (hero.hid != hid) return res; const dicHero = gameData.hero.get(hero.hid); const isWake = colorStar > 0; // 是否觉醒,只要激活了觉醒,彩星就会 > 1 if (isWake) { if (colorStarStage == ABI_STAGE.START) originColorStar = colorStar - 1; } else { if (starStage == ABI_STAGE.START) originStar = star - 1; } const dicStar = isWake ? getHeroWakeByQuality(dicHero.quality, originColorStar) : getHeroStarByQuality(quality, originStar); // 星级表 let stages = new Array(); // 需要升级的阶 if (type == HERO_SYSTEM_TYPE.INIT) { stages = getAllAttrStage(); } else if (type == HERO_SYSTEM_TYPE.LVUP) { stages = getAllAttrStage(); } else if (type == HERO_SYSTEM_TYPE.STAR) { stages = [args[0] ? ABI_STAGE.END : starStage]; } else if (type == HERO_SYSTEM_TYPE.QUALITY) { stages = getAllAttrStage(); } else if (type = HERO_SYSTEM_TYPE.COLORSTAR) { if (args[1]) { // 首次觉醒 stages = getAllAttrStage(); } else { stages.push(args[0] ? ABI_STAGE.END : hero.colorStarStage) } } for (let stage of stages) { 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 = 0; if (!!dicStar && !!dicStar.ceAttr) { starUp = dicStar.ceAttr.get(stage); } let newBase = (heroAttr + (hero.lv - 1) * (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 } // 解锁技能 let curSkin = skins.find(cur => cur.enable); let curSeidList = getSeidListOfFashion(curSkin.id, star, colorStar); let preSeidList = getSeidListOfFashion(curSkin.id, isInit ? 0 : originStar, isInit ? 0 : originColorStar); for (let [type, seid] of curSeidList) { if (!preSeidList.has(type)) { addSeidList.push(seid, 0); } } for (let [type, seid] of preSeidList) { if (!curSeidList.has(type)) { removeSeidList.push(seid, 0); } } return res;//属性增量可以是多个 } function getSeidListOfFashion(fashionid: number, originStar: number, originColorStar: number) { let seidList = new Map(); // type => seid if (!gameData.fashion.has(fashionid)) return seidList; let { skillId } = gameData.fashion.get(fashionid); let { starSeidArr, colorStarSeidArr } = gameData.heroSkill.get(skillId); for (let { star, value, type } of starSeidArr) { if (originStar >= star) { seidList.set(type, value); } } for (let { star, value, type } of colorStarSeidArr) { if (originColorStar >= star) { seidList.set(type, value); } } return seidList } //训练 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, addSeidList: Array, removeSeidList: Array) { let res: CeAttr = {}; let lastJob = gameData.job.get(args[0]) || { seid: [] }; let currentJob = gameData.job.get(hero.job); for (let seid of currentJob.seid) { let index = _.findIndex(lastJob.seid, seid); if (index < 0) { addSeidList.push(seid, 0); } } for (let seid of lastJob.seid) { let index = _.findIndex(currentJob.seid, seid); if (index < 0) { removeSeidList.push(seid, 0); } } return res; } export function calHeroJobAttr(hero: HeroType, res: CeAttr, addSeidList: Array, removeSeidList: Array) { let currentJob = gameData.job.get(hero.job); let jobGradeAndClass = getJobByGradeAndClass(currentJob.job_class, currentJob.grade - 1); let lastJob; if (!!jobGradeAndClass) { lastJob = gameData.job.get(jobGradeAndClass.jobid); } for (let key in HEROTARIN) { let attrName: string = HEROTARIN[key]; res[attrName] = res[attrName] || { fixUp: hero.ceAttr[attrName].fixUp, base: hero.ceAttr[attrName].base, ratioUp: hero.ceAttr[attrName].ratioUp }; if (hero.jobStage >= parseInt(key)) { res[attrName].fixUp += currentJob[attrName] * HERO_CE_RATIO; } else { if (lastJob) res[attrName].fixUp += lastJob[attrName] * HERO_CE_RATIO; } } calHeroJobStageUpIncAttr(hero, [0], addSeidList, removeSeidList); return res; } //穿戴时装 export function calHeroWearSkinIncAttr(hero: HeroType, args: Array, addSeidList: Array, removeSeidList: Array, isInit = false, heroAttr?: CeAttr) { let res: CeAttr = heroAttr || {}; let addSkin = gameData.fashion.get(args[0]); let delSkin = gameData.fashion.get(args[1]); let attrName: string; if (delSkin) { for (let attr of delSkin.actorAttr) { attrName = getAtrrNameById(attr.id); res[attrName] = 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] = 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; } if (!isInit) { // 初始的时候,这一段技能在calHeroStarIncAttr里计算了,不用重复算 let { star, colorStar } = hero; let curSeidList = getSeidListOfFashion(args[0], star, colorStar); let preSeidList = getSeidListOfFashion(args[1], star, colorStar); for (let [type, seid] of curSeidList) { if (!preSeidList.has(type)) { removeSeidList.push(seid, 0); } } for (let [type, seid] of preSeidList) { if (!curSeidList.has(type)) { addSeidList.push(seid, 0); } } } return res; } //羁绊解锁 export function calHeroConectIncAttr(hero: HeroType, args: Array) { 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) { 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; } // 穿脱, removeSeidList原来身上穿着的所有装备的seid,包括套装的 export function calEquipPutOnOffIncAttr(hero: HeroType, args: Array, addSeidList: Array, removeSeidList: Array) { // 计算身上所有装备的战力值(特技相关以外) let res = calHeroEquipIncAttr(hero); // 计算被动技能 let { ePlace } = hero; let suits = new Map(); for (let { equip } of ePlace) { if (equip) { let e = equip; for (let { seid, rand } of e.randSe) { addSeidList.push(seid, rand); } if (e.suitId > 0) { if (suits.has(e.suitId)) { suits.set(e.suitId, suits.get(e.suitId) + 1); } else { suits.set(e.suitId, 1); } } } } suits.forEach((suitId, count) => { let { effect } = gameData.suit.get(suitId); for (let e of effect) { if (count >= e.count) { addSeidList.push(e.seid, 0); } } }); for (let arg of args) { removeSeidList.push(arg) } return res } export function calEquipSeids(hero: HeroType) { let seids = []; // 计算被动技能 let { ePlace } = hero; let suits = new Map(); for (let { equip } of ePlace) { if (equip) { let e = equip; if (!!e.randSe) { for (let { seid, rand } of e.randSe) { seids.push(seid, rand); } } if (e.suitId > 0) { if (suits.has(e.suitId)) { suits.set(e.suitId, suits.get(e.suitId) + 1); } else { suits.set(e.suitId, 1); } } } } suits.forEach((suitId, count) => { let { effect } = gameData.suit.get(suitId); for (let e of effect) { if (count >= e.count) { seids.push(e.seid, 0); } } }); return seids; } // 装备,装备栏升级,装备精炼等涉及到值的 export function calHeroEquipIncAttr(hero: HeroType) { let res: CeAttr = {}; let { ePlace } = hero; let attrResult = new CeAttrNumber(); for (let { equip, lv, refineLv } of ePlace) { if (equip) { let e = equip; let dicGoods = gameData.goods.get(e.id); let { goodsAbility, goodsAbilityUp } = dicGoods; let dicRefine = gameData.refine.get(refineLv); let jewel = new Map(); 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; attrResult[attrName] += attr; } } } for (let attrName in attrResult) { let originalCe = hero.ceAttr[attrName].equipUp || 0; console.log('装备战力:', attrName, attrResult[attrName], originalCe); res[attrName] = { fixUp: hero.ceAttr[attrName].fixUp, base: hero.ceAttr[attrName].base, ratioUp: hero.ceAttr[attrName].ratioUp, equipUp: originalCe }; res[attrName].equipUp += attrResult[attrName] - originalCe; } return res; } // 洗炼 export function calRestrengthenIncAttr(hero: HeroType, ePaceId: number, args: Array, addSeidList: Array, removeSeidList: Array) { let res: CeAttr = {}; let { ePlace } = hero; let curPlace = ePlace.find(cur => cur.id == ePaceId); if (curPlace && curPlace.equip) { let e = curPlace.equip; for (let { seid, rand } of e.randSe) { addSeidList.push(seid, rand); } } for (let arg of args) { removeSeidList.push(arg) } return res } // 添加技能增加的被动属性 function addSeidEffect(reIncAttr: CeAttr, heroCeAttr: CeAttr, addSeidList: Array, removeSeidList: Array) { console.log('addSeidList', addSeidList) console.log('removeSeidList', removeSeidList) let otiginalSeidList = [ { list: addSeidList, multi: 1 }, { list: removeSeidList, multi: -1 } ]; for (let { list, multi } of otiginalSeidList) { let effectList = new Array(); // any: dic_zyz_se表内容 for (let ii = 0; ii < list.length; ii += 2) { let seid = list[ii]; let rand = list[ii + 1] || 0; let dicSeid: DicSe | DicRandomEffectPool = gameData.se.get(seid); if (!dicSeid) dicSeid = gameData.randomEffectPool.get(seid); if (dicSeid && dicSeid.id > 0) { addSeid(effectList, dicSeid.id, rand, dicSeid.gainValueArr) } } for (let { type, gainValueArr: [ability, value] } of effectList) { let attrName = getAtrrNameById(ability); if (!attrName) continue; if (type == SEID_TYPE.TYPE101) { // 加值 if (!reIncAttr[attrName]) { reIncAttr[attrName] = deepCopy(heroCeAttr[attrName]); } if (!reIncAttr[attrName]) { delete reIncAttr[attrName]; continue; } reIncAttr[attrName].fixUp += value * multi * HERO_CE_RATIO; delete reIncAttr[attrName]._id; } else if (type == SEID_TYPE.TYPE102) { // 加百分比 if (!reIncAttr[attrName]) { reIncAttr[attrName] = deepCopy(heroCeAttr[attrName]); } if (!reIncAttr[attrName]) { delete reIncAttr[attrName]; continue; } reIncAttr[attrName].ratioUp += value * multi; delete reIncAttr[attrName]._id; } } } } // 获取dic_zyz_se内容 function addSeid(effectList: Array, seidId: number, rand: number, seidValue = new Array()) { // console.log('addSeidEffect', seidId, seidValue) let curSeid: DicSe | DicRandomEffectPool = gameData.se.get(seidId); if (!curSeid) curSeid = gameData.randomEffectPool.get(seidId); if (!curSeid) { console.log("seidId not found:" + seidId); return; } if (!seidValue) seidValue = curSeid.gainValueArr; if (curSeid.type === SEID_TYPE.TYPE999) { for (let i = 0; i < seidValue.length; i++) { addSeid(effectList, seidValue[i], rand); } return; } let seid: DicSe | DicRandomEffectPool = deepCopy(curSeid); if (curSeid.index > 0) { seid.gainValueArr[curSeid.index - 1] = rand; } effectList.push(seid); } function calHeroCeWhenJewelOn(hero: HeroType, args: Array) { let res: CeAttr = {}; let id = args[0]; let oldId = args[1]; let goodInfo = getGoodById(id); let oldGoodInfo; if (!!oldId) oldGoodInfo = getGoodById(oldId); for (let attrName in JEWEL_ATTR) { if (!!goodInfo[attrName]) { res[attrName] = { fixUp: hero.ceAttr[attrName].fixUp, base: hero.ceAttr[attrName].base, ratioUp: hero.ceAttr[attrName].ratioUp }; res[attrName].fixUp += goodInfo[attrName]; if (oldGoodInfo) res[attrName].fixUp -= oldGoodInfo[attrName]; } } return res; } function calHeroCeWhenJewelOff(hero: HeroType, args: Array) { let res: CeAttr = {}; for (let id of args) { let goodInfo = getGoodById(id); for (let attrName in JEWEL_ATTR) { if (!!goodInfo[attrName]) { res[attrName] = { fixUp: hero.ceAttr[attrName].fixUp, base: hero.ceAttr[attrName].base, ratioUp: hero.ceAttr[attrName].ratioUp }; res[attrName].fixUp -= goodInfo[attrName]; } } } return res; } //全局属性加成 export async function reCalAllHeroCe(roleId: string, type: number, args: Array) { let role = await RoleModel.findByRoleId(roleId); if (!role.globalCeAttr) role.globalCeAttr = new CeAttr(); let pushHeros: Array<{ hid: number, ce: number, incHeroCe: number }> = [] let heros = await HeroModel.findByRole(roleId); await reCalRoleAttr(heros, role.globalCeAttr, type, args); role.ce = 0; for (let hero of heros) { let heroCe = 0; for (let attrName in role.globalCeAttr) { if (attrName == '_id') continue; let heroAttrData: CeAttrData = hero.ceAttr[attrName] || new CeAttrData(); let globalAttrData: CeAttrData = role.globalCeAttr[attrName]; let attrNumber = (heroAttrData.fixUp + (heroAttrData.equipUp || 0) + globalAttrData.fixUp) * HERO_CE_RATIO + heroAttrData.base * (HERO_CE_RATIO + heroAttrData.ratioUp + globalAttrData.ratioUp); heroCe += attrNumber * getAttrCeRatio(attrName); } let incHeroCe = heroCe - hero.ce; hero.ce = heroCe; role.ce += hero.ce; pushHeros.push({ hid: hero.hid, ce: reduceCe(hero.ce), incHeroCe: reduceCe(incHeroCe) }); await HeroModel.updateHeroInfo(roleId, hero.hid, { ce: hero.ce }); } role = await RoleModel.updateRoleInfo(roleId, { globalCeAttr: role.globalCeAttr, ce: role.ce }); return { pushHeros, ce: role.ce, topFiveCe: role.topFiveCe } } function calHeroAddSkin(args: Array, ceAttr: CeAttrRole) { let res: CeAttrRole = {}; for (let arg of args) { let addSkin = gameData.fashion.get(arg); let attrName: string; for (let attr of addSkin.globalAttr) { attrName = getAtrrNameById(attr.id); res[attrName] = { fixUp: ceAttr[attrName].fixUp, ratioUp: ceAttr[attrName].ratioUp }; res[attrName].fixUp += attr.number * HERO_CE_RATIO; } } return res; } /** * 全局加成,百家学宫 * @param heros 所有武将 * @param schoolId 学宫学派 * @param hid 换上的武将 * @param preHid 撤下的武将 * @param ceAttr */ function calSchoolAddAttr(heros: HeroType[], schoolId: number, hid: number, preHid: number, ceAttr: CeAttrRole) { let res: CeAttrRole = {}; let school = gameData.school.get(schoolId); let preHero = heros.find(cur => cur.hid == preHid); let curHero = heros.find(cur => cur.hid == hid); if (!school) return res; let defaultPercent = { mainAttrAPerent: 0, assiAttrAddValue: 0 }; let preRate = preHero ? getSchoolRateByStar(preHero.star, preHero.colorStar, preHero.quality) : defaultPercent; let curRate = curHero ? getSchoolRateByStar(curHero.star, curHero.colorStar, curHero.quality) : defaultPercent; let attrName: string; for (let attrId of school.upAttribute) { attrName = getAtrrNameById(attrId); res[attrName] = { fixUp: ceAttr[attrName].fixUp, ratioUp: ceAttr[attrName].ratioUp }; if (attrId < ABI_TYPE.ABI_SPEED) { // 主属性 res[attrName].ratioUp += curRate.mainAttrAPerent - preRate.mainAttrAPerent; } else { // 次级属性 res[attrName].fixUp += (curRate.assiAttrAddValue - preRate.assiAttrAddValue) * HERO_CE_RATIO; } } return res; } /** * 升星,觉醒,升品时,百家学宫配置武将会相应修改全局战力 * @param heros HeroType[] 传入只有一个,如果有全局计算,后面push其他武将 * @param type number 类型 * @param args * @param ceAttr */ async function calSchoolStarIncAttr(heros: HeroType[], type: number, args: number[], ceAttr: CeAttrRole) { let res: CeAttrRole = {}; let [hid, isStarUp] = args; // 是否升星,是否初次觉醒 let needCal = false; let roleId: string = ''; for (let hero of heros) { if (hero.hid != hid) { continue; } if ((type == HERO_SYSTEM_TYPE.STAR || type == HERO_SYSTEM_TYPE.COLORSTAR) && !isStarUp) { continue; } roleId = hero.roleId; let curHeroInSchool = await SchoolModel.findByHid(roleId, hid); if (!curHeroInSchool) continue; let preStar = hero.star, preColorStar = hero.colorStar, preQuality = hero.quality; if (type == HERO_SYSTEM_TYPE.STAR && isStarUp) { preStar--; } else if (type == HERO_SYSTEM_TYPE.QUALITY) { preQuality--; } else if (type == HERO_SYSTEM_TYPE.COLORSTAR) { preColorStar--; } else { continue; } let school = gameData.school.get(curHeroInSchool.schoolId); let preRate = getSchoolRateByStar(preStar, preColorStar, preQuality); let curRate = getSchoolRateByStar(hero.star, hero.colorStar, hero.quality); let attrName: string; for (let attrId of school.upAttribute) { attrName = getAtrrNameById(attrId); res[attrName] = { fixUp: ceAttr[attrName].fixUp, ratioUp: ceAttr[attrName].ratioUp }; if (attrId < ABI_TYPE.ABI_SPEED) { // 主属性 res[attrName].ratioUp += curRate.mainAttrAPerent - preRate.mainAttrAPerent; } else { // 次级属性 res[attrName].fixUp += (curRate.assiAttrAddValue - preRate.assiAttrAddValue) * HERO_CE_RATIO; } } needCal = true; } if (needCal) { const allHeros = await HeroModel.findByRole(roleId); for (let hero of allHeros) { if (hero.hid != hid) heros.push(hero); } } return res; } /** * 全局加成, 名将谱 * @param heros 所有武将 * @param hid 激活的武将 * @param ceAttr */ function calScrollAddAttr(heros: HeroType[], hid: number, ceAttr: CeAttrRole) { let res: CeAttrRole = {}; let curHero = heros.find(cur => cur.hid == hid); let dicHero = gameData.hero.get(hid); if (!curHero || !dicHero) return res; let { quality } = dicHero; let { star, quality: curQuality, colorStar, job } = curHero; let heroScroll = getScollByStar(quality, star, curQuality, colorStar); if (!heroScroll) return res; let preScroll = gameData.preHeroScroll.get(heroScroll.id); heroScroll.ceAttr.forEach((add, id) => { let attId = getFieldByStage(id, job); let attrName = getAtrrNameById(attId); let preAdd = preScroll ? preScroll.ceAttr.get(id) : 0; res[attrName] = { fixUp: ceAttr[attrName].fixUp, ratioUp: ceAttr[attrName].ratioUp }; res[attrName].fixUp += (add - preAdd) * HERO_CE_RATIO; }); return res; } /** * 名将谱激活增加单个武将好感 * @param hero 当前武将 * @param hid 激活武将 * @param preFavourLv 之前的好感度等级,有提升时才计算加成 */ function calHeroCeScrollIncAttr(hero: HeroType, hid: number, preFavourLv: number) { let res: CeAttr = {}; if (hero.hid == hid && hero.favourLv != preFavourLv) { res = calHeroFavourUpIncAttr(hero, [preFavourLv]); } return res; } function calTitle(args: Array, ceAttr: CeAttrRole) { let res: CeAttrRole = {}; let titleId = args[0]; let titleInfo = gameData.title.get(titleId); for (let attrName in getTeraphAttr()) { res[attrName] = { fixUp: ceAttr[attrName].fixUp, ratioUp: ceAttr[attrName].ratioUp }; res[attrName].fixUp += titleInfo[attrName] * HERO_CE_RATIO; } for (let attr of titleInfo.assiAttrValue) { let attrName = getAtrrNameById(attr.id); if (!attrName) continue; res[attrName] = res[attrName] || { fixUp: ceAttr[attrName].fixUp, ratioUp: ceAttr[attrName].ratioUp }; res[attrName].ratioUp += attr.number * HERO_CE_RATIO; } return res; } export function initRoleAtrr(role: RoleType) { if (!role.globalCeAttr) role.globalCeAttr = new CeAttr(); let titleId = role.title; let titleInfo = gameData.title.get(titleId); if (!!titleInfo) { for (let attrName in getTeraphAttr()) { if (!attrName) continue; role.globalCeAttr[attrName].fixUp += titleInfo[attrName] * HERO_CE_RATIO; } for (let attr of titleInfo.assiAttrValue) { let attrName = getAtrrNameById(attr.id); if (!attrName) continue; role.globalCeAttr[attrName].ratioUp += attr.number * HERO_CE_RATIO; } } return; } async function reCalRoleAttr(heros: Array, ceAttr: CeAttrRole, type: number, args: Array) { let reIncAttr: CeAttrRole = {}; // role表属性增量 switch (type) { case HERO_SYSTEM_TYPE.INIT: reIncAttr = calRoleInitIncAttr(heros, ceAttr); // 全局变量增 break; case HERO_SYSTEM_TYPE.ADD_SKIN: reIncAttr = calHeroAddSkin(args, ceAttr); break; case HERO_SYSTEM_TYPE.SCHOOL: reIncAttr = calSchoolAddAttr(heros, args[0], args[1], args[2], ceAttr); break; case HERO_SYSTEM_TYPE.SCROLL: reIncAttr = calScrollAddAttr(heros, args[0], ceAttr); break; case HERO_SYSTEM_TYPE.STAR: case HERO_SYSTEM_TYPE.COLORSTAR: case HERO_SYSTEM_TYPE.QUALITY: reIncAttr = await calSchoolStarIncAttr(heros, type, args, ceAttr); break; case HERO_SYSTEM_TYPE.TITLE: reIncAttr = calTitle(args, ceAttr); } for (let attrName in reIncAttr) { if (attrName == '_id') continue; let globalAttrData: CeAttrDataRole = reIncAttr[attrName] || new CeAttrDataRole(); for (let key in globalAttrData) { ceAttr[attrName][key] += parseInt(globalAttrData[key] || 0); } } }