diff --git a/game-server/app/servers/role/handler/equipHandler.ts b/game-server/app/servers/role/handler/equipHandler.ts index 10e6e688d..819818a74 100644 --- a/game-server/app/servers/role/handler/equipHandler.ts +++ b/game-server/app/servers/role/handler/equipHandler.ts @@ -138,7 +138,7 @@ export class EquipHandler { hero.ePlace = ePlace; - await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.EQUIP_BASE); + await calPlayerCeAndSave(HERO_SYSTEM_TYPE.EQUIP_BASE, sid, roleId, hero, { ePlace }); const curHero = { hid, ePlace: strengthenArr @@ -197,7 +197,7 @@ export class EquipHandler { hero.ePlace = ePlace; - await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.EQUIP_BASE); + await calPlayerCeAndSave(HERO_SYSTEM_TYPE.EQUIP_BASE, sid, roleId, hero, { ePlace }); const curHero = { hid, ePlace: strengthenArr @@ -261,7 +261,7 @@ export class EquipHandler { let result = await handleCost(roleId, sid, cost); if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.EQUIP_BASE); + await calPlayerCeAndSave(HERO_SYSTEM_TYPE.EQUIP_BASE, sid, roleId, hero, { ePlace }); const curHero = { hid, @@ -381,7 +381,7 @@ export class EquipHandler { // 更新战力 const hero = await HeroModel.findByHidAndRoleWithEquip(hid, roleId); - await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.RESTRENGTHEN, [ePlaceId, ...removeSeidList]); + await calPlayerCeAndSave(HERO_SYSTEM_TYPE.RESTRENGTHEN, sid, roleId, hero, {}, [ePlaceId, ...removeSeidList]); return resResult(STATUS.SUCCESS,{curEquip}); @@ -448,7 +448,7 @@ export class EquipHandler { } else if (type == 2) { if (!equip.hid) return resResult(STATUS.EQUIP_NOT_EQUIPED); - let curEquip = await takeOffEquipAndCalPlayerCe(roleId, sid, equip.seqId, hero, id) + let curEquip = await takeOffEquipAndCalPlayerCe(roleId, sid, hero, equip, id) curEquips.push(curEquip); } return resResult(STATUS.SUCCESS, { curEquips: curEquips }); @@ -513,7 +513,7 @@ export class EquipHandler { await addItems(roleId, roleName, sid, goods); if (!!equip.hid) { let hero = await HeroModel.findByHidAndRole(equip.hid, roleId); - await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.JEWEL_ON, [jewel, oldJewel]); + await calPlayerCeAndSave(HERO_SYSTEM_TYPE.JEWEL_ON, sid, roleId, hero, {}, [jewel, oldJewel]); } return resResult(STATUS.SUCCESS, { curEquip: { seqId: eid, holes: equip.holes } }); } @@ -560,7 +560,7 @@ export class EquipHandler { await addItems(roleId, roleName, sid, goods); if (!!equip.hid) { let hero = await HeroModel.findByHidAndRole(equip.hid, roleId); - await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.JEWEL_OFF, [jewel]); + await calPlayerCeAndSave(HERO_SYSTEM_TYPE.JEWEL_OFF, sid, roleId, hero, {}, [jewel]); } return resResult(STATUS.SUCCESS, { curEquip: { seqId: eid, holes: equip.holes } }); } @@ -651,7 +651,7 @@ export class EquipHandler { await EquipModel.updateEquipInfo(eid, { holes: equip.holes }); if (!!equip.hid) { let hero = await HeroModel.findByHidAndRole(equip.hid, roleId); - await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.JEWEL_ON, [jewel, oldJewel]); + await calPlayerCeAndSave(HERO_SYSTEM_TYPE.JEWEL_ON, sid, roleId, hero, {}, [jewel, oldJewel]); } return resResult(STATUS.SUCCESS, { curEquip: { seqId: eid, holes: equip.holes } }); } else { diff --git a/game-server/app/servers/role/handler/friendHandler.ts b/game-server/app/servers/role/handler/friendHandler.ts index 2a9af4043..b7fa27c91 100644 --- a/game-server/app/servers/role/handler/friendHandler.ts +++ b/game-server/app/servers/role/handler/friendHandler.ts @@ -681,12 +681,12 @@ export class FriendHandler { if(heroList.length <= 0) return resResult(STATUS.HERO_NOT_FIND); let list = new Array(); - for(let {roleId, roleName, hid, hName, ce, lv, star, colorStar, quality, job, skins, ceAttr} of heroList) { + for(let {roleId, roleName, hid, hName, ce, lv, star, colorStar, quality, job, skins, attr: heroAttrs} of heroList) { let curSkin = skins.find(cur => cur.enable); let equips = await EquipModel.findListByHidAndRole(hisRoleId, hid, EQUIP_SELECT.HERO_DETAIL); - let attributes = getPlayerMainAttribute(ceAttr, role.globalCeAttr); + let attributes = getPlayerMainAttribute(heroAttrs, role.attr); list.push({ roleId, roleName, hid, hName, ce, lv, star, colorStar, quality, job, diff --git a/game-server/app/servers/role/handler/heroHandler.ts b/game-server/app/servers/role/handler/heroHandler.ts index 9f4b74c28..45e85942a 100644 --- a/game-server/app/servers/role/handler/heroHandler.ts +++ b/game-server/app/servers/role/handler/heroHandler.ts @@ -1,9 +1,9 @@ import {Application, BackendSession, ChannelService} from 'pinus'; import { handleCost, addItems } from '../../../services/rewardService'; -import { calPlayerCeAndSave } from '../../../services/playerCeService'; -import { resResult, returnHeroCeRatio } from '../../../pubUtils/util'; +import { calPlayerCeAndSave, calAllHeroCe } from '../../../services/playerCeService'; +import { resResult, returnHeroCeRatio, deepCopy } from '../../../pubUtils/util'; import { STATUS } from '../../../consts/statusCode'; -import {HeroModel} from '../../../db/Hero'; +import { HeroModel, Connect } from '../../../db/Hero'; import {CURRENCY_BY_TYPE, CURRENCY_TYPE, CONSUME_TYPE, HERO_GROW_MAX, HERO_SYSTEM_TYPE, ITID, ABI_STAGE, HERO_CE_RATIO} from '../../../consts'; import { RoleModel } from '../../../db/Role'; import { ItemModel } from '../../../db/Item'; @@ -11,6 +11,7 @@ import { gameData, getHeroExpByLv, getHeroStarByQuality, getHeroWakeByQuality, g import { RewardInter } from '../../../pubUtils/interface'; import { getDropItems } from '../../../consts/constModules/itemConst' import { getRoleOnlineInfo, getAllOnlineRoles } from '../../../services/redisService'; +import { CeAttrDataRole, CeAttrData } from '../../../domain/roleField/attribute'; export default function(app: Application) { return new HeroHandler(app); } @@ -80,7 +81,8 @@ export class HeroHandler { let curHero = await HeroModel.createHero({ roleId, serverId, roleName, hid, hName, star, quality, job, skins:[{id: initialSkin, enable: true}] }); - await calPlayerCeAndSave(sid, roleId, [curHero], HERO_SYSTEM_TYPE.INIT); + await calPlayerCeAndSave(HERO_SYSTEM_TYPE.INIT, sid, roleId, curHero, {}); + await calAllHeroCe(HERO_SYSTEM_TYPE.ADD_SKIN, sid, roleId, {}, [initialSkin]) return resResult(STATUS.SUCCESS, {curHero: returnHeroCeRatio(curHero)}); } @@ -137,12 +139,14 @@ export class HeroHandler { let costResult = await handleCost(roleId, sid, material); if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - hero.lv = playerLv > newLv?newLv: playerLv; - hero.exp = newExp; + let update = { + lv: playerLv > newLv?newLv: playerLv, + exp: newExp + } - let heros = await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.LVUP, [hid]); + hero = await calPlayerCeAndSave(HERO_SYSTEM_TYPE.LVUP, sid, roleId, hero, update); const curHero = { - hid, lv : heros[0].lv, exp : heros[0].exp + hid, lv : hero.lv, exp : hero.exp } return resResult(STATUS.SUCCESS, { curHero }); @@ -177,16 +181,20 @@ export class HeroHandler { if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); let isUpStar = oldStarStage + 1 == ABI_STAGE.END; - hero.star = isUpStar? oldStar + 1: oldStar; - hero.starStage = isUpStar? ABI_STAGE.START: oldStarStage + 1; - let heros = await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.STAR, [hid, isUpStar?1:0]); + let update = { + star: isUpStar? oldStar + 1: oldStar, + starStage: isUpStar? ABI_STAGE.START: oldStarStage + 1 + } + + hero = await calPlayerCeAndSave(HERO_SYSTEM_TYPE.STAR, sid, roleId, hero, update); + if(isUpStar) await calAllHeroCe(HERO_SYSTEM_TYPE.STAR, sid, roleId, {}, [hid, isUpStar?1:0]); // 升星可能影响到百家学院全局加成 const curHero = { hid, - star : heros[0].star, - starStage : heros[0].starStage, - colorStar: heros[0].colorStar, - colorStarStage: heros[0].colorStarStage + star : hero.star, + starStage : hero.starStage, + colorStar: hero.colorStar, + colorStarStage: hero.colorStarStage } return resResult(STATUS.SUCCESS, {isUpStar, curHero}); } @@ -223,11 +231,14 @@ export class HeroHandler { let costResult = await handleCost(roleId, sid, [{id: pieceId, count: fragmentNum}]); if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - hero.quality ++; - let heros = await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.QUALITY, [hid]); + hero = await calPlayerCeAndSave(HERO_SYSTEM_TYPE.QUALITY, sid, roleId, hero, { + quality: hero.quality + 1 + }); + await calAllHeroCe(HERO_SYSTEM_TYPE.QUALITY, sid, roleId, {}, [hid, 0]); // 升品可能影响到百家学院全局加成 + const curHero = { hid, - quality : heros[0].quality + quality : hero.quality } return resResult(STATUS.SUCCESS, {curHero}); } @@ -269,16 +280,21 @@ export class HeroHandler { let isWakeUp = oldColorStar == 0; let isUpStar = isWakeUp || oldColorStarStage + 1 == ABI_STAGE.END; - hero.colorStar = isUpStar? oldColorStar + 1: oldColorStar; - hero.colorStarStage = isUpStar? ABI_STAGE.START: oldColorStarStage + 1; - let heros = await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.COLORSTAR, [hid, isUpStar?1:0, isWakeUp?1:0]); + let update = { + colorStar: isUpStar? oldColorStar + 1: oldColorStar, + colorStarStage: isUpStar? ABI_STAGE.START: oldColorStarStage + 1 + } + + hero = await calPlayerCeAndSave(HERO_SYSTEM_TYPE.COLORSTAR, sid, roleId, hero, update); + if(isUpStar) await calAllHeroCe(HERO_SYSTEM_TYPE.COLORSTAR, sid, roleId, {}, [hid, isUpStar?1:0]); // 升星可能影响到百家学院全局加成 + const curHero = { hid, - star : heros[0].star, - starStage : heros[0].starStage, - colorStar: heros[0].colorStar, - colorStarStage: heros[0].colorStarStage + star : hero.star, + starStage : hero.starStage, + colorStar: hero.colorStar, + colorStarStage: hero.colorStarStage } return resResult(STATUS.SUCCESS, {isUpStar, curHero}); } @@ -289,26 +305,30 @@ export class HeroHandler { let sid: string = session.get('sid'); let { hid } = msg; let hero = await HeroModel.findByHidAndRole(hid, roleId); - if (!hero) - return resResult(STATUS.HERO_NOT_FIND); - let heroJob = gameData.job.get(hero.job); - if (hero.jobStage >= 6) + if (!hero) return resResult(STATUS.HERO_NOT_FIND); + + let dicJob = gameData.job.get(hero.job); + if(!dicJob) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + if (hero.jobStage >= ABI_STAGE.END) return resResult(STATUS.HERO_JOB_STAGE_REACH_MAX_STAGE); - if (hero.job >= getMaxGradeByjobClass(heroJob.job_class)) + if (hero.job >= getMaxGradeByjobClass(dicJob.job_class)) return resResult(STATUS.HERO_JOB_REACH_MAX_STAGE); let consume = new Array(); - if(heroJob.trainingConsume[hero.jobStage]) { - consume.push(heroJob.trainingConsume[hero.jobStage]); + if(dicJob.trainingConsume[hero.jobStage]) { + consume.push(dicJob.trainingConsume[hero.jobStage]); } let result = await handleCost(roleId, sid, consume); if(!result) { return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); } - hero.jobStage = hero.jobStage +1; + //重算战力并下发 - let heros = await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.TRAIN); - return resResult(STATUS.SUCCESS, { curHero: {hid : heros[0].hid, job : heros[0].job, jobStage: heros[0].jobStage}}); + hero = await calPlayerCeAndSave(HERO_SYSTEM_TYPE.TRAIN, sid, roleId, hero, { + jobStage: hero.jobStage + 1 + }); + return resResult(STATUS.SUCCESS, { curHero: {hid : hero.hid, job : hero.job, jobStage: hero.jobStage}}); } //进阶 @@ -330,27 +350,30 @@ export class HeroHandler { return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); } let nextHeroJob = getJobByGradeAndClass(heroJob.job_class, heroJob.grade + 1); - hero.job = nextHeroJob.jobid; - hero.jobStage = 0; + //重算战力并下发 - let heros = await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.STAGEUP, [curJob]); - return resResult(STATUS.SUCCESS, { curHero: {hid : heros[0].hid, job : heros[0].job, jobStage : heros[0].jobStage}}); + let update = { + job: nextHeroJob.jobid, + jobStage: 0 + } + hero = await calPlayerCeAndSave(HERO_SYSTEM_TYPE.STAGEUP, sid, roleId, hero, update); + return resResult(STATUS.SUCCESS, { curHero: {hid : hero.hid, job : hero.job, jobStage : hero.jobStage}}); } //激活羁绊 - async heroConectionActivate(msg: {shipId: number}, session: BackendSession) { + async heroConectionActivate(msg: { shipId: number }, session: BackendSession) { let roleId: string = session.get('roleId'); let sid: string = session.get('sid'); let { shipId } = msg; let shipHidAndLevel = gameData.friendShipHidAandIds.get(shipId); - if (!shipHidAndLevel) - return resResult(STATUS.HERO_CONECTION_IS_NOT_EXIT); + if (!shipHidAndLevel) return resResult(STATUS.HERO_CONECTION_IS_NOT_EXIT); let hero = await HeroModel.findByHidAndRole(shipHidAndLevel.actorId, roleId); - if (!hero) - return resResult(STATUS.HERO_NOT_FIND); + if (!hero) return resResult(STATUS.HERO_NOT_FIND); + + let heroConnections: Connect[] = deepCopy(hero.connections); let flag = true; let level = 1; - for (let conection of hero.connections) { + for (let conection of heroConnections) { if (conection.shipId == shipId ) { if (conection.level >= shipHidAndLevel.level) { return resResult(STATUS.HERO_CONECTION_IS_MAX_LEVEL); @@ -362,7 +385,7 @@ export class HeroHandler { } } if (!!flag) { - hero.connections.push({shipId, level}); + heroConnections.push({shipId, level}); } let friendShip = getFriendShipById(shipId, level); if (hero.star < friendShip.level) @@ -382,8 +405,8 @@ export class HeroHandler { return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); } //重算战力并下发 - let heros = await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.CONNECT, [shipId, level]); - return resResult(STATUS.SUCCESS, { curHero: {hid : heros[0].hid, connections : heros[0].connections}}); + hero = await calPlayerCeAndSave(HERO_SYSTEM_TYPE.CONNECT, sid, roleId, hero, { connections: heroConnections }, [shipId]); + return resResult(STATUS.SUCCESS, { curHero: {hid : hero.hid, connections : hero.connections}}); } //赠送(包括一键赠送) @@ -441,8 +464,6 @@ export class HeroHandler { } let newLv = getFavourLvByExp(newExp); - hero.favour = newExp; - hero.favourLv = newLv; let result = await handleCost(roleId, sid, material); if(!result) { @@ -450,11 +471,13 @@ export class HeroHandler { } //重算战力并下发 if (oldLv != hero.favourLv) { - await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.FAVOUR, [oldLv]); + await calPlayerCeAndSave(HERO_SYSTEM_TYPE.FAVOUR, sid, roleId, hero, { + favour: newExp, favourLv: newLv + }, [oldLv]); } else { await HeroModel.updateHeroInfo(roleId, hero.hid, hero); } - return resResult(STATUS.SUCCESS, { curHero: {hid : hero.hid, favour : hero.favour, favourLv : hero.favourLv}}); + return resResult(STATUS.SUCCESS, { curHero: { hid: hero.hid, favour: hero.favour, favourLv: hero.favourLv } }); } //穿带时装 @@ -463,14 +486,15 @@ export class HeroHandler { let sid: string = session.get('sid'); let { id } = msg; let skinInfo = gameData.fashion.get(id); - if (!skinInfo) - return resResult(STATUS.HERO_SKIN_NOT_FIND); + if (!skinInfo) return resResult(STATUS.HERO_SKIN_NOT_FIND); let hero = await HeroModel.findByHidAndRole(skinInfo.actorId, roleId); - if (!hero) - return resResult(STATUS.HERO_NOT_FIND); + if (!hero) return resResult(STATUS.HERO_NOT_FIND); + + let heroSkins = deepCopy(hero.skins); + let result = false; let lastSkinId: number; - for (let skin of hero.skins) { + for (let skin of heroSkins) { if (skin.id == id) { if (!!skin.enable) { return resResult(STATUS.HERO_SKIN_IS_EQUIPED); @@ -487,7 +511,7 @@ export class HeroHandler { if (!result) { return resResult(STATUS.HERO_SKIN_NOT_FIND); } - await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.SKIN, [id, lastSkinId]); + await calPlayerCeAndSave(HERO_SYSTEM_TYPE.SKIN, sid, roleId, hero, { skins: heroSkins }, [id, lastSkinId]); return resResult(STATUS.SUCCESS, {curHero: {hid : hero.hid, skins : hero.skins} }); } } diff --git a/game-server/app/servers/role/handler/roleHandler.ts b/game-server/app/servers/role/handler/roleHandler.ts index 49b19d45b..ca77cb334 100644 --- a/game-server/app/servers/role/handler/roleHandler.ts +++ b/game-server/app/servers/role/handler/roleHandler.ts @@ -1,12 +1,12 @@ import { STATUS } from '../../../consts/statusCode'; import { RoleModel } from './../../../db/Role'; import { HeroModel } from '../../../db/Hero'; -import { resResult, decodeIdCntArrayStr, parseGoodStr, reduceCe } from '../../../pubUtils/util'; +import { resResult, decodeIdCntArrayStr, parseGoodStr } from '../../../pubUtils/util'; import {Application, BackendSession} from 'pinus'; import { handleCost } from '../../../services/rewardService'; import { getTitle, getTeraph, gameData, getScollByStar, getFriendLvByExp } from '../../../pubUtils/data'; import { SCHOOL, SCROLL } from '../../../pubUtils/dicParam'; -import { getTeraphAttr, getAtrrNameById } from '../../../consts/constModules/abilityConst' +import { getAtrrNameById } from '../../../consts/constModules/abilityConst' import { findIndex } from 'underscore'; import { SclResultInter, SclPosInter } from '../../../pubUtils/interface'; import { SchoolModel } from '../../../db/School'; @@ -79,11 +79,12 @@ export class RoleHandler { //爵位 async roleTitleLevelUp(msg: {}, session: BackendSession){ let roleId = session.get('roleId'); - let role = await RoleModel.findByRoleId(roleId); - let oldCe = role.ce; let sid: string = session.get('sid'); - let title = ++role.title; - let titleInfo = getTitle(role.title); + + let role = await RoleModel.findByRoleId(roleId); + + let { title } = role; + let titleInfo = getTitle(title + 1); if (!titleInfo) return resResult(STATUS.DIC_DATA_NOT_FOUND) if (titleInfo.lvLimited > role.lv) @@ -92,44 +93,47 @@ export class RoleHandler { let result = await handleCost(roleId, sid, consumes); if (!result) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - await RoleModel.updateRoleInfo(roleId, { title }); - let {ce} = await calAllHeroCe( sid, roleId, HERO_SYSTEM_TYPE.TITLE, [title]); - return resResult(STATUS.SUCCESS, { roleId, title }); + + let update = { title: title + 1 } + role = await calAllHeroCe(HERO_SYSTEM_TYPE.TITLE, sid, roleId, update); + return resResult(STATUS.SUCCESS, { roleId, title: role.title }); } //神像强化 async roleTeraphStrengthen(msg: {id: number, count: number}, session: BackendSession){ let {id, count} = msg; let roleId = session.get('roleId'); - let role = await RoleModel.findByRoleId(roleId); let sid: string = session.get('sid'); - let index = findIndex(role.teraphs, {id}); + + let role = await RoleModel.findByRoleId(roleId); + let teraphs = role.teraphs; + let index = findIndex(teraphs, {id}); if (index < 0) return resResult(STATUS.WRONG_PARMS); - let teraph = role.teraphs[index]; - let teraphInfo = getTeraph(id, teraph.grade); - if (!teraphInfo) - return resResult(STATUS.DIC_DATA_NOT_FOUND) - let attrs = []; - for (let attrName in getTeraphAttr()) { - let attrNameMax = attrName+'Max'; - if (teraph[attrName] < teraphInfo[attrNameMax]) { - attrs.push(attrName); + let teraph = teraphs[index]; + let dicTeraph = getTeraph(id, teraph.grade); + if (!dicTeraph) + return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let attrs = new Array(); // 可以强化的属性 + dicTeraph.mainAttrMax.forEach(( max, id) => { + let attrName = getAtrrNameById(id); + if (teraph[attrName] < max) { + attrs.push(id); } - } + }); + if (!attrs.length) return resResult(STATUS.ROLE_TERAPH_NOT_STRENGTHEN); - // 随机神像中的一条属性并检查道具是否足够 - let {attr, consumes} = checkTeraphMaterialEnough(count, attrs, teraphInfo, teraph); - for (let key in attr) { - teraph[key] += attr[key]; - role.globalCeAttr[key].fixUp += attr[key]; - } + + // 随机神像中的一条属性并检查道具是否足够,以及更新teraph + let { consumes} = checkTeraphMaterialEnough(count, attrs, dicTeraph, teraph); + let result = await handleCost(roleId, sid, consumes); if (!result) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - await RoleModel.updateRoleInfo(roleId, { teraphs: role.teraphs, globalCeAttr: role.globalCeAttr}); - await calAllHeroCe( sid, roleId); + + role = await calAllHeroCe(HERO_SYSTEM_TYPE.TERAPH, sid, roleId, { teraphs }, [id]); return resResult(STATUS.SUCCESS, { roleId, teraphs: role.teraphs }); } @@ -137,34 +141,38 @@ export class RoleHandler { async roleTeraphQualityUp(msg: {id: number}, session: BackendSession){ let {id} = msg; let roleId = session.get('roleId'); - let role = await RoleModel.findByRoleId(roleId); let sid: string = session.get('sid'); - let index = findIndex(role.teraphs, {id}); + + let role = await RoleModel.findByRoleId(roleId); + let teraphs = role.teraphs; + let index = findIndex(teraphs, {id}); if (index < 0) return resResult(STATUS.WRONG_PARMS); - let teraph = role.teraphs[index]; + let teraph = teraphs[index]; let teraphInfo = getTeraph(id, teraph.grade); if (!teraphInfo) return resResult(STATUS.DIC_DATA_NOT_FOUND) - for (let attrName in getTeraphAttr()) { - if (teraph[attrName] != teraphInfo[attrName +'Max']) + + for(let [attrId, val] of teraph.attr) { + if (teraph.attr.get(attrId) != teraphInfo.mainAttrMax.get(attrId)) return resResult(STATUS.ROLE_TERAPH_NOT_QUILITY); - teraph[attrName] = 0; + + teraph.attr.set(attrId, 0); + console.log('****', attrId, val) } - teraph.grade++; + teraph.grade ++; + + let nextTeraphInfo = getTeraph(id, teraph.grade) if (!nextTeraphInfo) - return resResult(STATUS.DIC_DATA_NOT_FOUND) + return resResult(STATUS.DIC_DATA_NOT_FOUND); + let consumes = teraphInfo.upGradeMaterial; let result = await handleCost(roleId, sid, consumes); if (!result) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - for (let {id, number} of nextTeraphInfo.assiAttrValue) { - let attrName = getAtrrNameById(id); - role.globalCeAttr[attrName].ratioUp += number; - } - await RoleModel.updateRoleInfo(roleId, { teraphs: role.teraphs, globalCeAttr: role.globalCeAttr}); - await calAllHeroCe(sid, roleId); + + role = await calAllHeroCe(HERO_SYSTEM_TYPE.TERAPH_UP, sid, roleId, { teraphs }); return resResult(STATUS.SUCCESS, { roleId, teraphs: role.teraphs }); } @@ -246,7 +254,7 @@ export class RoleHandler { } await SchoolModel.updateBySclAndPos(roleId, schoolId, positionId, { hid, isOpen }) - await calPlayerCeAndSave(sid, roleId, [], HERO_SYSTEM_TYPE.SCHOOL, [schoolId, hid, preHid]); + await calAllHeroCe(HERO_SYSTEM_TYPE.SCHOOL, sid, roleId, {}, [schoolId, hid, preHid]); return resResult(STATUS.SUCCESS, { schoolId, positionId, hid, preHid, isOpen @@ -334,11 +342,20 @@ export class RoleHandler { let dicHeroScroll = getScollByStar(dicHero.quality, update.scrollStar, update.scrollQuality, update.scrollColorStar); update.scrollId = dicHeroScroll?dicHeroScroll.id: 0; - curHero = await HeroModel.updateHeroInfo(roleId, hid, update, 'hid scrollActive scrollId scrollStar scrollColorStar scrollQuality favour favourLv'); - await calPlayerCeAndSave(sid, roleId, [], HERO_SYSTEM_TYPE.SCROLL, [hid, favourLv]); + let hero = await calPlayerCeAndSave(HERO_SYSTEM_TYPE.SCROLL, sid, roleId, curHero, update); // 更新单个武将战力 + calAllHeroCe(HERO_SYSTEM_TYPE.SCROLL, sid, roleId, {}, [hid]); // 全局增加战力 return resResult(STATUS.SUCCESS, { - curHero + curHero: { + hid: hero.hid, + scrollActive: hero.scrollActive, + scrollId: hero.scrollId, + scrollStar: hero.scrollStar, + scrollColorStar: hero.scrollColorStar, + scrollQuality: hero.scrollQuality, + favour: hero.favour, + favourLv: hero.favourLv, + } }); } diff --git a/game-server/app/services/battleService.ts b/game-server/app/services/battleService.ts index f19acf10a..acff4446b 100644 --- a/game-server/app/services/battleService.ts +++ b/game-server/app/services/battleService.ts @@ -1,6 +1,6 @@ import { HeroModel } from './../db/Hero'; import { HangUpRecordModel } from './../db/HangUpRecord'; -import { ChannelService, pinus } from 'pinus'; +import { pinus } from 'pinus'; import { HANG_UP_CONSTS, TOWER_TASK_CONST, REDIS_KEY } from './../consts'; import { BattleRecordModel } from './../db/BattleRecord'; import { TowerRecordModel } from './../db/TowerRecord'; diff --git a/game-server/app/services/equipService.ts b/game-server/app/services/equipService.ts index 94abbff46..8e4b1495c 100644 --- a/game-server/app/services/equipService.ts +++ b/game-server/app/services/equipService.ts @@ -1,4 +1,4 @@ -import { mergeSameGoods } from '../pubUtils/util'; +import { mergeSameGoods, deepCopy } from '../pubUtils/util'; import { EquipModel } from "../db/Equip"; import { HeroModel, EPlace, HeroType } from "../db/Hero"; import { getHeroJob, getGoodById, gameData, getJewelById, getHeroEquipByClassId } from "../pubUtils/data"; @@ -77,7 +77,7 @@ export async function changeEquip(roleId: string, sid: string, equip: EquipType, return res; } } else if (!!hero) {//从穿戴装备的武将上卸下装备 - await takeOffEquipAndCalPlayerCe(roleId, sid, seqId, hero, id);//卸下装备并重算战力 + await takeOffEquipAndCalPlayerCe(roleId, sid, hero, equip, id);//卸下装备并重算战力 } } /** @@ -88,15 +88,12 @@ export async function changeEquip(roleId: string, sid: string, equip: EquipType, * @param hero * @param id */ -export async function takeOffEquipAndCalPlayerCe(roleId: string, sid: string, seqId: number, hero:HeroType, id: number ) { - let index = findIndex(hero.ePlace, { id }); - if (index < 0) - return; - await EquipModel.updateEquipInfo(seqId, { hid: 0 }); - hero.ePlace[index].equip = null; +export async function takeOffEquipAndCalPlayerCe(roleId: string, sid: string, hero:HeroType, equip: EquipType, id: number ) { let args = calEquipSeids(hero); - await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.EQUIP, args); - return { seqId, hid: 0}; + hero = await HeroModel.removeEquip(roleId, hero.hid, id, equip._id); + + await calPlayerCeAndSave(HERO_SYSTEM_TYPE.EQUIP, sid, roleId, hero, {}, args); + return { seqId: equip.seqId, hid: 0}; } /** * 穿戴装备并重算战力 @@ -106,9 +103,10 @@ export async function takeOffEquipAndCalPlayerCe(roleId: string, sid: string, se * @param equip */ export async function dressEquip(roleId: string, sid: string, hero:HeroType, equip: EquipType) { - hero = await HeroModel.addEquip(roleId, hero.hid, equip.ePlaceId, equip._id); let args = calEquipSeids(hero); - await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.EQUIP, args); + + hero = await HeroModel.addEquip(roleId, hero.hid, equip.ePlaceId, equip._id); + await calPlayerCeAndSave(HERO_SYSTEM_TYPE.EQUIP, sid, roleId, hero, {}, args); return { seqId: equip.seqId, hid: hero.hid }; } /** diff --git a/game-server/app/services/expeditionService.ts b/game-server/app/services/expeditionService.ts index d956367a5..3d303890d 100644 --- a/game-server/app/services/expeditionService.ts +++ b/game-server/app/services/expeditionService.ts @@ -3,9 +3,9 @@ import { ExpeditionPointModel } from '../db/ExpeditionPoint'; import Role, { RoleModel, RoleType } from '../db/Role'; import { PvpDefenseModel } from '../db/PvpDefense'; -import { getWarJsons, getGamedata, getExpeditionById } from '../pubUtils/gamedata'; -import { decodeStr, resResult, shouldRefresh } from '../pubUtils/util'; -import { EXPEDITION_CONST, HERO_CE_RATIO, getAttrCeRatio } from '../consts'; +import { getWarJsons, getGamedata } from '../pubUtils/gamedata'; +import { decodeStr, shouldRefresh } from '../pubUtils/util'; +import { EXPEDITION_CONST, HERO_CE_RATIO } from '../consts'; import { getAtrrNameById} from '../consts'; import { ExpeditionWarRecordModel } from '../db/ExpeditionWarRecord'; import { HeroType } from '../db/Hero'; @@ -75,7 +75,7 @@ export async function matchPlayers(roleId: string, scale: number, range: number, let result = resultRange[index]; let {roleId, heroes, defCe } = result; let role = result.role; - let { globalCeAttr } = role; + let { attr: roleAttrs } = role; enemyObj.enemyFrom = 1; enemyObj.enemyId = roleId; @@ -87,9 +87,9 @@ export async function matchPlayers(roleId: string, scale: number, range: number, let hero = heroes[heroIndex]; if(hero) { let h = hero.hero; - let { star, lv, ceAttr } = h; + let { star, lv, attr: heroAttrs } = h; let dicHero = gameData.hero.get(hero.actorId); - let newAttribute = getPlayerAttribute(ceAttr, globalCeAttr); + let newAttribute = getPlayerAttribute(heroAttrs, roleAttrs); let heroInfo = { actorId: hero.actorId, actorName: dicHero.name, @@ -127,10 +127,7 @@ export async function matchRobots(scale: number, myCe: number, robotCe: number, const { attribute } = json; let newAttribute = getRobotAttribute(attribute, myCe, robotCe, scale); - let ce = 0; - for(let attrName in newAttribute) { - ce += newAttribute[attrName] * getAttrCeRatio(attrName)||0; - } + let ce = newAttribute.calCe(); enemyObj.enemies.push({...json, attribute: newAttribute, lv}); allCe += ce; } diff --git a/game-server/app/services/playerCeService.ts b/game-server/app/services/playerCeService.ts index df4047c8f..ce222a59a 100644 --- a/game-server/app/services/playerCeService.ts +++ b/game-server/app/services/playerCeService.ts @@ -7,22 +7,23 @@ import { STATUS } from '../consts/statusCode'; import { resResult, reduceCe } from '../pubUtils/util'; import { calPlayerCeAndSave as pubCalPlayerCeAndSave, reCalAllHeroCe } from '../pubUtils/playerCe'; -import { HeroType } from '../db/Hero'; +import Hero, { HeroType, HeroUpdate } from '../db/Hero'; import { defaultHeroes } from './pvpService'; +import { RoleUpdate } from '../db/Role'; //修改并下发战力 -export async function calPlayerCeAndSave(sid: string, roleId: string, heros: Array, type?: number, args?: Array) { - let {role, pushHeros, topLineupCe} = await pubCalPlayerCeAndSave(roleId, heros, type, args); +export async function calPlayerCeAndSave(type: number, sid: string, roleId: string, originHero: HeroType, update: HeroUpdate, args?: Array) { + let {role, pushHeros, topLineupCe, hero} = await pubCalPlayerCeAndSave(type, roleId, originHero, update, null, args); //下发战力 let uids = [{ uid: roleId, sid }]; pinus.app.get('channelService').pushMessageByUids('onPlayerCeUpdate', resResult(STATUS.SUCCESS, { ce: reduceCe(role.ce) , heros: pushHeros, topLineupCe: reduceCe(topLineupCe) }), uids); defaultHeroes(role); - return heros; + return hero; } -export async function calAllHeroCe(sid: string, roleId: string, type?:number, args?:Array) { - let {ce, pushHeros, topLineupCe }= await reCalAllHeroCe(roleId, type, args); +export async function calAllHeroCe(type:number, sid: string, roleId: string, update: RoleUpdate, args?:Array) { + let {role, ce, pushHeros, topLineupCe } = await reCalAllHeroCe(type, roleId, update, args); let uids = [{ uid: roleId, sid }]; pinus.app.get('channelService').pushMessageByUids('onPlayerCeUpdate', resResult(STATUS.SUCCESS, { ce: reduceCe(ce), heros: pushHeros, topLineupCe: reduceCe(topLineupCe) }), uids); - return {ce: reduceCe(ce)}; + return role; } \ No newline at end of file diff --git a/game-server/app/services/pvpService.ts b/game-server/app/services/pvpService.ts index 36787b48f..61a0878f9 100644 --- a/game-server/app/services/pvpService.ts +++ b/game-server/app/services/pvpService.ts @@ -5,7 +5,7 @@ import { PVP_HERO_POS, ROBOT_NAME, REDIS_KEY, PVP_CONST, HERO_CE_RATIO } from '. import { setPvpDefResult } from '../services/timeTaskService'; import { dicPvpOpponent, DicPvpOpponent } from "../pubUtils/dictionary/DicPvpOpponent"; import { getRandomIndexByLen, genCode, getRandomByLen, shouldRefresh, reduceCe, getChineseName } from '../pubUtils/util'; -import { oppPlayersInter, pvpEndParamInter, Attributes } from '../pubUtils/interface'; +import { oppPlayersInter, pvpEndParamInter } from '../pubUtils/interface'; import { RankParam } from '../domain/rank'; import { gameData, getPLvByScore } from "../pubUtils/data"; import { PVP } from '../pubUtils/dicParam'; @@ -14,7 +14,7 @@ import { setRank, getMyRank, getFieldByRank } from './redisService'; import { nowSeconds, checkTodayTime } from '../pubUtils/timeUtil'; import { HeroesRecord } from '../db/PvpRecord'; import { HeroModel, HeroType } from '../db/Hero'; -import { CeAttrNumber, CeAttr, CeAttrRole, MainAttrNumber } from '../domain/roleField/attribute'; +import { MainAttrNumber, Attribute, CeAttrData, CeAttrDataRole } from '../domain/roleField/attribute'; import { PvpEnemies, PvpHeroInfo, PvpOtherHeroes } from '../domain/dbGeneral'; import { DicWarJson } from '../pubUtils/dictionary/DicWarJson'; import { findWhere, findIndex } from 'underscore'; @@ -213,7 +213,7 @@ async function generPlayerOppHis(pvpdefense: PvpDefenseType, mapWarJson: DicWarJ let heroInfo = new PvpHeroInfo(); heroInfo.setHeroInfo(dbHero); heroInfo.setOutIndex(h.order); - let attribute = getPlayerAttribute(dbHero.ceAttr, role.globalCeAttr); + let attribute = getPlayerAttribute(dbHero.attr, role.attr); heroInfo.setAttribute(attribute); let enemy = new PvpEnemies(warJson, heroInfo, hs?hs.score: 0); heroes.push(enemy); @@ -491,14 +491,10 @@ export async function findPvpDefAllByRoleId(roleId: string) { * @param enemyCe 出兵表对手战力 * @param ratio 系数 */ -export function getRobotAttribute(attribute: Attributes, ce: number, enemyCe: number, ratio: number) { +export function getRobotAttribute(attribute: {id: number, val: number}[], ce: number, enemyCe: number, ratio: number) { - let newAttribute = new CeAttrNumber(); - for(let attrName in newAttribute) { - newAttribute[attrName] = Math.floor(attribute[attrName] * ce / enemyCe * ratio); - } - newAttribute['speed'] = 0; - newAttribute['ap'] = 0; + let newAttribute = new Attribute(); + newAttribute.setByWarJson(attribute, ce / enemyCe * ratio) return newAttribute; } @@ -508,16 +504,9 @@ export function getRobotAttribute(attribute: Attributes, ce: number, enemyCe: nu * @param ceAttr hero表的ceAttr * @param globalCeAttr role表中的globalCeAttr */ -export function getPlayerAttribute(ceAttr: CeAttr, globalCeAttr: CeAttrRole) { - let newAttribute = new CeAttrNumber(); - for(let attrName in newAttribute) { - let { base, ratioUp, fixUp, equipUp } = ceAttr[attrName]; - let { ratioUp: ratioUp2, fixUp: fixUp2 } = globalCeAttr[attrName]; - let result = base * ( HERO_CE_RATIO + ratioUp + ratioUp2) + (fixUp + fixUp2 + equipUp) * HERO_CE_RATIO; - newAttribute[attrName] += reduceCe(result); - } - newAttribute['speed'] = 0; - newAttribute['ap'] = 0; +export function getPlayerAttribute(heroAttrs: CeAttrData[], roleAttrs: CeAttrDataRole[]) { + let newAttribute = new Attribute(); + newAttribute.setByDbData(roleAttrs, heroAttrs); return newAttribute; } @@ -527,8 +516,8 @@ export function getPlayerAttribute(ceAttr: CeAttr, globalCeAttr: CeAttrRole) { * @param ceAttr * @param globalCeAttr */ -export function getPlayerMainAttribute(ceAttr: CeAttr, globalCeAttr: CeAttrRole) { - let attribute = getPlayerAttribute(ceAttr, globalCeAttr); +export function getPlayerMainAttribute(heroAttrs: CeAttrData[], roleAttrs: CeAttrDataRole[]) { + let attribute = getPlayerAttribute(heroAttrs, roleAttrs); let mainAttributes = new MainAttrNumber(attribute); return mainAttributes; diff --git a/game-server/app/services/rewardService.ts b/game-server/app/services/rewardService.ts index 078c687af..375309d60 100644 --- a/game-server/app/services/rewardService.ts +++ b/game-server/app/services/rewardService.ts @@ -156,7 +156,7 @@ export async function addItems(roleId: string, roleName: string, sid: string, go } } if (!!skinInfos.length) { - calAllHeroCe(sid, roleId, HERO_SYSTEM_TYPE.ADD_SKIN, addSkinIds) + calAllHeroCe(HERO_SYSTEM_TYPE.ADD_SKIN, sid, roleId, {}, addSkinIds); pinus.app.get('channelService').pushMessageByUids('onHeroSkinChange', resResult(STATUS.SUCCESS, {skinInfos}), uids); } return showItems; diff --git a/game-server/app/services/roleService.ts b/game-server/app/services/roleService.ts index 8be3c531c..b8f2c0f64 100644 --- a/game-server/app/services/roleService.ts +++ b/game-server/app/services/roleService.ts @@ -3,44 +3,47 @@ import { Channel } from 'pinus'; import { getRandNum, getRandomArr } from '../pubUtils/util'; import { TERAPH_RANDOM } from "../consts/consts"; import { indexOf } from 'underscore'; +import { DicTeraph } from '../pubUtils/dictionary/DicTeraph'; +import { Teraph } from '../db/Role'; const TERAPH_STRENGTHEN = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; /** * 计算强化次数和消耗 * @param count 强化次数 - * @param attrNames 可以强化的属性名字 + * @param attrs 可以强化的属性名字 * @param teraphInfo 字典表对应的神像信息 - * @param teraph + * @param teraph 数据库内单个神像信息 */ -export function checkTeraphMaterialEnough(count: number, attrNames:Array, teraphInfo: any, teraph: any) { - let res = {}; +export function checkTeraphMaterialEnough(count: number, attrs:number[], teraphInfo: DicTeraph, teraph: Teraph) { let consumes = []; let times = 0; if (count < 10) { for (let i = 0; i < count; i++) { - if (!attrNames.length) { + if (!attrs.length) { break; } - let num = getRandNum(TERAPH_RANDOM.MIN, TERAPH_RANDOM.MAX); - let arr = getRandomArr(attrNames, num) + let num = getRandNum(TERAPH_RANDOM.MIN, TERAPH_RANDOM.MAX); // 强化时随机增加 2-4 属性 + let arr: number[] = getRandomArr(attrs, num); // 随机出的属性id let critical = getRandNum(0, 100);//属性暴击率 - let criEffect = 1; + let criEffect = 1; // 暴击效果 if (critical <= teraphInfo.criRate) criEffect = teraphInfo.criEffect; - for (let attrName of arr) { - let attrNameMax = attrName+'Max'; - res[attrName] = teraphInfo[attrName] * criEffect; - if (teraph[attrName] + res[attrName] > teraphInfo[attrNameMax]) { - res[attrName] = teraphInfo[attrNameMax] - teraph[attrName]; - let attrIndex = indexOf(attrNames, attrName); - attrNames.splice(attrIndex, 1); + for (let attrId of arr) { + let val = teraph.attr.get(attrId); // 已有的强化值 + val += teraphInfo.mainAttrUp.get(attrId) * criEffect; + let max = teraphInfo.mainAttrMax.get(attrId); + if(val > max) { + val = max; + let attrIndex = attrs.indexOf(attrId); + attrs.splice(attrIndex, 1); } + teraph.attr.set(attrId, val); } times++; } } else if (count == 10){ let criticalArrTimes = getRandomArr(TERAPH_STRENGTHEN, 2);//10次中随机2次发生暴击 for (let item of TERAPH_STRENGTHEN) { - if (!attrNames.length) { + if (!attrs.length) { break; } let criEffect = 1; @@ -49,24 +52,27 @@ export function checkTeraphMaterialEnough(count: number, attrNames:Array, t criEffect = teraphInfo.criEffect;//本次是暴击 item 在 criticalArrTimes 中 } let num = getRandNum(TERAPH_RANDOM.MIN, TERAPH_RANDOM.MAX); - let arr = getRandomArr(attrNames, num); - for (let attrName of arr) { - res[attrName] = (res[attrName]||0) + teraphInfo[attrName] * criEffect; - let attrNameMax = attrName+'Max'; - if (teraph[attrName] + res[attrName] > teraphInfo[attrNameMax]) { - res[attrName] = teraphInfo[attrNameMax] - teraph[attrName]; - let attrIndex = indexOf(attrNames, attrName); - attrNames.splice(attrIndex, 1); + let arr: number[] = getRandomArr(attrs, num); + for (let attrId of arr) { + let val = teraph.attr.get(attrId); // 已有的强化值 + val += teraphInfo.mainAttrUp.get(attrId) * criEffect; + let max = teraphInfo.mainAttrMax.get(attrId); + + if(val > max) { + val = max; + let attrIndex = attrs.indexOf(attrId); + attrs.splice(attrIndex, 1); } + teraph.attr.set(attrId, val); } times++; } } //计算消耗 for (let {id, count} of teraphInfo.upMaterial) { - consumes.push({ id, count: count*times}); + consumes.push({ id, count: count * times}); } - return {attr: res, consumes}; + return { consumes}; } /** * diff --git a/gm-server/app/service/Utils.ts b/gm-server/app/service/Utils.ts index 4ea97eff2..ede7cfa21 100644 --- a/gm-server/app/service/Utils.ts +++ b/gm-server/app/service/Utils.ts @@ -2,8 +2,6 @@ import { Service } from 'egg'; import { addSkins, addBags, addEquips } from '@pubUtils/itemUtils'; import * as pubUtils from '@pubUtils/util'; import * as pubGamedata from '@pubUtils/gamedata' -import { HeroType } from '@db/Hero'; -import { calPlayerCeAndSave } from '@pubUtils/playerCe'; import { BagInter, EquipInter } from '@pubUtils/interface'; const csprng = require('csprng'); @@ -47,10 +45,6 @@ export default class Utils extends Service { return pubUtils.resResult(status, data, customMsg); } - public calPlayerCeAndSave(roleId: string, heros: HeroType[], type: number, args: number[]) { - return calPlayerCeAndSave(roleId, heros, type, args) - } - public addSkins(roleId: string, id: number) { return addSkins(roleId, id); } diff --git a/gm-server/app/service/users.ts b/gm-server/app/service/users.ts index 111fc2ead..3d34079ec 100644 --- a/gm-server/app/service/users.ts +++ b/gm-server/app/service/users.ts @@ -24,7 +24,7 @@ import { STATUS, HERO_SYSTEM_TYPE } from '@consts'; import { ITID, COUNTER } from '@consts'; import { ItemModel } from '@db/Item'; import { gameData, getHeroExpByLv } from '@pubUtils/data'; -import { calPlayerCeAndSave, calculatetopLineup, calEquipSeids } from '@pubUtils/playerCe'; +import { calPlayerCeAndSave, calculatetopLineup, calEquipSeids, initRoleAtrr } from '@pubUtils/playerCe'; import { SchoolModel } from '@db/School'; import { CeAttrNumber } from '@domain/roleField/attribute'; import { smsModel } from '@db/Sms'; @@ -267,7 +267,7 @@ export default class GMUsers extends Service { try { for(let heroInfo of heroInfos) { let hero = await HeroModel.createHero(heroInfo); - await calPlayerCeAndSave(heroInfo.roleId, [hero], HERO_SYSTEM_TYPE.INIT); + await calPlayerCeAndSave(HERO_SYSTEM_TYPE.INIT, heroInfo.roleId, hero, {}); } return ctx.service.utils.resResult(STATUS.SUCCESS, { uids }); } catch(e) { @@ -540,9 +540,9 @@ export default class GMUsers extends Service { let hero = await HeroModel.findByHidAndRole(equip.hid, roleId); let index = hero.ePlace.findIndex(cur => cur.id == equip.ePlaceId); if (index < 0) continue; - hero.ePlace[index].equip = null; let args = calEquipSeids(hero); - await calPlayerCeAndSave(roleId, [hero], HERO_SYSTEM_TYPE.EQUIP, args); + hero.ePlace[index].equip = null; + await calPlayerCeAndSave(HERO_SYSTEM_TYPE.EQUIP, roleId, hero, {}, null, args); } seqIds.push(seqId); } @@ -617,8 +617,7 @@ export default class GMUsers extends Service { let hero = await HeroModel.findByHidAndRole(hid, roleId); console.log(hid, roleId, !!hero); if(!hero) continue; - hero.lv = hlv; - await calPlayerCeAndSave(roleId, [hero], HERO_SYSTEM_TYPE.LVUP, [hid]); + await calPlayerCeAndSave(HERO_SYSTEM_TYPE.LVUP, roleId, hero, {lv: hlv}); } return ctx.service.utils.resResult(STATUS.SUCCESS); diff --git a/shared/consts/constModules/abilityConst.ts b/shared/consts/constModules/abilityConst.ts index 63f1785b5..7776c409e 100644 --- a/shared/consts/constModules/abilityConst.ts +++ b/shared/consts/constModules/abilityConst.ts @@ -4,9 +4,6 @@ * 属性 id */ - -import { JOB_TYPE } from ".."; - export enum ABI_TYPE{ /**生命 */ ABI_HP = 1, @@ -41,12 +38,33 @@ export enum ABI_TYPE{ ABI_DEF_IGNORE = 15, /**吸血等级 */ ABI_BLOOD_SUCK = 16, - /**怒气 */ + /**怒气恢复效果 */ ABI_AP = 17, + /**暴击伤害 */ + ABI_DAMAGE_CRI = 18, ABI_MAX, } +// 主属性 +export const ABI_TYPE_MAIN = [ + ABI_TYPE.ABI_HP, + ABI_TYPE.ABI_ATK, + ABI_TYPE.ABI_DEF, + ABI_TYPE.ABI_MDEF +]; + +// 次级属性 +export const ABI_TYPE_SUB = [ + ABI_TYPE.ABI_HIT, + ABI_TYPE.ABI_CRI, + ABI_TYPE.ABI_FLEE, + ABI_TYPE.ABI_ANT_CRI, + ABI_TYPE.ABI_DAMAGE_INCREASE, + ABI_TYPE.ABI_DAMAGE_DECREASE, + ABI_TYPE.ABI_DEF_IGNORE, + ABI_TYPE.ABI_DAMAGE_CRI +]; export enum SEID_TYPE { /**属性固定值加成(数值) */ @@ -63,39 +81,10 @@ export enum ABI_STAGE { ATK = 2, DEF = 3, MDEF = 4, - AGI = 5, - LUK = 6, - END = 6 + END = 4 } export const ATTR = {} -//武将训练等级 -export const HEROTARIN = { - 1: "hp", - 2: "atk", - 3: "def", - 4: "mdef", - 5: "agi", - 6: "luk" -}; -//战力系数 -export const CE_RATIO = { - "hp" : 1, - "atk" : 2, - "matk": 2, - "def": 2, - "mdef": 2, - "agi": 2, - "luk": 0, - "hit": 0, - "cri": 0, - "flee": 0, - "antCri": 0, - "damageIncrease": 0, - "damageDecrease": 0, - "defIngnore": 0, - "bloodSuck": 0, -}; export const HERO_ATTR = { 1: "hp", // 生命 @@ -114,44 +103,30 @@ export const HERO_ATTR = { 14: "damageDecrease", // 伤害减免等级 15: "defIngnore", // 忽视防御等级 16: "bloodSuck", // 吸血等级 - 17: "ap" // 怒气 + 17: "damageCri", // 暴击伤害 + 18: "ap" // 暴击伤害 }; -export const JEWEL_ATTR = { - 1: "hp", - 2: "atk", - 3: "def", - 4: "mdef", - 5: "agi", - 6: "luk" -} -const BASE_ATTR = { - 'hp' : 1 , - 'atk' : 2, - 'def' : 3, - 'mdef' : 4 -} -export const ABI_TYPE_TO_STAGE = new Map number)>([ +export const ABI_TYPE_TO_STAGE = new Map([ [ABI_STAGE.HP, ABI_TYPE.ABI_HP], - [ABI_STAGE.ATK, (jobType:number) => { return jobType == JOB_TYPE.PHYSIC?ABI_TYPE.ABI_ATK: ABI_TYPE.ABI_MATK}], + [ABI_STAGE.ATK, ABI_TYPE.ABI_ATK], [ABI_STAGE.DEF, ABI_TYPE.ABI_DEF], - [ABI_STAGE.MDEF, ABI_TYPE.ABI_MDEF], - [ABI_STAGE.AGI, ABI_TYPE.ABI_AGI], - [ABI_STAGE.LUK, ABI_TYPE.ABI_LUK] + [ABI_STAGE.MDEF, ABI_TYPE.ABI_MDEF] ]); export function getAtrrNameById(attrId: number):string { return HERO_ATTR[attrId]; }; -export function getAttrCeRatio(attr: string):number { - return CE_RATIO[attr]; -}; - -export function getAttrNameByJobStage(jobStage: number) { - return HEROTARIN[jobStage]; -}; - -export function getTeraphAttr() { - return BASE_ATTR; -}; +export enum CE_CONST { + FLEE_VALUE = 0.3, // 格挡价值 + PUT_HIT = 50000, // 投放总命中 + HIT_RATE_BASE = 0.75, // 命中率基础 + HIT_RATE_MAX = 1, // 命中率上限 + HIT_RATE_MIN = 0, // 命中率下限 + PUT_ANT_CRI = 50000, // 投放总抗暴 + CRI_RATE_BASE = 0.05, // 暴击率基础 + CRI_RATE_MAX = 0.75, // 暴击率上限 + CRI_RATE_MIN = 0.05, // 暴击率下限 + CRI_VALUE_BASE = 1.5, // 暴击价值基础 +} \ No newline at end of file diff --git a/shared/consts/constModules/calcuConst.ts b/shared/consts/constModules/calcuConst.ts index e239a140a..f0c819380 100644 --- a/shared/consts/constModules/calcuConst.ts +++ b/shared/consts/constModules/calcuConst.ts @@ -14,7 +14,3 @@ export const GOLD_COST_RATIO = { "DAILY_REF_NUM": { "A": 50, "B": 0 }, // 每日购买次数花费 "DUNGRON_BUY_NUM": { "A": 0, "B": 50 } // 秘境购买次数花费 } - -export const EXPRESSION = { - "CE": "1*hp+2*atk+2*matk+2*def+2*mdef+2*agi+2*luk+0*hit+0*cri+0*flee+0*antCri+0*damageIncrease+0*damageDecrease+0*defIngnore+0*bloodSuck" -} diff --git a/shared/consts/constModules/heroConst.ts b/shared/consts/constModules/heroConst.ts index 35518b705..efb947bab 100644 --- a/shared/consts/constModules/heroConst.ts +++ b/shared/consts/constModules/heroConst.ts @@ -18,7 +18,9 @@ export const HERO_SYSTEM_TYPE = { ADD_SKIN: 15, SCHOOL: 16, SCROLL: 17, - TITLE:18, + TITLE: 18, + TERAPH: 19, + TERAPH_UP: 20 }; // 武将上限 @@ -36,4 +38,6 @@ export const JOB_TYPE = { } // 武将战力放大系数 -export const HERO_CE_RATIO = 100; \ No newline at end of file +export const HERO_CE_RATIO = 100; +// 次级属性放大系数 +export const HERO_SUB_ATTR_RATIO = 1000; \ No newline at end of file diff --git a/shared/db/Equip.ts b/shared/db/Equip.ts index 9d16b7f53..59671d852 100644 --- a/shared/db/Equip.ts +++ b/shared/db/Equip.ts @@ -94,7 +94,7 @@ export default class Equip extends BaseModel { return equip; } - public static async putOn(hid: number, equipId: string, lean = true) { + public static async putOnOrOff(equipId: string, hid: number, lean = true) { const equip: EquipType = await EquipModel.findOneAndUpdate({ _id: equipId }, { hid }, { new: true }).lean(lean); return equip; } diff --git a/shared/db/Hero.ts b/shared/db/Hero.ts index 3c0d78279..a7e8bb39c 100644 --- a/shared/db/Hero.ts +++ b/shared/db/Hero.ts @@ -1,5 +1,5 @@ import BaseModel from './BaseModel'; -import { CeAttr } from '../domain/roleField/attribute'; +import { CeAttrData } from '../domain/roleField/attribute'; import { index, getModelForClass, prop, Ref, mongoose, DocumentType } from '@typegoose/typegoose'; import Equip, { } from './Equip'; import { CounterModel } from './Counter'; @@ -11,7 +11,7 @@ import { reduceCe } from '../pubUtils/util'; * 英雄表 */ -class Connect { +export class Connect { @prop({ required: true }) shipId: number; @prop({ required: true }) @@ -51,31 +51,6 @@ function getInitialEplace() { return ePlace; } -interface heroUpdate { - exp?: number; - lv?: number; - ce?: number; - star?: number; - starStage?: number; - colorStar?: number; - colorStarStage?: number; - quality?: number; - job?:number; - jobStage?:number; - favour?:number; - favourLv?:number; - skins?: Skin[]; - connections?: Connect[]; - ePlace?:EPlace[]; - _id?:number; - scrollActive?: boolean; - scrollId?: number; - scrollStar?: number; - scrollColorStar?: number; - scrollQuality?: number; - historyCe?: number; -} - @index({ roleId: 1, hid: 1 }) @index({ roleId: 1, seqId: 1 }) export default class Hero extends BaseModel { @@ -102,8 +77,8 @@ export default class Hero extends BaseModel { ce: number; // 武将战力 @prop({ required: true, default: 0 }) historyCe: number; // 武将历史最高战力 - @prop({required: true, default: new CeAttr(), _id: false }) - ceAttr: CeAttr; // 影响战力的属性 + @prop({required: true, type: CeAttrData, default: [], _id: false }) + attr: CeAttrData[]; // 影响战力的属性 @prop({ required: true, default: 1 }) star: number; // 星级 @@ -181,10 +156,21 @@ export default class Hero extends BaseModel { public static async addEquip(roleId: string, hid: number, ePlaceId: number, equipId: string, lean = true) { const hero: HeroType = await HeroModel.findOneAndUpdate( { roleId, hid, 'ePlace.id': ePlaceId }, - {$set: {'ePlace.$.equip': equipId, 'ePlace.$.hid':hid, 'ePlace.$.ePlaceId':ePlaceId}}, + {$set: { 'ePlace.$.equip': equipId }}, {new: true}).populate('ePlace.equip').lean(lean); if (hero) { - await Equip.putOn(hero.hid, equipId); + await Equip.putOnOrOff( equipId, hero.hid ); + } + return hero; + } + + public static async removeEquip(roleId: string, hid: number, ePlaceId: number, equipId: string, lean = true) { + const hero: HeroType = await HeroModel.findOneAndUpdate( + { roleId, hid, 'ePlace.id': ePlaceId }, + {$set: {'ePlace.$.equip': null}}, + {new: true}).populate('ePlace.equip').lean(lean); + if (hero) { + await Equip.putOnOrOff( equipId, 0 ); } return hero; } @@ -238,7 +224,7 @@ export default class Hero extends BaseModel { return result; } - public static async updateHeroInfo(roleId: string, hid:number, heroUpdate:heroUpdate, select?: string, lean = true) { + public static async updateHeroInfo(roleId: string, hid:number, heroUpdate:HeroUpdate, select?: string, lean = true) { delete heroUpdate._id; let result: HeroType = await HeroModel.findOneAndUpdate({roleId, hid}, {$set:heroUpdate}, {new: true}).select(select).lean(lean); return result; @@ -270,3 +256,4 @@ export default class Hero extends BaseModel { export const HeroModel = getModelForClass(Hero); export interface HeroType extends Pick, keyof Hero>{}; +export type HeroUpdate = Partial; // 将所有字段变成可选项 diff --git a/shared/db/Role.ts b/shared/db/Role.ts index 388eec6e5..027a9d383 100644 --- a/shared/db/Role.ts +++ b/shared/db/Role.ts @@ -1,6 +1,6 @@ -import { HANG_UP_CONSTS, ROLE_TERAPH, ROLE_SELECT } from './../consts'; +import { HANG_UP_CONSTS, ROLE_TERAPH, ROLE_SELECT, ABI_TYPE } from './../consts'; import BaseModel from './BaseModel'; -import { CeAttrRole } from '../domain/roleField/attribute'; +import { CeAttrDataRole } from '../domain/roleField/attribute'; import { index, getModelForClass, prop, DocumentType, Ref, mongoose } from '@typegoose/typegoose'; import User from './User'; import { shouldRefresh, reduceCe } from '../pubUtils/util'; @@ -41,37 +41,47 @@ export class WarStar { star: number; // 星级 } -class Teraph{ +export class Teraph{ @prop({ required: true, default: 1 }) id: number; // 神像的id @prop({ required: true, default: 1 }) - grade: number; // 等级 + grade: number = 1; // 等级 @prop({ required: true, default: 0 }) - hp: number; + hp: number = 0; @prop({ required: true, default: 0 }) - atk: number; + atk: number = 0; @prop({ required: true, default: 0 }) - def: number; + def: number = 0; @prop({ required: true, default: 0 }) - mdef: number; - @prop({ required: true, default: 0 }) - agi: number; - @prop({ required: true, default: 0 }) - luk: number; + mdef: number = 0; + + constructor(id: number) { + this.id = id; + } + + public get attr() { + let map = new Map(); + map.set(ABI_TYPE.ABI_HP, this.hp); + map.set(ABI_TYPE.ABI_ATK, this.atk); + map.set(ABI_TYPE.ABI_DEF, this.def); + map.set(ABI_TYPE.ABI_MDEF, this.mdef); + return map + } + + public set attr(value: Map) { + value.forEach((val, id) => { + if(id == ABI_TYPE.ABI_HP) this.hp = val; + if(id == ABI_TYPE.ABI_ATK) this.atk = val; + if(id == ABI_TYPE.ABI_DEF) this.def = val; + if(id == ABI_TYPE.ABI_MDEF) this.mdef = val; + }); + } } // 初始化 function getInitialTeraph() { let teraphs = new Array(); for(let i = ROLE_TERAPH.START; i <= ROLE_TERAPH.END; i++) { - let p = new Teraph(); - p.id = i; - p.grade = 1; - p.hp = 0; - p.atk = 0; - p.def = 0; - p.mdef = 0; - p.agi = 0; - p.luk = 0; + let p = new Teraph(i); teraphs.push(p); } return teraphs; @@ -114,8 +124,8 @@ export default class Role extends BaseModel { lv: number; // 主公等级 @prop({ required: true, default: 0, set: (val: number) => val, get: (val: number) => reduceCe(val) }) ce: number; // 总战力 - @prop({ required: true, default: new CeAttrRole(), _id: false }) - globalCeAttr: CeAttrRole; // 总战力 + @prop({ required: true, type: CeAttrDataRole, default: [], _id: false }) + attr: CeAttrDataRole[]; // 总战力 @prop({ required: true, default: 0, set: (val: number) => val, get: (val: number) => reduceCe(val) }) topLineupCe: number; // 最强x人战力 @prop({ required: true, type: TopHero, default: [], _id: false }) @@ -242,8 +252,8 @@ export default class Role extends BaseModel { * @param select 选取字段,来自 selectConst/ROLE * @param getters 是否使用get方法,如ce使用了自动缩小1w倍 */ - public static async findByRoleId(roleId: string, select?: string, getters = false) { - const role: RoleType = await RoleModel.findOne({ roleId }).select(select).lean({getters}); + public static async findByRoleId(roleId: string, select?: string, getters = false, virtuals = true) { + const role: RoleType = await RoleModel.findOne({ roleId }).select(select).lean({getters, virtuals}); return role; } @@ -252,9 +262,8 @@ export default class Role extends BaseModel { if (!user) return null; const doc = new RoleModel(); const update = Object.assign(doc.toJSON(), roleInfo, { userInfo: user, serverType: user.serverType, serverId }); - initRoleAtrr(update); const role: RoleType = await RoleModel.findOneAndUpdate({ 'userInfo.uid': uid, serverId }, update, { upsert: true, new: true }).lean(lean); - + initRoleAtrr(role); return role; } @@ -427,7 +436,7 @@ export default class Role extends BaseModel { return recs } - public static async updateRoleInfo(roleId: string, roleUpdate:roleUpdate, lean = true) { + public static async updateRoleInfo(roleId: string, roleUpdate:RoleUpdate, lean = true) { delete roleUpdate._id; let result: RoleType = await RoleModel.findOneAndUpdate({roleId}, {$set:roleUpdate}, {new: true}).lean(lean); return result; @@ -519,4 +528,4 @@ export default class Role extends BaseModel { export const RoleModel = getModelForClass(Role); export interface RoleType extends Pick, keyof Role>{}; -type roleUpdate = Partial; // 将所有字段变成可选项 +export type RoleUpdate = Partial; // 将所有字段变成可选项 diff --git a/shared/domain/dbGeneral.ts b/shared/domain/dbGeneral.ts index 58583484a..c621ea44d 100644 --- a/shared/domain/dbGeneral.ts +++ b/shared/domain/dbGeneral.ts @@ -1,7 +1,7 @@ import { prop } from '@typegoose/typegoose'; import { DicWarJson } from '../pubUtils/dictionary/DicWarJson'; import { HeroType } from '../db/Hero'; -import { CeAttrNumber } from './roleField/attribute'; +import { Attribute } from './roleField/attribute'; // 从玩家数据中覆盖warjson的部分字段 export class PvpHeroInfo { @@ -27,7 +27,7 @@ export class PvpHeroInfo { quality?: number = 0; // 品质 @prop({ required: true, _id: false }) - attribute?: CeAttrNumber; // 属性 + attribute?: Attribute; // 属性 setHeroInfo(hero: HeroType) { this.actorId = hero.hid; @@ -46,7 +46,7 @@ export class PvpHeroInfo { this.quality = quality; } - setAttribute(attribute: CeAttrNumber) { + setAttribute(attribute: Attribute) { this.attribute = attribute; } diff --git a/shared/domain/roleField/attribute.ts b/shared/domain/roleField/attribute.ts index f290fc096..99f20c12f 100644 --- a/shared/domain/roleField/attribute.ts +++ b/shared/domain/roleField/attribute.ts @@ -1,7 +1,10 @@ import { prop } from '@typegoose/typegoose'; +import { HERO_CE_RATIO, getAtrrNameById, CE_CONST, HERO_SUB_ATTR_RATIO } from '../../consts'; // hero表内属性基础格式 export class CeAttrData { + @prop({ required: true }) + id?: number = 0; @prop({ required: true }) base: number = 0; @prop({ required: true }) @@ -12,132 +15,128 @@ export class CeAttrData { equipUp: number = 0; } -// hero表全属性 -export class CeAttr { - @prop({ required: false, _id: false }) - hp?: CeAttrData = new CeAttrData(); - @prop({ required: false, _id: false }) - atk?: CeAttrData = new CeAttrData(); - @prop({ required: false, _id: false }) - matk?: CeAttrData = new CeAttrData(); - @prop({ required: false, _id: false }) - def?: CeAttrData = new CeAttrData(); - @prop({ required: false, _id: false }) - mdef?: CeAttrData = new CeAttrData(); - @prop({ required: false, _id: false }) - agi?: CeAttrData = new CeAttrData(); - @prop({ required: false, _id: false }) - luk?: CeAttrData = new CeAttrData(); - @prop({ required: false, _id: false }) - hit?: CeAttrData = new CeAttrData(); - @prop({ required: false, _id: false }) - cri?: CeAttrData = new CeAttrData(); - @prop({ required: false, _id: false }) - flee?: CeAttrData = new CeAttrData(); - @prop({ required: false, _id: false }) - antCri?: CeAttrData = new CeAttrData(); - @prop({ required: false, _id: false }) - damageIncrease?: CeAttrData = new CeAttrData(); - @prop({ required: false, _id: false }) - damageDecrease?: CeAttrData = new CeAttrData(); - @prop({ required: false, _id: false }) - defIngnore?: CeAttrData = new CeAttrData(); - @prop({ required: false, _id: false }) - bloodSuck?: CeAttrData = new CeAttrData(); -} - // role表属性格式 export class CeAttrDataRole { + @prop({ required: true }) + id?: number = 0; @prop({ required: true }) ratioUp: number = 0; @prop({ required: true }) fixUp: number = 0; } -// role表全属性 -export class CeAttrRole { - @prop({ required: false, _id: false }) - hp?: CeAttrDataRole = new CeAttrDataRole(); - @prop({ required: false, _id: false }) - atk?: CeAttrDataRole = new CeAttrDataRole(); - @prop({ required: false, _id: false }) - matk?: CeAttrDataRole = new CeAttrDataRole(); - @prop({ required: false, _id: false }) - def?: CeAttrDataRole = new CeAttrDataRole(); - @prop({ required: false, _id: false }) - mdef?: CeAttrDataRole = new CeAttrDataRole(); - @prop({ required: false, _id: false }) - agi?: CeAttrDataRole = new CeAttrDataRole(); - @prop({ required: false, _id: false }) - luk?: CeAttrDataRole = new CeAttrDataRole(); - @prop({ required: false, _id: false }) - hit?: CeAttrDataRole = new CeAttrDataRole(); - @prop({ required: false, _id: false }) - cri?: CeAttrDataRole = new CeAttrDataRole(); - @prop({ required: false, _id: false }) - flee?: CeAttrDataRole = new CeAttrDataRole(); - @prop({ required: false, _id: false }) - antCri?: CeAttrDataRole = new CeAttrDataRole(); - @prop({ required: false, _id: false }) - damageIncrease?: CeAttrDataRole = new CeAttrDataRole(); - @prop({ required: false, _id: false }) - damageDecrease?: CeAttrDataRole = new CeAttrDataRole(); - @prop({ required: false, _id: false }) - defIngnore?: CeAttrDataRole = new CeAttrDataRole(); - @prop({ required: false, _id: false }) - bloodSuck?: CeAttrDataRole = new CeAttrDataRole(); -} - -// 所有属性使用数字格式 -export class CeAttrNumber { - @prop({ required: false }) - hp?: number = 0; - @prop({ required: false }) - atk?: number = 0; - @prop({ required: false }) - matk?: number = 0; - @prop({ required: false }) - def?: number = 0; - @prop({ required: false }) - mdef?: number = 0; - @prop({ required: false }) - agi?: number = 0; - @prop({ required: false }) - luk?: number = 0; - @prop({ required: false }) - hit?: number = 0; - @prop({ required: false }) - cri?: number = 0; - @prop({ required: false }) - flee?: number = 0; - @prop({ required: false }) - antCri?: number = 0; - @prop({ required: false }) - damageIncrease?: number = 0; - @prop({ required: false }) - damageDecrease?: number = 0; - @prop({ required: false }) - defIngnore?: number = 0; - @prop({ required: false }) - bloodSuck?: number = 0; -} - // 主属性 export class MainAttrNumber { hp: number = 0; atk: number = 0; - matk: number = 0; def: number = 0; mdef: number = 0; - agi: number = 0; - luk: number = 0; - constructor(attr: CeAttrNumber) { + constructor(attr: Attribute) { if(attr.hp) this.hp = attr.hp; if(attr.atk) this.atk = attr.atk; if(attr.def) this.def = attr.def; if(attr.mdef) this.mdef = attr.mdef; - if(attr.agi) this.agi = attr.agi; - if(attr.luk) this.luk = attr.luk; + } +} + +export class Attribute { + @prop({ required: false }) + hp: number = 0; + @prop({ required: false }) + atk: number = 0; + @prop({ required: false }) + def: number = 0; + @prop({ required: false }) + mdef: number = 0; + @prop({ required: false }) + speed: number = 0; + @prop({ required: false }) + hit: number = 0; + @prop({ required: false }) + cri: number = 0; + @prop({ required: false }) + flee: number = 0; + @prop({ required: false }) + antCri: number = 0; + @prop({ required: false }) + damageIncrease: number = 0; + @prop({ required: false }) + damageDecrease: number = 0; + @prop({ required: false }) + defIngnore: number = 0; + @prop({ required: false }) + bloodSuck: number = 0; + @prop({ required: false }) + ap: number = 0; + @prop({ required: false }) + damageCri: number = 0; + + setByDbData(roleAttrs: CeAttrDataRole[], heroAttrs: CeAttrData[]) { + for(let { id, fixUp: roleFix, ratioUp: roleRatio } of roleAttrs) { + let attrName = getAtrrNameById(id); + let heroAttr = heroAttrs.find(heroAttr => heroAttr.id == id); + if(heroAttr) { + let { fixUp: heroFix, base: heroBase, ratioUp: heroRatio, equipUp: heroEquip } = heroAttr; + let value = this.calAttrValue(roleFix, roleRatio, heroBase, heroFix, heroRatio, heroEquip); + if(attrName in this) this[attrName] = value; + } else { + let value = this.calAttrValue(roleFix, roleRatio, 0, 0, 0, 0); + if(attrName in this) this[attrName] = value; + } + } + + for(let { id, base: heroBase, fixUp: heroFix, ratioUp: heroRatio, equipUp: heroEquip } of heroAttrs) { + let attrName = getAtrrNameById(id); + let roleAttr = roleAttrs.find(roleAttr => roleAttr.id == id); + if(!roleAttr) { + let value = this.calAttrValue(0, 0, heroBase, heroFix, heroRatio, heroEquip); + if(attrName in this) this[attrName] = value; + } + } + } + + setByWarJson( attributes: {id: number, val: number}[], ratio: number = 1) { + for(let {id, val} of attributes) { + let attrName = getAtrrNameById(id); + if(attrName in this) this[attrName] = Math.floor(val * ratio); + } + } + + private calAttrValue(roleFix: number = 0, roleRatio: number = 0, heroBase: number = 0, heroFix: number = 0, heroRatio: number = 0, heroEquip: number = 0) { + return (heroFix + heroEquip + roleFix) * HERO_CE_RATIO + heroBase * ( HERO_CE_RATIO + heroRatio + roleRatio ); + } + + private setSubAttrRatio() { + return { + hit: this.hit / HERO_SUB_ATTR_RATIO, + cri: this.cri / HERO_SUB_ATTR_RATIO, + flee: this.flee / HERO_SUB_ATTR_RATIO, + antCri: this.antCri / HERO_SUB_ATTR_RATIO, + damageIncrease: this.damageIncrease / HERO_SUB_ATTR_RATIO, + damageDecrease: this.damageDecrease / HERO_SUB_ATTR_RATIO, + defIngnore: this.defIngnore / HERO_SUB_ATTR_RATIO, + damageCri: this.damageCri / HERO_SUB_ATTR_RATIO + } + } + + public calCe() { + let { cri, flee, damageIncrease, damageDecrease, damageCri } = this.setSubAttrRatio(); + + let hitRate = CE_CONST.HIT_RATE_BASE + CE_CONST.PUT_HIT/2 - flee; // 命中率 + if(hitRate > CE_CONST.HIT_RATE_MAX) hitRate = CE_CONST.HIT_RATE_MAX; + if(hitRate < CE_CONST.HIT_RATE_MIN) hitRate = CE_CONST.HIT_RATE_MIN; + let fleeRate = 1 - hitRate; // 格挡率 + + let criRate = CE_CONST.CRI_RATE_BASE + cri - CE_CONST.PUT_ANT_CRI/2; + if(criRate > CE_CONST.CRI_RATE_MAX) criRate = CE_CONST.CRI_RATE_MAX; + if(criRate < CE_CONST.CRI_RATE_MIN) criRate = CE_CONST.CRI_RATE_MIN; + + let criValue = CE_CONST.CRI_VALUE_BASE + damageCri; + + let validHp = this.hp + (this.def + this.mdef) * 0.5 / ((1 - fleeRate * CE_CONST.FLEE_VALUE) * (1 - damageDecrease)); // 有效生命 + let validAtk = this.atk * hitRate * ( 1 + criRate * criValue) * ( 1 + damageIncrease); // 有效输出 + let ce = Math.floor(validHp * validAtk); + return ce > 0? ce: 1; } } \ No newline at end of file diff --git a/shared/pubUtils/data.ts b/shared/pubUtils/data.ts index d73617059..fa688f42a 100644 --- a/shared/pubUtils/data.ts +++ b/shared/pubUtils/data.ts @@ -35,7 +35,6 @@ import { dicTeraph } from './dictionary/DicTeraph'; import { dicSchool } from './dictionary/DicSchool'; import { dicSchoolRate } from './dictionary/DicSchoolRate'; import { dicHeroScroll, preHeroScroll } from './dictionary/DicHeroScroll'; -import { ABI_TYPE_TO_STAGE } from "../consts"; import { dicPvpOpponent } from './dictionary/DicPvpOpponent'; import { dicPvpTeamLevel } from './dictionary/DicPvpTeamLevel'; import { dicPvpRefreshConsume, maxPvpRefreshCnt } from './dictionary/DicPvpRefreshConsume'; @@ -58,6 +57,7 @@ import { dicArmyBossRank } from '../pubUtils/dictionary/DicArmyBossRank'; import { dicArmyDonate } from '../pubUtils/dictionary/DicArmyDonateBoxReward'; import { dicRoleFriend } from "./dictionary/DicRoleFriend"; import { dicRoleFriendLv } from "./dictionary/DicRoleFriendLv"; +import { Attribute } from "../domain/roleField/attribute"; export const gameData = { blurprtCompose: dicBlueprtCompose, @@ -213,7 +213,10 @@ export function getBossHpByWarId(warId: number) { warInfo.forEach(hero => { let { attribute, dataId, relation, actorId } = hero; if (relation === 2) { - const hp = attribute.hp||0; + let attrJson = new Attribute(); + attrJson.setByWarJson(attribute, 1); + + const hp = attrJson.hp||0; if (hp > 0) { bossHpArr.push({dataId, hp, actorId}); bossHpSum += hp; @@ -300,17 +303,6 @@ export function getScollByStar(quality: number, star: number, curQuality: number return heroScroll; } -// 根据存在升星表等的stage字段的id对应17维id -export 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); - } -} - export function getSuit(id: number) { const suitInfo = gameData.suit.get(id); return suitInfo; @@ -420,7 +412,7 @@ export function getArmyWishPoolBaseByLv(lv: number) { export function getFriendLvByExp(exp: number) { let resultLv = 1; - for(let [lv, {sum}] of gameData.roleFriendLv) { + for(let [lv, {sum}] of gameData.roleFriendLv.entries()) { resultLv = lv; if(exp < sum) break; } diff --git a/shared/pubUtils/dictionary/DicGoods.ts b/shared/pubUtils/dictionary/DicGoods.ts index 06c13debd..f3bf45fd7 100644 --- a/shared/pubUtils/dictionary/DicGoods.ts +++ b/shared/pubUtils/dictionary/DicGoods.ts @@ -152,12 +152,10 @@ function parseAbility(json) { let map = new Map(); map.set(ABI_TYPE.ABI_HP, json.hp||0); map.set(ABI_TYPE.ABI_ATK, json.atk||0); - map.set(ABI_TYPE.ABI_MATK, json.matk||0); map.set(ABI_TYPE.ABI_DEF, json.def||0); map.set(ABI_TYPE.ABI_MDEF, json.mdef||0); - map.set(ABI_TYPE.ABI_AGI, json.agi||0); - map.set(ABI_TYPE.ABI_LUK, json.luk||0); - map.set(ABI_TYPE.ABI_SPEED, json.speed||0); + map.set(ABI_TYPE.ABI_DAMAGE_INCREASE, json.damageIncrease||0); + map.set(ABI_TYPE.ABI_DAMAGE_DECREASE, json.damageDecrease||0); return map } @@ -165,12 +163,10 @@ function parseAbilityUp(json) { let map = new Map(); map.set(ABI_TYPE.ABI_HP, json.hp_up||0); map.set(ABI_TYPE.ABI_ATK, json.atk_up||0); - map.set(ABI_TYPE.ABI_MATK, json.matk_up||0); map.set(ABI_TYPE.ABI_DEF, json.def_up||0); map.set(ABI_TYPE.ABI_MDEF, json.mdef_up||0); - map.set(ABI_TYPE.ABI_AGI, json.agi_up||0); - map.set(ABI_TYPE.ABI_LUK, json.luk_up||0); - map.set(ABI_TYPE.ABI_SPEED, json.speed_up||0); + map.set(ABI_TYPE.ABI_DAMAGE_INCREASE, json.damageIncrease_up||0); + map.set(ABI_TYPE.ABI_DAMAGE_DECREASE, json.damageDecrease_up||0); return map } diff --git a/shared/pubUtils/dictionary/DicHeroScroll.ts b/shared/pubUtils/dictionary/DicHeroScroll.ts index 7d5d0ba67..5d2b96e90 100644 --- a/shared/pubUtils/dictionary/DicHeroScroll.ts +++ b/shared/pubUtils/dictionary/DicHeroScroll.ts @@ -41,7 +41,5 @@ function parseCeAttr(elem) { ceAttr.set(ABI_STAGE.ATK, elem.atk); ceAttr.set(ABI_STAGE.DEF, elem.def); ceAttr.set(ABI_STAGE.MDEF, elem.mdef); - ceAttr.set(ABI_STAGE.AGI, elem.agi); - ceAttr.set(ABI_STAGE.LUK, elem.luk); return ceAttr; } \ No newline at end of file diff --git a/shared/pubUtils/dictionary/DicHeroStar.ts b/shared/pubUtils/dictionary/DicHeroStar.ts index 4fdec7f7b..0c5fc18f8 100644 --- a/shared/pubUtils/dictionary/DicHeroStar.ts +++ b/shared/pubUtils/dictionary/DicHeroStar.ts @@ -36,7 +36,6 @@ function parseCeAttr(elem) { ceAttr.set(ABI_STAGE.ATK, elem.atk_up); ceAttr.set(ABI_STAGE.DEF, elem.def_up); ceAttr.set(ABI_STAGE.MDEF, elem.mdef_up); - ceAttr.set(ABI_STAGE.AGI, elem.agi_up); - ceAttr.set(ABI_STAGE.LUK, elem.luk_up); return ceAttr; -} \ No newline at end of file +} +arr = undefined; \ No newline at end of file diff --git a/shared/pubUtils/dictionary/DicHeroWake.ts b/shared/pubUtils/dictionary/DicHeroWake.ts index 24e4e56f4..eb71b8523 100644 --- a/shared/pubUtils/dictionary/DicHeroWake.ts +++ b/shared/pubUtils/dictionary/DicHeroWake.ts @@ -40,7 +40,5 @@ function parseCeAttr(elem) { ceAttr.set(ABI_STAGE.ATK, elem.atk_up); ceAttr.set(ABI_STAGE.DEF, elem.def_up); ceAttr.set(ABI_STAGE.MDEF, elem.mdef_up); - ceAttr.set(ABI_STAGE.AGI, elem.agi_up); - ceAttr.set(ABI_STAGE.LUK, elem.luk_up); return ceAttr; } \ No newline at end of file diff --git a/shared/pubUtils/dictionary/DicJob.ts b/shared/pubUtils/dictionary/DicJob.ts index 7ed2a6749..32d83989e 100644 --- a/shared/pubUtils/dictionary/DicJob.ts +++ b/shared/pubUtils/dictionary/DicJob.ts @@ -1,6 +1,6 @@ // 兵种表 import {readJsonFile, parseNumberList, parseGoodStr} from '../util' -import { FILENAME } from '../../consts' +import { FILENAME, ABI_STAGE } from '../../consts' import { RewardInter } from '../interface'; const _ = require('lodash'); @@ -23,18 +23,8 @@ export interface DicJob { readonly trainingConsume: Array; // 升阶消耗 readonly upGradeConsume: Array; - // 生命训练提升 - readonly hp: number; - // 攻击力训练提升 - readonly atk: number; - // 防御力训练提升 - readonly def: number; - // 策防训练提升 - readonly mdef: number; - // 敏捷训练提升 - readonly agi: number; - // 幸运训练提升 - readonly luk: number; + // 每阶升级属性 + readonly ceAttr: Map } @@ -42,7 +32,7 @@ const str = readJsonFile(FILENAME.DIC_JOB); let arr = JSON.parse(str); type KeysEnum = { [P in keyof Required]: true }; -const DicJobKeys: KeysEnum = {jobid: true, name: true, grade: true, unlockLevel: true, job_class: true, type: true, seid: true,trainingConsume: true, upGradeConsume: true, hp: true, atk: true, def: true, mdef: true, agi: true, luk: true}; +const DicJobKeys: KeysEnum = {jobid: true, name: true, grade: true, unlockLevel: true, job_class: true, type: true, seid: true,trainingConsume: true, upGradeConsume: true, ceAttr: true}; export const dicJob = new Map(); export const jobClassMaxGrades = new Map(); @@ -52,6 +42,7 @@ arr.forEach(o => { o.seid = parseNumberList(o.seid); o.trainingConsume = parseGoodStr(o.trainingConsume); o.upGradeConsume = parseGoodStr(o.upGradeConsume); + o.ceAttr = parseCeAttr(o); dicJob.set(o.jobid, _.pick(o, Object.keys(DicJobKeys))); let jobClass = jobClassMaxGrades.get(o.job_class); if (!!jobClass && jobClass.grade < o.grade) { @@ -61,4 +52,13 @@ arr.forEach(o => { }); +function parseCeAttr(elem) { + let ceAttr = new Map(); + ceAttr.set(ABI_STAGE.HP, elem.hp); + ceAttr.set(ABI_STAGE.ATK, elem.atk); + ceAttr.set(ABI_STAGE.DEF, elem.def); + ceAttr.set(ABI_STAGE.MDEF, elem.mdef); + return ceAttr; +} + arr = undefined; \ No newline at end of file diff --git a/shared/pubUtils/dictionary/DicTeraph.ts b/shared/pubUtils/dictionary/DicTeraph.ts index 341ca53f6..2ab43df0a 100644 --- a/shared/pubUtils/dictionary/DicTeraph.ts +++ b/shared/pubUtils/dictionary/DicTeraph.ts @@ -1,6 +1,7 @@ // 物品表 import { decodeArrayListStr, readJsonFile, parseGoodStr } from '../util' -import { FILENAME} from '../../consts' +import { FILENAME, ABI_TYPE} from '../../consts' +import { RewardInter } from '../interface'; const _ = require('lodash'); export interface SpecialMaterial { @@ -13,25 +14,16 @@ export interface DicTeraph { readonly id: number; readonly index: number; readonly grade: number; - readonly hpMax: number; - readonly atkMax: number; - readonly defMax: number; - readonly mdefMax: number; - readonly agiMax: number; - readonly lukMax: number; - readonly hp; - readonly atk; - readonly def; - readonly mdef; - readonly agi; - readonly luk; - readonly criRate; - readonly criEffect; - readonly upMaterial:Array<{id: number, number: number}>; + readonly mainAttrMax: Map; // 最大强化加成 id => value 18围内的id + readonly mainAttrUp: Map; // 每次强化加成 id => value 18围内的id + + readonly criRate: number; + readonly criEffect: number; + readonly upMaterial:Array; - readonly assiAttrValue:Array<{id: number, number: number}>; - readonly upGradeMaterial:Array<{id: number, number: number}>; + readonly assiAttrValue:Map; // 次级属性 + readonly upGradeMaterial:Array; } const str = readJsonFile(FILENAME.DIC_TERAPH); @@ -42,18 +34,8 @@ const DicTeraphKeys: KeysEnum = { id: true, index: true, grade: true, - hpMax: true, - atkMax: true, - defMax: true, - mdefMax: true, - agiMax: true, - lukMax: true, - hp: true, - atk: true, - def: true, - mdef: true, - agi: true, - luk: true, + mainAttrMax: true, + mainAttrUp: true, criRate: true, criEffect: true, upMaterial: true, @@ -65,26 +47,38 @@ arr.forEach(o => { o.assiAttrValue = parseAttr(o.assiAttrValue); o.upGradeMaterial = parseGoodStr(o.upGradeMaterial); o.upMaterial = parseGoodStr(o.upMaterial); - o.hp = o.hpUp; - o.atk = o.atkUp; - o.def = o.defUp; - o.mdef = o.mdefUp; - o.agi = o.agiUp; - o.luk = o.lukUp; + o.mainAttrMax = parseMainAttrMax(o); + o.mainAttrUp = parseMainAttrUp(o); dicTeraph.set(o.index + '_' + o.grade, _.pick(o, Object.keys(DicTeraphKeys))); }); arr = undefined; function parseAttr(str: string) { - let result = new Array<{id: number, number: number}>(); + let result = new Map(); if(!str) return result; let decodeArr = decodeArrayListStr(str); for(let [id, number] of decodeArr) { if(isNaN(parseInt(id)) || isNaN(parseInt(number))) { throw new Error('data table format wrong'); } - result.push({id: parseInt(id), number: parseInt(number)}); + result.set(parseInt(id), parseInt(number)); } return result } + +function parseMainAttrMax(elem) { + let result = new Map(); + result.set(ABI_TYPE.ABI_HP, elem.hpMax); + result.set(ABI_TYPE.ABI_ATK, elem.atkMax); + result.set(ABI_TYPE.ABI_DEF, elem.defMax); + result.set(ABI_TYPE.ABI_MDEF, elem.mdefMax); +} + +function parseMainAttrUp(elem) { + let result = new Map(); + result.set(ABI_TYPE.ABI_HP, elem.hpUp); + result.set(ABI_TYPE.ABI_ATK, elem.atkUp); + result.set(ABI_TYPE.ABI_DEF, elem.defUp); + result.set(ABI_TYPE.ABI_MDEF, elem.mdefUp); +} \ No newline at end of file diff --git a/shared/pubUtils/dictionary/DicTitle.ts b/shared/pubUtils/dictionary/DicTitle.ts index 79047d65e..1e47f2dca 100644 --- a/shared/pubUtils/dictionary/DicTitle.ts +++ b/shared/pubUtils/dictionary/DicTitle.ts @@ -1,6 +1,6 @@ // 物品表 import { decodeArrayListStr, readJsonFile, parseGoodStr } from '../util' -import { FILENAME} from '../../consts' +import { FILENAME, ABI_STAGE, ABI_TYPE_TO_STAGE, ABI_TYPE} from '../../consts' const _ = require('lodash'); export interface SpecialMaterial { @@ -9,15 +9,10 @@ export interface SpecialMaterial { } export interface DicTitle { - // 等级 readonly id: number; - readonly hp: number; - readonly atk: number; - readonly def: number; - readonly mdef: number; - readonly agi: number; - readonly luk: number; - readonly assiAttrValue: Array<{id: number, number: number}>; + // 等级 + readonly mainAttrValue: Map; // id => value 这里的值是上一级的基础上增加的值 + readonly assiAttrValue: Map; // id => value // 等级现在 readonly lvLimited: number; // 升级消耗 @@ -30,18 +25,14 @@ let arr = JSON.parse(str); type KeysEnum = { [P in keyof Required]: true }; const DicTitleKeys: KeysEnum = { id: true, - hp: true, - atk: true, - def: true, - mdef: true, - agi: true, - luk: true, + mainAttrValue: true, assiAttrValue: true, lvLimited: true, material: true } export const dicTitle = new Map(); arr.forEach(o => { + o.mainAttrValue = parseMainAttr(o); o.assiAttrValue = parseAttr(o.assiAttrValue); o.material = parseGoodStr(o.material); dicTitle.set(o.id, _.pick(o, Object.keys(DicTitleKeys))); @@ -50,14 +41,23 @@ arr.forEach(o => { arr = undefined; function parseAttr(str: string) { - let result = new Array<{id: number, number: number}>(); + let result = new Map(); if(!str) return result; let decodeArr = decodeArrayListStr(str); - for(let [id, number] of decodeArr) { - if(isNaN(parseInt(id)) || isNaN(parseInt(number))) { + for(let [id, value] of decodeArr) { + if(isNaN(parseInt(id)) || isNaN(parseInt(value))) { throw new Error('data table format wrong'); } - result.push({id: parseInt(id), number: parseInt(number)}); + result.set(parseInt(id), parseInt(value)); } return result } + +function parseMainAttr(elem) { + let result = new Map(); + result.set(ABI_TYPE.ABI_HP, elem.hp); + result.set(ABI_TYPE.ABI_ATK, elem.atk); + result.set(ABI_TYPE.ABI_DEF, elem.def); + result.set(ABI_TYPE.ABI_MDEF, elem.mdef); + return result; +} \ No newline at end of file diff --git a/shared/pubUtils/dictionary/DicWarJson.ts b/shared/pubUtils/dictionary/DicWarJson.ts index 0d5a6a4a9..b3df59cb4 100644 --- a/shared/pubUtils/dictionary/DicWarJson.ts +++ b/shared/pubUtils/dictionary/DicWarJson.ts @@ -1,8 +1,5 @@ // 关卡表 import {decodeArrayListStr, readWarJsonFileList} from '../util' -import { ABI_TYPE } from '../../consts'; -import { Attributes } from '../interface'; - export interface DicWarJson { @@ -33,7 +30,7 @@ export interface DicWarJson { // 角色使用的AI类型 readonly initial_ai: number; // 属性 - readonly attribute: Attributes; + readonly attribute: {id: number, val: number}[]; // 武将技能 readonly skill: string; // 武将被动技能 @@ -63,55 +60,15 @@ readWarJsonFileList().forEach(str => { dicWarJson.set(warid, warjson); }) -function parseAttribute(str: string) { - - let attribute: Attributes = {}; - if(!str) return attribute; - - let arr = decodeArrayListStr(str); - for(let [id, value] of arr) { - if(isNaN(parseInt(id)) || isNaN(parseInt(value))) { +export function parseAttribute(str: string) { + let result = new Array<{ id: number, val: number }>(); + if (!str) return result; + let decodeArr = decodeArrayListStr(str); + for (let [id, val] of decodeArr) { + if (isNaN(parseInt(id)) || isNaN(parseInt(val))) { throw new Error('data table format wrong'); } - let _id = parseInt(id), _value = parseInt(value); - switch(_id) { - case ABI_TYPE.ABI_HP: - attribute.hp = _value; break; - case ABI_TYPE.ABI_ATK: - attribute.atk = _value; break; - case ABI_TYPE.ABI_MATK: - attribute.matk = _value; break; - case ABI_TYPE.ABI_DEF: - attribute.def = _value; break; - case ABI_TYPE.ABI_MDEF: - attribute.mdef = _value; break; - case ABI_TYPE.ABI_AGI: - attribute.agi = _value; break; - case ABI_TYPE.ABI_LUK: - attribute.luk = _value; break; - case ABI_TYPE.ABI_SPEED: - attribute.speed = _value; break; - case ABI_TYPE.ABI_HIT: - attribute.hit = _value; break; - case ABI_TYPE.ABI_CRI: - attribute.cri = _value; break; - case ABI_TYPE.ABI_FLEE: - attribute.flee = _value; break; - case ABI_TYPE.ABI_ANT_CRI: - attribute.antCri = _value; break; - case ABI_TYPE.ABI_DAMAGE_INCREASE: - attribute.damageIncrease = _value; break; - case ABI_TYPE.ABI_DAMAGE_DECREASE: - attribute.damageDecrease = _value; break; - case ABI_TYPE.ABI_DEF_IGNORE: - attribute.defIngnore = _value; break; - case ABI_TYPE.ABI_BLOOD_SUCK: - attribute.bloodSuck = _value; break; - case ABI_TYPE.ABI_AP: - attribute.ap = _value; break; - default: - break; - } + result.push({ id: parseInt(id), val: parseInt(val) }); } - return attribute -} \ No newline at end of file + return result +} diff --git a/shared/pubUtils/gamedata.ts b/shared/pubUtils/gamedata.ts index d53e14612..5d5dddd3c 100644 --- a/shared/pubUtils/gamedata.ts +++ b/shared/pubUtils/gamedata.ts @@ -373,8 +373,6 @@ function parseHeroStar() { ceAttr.set(ABI_STAGE.ATK, elem.atk_up); ceAttr.set(ABI_STAGE.DEF, elem.def_up); ceAttr.set(ABI_STAGE.MDEF, elem.mdef_up); - ceAttr.set(ABI_STAGE.AGI, elem.agi_up); - ceAttr.set(ABI_STAGE.LUK, elem.luk_up); heroStarList.set(`${elem.quality}_${elem.star}`,{ceAttr, ...elem}); } @@ -392,8 +390,6 @@ function parseHeroWake() { ceAttr.set(ABI_STAGE.ATK, elem.atk_up); ceAttr.set(ABI_STAGE.DEF, elem.def_up); ceAttr.set(ABI_STAGE.MDEF, elem.mdef_up); - ceAttr.set(ABI_STAGE.AGI, elem.agi_up); - ceAttr.set(ABI_STAGE.LUK, elem.luk_up); heroWakeList.set(`${elem.quality}_${elem.star}`,{ceAttr, ...elem}); } diff --git a/shared/pubUtils/interface.ts b/shared/pubUtils/interface.ts index 7228c5cf2..1e79f7769 100644 --- a/shared/pubUtils/interface.ts +++ b/shared/pubUtils/interface.ts @@ -1,31 +1,12 @@ // 一些通用的interface定义 +import { Attribute } from "../domain/roleField/attribute"; + export interface RewardInter { id: number; count: number; } - -export interface Attributes { - hp?: number; - atk?: number; - matk?: number; - def?: number; - mdef?: number; - agi?: number; - luk?: number; - speed?: number; - hit?: number; - cri?: number; - flee?: number; - antCri?: number; - damageIncrease?: number; - damageDecrease?: number; - defIngnore?: number; - bloodSuck?: number; - ap?: number; -} - export interface EquipInter { id: number; name: string; @@ -82,7 +63,7 @@ export interface oppHeroesDefenseInter { lv: number; // 等级 hide: number; // 是否隐藏 initial_ai: number; // ai类型 - attribute: Attributes; + attribute: Attribute; star: number; // 星级 skill: string|number; // 技能 seid: string; // 技能 diff --git a/shared/pubUtils/playerCe.ts b/shared/pubUtils/playerCe.ts index 202431d98..1bd217fa2 100644 --- a/shared/pubUtils/playerCe.ts +++ b/shared/pubUtils/playerCe.ts @@ -2,213 +2,284 @@ * 体力系统 */ -import { HERO_SYSTEM_TYPE, ABI_TYPE, JEWEL_ATTR } from '../consts'; +import { HERO_SYSTEM_TYPE, ABI_TYPE } 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 '../domain/roleField/attribute'; -import { getAttrNameByJobStage, getAttrCeRatio, getAtrrNameById, ABI_STAGE, SEID_TYPE } from '../consts'; -import { gameData, getJobByGradeAndClass, getHeroWakeByQuality, getHeroStarByQuality, getFriendShipById, getSchoolRateByStar, getScollByStar, getFieldByStage } from './data'; +import { HeroModel, HeroType, HeroUpdate } from '../db/Hero'; +import { RoleModel, RoleType, RoleUpdate } from '../db/Role'; +import { CeAttrData, CeAttrDataRole, Attribute } from '../domain/roleField/attribute'; +import { ABI_STAGE, SEID_TYPE } from '../consts'; +import { gameData, getJobByGradeAndClass, getHeroWakeByQuality, getHeroStarByQuality, getFriendShipById, getSchoolRateByStar, getScollByStar, getTeraph } 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 { ABI_TYPE_TO_STAGE, ABI_TYPE_MAIN } from '../consts/constModules/abilityConst' import { PvpDefenseModel } from '../db/PvpDefense'; const HERO_CE_RATIO = 100; import { findIndex } from 'underscore'; import { GuildModel } from '../db/Guild'; +import { DicJob } from './dictionary/DicJob'; -//战力计算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}} +// 修改并下发战力 +export async function calPlayerCeAndSave(type: number, roleId: string, originHero: HeroType, update: HeroUpdate, role?: RoleType, args?: Array) { + if(!role) role = await RoleModel.findByRoleId(roleId); + + let { attr: roleAttrs = [] } = role; + + let heroAttrs = calPlayerCe(originHero, update, type, args); // 根据操作计算attr的增加 + + let newAttr = new Attribute(); + newAttr.setByDbData(roleAttrs, heroAttrs); + let heroCe = newAttr.calCe(); // 计算最终战力 + let incCe = heroCe - originHero.ce; + + // 更新到武将 + update.attr = heroAttrs; + update.ce = heroCe; + if (originHero.historyCe < heroCe) update.historyCe = heroCe; + let hero = await HeroModel.updateHeroInfo(roleId, originHero.hid, update); // 更新武将 + + // 更新到角色 + let { topLineup, topLineupCe } = await calculatetopLineup(role, originHero.hid, heroCe, originHero._id); // 计算更新最强五人战力 + role = await RoleModel.updateRoleInfo(roleId, { ce: role.ce + incCe, topLineup, topLineupCe }); + + await PvpDefenseModel.updateCe(roleId, originHero.hid, heroCe); // 更新pvp防守阵战力 + await GuildModel.updateCe(roleId, incCe); // 公会更新战力 + + let pushHeros = new Array<{ hid: number, ce: number, incHeroCe: number }>(); + pushHeros.push({ + hid: originHero.hid, + ce: reduceCe(heroCe), + incHeroCe: reduceCe(incCe), + }); + return { pushHeros, role, topLineupCe, hero } +} + +//全局属性加成 +export async function reCalAllHeroCe(type: number, roleId: string, update: RoleUpdate, args?: Array) { + let role = await RoleModel.findByRoleId(roleId); + let heros = await HeroModel.findByRole(roleId); + + let roleAttrs = await reCalRoleAttr(type, heros, role, update, args); + if(!roleAttrs) return {pushHeros: [], ce: role.ce, topLineupCe: role.topLineupCe}; // 无加成 + + let pushHeros = new Array<{ hid: number, ce: number, incHeroCe: number }>(); + + let roleCe = 0; // 总战力加成 + for (let hero of heros) { + let { attr: heroAttrs } = hero; + let newAttr = new Attribute(); + newAttr.setByDbData(roleAttrs, heroAttrs); + let heroCe = newAttr.calCe(); // 计算最终战力 + + let incHeroCe = heroCe - hero.ce; + roleCe += heroCe; + pushHeros.push({ hid: hero.hid, ce: reduceCe(hero.ce), incHeroCe: reduceCe(incHeroCe) }); + await HeroModel.updateHeroInfo(roleId, hero.hid, { ce: heroCe }); + } + let { topLineup, topLineupCe } = await calculatetopLineup(role); // 计算更新最强五人战力 + + update.attr = roleAttrs; + update.ce = roleCe; + update.topLineup = topLineup; + update.topLineupCe = topLineupCe; + + role = await RoleModel.updateRoleInfo(roleId, update); + return { role, pushHeros, ce: role.ce, topLineupCe: role.topLineupCe } +} + +// 计算武将全局战力 +async function reCalRoleAttr(type: number, heros: Array, role: RoleType, update: RoleUpdate, args: Array) { + let { attr: roleAttrs } = role; + switch (type) { + case HERO_SYSTEM_TYPE.ADD_SKIN: + roleAttrs = calHeroAddSkin(role, args); + break; + case HERO_SYSTEM_TYPE.SCHOOL: + roleAttrs = calSchoolAddAttr(role, heros, args[0], args[1], args[2]); + break; + case HERO_SYSTEM_TYPE.SCROLL: + roleAttrs = calScrollAddAttr(role, heros, args[0]); + break; + case HERO_SYSTEM_TYPE.STAR: + case HERO_SYSTEM_TYPE.COLORSTAR: + case HERO_SYSTEM_TYPE.QUALITY: + roleAttrs = await calSchoolStarIncAttr(role, heros, type, args[0], args[1]); + break; + case HERO_SYSTEM_TYPE.TITLE: + roleAttrs = calTitle(role, update); + break; + case HERO_SYSTEM_TYPE.TERAPH: + roleAttrs = calTeraphMainAttr(role, update, args[0]); + break; + case HERO_SYSTEM_TYPE.TERAPH_UP: + roleAttrs = calTeraphAssistAttr(role, update, args[0]); + break; + } + + return roleAttrs; +} + +// 计算单个武将战力 +export function calPlayerCe(hero: HeroType, update: HeroUpdate, type: number, args: Array = []) { + let heroAttrs: CeAttrData[] = []; // {"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: 升的星盘 + heroAttrs = 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: 升的星盘 + heroAttrs = calHeroStarIncAttr(hero, update, type, addSeidList, removeSeidList); // args: 升的星盘 break; case HERO_SYSTEM_TYPE.TRAIN: - reIncAttr = calHeroTrainIncAttr(hero); + heroAttrs = calHeroTrainIncAttr(hero, update); break; case HERO_SYSTEM_TYPE.STAGEUP: - reIncAttr = calHeroJobStageUpIncAttr(hero, args, addSeidList, removeSeidList); + heroAttrs = calHeroJobStageUpIncAttr(hero, update, addSeidList, removeSeidList); break; case HERO_SYSTEM_TYPE.SKIN: - reIncAttr = calHeroWearSkinIncAttr(hero, args, addSeidList, removeSeidList); + heroAttrs = calHeroWearSkinIncAttr(hero, args[0], args[1], addSeidList, removeSeidList); break; case HERO_SYSTEM_TYPE.FAVOUR: - reIncAttr = calHeroFavourUpIncAttr(hero, args); + heroAttrs = calHeroFavourUpIncAttr(hero, update); break; case HERO_SYSTEM_TYPE.CONNECT: - reIncAttr = calHeroConectIncAttr(hero, args); + heroAttrs = calHeroConectIncAttr(hero, update, args[0]); break; case HERO_SYSTEM_TYPE.EQUIP: - reIncAttr = calEquipPutOnOffIncAttr(hero, args, addSeidList, removeSeidList); + heroAttrs = calEquipPutOnOffIncAttr(hero, args, addSeidList, removeSeidList); break; case HERO_SYSTEM_TYPE.EQUIP_BASE: - reIncAttr = calHeroEquipIncAttr(hero); + heroAttrs = calHeroEquipIncAttr(hero); break; case HERO_SYSTEM_TYPE.RESTRENGTHEN: - reIncAttr = calRestrengthenIncAttr(hero, args.shift(), args, addSeidList, removeSeidList); + heroAttrs = calRestrengthenIncAttr(hero, args.shift(), args, addSeidList, removeSeidList); break; case HERO_SYSTEM_TYPE.JEWEL_ON: - reIncAttr = calHeroCeWhenJewelOn(hero, args); + heroAttrs = calHeroCeWhenJewelOn(hero, args[0], args[1]); break; case HERO_SYSTEM_TYPE.JEWEL_OFF: - reIncAttr = calHeroCeWhenJewelOff(hero, args); + heroAttrs = calHeroCeWhenJewelOff(hero, args); break; case HERO_SYSTEM_TYPE.SCROLL: - reIncAttr = calHeroCeScrollIncAttr(hero, args[0], args[1]); + heroAttrs = calHeroCeScrollIncAttr(hero, update); 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; + addSeidEffect(heroAttrs, addSeidList, removeSeidList); // 处理加值 + + return heroAttrs; } -//修改并下发战力 -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 calculatetopLineup(role, hero.hid, hero.ce, hero._id); // 计算更新最强五人战力 - 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 { topLineup, topLineupCe } = role; - await RoleModel.updateRoleInfo(roleId, { globalCeAttr: role.globalCeAttr, ce: role.ce, topLineup, topLineupCe }); - await GuildModel.updateCe(roleId, incPlayerCe); - return { pushHeros, role, topLineupCe } -} - -export async function calculatetopLineup(role: RoleType, hid: number, ce: number, heroId: string) { +/** + * 计算最强阵容战力 + * @param role + * @param hid + * @param ce + * @param heroId + */ +export async function calculatetopLineup(role: RoleType, hid?: number, ce?: number, heroId?: string) { let topLineup = role?.topLineup || new Array(); - - topLineup.sort((a, b) => { return b.ce - a.ce }); // 0-6,最大-最小 - let index = topLineup.findIndex(cur => cur.hid == hid); - if(index != -1 && !heroId) { + if(!hid) { // 直接重新排 let heroes = await HeroModel.getTopHero(role.roleId, 6); topLineup = heroes.map(cur => { return { hid: cur.hid, ce: cur.ce, hero: cur._id } }); } else { - if (index == -1) { // 不在最强列表 - if (topLineup.length < 6) { // 不满6人 - topLineup.push({ hid, ce, hero: heroId }); - } else if (topLineup.length == 6) { - if (ce > topLineup[topLineup.length - 1].ce) { // 跻身最强6人 - topLineup.pop(); + topLineup.sort((a, b) => { return b.ce - a.ce }); // 0-6,最大-最小 + let index = topLineup.findIndex(cur => cur.hid == hid); + if(index != -1 && !heroId) { + let heroes = await HeroModel.getTopHero(role.roleId, 6); + topLineup = heroes.map(cur => { return { hid: cur.hid, ce: cur.ce, hero: cur._id } }); + } else { + if (index == -1) { // 不在最强列表 + if (topLineup.length < 6) { // 不满6人 topLineup.push({ hid, ce, hero: heroId }); + } else if (topLineup.length == 6) { + if (ce > topLineup[topLineup.length - 1].ce) { // 跻身最强6人 + topLineup.pop(); + topLineup.push({ hid, ce, hero: heroId }); + } + } else { + topLineup.splice(6, topLineup.length - 6); + } + } else { // 原来就是最强6人 + if (ce < topLineup[topLineup.length - 1].ce) { // 滑出最强 + let heroes = await HeroModel.getTopHero(role.roleId, 6); + topLineup = heroes.map(cur => { return { hid: cur.hid, ce: cur.ce, hero: cur._id } }); + } else { + topLineup[index].ce = ce; } - } else { - topLineup.splice(6, topLineup.length - 6); - } - } else { // 原来就是最强6人 - if (ce < topLineup[topLineup.length - 1].ce) { // 滑出最强 - let heroes = await HeroModel.getTopHero(role.roleId, 6); - topLineup = heroes.map(cur => { return { hid: cur.hid, ce: cur.ce, hero: cur._id } }); - } else { - topLineup[index].ce = ce; } } } - let topLineupCe = topLineup.reduce((pre, cur) => { return pre + cur.ce }, 0); - role.topLineup = topLineup; - role.topLineupCe = topLineupCe; - 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; + return { topLineup, topLineupCe }; } /** * - * @param hero HeroType 武将更新后的值 - * @param type number 类型 - * @param hid number 当前武将id - * @param args number[] 当升星时,一个参数,0-是否升了一星;当觉醒时,两个参数,0-是否升了一星,1-是否初次觉醒 - * @param addSeidList number[] 用于更新被动 - * @param removeSeidList number[] 用于更新被动 + * @param {HeroType} hero 武将数据 + * @param {number[]} addSeidList 用于更新被动 + * @param {number[]} removeSeidList 用于更新被动 */ -export function calHeroStarIncAttr(hero: HeroType, type: number, hid: number, args: number[], addSeidList: Array, removeSeidList: Array) { +export function calHeroInitIncAttr(hero: HeroType, addSeidList: Array, removeSeidList: Array) { + let originHero = new HeroModel(); + let heroAttrs = calHeroStarIncAttr(originHero, hero, HERO_SYSTEM_TYPE.INIT, addSeidList, removeSeidList); + let curSkin = hero.skins.find(cur => cur.enable); + heroAttrs = calHeroWearSkinIncAttr(hero, curSkin ? curSkin.id : 0, 0, addSeidList, removeSeidList, true); + heroAttrs = calHeroJobAttr(originHero, hero, addSeidList, removeSeidList); + return heroAttrs; +} + +/** + * 添加皮肤全局加成 + * @param args + * @param ceAttr + */ +function calHeroAddSkin(role: RoleType, skinIds: Array) { + let { attr: roleAttrs } = role; + + for (let id of skinIds) { + let addSkin = gameData.fashion.get(id); + for (let attr of addSkin.globalAttr) { + let fixUp = attr.number * HERO_CE_RATIO; + updateRoleAttr(roleAttrs, attr.id, { inc: { fixUp } }); + } + } + role.attr = roleAttrs; + return roleAttrs; +} + +/** + * 升星觉醒升品等 + * @param {HeroType} hero 武将更新前的值 + * @param {HeroUpdate} update 更新的值 + * @param {number} type 养成类型 + * @param {number[]} addSeidList 用于更新被动 + * @param {number[]} removeSeidList 用于更新被动 + */ +export function calHeroStarIncAttr(originHero: HeroType, update: HeroUpdate, type: 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 { hid, star: originStar, starStage: originStarStage, quality: originQuality, colorStar: originColorStar, colorStarStage: originColorStarStage, attr: heroAttrs, skins, lv } = originHero; + let { star = originStar, starStage = originStarStage, quality = originQuality, colorStar = originStarStage, colorStarStage = originColorStarStage } = update; - let res: CeAttr = {}; - if (hero.hid != hid) return res; - - const dicHero = gameData.hero.get(hero.hid); + const dicHero = gameData.hero.get(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 isFirstWake = colorStar > 0 && originColorStar <= 0; // 是否是初次觉醒 + const isUpStar = originStarStage + 1 != starStage; // 如果升星了starStage会变成0 + const dicStar = isWake ? getHeroWakeByQuality(dicHero.quality, originColorStar) : getHeroStarByQuality(quality, originStar); // 星级表 let stages = new Array(); // 需要升级的阶 @@ -217,51 +288,97 @@ export function calHeroStarIncAttr(hero: HeroType, type: number, hid: number, ar } else if (type == HERO_SYSTEM_TYPE.LVUP) { stages = getAllAttrStage(); } else if (type == HERO_SYSTEM_TYPE.STAR) { - stages = [args[0] ? ABI_STAGE.END : starStage]; + stages = [isUpStar ? ABI_STAGE.END : starStage]; } else if (type == HERO_SYSTEM_TYPE.QUALITY) { stages = getAllAttrStage(); } else if (type = HERO_SYSTEM_TYPE.COLORSTAR) { - if (args[1]) { // 首次觉醒 + if (isFirstWake) { // 首次觉醒 stages = getAllAttrStage(); } else { - stages.push(args[0] ? ABI_STAGE.END : hero.colorStarStage) + stages.push(isUpStar ? ABI_STAGE.END : colorStarStage); } } for (let stage of stages) { - let targetAttrId = getFieldByStage(stage, hero.job); // 转换为17维的属性id + let targetAttrId = ABI_TYPE_TO_STAGE.get(stage); // 转换为18维的属性id let heroAttr = dicHero.baseAbilityArr.get(targetAttrId); // 武将表hp等 let heroUpAttr = dicHero.baseAbilityUpArr.get(targetAttrId); // 武将表hp_up等 - let starUp = 0; + 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 newBase = (heroAttr + (lv - 1) * (heroUpAttr + starUp)) * HERO_CE_RATIO; + updateHeroAttr(heroAttrs, targetAttrId, { set: { base: newBase } }); } // 解锁技能 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) { + + curSeidList.forEach((seid, type) => { if (!preSeidList.has(type)) { addSeidList.push(seid, 0); } - } - for (let [type, seid] of preSeidList) { + }); + preSeidList.forEach((seid, type) => { if (!curSeidList.has(type)) { removeSeidList.push(seid, 0); } - } + }); - return res;//属性增量可以是多个 + originHero.attr = heroAttrs; + return heroAttrs;//属性增量可以是多个 } +type updateCeAttr = Partial; +function updateHeroAttr(heroAttrs: CeAttrData[], id: number, update: { inc?: updateCeAttr, set?: updateCeAttr }) { + let curAttr = heroAttrs.find(cur => cur.id == id); + if(!curAttr) { + curAttr = new CeAttrData(); + heroAttrs.push(curAttr); + } + if(update.inc) { + let { base, equipUp, fixUp, ratioUp } = update.inc; + if(base) curAttr.base += base; + if(equipUp) curAttr.equipUp += equipUp; + if(fixUp) curAttr.fixUp += fixUp; + if(ratioUp) curAttr.ratioUp += ratioUp; + } + if(update.set) { + let { base, equipUp, fixUp, ratioUp } = update.set; + if(base) curAttr.base = base; + if(equipUp) curAttr.equipUp = equipUp; + if(fixUp) curAttr.fixUp = fixUp; + if(ratioUp) curAttr.ratioUp = ratioUp; + } +} + +type updateCeAttrRole = Partial; +function updateRoleAttr(roleAttrs: CeAttrDataRole[], id: number, update: { inc?: updateCeAttrRole, set?: updateCeAttrRole }) { + let curAttr = roleAttrs.find(cur => cur.id == id); + if(!curAttr) { + curAttr = new CeAttrDataRole(); + roleAttrs.push(curAttr); + } + if(update.inc) { + let { fixUp, ratioUp } = update.inc; + if(fixUp) curAttr.fixUp += fixUp; + if(ratioUp) curAttr.ratioUp += ratioUp; + } + if(update.set) { + let { fixUp, ratioUp } = update.set; + if(fixUp) curAttr.fixUp = fixUp; + if(ratioUp) curAttr.ratioUp = ratioUp; + } +} +/** + * 获取皮肤上的seid + * @param fashionid + * @param originStar + * @param originColorStar + */ function getSeidListOfFashion(fashionid: number, originStar: number, originColorStar: number) { let seidList = new Map(); // type => seid if (!gameData.fashion.has(fashionid)) return seidList; @@ -281,152 +398,216 @@ function getSeidListOfFashion(fashionid: number, originStar: number, originColor 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); +/** + * 兵种训练 + * @param {HeroType} originHero 原始武将 + * @param {HeroUpdate} update 更新的数据 + */ +export function calHeroTrainIncAttr(originHero: HeroType, update: HeroUpdate) { + let { attr: heroAttrs, job: oldJob, jobStage: oldJobStage } = originHero; + let { job = oldJob, jobStage = oldJobStage } = update; + + let targetAttrId = ABI_TYPE_TO_STAGE.get(jobStage); // 转换为18维的属性id + + let dicJob = gameData.job.get(job); + if (dicJob.grade > 1) { + let jobGradeAndClass = getJobByGradeAndClass(dicJob.job_class, dicJob.grade - 1); let lastJob = gameData.job.get(jobGradeAndClass.jobid); - res[attrName].fixUp += (currentJob[attrName] - lastJob[attrName]) * HERO_CE_RATIO; + let inc = (dicJob.ceAttr.get(jobStage) - lastJob.ceAttr.get(jobStage)) * HERO_CE_RATIO; + updateHeroAttr(heroAttrs, targetAttrId, { inc: { fixUp: inc } }) } else { - res[attrName].fixUp += currentJob[attrName] * HERO_CE_RATIO; + let inc = dicJob.ceAttr.get(jobStage) * HERO_CE_RATIO; + updateHeroAttr(heroAttrs, targetAttrId, { inc: { fixUp: inc } }) } - return res; + return heroAttrs; } -//进阶 -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); +/** + * 兵种进阶 + * @param {HeroType} originHero 原始武将 + * @param {HeroUpdate} update 更新内容 + * @param {number[]} addSeidList 用于更新被动 + * @param {number[]} removeSeidList 用于更新被动 + */ +export function calHeroJobStageUpIncAttr(originHero: HeroType, update: HeroUpdate, addSeidList: Array, removeSeidList: Array) { + let { job: oldJob, attr: heroAttrs } = originHero; + let { job = oldJob } = update; + + let lastJob = gameData.job.get(oldJob); + let currentJob = gameData.job.get(job); + let lastSeids = lastJob?.seid||new Array(); + let curSeids = currentJob?.seid||new Array(); + + for (let seid of curSeids) { + let index = findIndex(lastSeids, seid); if (index < 0) { addSeidList.push(seid, 0); } } - for (let seid of lastJob.seid) { - let index = findIndex(currentJob.seid, seid); + for (let seid of lastSeids) { + let index = findIndex(curSeids, seid); if (index < 0) { removeSeidList.push(seid, 0); } } - return res; + return heroAttrs; } - -export function calHeroJobAttr(hero: HeroType, res: CeAttr, addSeidList: Array, removeSeidList: Array) { +/** + * 初始计算兵种属性 + * @param {HeroType} originHero 原始武将 + * @param {HeroUpdate} hero 更新后的武将 + * @param {number[]} addSeidList 用于更新被动 + * @param {number[]} removeSeidList 用于更新被动 + */ +export function calHeroJobAttr(originHero: HeroType, hero: HeroUpdate, addSeidList: Array, removeSeidList: Array) { + let { attr: heroAttrs } = originHero; let currentJob = gameData.job.get(hero.job); let jobGradeAndClass = getJobByGradeAndClass(currentJob.job_class, currentJob.grade - 1); - let lastJob; + let lastJob: DicJob; 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; + + for (let stage = ABI_STAGE.START + 1; stage <= ABI_STAGE.END; stage++) { + let targetAttrId = ABI_TYPE_TO_STAGE.get(stage); + if(hero.jobStage >= stage) { + let fixUp = currentJob.ceAttr.get(stage) * HERO_CE_RATIO; + updateHeroAttr(heroAttrs, targetAttrId, { inc: { fixUp }}) } else { - if (lastJob) - res[attrName].fixUp += lastJob[attrName] * HERO_CE_RATIO; + if(lastJob) { + let fixUp = lastJob.ceAttr.get(stage) * HERO_CE_RATIO; + updateHeroAttr(heroAttrs, targetAttrId, { inc: { fixUp } }); + } } - } - calHeroJobStageUpIncAttr(hero, [0], addSeidList, removeSeidList); - return res; + }; + + originHero.attr = heroAttrs; + heroAttrs = calHeroJobStageUpIncAttr(originHero, hero, addSeidList, removeSeidList); + return heroAttrs; } -//穿戴时装 -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; +/** + * 穿戴时装的单武将加成 + * @param {HeroType} originHero 原始武将 + * @param {number} wearSkinId 穿戴的皮肤 + * @param {number} pullSkinId 脱下的皮肤 + * @param {number[]} addSeidList 用于更新被动 + * @param {number[]} removeSeidList 用于更新被动 + * @param {boolean} isInit 是否是计算初始战力 + */ +export function calHeroWearSkinIncAttr(originHero: HeroType, wearSkinId: number, pullSkinId: number, addSeidList: number[], removeSeidList: number[], isInit: boolean = false) { + let { attr: heroAttrs } = originHero; + + let addSkin = gameData.fashion.get(wearSkinId); + let delSkin = gameData.fashion.get(pullSkinId); + 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; + let fixUp = -1 * attr.number * HERO_CE_RATIO; + updateHeroAttr(heroAttrs, attr.id, { inc: { fixUp } }); } } 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; + let fixUp = attr.number * HERO_CE_RATIO; + updateHeroAttr(heroAttrs, attr.id, { inc: { fixUp } }); } if (!isInit) { // 初始的时候,这一段技能在calHeroStarIncAttr里计算了,不用重复算 - let { star, colorStar } = hero; + let { star, colorStar } = originHero; - let curSeidList = getSeidListOfFashion(args[0], star, colorStar); - let preSeidList = getSeidListOfFashion(args[1], star, colorStar); - for (let [type, seid] of curSeidList) { + let curSeidList = getSeidListOfFashion(wearSkinId, star, colorStar); + let preSeidList = getSeidListOfFashion(pullSkinId, star, colorStar); + curSeidList.forEach((seid, type) => { if (!preSeidList.has(type)) { removeSeidList.push(seid, 0); } - } - for (let [type, seid] of preSeidList) { + }); + preSeidList.forEach((seid, type) => { if (!curSeidList.has(type)) { addSeidList.push(seid, 0); } - } + }); } - - return res; + originHero.attr = heroAttrs; + return heroAttrs; } -//羁绊解锁 -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; +/** + * 羁绊解锁 + * @param {HeroType} originHero 原始武将 + * @param {HeroUpdate} update 更新数据 + * @param {number} shipId 解锁的那个id + */ +export function calHeroConectIncAttr(originHero: HeroType, update: HeroUpdate, shipId: number) { + let { connections: oldConnections = [], favourLv, attr: heroAttrs } = originHero; + let { connections = oldConnections } = update; + + let oldConnect = oldConnections.find(cur => cur.shipId == shipId); + let connect = connections.find(cur => cur.shipId == shipId); + + let oldLevel = oldConnect?.level||0; + let level = connect?.level||0; + + let fiendShipLevel = gameData.friendShipLevelMap.get(favourLv); 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 (currentShip) { + for (let attr of currentShip.attributes) { + let fixUp = attr.number * (HERO_CE_RATIO + fiendShipLevel.add); + updateHeroAttr(heroAttrs, attr.id, { inc: { fixUp } }); + } } 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); + let lastShip = getFriendShipById(shipId, oldLevel); + if (lastShip) { + for (let attr of lastShip.attributes) { + let fixUp = -1 * attr.number * (HERO_CE_RATIO + fiendShipLevel.add); + updateHeroAttr(heroAttrs, attr.id, { inc: { fixUp } }) + } } } - return res; + originHero.attr = heroAttrs; + return heroAttrs; } -//好感升级 -export function calHeroFavourUpIncAttr(hero: HeroType, args: Array) { - let res: CeAttr = {}; - let currentFiendShipLevel = gameData.friendShipLevelMap.get(hero.favourLv); +/** + * 好感度升级,影响羁绊加成 + * + * @param {HeroType} originHero 原始武将数据 + * @param {HeroUpdate} update 更新的数据 + */ +export function calHeroFavourUpIncAttr(originHero: HeroType, update: HeroUpdate) { + let { favourLv: oldFavourLv, attr: heroAttrs } = originHero; + let { favourLv = oldFavourLv } = update; + + let currentFiendShipLevel = gameData.friendShipLevelMap.get(favourLv); let difAdd = currentFiendShipLevel.add; - if (!!args[0]) { - let lastFiendShipLevel = gameData.friendShipLevelMap.get(args[0]); + if (oldFavourLv && oldFavourLv > 0) { // 减上一级好感 + let lastFiendShipLevel = gameData.friendShipLevelMap.get(oldFavourLv); 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); + + for (let {shipId, level} of originHero.connections) { + let dicHeroFriendShip = getFriendShipById(shipId, level); + for (let attr of dicHeroFriendShip.attributes) { + let fixUp = attr.number * (HERO_CE_RATIO + difAdd); + updateHeroAttr(heroAttrs, attr.id, { inc: { fixUp } }); } } - return res; + originHero.attr = heroAttrs; + return heroAttrs; } -// 穿脱, removeSeidList原来身上穿着的所有装备的seid,包括套装的 -export function calEquipPutOnOffIncAttr(hero: HeroType, args: Array, addSeidList: Array, removeSeidList: Array) { +/** + * 穿脱, removeSeidList原来身上穿着的所有装备的seid,包括套装的 + * @param {HeroType} hero 武将 + * @param {number[]} seids args 原来穿着的装备的seid + * @param {number[]} addSeidList 用于更新被动 + * @param {number[]} removeSeidList 用于更新被动 + */ +export function calEquipPutOnOffIncAttr(hero: HeroType, seids: Array, addSeidList: Array, removeSeidList: Array) { // 计算身上所有装备的战力值(特技相关以外) - let res = calHeroEquipIncAttr(hero); + let heroAttrs = calHeroEquipIncAttr(hero); // 计算被动技能 let { ePlace } = hero; @@ -457,15 +638,19 @@ export function calEquipPutOnOffIncAttr(hero: HeroType, args: Array, add } }); - for (let arg of args) { - removeSeidList.push(arg) + for (let seid of seids) { + removeSeidList.push(seid) } - return res + return heroAttrs } +/** + * 计算一个武将身上的所有被动seid + * @param {HeroType} hero 武将,equip需要populate + */ export function calEquipSeids(hero: HeroType) { - let seids = []; + let seids: number[] = []; // 计算被动技能 let { ePlace } = hero; let suits = new Map(); @@ -498,12 +683,12 @@ export function calEquipSeids(hero: HeroType) { return seids; } -// 装备,装备栏升级,装备精炼等涉及到值的 +/** + * 装备,装备栏升级,装备精炼等涉及到值的 + * @param {HeroType} hero 装备更新过的武将 + */ export function calHeroEquipIncAttr(hero: HeroType) { - let res: CeAttr = {}; - let { ePlace } = hero; - - let attrResult = new CeAttrNumber(); + let { ePlace, attr: heroAttrs } = hero; for (let { equip, lv, refineLv } of ePlace) { if (equip) { @@ -530,8 +715,6 @@ export function calHeroEquipIncAttr(hero: HeroType) { } 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); @@ -543,25 +726,29 @@ export function calHeroEquipIncAttr(hero: HeroType) { // console.log('jewel', valueJewel); let attr = (value1 + lv * valueup) * (HERO_CE_RATIO + valueRefine) + valueJewel * HERO_CE_RATIO; - attrResult[attrName] += attr; + if(attr > 0) { + console.log('装备战力:', i, attr); + updateHeroAttr(heroAttrs, i, { set: { equipUp: 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; + hero.attr = heroAttrs; + return heroAttrs; } -// 洗炼 -export function calRestrengthenIncAttr(hero: HeroType, ePaceId: number, args: Array, addSeidList: Array, removeSeidList: Array) { +/** + * 洗炼 + * @param {HeroType} hero 更新过的武将 + * @param {number} ePaceId 更新的栏位id + * @param {number[]} seids 移除的seid + * @param {number[]} addSeidList 用于更新被动 + * @param {number[]} removeSeidList 用于更新被动 + */ +export function calRestrengthenIncAttr(hero: HeroType, ePaceId: number, seids: Array, addSeidList: Array, removeSeidList: Array) { - let res: CeAttr = {}; + let { attr: heroAttrs } = hero; let { ePlace } = hero; let curPlace = ePlace.find(cur => cur.id == ePaceId); @@ -572,13 +759,15 @@ export function calRestrengthenIncAttr(hero: HeroType, ePaceId: number, args: Ar } } - for (let arg of args) { removeSeidList.push(arg) } + for (let seid of seids) { + removeSeidList.push(seid) + } - return res + return heroAttrs } // 添加技能增加的被动属性 -function addSeidEffect(reIncAttr: CeAttr, heroCeAttr: CeAttr, addSeidList: Array, removeSeidList: Array) { +function addSeidEffect(heroAttrs: CeAttrData[], addSeidList: Array, removeSeidList: Array) { console.log('addSeidList', addSeidList) console.log('removeSeidList', removeSeidList) @@ -600,28 +789,10 @@ function addSeidEffect(reIncAttr: CeAttr, heroCeAttr: CeAttr, addSeidList: Array } 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; + updateHeroAttr(heroAttrs, ability, { inc: {fixUp: value * multi * HERO_CE_RATIO} }); } 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; + updateHeroAttr(heroAttrs, ability, { inc: {ratioUp: value * multi} }); } } } @@ -649,171 +820,131 @@ function addSeid(effectList: Array, seidId: number, rand: number, seidValue 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]; +/** + * 带上宝石 + * @param {HeroType} hero 武将数据 + * @param {number} id 带上的宝石 + * @param {number} oldId 脱下的宝石 + */ +function calHeroCeWhenJewelOn(hero: HeroType, id: number, oldId: number) { + let { attr: heroAttrs } = hero; + let goodInfo = gameData.goods.get(id); + let oldGoodInfo = gameData.goods.get(oldId); + + if(goodInfo) { + let jGoods = goodInfo.goodsAbility; + jGoods.forEach((value, key) => { + let equipUp = value; + if(oldGoodInfo && oldGoodInfo.goodsAbility) { + equipUp -= oldGoodInfo.goodsAbility.get(key); } - } + updateHeroAttr(heroAttrs, key, { set: { equipUp } }) + }); } - 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, topLineupCe: role.topLineupCe } + + hero.attr = heroAttrs; + return heroAttrs; } -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; +/** + * 脱下宝石 + * @param {HeroType} hero 武将数据 + * @param {number[]} ids 脱下的宝石 + */ +function calHeroCeWhenJewelOff(hero: HeroType, ids: Array) { + let { attr: heroAttrs } = hero; + for (let id of ids) { + let goodInfo = gameData.goods.get(id); + if(goodInfo) { + let jGoods = goodInfo.goodsAbility; + jGoods.forEach((value, key) => { + let equipUp = -1 * value; + updateHeroAttr(heroAttrs, key, { set: { equipUp } }) + }); } } - return res; + hero.attr = heroAttrs; + return heroAttrs; } /** * 全局加成,百家学宫 + * @param role 角色 * @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 = {}; +function calSchoolAddAttr(role: RoleType, heros: HeroType[], schoolId: number, hid: number, preHid: number) { + let { attr: roleAttrs } = role; let school = gameData.school.get(schoolId); + if (!school) return null; + 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; + if(ABI_TYPE_MAIN.includes(attrId)) { // 主属性 + let ratioUp = curRate.mainAttrAPerent - preRate.mainAttrAPerent; + updateRoleAttr(roleAttrs, attrId, { inc: { ratioUp } }); + } else { + let fixUp = (curRate.assiAttrAddValue - preRate.assiAttrAddValue) * HERO_CE_RATIO; + updateRoleAttr(roleAttrs, attrId, { inc: { fixUp } }); } } - return res; + return roleAttrs; } /** * 升星,觉醒,升品时,百家学宫配置武将会相应修改全局战力 - * @param heros HeroType[] 传入只有一个,如果有全局计算,后面push其他武将 - * @param type number 类型 - * @param args - * @param ceAttr + * @param {HeroType[]} heros 全部武将 + * @param {number} type 类型 HERO_SYSTEM_TYPE + * @param {number} hid 更新的那个武将 + * @param {number} isStarUp 是否升星 */ -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; +async function calSchoolStarIncAttr(role: RoleType, heros: HeroType[], type: number, hid: number, isStarUp: number) { + let { roleId, attr: roleAttrs } = role; - 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--; + if ((type == HERO_SYSTEM_TYPE.STAR || type == HERO_SYSTEM_TYPE.COLORSTAR) && !isStarUp) { + return null; + } + + let hero = heros.find(cur => cur.hid == hid); + if(!hero) return null; + + let curHeroInSchool = await SchoolModel.findByHid(roleId, hid); + if (!curHeroInSchool) return null; + + 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 { + return null; + } + let school = gameData.school.get(curHeroInSchool.schoolId); + let preRate = getSchoolRateByStar(preStar, preColorStar, preQuality); + let curRate = getSchoolRateByStar(hero.star, hero.colorStar, hero.quality); + + for (let attrId of school.upAttribute) { + if(ABI_TYPE_MAIN.includes(attrId)) { // 主属性 + let ratioUp = curRate.mainAttrAPerent - preRate.mainAttrAPerent; + updateRoleAttr(roleAttrs, attrId, { inc: { ratioUp } }); } 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); + let fixUp = (curRate.assiAttrAddValue - preRate.assiAttrAddValue) * HERO_CE_RATIO; + updateRoleAttr(roleAttrs, attrId, { inc: { fixUp } }); } } - return res; + + return roleAttrs; } /** @@ -822,107 +953,129 @@ async function calSchoolStarIncAttr(heros: HeroType[], type: number, args: numbe * @param hid 激活的武将 * @param ceAttr */ -function calScrollAddAttr(heros: HeroType[], hid: number, ceAttr: CeAttrRole) { - let res: CeAttrRole = {}; +function calScrollAddAttr(role: RoleType,heros: HeroType[], hid: number) { + let { attr: roleAttrs } = role; let curHero = heros.find(cur => cur.hid == hid); let dicHero = gameData.hero.get(hid); - if (!curHero || !dicHero) return res; + if (!curHero || !dicHero) return roleAttrs; let { quality } = dicHero; - let { star, quality: curQuality, colorStar, job } = curHero; + let { star, quality: curQuality, colorStar } = curHero; let heroScroll = getScollByStar(quality, star, curQuality, colorStar); - if (!heroScroll) return res; + if (!heroScroll) return roleAttrs; let preScroll = gameData.preHeroScroll.get(heroScroll.id); heroScroll.ceAttr.forEach((add, id) => { - let attId = getFieldByStage(id, job); - let attrName = getAtrrNameById(attId); + let attrId = ABI_TYPE_TO_STAGE.get(id); 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; + let fixUp = (add - preAdd) * HERO_CE_RATIO; + updateRoleAttr(roleAttrs, attrId, { inc: { fixUp } }); }); - return res; + return roleAttrs; } /** * 名将谱激活增加单个武将好感 - * @param hero 当前武将 - * @param hid 激活武将 - * @param preFavourLv 之前的好感度等级,有提升时才计算加成 + * @param originHero 原始武将 + * @param update 更新数据 */ -function calHeroCeScrollIncAttr(hero: HeroType, hid: number, preFavourLv: number) { - let res: CeAttr = {}; - if (hero.hid == hid && hero.favourLv != preFavourLv) { - res = calHeroFavourUpIncAttr(hero, [preFavourLv]); +function calHeroCeScrollIncAttr(originHero: HeroType, update: HeroUpdate) { + let { attr: heroAttrs, favourLv: oldFavourLv } = originHero; + let { favourLv = oldFavourLv } = update; + if (favourLv != oldFavourLv) { + heroAttrs = calHeroFavourUpIncAttr(originHero, update); } - return res; + return heroAttrs; } -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; +/** + * 升爵位 + * @param role 角色数据 + * @param titleId 升到哪个爵位 + */ +function calTitle(role: RoleType, update: RoleUpdate) { + let { title: oldTitle, attr: roleAttrs } = role; + let { title = oldTitle } = update; + + let dicTitle = gameData.title.get(title); + if(!dicTitle) return null; + + for (let i = ABI_TYPE.ABI_HP; i < ABI_TYPE.ABI_MAX; i++) { + if(dicTitle.mainAttrValue.has(i)) { + let fixUp = dicTitle.mainAttrValue.get(i) * HERO_CE_RATIO; + updateRoleAttr(roleAttrs, i, { inc: { fixUp }}); + } + if(dicTitle.assiAttrValue.has(i)) { + let fixUp = dicTitle.assiAttrValue.get(i) * HERO_CE_RATIO; + updateRoleAttr(roleAttrs, i, { inc: { fixUp }}); + } } - 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; + + return roleAttrs; } + +/** + * 神像强化,更新主属性加成 + * @param role 角色数据 + * @param update 更新数据 + * @param id 更新哪座神像 + */ +function calTeraphMainAttr(role: RoleType, update: RoleUpdate, id: number) { + let { attr: roleAttrs, teraphs: oldTeraphs = [] } = role; + let { teraphs = oldTeraphs } = update; + + let oldTeraph = oldTeraphs.find(cur => cur.id == id); + let teraph = teraphs.find(cur => cur.id == id); + if(teraph && teraph.attr) { + for(let [attrId, val] of teraph.attr) { + let oldVal = 0; + if(oldTeraph && oldTeraph.attr && oldTeraph.attr.has(attrId)) { + oldVal = oldTeraph.attr.get(attrId); + } + + let fixUp = (val - oldVal) * HERO_CE_RATIO; + updateRoleAttr(roleAttrs, attrId, { inc: {fixUp} }) + } + } + return roleAttrs; +} + + +/** + * 神像进阶,更新次级属性加成 + * @param role 角色数据 + * @param update 更新数据 + * @param id 更新哪座神像 + */ +function calTeraphAssistAttr(role: RoleType, update: RoleUpdate, id: number) { + let { attr: roleAttrs, teraphs: oldTeraphs = [] } = role; + let { teraphs = oldTeraphs } = update; + + let oldTeraph = oldTeraphs.find(cur => cur.id == id); + let teraph = teraphs.find(cur => cur.id == id); + + let dicOldTeraph = getTeraph(id, oldTeraph?.grade); + let dicTeraph = getTeraph(id, teraph?.grade); + if(!dicTeraph) return null; + + dicTeraph.assiAttrValue.forEach((val, attrId) => { + let oldVal = 0; + if(dicOldTeraph && dicOldTeraph.assiAttrValue && dicOldTeraph.assiAttrValue.has(attrId)) { + oldVal = dicOldTeraph.assiAttrValue.get(attrId); + } + + let ratioUp = val - oldVal; + updateRoleAttr(roleAttrs, attrId, { inc: { ratioUp } }); + }); + return roleAttrs; +} + +/** + * 全局加成初始化 + * @param role + */ 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; + calTitle(role, role); // 计算初始爵位带来的全局 } - -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); - } - } -} \ No newline at end of file diff --git a/web-server/app/service/Auth.ts b/web-server/app/service/Auth.ts index ecf4e5391..a02f4d372 100644 --- a/web-server/app/service/Auth.ts +++ b/web-server/app/service/Auth.ts @@ -8,7 +8,7 @@ import { smsModel } from '@db/Sms'; import { Service } from 'egg'; import Counter from '@db/Counter'; import { getHeroInfoById } from 'app/pubUtils/gamedata'; -import { calPlayerCeAndSave } from 'app/pubUtils/playerCe'; +import { calPlayerCeAndSave, reCalAllHeroCe } from 'app/pubUtils/playerCe'; import { getExpByLv, getHeroExpByLv, gameData } from 'app/pubUtils/data'; import { isString } from 'underscore'; @@ -139,6 +139,7 @@ export default class Auth extends Service { const seqId = await Counter.getNewCounter(COUNTER.ROLE) || -1; const role = await RoleModel.createRole(uid, serverId, { roleId, code, roleName, seqId, lv: DEFAULT_LV, exp: (getExpByLv(DEFAULT_LV - 1)||{sum:0}).sum||0 }); if (role) { + let skinIds = new Array(); for (let hid of DEFAULT_HEROES) { let hero = await HeroModel.findByHidAndRole(hid, roleId); if(hero) { @@ -155,9 +156,11 @@ export default class Auth extends Service { roleId, roleName: role.roleName, hid, hName, star, quality, job, serverId: role.serverId, skins:[{id: initialSkin, enable: true}], lv: DEFAULT_HERO_LV, exp: getHeroExpByLv(DEFAULT_HERO_LV - 1)||0 }); - await calPlayerCeAndSave(roleId, [hero], HERO_SYSTEM_TYPE.INIT); + skinIds.push(initialSkin); + await calPlayerCeAndSave(HERO_SYSTEM_TYPE.INIT, roleId, hero, {}, role); } + await reCalAllHeroCe(HERO_SYSTEM_TYPE.ADD_SKIN, roleId, {}, skinIds) for(let {id, count} of DEFAULT_ITEMS) { let dicGoods = gameData.goods.get(id); diff --git a/web-server/app/service/Utils.ts b/web-server/app/service/Utils.ts index 9f80ed6a6..241d4ae30 100644 --- a/web-server/app/service/Utils.ts +++ b/web-server/app/service/Utils.ts @@ -1,7 +1,5 @@ import { Service } from 'egg'; import { resResult as pubResult } from '../pubUtils/util'; -import { calPlayerCeAndSave } from 'app/pubUtils/playerCe'; -import { HeroType } from '@db/Hero'; import { addSkins, addBags, addEquips } from 'app/pubUtils/itemUtils'; import { BagInter, EquipInter } from 'app/pubUtils/interface'; const csprng = require('csprng'); @@ -44,10 +42,6 @@ export default class Utils extends Service { return pubResult(status, data, customMsg); } - public calPlayerCeAndSave(roleId: string, heros: HeroType[], type: number, args: number[]) { - return calPlayerCeAndSave(roleId, heros, type, args) - } - public addSkins(roleId: string, id: number) { return addSkins(roleId, id); }