diff --git a/game-server/app.ts b/game-server/app.ts index 2534a91d0..52bf5fd0f 100644 --- a/game-server/app.ts +++ b/game-server/app.ts @@ -25,7 +25,6 @@ import * as redLockService from './app/services/redLockService'; // TODO 需要整理。 import _pinus = require('pinus'); import { updateTeamStatus } from './app/services/comBattleService'; -import { init } from './app/pubUtils/gmData/gmDataUtil'; import { resResult, genCode } from './app/pubUtils/util'; import { errlogger, infologger } from './app/util/logger'; @@ -129,7 +128,7 @@ app.configure(ALL_ENVS, 'gm', function () { connector: pinus.connectors.hybridconnector, useProtobuf: true }); - init();//将gm后台数据加载到gate服 + // init();//将gm后台数据加载到gate服 }); app.configure(ALL_ENVS, 'guild', function () { diff --git a/game-server/app/servers/activity/handler/gachaHandler.ts b/game-server/app/servers/activity/handler/gachaHandler.ts index 1f4cd48da..f94698a24 100644 --- a/game-server/app/servers/activity/handler/gachaHandler.ts +++ b/game-server/app/servers/activity/handler/gachaHandler.ts @@ -87,7 +87,7 @@ export class GachaHandler { if (!costResult) return resResult(STATUS.GACHA_COST_NOT_ENOUGH); } // 给东西 - console.log('****', heroInfo) + // console.log('****', heroInfo) let { heroes } = await createHeroes(roleId, roleName, sid, serverId, funcs, heroInfo); await addItems(roleId, roleName, sid, items); // 更新数据 diff --git a/game-server/app/servers/role/handler/roleHandler.ts b/game-server/app/servers/role/handler/roleHandler.ts index 3796f89a4..f281b6c87 100644 --- a/game-server/app/servers/role/handler/roleHandler.ts +++ b/game-server/app/servers/role/handler/roleHandler.ts @@ -1,6 +1,6 @@ import { STATUS } from '../../../consts/statusCode'; -import { RoleModel } from './../../../db/Role'; -import { HeroModel } from '../../../db/Hero'; +import { RoleModel, RoleUpdate } from './../../../db/Role'; +import { HeroModel, HeroUpdate } from '../../../db/Hero'; import { resResult, decodeIdCntArrayStr, parseGoodStr } from '../../../pubUtils/util'; import { Application, BackendSession, pinus, HandlerService, } from 'pinus'; import { handleCost, addItems, createHeroes } from '../../../services/rewardService'; @@ -17,10 +17,10 @@ import { checkBattleHeroesByHid } from '../../../services/normalBattleService'; import { Rank } from '../../../services/rankService'; import { updateUserInfo } from '../../../services/redisService'; import { checkTaskWithHero, checkTask, checkTaskWithArgs, checkActivityTask } from '../../../services/taskService'; -import { getGoldObject, getCoinObject } from '../../../pubUtils/itemUtils'; +import { getGoldObject, getCoinObject, createHeroesWhenInit } from '../../../pubUtils/itemUtils'; import { RScriptRecordModel } from '../../../db/RScriptRecord'; import { checkPvp } from '../../../services/pvpService'; -import { pushData } from '../../../services/connectorService'; +import { SkinModel, SkinUpdate } from '../../../db/Skin'; export default function (app: Application) { new HandlerService(app, {}); @@ -32,7 +32,6 @@ export class RoleHandler { } async initRole(msg: { roleName: string }, session: BackendSession) { - console.log('******** initRole start', Date.now()); let roleId = session.get('roleId'); let serverId = session.get('serverId'); let sid: string = session.get('sid'); @@ -45,15 +44,11 @@ export class RoleHandler { let checkName = await RoleModel.checkName(roleName, serverId); if (checkName) return resResult(STATUS.NAME_HAS_USED); - let heroInfos = []; - for (let hid of DEFAULT_HEROES) { - heroInfos.push({ - hid, lv: DEFAULT_HERO_LV, exp: getHeroExpByLv(DEFAULT_HERO_LV - 1) || 0 - }); - } - console.log('****** createHeroes before', Date.now()) - await createHeroes(roleId, roleName, sid, serverId, funcs, heroInfos); + let initInfos: { role: RoleUpdate, heroes: HeroUpdate[], skins: SkinUpdate[]} = await this.app.rpc.role.roleRemote.getInitRoleInfos.toServer(this.app.getServerId()); + role = await RoleModel.updateRoleInfo(roleId, {...initInfos.role, roleName, hasInit: true}); + let { heroes } = await createHeroesWhenInit(roleId, roleName, serverId, initInfos.heroes, initInfos.skins); + console.log('****** createHeroes after', Date.now()) session.set('roleName', roleName); session.push('roleName', () => { }); @@ -61,19 +56,15 @@ export class RoleHandler { let items = [].concat(DEFAULT_ITEMS, DEFAULT_EQUIPS, [getGoldObject(DEFAULT_GOLD)], [getCoinObject(DEFAULT_COIN)]); await addItems(roleId, roleName, sid, items); - console.log('****** calAllHeroCe before', Date.now()) - let calResult = await calAllHeroCe(HERO_SYSTEM_TYPE.INIT, sid, roleId, { hasInit: true, roleName }); - console.log('****** calAllHeroCe after', Date.now()) - let battleId = SCRIPT.SCRIPT_BATTLE_ID; let warInfo = gameData.war.get(battleId); await RScriptRecordModel.setScript(roleId, battleId, warInfo.warType, 2, SCRIPT.SCRIPT_NAME); - await checkPvp(calResult.role); + await checkPvp(role); console.log('******** initRole end', Date.now()); return resResult(STATUS.SUCCESS, { - roleId, roleName, heroes: calResult.heros + roleId, roleName, heroes }) } @@ -523,4 +514,13 @@ export class RoleHandler { return resResult(STATUS.SUCCESS, { roleName: role.roleName }); } + async setInitRole() { + this.app.rpc.role.roleRemote.setInitRole.toServer(this.app.getServerId()); + return resResult(STATUS.SUCCESS); + } + async getInitRole() { + let initRoleInfo = await this.app.rpc.role.roleRemote.getInitRoleInfos.toServer(this.app.getServerId()); + + return resResult(STATUS.SUCCESS, initRoleInfo) + } } diff --git a/game-server/app/servers/role/remote/roleRemote.ts b/game-server/app/servers/role/remote/roleRemote.ts index d3e8a1180..517e9c8cd 100644 --- a/game-server/app/servers/role/remote/roleRemote.ts +++ b/game-server/app/servers/role/remote/roleRemote.ts @@ -1,8 +1,11 @@ -import { Application, ChannelService, FrontendSession, RemoterClass, HandlerService, } from 'pinus'; -import { STATUS } from '../../../consts/statusCode'; -import { resResult } from '../../../pubUtils/util'; +import { Application, ChannelService, HandlerService, } from 'pinus'; // import { sendRolesMails } from '../../../services/mailService'; import { reloadResources } from '../../../pubUtils/data'; +import { HeroUpdate } from '../../../db/Hero'; +import { RoleUpdate } from '../../../db/Role'; +import { SkinUpdate } from '../../../db/Skin'; +import { getInitRoleInfo } from '../../../pubUtils/roleUtil'; +import { DEFAULT_HEROES } from '../../../consts'; export default function (app: Application) { new HandlerService(app, {}); return new RoleRemote(app); @@ -13,13 +16,53 @@ export class RoleRemote { constructor(private app: Application) { this.app = app; this.channelService = app.get('channelService'); + this.setInitRole(); } private channelService: ChannelService; + private initHeroes: Map = new Map(); // hid => hero + private initRole: RoleUpdate = {}; + private initSkins: Map = new Map(); // hid => skin + public setInitRole() { + let result = getInitRoleInfo(); + let { role, heroes, skins } = result; + for(let hero of heroes) { + this.initHeroes.set(hero.hid, hero); + } + for(let skin of skins) { + this.initSkins.set(skin.hid, skin); + } + this.initRole = role; + } + + public getInitRoleInfos() { + return { + heroes: this.getInitHeroes(), + skins: this.getInitSkins(), + role: this.initRole + }; + } + + public getInitHeroes() { + let result: HeroUpdate[] = []; + for(let hid of DEFAULT_HEROES) { + result.push(this.initHeroes.get(hid)); + } + return result; + } + + public getInitSkins() { + let result: SkinUpdate[] = []; + for(let hid of DEFAULT_HEROES) { + result.push(this.initSkins.get(hid)); + } + return result; + } + + public getInitHeroById(hid: number) { + return this.initHeroes.get(hid) + } - // sendGmMailsToRoles(mails) { - // sendRolesMails(mails) - // } /** * 重载json资源 diff --git a/game-server/app/services/pvpService.ts b/game-server/app/services/pvpService.ts index a9ce54331..055564bad 100644 --- a/game-server/app/services/pvpService.ts +++ b/game-server/app/services/pvpService.ts @@ -1,6 +1,6 @@ import { PvpDefenseModel, Heroes, OppPlayers, PvpDefenseType, HeroScores, pvpUpdateInter } from '../db/PvpDefense'; -import { RoleType } from '../db/Role'; +import { RoleType, CeAttrDataRole } from '../db/Role'; import { PVP_HERO_POS, REDIS_KEY, PVP_CONST, COUNTER } from '../consts'; import { setPvpDefResult } from '../services/timeTaskService'; import { dicPvpOpponent, DicPvpOpponent } from "../pubUtils/dictionary/DicPvpOpponent"; @@ -11,8 +11,8 @@ import { PVP } from '../pubUtils/dicParam'; import { PVPConfigModel } from '../db/SystemConfig' import { nowSeconds, getTimeFun } from '../pubUtils/timeUtil'; import { HeroesRecord } from '../db/PvpRecord'; -import { HeroModel } from '../db/Hero'; -import { CeAttrData, CeAttrDataRole, AttributeCal } from '../domain/roleField/attribute'; +import { HeroModel, CeAttrData } from '../db/Hero'; +import { AttributeCal } from '../domain/roleField/attribute'; import { PvpEnemies, PvpHeroInfo, PvpOtherHeroes } from '../domain/dbGeneral'; import { DicWarJson } from '../pubUtils/dictionary/DicWarJson'; import { findWhere, findIndex } from 'underscore'; diff --git a/game-server/app/services/roleService.ts b/game-server/app/services/roleService.ts index b3dda95f5..2016bd3fc 100644 --- a/game-server/app/services/roleService.ts +++ b/game-server/app/services/roleService.ts @@ -1,5 +1,5 @@ import { ChannelUser } from './../domain/ChannelUser'; -import { Channel } from 'pinus'; +import { Channel, pinus } from 'pinus'; import { getRandValueByMinMax, getRandEelm, decodeIdCntArrayStr } from '../pubUtils/util'; import { TERAPH_RANDOM } from "../consts"; import { DicTeraph } from '../pubUtils/dictionary/DicTeraph'; diff --git a/shared/consts/constModules/abilityConst.ts b/shared/consts/constModules/abilityConst.ts index 37ef1050f..3ccf00cf7 100644 --- a/shared/consts/constModules/abilityConst.ts +++ b/shared/consts/constModules/abilityConst.ts @@ -152,12 +152,19 @@ export const HERO_ATTR = { 28: "strikeBack", // 反击伤害 }; -export const ABI_TYPE_TO_STAGE = new Map([ - [ABI_STAGE.HP, ABI_TYPE.ABI_HP], - [ABI_STAGE.ATK, ABI_TYPE.ABI_ATK], - [ABI_STAGE.DEF, ABI_TYPE.ABI_DEF], - [ABI_STAGE.MDEF, ABI_TYPE.ABI_MDEF] -]); +const abilityTypeWithStage = [ + { type: ABI_TYPE.ABI_HP, stage: ABI_STAGE.HP }, + { type: ABI_TYPE.ABI_ATK, stage: ABI_STAGE.ATK }, + { type: ABI_TYPE.ABI_DEF, stage: ABI_STAGE.DEF }, + { type: ABI_TYPE.ABI_MDEF, stage: ABI_STAGE.MDEF }, +]; + +export const ABI_TYPE_TO_STAGE = new Map(); +export const ABI_STAGE_TO_TYPE = new Map(); +for(let {type, stage} of abilityTypeWithStage) { + ABI_TYPE_TO_STAGE.set(type, stage); + ABI_STAGE_TO_TYPE.set(stage, type); +} export function getAtrrNameById(attrId: number):string { return HERO_ATTR[attrId]; diff --git a/shared/db/Hero.ts b/shared/db/Hero.ts index 3fd6b2624..b85492753 100644 --- a/shared/db/Hero.ts +++ b/shared/db/Hero.ts @@ -2,11 +2,12 @@ import BaseModel from './BaseModel'; import { index, getModelForClass, prop, Ref, mongoose, DocumentType } from '@typegoose/typegoose'; import Equip, { } from './Equip'; import { CounterModel } from './Counter'; -import { COUNTER, EQUIP_TYPE } from '../consts'; +import { COUNTER, EQUIP_TYPE, HERO_CE_RATIO } from '../consts'; import { reduceCe } from '../pubUtils/util'; import Skin from './Skin'; -class CeAttrData { +type CeAttrUpdate = Partial; +export class CeAttrData { @prop({ required: true }) id: number = 0; @prop({ required: true }) @@ -21,6 +22,23 @@ class CeAttrData { constructor(id: number) { this.id = id; } + + public updateAttr(update: { inc?: CeAttrUpdate, set?: CeAttrUpdate }) { + if(update.inc) { + let { base, equipUp, fixUp, ratioUp } = update.inc; + if(base != undefined) this.base += base * HERO_CE_RATIO; + if(equipUp != undefined) this.equipUp += equipUp * HERO_CE_RATIO; + if(fixUp != undefined) this.fixUp += fixUp * HERO_CE_RATIO; + if(ratioUp != undefined) this.ratioUp += ratioUp; + } + if(update.set) { + let { base, equipUp, fixUp, ratioUp } = update.set; + if(base != undefined) this.base = base * HERO_CE_RATIO; + if(equipUp != undefined) this.equipUp = equipUp * HERO_CE_RATIO; + if(fixUp != undefined) this.fixUp = fixUp * HERO_CE_RATIO; + if(ratioUp != undefined) this.ratioUp = ratioUp; + } + } } /** @@ -207,6 +225,16 @@ export default class Hero extends BaseModel { return hero; } + public static async insertHeroes(roleId: string, roleName: string, serverId: number, heroInfos: HeroUpdate[]) { + let insertInfos: HeroUpdate[] = []; + for(let hero of heroInfos) { + const seqId = await CounterModel.getNewCounter(COUNTER.HID) || -1; + insertInfos.push({ ...hero, seqId, roleId, roleName, serverId }) + } + const hero: HeroType[] = await HeroModel.insertMany(insertInfos); + return hero; + } + public static async sumTopHeroCe(roleId: string, num: number) { let ce: Array<{ historyCe: number }> = await HeroModel.aggregate([ { $match: { roleId } }, diff --git a/shared/db/Role.ts b/shared/db/Role.ts index 5adbe386d..6193b6d00 100644 --- a/shared/db/Role.ts +++ b/shared/db/Role.ts @@ -1,4 +1,4 @@ -import { ROLE_TERAPH, ROLE_SELECT, ABI_TYPE } from './../consts'; +import { ROLE_TERAPH, ROLE_SELECT, ABI_TYPE, HERO_CE_RATIO } from './../consts'; import BaseModel from './BaseModel'; import { index, getModelForClass, prop, DocumentType, Ref, mongoose } from '@typegoose/typegoose'; import User from './User'; @@ -8,6 +8,7 @@ import { Figure } from '../domain/dbGeneral'; import * as dicParam from '../pubUtils/dicParam'; import Hero from './Hero'; +type CeAttrUpdate = Partial; // role表属性格式 export class CeAttrDataRole { @prop({ required: true }) @@ -20,6 +21,19 @@ export class CeAttrDataRole { constructor(id: number) { this.id = id; } + + public updateAttr(update: { inc?: CeAttrUpdate, set?: CeAttrUpdate }) { + if(update.inc) { + let { fixUp, ratioUp } = update.inc; + if(fixUp != undefined) this.fixUp += fixUp * HERO_CE_RATIO; + if(ratioUp != undefined) this.ratioUp += ratioUp; + } + if(update.set) { + let { fixUp, ratioUp } = update.set; + if(fixUp != undefined) this.fixUp = fixUp * HERO_CE_RATIO; + if(ratioUp != undefined) this.ratioUp = ratioUp; + } + } } class TopHero { @@ -75,6 +89,7 @@ export class Teraph { constructor(id: number) { this.id = id; + this.attr = this.getAttr(); } public get attr() { @@ -86,6 +101,15 @@ export class Teraph { return map } + private getAttr() { + 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; diff --git a/shared/db/Skin.ts b/shared/db/Skin.ts index 6741a5354..d5663cfaf 100644 --- a/shared/db/Skin.ts +++ b/shared/db/Skin.ts @@ -26,6 +26,15 @@ export default class Skin extends BaseModel { return rec; } + public static async insertSkins(roleId: string, roleName: string, skinInfos: SkinUpdate[]) { + let insertInfos: SkinUpdate[] = []; + for(let skinInfo of skinInfos) { + insertInfos.push({ ...skinInfo, roleId, roleName }); + } + const items: SkinType[] = await SkinModel.insertMany(insertInfos); + return items; + } + public static async increaseSkin(roleId: string, id: number, info: { roleId: string, roleName: string, id: number, skinName: string, hid: number }, lean = true) { const doc = new SkinModel(); const setOnInsert = Object.assign(doc.toJSON(), info); @@ -39,3 +48,4 @@ export const SkinModel = getModelForClass(Skin); export interface SkinType extends Pick, keyof Skin> { id: number; }; +export type SkinUpdate = Partial; // 将所有字段变成可选项 \ No newline at end of file diff --git a/shared/domain/roleField/attribute.ts b/shared/domain/roleField/attribute.ts index 74666da81..0fa4130b4 100644 --- a/shared/domain/roleField/attribute.ts +++ b/shared/domain/roleField/attribute.ts @@ -1,40 +1,9 @@ -import { prop } from '@typegoose/typegoose'; import { HERO_CE_RATIO, getAtrrNameById, ABI_TYPE_MAIN } from '../../consts'; +import { CeAttrDataRole } from '../../db/Role'; +import { CeAttrData } from '../../db/Hero'; import { gameData } from '../../pubUtils/data'; import { decodeArrayListStr, reduceCe } from '../../pubUtils/util'; -// hero表内属性基础格式 -export class CeAttrData { - @prop({ required: true }) - id: number = 0; - @prop({ required: true }) - base: number = 0; - @prop({ required: true }) - ratioUp: number = 0; - @prop({ required: true }) - fixUp: number = 0; - @prop({ required: true }) - equipUp: number = 0; - - constructor(id: number) { - this.id = id; - } -} - -// role表属性格式 -export class CeAttrDataRole { - @prop({ required: true }) - id: number = 0; - @prop({ required: true }) - ratioUp: number = 0; - @prop({ required: true }) - fixUp: number = 0; - - constructor(id: number) { - this.id = id; - } -} - export class AttributeCal { attrs: Map = new Map(); ce?: number = 0; diff --git a/shared/domain/roleField/calCe.ts b/shared/domain/roleField/calCe.ts new file mode 100644 index 000000000..b7e42bb04 --- /dev/null +++ b/shared/domain/roleField/calCe.ts @@ -0,0 +1,249 @@ +import { ABI_STAGE, ABI_STAGE_TO_TYPE, ABI_TYPE, ABI_TYPE_MAIN, HERO_SUB_ATTR_RATIO, HERO_SYSTEM_TYPE, SEID_TYPE } from "../../consts"; +import { HeroModel, HeroUpdate, CeAttrData } from "../../db/Hero"; +import { CeAttrDataRole, RoleUpdate } from "../../db/Role"; +import { gameData, getHeroStarByQuality, getHeroWakeByQuality } from "../../pubUtils/data"; +import { DicRandomEffectPool } from "../../pubUtils/dictionary/DicRandomEffectPool"; +import { DicSe } from "../../pubUtils/dictionary/DicSe"; +import { deepCopy } from "../../pubUtils/util"; +import { AttributeCal } from "./attribute"; + +export class CalRoleCe { + private roleInfo: RoleUpdate; + private roleCeWithAttr: Map = new Map(); + + constructor(roleInfo?: RoleUpdate) { + this.roleInfo = roleInfo; + } + + public cal(type: HERO_SYSTEM_TYPE) { + switch (type) { + case HERO_SYSTEM_TYPE.INIT: + this.calTitleAbility(); + this.calTeraphMainAttr(); + break; + } + return this.getRoleAttr(); + } + + private calTitleAbility() { + let { title } = this.roleInfo; + + let dicTitle = gameData.title.get(title)||{ mainAttrValue: new Map(), assiAttrValue: new Map() }; + + for (let i = ABI_TYPE.ABI_HP; i < ABI_TYPE.ABI_MAX; i++) { + if (dicTitle.mainAttrValue.has(i)) { + let fixUp = dicTitle.mainAttrValue.get(i) || 0; + this.getSingleAttrObj(i).updateAttr({ inc: { fixUp } }); + } + if (dicTitle.assiAttrValue.has(i)) { + let fixUp = dicTitle.assiAttrValue.get(i) || 0; + this.getSingleAttrObj(i).updateAttr({ inc: { fixUp } }); + } + } + } + + private calTeraphMainAttr(id?: number) { + let { teraphs = [] } = this.roleInfo; + for(let teraph of teraphs) { + if(id == undefined || teraph.id == id) { + for(let [attrId, val] of teraph.attr) { + this.getSingleAttrObj(attrId).updateAttr({ inc: { fixUp: val } }); + } + } + } + } + + // 获取一个CeAttrData对象,没有就新建 + public getSingleAttrObj(attrId: ABI_TYPE) { + if(!this.roleCeWithAttr.has(attrId)) { + let calSingleAttr = new CeAttrDataRole(attrId); + this.roleCeWithAttr.set(attrId, calSingleAttr); + } + return this.roleCeWithAttr.get(attrId); + } + + private getRoleAttr() { + let attr: CeAttrDataRole[] = []; + this.roleCeWithAttr.forEach(value => { + if(value.ratioUp > 0 || value.fixUp > 0) { + attr.push(value); + } + }); + return attr; + } +} + +export class CalHeroCe { + private hid: number; + private heroInfo: HeroUpdate; + private heroCeWithAttr: Map = new Map(); + + constructor(hid: number, heroInfo?: HeroUpdate) { + this.hid = hid; + if(heroInfo) this.heroInfo = heroInfo; + } + + public async setHeroInfoByHid(roleId: string) { + let hero = await HeroModel.findByHidAndRole(this.hid, roleId); + this.heroInfo = hero; + } + + // 主要接口 + public cal(type: HERO_SYSTEM_TYPE) { + switch (type) { + case HERO_SYSTEM_TYPE.INIT: + this.calBaseAbility(); + this.calSkinSeid(); + this.calJobAbility(); + break; + } + return this.getHeroAttr() + } + + // 计算基础属性 + private calBaseAbility() { + let { star, starStage, quality, colorStar, colorStarStage, lv } = this.heroInfo; + const dicHero = gameData.hero.get(this.hid); + + for (let stage = ABI_STAGE.START + 1; stage <= ABI_STAGE.END; stage++) { + let attrId = ABI_STAGE_TO_TYPE.get(stage); + + const isWake = colorStar > 0; // 是否觉醒,只要激活了觉醒,彩星就会 > 1 + // console.log('*isUpstar', isUpStar, originStar, star, originColorStar, colorStar) + if(starStage < stage) star--; + if(colorStarStage < stage) colorStar--; + + const dicJob = gameData.job.get(dicHero.jobid); + const dicStar = isWake ? getHeroWakeByQuality(dicJob.job_class, dicHero.quality, colorStar) : getHeroStarByQuality(dicJob.job_class, quality, star); // 星级表 + + let heroAttr = dicHero.baseAbilityArr.get(attrId); // 武将表hp等 + let heroUpAttr = dicHero.baseAbilityUpArr.get(attrId); // 武将表hp_up等 + let starUp = 0; // 星级成长 + if (!!dicStar && !!dicStar.ceAttr) { + starUp = dicStar.ceAttr.get(stage); + } + let base = heroAttr + (lv - 1) * (heroUpAttr + starUp); + this.getSingleAttrObj(attrId).updateAttr({ inc: { base } }); + }; + } + + // 计算职业属性 + private calJobAbility() { + let { job, jobStage } = this.heroInfo; + + const dicJob = gameData.job.get(job); + for(let i = 1; i <= dicJob.maxStage; i++) { + if(jobStage >= i) { + let { id, attr } = dicJob.ceAttr.get(i); + this.getSingleAttrObj(id).updateAttr({ inc: { fixUp: attr } }); + } + } + addSeidEffect.bind(this, dicJob.seid); + } + + + // 计算皮肤属性 + private calSkinSeid() { + let { skins, star: _star, colorStar: _colorStar } = this.heroInfo; + let curSkin = skins.find(cur => cur.enable); + let fashionid = curSkin.id; + + let seidList = new Map(); // type => seid + if (!gameData.fashion.has(fashionid)) return + + let { skillId } = gameData.fashion.get(fashionid); + let { starSeidArr, colorStarSeidArr } = gameData.heroSkill.get(skillId); + for (let { star, value, type } of starSeidArr) { + if (_star >= star) { + seidList.set(type, value); + } + } + for (let { star, value, type } of colorStarSeidArr) { + if (_colorStar >= star) { + seidList.set(type, value); + } + } + let list: number[] = []; + for(let [_type, value] of seidList) list.push(value); + addSeidEffect.bind(this, list); + } + + public getHeroAttr() { + let attr: CeAttrData[] = []; + this.heroCeWithAttr.forEach(value => { + if(value.base > 0 || value.equipUp > 0 || value.fixUp > 0 || value.ratioUp > 0) { + attr.push(value); + } + }); + return attr; + } + + // 获取一个CeAttrData对象,没有就新建 + public getSingleAttrObj(attrId: ABI_TYPE) { + if(!this.heroCeWithAttr.has(attrId)) { + let calSingleAttr = new CeAttrData(attrId); + this.heroCeWithAttr.set(attrId, calSingleAttr); + } + return this.heroCeWithAttr.get(attrId); + } + + public getCalculatedCe(roleAttr: CeAttrDataRole[]) { + let attrCal = new AttributeCal(); + attrCal.setLv(this.heroInfo.lv); + attrCal.setByDbData(roleAttr, this.getHeroAttr()); + return attrCal.calCe(); + } +} + +// 添加技能增加的被动属性 +function addSeidEffect(this: CalRoleCe, seidList: number[]) { + console.log('******addSeidEffect',this, seidList) + + // console.log('addSeidList', addSeidList.join()) + // console.log('removeSeidList', removeSeidList.join()) + let effectList: DicSe[] = []; // any: dic_zyz_se表内容 + + for (let ii = 0; ii < seidList.length; ii += 2) { + let seid = seidList[ii]; + let rand = seidList[ii + 1] || 0; + let dicSeid: DicSe | DicRandomEffectPool = gameData.se.get(seid); + if (!dicSeid) dicSeid = gameData.randomEffectPool.get(seid); + if (dicSeid && dicSeid.id > 0) { + addSeid(effectList, dicSeid.id, rand, dicSeid.gainValueArr) + } + } + + // console.log('effectList', JSON.stringify(effectList)); + for (let { type, gainValueArr: [ability, value] } of effectList) { + if (type == SEID_TYPE.TYPE101) { // 加值 + this.getSingleAttrObj(ability).updateAttr({ inc: { fixUp: value } }); + } else if (type == SEID_TYPE.TYPE102) { // 加百分比 + if(ABI_TYPE_MAIN.includes(ability)) { + this.getSingleAttrObj(ability).updateAttr({ inc: {ratioUp: value } }); + } else { // 次级属性102特殊处理 + this.getSingleAttrObj(ability).updateAttr({ inc: {fixUp: value * HERO_SUB_ATTR_RATIO } }); + } + } + } + +} + +// 获取dic_zyz_se内容 +function addSeid(effectList: (DicSe | DicRandomEffectPool)[], seidId: number, rand: number, seidValue: number[] = []) { + let curSeid: DicSe | DicRandomEffectPool = gameData.se.get(seidId); + if (!curSeid) curSeid = gameData.randomEffectPool.get(seidId); + if (!curSeid) { console.log("seidId not found:" + seidId); return; } + if (!seidValue) seidValue = curSeid.gainValueArr; + + if (curSeid.type === SEID_TYPE.TYPE999) { + for (let i = 0; i < seidValue.length; i++) { + addSeid(effectList, seidValue[i], rand); + } + return; + } + let seid: DicSe | DicRandomEffectPool = deepCopy(curSeid); + if (curSeid.index > 0) { + seid.gainValueArr[curSeid.index - 1] = rand; + } + effectList.push(seid); +} \ No newline at end of file diff --git a/shared/pubUtils/itemUtils.ts b/shared/pubUtils/itemUtils.ts index 8378c9b10..b093c506d 100644 --- a/shared/pubUtils/itemUtils.ts +++ b/shared/pubUtils/itemUtils.ts @@ -1,6 +1,6 @@ -import { HeroModel, HeroType } from '../db/Hero'; +import { HeroModel, HeroType, HeroUpdate } from '../db/Hero'; import { ItemModel } from '../db/Item'; import { EquipModel, RandSe, Holes, RandMain, equipUpdate } from './../db/Equip'; import { gameData, getQuenchByQualityAndGrade, getQuenchGradeByValue } from './data'; @@ -8,14 +8,14 @@ import { RANDOM_SE_COUNT, ITID, CURRENCY_BY_TYPE, CURRENCY_TYPE, ROLE_SELECT, FI import { getRandValueByMinMax, getRandEelm } from './util'; import { findWhere } from 'underscore'; -import { RoleModel, RoleType } from '../db/Role'; +import { RoleModel, RoleType, } from '../db/Role'; import { Figure } from '../domain/dbGeneral'; import { getTimeFun, nowSeconds } from './timeUtil'; import { calPlayerCeAndSave, reCalAllHeroCe } from './playerCe'; import { accomplishTask, checkTask, checkTaskWithEquip, checkTaskWithHeroes } from './taskUtil'; // import { checkTask, checkTaskWithHeroes, checkTaskWithEquip, accomplishTask } from './taskUtil'; import { CreateHeroParam } from '../domain/roleField/hero'; -import { SkinModel } from '../db/Skin'; +import { SkinModel, SkinType, SkinUpdate, } from '../db/Skin'; import { TaskListReturn } from '../domain/roleField/task'; /** @@ -314,11 +314,11 @@ function unlockSingleFigure(dbFigures: Figure[], id: number, unlockDirect = fals return figure } -async function getSkinsOfThisHero(roleId: string, roleName: string, hid: number, initialSkin: number) { - let allSkins = await SkinModel.findbyRoleAndHid(roleId, hid); +async function getSkinsOfThisHero(roleId: string, roleName: string, hid: number, initialSkin: number, allSkins?: SkinType[]) { + if(!allSkins) allSkins = await SkinModel.findbyRoleAndHid(roleId, hid); let skin = await increaseSkin(roleId, roleName, initialSkin); if(skin) allSkins.push(skin); - let skins = []; + let skins: { id: number, skin: string, enable: boolean }[] = []; for(let skin of allSkins) { skins.push({ id: skin.id, skin: skin._id, enable: skin.id == initialSkin }); } @@ -367,7 +367,7 @@ export async function createHeroes(roleId: string, roleName: string, serverId: n let role = await RoleModel.incRoleInfo(roleId, { heroNum }, { heroNumUpdatedAt: nowSeconds() }); // 任务 - console.log('****** checkTask before', Date.now()) + console.log('****** checkTask before', Date.now()) let m1 = await checkTask(roleId, TASK_TYPE.HERO_NUM, heroNum, true, {}, funcs); let m2 = await checkTaskWithHeroes(roleId, TASK_TYPE.HERO_QUALITY, heroes, funcs); let m3 = await checkTaskWithHeroes(roleId, TASK_TYPE.HERO_QUALITY_STAR_UP, heroes, funcs); @@ -375,7 +375,7 @@ export async function createHeroes(roleId: string, roleName: string, serverId: n let taskPushMessage = m1.concat(m2, m3, m4); console.log('****** checkTask after', Date.now()) //成长任务 - console.log('****** accomplishTask before', Date.now()) + console.log('****** accomplishTask before', Date.now()) let mm1 = await accomplishTask(serverId, roleId, TASK_TYPE.HERO_NUM, heroNum) let mm2 = await accomplishTask(serverId, roleId, TASK_TYPE.HERO_QUALITY, heroNum, { heroes }) console.log('****** accomplishTask after', Date.now()) @@ -384,6 +384,39 @@ export async function createHeroes(roleId: string, roleName: string, serverId: n return { role, figureInfo: combineFigureInfo(figureInfos), heroes, calHeroResults, calAllHeroResult, taskPushMessage, activityTaskPushMessage } } + +export async function createHeroesWhenInit(roleId: string, roleName: string, serverId: number, heroInfos: HeroUpdate[], skinInfos: SkinUpdate[], funcs?: number[]) { + + let heroNum = 0; + let conditions = new Array<{ type: number, paramHid?: number, paramFavourLv?: number, paramSkinId?: number }>(); + let figureInfos:{ heads: Figure[], frames: Figure[], spines: Figure[] }[] = []; + + for (let heroInfo of heroInfos) { + conditions.push({ type: FIGURE_UNLOCK_CONDITION.GET_HERO, paramHid: heroInfo.hid }); + heroNum++; + } + figureInfos.push(await unlockFigure(roleId, conditions)); // 解锁头像 + let heroes = await HeroModel.insertHeroes(roleId, roleName, serverId, heroInfos); + await SkinModel.insertSkins(roleId, roleName, skinInfos); + + // 任务 + console.log('****** checkTask before', Date.now()) + let m1 = await checkTask(roleId, TASK_TYPE.HERO_NUM, heroNum, true, {}, funcs); + let m2 = await checkTaskWithHeroes(roleId, TASK_TYPE.HERO_QUALITY, heroes, funcs); + let m3 = await checkTaskWithHeroes(roleId, TASK_TYPE.HERO_QUALITY_STAR_UP, heroes, funcs); + let m4 = await checkTaskWithHeroes(roleId, TASK_TYPE.HERO_LV, heroes, funcs); + let taskPushMessage = m1.concat(m2, m3, m4); + console.log('****** checkTask after', Date.now()) + //成长任务 + console.log('****** accomplishTask before', Date.now()) + let mm1 = await accomplishTask(serverId, roleId, TASK_TYPE.HERO_NUM, heroNum) + let mm2 = await accomplishTask(serverId, roleId, TASK_TYPE.HERO_QUALITY, heroNum, { heroes }) + console.log('****** accomplishTask after', Date.now()) + let activityTaskPushMessage = mm1.concat(mm2); + console.log(funcs); + return { figureInfo: combineFigureInfo(figureInfos), heroes, taskPushMessage, activityTaskPushMessage } +} + export function combineFigureInfo(figureInfos: { heads: Figure[], frames: Figure[], spines: Figure[] }[]) { let figureInfo = { heads: new Array
(), frames: new Array
(), spines: new Array
() }; for(let {heads, frames, spines} of figureInfos) { @@ -404,4 +437,14 @@ export function transPiece(hid: number) { let dicHero = gameData.hero.get(hid); let count = gameData.heroTransPiece.get(dicHero.quality); return { pieceId: dicHero.pieceId, count } -} \ No newline at end of file +} + +// export class CreateHero { +// roleId: string; +// roleName: string; +// serverId: number; + +// constructor(roleId: string, roleName: string, serverId: number) { + +// } +// } \ No newline at end of file diff --git a/shared/pubUtils/playerCe.ts b/shared/pubUtils/playerCe.ts index 44b4e9de1..c55accec9 100644 --- a/shared/pubUtils/playerCe.ts +++ b/shared/pubUtils/playerCe.ts @@ -5,9 +5,9 @@ import { HERO_SYSTEM_TYPE, ABI_TYPE, HERO_CE_RATIO, HERO_SUB_ATTR_RATIO, LINEUP_NUM } from '../consts'; import { cal, deepCopy, getAllAttrStage, reduceCe } from './util'; -import { HeroModel, HeroType, HeroUpdate } from '../db/Hero'; -import { RoleModel, RoleType, RoleUpdate } from '../db/Role'; -import { CeAttrData, CeAttrDataRole, AttributeCal } from '../domain/roleField/attribute'; +import { HeroModel, HeroType, HeroUpdate, CeAttrData } from '../db/Hero'; +import { RoleModel, RoleType, RoleUpdate, CeAttrDataRole } from '../db/Role'; +import { AttributeCal } from '../domain/roleField/attribute'; import { ABI_STAGE, SEID_TYPE } from '../consts'; import { gameData, getJobByGradeAndClass, getHeroWakeByQuality, getHeroStarByQuality, getFriendShipById, getSchoolRateByStar, getScollByStar, getTeraph, getDicSuitByTypeAndLv } from './data'; import { DicSe } from './dictionary/DicSe'; diff --git a/shared/pubUtils/roleUtil.ts b/shared/pubUtils/roleUtil.ts new file mode 100644 index 000000000..9e05858dd --- /dev/null +++ b/shared/pubUtils/roleUtil.ts @@ -0,0 +1,49 @@ +import { DEFAULT_HERO_LV, LINEUP_NUM } from "../consts"; +import { SkinModel } from "../db/Skin"; +import { DEFAULT_COIN, DEFAULT_GOLD, DEFAULT_HEROES, DEFAULT_LV, HERO_SYSTEM_TYPE } from "../consts"; +import { HeroModel, HeroUpdate } from "../db/Hero"; +import { RoleModel, RoleUpdate } from "../db/Role"; +import { SkinUpdate } from "../db/Skin"; +import { TopHero } from "../domain/dbGeneral"; +import { CalHeroCe, CalRoleCe } from "../domain/roleField/calCe"; +import { gameData, getHeroExpByLv } from "../pubUtils/data"; + +// 储存在内存中的初始数据 +export function getInitRoleInfo() { + let topLineup: TopHero[] = [], topLineupCe = 0, allCe = 0, initHeroes: HeroUpdate[] = [], initSkins: SkinUpdate[] = [], heroNum = 0; + let role = new RoleModel(); + let calRoleCe = new CalRoleCe(role); + let roleAttr = calRoleCe.cal(HERO_SYSTEM_TYPE.INIT); + + for(let hid of DEFAULT_HEROES) { + let { quality, initialStars: star, jobid: job, name: hName, initialSkin } = gameData.hero.get(hid); + // 皮肤 + let skin = new SkinModel(); + let dicFashion = gameData.fashion.get(initialSkin); + let skinInfo = { ...skin.toJSON(), id: initialSkin, hid, skinName: dicFashion.name }; + initSkins.push(skinInfo); + // 武将 + let hero = new HeroModel(); + let heroInfo = {...hero.toJSON(), hid, star, quality, hName, job, skins: [{ id: initialSkin, skin: skinInfo._id, enable: true }], lv: DEFAULT_HERO_LV, exp: getHeroExpByLv(DEFAULT_HERO_LV - 1) || 0 }; + let calHeroCe = new CalHeroCe(hid, heroInfo); + let heroAttr = calHeroCe.cal(HERO_SYSTEM_TYPE.INIT); + let ce = calHeroCe.getCalculatedCe(roleAttr); + allCe += ce; + initHeroes.push({ ...heroInfo, attr: heroAttr, ce, historyCe: ce }); + heroNum++; + } + // 最强阵容 + initHeroes.sort((a, b) => { return b.ce - a.ce }); + for(let i = 0; i < LINEUP_NUM; i++) { + if(initHeroes[i]) { + let { hid, ce, _id } = initHeroes[i]; + topLineup.push({ hid, ce, hero: _id }); + topLineupCe += ce; + } + } + + let initRole: RoleUpdate = { topLineupCe, topLineup, attr: roleAttr, ce: allCe, lv: DEFAULT_LV, gold: DEFAULT_GOLD, coin: DEFAULT_COIN, heroNum, heroNumUpdatedAt: Date.now() }; + return { + role: initRole, heroes: initHeroes, skins: initSkins + } +} \ No newline at end of file