Files
ZYZ/game-server/app/services/expeditionService.ts
2021-03-10 16:07:47 +08:00

221 lines
7.8 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, { RoleModel, RoleType } from '../db/Role';
import { PvpDefenseModel } from '../db/PvpDefense';
import { getWarJsons, getGamedata } from '../pubUtils/gamedata';
import { decodeStr, shouldRefresh } from '../pubUtils/util';
import { EXPEDITION_CONST, HERO_CE_RATIO } from '../consts';
import { getAtrrNameById} from '../consts';
import { ExpeditionWarRecordModel } from '../db/ExpeditionWarRecord';
import { HeroType } from '../db/Hero';
import { gameData } from '../pubUtils/data';
import { getPlayerAttribute, getRobotAttribute } from './pvpService';
/**
* 根据存下的战力获取当前远征关卡的对手
* @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;
expeditionWarRecord = await ExpeditionWarRecordModel.saveRecord(expeditionCode, expeditionId, {
roleId, battleId: warId, ...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 {
cur.hp = enemy.attribute.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 {json: dicWarJson } = getWarJsons(warJsonIndex);
let min = myCe * scale * (1 - range/100);
let max = myCe * scale * (1 + range/100);
let resultRange = await PvpDefenseModel.findByScale(roleId, min, max);
if(resultRange.length > 0) {
let index = Math.floor(Math.random() * resultRange.length);
let result = resultRange[index];
let {roleId, heroes, defCe } = result;
let role = <RoleType>result.role;
let { attr: roleAttrs } = role;
enemyObj.enemyFrom = 1;
enemyObj.enemyId = roleId;
enemyObj.ce = defCe;
let heroIndex = 0;
for(let json of dicWarJson) {
if(json.relation == 2) {
let hero = heroes[heroIndex];
if(hero) {
let h = <HeroType>hero.hero;
let { star, lv, attr: heroAttrs, ce } = h;
let dicHero = gameData.hero.get(hero.actorId);
let newAttribute = getPlayerAttribute(heroAttrs, roleAttrs);
let heroInfo = {
actorId: hero.actorId,
actorName: dicHero.name,
skill:0,
seid:'&',
star,
spine: 0,
attribute: newAttribute,
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;
for(let json of dicWarJson) {
if(json.relation == 2) {
const { attribute } = json;
let newAttribute = getRobotAttribute(attribute, myCe, robotCe, scale);
let ce = newAttribute.ce;
enemyObj.enemies.push({...json, 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 now = new Date();
let today = now.setHours(0, 0, 0, 0);;
let isNew = today - role.createdAt.getTime() <= 3*24*60*60*1000;
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 = getGamedata('dic_expedition_point');
let pointRewards = {
expeditionPoint,
rewards: dicExpeditionPoint.map(cur => {
return { point: cur.point, received: false }
})
};
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, EXPEDITION_CONST.REFRESH_TIME);
if(needRefresh) {
expeditionResetCnt = 0; expeditionResetRefTime = curTime;
}
let maxCnt = EXPEDITION_CONST.RESET_CNT;
return {
resetCnt: maxCnt - expeditionResetCnt,
needRefresh
};
}