275 lines
13 KiB
TypeScript
275 lines
13 KiB
TypeScript
import { FIGURE_UNLOCK_CONDITION, ITEM_CHANGE_REASON, REDIS_KEY, STATUS, TASK_TYPE, HERO_SYSTEM_TYPE } from "../../consts";
|
|
import { SkinModel } from "../../db/Skin";
|
|
import { HeroModel, HeroSkin, HeroType, HeroUpdate } from "../../db/Hero";
|
|
import { RoleModel, RoleType, RoleUpdate } from "../../db/Role";
|
|
import { SkinUpdate } from "../../db/Skin";
|
|
import { Figure, TopHero } from "../../domain/dbGeneral";
|
|
import { TaskListReturn } from "../../domain/roleField/task";
|
|
import { GuildModel, GuildType } from "../../db/Guild";
|
|
import { PvpDefenseModel } from "../../db/PvpDefense";
|
|
import { pick } from "underscore";
|
|
import { calculatetopLineup } from "../../pubUtils/playerCe";
|
|
import { nowSeconds } from "../../pubUtils/timeUtil";
|
|
import { saveCeChangeLog } from "../../pubUtils/logUtil";
|
|
import { getRandSingleEelm, reduceCe, resResult } from "../../pubUtils/util";
|
|
import { AttributeCal } from "../../domain/roleField/attribute";
|
|
import { CreateHeroParam, HeroShowParam } from "../../domain/roleField/hero";
|
|
import { pinus } from "pinus";
|
|
import { Rank } from "../rankService";
|
|
import { checkTaskInCreateHero } from "../task/taskService";
|
|
import { ItemInter, RewardInter } from "../../pubUtils/interface";
|
|
import { transPiece } from "./util";
|
|
import { getInitHeroById } from "../roleService";
|
|
import { addItems, combineFigureInfo, unlockFigureWithoutSave } from "./rewardService";
|
|
|
|
export class UpdateHeroes {
|
|
roleId: string;
|
|
roleName: string;
|
|
serverId: number;
|
|
incHeroNum: number = 0;
|
|
incRoleCe: number = 0;
|
|
pushHeroes: {hid: number, incHeroCe: number, ce: number, hero: HeroUpdate}[] = [];
|
|
roleUpdate: RoleUpdate;
|
|
role: RoleType;
|
|
guild: GuildType;
|
|
|
|
constructor(roleId: string, roleName: string, serverId: number) {
|
|
this.roleId = roleId;
|
|
this.roleName = roleName;
|
|
this.serverId = serverId;
|
|
}
|
|
|
|
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, hero: heroInfo });
|
|
}
|
|
|
|
// 更新战力相关的各个表
|
|
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, true); // 公会更新战力
|
|
}
|
|
for(let { hid, incHeroCe } of this.pushHeroes) {
|
|
await PvpDefenseModel.updateCe(this.roleId, hid, incHeroCe); // 更新pvp防守阵战力
|
|
}
|
|
saveCeChangeLog(this.role, this.incRoleCe, this.role.ce, HERO_SYSTEM_TYPE.INIT, this.pushHeroes.map(cur => cur.hid));
|
|
}
|
|
|
|
public async updateRedisRank() {
|
|
let role = await this.getRole();
|
|
let { serverId, roleId, pushHeroes } = this;
|
|
// 更新军团信息
|
|
if(this.guild) {
|
|
let r = new Rank(REDIS_KEY.GUILD_INFO, { guildCode: this.guild.code });
|
|
await r.generParamAndSet(REDIS_KEY.GUILD_INFO, { guildCode: this.guild.code }, { guild: this.guild });
|
|
}
|
|
// 武将数量
|
|
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, hero } of pushHeroes) {
|
|
let r2 = new Rank(REDIS_KEY.TOP_HERO_RANK, { serverId });
|
|
await r2.setRankWithHeroInfo(roleId, hid, reduceCe(ce), 0, hero);
|
|
|
|
let r4 = new Rank(REDIS_KEY.HERO_RANK, { serverId, hid });
|
|
await r4.setRankWithHeroInfo(roleId, hid, reduceCe(ce), 0, hero);
|
|
}
|
|
// 总战力
|
|
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 figureInfos: { heads: Figure[], frames: Figure[], spines: Figure[] }[] = [];
|
|
private skinPushMessages: { heros: {skins: HeroSkin[], hid: number}[], skins: {id: number, hid: number, inc: number, reason: number }[]} = { heros: [], skins: [] };
|
|
|
|
private async getSkinsOfThisHero(hid: number, initSkinInfo: SkinUpdate, isInit: boolean) {
|
|
let allSkins = isInit? []: await SkinModel.findbyRoleAndHid(this.roleId, hid);
|
|
let skin = await SkinModel.insertSkins(this.roleId, this.roleName, [initSkinInfo]);
|
|
let skinInfos = skin.map(cur => ({ id: cur.id, hid, inc: 1, reason: ITEM_CHANGE_REASON.GET_HERO_UNLOCK_SKIN}))
|
|
this.skinPushMessages.skins.push(...skinInfos);
|
|
if(skin) allSkins.push(...skin);
|
|
let skins: HeroSkin[] = [];
|
|
for(let skin of allSkins) {
|
|
skins.push(new HeroSkin(skin.id, skin.skinId, skin._id, 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, _id: new SkinModel()._id }, false);
|
|
let newAttr = new AttributeCal();
|
|
newAttr.setLv(heroInfo.lv);
|
|
newAttr.setByDbData(role.attr, heroInfo.attr);
|
|
let heroCe = newAttr.calCe(); // 计算最终战力
|
|
initHeroInfos.push({ ...heroInfo, skins, _id: new HeroModel()._id, ce: heroCe });
|
|
this.heroNum ++;
|
|
}
|
|
// 武将使用初始加载数据插入
|
|
this.resultHeroes = await HeroModel.insertHeroes(this.roleId, this.roleName, this.serverId, initHeroInfos);
|
|
let heroSkins = this.resultHeroes.map(cur => { return pick(cur, ['hid', 'skins']) });
|
|
|
|
this.skinPushMessages.heros.push(...heroSkins);
|
|
// 头像解锁
|
|
let { figureInfo, frames, heads, spines } = unlockFigureWithoutSave(conditions, role);
|
|
this.figureInfos.push(figureInfo);
|
|
this.addRoleUpdateParam({ frames, heads, spines });
|
|
// 更新战力
|
|
await this.saveCeToDb();
|
|
}
|
|
|
|
// 创建初始账号时候的初始
|
|
public async createWithInitInfo(infos: Map<number, { heroInfo: HeroUpdate, skinInfo: SkinUpdate }>, figureInfo: { heads: Figure[], frames: Figure[], spines: Figure[] }) {
|
|
this.figureInfos.push(figureInfo);
|
|
let heroeInfos: HeroUpdate[] = [];
|
|
for (let [ hid, { heroInfo, skinInfo }] of infos) {
|
|
this.updateDbCe(true, heroInfo);
|
|
let model = new SkinModel();
|
|
let skins = await this.getSkinsOfThisHero(hid, { ...skinInfo, _id: model._id }, true);
|
|
heroeInfos.push({ ...heroInfo, skins, _id: new HeroModel()._id});
|
|
this.heroNum ++;
|
|
}
|
|
this.resultHeroes = await HeroModel.insertHeroes(this.roleId, this.roleName, this.serverId, heroeInfos);
|
|
}
|
|
|
|
public async pushMessage(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);
|
|
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);
|
|
}
|
|
pinus.app.get('channelService').pushMessageByUids('onHeroSkinChange', resResult(STATUS.SUCCESS, this.skinPushMessages), uids);
|
|
pinus.app.get('channelService').pushMessageByUids('onHeroUpdate', resResult(STATUS.SUCCESS, { heroes: this.getResultHeroes() }), uids);
|
|
checkTaskInCreateHero(this.serverId, this.roleId, sid, this.heroNum, this.resultHeroes)
|
|
}
|
|
|
|
public getResultHeroes() {
|
|
return this.resultHeroes.map(cur => ({...cur, ce: reduceCe(cur.ce)}))
|
|
}
|
|
|
|
public getShowHeroes() {
|
|
return this.resultHeroes.map(cur => {
|
|
let hero = new HeroShowParam(cur);
|
|
return { ...hero, ce: reduceCe(cur.ce)}
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* 创建多个武将
|
|
* @param roleId
|
|
* @param sid
|
|
* @param serverId
|
|
* @param heroInfo
|
|
*/
|
|
export async function createHeroes(roleId: string, roleName: string, sid: string, serverId: number, heroInfo: CreateHeroParam[]) {
|
|
let hids = heroInfo.map(cur => cur.hid);
|
|
let userHeroesMap = await HeroModel.findMapByHidRange(hids, roleId);
|
|
|
|
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 {
|
|
let initInfo: { heroInfo: HeroUpdate, skinInfo: SkinUpdate };
|
|
if(pinus.app.getServerType() == 'role') {
|
|
initInfo = getInitHeroById(h.hid);
|
|
} else {
|
|
let roleServers = pinus.app.getServersByType('role');
|
|
let server = getRandSingleEelm(roleServers);
|
|
initInfo = await pinus.app.rpc.role.roleRemote.getInitHeroById.toServer(server.id, h.hid);
|
|
}
|
|
|
|
initInfo.heroInfo = { ...initInfo.heroInfo, ...h };
|
|
|
|
infos.set(h.hid, initInfo);
|
|
userHeroesMap.set(h.hid, null);
|
|
if (heroCount > 1) {
|
|
let { pieceId, count } = transPiece(h.hid);
|
|
pieces.push({ id: pieceId, count: count * (heroCount - 1) });
|
|
}
|
|
}
|
|
}
|
|
|
|
let resultHeroes: HeroType[] = [], resultItems: RewardInter[] = [], heroes: HeroShowParam[] = [];
|
|
if (infos.size > 0) {
|
|
let createHero = new CreateHeroes(roleId, roleName, serverId);
|
|
await createHero.createWithHeroInfo(infos);
|
|
await createHero.pushMessage(sid);
|
|
await createHero.updateRedisRank();
|
|
heroes = createHero.getShowHeroes();
|
|
resultHeroes = createHero.getResultHeroes();
|
|
}
|
|
|
|
if (pieces.length > 0) {
|
|
let goods = await addItems(roleId, roleName, sid, pieces, ITEM_CHANGE_REASON.HERO_TRANSFER_PIECE);
|
|
resultItems = goods;
|
|
}
|
|
return { heroes, resultHeroes, goods: resultItems }
|
|
}
|
|
|
|
export async function createHero(roleId: string, roleName: string, sid: string, serverId: number, heroInfo: CreateHeroParam) {
|
|
let result = await createHeroes(roleId, roleName, sid, serverId, [heroInfo]);
|
|
return result;
|
|
} |