From e572cb2fa544aa3d783ee78d798a8b2161b870f5 Mon Sep 17 00:00:00 2001 From: luying Date: Wed, 1 Sep 2021 19:40:19 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=9A=E6=AD=A6?= =?UTF-8?q?=E5=B0=86=E5=88=9D=E5=A7=8B=E5=8A=A0=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game-server/app.ts | 3 +- .../servers/activity/handler/gachaHandler.ts | 2 +- .../app/servers/role/handler/roleHandler.ts | 38 +-- .../app/servers/role/remote/roleRemote.ts | 55 +++- game-server/app/services/pvpService.ts | 6 +- game-server/app/services/roleService.ts | 2 +- shared/consts/constModules/abilityConst.ts | 19 +- shared/db/Hero.ts | 32 ++- shared/db/Role.ts | 26 +- shared/db/Skin.ts | 10 + shared/domain/roleField/attribute.ts | 35 +-- shared/domain/roleField/calCe.ts | 249 ++++++++++++++++++ shared/pubUtils/itemUtils.ts | 61 ++++- shared/pubUtils/playerCe.ts | 6 +- shared/pubUtils/roleUtil.ts | 49 ++++ 15 files changed, 507 insertions(+), 86 deletions(-) create mode 100644 shared/domain/roleField/calCe.ts create mode 100644 shared/pubUtils/roleUtil.ts 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 From 62e32a4eb345598cc89672829d2675b225fb3425 Mon Sep 17 00:00:00 2001 From: luying Date: Thu, 2 Sep 2021 20:33:00 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=9Agm-server?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E6=AD=A6=E5=B0=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/servers/role/handler/roleHandler.ts | 14 +- .../app/servers/role/remote/roleRemote.ts | 13 +- game-server/app/services/rankService.ts | 1 - game-server/app/services/rewardService.ts | 37 +-- gm-server/app/service/Utils.ts | 31 +++ gm-server/app/service/users.ts | 59 ++-- shared/db/Role.ts | 2 +- shared/db/Skin.ts | 2 +- shared/domain/roleField/calCe.ts | 2 +- shared/pubUtils/itemUtils.ts | 146 +++------- shared/pubUtils/roleUtil.ts | 256 +++++++++++++++++- 11 files changed, 372 insertions(+), 191 deletions(-) diff --git a/game-server/app/servers/role/handler/roleHandler.ts b/game-server/app/servers/role/handler/roleHandler.ts index f281b6c87..4eff0a9c6 100644 --- a/game-server/app/servers/role/handler/roleHandler.ts +++ b/game-server/app/servers/role/handler/roleHandler.ts @@ -17,10 +17,12 @@ 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, createHeroesWhenInit } from '../../../pubUtils/itemUtils'; +import { getGoldObject, getCoinObject } from '../../../pubUtils/itemUtils'; import { RScriptRecordModel } from '../../../db/RScriptRecord'; import { checkPvp } from '../../../services/pvpService'; import { SkinModel, SkinUpdate } from '../../../db/Skin'; +import { CreateHeroes } from '../../../pubUtils/roleUtil'; +import { Figure } from '../../../domain/dbGeneral'; export default function (app: Application) { new HandlerService(app, {}); @@ -32,6 +34,7 @@ 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,9 +48,14 @@ export class RoleHandler { if (checkName) return resResult(STATUS.NAME_HAS_USED); console.log('****** createHeroes before', Date.now()) - let initInfos: { role: RoleUpdate, heroes: HeroUpdate[], skins: SkinUpdate[]} = await this.app.rpc.role.roleRemote.getInitRoleInfos.toServer(this.app.getServerId()); + let initInfos: { role: RoleUpdate, heroes: HeroUpdate[], skins: SkinUpdate[], figureInfo: { heads: Figure[], frames: Figure[], spines: Figure[] }} + = 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); + let createHero = new CreateHeroes(roleId, roleName, serverId, funcs); + await createHero.createWithInitInfo(initInfos.heroes, initInfos.skins, initInfos.figureInfo); + await createHero.pushMessage(pinus, sid); + await createHero.updateRedisRank(Rank); + let heroes = createHero.getResultHeroes(); console.log('****** createHeroes after', Date.now()) session.set('roleName', roleName); diff --git a/game-server/app/servers/role/remote/roleRemote.ts b/game-server/app/servers/role/remote/roleRemote.ts index 517e9c8cd..25d2ff33b 100644 --- a/game-server/app/servers/role/remote/roleRemote.ts +++ b/game-server/app/servers/role/remote/roleRemote.ts @@ -6,6 +6,7 @@ import { RoleUpdate } from '../../../db/Role'; import { SkinUpdate } from '../../../db/Skin'; import { getInitRoleInfo } from '../../../pubUtils/roleUtil'; import { DEFAULT_HEROES } from '../../../consts'; +import { Figure } from '../../../domain/dbGeneral'; export default function (app: Application) { new HandlerService(app, {}); return new RoleRemote(app); @@ -22,10 +23,11 @@ export class RoleRemote { private initHeroes: Map = new Map(); // hid => hero private initRole: RoleUpdate = {}; private initSkins: Map = new Map(); // hid => skin + private figureInfo: {heads: Figure[], frames: Figure[], spines: Figure[]}; public setInitRole() { let result = getInitRoleInfo(); - let { role, heroes, skins } = result; + let { role, heroes, skins, figureInfo } = result; for(let hero of heroes) { this.initHeroes.set(hero.hid, hero); } @@ -33,13 +35,15 @@ export class RoleRemote { this.initSkins.set(skin.hid, skin); } this.initRole = role; + this.figureInfo = figureInfo; } public getInitRoleInfos() { return { heroes: this.getInitHeroes(), skins: this.getInitSkins(), - role: this.initRole + role: this.initRole, + figureInfo: this.figureInfo }; } @@ -60,7 +64,10 @@ export class RoleRemote { } public getInitHeroById(hid: number) { - return this.initHeroes.get(hid) + return { + heroInfo: this.initHeroes.get(hid), + skinInfo: this.initSkins.get(hid) + } } diff --git a/game-server/app/services/rankService.ts b/game-server/app/services/rankService.ts index 30e9a9af2..77eed673c 100644 --- a/game-server/app/services/rankService.ts +++ b/game-server/app/services/rankService.ts @@ -773,7 +773,6 @@ export class Rank { * @param serverId 分服 */ export async function setRankRedisFromDb(type: string, args?: { serverId?: number }) { - if (type == REDIS_KEY.TOWER_RANK) { let serverId = args.serverId; let ranks = await RoleModel.getRank('tower', serverId, ROLE_SELECT.RANK); diff --git a/game-server/app/services/rewardService.ts b/game-server/app/services/rewardService.ts index 199a452f9..4ea5d1ef9 100644 --- a/game-server/app/services/rewardService.ts +++ b/game-server/app/services/rewardService.ts @@ -7,11 +7,11 @@ import { pushCalPlayerCe, pushCalAllHeroCe, calPlayerCeAndSave } from './playerC import { ItemModel, ItemType } from '../db/Item'; import { STATUS } from '../consts/statusCode'; import { pinus } from 'pinus'; -import { addEquips, addBags, addSkin, addFigure, unlockFigure as pubUnlockFigure, createHeroes as pubCreateHeroes, transPiece, getGoldObject, getCoinObject, getApObject } from '../pubUtils/itemUtils'; +import { addEquips, addBags, addSkin, addFigure, unlockFigure as pubUnlockFigure, transPiece, getGoldObject, getCoinObject, getApObject } from '../pubUtils/itemUtils'; import { ItemInter, RewardInter, } from '../pubUtils/interface'; import { gameData } from '../pubUtils/data'; import { uniq } from 'underscore'; -import { HeroModel, HeroType } from '../db/Hero'; +import { HeroModel, HeroType, HeroUpdate } from '../db/Hero'; import { Figure } from '../domain/dbGeneral'; import { Rank } from './rankService'; import { checkActivityTask, checkTaskWithHero, pushActivityUpdate, pushTaskUpdate } from './taskService'; @@ -21,6 +21,8 @@ import { errlogger } from '../util/logger'; import { BAG } from '../pubUtils/dicParam'; import { sendMailByContent } from './mailService'; import { calEquipSeids } from '../pubUtils/playerCe'; +import { CreateHeroes } from '../pubUtils/roleUtil'; +import { SkinUpdate } from '../db/Skin'; export class CheckMeterial { private roleId: string; @@ -439,15 +441,15 @@ export async function createHeroes(roleId: string, roleName: string, sid: string let hids = heroInfo.map(cur => cur.hid); let userHeroesMap = await HeroModel.findMapByHidRange(hids, roleId); - - let newHeroInfo: CreateHeroParam[] = [], pieces: ItemInter[] = []; + let infos: Map = new Map(), pieces: ItemInter[] = []; for (let h of heroInfo) { let heroCount = h.count || 1; if (userHeroesMap.has(h.hid)) { let { pieceId, count } = transPiece(h.hid); pieces.push({ id: pieceId, count: count * heroCount }); } else { - newHeroInfo.push(h) + let initInfo = await pinus.app.rpc.role.roleRemote.getInitHeroById.toServer(pinus.app.getServerId(), h.hid); + infos.set(h.hid, initInfo); userHeroesMap.set(h.hid, null); if (heroCount > 1) { let { pieceId, count } = transPiece(h.hid); @@ -457,25 +459,12 @@ export async function createHeroes(roleId: string, roleName: string, sid: string } let resultHeroes: HeroType[] = [], resultItems: RewardInter[] = []; - if (newHeroInfo.length > 0) { - - console.log('****** pubCreateHeroes before', Date.now()) - let { heroes, role, figureInfo, calHeroResults, calAllHeroResult, taskPushMessage, activityTaskPushMessage } = await pubCreateHeroes(roleId, roleName, serverId, newHeroInfo, funcs); - - console.log('****** pubCreateHeroes after', Date.now()) - let r = new Rank(REDIS_KEY.HERO_NUM_RANK, { serverId }); - await r.setRankWithRoleInfo(roleId, role.heroNum, role.heroNumUpdatedAt, role); - - await pushFigureUpdate(roleId, sid, figureInfo); - - // await pushCalAllHeroCe(roleId, sid, calAllHeroResult); - for (let calHeroResult of calHeroResults) { - await pushCalPlayerCe(roleId, sid, calHeroResult); - } - - pushTaskUpdate(roleId, sid, null, taskPushMessage); - pushActivityUpdate(roleId, sid, null, activityTaskPushMessage); - resultHeroes = heroes; + if (infos.size > 0) { + let createHero = new CreateHeroes(roleId, roleName, serverId, funcs); + await createHero.createWithHeroInfo(infos); + await createHero.pushMessage(pinus, sid); + await createHero.updateRedisRank(Rank); + resultHeroes = createHero.getResultHeroes(); } if (pieces.length > 0) { diff --git a/gm-server/app/service/Utils.ts b/gm-server/app/service/Utils.ts index 588b81fde..b20921e25 100644 --- a/gm-server/app/service/Utils.ts +++ b/gm-server/app/service/Utils.ts @@ -1,11 +1,42 @@ import { Service } from 'egg'; import * as pubUtils from '@pubUtils/util'; +import { HeroUpdate } from '@db/Hero'; +import { SkinUpdate } from '@db/Skin'; +import { getInitRoleInfo } from '@pubUtils/roleUtil'; const csprng = require('csprng'); /** * Utils Service */ export default class Utils extends Service { + + constructor(args) { + super(args); + + this.setInitRole(); + } + + private initHeroes: Map = new Map(); // hid => hero + private initSkins: Map = new Map(); // hid => skin + + public setInitRole() { + let result = getInitRoleInfo(); + let { 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); + } + } + + public getInitHeroById(hid: number) { + return { + heroInfo: this.initHeroes.get(hid), + skinInfo: this.initSkins.get(hid) + } + } + /** * 生成 len 长度的随机字符串 * @param len 长度 diff --git a/gm-server/app/service/users.ts b/gm-server/app/service/users.ts index 9db6611f2..559b97355 100644 --- a/gm-server/app/service/users.ts +++ b/gm-server/app/service/users.ts @@ -23,7 +23,7 @@ import Counter from '@db/Counter'; import { STATUS, HERO_SYSTEM_TYPE } from '@consts'; import { ITID, COUNTER } from '@consts'; import { ItemModel } from '@db/Item'; -import { gameData, getHeroExpByLv, getExpByLv } from '@pubUtils/data'; +import { gameData, getExpByLv } from '@pubUtils/data'; import { calPlayerCeAndSave, calculatetopLineup, calEquipSeids } from '@pubUtils/playerCe'; import { SchoolModel } from '@db/School'; import { AttributeCal } from '@domain/roleField/attribute'; @@ -32,9 +32,10 @@ import { isString } from 'underscore'; import { FriendShipModel } from '@db/FriendShip'; import { FriendApplyModel } from '@db/FriendApply'; import { FriendRelationModel } from '@db/FriendRelation'; -import { createHero as pubCreateHero, addSkin, addEquips, addBags } from '@pubUtils/itemUtils'; +import { addSkin, addEquips, addBags } from '@pubUtils/itemUtils'; import { GiftCodeModel } from '@db/GiftCode'; import { GiftCodeDetailModel } from '@db/GiftCodeDetail'; +import { CreateHeroes } from '@pubUtils/roleUtil'; // import { resResult } from '@pubUtils/util'; // import * as fs from 'fs'; @@ -240,38 +241,32 @@ export default class GMUsers extends Service { public async createHero(uids: Array, _hid: string, _hlv: string) { const { ctx } = this; - console.log('gm createHero', uids, _hid, _hlv); - let hlv = parseInt(_hlv); - if (isNaN(hlv)) return ctx.service.utils.resResult(STATUS.WRONG_PARMS); - let hids = (_hid as string).split('&').map(cur => parseInt(cur)); - for (let hid of hids) { - if (isNaN(hid)) return ctx.service.utils.resResult(STATUS.WRONG_PARMS); - } - - let heroInfos = new Array(); - for (let roleId of uids) { - let role = await RoleModel.findByRoleId(roleId); - if (role) { - for (let hid of hids) { - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if (hero) continue; - let dicHero = gameData.hero.get(hid); - if (!dicHero) continue; - const heroInfo = { - roleId, roleName: role.roleName, hid, serverId: role.serverId, - lv: hlv, exp: getHeroExpByLv(hlv - 1) || 0 - } - heroInfos.push(heroInfo); - } - } else { - return ctx.service.utils.resResult(STATUS.GM_CREATE_ERROR, null, '未找到角色' + roleId) - } - } - try { - for (let heroInfo of heroInfos) { - await pubCreateHero(heroInfo.roleId, heroInfo.roleName, heroInfo.serverId, heroInfo); + console.log('gm createHero', uids, _hid, _hlv); + let hlv = parseInt(_hlv); + if (isNaN(hlv)) return ctx.service.utils.resResult(STATUS.WRONG_PARMS); + let hids = (_hid as string).split('&').map(cur => parseInt(cur)); + for (let hid of hids) { + if (isNaN(hid)) return ctx.service.utils.resResult(STATUS.WRONG_PARMS); } + + for (let roleId of uids) { + let role = await RoleModel.findByRoleId(roleId); + if (role) { + let heroInfos = new Map(); + for (let hid of hids) { + let heroInfo = ctx.service.utils.getInitHeroById(hid); + heroInfos.set(hid, {...heroInfo}); + } + + let createHero = new CreateHeroes(roleId, role.roleName, role.serverId); + await createHero.createWithHeroInfo(heroInfos); + + } else { + return ctx.service.utils.resResult(STATUS.GM_CREATE_ERROR, null, '未找到角色' + roleId) + } + } + return ctx.service.utils.resResult(STATUS.SUCCESS, { uids }); } catch (e) { console.error(e.stack) diff --git a/shared/db/Role.ts b/shared/db/Role.ts index 6193b6d00..4c2921dfd 100644 --- a/shared/db/Role.ts +++ b/shared/db/Role.ts @@ -728,7 +728,7 @@ export const RoleModel = getModelForClass(Role); export interface RoleType extends Pick, keyof Role> { }; export type RoleUpdate = Partial; // 将所有字段变成可选项 -export type RoleInc = Partial, 'heroNum' | 'blockCnt' | 'friendCnt' | 'gold' | 'coin'>>; +export type RoleInc = Partial, 'heroNum' | 'blockCnt' | 'friendCnt' | 'gold' | 'coin' | 'ce'>>; // 初始化 function getInitialTeraph() { diff --git a/shared/db/Skin.ts b/shared/db/Skin.ts index d5663cfaf..a500de023 100644 --- a/shared/db/Skin.ts +++ b/shared/db/Skin.ts @@ -34,7 +34,7 @@ export default class Skin extends BaseModel { 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); diff --git a/shared/domain/roleField/calCe.ts b/shared/domain/roleField/calCe.ts index b7e42bb04..9eb206ee0 100644 --- a/shared/domain/roleField/calCe.ts +++ b/shared/domain/roleField/calCe.ts @@ -196,7 +196,7 @@ export class CalHeroCe { } // 添加技能增加的被动属性 -function addSeidEffect(this: CalRoleCe, seidList: number[]) { +function addSeidEffect(this: CalRoleCe|CalHeroCe, seidList: number[]) { console.log('******addSeidEffect',this, seidList) // console.log('addSeidList', addSeidList.join()) diff --git a/shared/pubUtils/itemUtils.ts b/shared/pubUtils/itemUtils.ts index b093c506d..397e8e1bc 100644 --- a/shared/pubUtils/itemUtils.ts +++ b/shared/pubUtils/itemUtils.ts @@ -1,6 +1,6 @@ -import { HeroModel, HeroType, HeroUpdate } from '../db/Hero'; +import { HeroModel, HeroType, } from '../db/Hero'; import { ItemModel } from '../db/Item'; import { EquipModel, RandSe, Holes, RandMain, equipUpdate } from './../db/Equip'; import { gameData, getQuenchByQualityAndGrade, getQuenchGradeByValue } from './data'; @@ -10,12 +10,11 @@ import { getRandValueByMinMax, getRandEelm } from './util'; import { findWhere } from 'underscore'; 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 { getTimeFun } from './timeUtil'; +import { reCalAllHeroCe } from './playerCe'; +import { checkTaskWithEquip } from './taskUtil'; // import { checkTask, checkTaskWithHeroes, checkTaskWithEquip, accomplishTask } from './taskUtil'; -import { CreateHeroParam } from '../domain/roleField/hero'; -import { SkinModel, SkinType, SkinUpdate, } from '../db/Skin'; +import { SkinModel, } from '../db/Skin'; import { TaskListReturn } from '../domain/roleField/task'; /** @@ -185,16 +184,14 @@ export function getFriendPointObject(count: number) { export function getHonourObject(count: number) { return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.HONOUR), count }; } + /** - * 解锁头像/相框 - * @param roleId 玩家id + * 返回 解锁头像/相框 * @param conditions 解锁条件 * @param role 如果已查询过role表就直接可以使用 */ -export async function unlockFigure(roleId: string, conditions: { type: number, paramHid?: number, paramFavourLv?: number, paramSkinId?: number }[], role?: RoleType) { - if (!role || !role.heads || !role.frames) { - role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_HEADS); - } + export function unlockFigureWithoutSave(conditions: { type: number, paramHid?: number, paramFavourLv?: number, paramSkinId?: number }[], role: RoleType) { + let { heads, frames, spines } = role; let figureInfo = { heads: new Array
(), frames: new Array
(), spines: new Array
() }; for (let { type, paramHid, paramFavourLv, paramSkinId } of conditions) { @@ -235,6 +232,20 @@ export async function unlockFigure(roleId: string, conditions: { type: number, p } } + return { figureInfo, heads, frames, spines }; +} + +/** + * 解锁头像/相框 + * @param roleId 玩家id + * @param conditions 解锁条件 + * @param role 如果已查询过role表就直接可以使用 + */ +export async function unlockFigure(roleId: string, conditions: { type: number, paramHid?: number, paramFavourLv?: number, paramSkinId?: number }[], role?: RoleType) { + if (!role || !role.heads || !role.frames) { + role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_HEADS); + } + let { figureInfo, heads, frames, spines } = unlockFigureWithoutSave(conditions, role); role = await RoleModel.updateRoleInfo(roleId, { heads, frames, spines }); return figureInfo; } @@ -314,108 +325,17 @@ function unlockSingleFigure(dbFigures: Figure[], id: number, unlockDirect = fals return figure } -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: { id: number, skin: string, enable: boolean }[] = []; - for(let skin of allSkins) { - skins.push({ id: skin.id, skin: skin._id, enable: skin.id == initialSkin }); - } +// 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: { id: number, skin: string, enable: boolean }[] = []; +// for(let skin of allSkins) { +// skins.push({ id: skin.id, skin: skin._id, enable: skin.id == initialSkin }); +// } - return skins -} - -/** - * 创建武将 - * @param roleId 玩家id - * @param roleName 玩家名 - * @param serverId 服务器id - * @param {CreateHeroParam} heroInfo 创建武将所需信息 - * @param funcs 玩家开启了的功能,主要用于任务 - */ -export async function createHero(roleId: string, roleName: string, serverId: number, heroInfo: CreateHeroParam, funcs?: number[]) { - let { role, figureInfo, heroes, calHeroResults, calAllHeroResult, taskPushMessage, activityTaskPushMessage } = await createHeroes(roleId, roleName, serverId, [heroInfo], funcs) - return { hero: heroes[0], role, figureInfo, calHeroResult: calHeroResults[0], calAllHeroResult, taskPushMessage, activityTaskPushMessage } -} - -export async function createHeroes(roleId: string, roleName: string, serverId: number, heroInfos: CreateHeroParam[], funcs?: number[]) { - - let heroNum = 0; - let conditions = new Array<{ type: number, paramHid?: number, paramFavourLv?: number, paramSkinId?: number }>(); - let heroes: HeroType[] = [], calHeroResults = [], calAllHeroResult = undefined; - let figureInfos:{ heads: Figure[], frames: Figure[], spines: Figure[] }[] = []; - - for (let heroInfo of heroInfos) { - let dicHero = gameData.hero.get(heroInfo.hid); - let { quality, initialStars: star, jobid: job, name: hName, initialSkin } = dicHero; - - let info = { roleId, roleName, serverId, quality, star, job, hName }; - - let skins = await getSkinsOfThisHero(roleId, roleName, heroInfo.hid, initialSkin); - - let curHero = await HeroModel.createHero(Object.assign(info, heroInfo, { skins })); - - // 计算初始战力 - let calHeroResult = await calPlayerCeAndSave(HERO_SYSTEM_TYPE.INIT, roleId, curHero, {}); - calHeroResults.push(calHeroResult); - heroes.push(calHeroResult.hero); - conditions.push({ type: FIGURE_UNLOCK_CONDITION.GET_HERO, paramHid: heroInfo.hid }); - heroNum++; - } - figureInfos.push(await unlockFigure(roleId, conditions)); // 解锁头像 - - let role = await RoleModel.incRoleInfo(roleId, { heroNum }, { heroNumUpdatedAt: nowSeconds() }); - // 任务 - 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 { 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 } -} +// return skins +// } export function combineFigureInfo(figureInfos: { heads: Figure[], frames: Figure[], spines: Figure[] }[]) { let figureInfo = { heads: new Array
(), frames: new Array
(), spines: new Array
() }; diff --git a/shared/pubUtils/roleUtil.ts b/shared/pubUtils/roleUtil.ts index 9e05858dd..107969bf0 100644 --- a/shared/pubUtils/roleUtil.ts +++ b/shared/pubUtils/roleUtil.ts @@ -1,21 +1,32 @@ -import { DEFAULT_HERO_LV, LINEUP_NUM } from "../consts"; +import { DEFAULT_HERO_LV, FIGURE_UNLOCK_CONDITION, LINEUP_NUM, REDIS_KEY, STATUS, TASK_TYPE } 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 { DEFAULT_HEROES, DEFAULT_LV, HERO_SYSTEM_TYPE } from "../consts"; +import { HeroModel, HeroType, HeroUpdate } from "../db/Hero"; +import { RoleModel, RoleType, RoleUpdate } from "../db/Role"; import { SkinUpdate } from "../db/Skin"; -import { TopHero } from "../domain/dbGeneral"; +import { Figure, TopHero } from "../domain/dbGeneral"; import { CalHeroCe, CalRoleCe } from "../domain/roleField/calCe"; import { gameData, getHeroExpByLv } from "../pubUtils/data"; +import { accomplishTask, checkTask, checkTaskWithHeroes } from './taskUtil'; +import { combineFigureInfo, unlockFigure, unlockFigureWithoutSave } from './itemUtils'; +import { TaskListReturn } from "../domain/roleField/task"; +import { nowSeconds } from "./timeUtil"; +import { reduceCe, resResult } from "./util"; +import { calculatetopLineup, calPlayerCeAndSave } from "./playerCe"; +import { GuildModel, GuildType } from "../db/Guild"; +import { PvpDefenseModel } from "../db/PvpDefense"; +import { CreateHeroParam } from "../domain/roleField/hero"; // 储存在内存中的初始数据 export function getInitRoleInfo() { - let topLineup: TopHero[] = [], topLineupCe = 0, allCe = 0, initHeroes: HeroUpdate[] = [], initSkins: SkinUpdate[] = [], heroNum = 0; + let topLineup: TopHero[] = [], topLineupCe = 0, allCe = 0, + heroes: HeroUpdate[] = [], initHeroes: HeroUpdate[] = [], initSkins: SkinUpdate[] = [], heroNum = 0, + conditions: {type: FIGURE_UNLOCK_CONDITION, paramHid: number }[] = []; let role = new RoleModel(); let calRoleCe = new CalRoleCe(role); let roleAttr = calRoleCe.cal(HERO_SYSTEM_TYPE.INIT); - for(let hid of DEFAULT_HEROES) { + for(let { actorId: hid } of gameData.recruit) { let { quality, initialStars: star, jobid: job, name: hName, initialSkin } = gameData.hero.get(hid); // 皮肤 let skin = new SkinModel(); @@ -28,10 +39,17 @@ export function getInitRoleInfo() { 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++; + heroes.push({ ...heroInfo, attr: heroAttr, ce, historyCe: ce }); + // 更新role表 + if(DEFAULT_HEROES.includes(hid)) { + // 头像 + conditions.push({ type: FIGURE_UNLOCK_CONDITION.GET_HERO, paramHid: hid }); + allCe += ce; + heroNum++; + initHeroes.push({ ...heroInfo, attr: heroAttr, ce, historyCe: ce }); + } } + let { figureInfo, heads, frames, spines } = unlockFigureWithoutSave(conditions, role); // 最强阵容 initHeroes.sort((a, b) => { return b.ce - a.ce }); for(let i = 0; i < LINEUP_NUM; i++) { @@ -42,8 +60,222 @@ export function getInitRoleInfo() { } } - let initRole: RoleUpdate = { topLineupCe, topLineup, attr: roleAttr, ce: allCe, lv: DEFAULT_LV, gold: DEFAULT_GOLD, coin: DEFAULT_COIN, heroNum, heroNumUpdatedAt: Date.now() }; + let initRole: RoleUpdate = { topLineupCe, topLineup, attr: roleAttr, ce: allCe, lv: DEFAULT_LV, exp: getHeroExpByLv(DEFAULT_HERO_LV - 1) || 0, heroNum, heroNumUpdatedAt: Date.now(), heads, frames, spines }; return { - role: initRole, heroes: initHeroes, skins: initSkins + role: initRole, heroes, skins: initSkins, figureInfo + } +} + +export class UpdateHeroes { + roleId: string; + roleName: string; + serverId: number; + funcs: number[] = []; + incHeroNum: number = 0; + incRoleCe: number = 0; + pushHeroes: {hid: number, incHeroCe: number, ce: number}[] = []; + roleUpdate: RoleUpdate; + role: RoleType; + guild: GuildType; + + constructor(roleId: string, roleName: string, serverId: number, funcs?: number[]) { + this.roleId = roleId; + this.roleName = roleName; + this.serverId = serverId; + if(funcs) this.funcs = funcs; + } + + public setRole(role: RoleType) { + this.role = role; + } + + public async getRole() { + if(!this.role) { + this.role = await RoleModel.findByRoleId(this.roleId); + } + return this.role; + } + + public addRoleUpdateParam(param: RoleUpdate) { + this.roleUpdate = {...this.roleUpdate, ...param}; + } + + public async updateDbCe(isCreate: boolean, heroInfo: HeroUpdate, originCe = 0) { + let role = await this.getRole(); + if(isCreate) this.incHeroNum ++; + if(heroInfo != originCe) this.incRoleCe += heroInfo.ce - originCe; + this.addRoleUpdateParam(await calculatetopLineup(role, heroInfo.hid, heroInfo.ce, heroInfo._id )); + this.pushHeroes.push({ hid: heroInfo.hid, incHeroCe: heroInfo.ce - originCe, ce: heroInfo.ce }); + } + + // 更新战力相关的各个表 + public async saveCeToDb() { + let role = await this.getRole(); + // 更新role表 + this.role = await RoleModel.updateRoleInfo(this.roleId, { + heroNum: this.incHeroNum + role.heroNum, ce: this.incRoleCe + role.ce, heroNumUpdatedAt: nowSeconds(), ...this.roleUpdate + }); + + // 更新guild表 + if(role.hasGuild) { + this.guild = await GuildModel.updateCe(this.roleId, this.incRoleCe); // 公会更新战力 + } + for(let { hid, incHeroCe } of this.pushHeroes) { + await PvpDefenseModel.updateCe(this.roleId, hid, incHeroCe); // 更新pvp防守阵战力 + } + } + + public async updateRedisRank(Rank: any) { + let role = await this.getRole(); + let { serverId, roleId, pushHeroes } = this; + // 更新军团信息 + if(this.guild) { + let r = new Rank(REDIS_KEY.GUILD_INFO, { code: this.guild.code }); + await r.generParamAndSet(REDIS_KEY.GUILD_INFO, { roleId }, { role }); + } + // 武将数量 + if(this.incHeroNum > 0) { + let r = new Rank(REDIS_KEY.HERO_NUM_RANK, { serverId }); + await r.setRankWithRoleInfo(roleId, role.heroNum, role.heroNumUpdatedAt, role); + } + + // 最强阵容 + let r = new Rank(REDIS_KEY.TOP_LINEUP_RANK, { serverId }); + await r.setRankWithRoleInfo(roleId, reduceCe(role.topLineupCe), 0, role); + + // 最强武将 + for(let { hid, ce } of pushHeroes) { + let r2 = new Rank(REDIS_KEY.TOP_HERO_RANK, { serverId }); + await r2.setRankWithHeroInfo(roleId, hid, ce, 0); + + let r4 = new Rank(REDIS_KEY.HERO_RANK, { serverId, hid }); + await r4.setRankWithHeroInfo(roleId, hid, ce, 0); + } + + // 总战力 + let r3 = new Rank(REDIS_KEY.SUM_CE_RANK, { serverId }); + await r3.setRankWithRoleInfo(roleId, reduceCe(role.ce), 0, role); + + // 更新最强五人阵容信息 + let r5 = new Rank(REDIS_KEY.TOP_LINEUP_INFO, { serverId }); + await r5.generParamAndSet(REDIS_KEY.TOP_LINEUP_INFO, { roleId }, { role }); + } + + public async pushMessage(pinus: any, sid: string) { + let role = await this.getRole(); + let uids = [{ uid: this.roleId, sid }]; + pinus.app.get('channelService').pushMessageByUids('onPlayerCeUpdate', resResult(STATUS.SUCCESS, { ce: reduceCe(role.ce) , heros: this.pushHeroes.map(cur => { return {...cur, ce: reduceCe(cur.ce), incHeroCe: reduceCe(cur.incHeroCe) }}), topLineupCe: reduceCe(role.topLineupCe) }), uids); + } + +} + +export class CreateHeroes extends UpdateHeroes { + private resultHeroes: HeroType[] = []; + private heroNum = 0; + // 推送信息 + private taskPushMessage: TaskListReturn[] = []; + private activityTaskPushMessage = []; + private figureInfos: { heads: Figure[], frames: Figure[], spines: Figure[] }[] = []; + + // web-server和gm-server里面创建 + public async calWithParam(heroInfos: CreateHeroParam[]) { + let heroNum = 0; + let conditions = new Array<{ type: number, paramHid?: number, paramFavourLv?: number, paramSkinId?: number }>(); + + for (let heroInfo of heroInfos) { + let dicHero = gameData.hero.get(heroInfo.hid); + let { quality, initialStars: star, jobid: job, name: hName, initialSkin } = dicHero; + let info = { roleId: this.roleId, roleName: this.roleName, serverId: this.serverId, quality, star, job, hName }; + let skin = new SkinModel(); + let dicFashion = gameData.fashion.get(initialSkin); + let skins = await this.getSkinsOfThisHero(heroInfo.hid, { ...skin.toJSON(), id: initialSkin, hid: heroInfo.hid, skinName: dicFashion.name }); + let curHero = await HeroModel.createHero(Object.assign(info, heroInfo, { skins })); + + // 计算初始战力 + await calPlayerCeAndSave(HERO_SYSTEM_TYPE.INIT, this.roleId, curHero, {}); + conditions.push({ type: FIGURE_UNLOCK_CONDITION.GET_HERO, paramHid: heroInfo.hid }); + heroNum++; + } + this.figureInfos.push(await unlockFigure(this.roleId, conditions)); // 解锁头像 + + await RoleModel.incRoleInfo(this.roleId, { heroNum }, { heroNumUpdatedAt: nowSeconds() }); + await this.clearTask(); + } + + private async getSkinsOfThisHero(hid: number, initSkinInfo: SkinUpdate) { + let allSkins = await SkinModel.findbyRoleAndHid(this.roleId, hid); + let skin = await SkinModel.insertSkins(this.roleId, this.roleName, [initSkinInfo]); + if(skin) allSkins.push(...skin); + let skins: { id: number, skin: string, enable: boolean }[] = []; + for(let skin of allSkins) { + skins.push({ id: skin.id, skin: skin._id, enable: skin.id == initSkinInfo.id }); + } + return skins + } + + // game-server里面创建武将 + public async createWithHeroInfo(infos: Map) { + let role = await this.getRole(); + // 数据处理 + let conditions = new Array<{ type: number, paramHid?: number, paramFavourLv?: number, paramSkinId?: number }>(); // 解锁头像条件 + let initHeroInfos: HeroUpdate[] = []; + for (let [ hid, { heroInfo, skinInfo }] of infos) { + conditions.push({ type: FIGURE_UNLOCK_CONDITION.GET_HERO, paramHid: heroInfo.hid }); + this.updateDbCe(true, heroInfo); + // 皮肤使用初始加载进内存的数据 + let skins = await this.getSkinsOfThisHero(hid, skinInfo); + initHeroInfos.push({ ...heroInfo, skins }); + } + // 武将使用初始加载数据插入 + this.resultHeroes = await HeroModel.insertHeroes(this.roleId, this.roleName, this.serverId, initHeroInfos); + // 头像解锁 + let { figureInfo, frames, heads, spines } = unlockFigureWithoutSave(conditions, role); + this.figureInfos.push(figureInfo); + this.addRoleUpdateParam({ frames, heads, spines }); + // 更新战力 + await this.saveCeToDb(); + await this.clearTask(); + } + + // 创建初始账号时候的初始 + public async createWithInitInfo(heroeInfos: HeroUpdate[], skinInfos: SkinUpdate[], figureInfo: { heads: Figure[], frames: Figure[], spines: Figure[] }) { + this.figureInfos.push(figureInfo); + for(let heroInfo of heroeInfos) this.updateDbCe(true, heroInfo); + this.resultHeroes = await HeroModel.insertHeroes(this.roleId, this.roleName, this.serverId, heroeInfos); + await SkinModel.insertSkins(this.roleId, this.roleName, skinInfos); + await this.clearTask(); + } + + private async clearTask() { + // 任务 + console.log('****** checkTask before', Date.now()) + let m1 = await checkTask(this.roleId, TASK_TYPE.HERO_NUM, this.heroNum, true, {}, this.funcs); + let m2 = await checkTaskWithHeroes(this.roleId, TASK_TYPE.HERO_QUALITY, this.resultHeroes, this.funcs); + let m3 = await checkTaskWithHeroes(this.roleId, TASK_TYPE.HERO_QUALITY_STAR_UP, this.resultHeroes, this.funcs); + let m4 = await checkTaskWithHeroes(this.roleId, TASK_TYPE.HERO_LV, this.resultHeroes, this.funcs); + this.taskPushMessage.push(...m1, ...m2, ...m3, ...m4); + console.log('****** checkTask after', Date.now()) + //成长任务 + console.log('****** accomplishTask before', Date.now()) + let mm1 = await accomplishTask(this.serverId, this.roleId, TASK_TYPE.HERO_NUM, this.heroNum) + let mm2 = await accomplishTask(this.serverId, this.roleId, TASK_TYPE.HERO_QUALITY, this.heroNum, { heroes: this.resultHeroes }) + console.log('****** accomplishTask after', Date.now()) + this.activityTaskPushMessage.push(...mm1, ...mm2); + } + + public async pushMessage(pinus: any, sid: string) { + let role = await this.getRole(); + let uids = [{ uid: this.roleId, sid }]; + pinus.app.get('channelService').pushMessageByUids('onPlayerCeUpdate', resResult(STATUS.SUCCESS, { ce: reduceCe(role.ce) , heros: this.pushHeroes.map(cur => { return {...cur, ce: reduceCe(cur.ce), incHeroCe: reduceCe(cur.incHeroCe) }}), topLineupCe: reduceCe(role.topLineupCe) }), uids); + pinus.app.get('channelService').pushMessageByUids('onTaskUpdate', resResult(STATUS.SUCCESS, this.taskPushMessage), uids); + pinus.app.get('channelService').pushMessageByUids('onActivityUpdate', resResult(STATUS.SUCCESS, this.activityTaskPushMessage), uids); + let figureInfo = combineFigureInfo(this.figureInfos); + if (!!figureInfo && (figureInfo.heads.length > 0 || figureInfo.frames.length > 0 || figureInfo.spines.length > 0)) { + pinus.app.get('channelService').pushMessageByUids('onHeadChange', resResult(STATUS.SUCCESS, { ...figureInfo }), uids); + } + } + + public getResultHeroes() { + return this.resultHeroes; } } \ No newline at end of file