Files
ZYZ/game-server/app/services/expeditionService.ts
2021-10-29 16:36:23 +08:00

311 lines
12 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { ExpeditionPointModel } from '../db/ExpeditionPoint';
import Role, { CeAttrDataRole, RoleModel } from '../db/Role';
import { shouldRefresh, calculateSumCE, getRandSingleEelm } from '../pubUtils/util';
import { LINEUP_NUM, EXPEDITION_WAR_RECORD_STATUS } from '../consts';
import { ExpeditionWarRecordModel } from '../db/ExpeditionWarRecord';
import { CeAttrData, HeroType } from '../db/Hero';
import { gameData } from '../pubUtils/data';
import { getTimeFunD } from '../pubUtils/timeUtil';
import { ExpeditionRecordModel } from '../db/ExpeditionRecord';
import { Attribute, AttributeCal } from '../domain/roleField/attribute';
import * as dicParam from '../pubUtils/dicParam';
/**
* 获取远征关卡列表
* @param roleId
* @param roleName
*/
export async function getExpeditionStatus(roleId: string, roleName: string) {
// 重置次数
let role = await RoleModel.findByRoleId(roleId);
if(!role.hasInit) return false
// 获取远征关卡状态
let expeditionRecord = await ExpeditionRecordModel.getCurRecord(roleId);
if (!expeditionRecord) { // 首次新建一条记录
// 我方战力
let myCe = await calculateSumCE(roleId, 1, { num: LINEUP_NUM });
expeditionRecord = await ExpeditionRecordModel.createRecord({
roleId, roleName, heroes: [], myCe
});
await findOrCreateEnemies(roleId, myCe, expeditionRecord.expeditionCode, 1, EXPEDITION_WAR_RECORD_STATUS.WAITING);
}
// 每一关的挑战状态
let { expeditionCode, heroes } = expeditionRecord;
let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCode(expeditionCode);
let curLv = 0;
if (expeditionWarRecord.length > 0) {
curLv = expeditionWarRecord[expeditionWarRecord.length - 1].expeditionId;
}
let curTime = new Date();
let { resetCnt } = await getResetRemainCnt(curTime, roleId, role);
// 点数,和宝箱领取状态
let pointRewards = await getPointRewardStatus(roleId, role);
return {
expeditionCode,
curLv,
expeditionWarRecord,
pointRewards,
heroes: heroes.map(cur => { return { "dataId": cur.seqId, "hp": cur.hp, "ap": cur.ap } }),
resetCnt
}
}
/**
* 根据存下的战力获取当前远征关卡的对手
* @param roleId 我的id
* @param myCe 存在expeditionRecord内的战力缩过
* @param expeditionCode 远征批次id
* @param expeditionId 该关卡id
* @param battleStatus 该关卡的挑战状态
*/
export async function findOrCreateEnemies(roleId: string, myCe: number, expeditionCode: string, expeditionId: number, battleStatus: number) {
let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCodeAndId(expeditionCode, expeditionId);
if(!expeditionWarRecord) { // 如果没有信息
let curDicExpedition = gameData.expedition.get(expeditionId);
if(curDicExpedition) {
let enemyObj = {
enemyFrom: 0,
enemyId: '',
enemies: new Array(),
ce: 0
};
// 获取系数和步长
let { scale, range, lv } = await getCEScaleAndRange(roleId, curDicExpedition);
// 优先匹配其他玩家
let flag = await matchPlayers(roleId, scale, range, myCe, curDicExpedition.json, enemyObj);
// 当数量不够时使用机器人匹配
if(!flag) {
flag = await matchRobots(scale, myCe, curDicExpedition.ce, curDicExpedition.json, lv, enemyObj);
}
if(flag) {
// 保存
let { warId } = curDicExpedition;
let { mapseid } = gameData.war.get(warId);
expeditionWarRecord = await ExpeditionWarRecordModel.saveRecord(expeditionCode, expeditionId, {
roleId, battleId: warId, mapseid: getRandSingleEelm(mapseid), ...enemyObj, battleStatus
});
}
}
}
// 处理当前血量
let {enemiesCurHpAp, enemies} = expeditionWarRecord;
for(let enemy of enemies) {
let cur = {"hp": 0, "ap": 0};
let getHp = enemiesCurHpAp && enemiesCurHpAp.find(cur => cur.dataId == enemy.dataId);
if(getHp) {
cur.hp = getHp.hp;
cur.ap = getHp.ap;
} else {
let attr = new Attribute();
attr.setByStr(enemy.attribute);
cur.hp = attr.hp;
cur.ap = 0;
}
enemy["cur"] = cur;
}
return expeditionWarRecord;
}
/**
* 远征关卡匹配玩家
* @param roleId 我的id
* @param scale 己方战力和对方战力比
* @param range 浮动范围
* @param myCe 己方战力(已缩小)
* @param warJsonIndex 模板出兵表id
* @param enemyObj 返回的敌军数据
*/
export async function matchPlayers(roleId: string, scale: number, range: number, myCe: number, warJsonIndex:any, enemyObj: {enemyFrom: number, enemyId: string, enemies: Array<any>, ce: number }) {
let dicWarJson = gameData.warJson.get(warJsonIndex);
let min = myCe * scale * (1 - range/100);
let max = myCe * scale * (1 + range/100);
let resultRange = await RoleModel.findByCeScale(min, max);
resultRange = resultRange.filter(cur => cur.roleId != roleId);
if(resultRange.length > 0) {
let index = Math.floor(Math.random() * resultRange.length);
let role = resultRange[index];
let {roleId, topLineup, topLineupCe } = role;
let { attr: roleAttrs } = role;
enemyObj.enemyFrom = 1;
enemyObj.enemyId = roleId;
enemyObj.ce = topLineupCe;
let heroIndex = 0;
for(let json of dicWarJson) {
if(json.relation == 2) {
let hero = topLineup[heroIndex];
if(hero) {
let h = <HeroType>hero.hero;
if(h) {
let { star, lv, attr: heroAttrs, ce } = h;
let dicHero = gameData.hero.get(hero.hid);
let { attribute } = getPlayerAttribute(lv, heroAttrs, roleAttrs);
let heroInfo = {
actorId: hero.hid,
skinId: h.skinId,
actorName: dicHero.name,
skill:0,
seid:'&',
star,
spine: 0,
attribute,
lv,
ce
};
enemyObj.enemies.push({...json, ...heroInfo});
heroIndex ++;
}
}
}
}
return true;
} else {
return false
}
}
/**
* 匹配远征机器人
* @param scale 己方战力和出兵表配置战力比
* @param myCe 己方战力(已缩小)
* @param robotCe 机器人战力10000相当于已缩小战力
* @param warJsonIndex 模板出兵表id
* @param lv 我的主公等级
* @param enemyObj 返回的敌军数据
*/
export async function matchRobots(scale: number, myCe: number, robotCe: number, warJsonIndex: number, lv: number, enemyObj: {enemyFrom: number, enemyId: string, enemies: Array<any>, ce: number }) {
let dicWarJson = gameData.warJson.get(warJsonIndex);
if(dicWarJson) {
enemyObj.enemyFrom = 2;
enemyObj.enemyId = warJsonIndex + '';
let allCe = 0;
let dicExpeditionSubAttr = gameData.expeditionSubAttr.get(lv);
for(let json of dicWarJson) {
if(json.relation == 2) {
const { attribute, enemyCount } = json;
let { attribute: newAttribute, ce } = getRobotAttribute(attribute, enemyCount, dicExpeditionSubAttr.attribute, dicExpeditionSubAttr.lv, myCe, robotCe, scale);
enemyObj.enemies.push({...json, skinId: json.actorId, attribute: newAttribute, lv, ce});
allCe += ce;
}
}
enemyObj.ce = Math.floor(allCe);
return true
} else {
return false
}
}
// 远征匹配系数表
export async function getCEScaleAndRange(roleId: string, curDicExpedition: any) {
// 匹配,判断是不是新手期
const role = await RoleModel.findByRoleId(roleId);
let timef = getTimeFunD(role.createdAt)
let isNew = timef.getDayGap() <= 3;
let scale = isNew?curDicExpedition.CEScaleNew:curDicExpedition.CEScale;
let range = isNew?curDicExpedition.CERangeNew:curDicExpedition.CERange;
return {scale, range, lv: role.lv}
}
// 远征累计点数获取
export async function getPointRewardStatus(roleId: string, role?: Role) {
if(!role) {
role = await RoleModel.findByRoleId(roleId);
}
let {expeditionPoint = 0} = role;
let dicExpeditionPoint = gameData.expeditionPoint;
let rewards: { point: number, received: boolean }[] = [];
for(let [point] of dicExpeditionPoint) {
rewards.push({ point, received: false })
}
let pointRewards = {
expeditionPoint, rewards
};
let pointStatusInDatabase = await ExpeditionPointModel.getExpeditionPoint(roleId);
if(pointStatusInDatabase) {
let { rewards = [] } = pointStatusInDatabase;
pointRewards.rewards.forEach(cur => {
let obj = rewards.find(ccur => ccur.point == cur.point);
if(obj) cur.received = obj.received;
});
}
return pointRewards
}
export async function getResetRemainCnt(curTime: Date, roleId: string, role?: Role, ) {
if(!role) {
role = await RoleModel.findByRoleId(roleId);
}
let { expeditionResetCnt, expeditionResetRefTime } = role;
let needRefresh = !expeditionResetRefTime || shouldRefresh(expeditionResetRefTime, curTime);
if(needRefresh) {
expeditionResetCnt = 0; expeditionResetRefTime = curTime;
}
let maxCnt = dicParam.EXPEDITION_CONST.EXPEDITION_CONST_TIMES;
return {
resetCnt: maxCnt - expeditionResetCnt,
needRefresh
};
}
/**
* 根据比例计算机器人属性
* @param attribute 出兵表中的属性字段
* @param ce 我的战力
* @param enemyCe 出兵表对手战力
* @param ratio 系数
*/
export function getRobotAttribute(mainAttrs: { id: number, val: number }[], enemyCount: number, subAttrs: {id: number, val: number}[], lv: number, ce: number, enemyCe: number, ratio: number) {
let newAttribute = new AttributeCal();
newAttribute.setLv(lv);
newAttribute.setByWarJson(subAttrs); // 次级属性
let subAttrCe = newAttribute.calSubAttrCeAndReduce() * enemyCount;
if(ce * ratio > subAttrCe) {
let mainAttrCe = ce * ratio - subAttrCe;
newAttribute.setByWarJson(mainAttrs, mainAttrCe / enemyCe);
let attrArr = newAttribute.getReduceAttributesToString();
let newCe = newAttribute.calCelAndReduce();
return { attribute: attrArr, ce: newCe };
} else {
newAttribute = new AttributeCal();
newAttribute.setByWarJson(mainAttrs, ce * ratio / enemyCe);
let attrArr = newAttribute.getReduceAttributesToString();
let newCe = newAttribute.calCelAndReduce();
return { attribute: attrArr, ce: newCe };
}
}
/**
* @description 根据玩家数据获取到他的属性
* @param ceAttr hero表的ceAttr
* @param globalCeAttr role表中的globalCeAttr
*/
export function getPlayerAttribute(lv: number, heroAttrs: CeAttrData[] = [], roleAttrs: CeAttrDataRole[] = []) {
let newAttribute = new AttributeCal();
newAttribute.setLv(lv);
newAttribute.setByDbData(roleAttrs, heroAttrs);
let attribute = newAttribute.getReduceAttributesToString();
let ce = newAttribute.calCelAndReduce();
return { attribute, ce };
}