Merge branch 'ce'

# Conflicts:
#	game-server/app.ts
This commit is contained in:
luying
2021-09-02 20:37:02 +08:00
19 changed files with 816 additions and 218 deletions

View File

@@ -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';
@@ -118,10 +117,6 @@ app.configure(ALL_ENVS, 'gate', function () {
});
});
app.configure(ALL_ENVS, 'gm', function () {
init();//将gm后台数据加载到gate服
});
app.configure(ALL_ENVS, 'guild', function () {
app.filter(guildAuthFilter(app));
})

View File

@@ -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);
// 更新数据

View File

@@ -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';
@@ -20,7 +20,9 @@ import { checkTaskWithHero, checkTask, checkTaskWithArgs, checkActivityTask } fr
import { getGoldObject, getCoinObject } from '../../../pubUtils/itemUtils';
import { RScriptRecordModel } from '../../../db/RScriptRecord';
import { checkPvp } from '../../../services/pvpService';
import { pushData } from '../../../services/connectorService';
import { SkinModel, SkinUpdate } from '../../../db/Skin';
import { CreateHeroes } from '../../../pubUtils/roleUtil';
import { Figure } from '../../../domain/dbGeneral';
export default function (app: Application) {
new HandlerService(app, {});
@@ -45,15 +47,16 @@ 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[], 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 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);
session.push('roleName', () => { });
@@ -61,19 +64,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 +522,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)
}
}

View File

@@ -1,8 +1,12 @@
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';
import { Figure } from '../../../domain/dbGeneral';
export default function (app: Application) {
new HandlerService(app, {});
return new RoleRemote(app);
@@ -13,13 +17,59 @@ export class RoleRemote {
constructor(private app: Application) {
this.app = app;
this.channelService = app.get('channelService');
this.setInitRole();
}
private channelService: ChannelService;
private initHeroes: Map<number, HeroUpdate> = new Map(); // hid => hero
private initRole: RoleUpdate = {};
private initSkins: Map<number, SkinUpdate> = new Map(); // hid => skin
private figureInfo: {heads: Figure[], frames: Figure[], spines: Figure[]};
public setInitRole() {
let result = getInitRoleInfo();
let { role, heroes, skins, figureInfo } = 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;
this.figureInfo = figureInfo;
}
public getInitRoleInfos() {
return {
heroes: this.getInitHeroes(),
skins: this.getInitSkins(),
role: this.initRole,
figureInfo: this.figureInfo
};
}
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 {
heroInfo: this.initHeroes.get(hid),
skinInfo: this.initSkins.get(hid)
}
}
// sendGmMailsToRoles(mails) {
// sendRolesMails(mails)
// }
/**
* 重载json资源

View File

@@ -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';

View File

@@ -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);

View File

@@ -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<number, { heroInfo: HeroUpdate, skinInfo: SkinUpdate }> = 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) {

View File

@@ -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';

View File

@@ -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<number, HeroUpdate> = new Map(); // hid => hero
private initSkins: Map<number, SkinUpdate> = 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 长度

View File

@@ -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<string>, _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)

View File

@@ -152,12 +152,19 @@ export const HERO_ATTR = {
28: "strikeBack", // 反击伤害
};
export const ABI_TYPE_TO_STAGE = new Map<number, number>([
[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<number, number>();
export const ABI_STAGE_TO_TYPE = new Map<number, number>();
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];

View File

@@ -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<CeAttrData>;
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 } },

View File

@@ -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<CeAttrDataRole>;
// 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<number, number>();
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<number, number>) {
value.forEach((val, id) => {
if (id == ABI_TYPE.ABI_HP) this.hp = val;
@@ -704,7 +728,7 @@ export const RoleModel = getModelForClass(Role);
export interface RoleType extends Pick<DocumentType<Role>, keyof Role> { };
export type RoleUpdate = Partial<RoleType>; // 将所有字段变成可选项
export type RoleInc = Partial<Pick<DocumentType<Role>, 'heroNum' | 'blockCnt' | 'friendCnt' | 'gold' | 'coin'>>;
export type RoleInc = Partial<Pick<DocumentType<Role>, 'heroNum' | 'blockCnt' | 'friendCnt' | 'gold' | 'coin' | 'ce'>>;
// 初始化
function getInitialTeraph() {

View File

@@ -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<DocumentType<Skin>, keyof Skin> {
id: number;
};
export type SkinUpdate = Partial<SkinType>; // 将所有字段变成可选项

View File

@@ -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<number, number> = new Map<number, number>();
ce?: number = 0;

View File

@@ -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<ABI_TYPE, CeAttrDataRole> = 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<ABI_TYPE, CeAttrData> = 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<number, number>(); // 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|CalHeroCe, 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);
}

View File

@@ -1,6 +1,6 @@
import { HeroModel, HeroType } 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';
@@ -8,14 +8,13 @@ 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 { 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 } 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<Figure>(), frames: new Array<Figure>(), spines: new Array<Figure>() };
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,75 +325,17 @@ 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);
let skin = await increaseSkin(roleId, roleName, initialSkin);
if(skin) allSkins.push(skin);
let skins = [];
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 }
}
// return skins
// }
export function combineFigureInfo(figureInfos: { heads: Figure[], frames: Figure[], spines: Figure[] }[]) {
let figureInfo = { heads: new Array<Figure>(), frames: new Array<Figure>(), spines: new Array<Figure>() };
@@ -404,4 +357,14 @@ export function transPiece(hid: number) {
let dicHero = gameData.hero.get(hid);
let count = gameData.heroTransPiece.get(dicHero.quality);
return { pieceId: dicHero.pieceId, count }
}
}
// export class CreateHero {
// roleId: string;
// roleName: string;
// serverId: number;
// constructor(roleId: string, roleName: string, serverId: number) {
// }
// }

View File

@@ -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';

281
shared/pubUtils/roleUtil.ts Normal file
View File

@@ -0,0 +1,281 @@
import { DEFAULT_HERO_LV, FIGURE_UNLOCK_CONDITION, LINEUP_NUM, REDIS_KEY, STATUS, TASK_TYPE } from "../consts";
import { SkinModel } from "../db/Skin";
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 { 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,
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 { actorId: hid } of gameData.recruit) {
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);
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++) {
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, exp: getHeroExpByLv(DEFAULT_HERO_LV - 1) || 0, heroNum, heroNumUpdatedAt: Date.now(), heads, frames, spines };
return {
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<number, { heroInfo: HeroUpdate, skinInfo: SkinUpdate }>) {
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;
}
}