创建武将

This commit is contained in:
陆莹
2022-03-25 14:14:36 +08:00
parent a394bae03e
commit 1bdace30f9
17 changed files with 747 additions and 357 deletions

View File

@@ -92,7 +92,6 @@ export class GuildRemote {
*/ */
private pushMessage(guildCode: string, path: string, message: any) { private pushMessage(guildCode: string, path: string, message: any) {
let channel = this.getChannel(guildCode); let channel = this.getChannel(guildCode);
console.log('##### channel', guildCode, channel)
if (!!channel) { if (!!channel) {
channel.pushMessage(path, resResult(STATUS.SUCCESS, message)); channel.pushMessage(path, resResult(STATUS.SUCCESS, message));
} }

View File

@@ -21,7 +21,7 @@ import { HeroModel } from '../../../db/Hero';
import { calAllHeroCe, calPlayerCeAndSave } from '../../../services/playerCeService'; import { calAllHeroCe, calPlayerCeAndSave } from '../../../services/playerCeService';
import { SkinModel } from '../../../db/Skin'; import { SkinModel } from '../../../db/Skin';
import { PvpDefenseModel } from '../../../db/PvpDefense'; import { PvpDefenseModel } from '../../../db/PvpDefense';
import { calculatetopLineup } from '../../../pubUtils/playerCe'; import { calculatetopLineup } from '../../../pubUtils/util';
import { createHeroes } from '../../../services/role/createHero'; import { createHeroes } from '../../../services/role/createHero';
let timer: NodeJS.Timer; let timer: NodeJS.Timer;

View File

@@ -11,14 +11,14 @@ import { gameData, getHeroExpByLv, getHeroStarByQuality, getHeroWakeByQuality, g
import { ItemInter, RewardInter } from '../../../pubUtils/interface'; import { ItemInter, RewardInter } from '../../../pubUtils/interface';
import { getDropItems, FIGURE_UNLOCK_CONDITION } from '../../../consts/constModules/itemConst' import { getDropItems, FIGURE_UNLOCK_CONDITION } from '../../../consts/constModules/itemConst'
import { pushComposeOrangeHero, pushHeroQualityUpMsg, pushHeroStarMax, pushHeroWakeUp } from '../../../services/chatService'; import { pushComposeOrangeHero, pushHeroQualityUpMsg, pushHeroStarMax, pushHeroWakeUp } from '../../../services/chatService';
import { calculatetopLineup } from '../../../pubUtils/playerCe'; import { calculatetopLineup } from '../../../pubUtils/util';
import { PvpDefenseModel } from '../../../db/PvpDefense'; import { PvpDefenseModel } from '../../../db/PvpDefense';
import { checkTask, checkTaskInHeroQUalityUp, checkTaskInHeroStarUp, checkTaskInHeroTrain, checkTaskInHeroWakeUp } from '../../../services/task/taskService'; import { checkTask, checkTaskInHeroQUalityUp, checkTaskInHeroStarUp, checkTaskInHeroTrain, checkTaskInHeroWakeUp } from '../../../services/task/taskService';
import { isNumber, pick } from 'underscore'; import { isNumber, pick } from 'underscore';
import { updateEplaces } from '../../../services/equipService'; import { updateEplaces } from '../../../services/equipService';
import { addConsumeToHero, checkUnlockTalentCondition, initSkinTalent, updateSkinTalent } from '../../../services/roleService'; import { addConsumeToHero, checkUnlockTalentCondition, initSkinTalent, updateSkinTalent } from '../../../services/roleService';
import { JewelModel, jewelUpdate } from '../../../db/Jewel'; import { JewelModel, jewelUpdate } from '../../../db/Jewel';
import { CalHeroCe } from '../../../domain/roleField/calCe'; import { CalHeroCe } from '../../../services/role/_calCe';
import { HERO, REBORN } from '../../../pubUtils/dicParam'; import { HERO, REBORN } from '../../../pubUtils/dicParam';
import { createHero, createHeroes } from '../../../services/role/createHero'; import { createHero, createHeroes } from '../../../services/role/createHero';
import { CheckMeterial } from '../../../services/role/checkMaterial'; import { CheckMeterial } from '../../../services/role/checkMaterial';
@@ -654,9 +654,8 @@ export class HeroHandler {
let newSkins = initSkinTalent(skins); let newSkins = initSkinTalent(skins);
let dicHeroScroll = getScollByStar(dicHero.quality, dicHero.initialStars, dicHero.quality, 0); let dicHeroScroll = getScollByStar(dicHero.quality, dicHero.initialStars, dicHero.quality, 0);
let initInfo = HeroModel.getInitInfo({ let initInfo = HeroModel.getInitInfo(hid, {
job: dicJob.jobid, skins: newSkins, skinId, ce, job: dicJob.jobid, skins: newSkins, skinId, ce,
star: dicHero.initialStars, quality: dicHero.quality,
scrollActive: scrollActive, scrollActive: scrollActive,
scrollId: scrollActive? dicHeroScroll.id: 0, scrollId: scrollActive? dicHeroScroll.id: 0,
scrollStar: scrollActive? dicHeroScroll.stars: 0, scrollStar: scrollActive? dicHeroScroll.stars: 0,

View File

@@ -25,7 +25,7 @@ import * as dicParam from '../../../pubUtils/dicParam';
import Counter from '../../../db/Counter'; import Counter from '../../../db/Counter';
import { UserModel } from '../../../db/User'; import { UserModel } from '../../../db/User';
import { checkFilterWords, reportTAEvent, treatRoleName } from '../../../services/sdkService'; import { checkFilterWords, reportTAEvent, treatRoleName } from '../../../services/sdkService';
import { CreateHeroes } from '../../../services/role/createHero'; import { createHeroes, CreateHeroes } from '../../../services/role/createHero';
export default function (app: Application) { export default function (app: Application) {
new HandlerService(app, {}); new HandlerService(app, {});
@@ -50,20 +50,8 @@ export class RoleHandler {
let checkName = await RoleModel.checkName(roleName, serverId); let checkName = await RoleModel.checkName(roleName, serverId);
if (checkName) return resResult(STATUS.NAME_HAS_USED); if (checkName) return resResult(STATUS.NAME_HAS_USED);
let initInfos: { role: RoleUpdate, initInfos: {heroInfo: HeroUpdate, skinInfo: SkinUpdate}[], figureInfo: { heads: Figure[], frames: Figure[], spines: Figure[] }} let { resultHeroes: heroes } = await createHeroes(roleId, roleName, sid, serverId, DEFAULT_HEROES.map(hid => ({hid, count: 1})));
= this.app.get('initRoleInfos'); role = await RoleModel.updateRoleInfo(roleId, { roleName, hasInit: true });
role = await RoleModel.updateRoleInfo(roleId, {...initInfos.role, roleName, hasInit: true});
let createHero = new CreateHeroes(roleId, roleName, serverId);
let infos = new Map();
for(let {heroInfo, skinInfo} of initInfos.initInfos) {
infos.set(heroInfo.hid, { heroInfo, skinInfo });
}
await createHero.createWithInitInfo(infos, initInfos.figureInfo);
await createHero.pushMessage(sid);
await createHero.updateRedisRank();
let heroes = createHero.getResultHeroes();
session.set('roleName', roleName); session.set('roleName', roleName);
session.push('roleName', () => { }); session.push('roleName', () => { });

View File

@@ -5,14 +5,11 @@ import { HeroUpdate } from '../../../db/Hero';
import { RoleUpdate } from '../../../db/Role'; import { RoleUpdate } from '../../../db/Role';
import { SkinUpdate } from '../../../db/Skin'; import { SkinUpdate } from '../../../db/Skin';
import { RankFirstModel, RankFirstType } from '../../../db/RankFirst'; import { RankFirstModel, RankFirstType } from '../../../db/RankFirst';
import { DEFAULT_HEROES } from '../../../consts';
import { Figure } from '../../../domain/dbGeneral'; import { Figure } from '../../../domain/dbGeneral';
import { getDefaultRoleInfo } from '../../../services/roleService';
import { PVPConfigModel, PVPConfigType } from '../../../db/SystemConfig'; import { PVPConfigModel, PVPConfigType } from '../../../db/SystemConfig';
import { treatRoleName, taflush } from '../../../services/sdkService'; import { treatRoleName, taflush } from '../../../services/sdkService';
import { getServerMainten, setServerMainten, stopServerMainten } from '../../../services/gmService'; import { getServerMainten, setServerMainten, stopServerMainten } from '../../../services/gmService';
import { errlogger } from '../../../util/logger'; import { errlogger } from '../../../util/logger';
import { getInitRoleInfo } from '../../../services/role/initRoleService';
export default function (app: Application) { export default function (app: Application) {
new HandlerService(app, {}); new HandlerService(app, {});
@@ -23,16 +20,12 @@ export class RoleRemote {
constructor(private app: Application) { constructor(private app: Application) {
this.app = app; this.app = app;
this.channelService = app.get('channelService'); // this.channelService = app.get('channelService');
this.setInitRole();
this.loadRankFirst(); this.loadRankFirst();
this.initPvpSeasonNum(); this.initPvpSeasonNum();
} }
private channelService: ChannelService; // 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[]};
private rankFirstRewards: Map<number, Map<number, RankFirstType>> = new Map(); private rankFirstRewards: Map<number, Map<number, RankFirstType>> = new Map();
private async loadRankFirst() { private async loadRankFirst() {
@@ -68,76 +61,6 @@ export class RoleRemote {
} }
} }
public setInitRole() {
try {
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;
const initRoleInfos = getDefaultRoleInfo(this.initHeroes, this.initSkins, this.initRole, this.figureInfo);
this.app.set('initRoleInfos', initRoleInfos);
this.app.set('initHeroes', this.initHeroes);
this.app.set('initSkins', this.initSkins);
} catch(e) {
errlogger.error(`remote ${__filename} \n ${e.stack}`);
}
}
public getInitRoleInfos() {
try {
let initRoleInfos = this.app.get('initRoleInfos');
if (!initRoleInfos) {
initRoleInfos = getDefaultRoleInfo(this.initHeroes, this.initSkins, this.initRole, this.figureInfo);
this.app.set('initRoleInfos', initRoleInfos);
}
return initRoleInfos;
} catch(e) {
errlogger.error(`remote ${__filename} \n ${e.stack}`);
}
}
public getInitHeroes() {
try {
let result: HeroUpdate[] = [];
for(let hid of DEFAULT_HEROES) {
result.push(this.initHeroes.get(hid));
}
return result;
} catch(e) {
errlogger.error(`remote ${__filename} \n ${e.stack}`);
}
}
public getInitSkins() {
try {
let result: SkinUpdate[] = [];
for(let hid of DEFAULT_HEROES) {
result.push(this.initSkins.get(hid));
}
return result;
} catch(e) {
errlogger.error(`remote ${__filename} \n ${e.stack}`);
}
}
public getInitHeroById(hid: number) {
try {
return {
heroInfo: this.initHeroes.get(hid),
skinInfo: this.initSkins.get(hid)
}
} catch(e) {
errlogger.error(`remote ${__filename} \n ${e.stack}`);
}
}
/** /**
* 重载json资源 * 重载json资源
*/ */

View File

@@ -61,7 +61,6 @@ export async function getEnemies(oppPlayers: OppPlayer[], winStreakNum: number)
* @param pLv 我的排名 * @param pLv 我的排名
*/ */
export async function refreshEnemies(role: RoleType, seasonNum: number, sumScore: number, score: number, pLv: number) { export async function refreshEnemies(role: RoleType, seasonNum: number, sumScore: number, score: number, pLv: number) {
console.log('#####',seasonNum, sumScore, score, pLv)
let { roleId } = role; let { roleId } = role;
let chosenOpps: string[] = []; let chosenOpps: string[] = [];
let pvpHistoryOppParam: PvpOppCreateParam[] = []; let pvpHistoryOppParam: PvpOppCreateParam[] = [];

View File

@@ -5,7 +5,7 @@ import { gameData, getHeroStarByQuality, getHeroWakeByQuality } from "../../pubU
import { DicRandomEffectPool } from "../../pubUtils/dictionary/DicRandomEffectPool"; import { DicRandomEffectPool } from "../../pubUtils/dictionary/DicRandomEffectPool";
import { DicSe } from "../../pubUtils/dictionary/DicSe"; import { DicSe } from "../../pubUtils/dictionary/DicSe";
import { deepCopy } from "../../pubUtils/util"; import { deepCopy } from "../../pubUtils/util";
import { AttributeCal } from "./attribute"; import { AttributeCal } from "../../domain/roleField/attribute";
export class CalRoleCe { export class CalRoleCe {
private roleInfo: RoleUpdate; private roleInfo: RoleUpdate;

View File

@@ -0,0 +1,465 @@
import { ABI_STAGE, ABI_STAGE_TO_TYPE, ABI_TYPE_MAIN, SEID_TYPE } from "../../consts";
import { HeroUpdate } from "../../db/Hero";
import { RoleUpdate, Teraph } from "../../db/Role";
import { GlobalAttr, HeroAttr, HeroAttrCell, RoleCeType } from "../../db/RoleCe";
import { AttributeCal } from "../../domain/roleField/attribute";
import { gameData, getHeroStarByQuality, getHeroWakeByQuality, getTeraph } from "../../pubUtils/data";
import { DicRandomEffectPool } from "../../pubUtils/dictionary/DicRandomEffectPool";
import { DicSe } from "../../pubUtils/dictionary/DicSe";
import { addToMap, deepCopy } from "../../pubUtils/util";
class RoleCe {
roleId: string;
globalAttrs: Map<number, GlobalMainAttr|GlobalSubAttr> = new Map(); // attrId => GlobalCe
heroAttrs: Map<string, HeroMainAttr|HeroSubAttr> = new Map(); // hid+attrId => HeroCe
heroAttrsByHid: Map<number, string[]> = new Map(); // hid => [hid+attrId]
heroLv: Map<number, number> = new Map();
setRoleCe(roleCe: RoleCeType) {
this.roleId = roleCe.roleId;
for(let globalAttr of roleCe.globalAttrs) {
let obj = this.getGlobalAttrById(globalAttr.attrId);
obj.setByRoleCe(globalAttr);
}
for(let {hid, lv, attrs} of roleCe.heroAttrs) {
this.heroLv.set(hid, lv);
for(let cell of attrs) {
let obj = this.getHeroAttrByHidAndId(hid, cell.attrId);
obj.setByRoleCe(cell);
}
}
}
public getGlobalAttrById(attrId: number) {
if(!this.globalAttrs.has(attrId)) {
if(ABI_TYPE_MAIN.indexOf(attrId) != -1) {
let obj = new GlobalMainAttr(attrId);
this.globalAttrs.set(attrId, obj);
} else {
let obj = new GlobalSubAttr(attrId);
this.globalAttrs.set(attrId, obj);
}
}
return this.globalAttrs.get(attrId);
}
public getHeroAttrByHidAndId(hid: number, attrId: number) {
let key = `${hid}_${attrId}`;
if(!this.heroAttrs.has(key)) {
if(ABI_TYPE_MAIN.indexOf(attrId) != -1) {
let obj = new HeroMainAttr(hid, attrId);
this.heroAttrs.set(key, obj);
} else {
let obj = new HeroSubAttr(hid, attrId);
this.heroAttrs.set(key, obj);
}
if(!this.heroAttrsByHid.has(hid)) {
this.heroAttrsByHid.set(hid, []);
}
this.heroAttrsByHid.get(hid).push(key);
}
return this.heroAttrs.get(key);
}
public calHeroCe() {
let ces = new Map<number, { id: number, val: number }[]>(); // hid => [{attrId, val}]
for(let [hid, keys] of this.heroAttrsByHid) {
let lv = this.heroLv.get(hid)||1;
for(let key of keys) {
let { attrId, base, baseUp, starUp, skillRatio, skill, job } = this.heroAttrs.get(key);
let { schoolRatio, title, teraph } = this.getGlobalAttrById(attrId);
let val = ( base + lv * ( baseUp + starUp ) + skill + job) * (1 + skillRatio + schoolRatio ) + teraph + title;
if(!ces.has(hid)) ces.set(hid, []);
ces.get(hid).push({ id: attrId, val });
}
}
let result = new Map<number, number>();
for(let [hid, arr] of ces) {
let obj = new AttributeCal();
obj.setByWarJson(arr);
result.set(hid, obj.calCe());
}
return result;
}
public getRoleCeTable() {
let globalAttrs: GlobalAttr[] = [];
for(let [_, globalAttr] of this.globalAttrs) {
globalAttrs.push(globalAttr.getGlobalAttr());
}
let heroAttrs: HeroAttr[] = [];
for(let [hid, keys] of this.heroAttrsByHid) {
let lv = this.heroLv.get(hid);
let attrs: HeroAttrCell[] = [];
for(let key of keys) {
let heroAttr = this.heroAttrs.get(key);
attrs.push(heroAttr.getHeroAttrCell());
}
heroAttrs.push({
hid, lv, attrs
});
}
return {
roleId: this.roleId, globalAttrs, heroAttrs
}
}
}
// 计算函数
export class CalCe extends RoleCe {
public setInitHero(role: RoleUpdate, heroes: HeroUpdate[]) {
for(let { hid, skinId, lv, quality, star, starStage, colorStar, colorStarStage, job, jobStage, } of heroes) {
this.setHeroBase(hid, skinId);
this.setHeroLv(hid, lv);
this.setHeroStar(hid, job, quality, star, starStage, colorStar, colorStarStage);
this.setSkill(hid, skinId, star, colorStar);
this.setJob(hid, job, jobStage);
}
this.setTitle(role.title);
this.setTeraph(role.teraphs);
}
// 武将基础&成长
public setHeroBase(hid: number, skinId: number) {
let dicHero = gameData.hero.get(skinId);
for(let [attrId, value] of dicHero.baseAbilityArr) {
let heroAttr = this.getHeroAttrByHidAndId(hid, attrId);
heroAttr.base = value;
}
for(let [attrId, value] of dicHero.baseAbilityUpArr) {
let heroAttr = this.getHeroAttrByHidAndId(hid, attrId);
heroAttr.baseUp = value;
}
}
// 武将等级
public setHeroLv(hid: number, lv: number) {
this.heroLv.set(hid, lv);
}
// 星级相关
public setHeroStar(hid: number, job: number, quality: number, star: number, starStage: number, colorStar: number, colorStarStage: number) {
let dicJob = gameData.job.get(job);
let jobClass = dicJob.job_class;
const isWake = colorStar > 0; // 是否觉醒,只要激活了觉醒,彩星就会 > 1
const dicStar = isWake ? getHeroWakeByQuality(jobClass, quality, colorStar) : getHeroStarByQuality(jobClass, quality, star); // 星级表
const dicPreStar = isWake? getHeroWakeByQuality(jobClass, quality, colorStar - 1): getHeroStarByQuality(jobClass, quality, star - 1);
let curStage = isWake? colorStarStage: starStage;
for (let stage = ABI_STAGE.START + 1; stage <= ABI_STAGE.END; stage++) {
let attrId = ABI_STAGE_TO_TYPE.get(stage);
let value = 0; // 星级成长
if(curStage >= stage) {
value = dicStar?.ceAttr.get(stage)||0;
} else {
value = dicPreStar?.ceAttr.get(stage)||0;
}
let heroAttr = this.getHeroAttrByHidAndId(hid, attrId);
heroAttr.starUp = value;
};
}
// 武将星级解锁被动技能计算
public setSkill(hid: number, skinId: number, _star: number, _colorStar: number) {
let seidList = new Map<number, number>(); // type => seid
let dicHero = gameData.hero.get(skinId);
let { starSeidArr, colorStarSeidArr } = gameData.heroSkill.get(dicHero.skill);
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);
let { fixUp, ratioUp } = this.addSeidEffect(list);
for(let [attrId, value] of fixUp) {
let heroAttr = this.getHeroAttrByHidAndId(hid, attrId);
heroAttr.skill = value;
}
for(let [attrId, value] of ratioUp) {
let heroAttr = this.getHeroAttrByHidAndId(hid, attrId);
heroAttr.skillRatio = value;
}
}
// 职业基础
public setJob(hid: number, job: number, jobStage: number) {
const dicJob = gameData.job.get(job);
for(let i = 1; i <= dicJob.maxStage; i++) {
if(jobStage >= i) {
let { id, attr } = dicJob.ceAttr.get(i);
let heroAttr = this.getHeroAttrByHidAndId(hid, id);
heroAttr.job = attr;
}
}
}
// 爵位
public setTitle(title: number) {
let dicTitle = gameData.title.get(title)||{ mainAttrValue: new Map(), assiAttrValue: new Map() };
for(let [attrId, value] of dicTitle.mainAttrValue) {
let globalAttr = this.getGlobalAttrById(attrId);
globalAttr.title = value;
}
for(let [attrId, value] of dicTitle.assiAttrValue) {
let globalAttr = this.getGlobalAttrById(attrId);
globalAttr.title = value;
}
}
// 神像相关
public setTeraph(teraphs: Teraph[]) {
let teraphOfAttrId = new Map<number, number>();
for(let teraph of teraphs) {
for(let [attrId, value] of teraph.attr) { // 主属性
addToMap(teraphOfAttrId, attrId, value);
}
let dicTeraph = getTeraph(teraph.id, teraph.grade);
for(let [attrId, value] of dicTeraph.assiAttrValue) { // 次属性
addToMap(teraphOfAttrId, attrId, value);
}
}
for(let [attrId, value] of teraphOfAttrId) {
let globalAttr = this.getGlobalAttrById(attrId);
globalAttr.teraph = value;
}
}
// 添加技能增加的被动属性
private addSeidEffect(seidList: number[]) {
let fixUp = new Map<number, number>(), ratioUp = new Map<number, number>();
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) {
this.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) { // 加值
addToMap(fixUp, ability, value);
} else if (type == SEID_TYPE.TYPE103) { // 主属性加百分比
if(ABI_TYPE_MAIN.includes(ability)) {
addToMap(ratioUp, ability, value / 1000);
}
} else if (type == SEID_TYPE.TYPE104) { // 次级属性加百分比
if(!ABI_TYPE_MAIN.includes(ability)) {
addToMap(ratioUp, ability, value * 100);
}
}
}
return { fixUp, ratioUp };
}
// 获取dic_zyz_se内容
private 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++) {
this.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);
}
}
abstract class GlobalAllAttr {
attrId: number;
schoolRatio: number = 0;
title: number = 0;
teraph: number = 0;
constructor(attrId: number) {
this.attrId = attrId;
}
abstract setByRoleCe(data: GlobalAttr): void;
abstract getValues(): number[];
public getGlobalAttr() {
return {
attrId: this.attrId,
values: this.getValues()
}
}
}
class GlobalMainAttr extends GlobalAllAttr {
public setByRoleCe(globalAttr: GlobalAttr) {
for(let i = 0; i < globalAttr.values.length; i++) {
let value = globalAttr.values[i];
if(value != undefined) {
switch(i) {
case GLOBAL_ATTR_INDEX.SCHOOL:
this.schoolRatio = value; break;
case GLOBAL_ATTR_INDEX.TITLE:
this.title = value; break;
case GLOBAL_ATTR_INDEX.TERAPH:
this.teraph = value; break;
}
}
}
}
public getValues() {
let values: number[] = [];
for(let i = GLOBAL_ATTR_INDEX.START; i < GLOBAL_ATTR_INDEX.END; i++) {
switch(i) {
case GLOBAL_ATTR_INDEX.SCHOOL:
values.push(this.schoolRatio); break;
case GLOBAL_ATTR_INDEX.TITLE:
values.push(this.title); break;
case GLOBAL_ATTR_INDEX.TERAPH:
values.push(this.teraph); break;
}
}
return values;
}
}
class GlobalSubAttr extends GlobalAllAttr {
public setByRoleCe(globalAttr: GlobalAttr) {
for(let i = 0; i < globalAttr.values.length; i++) {
let value = globalAttr.values[i];
if(value != undefined) {
switch(i) {
case GLOBAL_ATTR_INDEX.SCHOOL:
this.schoolRatio = value; break;
case GLOBAL_ATTR_INDEX.TITLE:
this.title = value; break;
case GLOBAL_ATTR_INDEX.TERAPH:
this.teraph = value; break;
}
}
}
}
public getValues() {
let values: number[] = [];
for(let i = GLOBAL_ATTR_INDEX.START; i < GLOBAL_ATTR_INDEX.END; i++) {
switch(i) {
case GLOBAL_ATTR_INDEX.SCHOOL:
values.push(this.schoolRatio); break;
case GLOBAL_ATTR_INDEX.TITLE:
values.push(this.title); break;
case GLOBAL_ATTR_INDEX.TERAPH:
values.push(this.teraph); break;
}
}
return values;
}
}
abstract class HeroAllAttr {
hid: number;
attrId: number;
base: number = 0;
lv: number = 0;
baseUp: number = 0;
starUp: number = 0;
skillRatio: number = 0;
skill: number = 0;
job: number = 0;
constructor(hid: number, attrId: number, ) {
this.hid = hid;
this.attrId = attrId;
}
abstract setByRoleCe(data: GlobalAttr): void;
abstract getValues(): number[];
public getHeroAttrCell() {
return {
attrId: this.attrId,
values: this.getValues()
}
}
}
class HeroMainAttr extends HeroAllAttr {
public setByRoleCe(heroAttr: HeroAttrCell) {
for(let i = 0; i < heroAttr.values.length; i++) {
let value = heroAttr.values[i];
if(value != undefined) {
switch(i) {
case HERO_ATTR_INDEX.BASE:
this.base = value;
}
}
}
}
public getValues() {
let values: number[] = [];
for(let i = HERO_ATTR_INDEX.START; i < HERO_ATTR_INDEX.END; i++) {
switch(i) {
case HERO_ATTR_INDEX.BASE:
values.push(this.base); break;
}
}
return values;
}
}
class HeroSubAttr extends HeroAllAttr {
public setByRoleCe(heroAttr: HeroAttrCell) {
for(let i = 0; i < heroAttr.values.length; i++) {
let value = heroAttr.values[i];
if(value != undefined) {
switch(i) {
case HERO_ATTR_INDEX.BASE:
this.base = value;
}
}
}
}
public getValues() {
let values: number[] = [];
for(let i = HERO_ATTR_INDEX.START; i < HERO_ATTR_INDEX.END; i++) {
switch(i) {
case HERO_ATTR_INDEX.BASE:
values.push(this.base); break;
}
}
return values;
}
}
enum GLOBAL_ATTR_INDEX {
START,
SCHOOL = 0,
TITLE = 1,
TERAPH = 2,
END
}
enum HERO_ATTR_INDEX {
START,
BASE = 0, // 角色基础属性(dic_zyz_hero的hp)
BASE_UP = 1,
END
}

View File

@@ -1,4 +1,4 @@
import { FIGURE_UNLOCK_CONDITION, ITEM_CHANGE_REASON, REDIS_KEY, STATUS, TASK_TYPE, HERO_SYSTEM_TYPE } from "../../consts"; import { FIGURE_UNLOCK_CONDITION, ITEM_CHANGE_REASON, REDIS_KEY, STATUS, TASK_TYPE, HERO_SYSTEM_TYPE, LINEUP_NUM } from "../../consts";
import { SkinModel } from "../../db/Skin"; import { SkinModel } from "../../db/Skin";
import { HeroModel, HeroSkin, HeroType, HeroUpdate } from "../../db/Hero"; import { HeroModel, HeroSkin, HeroType, HeroUpdate } from "../../db/Hero";
import { RoleModel, RoleType, RoleUpdate } from "../../db/Role"; import { RoleModel, RoleType, RoleUpdate } from "../../db/Role";
@@ -8,7 +8,7 @@ import { TaskListReturn } from "../../domain/roleField/task";
import { GuildModel, GuildType } from "../../db/Guild"; import { GuildModel, GuildType } from "../../db/Guild";
import { PvpDefenseModel } from "../../db/PvpDefense"; import { PvpDefenseModel } from "../../db/PvpDefense";
import { pick } from "underscore"; import { pick } from "underscore";
import { calculatetopLineup } from "../../pubUtils/playerCe"; import { calculatetopLineup } from "../../pubUtils/util";
import { nowSeconds } from "../../pubUtils/timeUtil"; import { nowSeconds } from "../../pubUtils/timeUtil";
import { saveCeChangeLog } from "../../pubUtils/logUtil"; import { saveCeChangeLog } from "../../pubUtils/logUtil";
import { getRandSingleEelm, reduceCe, resResult } from "../../pubUtils/util"; import { getRandSingleEelm, reduceCe, resResult } from "../../pubUtils/util";
@@ -20,18 +20,28 @@ import { checkTaskInCreateHero } from "../task/taskService";
import { ItemInter, RewardInter } from "../../pubUtils/interface"; import { ItemInter, RewardInter } from "../../pubUtils/interface";
import { transPiece } from "./util"; import { transPiece } from "./util";
import { getInitHeroById } from "../roleService"; import { getInitHeroById } from "../roleService";
import { addItems, combineFigureInfo, unlockFigureWithoutSave } from "./rewardService"; import { addItems, combineFigureInfo, unlockFigure, unlockFigureWithoutSave } from "./rewardService";
import { gameData } from "../../pubUtils/data";
import { CalCe } from "./calCe";
import { RoleCeUpdate } from "../../db/RoleCe";
export class UpdateHeroes { export class CreateHeroes {
roleId: string; private roleId: string;
roleName: string; private roleName: string;
serverId: number; private serverId: number;
incHeroNum: number = 0; private incHeroNum: number = 0;
incRoleCe: number = 0; private incRoleCe: number = 0;
pushHeroes: {hid: number, incHeroCe: number, ce: number, hero: HeroUpdate}[] = []; private role: RoleType;
roleUpdate: RoleUpdate; private guild: GuildType;
role: RoleType;
guild: GuildType; // 推送信息
private figureConditions: { type: FIGURE_UNLOCK_CONDITION, paramHid: number }[] = [];
private skins: SkinUpdate[] = [];
private heroes: HeroUpdate[] = [];
private roleCe: RoleCeUpdate = {};
private resultHeroes: HeroType[] = [];
private topLineup: TopHero[] = [];
private topLineupCe: number = 0;
constructor(roleId: string, roleName: string, serverId: number) { constructor(roleId: string, roleName: string, serverId: number) {
this.roleId = roleId; this.roleId = roleId;
@@ -46,43 +56,66 @@ export class UpdateHeroes {
public async getRole() { public async getRole() {
if(!this.role) { if(!this.role) {
this.role = await RoleModel.findByRoleId(this.roleId); this.role = await RoleModel.findByRoleId(this.roleId);
this.topLineup = this.role.topLineup;
this.topLineupCe = this.role.topLineupCe;
} }
return this.role; return this.role;
} }
public addRoleUpdateParam(param: RoleUpdate) { public async createHeroes(hids: number[]) {
this.roleUpdate = {...this.roleUpdate, ...param}; let { roleId, roleName } = this;
for(let hid of hids) {
let initSkin = SkinModel.getInitInfo(hid);
let initHero = HeroModel.getInitInfo(hid, { roleId, roleName, skins: [new HeroSkin(initSkin)] });
this.heroes.push(initHero);
this.skins.push(initSkin);
this.figureConditions.push({ type: FIGURE_UNLOCK_CONDITION.GET_HERO, paramHid: hid });
this.incHeroNum ++;
}
await this.calCe(); // 计算战力
await this.saveCeToDb();
} }
public async updateDbCe(isCreate: boolean, heroInfo: HeroUpdate, originCe = 0) { private async calCe() {
let role = await this.getRole(); let role = await this.getRole();
if(isCreate) this.incHeroNum ++; let calCe = new CalCe();
if(heroInfo != originCe) this.incRoleCe += heroInfo.ce - originCe; calCe.setInitHero(role, this.heroes); // 设置武将初始信息
this.addRoleUpdateParam(await calculatetopLineup(role, heroInfo.hid, heroInfo.ce, heroInfo._id )); let ces = calCe.calHeroCe(); // 战力
this.pushHeroes.push({ hid: heroInfo.hid, incHeroCe: heroInfo.ce - originCe, ce: heroInfo.ce, hero: heroInfo }); for(let hero of this.heroes) {
hero.ce = ces.get(hero.hid)||0;
hero.historyCe = hero.ce;
this.incRoleCe += hero.ce;
}
this.roleCe = calCe.getRoleCeTable();
} }
// 更新战力相关的各个表 // 更新战力相关的各个表
public async saveCeToDb() { private async saveCeToDb() {
let role = await this.getRole(); let role = await this.getRole();
// 更新武将表
for(let hero of this.heroes) {
let resultHero = await HeroModel.createHero(hero);
this.resultHeroes.push(resultHero);
await calculatetopLineup(role, resultHero.hid, resultHero.ce, resultHero._id);
}
this.heroes = [];
// 更新role表 // 更新role表
this.role = await RoleModel.updateRoleInfo(this.roleId, { role = await RoleModel.incRoleInfo(this.roleId, { heroNum: this.incHeroNum, ce: this.incRoleCe }, { heroNumUpdatedAt: nowSeconds(), });
heroNum: this.incHeroNum + role.heroNum, ce: this.incRoleCe + role.ce, heroNumUpdatedAt: nowSeconds(), ...this.roleUpdate this.setRole(role);
}); // 更新皮肤表
await SkinModel.insertSkins(this.roleId, this.roleName, this.skins)
// 更新guild表 // 更新guild表
if(role.hasGuild) { if(role.hasGuild) {
this.guild = await GuildModel.updateCe(this.roleId, this.incRoleCe, true); // 公会更新战力 this.guild = await GuildModel.updateCe(this.roleId, this.incRoleCe, true); // 公会更新战力
} }
for(let { hid, incHeroCe } of this.pushHeroes) { for(let { hid, ce } of this.resultHeroes) {
await PvpDefenseModel.updateCe(this.roleId, hid, incHeroCe); // 更新pvp防守阵战力 await PvpDefenseModel.updateCe(this.roleId, hid, ce); // 更新pvp防守阵战力
} }
saveCeChangeLog(this.role, this.incRoleCe, this.role.ce, HERO_SYSTEM_TYPE.INIT, this.pushHeroes.map(cur => cur.hid)); saveCeChangeLog(role, this.incRoleCe, role.ce, HERO_SYSTEM_TYPE.INIT, this.resultHeroes.map(cur => cur.hid));
} }
public async updateRedisRank() { public async updateRedisRank() {
let role = await this.getRole(); let { serverId, roleId, resultHeroes, role } = this;
let { serverId, roleId, pushHeroes } = this;
// 更新军团信息 // 更新军团信息
if(this.guild) { if(this.guild) {
let r = new Rank(REDIS_KEY.GUILD_INFO, { guildCode: this.guild.code }); let r = new Rank(REDIS_KEY.GUILD_INFO, { guildCode: this.guild.code });
@@ -99,12 +132,12 @@ export class UpdateHeroes {
await r.setRankWithRoleInfo(roleId, reduceCe(role.topLineupCe), 0, role); await r.setRankWithRoleInfo(roleId, reduceCe(role.topLineupCe), 0, role);
// 最强武将 // 最强武将
for(let { hid, ce, hero } of pushHeroes) { for(let hero of resultHeroes) {
let r2 = new Rank(REDIS_KEY.TOP_HERO_RANK, { serverId }); let r2 = new Rank(REDIS_KEY.TOP_HERO_RANK, { serverId });
await r2.setRankWithHeroInfo(roleId, hid, reduceCe(ce), 0, hero); await r2.setRankWithHeroInfo(roleId, hero.hid, hero.ce, 0, hero);
let r4 = new Rank(REDIS_KEY.HERO_RANK, { serverId, hid }); let r4 = new Rank(REDIS_KEY.HERO_RANK, { serverId, hid: hero.hid });
await r4.setRankWithHeroInfo(roleId, hid, reduceCe(ce), 0, hero); await r4.setRankWithHeroInfo(roleId, hero.hid, hero.ce, 0, hero);
} }
// 总战力 // 总战力
let r3 = new Rank(REDIS_KEY.SUM_CE_RANK, { serverId }); let r3 = new Rank(REDIS_KEY.SUM_CE_RANK, { serverId });
@@ -115,90 +148,26 @@ export class UpdateHeroes {
await r5.generParamAndSet(REDIS_KEY.TOP_LINEUP_INFO, { roleId }, { role }); 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) { public async pushMessage(sid: string) {
let role = await this.getRole(); let role = await this.getRole();
let uids = [{ uid: this.roleId, sid }]; 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('onPlayerCeUpdate', resResult(STATUS.SUCCESS, { ce: role.ce, heros: this.resultHeroes.map(({ hid, ce }) => ({ hid, ce, incHeroCe: ce})), topLineupCe: 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('onHeroSkinChange', resResult(STATUS.SUCCESS, this.getSkinPushMsg()), uids);
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); pinus.app.get('channelService').pushMessageByUids('onHeroUpdate', resResult(STATUS.SUCCESS, { heroes: this.getResultHeroes() }), uids);
checkTaskInCreateHero(this.serverId, this.roleId, sid, this.heroNum, this.resultHeroes) checkTaskInCreateHero(this.serverId, this.roleId, sid, this.incHeroNum, this.resultHeroes);
await unlockFigure(sid, this.roleId, this.figureConditions);
}
private getSkinPushMsg() {
let skinPushMessages: {heros: {skins: HeroSkin[], hid: number}[], skins: {id: number, hid: number, inc: number, reason: number }[]} = { heros: [], skins:[] }; // 皮肤推送信息
for(let { hid, skins } of this.resultHeroes) {
skinPushMessages.heros.push({ hid, skins });
}
for(let { id, hid } of this.skins) {
skinPushMessages.skins.push({ id, hid, inc: 1, reason: ITEM_CHANGE_REASON.GET_HERO_UNLOCK_SKIN })
}
return skinPushMessages;
} }
public getResultHeroes() { public getResultHeroes() {
@@ -225,25 +194,14 @@ export class CreateHeroes extends UpdateHeroes {
let hids = heroInfo.map(cur => cur.hid); let hids = heroInfo.map(cur => cur.hid);
let userHeroesMap = await HeroModel.findMapByHidRange(hids, roleId); let userHeroesMap = await HeroModel.findMapByHidRange(hids, roleId);
let infos: Map<number, { heroInfo: HeroUpdate, skinInfo: SkinUpdate }> = new Map(), pieces: ItemInter[] = []; let createHids: number[] = [], pieces: ItemInter[] = [];
for (let h of heroInfo) { for (let h of heroInfo) {
let heroCount = h.count || 1; let heroCount = h.count || 1;
if (userHeroesMap.has(h.hid)) { if (userHeroesMap.has(h.hid)) {
let { pieceId, count } = transPiece(h.hid); let { pieceId, count } = transPiece(h.hid);
pieces.push({ id: pieceId, count: count * heroCount }); pieces.push({ id: pieceId, count: count * heroCount });
} else { } else {
let initInfo: { heroInfo: HeroUpdate, skinInfo: SkinUpdate }; createHids.push(h.hid);
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); userHeroesMap.set(h.hid, null);
if (heroCount > 1) { if (heroCount > 1) {
let { pieceId, count } = transPiece(h.hid); let { pieceId, count } = transPiece(h.hid);
@@ -253,9 +211,9 @@ export class CreateHeroes extends UpdateHeroes {
} }
let resultHeroes: HeroType[] = [], resultItems: RewardInter[] = [], heroes: HeroShowParam[] = []; let resultHeroes: HeroType[] = [], resultItems: RewardInter[] = [], heroes: HeroShowParam[] = [];
if (infos.size > 0) { if (createHids.length > 0) {
let createHero = new CreateHeroes(roleId, roleName, serverId); let createHero = new CreateHeroes(roleId, roleName, serverId);
await createHero.createWithHeroInfo(infos); await createHero.createHeroes(createHids);
await createHero.pushMessage(sid); await createHero.pushMessage(sid);
await createHero.updateRedisRank(); await createHero.updateRedisRank();
heroes = createHero.getShowHeroes(); heroes = createHero.getShowHeroes();

View File

@@ -1,61 +0,0 @@
import { DEFAULT_HEROES, DEFAULT_HERO_LV, FIGURE_UNLOCK_CONDITION, HERO_SYSTEM_TYPE, LINEUP_NUM } from "../../consts";
import { HeroModel, HeroSkin, HeroUpdate } from "../../db/Hero";
import { RoleModel, RoleUpdate } from "../../db/Role";
import { SkinModel, SkinUpdate } from "../../db/Skin";
import { TopHero } from "../../domain/dbGeneral";
import { CalHeroCe, CalRoleCe } from "../../domain/roleField/calCe";
import { gameData, getHeroExpByLv } from "../../pubUtils/data";
import { unlockFigureWithoutSave } from "./rewardService";
// 储存在内存中的初始数据
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);
if(!dicFashion) {
console.log(`not found skin: ${initialSkin} of ${hid}`);
continue;
}
let skinInfo = { ...skin.toJSON(), id: initialSkin, hid, skinName: dicFashion.name, skinId: dicFashion.heroId };
initSkins.push(skinInfo);
// 武将
let hero = new HeroModel();
let heroInfo = {...hero.toJSON(), hid, star, quality, hName, job, skins: [new HeroSkin(initialSkin, skinInfo.skinId, skinInfo._id, true)], skinId: skinInfo.skinId, 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, heroNum, heroNumUpdatedAt: Date.now(), heads, frames, spines };
return {
role: initRole, heroes, skins: initSkins, figureInfo
}
}

View File

@@ -367,7 +367,7 @@ export async function addSkin(roleId: string, roleName: string, sid: string, ski
if (hero) { // 有武将的,将皮肤链接到武将上 if (hero) { // 有武将的,将皮肤链接到武将上
let curSkin = hero.skins.find(cur => cur.id == skinId); let curSkin = hero.skins.find(cur => cur.id == skinId);
if (!curSkin) { if (!curSkin) {
hero.skins.push(new HeroSkin(skin.id, skin.skinId, skin._id, enable )); hero.skins.push(new HeroSkin(skin, enable));
await HeroModel.updateHeroInfo(roleId, hero.hid, hero); await HeroModel.updateHeroInfo(roleId, hero.hid, hero);
} }
return hero; return hero;

View File

@@ -1,14 +1,14 @@
import { ChannelUser } from './../domain/ChannelUser'; import { ChannelUser } from './../domain/ChannelUser';
import { Channel, pinus } from 'pinus'; import { Channel, pinus } from 'pinus';
import { getRandValueByMinMax, getRandEelm, decodeIdCntArrayStr } from '../pubUtils/util'; import { getRandValueByMinMax, getRandEelm, decodeIdCntArrayStr } from '../pubUtils/util';
import { DEFAULT_HEROES, ROLE_SELECT, TALENT_RELATION_TYPE, TERAPH_RANDOM } from "../consts"; import { DEFAULT_HEROES, LINEUP_NUM, ROLE_SELECT, TALENT_RELATION_TYPE, TERAPH_RANDOM } from "../consts";
import { DicTeraph } from '../pubUtils/dictionary/DicTeraph'; import { DicTeraph } from '../pubUtils/dictionary/DicTeraph';
import { Teraph, RoleModel, RoleType, RoleUpdate } from '../db/Role'; import { Teraph, RoleModel, RoleType, RoleUpdate } from '../db/Role';
import { SCHOOL } from '../pubUtils/dicParam'; import { SCHOOL } from '../pubUtils/dicParam';
import { gameData, getHeroInitTalent } from '../pubUtils/data'; import { gameData, getHeroInitTalent } from '../pubUtils/data';
import { SchoolModel } from '../db/School'; import { SchoolModel } from '../db/School';
import { SclResultInter, SclPosInter, RewardInter, ItemInter } from '../pubUtils/interface'; import { SclResultInter, SclPosInter, RewardInter, ItemInter } from '../pubUtils/interface';
import { HeroSkin, HeroUpdate, Talent } from '../db/Hero'; import { HeroModel, HeroSkin, HeroUpdate, Talent } from '../db/Hero';
import { SkinUpdate } from '../db/Skin'; import { SkinUpdate } from '../db/Skin';
import { Figure } from '../domain/dbGeneral'; import { Figure } from '../domain/dbGeneral';
import { pick } from 'underscore'; import { pick } from 'underscore';
@@ -251,4 +251,4 @@ export function initSkinTalent(skins: HeroSkin[], isAll = false) {
} }
} }
return newSkins return newSkins
} }

View File

@@ -2,12 +2,12 @@ import BaseModel from './BaseModel';
import { index, getModelForClass, prop, Ref, mongoose, DocumentType } from '@typegoose/typegoose'; import { index, getModelForClass, prop, Ref, mongoose, DocumentType } from '@typegoose/typegoose';
// import Equip, { } from './Equip'; // import Equip, { } from './Equip';
import { CounterModel } from './Counter'; import { CounterModel } from './Counter';
import { COUNTER, HERO_CE_RATIO } from '../consts'; import { COUNTER, DEFAULT_HERO_LV, HERO_CE_RATIO } from '../consts';
import { reduceCe } from '../pubUtils/util'; import { reduceCe } from '../pubUtils/util';
import Skin from './Skin'; import Skin, { SkinUpdate } from './Skin';
import { SearchHeroParam } from '../domain/backEndField/search'; import { SearchHeroParam } from '../domain/backEndField/search';
import { Reward } from '../domain/battleField/pvp'; import { Reward } from '../domain/battleField/pvp';
import { getHeroInitTalent } from '../pubUtils/data'; import { gameData, getHeroExpByLv, getHeroInitTalent } from '../pubUtils/data';
type CeAttrUpdate = Partial<CeAttrData>; type CeAttrUpdate = Partial<CeAttrData>;
export class CeAttrData { export class CeAttrData {
@@ -88,12 +88,12 @@ export class HeroSkin {
@prop({ required: true }) @prop({ required: true })
usedTalentPoint: number; // 已使用的天赋点数 usedTalentPoint: number; // 已使用的天赋点数
constructor(id: number, skinId: number, skin: string, enable: boolean) { constructor(skin: SkinUpdate, enable = true) {
this.id = id; this.id = skin.id;
this.skinId = skinId; this.skinId = skin.skinId;
this.skin = skin; this.skin = skin._id;
this.enable = enable; this.enable = enable;
this.talent = getHeroInitTalent(skinId); this.talent = getHeroInitTalent(skin.skinId);
this.usedTalentPoint = 0; this.usedTalentPoint = 0;
} }
} }
@@ -274,16 +274,18 @@ export default class Hero extends BaseModel {
return hero; return hero;
} }
public static getInitInfo(heroInfo: HeroUpdate = {}): HeroUpdate { public static getInitInfo(hid: number, heroInfo: HeroUpdate = {}): HeroUpdate {
let dicHero = gameData.hero.get(hid)
let { quality, initialStars: star, jobid: job, name: hName } = dicHero;
const doc = new HeroModel(); const doc = new HeroModel();
const update = { ...doc.toJSON(), ...heroInfo}; const update = { ...doc.toJSON(), hid, skinId: hid, hName, star, quality, job, lv: DEFAULT_HERO_LV, exp: getHeroExpByLv(DEFAULT_HERO_LV - 1) || 0, ...heroInfo};
delete update._id; delete update._id;
return update return update
} }
public static async createHero(heroInfo: HeroUpdate, lean = true) { public static async createHero(heroInfo: HeroUpdate, lean = true) {
const seqId = await CounterModel.getNewCounter(COUNTER.HID) || -1; const seqId = await CounterModel.getNewCounter(COUNTER.HID) || -1;
const update = this.getInitInfo({ ...heroInfo, seqId }); const update = this.getInitInfo(heroInfo.hid, { ...heroInfo, seqId });
const hero: HeroType = await HeroModel.findOneAndUpdate({ roleId: heroInfo.roleId, hid: heroInfo.hid }, update, { upsert: true, new: true }).lean(lean); const hero: HeroType = await HeroModel.findOneAndUpdate({ roleId: heroInfo.roleId, hid: heroInfo.hid }, update, { upsert: true, new: true }).lean(lean);
return hero; return hero;
} }

98
shared/db/RoleCe.ts Normal file
View File

@@ -0,0 +1,98 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
// 全局加成
export class GlobalAttr {
@prop({ required: true })
attrId: number; // 属性id
@prop({ required: true })
values: number[]; // 战力公式中的全局加成的数据,查表后的结果
}
// 单武将加成
export class HeroAttr {
@prop({ required: true })
hid: number; // 武将id
@prop({ required: true })
lv: number;
@prop({ required: true, type: () => HeroAttrCell, _id: false })
attrs: HeroAttrCell[];
}
export class HeroAttrCell {
@prop({ required: true })
attrId: number; // 属性id
@prop({ required: true })
values: number[]; // 战力公式中的武将加成的数据,查表后的结果
}
// 装备加成
class EquipAttr {
@prop({ required: true })
hid: number; // 武将id
@prop({ required: true })
eplaceId: number; // 装备位置
@prop({ required: true })
attrId: number; // 属性id
@prop({ required: true })
values: number[]; // 战力公式中的武将加成的数据,查表后的结果
}
// 百家学宫加成
class SchoolAttr {
@prop({ required: true })
hid: number; // 武将id
@prop({ required: true })
attrId: number; // 属性id
@prop({ required: true })
value: number; // 百家学宫有多个武将单独拎出来方便计算计算之后结果存到globaAttrs的global1
}
// 名将谱加成
class ScrollAttr {
@prop({ required: true })
hid: number; // 武将id
@prop({ required: true })
attrId: number; // 属性id
@prop({ required: true })
value: number; // 百家学宫有多个武将单独拎出来方便计算计算之后结果存到globaAttrs的global1
}
/**
* 属性表
*/
@index({ roleId: 1 })
@index({ roleId: 1 })
export default class RoleCe extends BaseModel {
@prop({ required: true })
roleId: string; // 角色 id
@prop({ required: true, type: GlobalAttr, _id: false })
globalAttrs: GlobalAttr[]
@prop({ required: true, type: HeroAttr, _id: false })
heroAttrs: HeroAttr[]
@prop({ required: true, type: EquipAttr, _id: false })
equipAttrs: EquipAttr[]
@prop({ required: true, type: SchoolAttr, _id: false })
schoolAttr: SchoolAttr[];
@prop({ required: true, type: ScrollAttr, _id: false })
scrollAttrs: ScrollAttr[];
public static async findByRoleId(roleId: string) {
let result: RoleCeType[] = await RoleCeModel.find({ roleId }).lean();
return result;
}
}
export const RoleCeModel = getModelForClass(RoleCe);
export interface RoleCeType extends Pick<DocumentType<RoleCe>, keyof RoleCe> { };
export type RoleCeUpdate = Partial<RoleCeType>;

View File

@@ -1,5 +1,6 @@
import BaseModel from './BaseModel'; import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose'; import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose';
import { gameData } from '../pubUtils/data';
@index({ roleId: 1, id: 1 }) @index({ roleId: 1, id: 1 })
@index({ seqId: 1 }) @index({ seqId: 1 })
@modelOptions({ schemaOptions: { id: false } }) @modelOptions({ schemaOptions: { id: false } })
@@ -28,6 +29,15 @@ export default class Skin extends BaseModel {
return rec; return rec;
} }
public static getInitInfo(hid: number): SkinUpdate {
let dicHero = gameData.hero.get(hid);
let dicFashion = gameData.fashion.get(dicHero.initialSkin)
const doc = new SkinModel();
const update = { ...doc.toJSON(), id: dicFashion.id, skinId: dicFashion.heroId, skinName: dicFashion.name, hid};
delete update._id;
return update
}
public static async insertSkins(roleId: string, roleName: string, skinInfos: SkinUpdate[]) { public static async insertSkins(roleId: string, roleName: string, skinInfos: SkinUpdate[]) {
let insertInfos: SkinUpdate[] = []; let insertInfos: SkinUpdate[] = [];
for(let skinInfo of skinInfos) { for(let skinInfo of skinInfos) {

View File

@@ -4,7 +4,7 @@
import { HERO_SYSTEM_TYPE, ABI_TYPE, HERO_CE_RATIO, LINEUP_NUM, TALENT_RELATION_TYPE } from '../consts'; import { HERO_SYSTEM_TYPE, ABI_TYPE, HERO_CE_RATIO, LINEUP_NUM, TALENT_RELATION_TYPE } from '../consts';
import { cal, deepCopy, getAllAttrStage, reduceCe } from './util'; import { cal, calculatetopLineup, deepCopy, getAllAttrStage, reduceCe } from './util';
import { HeroModel, HeroType, HeroUpdate, CeAttrData, EPlace, Stone, Talent } from '../db/Hero'; import { HeroModel, HeroType, HeroUpdate, CeAttrData, EPlace, Stone, Talent } from '../db/Hero';
import { RoleModel, RoleType, RoleUpdate, CeAttrDataRole } from '../db/Role'; import { RoleModel, RoleType, RoleUpdate, CeAttrDataRole } from '../db/Role';
import { AttributeCal } from '../domain/roleField/attribute'; import { AttributeCal } from '../domain/roleField/attribute';
@@ -209,53 +209,6 @@ export async function calPlayerCe(hero: HeroType, update: HeroUpdate, type: numb
return heroAttrs; return heroAttrs;
} }
/**
* 计算最强阵容战力
* @param role
* @param hid
* @param ce
* @param heroId
*/
export async function calculatetopLineup(role: RoleType, hid?: number, ce?: number, heroId?: string) {
let topLineup = role?.topLineup || new Array();
if(!hid) { // 直接重新排
let heroes = await HeroModel.getTopHero(role.roleId, LINEUP_NUM);
topLineup = heroes.map(cur => { return { hid: cur.hid, ce: cur.ce, hero: cur._id } });
} else {
topLineup.sort((a, b) => { return b.ce - a.ce }); // 0-6最大-最小
let index = topLineup.findIndex(cur => cur.hid == hid);
if(index != -1 && !heroId) {
let heroes = await HeroModel.getTopHero(role.roleId, LINEUP_NUM);
topLineup = heroes.map(cur => { return { hid: cur.hid, ce: cur.ce, hero: cur._id } });
} else {
if (index == -1) { // 不在最强列表
if (topLineup.length < LINEUP_NUM) { // 不满6人
topLineup.push({ hid, ce, hero: heroId });
} else if (topLineup.length == LINEUP_NUM) {
if (ce > topLineup[topLineup.length - 1].ce) { // 跻身最强6人
topLineup.pop();
topLineup.push({ hid, ce, hero: heroId });
}
} else {
topLineup.splice(LINEUP_NUM, topLineup.length - LINEUP_NUM);
}
} else { // 原来就是最强6人
if (ce < topLineup[topLineup.length - 1].ce) { // 滑出最强
let heroes = await HeroModel.getTopHero(role.roleId, LINEUP_NUM);
topLineup = heroes.map(cur => { return { hid: cur.hid, ce: cur.ce, hero: cur._id } });
} else {
topLineup[index].ce = ce;
}
}
}
}
let topLineupCe = topLineup.reduce((pre, cur) => {
return pre + cur.ce
}, 0);
return { topLineup, topLineupCe };
}
/** /**
* 添加皮肤全局加成 * 添加皮肤全局加成

View File

@@ -6,13 +6,14 @@ import { isNumber } from 'underscore';
const csprng = require('csprng'); const csprng = require('csprng');
import fs = require('fs'); import fs = require('fs');
import path = require('path'); import path = require('path');
import { HERO_CE_RATIO, ABI_STAGE, GACHA_TO_FLOOR, REFRESH_TIME, ROBOT_SYS_TYPE, ITEM_CHANGE_REASON, WAR_TYPE } from '../consts'; import { HERO_CE_RATIO, ABI_STAGE, GACHA_TO_FLOOR, REFRESH_TIME, ROBOT_SYS_TYPE, ITEM_CHANGE_REASON, WAR_TYPE, LINEUP_NUM } from '../consts';
import { findIndex } from 'underscore'; import { findIndex } from 'underscore';
import { getTimeFunM } from './timeUtil'; import { getTimeFunM } from './timeUtil';
import { Floor } from '../domain/activityField/gachaField'; import { Floor } from '../domain/activityField/gachaField';
import { WhiteListModel } from '../db/RegionWhiteList'; import { WhiteListModel } from '../db/RegionWhiteList';
import { RewardInter } from './interface'; import { RewardInter } from './interface';
import { RoleType } from '../db/Role';
const randomName = require("chinese-random-name"); const randomName = require("chinese-random-name");
const moment = require('moment'); const moment = require('moment');
const crypto = require('crypto'); const crypto = require('crypto');
@@ -788,3 +789,59 @@ export function stringToRewardInter(rewardStr: string): Array<RewardInter> {
} }
return result return result
} }
export function addToMap<T>(map: Map<T, number>, id: T, value: number) {
if(!map.has(id)) {
map.set(id, value);
} else {
map.set(id, map.get(id) + value);
}
}
/**
* 计算最强阵容战力
* @param role
* @param hid
* @param ce
* @param heroId
*/
export async function calculatetopLineup(role: RoleType, hid?: number, ce?: number, heroId?: string) {
let topLineup = role?.topLineup || new Array();
if(!hid) { // 直接重新排
let heroes = await HeroModel.getTopHero(role.roleId, LINEUP_NUM);
topLineup = heroes.map(cur => { return { hid: cur.hid, ce: cur.ce, hero: cur._id } });
} else {
topLineup.sort((a, b) => { return b.ce - a.ce }); // 0-6最大-最小
let index = topLineup.findIndex(cur => cur.hid == hid);
if(index != -1 && !heroId) {
let heroes = await HeroModel.getTopHero(role.roleId, LINEUP_NUM);
topLineup = heroes.map(cur => { return { hid: cur.hid, ce: cur.ce, hero: cur._id } });
} else {
if (index == -1) { // 不在最强列表
if (topLineup.length < LINEUP_NUM) { // 不满6人
topLineup.push({ hid, ce, hero: heroId });
} else if (topLineup.length == LINEUP_NUM) {
if (ce > topLineup[topLineup.length - 1].ce) { // 跻身最强6人
topLineup.pop();
topLineup.push({ hid, ce, hero: heroId });
}
} else {
topLineup.splice(LINEUP_NUM, topLineup.length - LINEUP_NUM);
}
} else { // 原来就是最强6人
if (ce < topLineup[topLineup.length - 1].ce) { // 滑出最强
let heroes = await HeroModel.getTopHero(role.roleId, LINEUP_NUM);
topLineup = heroes.map(cur => { return { hid: cur.hid, ce: cur.ce, hero: cur._id } });
} else {
topLineup[index].ce = ce;
}
}
}
}
let topLineupCe = topLineup.reduce((pre, cur) => {
return pre + cur.ce
}, 0);
return { topLineup, topLineupCe };
}