diff --git a/game-server/app/servers/role/handler/equipHandler.ts b/game-server/app/servers/role/handler/equipHandler.ts index a812dbe71..6f51f1f8f 100644 --- a/game-server/app/servers/role/handler/equipHandler.ts +++ b/game-server/app/servers/role/handler/equipHandler.ts @@ -135,8 +135,8 @@ export class EquipHandler { hero.ePlace = ePlace; - await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.EQUIP); - const curHero = { + await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.EQUIP_BASE); + const curHero = { hid, ePlace: strengthenArr } @@ -200,7 +200,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); + await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.EQUIP_BASE); const curHero = { hid, @@ -258,8 +258,8 @@ export class EquipHandler { let equip = await EquipModel.findbySeqId(eid); if (!equip) return resResult(STATUS.EQUIP_NOT_FIND); - let { id, randSe } = equip; - if (!randSe || randSe.length <= 0) { + let {id, randSe, hid, ePlaceId } = equip; + if(!randSe || randSe.length <= 0 ) { return resResult(STATUS.EQUIP_HAVE_NO_RANDSE); } @@ -270,8 +270,12 @@ export class EquipHandler { let pool = randomEffect.map(cur => gameData.randomEffectPool.get(cur)); let chosen = randSe.map(cur => cur.seid); // 上一轮和这一轮随机出来的 let hasReset = false, lockNum = 0; - for (let i = 0; i < randSe.length; i++) { - if (!randSe[i].locked) { + + let removeSeidList = new Array(); // 原装备上的seid [seid, rand, ...] + for(let i = 0; i < randSe.length; i++) { + removeSeidList.push(randSe[i].seid, randSe[i].rand); + + if(!randSe[i].locked) { let newPool = pool.filter(cur => !chosen.includes(cur.id)); let random = getRandomByLen(newPool); if (!random) { break }; @@ -309,7 +313,12 @@ export class EquipHandler { id: equipResult.id, randSe: equipResult.randSe } - return resResult(STATUS.SUCCESS, { curEquip }); + + // 更新战力 + const hero = await HeroModel.findByHidAndRoleWithEquip(hid, roleId); + await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.RESTRENGTHEN, [ePlaceId, ...removeSeidList]); + + return resResult(STATUS.SUCCESS,{curEquip}); } diff --git a/shared/consts/constModules/abilityConst.ts b/shared/consts/constModules/abilityConst.ts index 95b485d67..a05edbcd9 100644 --- a/shared/consts/constModules/abilityConst.ts +++ b/shared/consts/constModules/abilityConst.ts @@ -53,6 +53,8 @@ export enum SEID_TYPE { TYPE101 = 101, /**属性固定值加成(百分比) */ TYPE102 = 102, + /**复合属性 */ + TYPE999 = 999, } export enum ABI_STAGE { diff --git a/shared/consts/constModules/heroConst.ts b/shared/consts/constModules/heroConst.ts index e68260f0c..950bc65e2 100644 --- a/shared/consts/constModules/heroConst.ts +++ b/shared/consts/constModules/heroConst.ts @@ -6,7 +6,9 @@ export const HERO_SYSTEM_TYPE = { SKIN:7, FAVOUR:8, CONNECT:9, - EQUIP: 10 + EQUIP: 10, + EQUIP_BASE: 11, + RESTRENGTHEN: 12 }; // 武将上限 diff --git a/shared/consts/constModules/sysConst.ts b/shared/consts/constModules/sysConst.ts index 104bb0872..83b59eda7 100644 --- a/shared/consts/constModules/sysConst.ts +++ b/shared/consts/constModules/sysConst.ts @@ -86,7 +86,8 @@ export const FILENAME = { DIC_RANDOM_EFFECT_POOL: 'dic_zyz_randomEffectPool', DIC_STRENGTHEN_COST: 'dic_zyz_enhancementCost', DIC_REFINE: 'dic_zyz_jinglian', - DIC_HERO_EQUIP: 'dic_zyz_heroEquip' + DIC_HERO_EQUIP: 'dic_zyz_heroEquip', + DIC_SUIT: 'dic_zyz_suit' } export const WAR_RELATE_TABLES = [ diff --git a/shared/pubUtils/data.ts b/shared/pubUtils/data.ts index f8931eb30..2c44e8202 100644 --- a/shared/pubUtils/data.ts +++ b/shared/pubUtils/data.ts @@ -29,6 +29,8 @@ import { dicRandomEffectPool } from './dictionary/DicRandomEffectPool'; import { dicStrengthenCost } from './dictionary/DicStrengthenCost'; import { dicRefine } from './dictionary/DicRefine'; import { dicHeroEquip } from './dictionary/DicHeroEquip'; +import { dicSuit } from './dictionary/DicSuit'; + export const gameData = { blurprtCompose: dicBlueprtCompose, blueprtPossibility: dicBlueprtPossibility, @@ -68,7 +70,8 @@ export const gameData = { strengthenCost: dicStrengthenCost, refine: dicRefine, jewels: dicJewel, - dicHeroEquip: dicHeroEquip + dicHeroEquip: dicHeroEquip, + suit: dicSuit }; // 在此提供一些原先在gamedata中提供的方法,以便更方便获取gameData数据 diff --git a/shared/pubUtils/dictionary/DicRandomEffectPool.ts b/shared/pubUtils/dictionary/DicRandomEffectPool.ts index a1aee1e30..1ec330cf6 100644 --- a/shared/pubUtils/dictionary/DicRandomEffectPool.ts +++ b/shared/pubUtils/dictionary/DicRandomEffectPool.ts @@ -26,6 +26,6 @@ let arr = JSON.parse(str); export const dicRandomEffectPool = new Map(); arr.forEach(o => { - o.gainValueArr = parseNumberList(o.gainvalue) + o.gainValueArr = parseNumberList(o.gainValue) dicRandomEffectPool.set(o.id, o); }); \ No newline at end of file diff --git a/shared/pubUtils/dictionary/DicSe.ts b/shared/pubUtils/dictionary/DicSe.ts index 0b65eef54..1b44b44e7 100644 --- a/shared/pubUtils/dictionary/DicSe.ts +++ b/shared/pubUtils/dictionary/DicSe.ts @@ -16,6 +16,8 @@ export interface DicSe { readonly gainValueArr: Array; // 最大触发数 readonly maxOnlyNum: number; + // 随机值位置 + readonly index: number; } @@ -25,6 +27,7 @@ let arr = JSON.parse(str); export const dicSe = new Map(); arr.forEach(o => { + o.index = 0; o.gainValueArr = parseNumberList(o.gainvalue) dicSe.set(o.id, o); }); \ No newline at end of file diff --git a/shared/pubUtils/dictionary/DicSuit.ts b/shared/pubUtils/dictionary/DicSuit.ts new file mode 100644 index 000000000..beeb9417e --- /dev/null +++ b/shared/pubUtils/dictionary/DicSuit.ts @@ -0,0 +1,38 @@ +// 镇念塔表 +import { decodeArrayListStr, readJsonFile } from '../util' +import { FILENAME } from '../../consts'; + +export interface DicSuit { + // 套装id + readonly id: number; + // 包含关卡 + readonly name: string; + // 总件数 + readonly totalCount: number; + // 套装效果 + readonly effect: Array<{ count: number, seid: number }>; +} + +const str = readJsonFile(FILENAME.DIC_SUIT); +let arr = JSON.parse(str); + +export const dicSuit = new Map(); + +arr.forEach(o => { + o.effect = parseSuitEffect(o.effect); + dicSuit.set(o.id, o); +}); +arr = undefined; + +function parseSuitEffect(str: string) { + let result = new Array<{ count: number, seid: number }>(); + if (!str) return result; + let decodeArr = decodeArrayListStr(str); + for (let [count, seid] of decodeArr) { + if (isNaN(parseInt(count)) || isNaN(parseFloat(seid))) { + throw new Error('data table format wrong'); + } + result.push({ count: parseInt(count), seid: parseFloat(seid) }); + } + return result +} \ No newline at end of file diff --git a/shared/pubUtils/playerCe.ts b/shared/pubUtils/playerCe.ts index 2e1758a32..8a9a7e3ca 100644 --- a/shared/pubUtils/playerCe.ts +++ b/shared/pubUtils/playerCe.ts @@ -7,12 +7,13 @@ import { HERO_SYSTEM_TYPE, ABI_TYPE } from '../consts'; import { deepCopy } from './util'; import { HeroModel, HeroType } from '../db/Hero'; import { RoleModel } from '../db/Role'; -import { CeAttrData, CeAttr } from '../db/generalField'; +import { CeAttrData, CeAttr, CeAttrNumber } from '../db/generalField'; import { getAttrNameByJobStage, getAttrCeRatio, getAtrrNameById, ABI_TYPE_TO_STAGE, ABI_STAGE, SEID_TYPE, HERO_ATTR} from '../consts'; import { gameData, getJobByGradeAndClass, getHeroWakeByQuality, getHeroStarByQuality, getFriendShipById } from './data'; import { Attributes } from './interface'; import { DicSe } from './dictionary/DicSe'; import { EquipType } from '../db/Equip'; +import { DicRandomEffectPool } from './dictionary/DicRandomEffectPool'; const HERO_CE_RATIO = 100; const _ = require('underscore'); @@ -38,10 +39,15 @@ export function calPlayerCe(hero: HeroType, type: number, args: Array) { } else if (type == HERO_SYSTEM_TYPE.CONNECT) { reIncAttr = calHeroConectIncAttr(hero, args); } else if (type == HERO_SYSTEM_TYPE.EQUIP) { + reIncAttr = calEquipPutOnOffIncAttr(hero, args, addSeidList, removeSeidList); + } else if (type == HERO_SYSTEM_TYPE.EQUIP_BASE) { reIncAttr = calHeroEquipIncAttr(hero); + } else if (type == HERO_SYSTEM_TYPE.RESTRENGTHEN) { + reIncAttr = calRestrengthenIncAttr(hero, args.shift(), args, addSeidList, removeSeidList); } - addSeidEffect(reIncAttr, addSeidList, removeSeidList); // 处理加值 + addSeidEffect(reIncAttr, hero.ceAttr, addSeidList, removeSeidList); // 处理加值 + console.log(JSON.stringify(reIncAttr)) if(!hero.ceAttr) hero.ceAttr = new CeAttr(); for (let attrName in reIncAttr) { let originalAttrData: CeAttrData = hero.ceAttr[attrName]||new CeAttrData(); @@ -112,13 +118,13 @@ export function calHeroStarIncAttr (hero: HeroType, args: Array, addSeid if(isWake) { for(let {star, value} of starSeidArr){ if(hero.star == star){ - addSeidList.push(value); + addSeidList.push(value, 0); } } } else { for(let {star, value} of colorStarSeidArr){ if(hero.colorStar == star){ - addSeidList.push(value); + addSeidList.push(value, 0); } } } @@ -149,22 +155,27 @@ export function calHeroTrainIncAttr(hero: HeroType) { } return res; } + //进阶 -export function calHeroJobStageUpIncAttr(hero: HeroType, args: Array, addSeidList: Array, removeSeidList: Array ) { +export function calHeroJobStageUpIncAttr(hero: HeroType, args: Array, addSeidList: Array, removeSeidList: Array) { let res: CeAttr = {}; let lastJob = gameData.job.get(args[0]); let currentJob = gameData.job.get(hero.job); - addSeidList.concat(deepCopy(currentJob.seid)); + for (let seid of currentJob.seid) { + let index = _.findIndex(lastJob.seid, seid); + if (index < 0) { + addSeidList.push(seid, 0); + } + } for (let seid of lastJob.seid) { let index = _.findIndex(currentJob.seid, seid); - if (index > 0) { - addSeidList.splice(index, 1); - } else { - removeSeidList.push(seid); + if (index < 0) { + removeSeidList.push(seid, 0); } - } + } return res; } + //穿戴时装 export function calWaerHeroSkinIncAttr(hero: HeroType, args: Array) { let res: CeAttr = {}; @@ -229,9 +240,52 @@ export function calHeroFavourUpIncAttr(hero: HeroType, args: Array) { return res; } +// 穿脱, removeSeidList原来身上穿着的所有装备的seid,包括套装的 +export function calEquipPutOnOffIncAttr(hero: HeroType, args: Array, addSeidList: Array, removeSeidList: Array) { + // 计算身上所有装备的战力值(特技相关以外) + let res = calHeroEquipIncAttr(hero); + + // 计算被动技能 + let { ePlace } = hero; + let suits = new Map(); + + for(let { equip } of ePlace) { + if(equip) { + let e = equip; + for(let { seid, rand } of e.randSe) { + addSeidList.push(seid, rand); + } + if(e.suitId > 0) { + if(suits.has(e.suitId)) { + suits.set(e.suitId, 1); + } else { + suits.set(e.suitId, suits.get(e.suitId) + 1); + } + } + } + } + + suits.forEach((suitId, count) => { + let { effect } = gameData.suit.get(suitId); + for(let e of effect) { + if(count >= e.count) { + addSeidList.push(e.seid, 0); + } + } + }); + + for(let arg of args) { removeSeidList.push(arg) } + + return res +} + + +// 装备,装备栏升级,装备精炼等涉及到值的 export function calHeroEquipIncAttr(hero: HeroType) { let res: CeAttr = {}; - let {ePlace} = hero; + let { ePlace } = hero; + + let attrResult = new CeAttrNumber(); for(let {equip, lv, refineLv} of ePlace) { if(equip) { @@ -271,22 +325,41 @@ export function calHeroEquipIncAttr(hero: HeroType) { // console.log('jewel', valueJewel); let attr = (value1 + lv * valueup) * ( HERO_CE_RATIO + valueRefine) + valueJewel * HERO_CE_RATIO; - - let originalCe = hero.ceAttr[attrName].equipUp||0; - - if(attr != originalCe) { - console.log('装备战力:', attr, originalCe); - - res[attrName] = {fixUp: hero.ceAttr[attrName].fixUp, base: hero.ceAttr[attrName].base, ratioUp: hero.ceAttr[attrName].ratioUp, equipUp: originalCe}; - console.log(attr, originalCe) - res[attrName].equipUp += attr * HERO_CE_RATIO - originalCe; - } + attrResult[attrName] += attr; } } } + + for(let attrName in attrResult) { + let originalCe = hero.ceAttr[attrName].equipUp||0; + console.log('装备战力:', attrName, attrResult[attrName] * HERO_CE_RATIO, 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] * HERO_CE_RATIO - originalCe; + } + return res; } +// 洗炼 +export function calRestrengthenIncAttr (hero: HeroType, ePaceId: number, args: Array, addSeidList: Array, removeSeidList: Array) { + + let res: CeAttr = {}; + let {ePlace} = hero; + + let curPlace = ePlace.find(cur => cur.id == ePaceId); + if(curPlace && curPlace.equip) { + let e = curPlace.equip; + for(let { seid, rand } of e.randSe) { + addSeidList.push(seid, rand); + } + } + + for(let arg of args) { removeSeidList.push(arg) } + + return res +} + + // 根据存在升星表等的stage字段的id对应17维id function getFieldByStage(stage: number, jobid: number) { let targetAttrId = ABI_TYPE_TO_STAGE.get(stage); @@ -300,7 +373,7 @@ function getFieldByStage(stage: number, jobid: number) { // 添加技能增加的被动属性 -function addSeidEffect(reIncAttr: CeAttr, addSeidList: Array, removeSeidList: Array) { +function addSeidEffect(reIncAttr: CeAttr, heroCeAttr: CeAttr,addSeidList: Array, removeSeidList: Array) { let otiginalSeidList = [ {list: addSeidList, multi: 1}, @@ -308,41 +381,55 @@ function addSeidEffect(reIncAttr: CeAttr, addSeidList: Array, removeSeid ]; for(let {list, multi} of otiginalSeidList) { let effectList = new Array(); // any: dic_zyz_se表内容 - for(let seid of list) { - let dicSeid = gameData.se.get(seid); + + for(let ii = 0; ii < list.length; ii += 2 ) { + let seid = list[ii]; + let rand = list[ii + 1]||0; + let dicSeid: DicSe|DicRandomEffectPool = gameData.se.get(seid); + if(!dicSeid) dicSeid = gameData.randomEffectPool.get(seid); if(dicSeid && dicSeid.id > 0){ - addSeid(effectList, dicSeid.id, dicSeid.gainValueArr) + addSeid(effectList, dicSeid.id, rand, dicSeid.gainValueArr) } } for(let {type, gainValueArr: [ability, value]} of effectList) { + let attrName = getAtrrNameById(ability); + if(!attrName) continue if(type == SEID_TYPE.TYPE101) { // 加值 - if(!reIncAttr[HERO_ATTR[ability]]) { - reIncAttr[HERO_ATTR[ability]] = new CeAttrData(); + if(!reIncAttr[attrName]) { + reIncAttr[attrName] = deepCopy(heroCeAttr[attrName]); } - reIncAttr[HERO_ATTR[ability]].fixUp += value * multi * HERO_CE_RATIO; + reIncAttr[attrName].fixUp += value * multi * HERO_CE_RATIO; + delete reIncAttr[attrName]._id; } else if (type == SEID_TYPE.TYPE102) { // 加百分比 - if(!reIncAttr[HERO_ATTR[ability]]) { - reIncAttr[HERO_ATTR[ability]] = new CeAttrData(); + if(!reIncAttr[attrName]) { + reIncAttr[attrName] = deepCopy(heroCeAttr[attrName]); } - reIncAttr[HERO_ATTR[ability]].ratioUp += value * multi; + reIncAttr[attrName].ratioUp += value * multi; + delete reIncAttr[attrName]._id; } } } } // 获取dic_zyz_se内容 -function addSeid(effectList: Array, seidId:number, seidValue = new Array()){ +function addSeid(effectList: Array, seidId:number, rand: number, seidValue = new Array()){ // console.log('addSeidEffect', seidId, seidValue) - let curSeid = gameData.se.get(seidId); + let curSeid: DicSe|DicRandomEffectPool = gameData.se.get(seidId); + if(!curSeid) curSeid = gameData.randomEffectPool.get(seidId); if(!curSeid) {console.log("seidId not found:"+seidId);return;} if(!seidValue) seidValue = curSeid.gainValueArr; - if(curSeid.type === 999){ + if(curSeid.type === SEID_TYPE.TYPE999){ for(let i = 0;i < seidValue.length;i++){ - addSeid(effectList, seidValue[i]); + addSeid(effectList, seidValue[i], rand); } return; } - effectList.push(curSeid); + let seid: DicSe|DicRandomEffectPool = deepCopy(curSeid); + if(curSeid.index > 0) { + seid.gainValueArr[curSeid.index - 1] = rand; + } + + effectList.push(seid); } \ No newline at end of file