pvp: 更改pvpdefense结构

This commit is contained in:
luying
2021-10-26 11:23:08 +08:00
parent 4a5e23969b
commit e39b120af4
31 changed files with 1542 additions and 1137 deletions

View File

@@ -2,11 +2,11 @@
import { Application, BackendSession, pinus, HandlerService, } from 'pinus';
import { uniq, findWhere, findIndex } from 'underscore';
import { gameData, getPvpBoxs, getPLvByScore } from '../../../pubUtils/data';
import { refreshEnemies, getEnemies, getLvByScore, defaultHeroes, comsumeChallengeCnt, refresh, findPvpDefByRoleId, getRefOppCnt, findPvpDefAllByRoleId, generPVPOppRecInfo, generMyRecInfo, initPvpInfo } from '../../../services/pvpService';
import { refreshEnemies, getEnemies, getLvByScore, comsumeChallengeCnt, refChallengeCnt, generPVPOppRecInfo, generMyRecInfo, sendLastSeasonRewardIfNotSent, refreshRefOppCnt } from '../../../services/pvpService';
import { RoleModel, RoleType } from '../../../db/Role';
import { STATUS } from '../../../consts/statusCode';
import { resResult, genCode, checkRoleIsRobot, robotIdComBack } from '../../../pubUtils/util';
import { PvpDefenseModel, OppPlayers } from '../../../db/PvpDefense';
import { PvpDefenseModel, pvpUpdateInter } from '../../../db/PvpDefense';
import { pvpEndParamInter } from '../../../pubUtils/interface';
import { PlayerDetail, PlayerDetailHero } from '../../../domain/battleField/guild';
import { PVP_HERO_POS, PVP_HERO_ORDER, REDIS_KEY, LINEUP_NUM, TASK_TYPE, COUNTER } from '../../../consts';
@@ -18,12 +18,12 @@ import { BattleRecordModel } from '../../../db/BattleRecord';
import { PvpRecordModel } from '../../../db/PvpRecord';
import { handleCost } from '../../../services/rewardService';
import { nowSeconds, getSeconds } from '../../../pubUtils/timeUtil';
import { pvpSeasonEnd, resetPvpWarId, createNextPvpSeason } from '../../../services/timeTaskService';
import { PvpSeasonResultModel } from '../../../db/PvpSeasonResult';
import { PvpHistoryOppModel, PvpHistoryOppType } from '../../../db/PvpHistoryOpp';
import { PVPConfigModel } from '../../../db/SystemConfig';
import { Rank } from '../../../services/rankService';
import { checkActivityTask, checkTask, checkTaskInPvpEnd } from '../../../services/taskService';
import { PvpDataReturn } from '../../../domain/battleField/pvp';
export default function (app: Application) {
new HandlerService(app, {});
@@ -37,48 +37,62 @@ export class PvpHandler {
//1获取主界面
async getData(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let { pvpDefense, warId, seasonEndTime } = await findPvpDefAllByRoleId(roleId);
let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId);
if(!pvpDefense) {
let role = await RoleModel.findByRoleId(roleId);
pvpDefense = await initPvpInfo(role);
pvpDefense = await PvpDefenseModel.createPvpDefense({ roleId: role.roleId, roleName: role.roleName, role: role._id });
}
let oppPlayers = await getEnemies(pvpDefense.oppPlayers, pvpDefense.winStreakNum);
let { isDefaultHero, heroes, score, pLv, winStreakNum, refOppCnt, challengeCnt, challengeRefTime, receivedBox, hisScore, heroScores, isFirstEntry, seasonNum } = pvpDefense;
if (isFirstEntry) {
await PvpDefenseModel.updateInfo(roleId, { isFirstEntry: false });
pvpDefense = await sendLastSeasonRewardIfNotSent(pvpDefense);
let { seasonNum, seasonEndTime } = await PVPConfigModel.findCurPVPConfig();
let refChallengeObj = refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime);
let refOppObj = refreshRefOppCnt(pvpDefense.refOppCnt, pvpDefense.refDaily);
let update: pvpUpdateInter = { ...refChallengeObj, ...refOppObj};
let result = new PvpDataReturn(pvpDefense); // 返回对象
if(refOppObj.shouldRefOpp) {
let role = <RoleType>pvpDefense.role;
let oppPlayers = await refreshEnemies(role, seasonNum, pvpDefense.score, pvpDefense.attack.pLv);
update.oppPlayers = oppPlayers;
let oppPlayersReturn = await getEnemies(oppPlayers||[], pvpDefense.winStreakNum);
result.setOppPlayers(oppPlayersReturn);
} else {
let oppPlayersReturn = await getEnemies(pvpDefense.oppPlayers||[], pvpDefense.winStreakNum);
result.setOppPlayers(oppPlayersReturn);
}
let pvpSeasonResult = await PvpSeasonResultModel.getPvpSeasonResult(roleId);
let flag = false;
if (!!pvpSeasonResult) {
var { oldSeasonData, show, heroGoods, rankGoods } = pvpSeasonResult;
if (oldSeasonData.seasonEndTime > nowSeconds()) {//结算中锁定玩家信息,结算结束后统一展示修改完成的信息
seasonEndTime = oldSeasonData.seasonEndTime;
heroScores = oldSeasonData.heroScores;
score = oldSeasonData.score;
refOppCnt = oldSeasonData.refOppCnt;
challengeCnt = oldSeasonData.challengeCnt;
challengeRefTime = oldSeasonData.challengeRefTime;
} else if (show) {//是否需要弹出结算奖励界面
await PvpSeasonResultModel.updatePvpSeasonResult(roleId, { show: false });
flag = true;
}
let { score, winStreakNum, refOppCnt, challengeCnt, challengeRefTime, receivedBox, hisScore, heroScores, isFirstEntry } = pvpDefense;
if (pvpDefense.isFirstEntry) {
update.isFirstEntry = false;
}
let pvpSeasonResult = await PvpSeasonResultModel.getPvpSeasonResult(roleId, pvpDefense.seasonNum);
result.setPvpConfig(seasonNum, seasonEndTime);
if (!!pvpSeasonResult && !!pvpSeasonResult.show) {
result.setPvpSeasonResult(pvpSeasonResult);
await PvpSeasonResultModel.updatePvpSeasonResult(roleId, pvpSeasonResult.seasonNum, { show: false });
}
let r = new Rank(REDIS_KEY.PVP_RANK, {});
let myRank = await r.getMyRank({ roleId });//去redis中获取排名
result.setMyRank(myRank);
let data: any = {
warId, seasonNum, seasonEndTime, myRank, oppPlayers, heroes: heroes.map(cur => {
let { actorId, dataId, order } = cur;
return { actorId, dataId, order }
}), score, pLv, winStreakNum, refOppCnt, challengeCnt, challengeRefTime, receivedBox, hisScore, heroScores, isFirstEntry, isDefaultHero
}
if (flag) {//弹出结赛季结算奖励
data.resultRecord = { oldSeasonData, heroGoods, rankGoods }
}
return resResult(STATUS.SUCCESS, data);
// let data: any = {
// warId, seasonNum, seasonEndTime, myRank, oppPlayers, heroes: heroes.map(cur => {
// let { actorId, dataId, order } = cur;
// return { actorId, dataId, order }
// }), score, pLv, winStreakNum, refOppCnt, challengeCnt, challengeRefTime, receivedBox, hisScore, heroScores, isFirstEntry, isDefaultHero
// }
return resResult(STATUS.SUCCESS, result);
}
/*
// 刷新对手
async refreshOppPlayer(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
@@ -140,7 +154,7 @@ export class PvpHandler {
if (!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN);
// 检查挑战次数
let { seasonEndTime } = await PVPConfigModel.findCurPVPConfig();
let { challengeCnt, challengeRefTime } = refresh(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime);
let { challengeCnt, challengeRefTime } = refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime);
if (challengeCnt == 0) {
return resResult(STATUS.PVP_CHALLENGE_TIMES_NOT_ENOUGH);
}
@@ -273,7 +287,7 @@ export class PvpHandler {
let { seasonEndTime } = await PVPConfigModel.findCurPVPConfig();
let { heroes: defHeros, challengeCnt: lastChallengeCnt, challengeRefTime: lastChallengeRefTime } = await PvpDefenseModel.findByRoleId(roleId);
let defCe = 0;
let { challengeCnt, challengeRefTime } = refresh(lastChallengeCnt, lastChallengeRefTime, seasonEndTime);
let { challengeCnt, challengeRefTime } = refChallengeCnt(lastChallengeCnt, lastChallengeRefTime, seasonEndTime);
if (!!isDefaultHero) {
let { topLineup } = await RoleModel.findByRoleId(roleId);
@@ -430,7 +444,7 @@ export class PvpHandler {
return resResult(STATUS.PVP_BOX_IS_GOT);
}
receivedBox.push(id);
let { challengeCnt, challengeRefTime } = refresh(lastChallengeCnt, lastChallengeRefTime, seasonEndTime);
let { challengeCnt, challengeRefTime } = refChallengeCnt(lastChallengeCnt, lastChallengeRefTime, seasonEndTime);
await PvpDefenseModel.updateInfo(roleId, { receivedBox, challengeCnt, challengeRefTime });
let result = await addItems(roleId, roleName, sid, pvpBox.reward);
// 任务
@@ -514,4 +528,6 @@ export class PvpHandler {
let { challengeRefTime } = await PvpDefenseModel.updateInfoAndInclude(roleId, { challengeCnt, challengeRefTime: nowSeconds(), refOppCnt: 0 });
return resResult(STATUS.SUCCESS, { challengeCnt, challengeRefTime });
}
*/
}

View File

@@ -1,5 +1,5 @@
import { Application, ChannelService } from 'pinus';
import { resetPvpSeasonTime, setPvpDefResult, guildActivityStart, gateActivityEnd, cityActivityEnd, raceActivityEnd, guildActivitySchedule, auctionSchedule } from '../../../services/timeTaskService';
import { resetPvpSeasonTime, guildActivityStart, gateActivityEnd, cityActivityEnd, raceActivityEnd, guildActivitySchedule, auctionSchedule } from '../../../services/timeTaskService';
import PvpDefenseType from '../../../db/PvpDefense';
import { DicGuildActivity } from '../../../pubUtils/dictionary/DicGuildActivity';
import { reloadResources } from '../../../pubUtils/data';
@@ -23,10 +23,6 @@ export class SystimerRemote {
return await resetPvpSeasonTime(day);
}
public async setPvpDefResult(pvpDefense: PvpDefenseType, seasonNum: number, seasonEndTime:number) {
return await setPvpDefResult(pvpDefense, seasonNum, seasonEndTime);
}
public async guildActivityStart(dicGuildActivity: DicGuildActivity) {
return await guildActivityStart(dicGuildActivity);
}

View File

@@ -35,7 +35,6 @@ import { setMedianCe, getAllGuildActivityStatus } from './guildActivityService';
import { getAllOnlineRoles } from './redisService';
import Item from '../db/Item';
import { PvpDefenseModel } from '../db/PvpDefense';
import { findPvpDefAllByRoleId } from './pvpService';
import { getDonation } from './donateService';
export async function pushData(role: RoleType, session: FrontendOrBackendSession, pushType: 'entry' | 'refresh' = 'entry') {
@@ -189,10 +188,10 @@ async function getTowerEntryData(role: RoleType) {
async function getPvpEntryData(roleId: string) {
let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId);
if (pvpDefense) {
let { pvpDefense, } = await findPvpDefAllByRoleId(roleId);
let { challengeCnt, receivedBox, score, hisScore } = pvpDefense;
// let { pvpDefense, } = await findPvpDefAllByRoleId(roleId);
// let { challengeCnt, receivedBox, score, hisScore } = pvpDefense;
return { challengeCnt, score, hisScore, receivedBox }
// return { challengeCnt, score, hisScore, receivedBox }
} else {
return null
}

View File

@@ -1,17 +1,14 @@
import { ExpeditionPointModel } from '../db/ExpeditionPoint';
import Role, { RoleModel, RoleType } from '../db/Role';
import { PvpDefenseModel } from '../db/PvpDefense';
import Role, { CeAttrDataRole, RoleModel } from '../db/Role';
import { shouldRefresh, calculateSumCE, getRandSingleEelm } from '../pubUtils/util';
import { LINEUP_NUM, EXPEDITION_WAR_RECORD_STATUS, ABI_TYPE } from '../consts';
import { LINEUP_NUM, EXPEDITION_WAR_RECORD_STATUS } from '../consts';
import { ExpeditionWarRecordModel } from '../db/ExpeditionWarRecord';
import { HeroType } from '../db/Hero';
import { CeAttrData, HeroType } from '../db/Hero';
import { gameData } from '../pubUtils/data';
import { getPlayerAttribute, getRobotAttribute } from './pvpService';
import { getTimeFunD } from '../pubUtils/timeUtil';
import { ExpeditionRecordModel } from '../db/ExpeditionRecord';
import { Attribute } from '../domain/roleField/attribute';
import { Attribute, AttributeCal } from '../domain/roleField/attribute';
import * as dicParam from '../pubUtils/dicParam';
/**
@@ -80,7 +77,7 @@ export async function findOrCreateEnemies(roleId: string, myCe: number, expediti
};
// 获取系数和步长
let {scale, range, lv} = await getCEScaleAndRange(roleId, curDicExpedition);
let { scale, range, lv } = await getCEScaleAndRange(roleId, curDicExpedition);
// 优先匹配其他玩家
let flag = await matchPlayers(roleId, scale, range, myCe, curDicExpedition.json, enemyObj);
// 当数量不够时使用机器人匹配
@@ -133,30 +130,30 @@ export async function matchPlayers(roleId: string, scale: number, range: number,
let min = myCe * scale * (1 - range/100);
let max = myCe * scale * (1 + range/100);
let resultRange = await PvpDefenseModel.findByScale(roleId, min, max);
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 result = resultRange[index];
let {roleId, heroes, defCe } = result;
let role = <RoleType>result.role;
let role = resultRange[index];
let {roleId, topLineup, topLineupCe } = role;
let { attr: roleAttrs } = role;
enemyObj.enemyFrom = 1;
enemyObj.enemyId = roleId;
enemyObj.ce = defCe;
enemyObj.ce = topLineupCe;
let heroIndex = 0;
for(let json of dicWarJson) {
if(json.relation == 2) {
let hero = heroes[heroIndex];
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.actorId);
let dicHero = gameData.hero.get(hero.hid);
let { attribute } = getPlayerAttribute(lv, heroAttrs, roleAttrs);
let heroInfo = {
actorId: hero.actorId,
actorId: hero.hid,
skinId: h.skinId,
actorName: dicHero.name,
skill:0,
@@ -269,4 +266,46 @@ export async function getResetRemainCnt(curTime: Date, roleId: string, role?: Ro
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 };
}

View File

@@ -316,7 +316,6 @@ export async function settleGuildWeekly() {
await initSingleRank(REDIS_KEY.GUILD_ACTIVE_RANK);
await initSingleRank(REDIS_KEY.GUILD_LV_RANK);
let curSeasonNum = await CounterModel.getCounter(COUNTER.PVP_SEASON_NUM);
await PVPConfigModel.updatePVPConfig(curSeasonNum, { settleGuildWeeklyTime: nowSeconds() }); // 记录一下,不知道原作者有什么用处...
console.log('————— settleGuildWeekly结束 —————');
}

View File

@@ -8,7 +8,6 @@ import { STATUS } from '../consts/statusCode';
import { resResult, reduceCe } from '../pubUtils/util';
import { calPlayerCeAndSave as pubCalPlayerCeAndSave, reCalAllHeroCe } from '../pubUtils/playerCe';
import { HeroType, HeroUpdate } from '../db/Hero';
import { defaultHeroes } from './pvpService';
import { RoleUpdate, RoleType } from '../db/Role';
import { Rank } from './rankService';
@@ -39,7 +38,6 @@ export async function pushCalPlayerCe(roleId: string, sid: string, calResult: ca
//下发战力
let uids = [{ uid: roleId, sid }];
pinus.app.get('channelService').pushMessageByUids('onPlayerCeUpdate', resResult(STATUS.SUCCESS, { ce: reduceCe(role.ce) , heros: pushHeros, topLineupCe: reduceCe(topLineupCe) }), uids);
defaultHeroes(role);
if(guild) {
await updateUserInfo(REDIS_KEY.GUILD_INFO, guild.code, [{ field: 'guildCe', value: guild.guildCe }]);
}

View File

@@ -1,5 +1,4 @@
import { findPvpDefByRoleId } from '../services/pvpService'
import { getFuncsSwitch, gameData } from '../pubUtils/data';
import { FUNCS_ID, FUNC_OPT_TYPE } from '../consts/constModules/sysConst';
import { RoleModel } from '../db/Role';
@@ -22,8 +21,4 @@ export async function eventOnPlayerLvUp(roleId: string, lv: number, addFuncs: Ar
}
}
}
export async function loginRefresh(roleId: string) {
await findPvpDefByRoleId(roleId);
}

View File

@@ -1,14 +1,14 @@
import { PvpDefenseModel, Heroes, OppPlayers, PvpDefenseType, HeroScores, pvpUpdateInter } from '../db/PvpDefense';
import { PvpDefenseModel, PvpDefenseType, pvpUpdateInter } from '../db/PvpDefense';
import { Defense, Attack, LineupCe, OppPlayer, HeroScore, HeroReward, OppPlayerReturn } from '../domain/battleField/pvp';
import { RoleType, CeAttrDataRole } from '../db/Role';
import { PVP_HERO_POS, REDIS_KEY, PVP_CONST, COUNTER } from '../consts';
import { setPvpDefResult } from '../services/timeTaskService';
import { PVP_HERO_POS, REDIS_KEY, PVP_CONST, COUNTER, TASK_TYPE, MAIL_TYPE } from '../consts';
import { dicPvpOpponent, DicPvpOpponent } from "../pubUtils/dictionary/DicPvpOpponent";
import { getRandSingleIndex, genCode, shouldRefresh, getChineseName, makeRobotId, robotIdComBack } from '../pubUtils/util';
import { oppPlayersInter, pvpEndParamInter } from '../pubUtils/interface';
import { gameData, getPLvByScore } from "../pubUtils/data";
import { getRandSingleIndex, genCode, shouldRefresh, getChineseName, makeRobotId, robotIdComBack, getRandSingleEelm } from '../pubUtils/util';
import { pvpEndParamInter, RewardInter } from '../pubUtils/interface';
import { gameData, getPLvByScore, getPvpHeroRewardsByScore, getPvpRankRewardsByRank } from "../pubUtils/data";
import { PVP } from '../pubUtils/dicParam';
import { PVPConfigModel } from '../db/SystemConfig'
import { PVPConfigModel, PVPConfigType } from '../db/SystemConfig'
import { nowSeconds, getTimeFun } from '../pubUtils/timeUtil';
import { HeroesRecord } from '../db/PvpRecord';
import { HeroModel, CeAttrData } from '../db/Hero';
@@ -20,50 +20,10 @@ import { pinus } from 'pinus';
import { PvpHistoryOppModel, PvpHistoryOppType } from '../db/PvpHistoryOpp';
import { Rank } from './rankService';
import { CounterModel } from '../db/Counter';
export async function getPvpData() {
}
export async function initPvpInfo(role: RoleType) {
let heroes: Array<Heroes> = [];
//初始化最强5人阵容
let defCe = 0;
for (let i = PVP_HERO_POS.START; i <= PVP_HERO_POS.END; i++) {
let index = i - PVP_HERO_POS.START;
let item = role.topLineup[index];
if (item) defCe += item.ce;
heroes.push({
actorId: item?.hid || 0,
hero: item?.hero || null,
ce: item?.ce || 0,
dataId: i,
order: index + 1,
});
}
//初始化对手人阵容
let oppPlayers: Array<OppPlayers> = await refreshEnemies(role, 0, 1);
let { seasonNum } = await PVPConfigModel.findCurPVPConfig();
let challengeCnt = PVP.PVP_CHALLENGE_COUNTS;
let result = await PvpDefenseModel.createPvpDefenseAndPopulate({ roleId: role.roleId, roleName: role.roleName, role: role._id, heroes, oppPlayers, defCe, seasonNum, challengeCnt });
//加入排行榜
let r = new Rank(REDIS_KEY.PVP_RANK, {});
await r.setRankWithRoleInfo(REDIS_KEY.PVP_RANK, result.score, result.updatedAt.getTime(), role, false);
return result;
}
export async function checkPvp(role: RoleType) {
if (role.hasInit) {
let result = await PvpDefenseModel.findByRoleId(role.roleId, true);
if (!!result)
return result;
result = await initPvpInfo(role);
return result;
}
}
import { DicRankRewads } from '../pubUtils/dictionary/DicPvpRankReward';
import { PvpSeasonResultModel } from '../db/PvpSeasonResult';
import { checkTask } from '../services/taskService';
import { sendMailByContent } from './mailService';
/**
* 返回对手三人信息
@@ -71,9 +31,9 @@ export async function checkPvp(role: RoleType) {
* @param oppPlayers pvpDefense表中的oppPlayers字段需要populate过的
* @param pLv 玩家本人的队伍等级
*/
export async function getEnemies(oppPlayers: OppPlayers[], winStreakNum: number) {
export async function getEnemies(oppPlayers: OppPlayer[], winStreakNum: number) {
let result = new Array<oppPlayersInter>();
let result = new Array<OppPlayerReturn>();
for (let oppPlayer of oppPlayers) {
let dicOpponent = dicPvpOpponent.get(oppPlayer.pos);
let oppDef = <PvpHistoryOppType>oppPlayer.oppDef; // select 'oppRoleId pos roleName head frame spine rankLv pLv defCe'
@@ -96,21 +56,18 @@ export async function getEnemies(oppPlayers: OppPlayers[], winStreakNum: number)
* @param score 我的军功
* @param pLv 我的排名
*/
export async function refreshEnemies(role: RoleType, score: number, pLv: number) {
let system = await PVPConfigModel.findCurPVPConfig();
let mapWarJson = gameData.warJson.get(system.warId);
export async function refreshEnemies(role: RoleType, seasonNum: number, score: number, pLv: number) {
let { roleId } = role;
let oppPlayers = new Array<OppPlayers>();
let oppPlayers: OppPlayer[] = [];
let opp = dicPvpOpponent.values()
for (let dicOpp of opp) {
let flag = false; // 是否筛选成功
if (score >= PVP_CONST.SCORE_LINE) { // 将这个放到const
flag = await matchPlayer(system.seasonNum, oppPlayers, mapWarJson, roleId, pLv, dicOpp); // 按照等级匹配对手
if (!flag) flag = await matchPlayerByRank(system.seasonNum, oppPlayers, mapWarJson, roleId, dicOpp.id); // 当前后分数段没有时,返回前一名的玩家
if (!flag) flag = await matchRobot(oppPlayers, mapWarJson, role, pLv, dicOpp);
flag = await matchPlayer(seasonNum, oppPlayers, roleId, pLv, dicOpp); // 按照等级匹配对手
if (!flag) flag = await matchPlayerByRank(seasonNum, oppPlayers, roleId, dicOpp.id); // 当前后分数段没有时,返回前一名的玩家
if (!flag) flag = await matchRobot(oppPlayers, role, pLv, dicOpp);
} else {
flag = await matchRobot(oppPlayers, mapWarJson, role, pLv, dicOpp);
flag = await matchRobot(oppPlayers, role, pLv, dicOpp);
}
if (!flag) continue;
}
@@ -118,7 +75,7 @@ export async function refreshEnemies(role: RoleType, score: number, pLv: number)
return oppPlayers;
}
export async function matchPlayerByRank(seasonNum: number, oppPlayers: OppPlayers[], mapWarJson: DicWarJson[], roleId: string, pos: number) {
export async function matchPlayerByRank(seasonNum: number, oppPlayers: OppPlayer[], roleId: string, pos: number) {
// console.log('matchPlayerByRank', JSON.stringify(oppPlayers))
let r = new Rank(REDIS_KEY.PVP_RANK, {});
let ridRanks = new Array<number>(); // 已经被使用了的排名
@@ -172,7 +129,7 @@ export async function matchPlayerByRank(seasonNum: number, oppPlayers: OppPlayer
let pvpdefense = await PvpDefenseModel.findByRoleIdIncludeAll(oppRoleId);
if (!pvpdefense || pvpdefense.seasonNum != seasonNum) return false;
let pvpHistoryOpp = await generPlayerOppHis(pvpdefense, mapWarJson, roleId, pos);
let pvpHistoryOpp = await generPlayerOppHis(pvpdefense, roleId, pos);
if (!pvpHistoryOpp) return false;
oppPlayers.push({
@@ -184,7 +141,7 @@ export async function matchPlayerByRank(seasonNum: number, oppPlayers: OppPlayer
return true
}
async function matchPlayer(seasonNum: number, oppPlayers: OppPlayers[], mapWarJson: DicWarJson[], roleId: string, pLv: number, dicOpp: DicPvpOpponent) {
async function matchPlayer(seasonNum: number, oppPlayers: OppPlayer[], roleId: string, pLv: number, dicOpp: DicPvpOpponent) {
// console.log('matchPlayer', JSON.stringify(oppPlayers))
let { id: pos, minLv, maxLv } = dicOpp
@@ -203,7 +160,7 @@ async function matchPlayer(seasonNum: number, oppPlayers: OppPlayers[], mapWarJs
index = getRandSingleIndex(range.length);
result = range[index];
}
let pvpHistoryOpp = await generPlayerOppHis(result, mapWarJson, roleId, pos);
let pvpHistoryOpp = await generPlayerOppHis(result, roleId, pos);
if (!pvpHistoryOpp) return false;
oppPlayers.push({
roleId: pvpHistoryOpp.oppRoleId,
@@ -217,12 +174,13 @@ async function matchPlayer(seasonNum: number, oppPlayers: OppPlayers[], mapWarJs
/**
* @description 对手是玩家时生成并返回pvpHistoryOpp
* @param result 随机出的对手pvpDefense
* @param mapWarJson 本周地图出兵表
* @param roleId 自己的玩家id
* @param pos 刷新这个对手的位置
*/
async function generPlayerOppHis(pvpdefense: PvpDefenseType, mapWarJson: DicWarJson[], roleId: string, pos: number) {
let { heroScores, heroes: defenseHeroes } = pvpdefense;
async function generPlayerOppHis(pvpdefense: PvpDefenseType, roleId: string, pos: number) {
let { heroScores, defense } = pvpdefense;
if(!defense) return false;
let { warId, heroes: defenseHeroes } = defense;
let role = <RoleType>pvpdefense.role;
let r = new Rank(REDIS_KEY.PVP_RANK, {});
let rankLv = await r.getMyRank({ roleId: role.roleId });
@@ -233,6 +191,7 @@ async function generPlayerOppHis(pvpdefense: PvpDefenseType, mapWarJson: DicWarJ
let h = defenseHeroes.find(cur => cur.actorId == dbHero.hid); // 阵容里是否有这个武将
let hs = heroScores.find(cur => cur.hid == dbHero.hid); // 这个武将是否有这个得分
if (!!h) {
let mapWarJson = gameData.warJson.get(warId);
let warJson = mapWarJson.find(cur => cur.dataId == h.dataId);
if (warJson && warJson.relation == 2) {
let heroInfo = new PvpHeroInfo();
@@ -258,7 +217,7 @@ async function generPlayerOppHis(pvpdefense: PvpDefenseType, mapWarJson: DicWarJ
return pvpHistoryOpp;
}
async function matchRobot(oppPlayers: OppPlayers[], mapWarJson: DicWarJson[], role: RoleType, pLv: number, dicOpp: DicPvpOpponent) {
async function matchRobot(oppPlayers: OppPlayer[], role: RoleType, pLv: number, dicOpp: DicPvpOpponent) {
// console.log('matchRobot', JSON.stringify(oppPlayers))
let { lv: myLv, topLineupCe: myCe, roleId } = role;
@@ -271,23 +230,21 @@ async function matchRobot(oppPlayers: OppPlayers[], mapWarJson: DicWarJson[], ro
if (!result) return false;
let robotWarjson = gameData.warJson.get(result.war_id);
if (!robotWarjson) { /* TODO 判空处理 */ }
let heroes = new Array<PvpEnemies>();
if (!robotWarjson) return false
let heroes: PvpEnemies[] = [];
let defCe = 0;
for (let warJson of mapWarJson) {
if (warJson.relation == 1) continue;
let h = robotWarjson.find(cur => cur.dataId == warJson.dataId);
if (h) {
let dicHero = gameData.hero.get(h.actorId);
if (!dicHero) continue;
let heroInfo = new PvpHeroInfo();
heroInfo.setRobotInfo(h, myLv, dicHero.initialStars, dicHero.quality);
let { attribute, ce } = getRobotAttribute(h.attribute, h.enemyCount, [], pLv, myCe, PVP_CONST.ENEMY_CE, ratio);
defCe += ce;
heroInfo.setAttribute(attribute);
let enemy = new PvpEnemies(warJson, heroInfo, 0, ce);
heroes.push(enemy);
}
for (let h of robotWarjson) {
if (h.relation == 1) continue;
let actorId = h.randomEnemy.length > 0? getRandSingleEelm(h.randomEnemy): 0;
let dicHero = gameData.hero.get(actorId);
if (!dicHero) continue;
let heroInfo = new PvpHeroInfo();
heroInfo.setRobotInfo(h, actorId, myLv, dicHero.initialStars, dicHero.quality);
let { attribute, ce } = getRobotAttribute(h.attribute, h.enemyCount, [], pLv, myCe, PVP_CONST.ENEMY_CE, ratio);
defCe += ce;
heroInfo.setAttribute(attribute);
let enemy = new PvpEnemies(h, heroInfo, 0, ce);
heroes.push(enemy);
}
let oppRoleId = generateRobotRoleId();
@@ -321,7 +278,7 @@ export function getPlusScore(win: number) {
return result;
}
export function getLvByScore(heroScores: HeroScores[]) {
export function getLvByScore(heroScores: HeroScore[]) {
heroScores.sort((a, b) => b.score - a.score);
let score = 0;
for (let i = 0; i < 5; i++) {
@@ -331,71 +288,7 @@ export function getLvByScore(heroScores: HeroScores[]) {
return getPLvByScore(score);
}
export async function defaultHeroes(role: RoleType, challengeCnt?: number, challengeRefTime?: number, isUpdate?: boolean) {
let pvpDefense = await PvpDefenseModel.findByRoleId(role.roleId);
if (!pvpDefense) return;
let { heroes, isDefaultHero } = pvpDefense;
if (!isUpdate && !isDefaultHero) {
return;
}
let orders = [1, 2, 3, 4, 5, 6];
role.topLineup.sort(function (a, b) {
return b.ce - a.ce;
});
heroes.sort(function (a, b) {
return b.ce - b.dataId - a.ce + a.dataId;
});
for (let hero of heroes) {
if (!!hero.order && !!hero.hero && findIndex(role.topLineup, { hid: hero.actorId }) != -1) {
let index = orders.indexOf(hero.order);
orders.splice(index, 1);
}
}
let defCe = 0;
let num = 0;
for (let i = 0; i < role.topLineup.length; i++) {
let item = role.topLineup[i];
let index = findIndex(heroes, { actorId: item.hid });
if (index == -1) {
for (let j = num; j < heroes.length; j++) {
let hero = heroes[j];
if (num >= 6) {
break;
}
if (!!findWhere(role.topLineup, { hid: hero.actorId })) {
continue;
}
if (!orders[0]) {
break;
}
hero.actorId = item.hid;
hero.hero = item.hero;
hero.ce = item.ce;
hero.order = orders[0];
num = j;
orders.splice(0, 1);
break;
}
} else {
heroes[index].ce = item.ce;
heroes[index].hero = item.hero;
if (!heroes[index].order) {
heroes[index].order = orders[0];
orders.splice(0, 1);
}
}
defCe += item.ce;
}
if (!!challengeCnt && !!challengeRefTime) {
let { heroes: resHeroes } = await PvpDefenseModel.updateInfo(role.roleId, { defCe, heroes, challengeCnt, challengeRefTime, isDefaultHero: true });
return { resHeroes };
} else {
let { heroes: resHeroes } = await PvpDefenseModel.updateInfo(role.roleId, { defCe, heroes, isDefaultHero: true });
return { resHeroes };
}
}
export function refresh(challengeCnt: number, challengeRefTime: number, seasonEndTime: number) {
export function refChallengeCnt(challengeCnt: number, challengeRefTime: number, seasonEndTime: number) {
if (challengeCnt >= PVP.PVP_CHALLENGE_COUNTS) {
return { challengeCnt, challengeRefTime };
}
@@ -422,89 +315,32 @@ export function comsumeChallengeCnt(challengeCnt: number, challengeRefTime: numb
challengeRefTime = nowSeconds();
return { challengeCnt, challengeRefTime };
}
return refresh(challengeCnt, challengeRefTime, seasonEndTime);
return refChallengeCnt(challengeCnt, challengeRefTime, seasonEndTime);
}
export async function findPvpDefByRoleId(roleId: string) {
let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId);
let { warId, seasonNum, seasonEndTime } = await PVPConfigModel.findCurPVPConfig();
if(!pvpDefense) return { pvpDefense, warId }
let oldSeasonNum = await CounterModel.getCounter(COUNTER.PVP_SEASON_NUM);
let { seasonEndTime: oldSeasonEndTime } = await PVPConfigModel.findPVPConfig(oldSeasonNum);
if (pvpDefense.seasonNum !== seasonNum && oldSeasonEndTime < nowSeconds()) {
let newPvpDefense = await setPvpDefResult(pvpDefense, seasonNum, oldSeasonEndTime);
return { pvpDefense: newPvpDefense, warId };
export async function sendLastSeasonRewardIfNotSent(pvpDefense: PvpDefenseType) {
let pvpConfig = await PVPConfigModel.findCurPVPConfig(); // 当前的pvp赛季
if(pvpDefense.seasonNum != pvpConfig.seasonNum && pvpConfig.seasonEndTime < nowSeconds()) {
let oldPvpCongig = await PVPConfigModel.findPVPConfig(pvpDefense.seasonNum);
pvpDefense = await sendPVPRewardToUser(pvpDefense, pvpDefense.seasonNum, oldPvpCongig.seasonEndTime);
}
let { challengeCnt, challengeRefTime } = refresh(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime);
let { refOppCnt, refOppTime, shouldRefOpp } = getRefOppCnt(pvpDefense.refOppCnt, pvpDefense.refOppTime); // 刷新次数
if (challengeCnt != pvpDefense.challengeCnt || refOppCnt != pvpDefense.refOppCnt) {
await PvpDefenseModel.updateInfo(roleId, { challengeCnt, challengeRefTime, refOppCnt });
pvpDefense.challengeCnt = challengeCnt;
pvpDefense.challengeRefTime = challengeRefTime;
pvpDefense.refOppCnt = refOppCnt;
pvpDefense.refOppTime = refOppTime;
}
return { pvpDefense, warId, shouldRefOpp };
return pvpDefense;
}
// 获取刷新对手次数及消耗
export function getRefOppCnt(refOppCnt: number, refOppTime: Date) {
export function refreshRefOppCnt(refOppCnt: number, refDaily: Date) {
let curTime = new Date();
let shouldRefOpp = shouldRefresh(refOppTime, curTime);
let shouldRefOpp = shouldRefresh(refDaily, curTime);
if (shouldRefOpp) {
refOppCnt = 0; refOppTime = curTime;
refOppCnt = 0; refDaily = curTime;
}
return {
shouldRefOpp,
refOppCnt, refOppTime,
refOppCnt, refDaily,
consume: gameData.pvpRefreshConsume.get(refOppCnt + 1)
}
}
/**
* 获得玩家pvp信息并检查是否在pvp赛季结算中结算过未结算的进行结算
* @param roleId
*/
export async function findPvpDefAllByRoleId(roleId: string) {
let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId);
let { warId, seasonNum, seasonEndTime } = await PVPConfigModel.findCurPVPConfig();
if(!pvpDefense) return { pvpDefense, warId }
let oldSeasonNum = await CounterModel.getCounter(COUNTER.PVP_SEASON_NUM);
let { seasonEndTime: oldSeasonEndTime } = await PVPConfigModel.findPVPConfig(oldSeasonNum);
if (pvpDefense.seasonNum != seasonNum && oldSeasonEndTime < nowSeconds()) {//检查玩家是否在pvp赛季结算中结算过
let { score, pLv, winStreakNum, heroScores, challengeCnt, challengeRefTime } = await pinus.app.rpc.systimer.systimerRemote.setPvpDefResult.toServer('systimer-server-1', pvpDefense, seasonNum, oldSeasonEndTime);
pvpDefense.score = score;
pvpDefense.pLv = pLv;
pvpDefense.winStreakNum = winStreakNum;
pvpDefense.heroScores = heroScores;
pvpDefense.challengeCnt = challengeCnt;
pvpDefense.challengeRefTime = challengeRefTime;
}
pvpDefense.seasonNum = seasonNum;
let { challengeCnt, challengeRefTime } = refresh(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime);
let { refOppCnt, refOppTime, shouldRefOpp } = getRefOppCnt(pvpDefense.refOppCnt, pvpDefense.refOppTime); // 刷新次数
if (challengeCnt != pvpDefense.challengeCnt || refOppCnt != pvpDefense.refOppCnt || shouldRefOpp) {
let update: pvpUpdateInter = {
challengeCnt, challengeRefTime, refOppCnt, refOppTime
};
if (shouldRefOpp) {
let role = <RoleType>pvpDefense.role;
let oppPlayers = await refreshEnemies(role, pvpDefense.score, pvpDefense.pLv);
update.oppPlayers = oppPlayers;
}
let updateResult = await PvpDefenseModel.updateInfoAndInclude(roleId, update);
pvpDefense.oppPlayers = updateResult.oppPlayers;
pvpDefense.challengeCnt = challengeCnt;
pvpDefense.challengeRefTime = challengeRefTime;
pvpDefense.refOppCnt = refOppCnt;
pvpDefense.refOppTime = refOppTime;
}
return { pvpDefense, warId, shouldRefOpp, seasonEndTime, oldSeasonEndTime };
}
/**
* 根据比例计算机器人属性
@@ -561,7 +397,7 @@ export function getPlayerMainAttribute(heroAttrs: CeAttrData[], roleAttrs: CeAtt
}
// 获取我方战报记录
export async function generMyRecInfo(heroScores: HeroScores[], winStreakNum: number, role: RoleType, isSuccess: boolean, pos: number, myHeroes: pvpEndParamInter[]) {
export async function generMyRecInfo(heroScores: HeroScore[], winStreakNum: number, role: RoleType, isSuccess: boolean, pos: number, myHeroes: pvpEndParamInter[]) {
let { roleId, roleName } = role;
@@ -618,7 +454,7 @@ export async function generMyRecInfo(heroScores: HeroScores[], winStreakNum: num
}
// 获取对手战报记录
export async function generPVPOppRecInfo(isSuccess: boolean, curOpp: OppPlayers, oppHeroes: pvpEndParamInter[], myLv: number) {
export async function generPVPOppRecInfo(isSuccess: boolean, curOpp: OppPlayer, oppHeroes: pvpEndParamInter[], myLv: number) {
let oppHeroRecords = new Array<HeroesRecord>();
let oppRole = <PvpHistoryOppType>curOpp.oppDef;
if (!oppRole) { console.error('opp role not found') }
@@ -643,3 +479,102 @@ export async function generPVPOppRecInfo(isSuccess: boolean, curOpp: OppPlayers,
score: 0
}
}
/**
* pvp定时任务赛季结算
* @param obj
*/
export async function pvpSeasonEnd(pvpConfig: PVPConfigType) {
const pageNum = 500;
console.log('exce pvpSeasonEnd' + pvpConfig?.seasonNum);
let systemConfig = await PVPConfigModel.findCurPVPConfig();
let resultMaxRank = gameData.pvpRankMax.max;//根据排行榜的奖励表获得最大排名挡位的最小值其余不在结算中结算的玩家按照最大排名挡位在登录或进入pvp时结算
let maxPage = (resultMaxRank.min + 1000) / pageNum; //保底结算玩家数量
let lastPageNum = resultMaxRank.min % pageNum;
for (let page = 0; page < maxPage + 1; page++) {
let pvpDefenses = await PvpDefenseModel.getPvpDef(pageNum, page == maxPage ? lastPageNum : page);
for (let pvpDefense of pvpDefenses) {
if (pvpDefense.seasonNum !== systemConfig.seasonNum) {
await sendPVPRewardToUser(pvpDefense, systemConfig.seasonNum, systemConfig.seasonEndTime);
}
}
}
await PVPConfigModel.setReward(pvpConfig.seasonNum);
}
/**
* pvp定时任务结算获得添加邮件信息
* @param pvpDefense
* @param seasonNum
* @param oldSeasonEndTime
*/
export async function sendPVPRewardToUser(pvpDefense: PvpDefenseType, seasonNum: number, seasonEndTime: number, notPush?: boolean) {
//检查并返回排名结算以及武将功勋结算
let pvpSeasonResult = await savePvpSeasonResult(pvpDefense, seasonNum, seasonEndTime);
let { rankGoods, heroGoods, rankLv } = pvpSeasonResult;
//下发邮件
if (!!rankGoods.length) //排名奖励
await sendMailByContent(MAIL_TYPE.PVP_RANK_REWARD, pvpDefense.roleId, {
params: [JSON.stringify(seasonNum), (rankLv > 1000 ? '999+' : JSON.stringify(rankLv))],
goods: rankGoods, endTime: seasonEndTime, notPush
});
if (!!heroGoods.length) //武将功勋奖励
await sendMailByContent(MAIL_TYPE.PVP_RESULT, pvpDefense.roleId, {
params: [JSON.stringify(seasonNum)],
goods: heroGoods, endTime: seasonEndTime, notPush
});
pvpDefense = await PvpDefenseModel.resetScores(pvpDefense.roleId, seasonNum + 1, pvpSeasonResult.newScore, pvpSeasonResult.newHeroScores);
return pvpDefense;
}
/**
* 检查并返回排名结算以及武将功勋结算
* @param pvpDefense
* @param seasonNum
* @param oldSeasonEndTime
* @param rankLv
*/
export async function savePvpSeasonResult(pvpDefense: PvpDefenseType, seasonNum: number, seasonEndTime: number, rankLv?: number) {
if (!rankLv) {
let r = new Rank(REDIS_KEY.PVP_RANK, {});
rankLv = await r.getMyRank({ roleId: pvpDefense.roleId });// 获得排行榜排名
}
let pvpRankReward: DicRankRewads = getPvpRankRewardsByRank(rankLv);
let rankGoods: RewardInter[] = [];
if (pvpRankReward) {
rankGoods = pvpRankReward.reward;//排名奖励
}
let heroGoods: HeroReward[] = [];
let newHeroScores: HeroScore[] = [], newScore = 0;
for (let heroScore of pvpDefense.heroScores) {
let pvpHeroReward = getPvpHeroRewardsByScore(heroScore.score); //获得武将功勋奖励
if (pvpHeroReward) {
newHeroScores.push({...heroScore, score: pvpHeroReward.heroscore });
for(let { id, count } of pvpHeroReward.reward) {
heroGoods.push({
hid: heroScore.hid, id, count
});
}
}
newScore += heroScore.score;
}
//pvp锁定的信息存入赛季结算表中
let pvpSeasonResult = await PvpSeasonResultModel.updatePvpSeasonResult(pvpDefense.roleId, seasonNum, {
...pvpDefense, rankLv, heroGoods, rankGoods, show: true, newScore, newHeroScores, seasonEndTime
});//结算修改玩家pvp信息
// 更新任务
await checkTask(pvpDefense.roleId, null, TASK_TYPE.PVP_HERO_SCORE, 0, false, { heroScores: pvpDefense.heroScores });
await checkTask(pvpDefense.roleId, null, TASK_TYPE.PVP_RANK, 1, false, { rankLv });
return pvpSeasonResult;
}
function getScore(arr, score) {
for (let item of arr) {
if ((item.max >= score || item.max == -1) && score >= item.min) {
return item;
}
}
}

View File

@@ -34,6 +34,10 @@ export async function initAllRank() {
await delKeys(REDIS_KEY.MAIN_ELITE_RANK);
await delKeys(REDIS_KEY.HERO_RANK);
await delKeys(REDIS_KEY.SHOW_LINEUP);
await delKeys(REDIS_KEY.PVP_RANK);
await setRankRedisFromDb(REDIS_KEY.PVP_RANK, {});
for(let {id} of serverList) {
await initRank(id);
}

View File

@@ -1,14 +1,11 @@
import { scheduleJob, Job, } from 'node-schedule';
import { PVPConfigModel } from '../db/SystemConfig';
import PvpDefenseType, { PvpDefenseModel } from '../db/PvpDefense';
import { PVP, SERVER_DEBUG_MODE } from '../pubUtils/dicParam';
import { nowSeconds, getTimeFun } from '../pubUtils/timeUtil';
import { getPvpGkWarIds, getPvpRankRewards, getPvpHeroRewards, getResultMaxRank, getTodayGuildActivity, gameData } from '../pubUtils/data';
import { deepCopy, getRandSingleEelm } from '../pubUtils/util';
import { getLvByScore } from './pvpService';
import { getAllOnlineRoles, getAllServers, initSingleRank, delGuildActivityRank } from './redisService';
import { MAIL_TYPE, REDIS_KEY, GUILD_ACTIVITY_STATUS, GUILD_ACTIVITY_TYPE, TASK_TYPE, TIME_OUTPUT_TYPE, REFRESH_TIME, SEND_NAME, SERVER_OPEN_TIME, COUNTER, AUCTION_TIME } from '../consts';
import { PVPConfigModel, PVPConfigType } from '../db/SystemConfig';
import { nowSeconds, getTimeFun, getZeroPoint } from '../pubUtils/timeUtil';
import { getTodayGuildActivity, gameData } from '../pubUtils/data';
import { pvpSeasonEnd } from './pvpService';
import { getAllOnlineRoles, getAllServers, delGuildActivityRank } from './redisService';
import { GUILD_ACTIVITY_TYPE, REFRESH_TIME, SEND_NAME, SERVER_OPEN_TIME, COUNTER, AUCTION_TIME } from '../consts';
import { RoleModel } from '../db/Role';
import { pinus } from 'pinus';
import { indexOf } from 'underscore';
@@ -29,8 +26,7 @@ import { reportOneOnline } from './authenticateService';
const PER_SECOND = 1 * 1000;
const PER_DAY = 24 * 60 * 60;
const SETTLE_DIFF = 29 * 60;
const pageNum = 500;
const SETTLE_DIFF_SECONDS = 29 * 60;
const PER_MINUTE = 1 * 60;
var seasonMakeRewardTimJobId: Job;
var warJobId: Job;
@@ -46,22 +42,9 @@ let pvpRefreshInterval = null;
* 服务器启动即开启定时任务结算时常是23-24点实际结算的时间点是2331分钟
*/
export async function init() {
let systemConfig = await PVPConfigModel.findCurPVPConfig();
let seasonEndTime = systemConfig ? systemConfig.seasonEndTime : <number>getTimeFun(moment(SERVER_OPEN_TIME).startOf('d').add(-1, 'minute').toDate()).getAfterDay(PVP.PVP_SEASON_DAYS);
if (nowSeconds() > seasonEndTime) {//停服太长,数据配置问题导致数据太老,需要刷新赛季数据
while (nowSeconds() > seasonEndTime) {
seasonEndTime = <number>getTimeFun(seasonEndTime).getAfterDay(PVP.PVP_SEASON_DAYS);
}
}
if (!systemConfig || seasonEndTime != systemConfig.seasonEndTime) {
systemConfig = await createNewPvpSeasonData(seasonEndTime)
}
await resetPVPTimer(seasonEndTime);
warJobId = scheduleJob("0 0 0 * * 1", resetPvpWarId);//每周1零点重置地图
await resetPvpRanks();//服务器重启,重置排行榜的信息
// pvp赛季
await setPvpSeason();
// 周功勋结算任务
guildWeeklyJobId = scheduleJob('settleGuildWeekly', '0 0 0 * * 1', settleGuildWeekly);
@@ -86,248 +69,67 @@ export async function init() {
await initMaintenance();
}
async function resetPVPTimer(seasonEndTime: number) {
function getSeasonContinueDay(seasonNum: number) {
const pvpSeasonDuring = [{seasonNum: 1, day: 7},{seasonNum: 2, day: 15},{seasonNum: 3, day: 30},];
let maxDay = 0;
for(let {seasonNum: dicSeasonNum, day } of pvpSeasonDuring) {
if(seasonNum == dicSeasonNum) return day;
if(maxDay < day) maxDay = day;
}
return maxDay;
}
async function setPvpSeason() {
let pvpConfig = await PVPConfigModel.findCurPVPConfig();
if(!pvpConfig || pvpConfig.seasonEndTime <= nowSeconds() ) {
if(!pvpConfig.hasSettleReward) {
await pvpSeasonEnd(pvpConfig);
}
let lastSeasonNum = pvpConfig? pvpConfig.seasonNum: 0;
let lastSeasonEndTime = pvpConfig? pvpConfig.seasonEndTime: 0;
let newSeasonStartTime = lastSeasonEndTime;
let during = getSeasonContinueDay(lastSeasonNum + 1) * PER_DAY;
let rewardTime = SETTLE_DIFF_SECONDS;
if(nowSeconds() - lastSeasonEndTime > during) {
newSeasonStartTime = getZeroPoint();
}
pvpConfig = await PVPConfigModel.createPVPConfig(lastSeasonNum + 1, newSeasonStartTime, newSeasonStartTime + during - rewardTime, newSeasonStartTime + during - PER_MINUTE);
}
await setPvpSeasonMakeRewardJob(pvpConfig);
await setNextSeasonJob(pvpConfig);
}
async function setPvpSeasonMakeRewardJob(pvpConfig: PVPConfigType) {
if (!!seasonMakeRewardTimJobId) {
seasonMakeRewardTimJobId.cancel();
clearInterval(pvpMakeRewardInterval);
}
if(pvpConfig.seasonRewardTime < nowSeconds() && !pvpConfig.hasSettleReward) { // 未发奖励
await pvpSeasonEnd(pvpConfig);
} else {
seasonMakeRewardTimJobId = scheduleJob('seasonMakeRewardTimJobId', pvpConfig.seasonRewardTime, async () => {
await pvpSeasonEnd(pvpConfig);
});
}
}
async function setNextSeasonJob(pvpConfig: PVPConfigType) {
if (!!seasonRefreshTimeJobId) {
seasonRefreshTimeJobId.cancel();
clearInterval(pvpRefreshInterval);
}
if (seasonEndTime - SETTLE_DIFF - nowSeconds() < 0) {//2330-2400之间,已经过了结算时间,还未开启新赛季
console.log('立刻结算奖励:', nowSeconds());
await pvpSeasonEnd();
//定时结算奖励
seasonMakeRewardTimJobId = scheduleJob('seasonMakeRewardTimJobId', (seasonEndTime - SETTLE_DIFF - nowSeconds()) * PER_SECOND + PVP.PVP_SEASON_DAYS * PER_DAY * PER_SECOND, pvpMakeRewardTimer);//
} else {
//定时结算奖励
seasonMakeRewardTimJobId = scheduleJob('seasonMakeRewardTimJobId', (seasonEndTime - SETTLE_DIFF - nowSeconds()) * PER_SECOND, pvpMakeRewardTimer);//
};
//定时开启新赛季
seasonRefreshTimeJobId = scheduleJob('seasonRefreshTimeJobId', (seasonEndTime - nowSeconds()) * PER_SECOND, pvpRefreshTimer);//
//定时开启新赛季,比seasonEndTime多定一分钟,保证定时器时间没错
seasonRefreshTimeJobId = scheduleJob('seasonRefreshTimeJobId', pvpConfig.seasonEndTime + PER_MINUTE, setPvpSeason);
}
//pvp结算奖励定时器
async function pvpMakeRewardTimer() {
pvpMakeRewardInterval = setInterval(async () => {
console.log('定时结算奖励:', nowSeconds());
await pvpSeasonEnd()
}, PVP.PVP_SEASON_DAYS * PER_DAY * PER_SECOND)
}
//pvp刷新开始新赛季定时器
async function pvpRefreshTimer() {
pvpRefreshInterval = setInterval(async () => {
console.log('定时开启新赛季:', nowSeconds());
await createNextPvpSeason();
}, PVP.PVP_SEASON_DAYS * PER_DAY * PER_SECOND)
}
//创建下个新赛季
export async function createNextPvpSeason() {
let systemConfig = await PVPConfigModel.findCurPVPConfig();
let seasonEndTime = systemConfig ? systemConfig.seasonEndTime : <number>getTimeFun(moment(SERVER_OPEN_TIME).startOf('d').add(-1, 'minute').toDate()).getAfterDay(PVP.PVP_SEASON_DAYS);
if (nowSeconds() > seasonEndTime) {//停服太长,数据配置问题导致数据太老,需要刷新赛季数据
while (nowSeconds() > seasonEndTime) {
seasonEndTime = <number>getTimeFun(seasonEndTime).getAfterDay(PVP.PVP_SEASON_DAYS);
}
}
systemConfig = await createNewPvpSeasonData(seasonEndTime)
await resetPvpRanks()
return systemConfig;
}
/**
* pvp定时任务赛季结算
* @param obj
*/
export async function pvpSeasonEnd(obj?: { name: string, notSetNext?: boolean, notPush?: boolean }) {
console.log('exce pvpSeasonEnd' + obj?.name);
let systemConfig = await PVPConfigModel.findCurPVPConfig();
let resultMaxRank = getResultMaxRank();//根据排行榜的奖励表获得最大排名挡位的最小值其余不在结算中结算的玩家按照最大排名挡位在登录或进入pvp时结算
let maxPage = (resultMaxRank.min + 1000) / pageNum; //保底结算玩家数量
let lastPageNum = resultMaxRank.min % pageNum;
for (let page = 0; page < maxPage + 1; page++) {
let pvpDefenses = await PvpDefenseModel.getPvpDef(pageNum, page == maxPage ? lastPageNum : page);
for (let pvpDefense of pvpDefenses) {
if (pvpDefense.seasonNum !== systemConfig.seasonNum) {
await setPvpDefResultOnTime(pvpDefense, systemConfig.seasonNum, systemConfig.seasonEndTime, obj?.notPush);
}
}
}
}
/**
* pvp定时任务结算获得添加邮件信息
* @param pvpDefense
* @param seasonNum
* @param oldSeasonEndTime
*/
export async function setPvpDefResultOnTime(pvpDefense: PvpDefenseType, seasonNum: number, oldSeasonEndTime: number, notPush?: boolean) {
//检查并返回排名结算以及武将功勋结算
let { score, pLv, heroScores, challengeCnt, challengeRefTime, rankGoods, heroGoods, rankLv } = await checkResult(pvpDefense, seasonNum, oldSeasonEndTime);
pvpDefense = await PvpDefenseModel.updateInfo(pvpDefense.roleId, { score, pLv, heroScores, seasonNum, challengeCnt, challengeRefTime });
//下发邮件
if (!!rankGoods.length) //排名奖励
await sendMailByContent(MAIL_TYPE.PVP_RANK_REWARD, pvpDefense.roleId, {
params: [JSON.stringify(seasonNum), (rankLv > 1000 ? '999+' : JSON.stringify(rankLv))],
goods: rankGoods, endTime: oldSeasonEndTime, notPush
});
if (!!heroGoods.length) //武将功勋奖励
await sendMailByContent(MAIL_TYPE.PVP_RESULT, pvpDefense.roleId, {
params: [JSON.stringify(seasonNum)],
goods: heroGoods, endTime: oldSeasonEndTime, notPush
});
return pvpDefense;
}
/**
* 检查并返回排名结算以及武将功勋结算
* @param pvpDefense
* @param seasonNum
* @param oldSeasonEndTime
* @param rankLv
*/
export async function checkResult(pvpDefense: PvpDefenseType, seasonNum: number, oldSeasonEndTime: number, rankLv?: number) {
let pvpRankRewards = getPvpRankRewards();
let pvpHeroRewards = getPvpHeroRewards();
if (!rankLv) {
let r = new Rank(REDIS_KEY.PVP_RANK, {});
rankLv = await r.getMyRank({ roleId: pvpDefense.roleId });// 获得排行榜排名
}
let oldPLv = getLvByScore(pvpDefense.heroScores);//结算前玩家的pvp等级
let { challengeCnt, challengeRefTime } = pvpDefense;
let pvpRankReward;
if (!!rankLv) {
pvpRankReward = getScore(pvpRankRewards, rankLv);//获得排名挡位信息
} else {
pvpRankReward = getResultMaxRank();//最大排名等级挡位信息
}
let rankGoods = [];
if (pvpRankReward) {
rankGoods = pvpRankReward.reward;//排名奖励
}
let heroGoods = [];
let score = 0;
let oldHeroScores = deepCopy(pvpDefense.heroScores)
for (let i = 0; i < pvpDefense.heroScores.length; i++) {
let heroScore = pvpDefense.heroScores[i];
let pvpHeroReward = getScore(pvpHeroRewards, heroScore.score);//获得武将功勋奖励
if (pvpHeroReward) {
heroScore.score = pvpHeroReward.heroscore;
if (!!pvpHeroReward.reward[0]) {
heroGoods.push({
hid: heroScore.hid,
id: pvpHeroReward.reward[0].id,
count: pvpHeroReward.reward[0].count,
});
}
}
score += heroScore.score;
}
let pLv = getLvByScore(pvpDefense.heroScores);
//pvp锁定的信息存入赛季结算表中
await PvpSeasonResultModel.updatePvpSeasonResult(pvpDefense.roleId, {
oldSeasonData: {
refOppCnt: pvpDefense.refOppCnt, rankLv, score: pvpDefense.score, pLv: oldPLv, heroScores: oldHeroScores,
seasonNum: pvpDefense.seasonNum, challengeCnt, challengeRefTime, seasonEndTime: oldSeasonEndTime
}, heroGoods, rankGoods, show: true
});//结算修改玩家pvp信息
// 更新任务
await checkTask(pvpDefense.roleId, null, TASK_TYPE.PVP_HERO_SCORE, 0, false, { heroScores: pvpDefense.heroScores });
await checkTask(pvpDefense.roleId, null, TASK_TYPE.PVP_RANK, 1, false, { rankLv });
return {
rankLv, score, pLv, heroScores: pvpDefense.heroScores, seasonNum, challengeCnt: PVP.PVP_CHALLENGE_COUNTS, challengeRefTime: 0, oldSeasonEndTime, heroGoods: heroGoods.map(({ id, count }) => {
return { id, count };
}), rankGoods
};
}
/**
* 个人pvp结算结算中未结算的都按照最大排名挡位结算
* @param pvpDefense
* @param seasonNum
* @param oldSeasonEndTime
*/
export async function setPvpDefResult(pvpDefense: PvpDefenseType, seasonNum: number, oldSeasonEndTime: number) {
let role = await RoleModel.findByRoleId(pvpDefense.roleId);
if (!role) {
return;
}
let resultMaxRank = getResultMaxRank();
let rankLv = resultMaxRank.min; //最大排名挡位结算
let { score, pLv, heroScores, challengeCnt, challengeRefTime, rankGoods, heroGoods } = await checkResult(pvpDefense, seasonNum, oldSeasonEndTime, rankLv);
pvpDefense = await PvpDefenseModel.updateInfoAndInclude(pvpDefense.roleId, { score, pLv, heroScores, seasonNum, challengeCnt, challengeRefTime });
let { roleId } = role;
let r = new Rank(REDIS_KEY.PVP_RANK, {});
r.setRankWithRoleInfo(pvpDefense.roleId, pvpDefense.score, pvpDefense.updatedAt.getTime(), role, true);
//下发邮件
if (!!rankGoods.length)
await sendMailByContent(MAIL_TYPE.PVP_RANK_REWARD, roleId, { params: [JSON.stringify(seasonNum), '999+'], goods: rankGoods, endTime: oldSeasonEndTime });
if (!!heroGoods.length)
await sendMailByContent(MAIL_TYPE.PVP_RESULT, roleId, { params: [JSON.stringify(seasonNum)], goods: heroGoods, endTime: oldSeasonEndTime });
return pvpDefense;
}
/**
* 新pvp赛季数据
*/
export async function createNewPvpSeasonData(seasonEndTime: number) {
console.log('createNewPvpSeasonData');
let seasonNum = await CounterModel.getNewCounter(COUNTER.PVP_SEASON_NUM);
// let seasonEndTime: number = <number>getTimeFun(oldEndTime).getAfterDay(PVP.PVP_SEASON_DAYS);
let warId = getPvpWarId(-1);
let systemConfig = await PVPConfigModel.createPVPConfig(seasonNum, seasonEndTime, warId);
return systemConfig;
}
/**
* 随机地图Id
*/
function getPvpWarId(oldWarId: number): number {
let warIds: number[] = deepCopy(getPvpGkWarIds());
let index = indexOf(warIds, oldWarId);
if (index != -1) {
warIds.splice(index, 1);
}
let warId = getRandSingleEelm(warIds);
console.log('getPvpWarId', oldWarId, warId);
return warId;
}
/**
* 每周重置地图
*/
export async function resetPvpWarId() {
let systemConfig = await PVPConfigModel.findCurPVPConfig();
let warId = getPvpWarId(systemConfig.warId)
return await PVPConfigModel.updatePVPConfig(systemConfig.seasonNum, { warId });
}
function getScore(arr, score) {
for (let item of arr) {
if ((item.max >= score || item.max == -1) && score >= item.min) {
return item;
}
}
}
/**
* debug接口
* @param hour
*/
export async function resetPvpSeasonTime(hour: number) {
let systemConfig = await PVPConfigModel.findCurPVPConfig();
let seasonEndTime = <number>getTimeFun().getTimeWithHour(REFRESH_TIME - hour);
systemConfig = await createNewPvpSeasonData(seasonEndTime);
await resetPVPTimer(seasonEndTime);
await resetPvpRanks();
console.log('settleTime = ' + systemConfig.seasonNum)
return { seasonEndTime, seasonNum: systemConfig.seasonNum };
}
export async function resetPvpRanks() {
await initSingleRank(REDIS_KEY.PVP_RANK);
await PVPConfigModel.setCurPvpConfig({ seasonEndTime: getZeroPoint() });
return await setPvpSeason();
}
export async function reportOnlineSchedule() {

View File

@@ -100,17 +100,17 @@ export default class UserController extends Controller {
ctx.body = await ctx.service.users.setHeroJob(roleIdAndHids, job);
}
public async saveHeroToDefense() {
const { ctx } = this;
const { roleId, roleName, hid } = ctx.request.body;
ctx.body = await ctx.service.users.saveHeroToDefense(roleId, roleName, hid);
}
// public async saveHeroToDefense() {
// const { ctx } = this;
// const { roleId, roleName, hid } = ctx.request.body;
// ctx.body = await ctx.service.users.saveHeroToDefense(roleId, roleName, hid);
// }
public async removeHeroFromDefense() {
const { ctx } = this;
const { roleId, hid } = ctx.request.body;
ctx.body = await ctx.service.users.removeHeroFromDefense(roleId, hid);
}
// public async removeHeroFromDefense() {
// const { ctx } = this;
// const { roleId, hid } = ctx.request.body;
// ctx.body = await ctx.service.users.removeHeroFromDefense(roleId, hid);
// }
public async getEquipList() {
const { ctx } = this;

View File

@@ -37,8 +37,8 @@ export default (app: Application) => {
router.post('/api/users/setherolv', tokenParser, controller.users.setHeroLv);
router.post('/api/users/setheroparam', controller.users.setHeroParam);
router.post('/api/users/setherojob', controller.users.setHeroJob);
router.post('/api/users/saveherotodefense',tokenParser, controller.users.saveHeroToDefense);
router.post('/api/users/removeherofromdefense',tokenParser, controller.users.removeHeroFromDefense);
// router.post('/api/users/saveherotodefense',tokenParser, controller.users.saveHeroToDefense);
// router.post('/api/users/removeherofromdefense',tokenParser, controller.users.removeHeroFromDefense);
router.post('/api/users/getequiplist', tokenParser, controller.users.getEquipList);
router.post('/api/users/getitemlist', tokenParser, controller.users.getItemList);
router.post('/api/users/deleteequip', tokenParser, controller.users.deleteEquip);

View File

@@ -193,7 +193,7 @@ export default class GMUsers extends Service {
let { uid, tel } = role.userInfo;
result.push({
key: roleId, roleId, roleName, serverId, lv, vLv, uid, tel, heroCount, equipCount, itemCount, gold, coin,
hasDefense: defense ? '是' : '否', defCe: defense ? defense.defCe : 0
hasDefense: defense ? '是' : '否', defCe: 0
});
}
return ctx.service.utils.resResult(STATUS.SUCCESS, { list: result });
@@ -394,59 +394,59 @@ export default class GMUsers extends Service {
// })
// }
public async saveHeroToDefense(roleId: string, _roleName: string, hid: number) {
const { ctx } = this;
let hero = await HeroModel.findByHidAndRole(hid, roleId);
let role = await RoleModel.findByRoleId(roleId);
if (!hero || !role) {
return ctx.service.utils.resResult(STATUS.GM_HERO_NOT_FOUND);
}
let { lv, ce, attr: heroAttrs } = hero;
let { attr: roleAttrs } = role;
// public async saveHeroToDefense(roleId: string, _roleName: string, hid: number) {
// const { ctx } = this;
// let hero = await HeroModel.findByHidAndRole(hid, roleId);
// let role = await RoleModel.findByRoleId(roleId);
// if (!hero || !role) {
// return ctx.service.utils.resResult(STATUS.GM_HERO_NOT_FOUND);
// }
// let { lv, ce, attr: heroAttrs } = hero;
// let { attr: roleAttrs } = role;
let dicHero = gameData.hero.get(hid);
// let dicHero = gameData.hero.get(hid);
let attribute = new AttributeCal();
attribute.setByDbData(roleAttrs, heroAttrs);
// let attribute = new AttributeCal();
// attribute.setByDbData(roleAttrs, heroAttrs);
let heroInfo = {
actorId: dicHero.heroId,
actorName: dicHero.name,
attribute, lv,
ce
};
// let heroInfo = {
// actorId: dicHero.heroId,
// actorName: dicHero.name,
// attribute, lv,
// ce
// };
let defense = await PvpDefenseModel.findByRoleId(roleId);
if (!defense) {
// defense = await PvpDefenseModel.createPvpDefense({roleId, roleName, heroes: [], defCe:ce});
} else {
defense = await PvpDefenseModel.addHeroToDefense(roleId, heroInfo, ce);
}
return ctx.service.utils.resResult(STATUS.SUCCESS, {
defense
});
}
// let defense = await PvpDefenseModel.findByRoleId(roleId);
// if (!defense) {
// // defense = await PvpDefenseModel.createPvpDefense({roleId, roleName, heroes: [], defCe:ce});
// } else {
// defense = await PvpDefenseModel.addHeroToDefense(roleId, heroInfo, ce);
// }
// return ctx.service.utils.resResult(STATUS.SUCCESS, {
// defense
// });
// }
public async removeHeroFromDefense(roleId: string, hid: number) {
const { ctx } = this;
// public async removeHeroFromDefense(roleId: string, hid: number) {
// const { ctx } = this;
let defense = await PvpDefenseModel.findByRoleId(roleId);
if (!defense) {
return ctx.service.utils.resResult(STATUS.GM_PVP_DEFENSE_NOT_FOUND);
}
let { heroes } = defense;
let curHero = heroes.find(cur => cur.actorId == hid);
if (!curHero) {
return ctx.service.utils.resResult(STATUS.GM_PVP_DEFENSE_HERO_NOT_FOUND);
}
defense = await PvpDefenseModel.removeHeroFromDefense(roleId, hid, curHero.ce);
// let defense = await PvpDefenseModel.findByRoleId(roleId);
// if (!defense) {
// return ctx.service.utils.resResult(STATUS.GM_PVP_DEFENSE_NOT_FOUND);
// }
// let { heroes } = defense;
// let curHero = heroes.find(cur => cur.actorId == hid);
// if (!curHero) {
// return ctx.service.utils.resResult(STATUS.GM_PVP_DEFENSE_HERO_NOT_FOUND);
// }
// defense = await PvpDefenseModel.removeHeroFromDefense(roleId, hid, curHero.ce);
return ctx.service.utils.resResult(STATUS.SUCCESS, {
defense
});
}
// return ctx.service.utils.resResult(STATUS.SUCCESS, {
// defense
// });
// }
/**
* 根据类型等搜索玩家

View File

@@ -1,64 +1,10 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, Ref, mongoose } from '@typegoose/typegoose';
import Hero, { } from './Hero';
import Role, { } from './Role';
import { PVP_PLAYER_POS, PVP_HERO_POS } from '../consts';
import PvpHistoryOpp from './PvpHistoryOpp';
import { reduceCe } from '../pubUtils/util';
export class Heroes {
@prop({ required: true })
actorId: number; // 武将id
@prop({ ref: 'Hero', type: mongoose.Schema.Types.ObjectId })
hero: Ref<Hero>;
@prop({ required: true })
ce: number; // 战斗力
@prop({ required: true })
dataId: number;
@prop({ required: true })
order: number;
}
// 初始化
function getInitialOppPlayers() {
let players = new Array<OppPlayers>();
for(let i = PVP_PLAYER_POS.START; i <= PVP_PLAYER_POS.END; i++) {
let p = new OppPlayers();
p.pos = i;
players.push(p);
}
return players;
}
// 初始化
function getInitialOppHeros() {
let heros = new Array<Heroes>();
for(let i = PVP_HERO_POS.START; i <= PVP_HERO_POS.END; i++) {
let p = new Heroes();
p.dataId = i;
p.order = i;
heros.push(p);
}
return heros;
}
export class OppPlayers {
@prop({ required: true })
roleId: string;
@prop({ ref: 'PvpHistoryOpp', type: mongoose.Schema.Types.ObjectId })
oppDef: Ref<PvpHistoryOpp>;
@prop({ required: true })
pos: number;
@prop({ required: true })
isRobot: boolean;
}
export class HeroScores {
@prop({ required: true })
hid: number;
@prop({ required: true })
score: number;
}
import { Defense, Attack, LineupCe, OppPlayer, HeroScore, } from '../domain/battleField/pvp';
import { CounterModel } from './Counter';
import { COUNTER } from '../consts';
import { PVP } from '../pubUtils/dicParam';
@index({ roleId: 1 })
export default class PvpDefense extends BaseModel {
@@ -68,38 +14,43 @@ export default class PvpDefense extends BaseModel {
roleName: string; // 角色名称
@prop({ ref: 'Role', type: mongoose.Schema.Types.ObjectId })
role: Ref<Role>;
@prop({ required: true, type: Heroes, default: getInitialOppHeros(), _id: false })
heroes: Array<Heroes>;
@prop({ required: true, default: null, _id: false })
defense: Defense;
@prop({ required: true, default: null, _id: false })
attack: Attack;
@prop({ required: true, type: () => LineupCe, default: [], _id: false })
lineupCe: LineupCe[];
@prop({ required: true, type: () => OppPlayer, default: [], _id: false })
oppPlayers: OppPlayer[];
@prop({ required: true, type: () => HeroScore, default: [], _id: false })
heroScores: HeroScore[];
@prop({ required: true, default: 0 })
score: number;
@prop({ required: true, default: 1 })
pLv: number;
@prop({ required: true, default: 0 })
hisScore: number; //历史最高积分
@prop({ required: true, default: 0 })
winStreakNum: number; //连胜次数
@prop({ required: true, default: 0, get: (val: number) => reduceCe(val), set: (val: number) => val })
defCe: number; //防守ce
@prop({ required: true, type: OppPlayers, default: getInitialOppPlayers(), _id: false })
oppPlayers: Array<OppPlayers>;
@prop({ required: true, type: HeroScores, default: [], _id: false })
heroScores: Array<HeroScores>;
@prop({ required: true, default: true })
isDefaultHero: boolean;
@prop({ required: true, default: () => { return new Date() } })
refDaily: Date; // 每日刷新控制refOppCnt和setAttackCnt
@prop({ required: true, default: 0 })
refOppCnt: number; // 刷新对手总次数,消耗可根据消耗表算出
@prop({ required: true, default: new Date() })
refOppTime: Date; // 刷新对手时间
@prop({ required: true, default: 0 })
challengeCnt: number; // 可挑战次数
setAttackCnt: number; // 设置挑战阵容次数
@prop({ required: true, default: 0 })
challengeCnt: number; // 可挑战次数每2小时回复一次
@prop({ required: true, default: 0 })
challengeRefTime: number; // 上一次刷新的时间
@prop({ required: true, type: Number, default: [] })
receivedBox: Array<number>;
@prop({ required: true, default: 0 })
seasonNum: number;
@prop({ required: true, default: true })
isFirstEntry: boolean;
public static async findByRoleId(roleId: string, getters = false) {
const result: PvpDefenseType = await PvpDefenseModel.findOne({ roleId }).lean({ getters});
return result;
@@ -114,18 +65,12 @@ export default class PvpDefense extends BaseModel {
}
public static async createPvpDefense(params: pvpUpdateInter) {
let seasonNum = await CounterModel.getCounter(COUNTER.PVP_SEASON_NUM);
const doc = new PvpDefenseModel();
const update = Object.assign(doc.toJSON(), params);
const defense: PvpDefenseType = await PvpDefenseModel.findOneAndUpdate({ roleId: params.roleId }, update, { upsert: true, new: true }).lean();
return defense;
}
public static async createPvpDefenseAndPopulate(params: pvpUpdateInter) {
const doc = new PvpDefenseModel();
const update = Object.assign(doc.toJSON(), params);
const update = Object.assign(doc.toJSON(), params, { seasonNum, challengeCnt: PVP.PVP_CHALLENGE_COUNTS });
const defense: PvpDefenseType = await PvpDefenseModel.findOneAndUpdate({ roleId: params.roleId }, update, { upsert: true, new: true })
.populate('oppPlayers.oppDef', 'oppRoleId pos roleName head frame spine heads frames spines rankLv pLv title lv defCe heroes')
.populate('role')
.lean();
return defense;
@@ -163,15 +108,15 @@ export default class PvpDefense extends BaseModel {
const result: PvpDefenseType = await PvpDefenseModel.findOne({ roleId })
.populate('role', 'head frame spine topLineupCe roleId roleName lv globalCeAttr')
.populate('heroes.hero')
.populate('oppPlayers.oppDef', 'oppRoleId pos roleName head frame spine heads frames spines rankLv title lv pLv defCe heroes').lean({ getters: true, virtuals: true });
.populate('oppPlayer.oppDef', 'oppRoleId pos roleName head frame spine heads frames spines rankLv title lv pLv defCe heroes').lean({ getters: true, virtuals: true });
return result;
}
public static async findByTeamLv(seasonNum: number, min: number, max: number) {
const result: PvpDefenseType[] = await PvpDefenseModel.find({ seasonNum, pLv: { $gte: min, $lte: max } })
const result: PvpDefenseType[] = await PvpDefenseModel.find({ seasonNum, 'defense.pLv': { $gte: min, $lte: max } })
.populate('role', 'head frame spine heads frames spines topLineupCe roleId roleName lv globalCeAttr')
.populate('heroes.hero')
.populate('oppPlayers.oppDef', 'oppRoleId pos roleName head frame spine heads frames spines rankLv pLv title lv defCe heroes')
.populate('oppPlayer.oppDef', 'oppRoleId pos roleName head frame spine heads frames spines rankLv pLv title lv defCe heroes')
.lean({ getters: true, virtuals: true });
return result;
}
@@ -180,7 +125,7 @@ export default class PvpDefense extends BaseModel {
delete update._id;
let result: PvpDefenseType = await PvpDefenseModel.findOneAndUpdate({roleId}, {$set:update}, {new: true})
.populate('role', 'head frame spine heads frames spines topLineupCe roleId roleName lv')
.populate('oppPlayers.oppDef', 'oppRoleId pos roleName head frame spine heads frames spines rankLv pLv title lv defCe heroes').lean({ getters: true, virtuals: true });
.populate('oppPlayer.oppDef', 'oppRoleId pos roleName head frame spine heads frames spines rankLv pLv title lv defCe heroes').lean({ getters: true, virtuals: true });
return result;
}
public static async updateInfo(roleId: string, update: pvpUpdateInter, lean = true) {
@@ -201,6 +146,11 @@ export default class PvpDefense extends BaseModel {
return ranks;
}
public static async resetScores(roleId: string, newSeasonNum: number, newScore: number, newHeroScores: HeroScore[]) {
let result: PvpDefenseType = await PvpDefenseModel.findOneAndUpdate({roleId}, {$set: { seasonNum: newSeasonNum, score: newScore, heroScores: newHeroScores, challengeCnt: PVP.PVP_CHALLENGE_COUNTS, challengeRefTime: 0, winStreakNum: 0 }}, {new: true}).lean();
return result;
}
public static async deleteHero(roleId: string, hid: number) {
let result:PvpDefenseType = await PvpDefenseModel.findOneAndUpdate({roleId}, {$pull:{heroes: {actorId:hid}}}, {new: true}).lean();
return result;

View File

@@ -1,94 +1,54 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
class Reward {
@prop({ required: true })
id: number;
@prop({ required: true })
count: number;
}
import { Reward, HeroReward, HeroScore } from '../domain/battleField/pvp';
class HeroReward {
@index({ roleId: 1, seasonNum: 1 })
export default class PvpSeasonResult extends BaseModel {
@prop({ required: true })
hid: number;
@prop({ required: true })
id: number;
@prop({ required: true })
count: number;
}
export class HeroScores {
@prop({ required: true })
hid: number;
@prop({ required: true })
score: number;
@prop({ required: true })
goodId: number;
@prop({ required: true })
count: number;
}
export interface pvpUpdate {
rankGoods?:Array<Reward>;
oldSeasonData?: SeasonData;
show?: boolean;
heroGoods?:Array<HeroReward>;
}
class SeasonData {
@prop({ required: true })
score: number;
@prop({ required: true })
pLv: number;
@prop({ required: true, type:HeroScores, default:[] })
heroScores: HeroScores[];
roleId: string;
@prop({ required: true })
seasonNum: number;
@prop({ required: true })
challengeCnt: number;
@prop({ required: true })
challengeRefTime: number;
@prop({ required: true })
seasonEndTime: number;
@prop({ required: true })
score: number;
@prop({ required: true, type: () => HeroScore, default:[] })
heroScores: HeroScore[];
@prop({ required: true })
rankLv: number;
@prop({ required: true })
refOppCnt:number;
}
@index({ roleId: 1 })
export default class PvpSeasonResult extends BaseModel {
@prop({ required: true })
roleId: string;
@prop({ required: true, type: SeasonData, _id: false})
oldSeasonData: SeasonData;
@prop({ required: true, default: true })
show: boolean;
@prop({ required: true, type: HeroReward, default: [], _id: false})
heroGoods: Array<HeroReward>;
@prop({ required: true, type: () => HeroReward, default: [], _id: false})
heroGoods: HeroReward[];
@prop({ required: true, type: Reward, default: [], _id: false})
rankGoods: Array<Reward>;
rankGoods: Reward[];
public static async updatePvpSeasonResult(roleId: string, update: pvpUpdate , lean = true) {
let result: PvpSeasonResultType = await PvpSeasonResultModel.findOneAndUpdate({roleId}, {$set: update}, {upsert: true, new: true}).lean(lean);
@prop({ required: true })
newScore: number;
@prop({ required: true, type: () => HeroScore, default:[] })
newHeroScores: HeroScore[];
public static async updatePvpSeasonResult(roleId: string, seasonNum: number, update: PvpSeasonResultUpdate , lean = true) {
let result: PvpSeasonResultType = await PvpSeasonResultModel.findOneAndUpdate({roleId, seasonNum}, {$set: update}, {upsert: true, new: true}).lean(lean);
return result;
}
public static async getPvpSeasonResult(roleId: string, lean = true) {
let result: PvpSeasonResultType = await PvpSeasonResultModel.findOne({roleId}).lean(lean);
public static async getPvpSeasonResult(roleId: string, seasonNum: number, lean = true) {
let result: PvpSeasonResultType = await PvpSeasonResultModel.findOne({ roleId, seasonNum }).lean(lean);
return result;
}
}
export const PvpSeasonResultModel = getModelForClass(PvpSeasonResult);
export interface PvpSeasonResultType extends Pick<DocumentType<PvpSeasonResult>, keyof PvpSeasonResult> { };
export interface PvpSeasonResultType extends Pick<DocumentType<PvpSeasonResult>, keyof PvpSeasonResult> { };
export type PvpSeasonResultUpdate = Partial<PvpSeasonResultType>;

View File

@@ -732,6 +732,14 @@ export default class Role extends BaseModel {
const role: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $addToSet: { guide: { $each: ids } } }, { new: true }).lean();
return role;
}
// 用于远征匹配
public static async findByCeScale(min: number, max: number) {
const result: RoleType[] = await RoleModel.find({ topLineupCe: { $lte: max, $gte: min } })
.populate('topLineup.hero')
.sort({ updatedAt: -1 }).limit(100).lean({ getters: true, virtuals: true });
return result;
}
}
export const RoleModel = getModelForClass(Role);

View File

@@ -6,17 +6,23 @@ import { COUNTER } from '../consts';
@index({ id: 1 })
@index({ seasonNum: 1 })
export default class PVPConfig extends BaseModel {
@prop({ required: true, default: 1 })
id: number;
@prop({ required: true })
warId: number; // 地图
@prop({ required: true, default: 1 })
seasonNum: number; // 赛季
@prop({ required: true })
seasonEndTime: number; //赛季结束的时间
@prop({ required: false })
settleGuildWeeklyTime: number;
@prop({ required: true })
seasonStartTime: number; // 赛季开始时间
@prop({ required: true })
seasonRewardTime: number; // 结算奖励时间
@prop({ required: true })
seasonEndTime: number; // 赛季结束的时间
@prop({ required: true })
hasSettleReward: boolean; // 赛季结束的时间
public static async findCurPVPConfig() {
let seasonNum = await CounterModel.getCounter(COUNTER.PVP_SEASON_NUM);
const result: PVPConfigType = await PVPConfigModel.findOne({ seasonNum }).lean(true);
@@ -28,13 +34,19 @@ export default class PVPConfig extends BaseModel {
return result;
}
public static async createPVPConfig(seasonNum: number, seasonEndTime: number, warId: number) {
const result: PVPConfigType = await PVPConfigModel.findOneAndUpdate({ seasonNum }, { warId, seasonEndTime }, { upsert: true, new: true }).lean(true);
public static async createPVPConfig(seasonNum: number, seasonStartTime: number, seasonRewardTime: number, seasonEndTime: number) {
const result: PVPConfigType = await PVPConfigModel.findOneAndUpdate({ seasonNum }, { seasonStartTime, seasonRewardTime, seasonEndTime, hasSettleReward: false }, { upsert: true, new: true }).lean(true);
return result;
}
public static async updatePVPConfig(seasonNum: number, update: { warId?: number, settleGuildWeeklyTime?: number }) {
const result: PVPConfigType = await PVPConfigModel.findOneAndUpdate({ seasonNum }, update, { new: true }).lean(true);
public static async setReward(seasonNum: number) {
const result: PVPConfigType = await PVPConfigModel.findOneAndUpdate({ seasonNum }, { hasSettleReward: true }, { new: true }).lean(true);
return result;
}
public static async setCurPvpConfig(update: PVPConfigUpdate) {
let seasonNum = await CounterModel.getCounter(COUNTER.PVP_SEASON_NUM);
const result: PVPConfigType = await PVPConfigModel.findOneAndUpdate({ seasonNum }, update).lean(true);
return result;
}
}
@@ -43,4 +55,5 @@ export const PVPConfigModel = getModelForClass(PVPConfig);
export interface PVPConfigType extends Pick<DocumentType<PVPConfig>, keyof PVPConfig> {
id: number;
};
};
export type PVPConfigUpdate = Partial<PVPConfigType>; // 将所有字段变成可选项

View File

@@ -0,0 +1,214 @@
import { prop, Ref, mongoose } from '@typegoose/typegoose';
import Hero, { } from '../../db/Hero';
import { PvpDefenseType } from '../../db/PvpDefense';
import PvpHistoryOpp from '../../db/PvpHistoryOpp';
import { PvpSeasonResultType } from '../../db/PvpSeasonResult';
import { RewardInter } from '../../pubUtils/interface';
// 防守阵容武将
export class DefenseHero {
@prop({ required: true })
actorId: number; // 武将id
@prop({ required: true })
ai: number; // ai逻辑1-进攻型 2-防守型
@prop({ required: true })
dataId: number;
@prop({ required: true })
order: number;
@prop({ ref: 'Hero', type: mongoose.Schema.Types.ObjectId })
hero: Ref<Hero>;
}
// 防守阵容
export class Defense {
@prop({ required: true })
warId: number;
@prop({ required: true })
buff: number;
@prop({ required: true, type: DefenseHero, _id: false })
heroes: DefenseHero[];
@prop({ required: true })
score: number; // 防守阵容的总军功
@prop({ required: true })
pLv: number; // 防守阵容的等级
}
// 挑战阵容武将
export class AttackHero {
@prop({ required: true })
actorId: number; // 武将id
@prop({ required: true })
order: number;
}
// 挑战阵容
export class Attack {
@prop({ required: true, type: AttackHero, _id: false })
heroes: AttackHero[];
@prop({ required: true })
score: number; // 防守阵容的总军功
@prop({ required: true })
pLv: number; // 防守阵容的等级
}
// 两个阵容中的武将的分别的战力
export class LineupCe {
@prop({ required: true })
hid: number; // 武将id
@prop({ required: true })
ce: number; // 战力
}
export class OppPlayer {
@prop({ required: true })
roleId: string;
@prop({ ref: 'PvpHistoryOpp', type: mongoose.Schema.Types.ObjectId })
oppDef: Ref<PvpHistoryOpp>;
@prop({ required: true })
pos: number;
@prop({ required: true })
isRobot: boolean;
}
export class HeroScore {
@prop({ required: true })
hid: number;
@prop({ required: true })
score: number;
}
export class Reward {
@prop({ required: true })
id: number;
@prop({ required: true })
count: number;
}
export class HeroReward {
@prop({ required: true })
hid: number;
@prop({ required: true })
id: number;
@prop({ required: true })
count: number;
}
export class OppPlayerReturn {
pos: number;
roleId: string;
roleName: string;
head: number;
frame: number;
spine: number;
lv: number;
pLv: number;
defCe: number;
rankLv: number;
addScore: number;
plusScore: number;
}
// 防守阵容武将
export class DefenseHeroReturn {
actorId: number; // 武将id
ai: number; // ai逻辑1-进攻型 2-防守型
dataId: number;
order: number;
}
export class DefenseLineupReturn {
warId: number;
buff: number;
heroes: DefenseHeroReturn[];
score: number;
pLv: number;
ce: number;
}
export class AttackLineupReturn {
warId: number;
buff: number;
heroes: AttackHero[];
score: number;
pLv: number;
ce: number;
}
export class heroScoreReturn extends HeroScore {
isDefense: boolean;
}
export class SeasonDataReturn {
score: number;
heroScores: HeroScore[];
seasonNum: number;
seasonEndTime: number;
rankLv: number;
constructor(pvpSeasonResult: PvpSeasonResultType) {
this.score = pvpSeasonResult.score;
this.heroScores = pvpSeasonResult.heroScores;
this.seasonNum = pvpSeasonResult.seasonNum;
this.seasonEndTime = pvpSeasonResult.seasonEndTime;
this.rankLv = pvpSeasonResult.rankLv;
}
}
export class PvpSeasonResultRecord {
oldSeasonData: SeasonDataReturn;
heroGoods: HeroReward[];
rankGoods: RewardInter[];
constructor(pvpSeasonResult: PvpSeasonResultType) {
this.oldSeasonData = new SeasonDataReturn(pvpSeasonResult);
this.heroGoods = pvpSeasonResult.heroGoods;
this.rankGoods = pvpSeasonResult.rankGoods;
}
}
export class PvpDataReturn {
seasonNum: number;
seasonEndTime: number;
myRank: number = 0;
oppPlayers: OppPlayerReturn[] = [];
defense: DefenseLineupReturn = null;
attack: AttackLineupReturn = null;
score: number = 0;
winStreakNum: number = 0;
refOppCnt: number;
setAttackCnt: number;
challengeCnt: number;
challengeRefTime: number;
receiveBox: number[] = [];
hisScore: number = 0;
heroScores: heroScoreReturn[] = [];
isFirstEntry: boolean = false;
resultRecord: PvpSeasonResultRecord;
constructor(pvpDefense: PvpDefenseType) {
this.score = pvpDefense.score;
this.winStreakNum = pvpDefense.winStreakNum;
this.receiveBox = pvpDefense.receivedBox;
this.hisScore = pvpDefense.hisScore;
// this.oppPlayers
// this.heroScores
}
setOppPlayers(oppPlayers: OppPlayerReturn[]) {
this.oppPlayers = oppPlayers;
}
setMyRank(rankLv: number) {
this.myRank = rankLv;
}
setPvpConfig(seasonNum: number, seasonEndTime: number) {
this.seasonNum = seasonNum;
this.seasonEndTime = seasonEndTime;
}
setPvpSeasonResult(pvpSeasonResult: PvpSeasonResultType) {
this.resultRecord = new PvpSeasonResultRecord(pvpSeasonResult);
}
}

View File

@@ -41,8 +41,8 @@ export class PvpHeroInfo {
this.quality = hero.quality;
}
setRobotInfo(warjson: DicWarJson, lv: number, initialStar: number, quality: number) {
this.actorId = warjson.actorId;
setRobotInfo(warjson: DicWarJson, actorId: number, lv: number, initialStar: number, quality: number) {
this.actorId = actorId;
this.skinId = warjson.actorId;
this.actorName = warjson.actorName;
this.star = initialStar;

View File

@@ -1,4 +1,4 @@
import { HeroScores } from "../../db/PvpHistoryOpp";
import { HeroScore } from "../../domain/battleField/pvp";
export class TaskParam {
star?: number;
@@ -17,7 +17,7 @@ export class TaskParam {
dailyType?: number;
point?: number;
gid?: number;
heroScores?: HeroScores[];
heroScores?: HeroScore[];
rankLv?: number;
title?: number;
job?: number;

View File

@@ -38,7 +38,6 @@ import { dicHeroScroll, preHeroScroll, loadHeroScroll } from './dictionary/DicHe
import { dicPvpOpponent, loadPvpOpponent } from './dictionary/DicPvpOpponent';
import { dicPvpTeamLevel, loadPvpTeamLevel } from './dictionary/DicPvpTeamLevel';
import { dicPvpRefreshConsume, maxPvpRefreshCnt, loadPvpRefreshConsume } from './dictionary/DicPvpRefreshConsume';
import { dicGkPvp, dicGkPvps, loadGkPvp } from './dictionary/DicGkPvp';
import { dicHeroRewads, loadPvpHeroReward } from './dictionary/DicPvpHeroReward';
import { dicRankRewads, dicRankMax, loadPvpRankReward } from './dictionary/DicPvpRankReward';
import { dicPvpBoxs, loadPvpBox } from './dictionary/DicPvpBox';
@@ -153,8 +152,6 @@ export const gameData = {
pvpWar: dicWarPvp,
pvpRefreshConsume: dicPvpRefreshConsume,
maxPvpRefreshCnt: maxPvpRefreshCnt,
pvpGk: dicGkPvp,
pvpGks: dicGkPvps,
pvpHeroRewards: dicHeroRewads,
pvpRankRewards: dicRankRewads,
pvpBoxs: dicPvpBoxs,
@@ -450,21 +447,22 @@ export function getPLvByScore(score: number) {
return lv;
}
export function getPvpGkByWarId(warId: number) {
return gameData.pvpGk.get(warId);
export function getPvpHeroRewardsByScore(score: number) {
for (let item of gameData.pvpHeroRewards) {
if ((item.max >= score || item.max == -1) && score >= item.min) {
return item;
}
}
return null
}
export function getPvpGkWarIds() {
let warIds = gameData.pvpGks;
return warIds;
}
export function getPvpHeroRewards() {
return gameData.pvpHeroRewards;
}
export function getPvpRankRewards() {
return gameData.pvpRankRewards;
export function getPvpRankRewardsByRank(rankLv: number) {
for (let item of gameData.pvpRankRewards) {
if ((item.max >= rankLv || item.max == -1) && rankLv >= item.min) {
return item;
}
}
return gameData.pvpRankMax.max;
}
export function getPvpBoxs() {
@@ -876,7 +874,6 @@ function loadDatas() {
loadPvpOpponent();
loadPvpTeamLevel();
loadPvpRefreshConsume();
loadGkPvp();
loadPvpHeroReward();
loadPvpRankReward();
loadPvpBox();

View File

@@ -1,23 +0,0 @@
import { readFileAndParse } from '../util'
import { FILENAME } from '../../consts'
export interface DicGkPvp {
readonly war_id: number;
readonly dispatchJsonId: number;
readonly bg_img_id: number;
readonly warType: number;
}
export const dicGkPvp = new Map<number, DicGkPvp>();
export const dicGkPvps = new Array<number>();
export function loadGkPvp() {
dicGkPvp.clear();
dicGkPvps.splice(0, dicGkPvps.length);
let arr = readFileAndParse(FILENAME.DIC_GK_PVP);
arr.forEach(o => {
dicGkPvp.set(o.war_id, o);
dicGkPvps.push(o.war_id);
});
arr = undefined;
}

View File

@@ -1,5 +1,5 @@
// 关卡表
import {decodeArrayListStr, readWarJsonFileAndParse} from '../util'
import {decodeArrayListStr, parseNumberList, readWarJsonFileAndParse} from '../util'
export interface DicWarJson {
@@ -47,6 +47,8 @@ export interface DicWarJson {
readonly callSkillData: string;
// 敌军数量
readonly enemyCount: number;
// pvp中随机敌军
readonly randomEnemy: number[];
}
export const dicWarJson = new Map<number, Array<DicWarJson>>();
@@ -63,6 +65,7 @@ export function loadWarJson() {
if(o.relation == 2) enemyCount++;
});
arr.forEach(o => {
o.randomEnemy = parseNumberList(o.randomEnemy);
o.enemyCount = enemyCount;
warjson.push(o);
});

View File

@@ -29,20 +29,6 @@ export interface SclResultInter {
position: SclPosInter[]
}
// pvp对手返回
export interface oppPlayersInter {
pos: number; // 对手位置
roleId: string; // 对手玩家id
roleName: string; // 对手玩家名
head: number; // 头像
frame: number; // 相框
spine: number; // 形象
pLv: number; // 对手队伍等级
defCe: number; // 防守阵容战力
addScore: number; // 战胜后可获军功
plusScore: number; // 连胜加成军功
rankLv: number;
}
export interface pvpEndParamInter {
hid: number;

View File

@@ -0,0 +1,44 @@
[
{
"id": 1,
"teamLineupMin": 0,
"teamLineupMax": 500,
"value": 10000,
"enemyLv": 10
},
{
"id": 2,
"teamLineupMin": 501,
"teamLineupMax": 1020,
"value": 15000,
"enemyLv": 15
},
{
"id": 3,
"teamLineupMin": 1021,
"teamLineupMax": 1560,
"value": 20000,
"enemyLv": 20
},
{
"id": 4,
"teamLineupMin": 1561,
"teamLineupMax": 2120,
"value": 25000,
"enemyLv": 25
},
{
"id": 5,
"teamLineupMin": 2121,
"teamLineupMax": 2700,
"value": 30000,
"enemyLv": 30
},
{
"id": 6,
"teamLineupMin": 2701,
"teamLineupMax": 3000,
"value": 35000,
"enemyLv": 35
}
]

View File

@@ -17,7 +17,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4501,
@@ -37,7 +38,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4501,
@@ -57,7 +59,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4501,
@@ -77,7 +80,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4501,
@@ -97,7 +101,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4501,
@@ -117,7 +122,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4501,
@@ -137,7 +143,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4501,
@@ -157,7 +164,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4501,
@@ -177,12 +185,13 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4501,
"actorName": "曹操",
"actorId": 301,
"actorName": "敌军",
"actorId": 0,
"dataId": 2001,
"relation": 2,
"outIndex": 0,
@@ -193,16 +202,17 @@
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&3000|2&600|4&250|5&250|9&0|10&25000|11&20000|12&0|13&10000|14&10000|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "301&306&307"
},
{
"warId": 4501,
"actorName": "郭嘉",
"actorId": 305,
"actorName": "敌军",
"actorId": 0,
"dataId": 2002,
"relation": 2,
"outIndex": 1,
@@ -213,16 +223,17 @@
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&5000|2&400|4&600|5&600|9&0|10&10000|11&30000|12&10000|13&0|14&20000|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "305&312"
},
{
"warId": 4501,
"actorName": "张飞",
"actorId": 317,
"actorName": "敌军",
"actorId": 0,
"dataId": 2003,
"relation": 2,
"outIndex": 2,
@@ -233,16 +244,17 @@
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&2500|2&700|4&200|5&200|9&0|10&20000|11&10000|12&0|13&10000|14&0|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "317&314&318&320&321"
},
{
"warId": 4501,
"actorName": "黄忠",
"actorId": 321,
"actorName": "敌军",
"actorId": 0,
"dataId": 2004,
"relation": 2,
"outIndex": 3,
@@ -253,16 +265,17 @@
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&4000|2&500|4&300|5&300|9&10000|10&0|11&0|12&0|13&5000|14&0|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "321&333&334&335"
},
{
"warId": 4501,
"actorName": "华佗",
"actorId": 346,
"actorName": "敌军",
"actorId": 0,
"dataId": 2005,
"relation": 2,
"outIndex": 4,
@@ -273,11 +286,12 @@
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&3500|2&500|4&400|5&400|9&0|10&0|11&0|12&0|13&0|14&10000|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "346&"
},
{
"warId": 4501,
@@ -297,7 +311,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4501,
@@ -317,7 +332,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4501,
@@ -337,7 +353,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "340&341&342"
},
{
"warId": 4501,
@@ -357,6 +374,7 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
}
]

View File

@@ -7,9 +7,9 @@
"relation": 0,
"outIndex": 0,
"dirction": 2,
"x": 6,
"y": 8,
"var": 0,
"x": 4,
"y": 6,
"var": 501,
"lv": 0,
"hide": 0,
"initial_ai": 1,
@@ -17,7 +17,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4502,
@@ -27,9 +28,9 @@
"relation": 0,
"outIndex": 1,
"dirction": 2,
"x": 7,
"y": 8,
"var": 1,
"x": 5,
"y": 6,
"var": 502,
"lv": 0,
"hide": 0,
"initial_ai": 1,
@@ -37,7 +38,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4502,
@@ -47,9 +49,9 @@
"relation": 0,
"outIndex": 2,
"dirction": 2,
"x": 7,
"y": 7,
"var": 2,
"x": 5,
"y": 5,
"var": 503,
"lv": 0,
"hide": 0,
"initial_ai": 1,
@@ -57,7 +59,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4502,
@@ -67,9 +70,9 @@
"relation": 0,
"outIndex": 3,
"dirction": 2,
"x": 6,
"y": 6,
"var": 3,
"x": 4,
"y": 4,
"var": 504,
"lv": 0,
"hide": 0,
"initial_ai": 1,
@@ -77,7 +80,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4502,
@@ -87,9 +91,9 @@
"relation": 0,
"outIndex": 4,
"dirction": 2,
"x": 7,
"y": 6,
"var": 4,
"x": 5,
"y": 4,
"var": 505,
"lv": 0,
"hide": 0,
"initial_ai": 1,
@@ -97,7 +101,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4502,
@@ -107,9 +112,9 @@
"relation": 0,
"outIndex": 5,
"dirction": 2,
"x": 5,
"y": 8,
"var": 5,
"x": 3,
"y": 6,
"var": 506,
"lv": 0,
"hide": 0,
"initial_ai": 1,
@@ -117,7 +122,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4502,
@@ -127,9 +133,9 @@
"relation": 0,
"outIndex": 6,
"dirction": 2,
"x": 5,
"y": 7,
"var": 6,
"x": 3,
"y": 5,
"var": 507,
"lv": 0,
"hide": 0,
"initial_ai": 1,
@@ -137,7 +143,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4502,
@@ -147,9 +154,9 @@
"relation": 0,
"outIndex": 7,
"dirction": 2,
"x": 6,
"y": 7,
"var": 7,
"x": 4,
"y": 5,
"var": 508,
"lv": 0,
"hide": 0,
"initial_ai": 1,
@@ -157,7 +164,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4502,
@@ -167,9 +175,9 @@
"relation": 0,
"outIndex": 8,
"dirction": 2,
"x": 5,
"y": 6,
"var": 8,
"x": 3,
"y": 4,
"var": 509,
"lv": 0,
"hide": 0,
"initial_ai": 1,
@@ -177,107 +185,113 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4502,
"actorName": "曹操",
"actorId": 301,
"actorName": "敌军",
"actorId": 0,
"dataId": 2001,
"relation": 2,
"outIndex": 0,
"dirction": 1,
"x": 13,
"y": 8,
"var": 2001,
"x": 12,
"y": 6,
"var": 1501,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&3000|2&600|4&250|5&250|9&0|10&25000|11&20000|12&0|13&10000|14&10000|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4502,
"actorName": "郭嘉",
"actorId": 305,
"actorName": "敌军",
"actorId": 0,
"dataId": 2002,
"relation": 2,
"outIndex": 1,
"dirction": 1,
"x": 14,
"y": 8,
"var": 2002,
"x": 13,
"y": 6,
"var": 1502,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&5000|2&400|4&600|5&600|9&0|10&10000|11&30000|12&10000|13&0|14&20000|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "305&312"
},
{
"warId": 4502,
"actorName": "张飞",
"actorId": 317,
"actorName": "敌军",
"actorId": 0,
"dataId": 2003,
"relation": 2,
"outIndex": 2,
"dirction": 1,
"x": 13,
"y": 7,
"var": 2003,
"y": 5,
"var": 1503,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&2500|2&700|4&200|5&200|9&0|10&20000|11&10000|12&0|13&10000|14&0|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "317&314&318&320&321"
},
{
"warId": 4502,
"actorName": "黄忠",
"actorId": 321,
"actorName": "敌军",
"actorId": 0,
"dataId": 2004,
"relation": 2,
"outIndex": 3,
"dirction": 1,
"x": 12,
"y": 6,
"var": 2004,
"x": 11,
"y": 4,
"var": 1504,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&4000|2&500|4&300|5&300|9&10000|10&0|11&0|12&0|13&5000|14&0|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "321&333&334&335"
},
{
"warId": 4502,
"actorName": "华佗",
"actorId": 346,
"actorName": "敌军",
"actorId": 0,
"dataId": 2005,
"relation": 2,
"outIndex": 4,
"dirction": 1,
"x": 13,
"y": 6,
"var": 2005,
"x": 12,
"y": 4,
"var": 1505,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&3500|2&500|4&400|5&400|9&0|10&0|11&0|12&0|13&0|14&10000|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4502,
@@ -287,9 +301,9 @@
"relation": 2,
"outIndex": 5,
"dirction": 1,
"x": 12,
"y": 8,
"var": 2006,
"x": 13,
"y": 4,
"var": 1506,
"lv": 0,
"hide": 0,
"initial_ai": 1,
@@ -297,7 +311,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "321&333&334&335"
},
{
"warId": 4502,
@@ -307,9 +322,9 @@
"relation": 2,
"outIndex": 6,
"dirction": 1,
"x": 12,
"y": 7,
"var": 2007,
"x": 11,
"y": 6,
"var": 1507,
"lv": 0,
"hide": 0,
"initial_ai": 1,
@@ -317,7 +332,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4502,
@@ -327,9 +343,9 @@
"relation": 2,
"outIndex": 7,
"dirction": 1,
"x": 14,
"y": 7,
"var": 2008,
"x": 11,
"y": 5,
"var": 1508,
"lv": 0,
"hide": 0,
"initial_ai": 1,
@@ -337,7 +353,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "340&341&342"
},
{
"warId": 4502,
@@ -347,9 +364,9 @@
"relation": 2,
"outIndex": 8,
"dirction": 1,
"x": 14,
"y": 6,
"var": 2009,
"x": 12,
"y": 5,
"var": 1509,
"lv": 0,
"hide": 0,
"initial_ai": 1,
@@ -357,6 +374,7 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "301&306&307"
}
]

View File

@@ -7,8 +7,8 @@
"relation": 0,
"outIndex": 0,
"dirction": 2,
"x": 2,
"y": 6,
"x": 6,
"y": 8,
"var": 0,
"lv": 0,
"hide": 0,
@@ -17,7 +17,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4503,
@@ -27,8 +28,8 @@
"relation": 0,
"outIndex": 1,
"dirction": 2,
"x": 3,
"y": 6,
"x": 7,
"y": 8,
"var": 1,
"lv": 0,
"hide": 0,
@@ -37,7 +38,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4503,
@@ -47,8 +49,8 @@
"relation": 0,
"outIndex": 2,
"dirction": 2,
"x": 4,
"y": 6,
"x": 7,
"y": 7,
"var": 2,
"lv": 0,
"hide": 0,
@@ -57,7 +59,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4503,
@@ -67,8 +70,8 @@
"relation": 0,
"outIndex": 3,
"dirction": 2,
"x": 2,
"y": 5,
"x": 6,
"y": 6,
"var": 3,
"lv": 0,
"hide": 0,
@@ -77,7 +80,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4503,
@@ -87,8 +91,8 @@
"relation": 0,
"outIndex": 4,
"dirction": 2,
"x": 3,
"y": 5,
"x": 7,
"y": 6,
"var": 4,
"lv": 0,
"hide": 0,
@@ -97,7 +101,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4503,
@@ -107,8 +112,8 @@
"relation": 0,
"outIndex": 5,
"dirction": 2,
"x": 4,
"y": 5,
"x": 5,
"y": 8,
"var": 5,
"lv": 0,
"hide": 0,
@@ -117,7 +122,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4503,
@@ -127,8 +133,8 @@
"relation": 0,
"outIndex": 6,
"dirction": 2,
"x": 2,
"y": 4,
"x": 5,
"y": 7,
"var": 6,
"lv": 0,
"hide": 0,
@@ -137,7 +143,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4503,
@@ -147,8 +154,8 @@
"relation": 0,
"outIndex": 7,
"dirction": 2,
"x": 3,
"y": 4,
"x": 6,
"y": 7,
"var": 7,
"lv": 0,
"hide": 0,
@@ -157,7 +164,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4503,
@@ -167,8 +175,8 @@
"relation": 0,
"outIndex": 8,
"dirction": 2,
"x": 4,
"y": 4,
"x": 5,
"y": 6,
"var": 8,
"lv": 0,
"hide": 0,
@@ -177,107 +185,113 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4503,
"actorName": "曹操",
"actorId": 301,
"actorName": "敌军",
"actorId": 0,
"dataId": 2001,
"relation": 2,
"outIndex": 0,
"dirction": 1,
"x": 11,
"y": 6,
"x": 13,
"y": 8,
"var": 2001,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&3000|2&600|4&250|5&250|9&0|10&25000|11&20000|12&0|13&10000|14&10000|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "301&306&307"
},
{
"warId": 4503,
"actorName": "郭嘉",
"actorId": 305,
"actorName": "敌军",
"actorId": 0,
"dataId": 2002,
"relation": 2,
"outIndex": 1,
"dirction": 1,
"x": 12,
"y": 6,
"x": 14,
"y": 8,
"var": 2002,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&5000|2&400|4&600|5&600|9&0|10&10000|11&30000|12&10000|13&0|14&20000|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "305&312"
},
{
"warId": 4503,
"actorName": "张飞",
"actorId": 317,
"actorName": "敌军",
"actorId": 0,
"dataId": 2003,
"relation": 2,
"outIndex": 2,
"dirction": 1,
"x": 13,
"y": 6,
"y": 7,
"var": 2003,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&2500|2&700|4&200|5&200|9&0|10&20000|11&10000|12&0|13&10000|14&0|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "317&314&318&320&321"
},
{
"warId": 4503,
"actorName": "黄忠",
"actorId": 321,
"actorName": "敌军",
"actorId": 0,
"dataId": 2004,
"relation": 2,
"outIndex": 3,
"dirction": 1,
"x": 11,
"y": 5,
"x": 12,
"y": 6,
"var": 2004,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&4000|2&500|4&300|5&300|9&10000|10&0|11&0|12&0|13&5000|14&0|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "321&333&334&335"
},
{
"warId": 4503,
"actorName": "华佗",
"actorId": 346,
"actorName": "敌军",
"actorId": 0,
"dataId": 2005,
"relation": 2,
"outIndex": 4,
"dirction": 1,
"x": 12,
"y": 5,
"x": 13,
"y": 6,
"var": 2005,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&3500|2&500|4&400|5&400|9&0|10&0|11&0|12&0|13&0|14&10000|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "346&"
},
{
"warId": 4503,
@@ -287,8 +301,8 @@
"relation": 2,
"outIndex": 5,
"dirction": 1,
"x": 13,
"y": 5,
"x": 12,
"y": 8,
"var": 2006,
"lv": 0,
"hide": 0,
@@ -297,7 +311,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4503,
@@ -307,8 +322,8 @@
"relation": 2,
"outIndex": 6,
"dirction": 1,
"x": 11,
"y": 4,
"x": 12,
"y": 7,
"var": 2007,
"lv": 0,
"hide": 0,
@@ -317,7 +332,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4503,
@@ -327,8 +343,8 @@
"relation": 2,
"outIndex": 7,
"dirction": 1,
"x": 12,
"y": 4,
"x": 14,
"y": 7,
"var": 2008,
"lv": 0,
"hide": 0,
@@ -337,7 +353,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "340&341&342"
},
{
"warId": 4503,
@@ -347,8 +364,8 @@
"relation": 2,
"outIndex": 8,
"dirction": 1,
"x": 13,
"y": 4,
"x": 14,
"y": 6,
"var": 2009,
"lv": 0,
"hide": 0,
@@ -357,6 +374,7 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
}
]

View File

@@ -7,8 +7,8 @@
"relation": 0,
"outIndex": 0,
"dirction": 2,
"x": 4,
"y": 7,
"x": 6,
"y": 8,
"var": 0,
"lv": 0,
"hide": 0,
@@ -17,7 +17,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4504,
@@ -27,8 +28,8 @@
"relation": 0,
"outIndex": 1,
"dirction": 2,
"x": 5,
"y": 7,
"x": 7,
"y": 8,
"var": 1,
"lv": 0,
"hide": 0,
@@ -37,7 +38,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4504,
@@ -47,8 +49,8 @@
"relation": 0,
"outIndex": 2,
"dirction": 2,
"x": 5,
"y": 6,
"x": 7,
"y": 7,
"var": 2,
"lv": 0,
"hide": 0,
@@ -57,7 +59,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4504,
@@ -67,8 +70,8 @@
"relation": 0,
"outIndex": 3,
"dirction": 2,
"x": 4,
"y": 5,
"x": 6,
"y": 6,
"var": 3,
"lv": 0,
"hide": 0,
@@ -77,7 +80,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4504,
@@ -87,8 +91,8 @@
"relation": 0,
"outIndex": 4,
"dirction": 2,
"x": 5,
"y": 5,
"x": 7,
"y": 6,
"var": 4,
"lv": 0,
"hide": 0,
@@ -97,7 +101,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4504,
@@ -107,8 +112,8 @@
"relation": 0,
"outIndex": 5,
"dirction": 2,
"x": 3,
"y": 6,
"x": 5,
"y": 8,
"var": 5,
"lv": 0,
"hide": 0,
@@ -117,7 +122,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4504,
@@ -127,8 +133,8 @@
"relation": 0,
"outIndex": 6,
"dirction": 2,
"x": 4,
"y": 6,
"x": 5,
"y": 7,
"var": 6,
"lv": 0,
"hide": 0,
@@ -137,7 +143,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4504,
@@ -147,7 +154,7 @@
"relation": 0,
"outIndex": 7,
"dirction": 2,
"x": 3,
"x": 6,
"y": 7,
"var": 7,
"lv": 0,
@@ -157,7 +164,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4504,
@@ -167,8 +175,8 @@
"relation": 0,
"outIndex": 8,
"dirction": 2,
"x": 3,
"y": 5,
"x": 5,
"y": 6,
"var": 8,
"lv": 0,
"hide": 0,
@@ -177,107 +185,113 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4504,
"actorName": "曹操",
"actorId": 301,
"actorName": "敌军",
"actorId": 0,
"dataId": 2001,
"relation": 2,
"outIndex": 0,
"dirction": 1,
"x": 13,
"y": 7,
"y": 8,
"var": 2001,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&3000|2&600|4&250|5&250|9&0|10&25000|11&20000|12&0|13&10000|14&10000|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4504,
"actorName": "郭嘉",
"actorId": 305,
"actorName": "敌军",
"actorId": 0,
"dataId": 2002,
"relation": 2,
"outIndex": 1,
"dirction": 1,
"x": 14,
"y": 7,
"y": 8,
"var": 2002,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&5000|2&400|4&600|5&600|9&0|10&10000|11&30000|12&10000|13&0|14&20000|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "305&312"
},
{
"warId": 4504,
"actorName": "张飞",
"actorId": 317,
"actorName": "敌军",
"actorId": 0,
"dataId": 2003,
"relation": 2,
"outIndex": 2,
"dirction": 1,
"x": 14,
"y": 6,
"x": 13,
"y": 7,
"var": 2003,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&2500|2&700|4&200|5&200|9&0|10&20000|11&10000|12&0|13&10000|14&0|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "317&314&318&320&321"
},
{
"warId": 4504,
"actorName": "黄忠",
"actorId": 321,
"actorName": "敌军",
"actorId": 0,
"dataId": 2004,
"relation": 2,
"outIndex": 3,
"dirction": 1,
"x": 13,
"y": 5,
"x": 12,
"y": 6,
"var": 2004,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&4000|2&500|4&300|5&300|9&10000|10&0|11&0|12&0|13&5000|14&0|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "321&333&334&335"
},
{
"warId": 4504,
"actorName": "华佗",
"actorId": 346,
"actorName": "敌军",
"actorId": 0,
"dataId": 2005,
"relation": 2,
"outIndex": 4,
"dirction": 1,
"x": 12,
"y": 5,
"x": 13,
"y": 6,
"var": 2005,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&3500|2&500|4&400|5&400|9&0|10&0|11&0|12&0|13&0|14&10000|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4504,
@@ -288,7 +302,7 @@
"outIndex": 5,
"dirction": 1,
"x": 12,
"y": 7,
"y": 8,
"var": 2006,
"lv": 0,
"hide": 0,
@@ -297,7 +311,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "321&333&334&335"
},
{
"warId": 4504,
@@ -308,7 +323,7 @@
"outIndex": 6,
"dirction": 1,
"x": 12,
"y": 6,
"y": 7,
"var": 2007,
"lv": 0,
"hide": 0,
@@ -317,7 +332,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4504,
@@ -327,8 +343,8 @@
"relation": 2,
"outIndex": 7,
"dirction": 1,
"x": 13,
"y": 6,
"x": 14,
"y": 7,
"var": 2008,
"lv": 0,
"hide": 0,
@@ -337,7 +353,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "340&341&342"
},
{
"warId": 4504,
@@ -348,7 +365,7 @@
"outIndex": 8,
"dirction": 1,
"x": 14,
"y": 5,
"y": 6,
"var": 2009,
"lv": 0,
"hide": 0,
@@ -357,6 +374,7 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "301&306&307"
}
]

View File

@@ -7,7 +7,7 @@
"relation": 0,
"outIndex": 0,
"dirction": 2,
"x": 3,
"x": 2,
"y": 6,
"var": 0,
"lv": 0,
@@ -17,7 +17,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4505,
@@ -27,7 +28,7 @@
"relation": 0,
"outIndex": 1,
"dirction": 2,
"x": 4,
"x": 3,
"y": 6,
"var": 1,
"lv": 0,
@@ -37,7 +38,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4505,
@@ -48,7 +50,7 @@
"outIndex": 2,
"dirction": 2,
"x": 4,
"y": 5,
"y": 6,
"var": 2,
"lv": 0,
"hide": 0,
@@ -57,7 +59,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4505,
@@ -67,8 +70,8 @@
"relation": 0,
"outIndex": 3,
"dirction": 2,
"x": 3,
"y": 4,
"x": 2,
"y": 5,
"var": 3,
"lv": 0,
"hide": 0,
@@ -77,7 +80,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4505,
@@ -87,8 +91,8 @@
"relation": 0,
"outIndex": 4,
"dirction": 2,
"x": 4,
"y": 4,
"x": 3,
"y": 5,
"var": 4,
"lv": 0,
"hide": 0,
@@ -97,7 +101,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4505,
@@ -107,8 +112,8 @@
"relation": 0,
"outIndex": 5,
"dirction": 2,
"x": 2,
"y": 6,
"x": 4,
"y": 5,
"var": 5,
"lv": 0,
"hide": 0,
@@ -117,7 +122,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4505,
@@ -128,7 +134,7 @@
"outIndex": 6,
"dirction": 2,
"x": 2,
"y": 5,
"y": 4,
"var": 6,
"lv": 0,
"hide": 0,
@@ -137,7 +143,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4505,
@@ -148,7 +155,7 @@
"outIndex": 7,
"dirction": 2,
"x": 3,
"y": 5,
"y": 4,
"var": 7,
"lv": 0,
"hide": 0,
@@ -157,7 +164,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4505,
@@ -167,7 +175,7 @@
"relation": 0,
"outIndex": 8,
"dirction": 2,
"x": 2,
"x": 4,
"y": 4,
"var": 8,
"lv": 0,
@@ -177,107 +185,113 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4505,
"actorName": "曹操",
"actorId": 301,
"actorName": "敌军",
"actorId": 0,
"dataId": 2001,
"relation": 2,
"outIndex": 0,
"dirction": 1,
"x": 14,
"x": 11,
"y": 6,
"var": 2001,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&3000|2&600|4&250|5&250|9&0|10&25000|11&20000|12&0|13&10000|14&10000|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "301&306&307"
},
{
"warId": 4505,
"actorName": "郭嘉",
"actorId": 305,
"actorName": "敌军",
"actorId": 0,
"dataId": 2002,
"relation": 2,
"outIndex": 1,
"dirction": 1,
"x": 15,
"x": 12,
"y": 6,
"var": 2002,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&5000|2&400|4&600|5&600|9&0|10&10000|11&30000|12&10000|13&0|14&20000|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "305&312"
},
{
"warId": 4505,
"actorName": "张飞",
"actorId": 317,
"actorName": "敌军",
"actorId": 0,
"dataId": 2003,
"relation": 2,
"outIndex": 2,
"dirction": 1,
"x": 15,
"y": 5,
"x": 13,
"y": 6,
"var": 2003,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&2500|2&700|4&200|5&200|9&0|10&20000|11&10000|12&0|13&10000|14&0|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "317&314&318&320&321"
},
{
"warId": 4505,
"actorName": "黄忠",
"actorId": 321,
"actorName": "敌军",
"actorId": 0,
"dataId": 2004,
"relation": 2,
"outIndex": 3,
"dirction": 1,
"x": 14,
"y": 4,
"x": 11,
"y": 5,
"var": 2004,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&4000|2&500|4&300|5&300|9&10000|10&0|11&0|12&0|13&5000|14&0|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "321&333&334&335"
},
{
"warId": 4505,
"actorName": "华佗",
"actorId": 346,
"actorName": "敌军",
"actorId": 0,
"dataId": 2005,
"relation": 2,
"outIndex": 4,
"dirction": 1,
"x": 15,
"y": 4,
"x": 12,
"y": 5,
"var": 2005,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "1&3500|2&500|4&400|5&400|9&0|10&0|11&0|12&0|13&0|14&10000|18&0",
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "346&"
},
{
"warId": 4505,
@@ -288,7 +302,7 @@
"outIndex": 5,
"dirction": 1,
"x": 13,
"y": 6,
"y": 5,
"var": 2006,
"lv": 0,
"hide": 0,
@@ -297,7 +311,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4505,
@@ -307,8 +322,8 @@
"relation": 2,
"outIndex": 6,
"dirction": 1,
"x": 13,
"y": 5,
"x": 11,
"y": 4,
"var": 2007,
"lv": 0,
"hide": 0,
@@ -317,7 +332,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4505,
@@ -327,8 +343,8 @@
"relation": 2,
"outIndex": 7,
"dirction": 1,
"x": 14,
"y": 5,
"x": 12,
"y": 4,
"var": 2008,
"lv": 0,
"hide": 0,
@@ -337,7 +353,8 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "340&341&342"
},
{
"warId": 4505,
@@ -357,6 +374,7 @@
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0
"spine": 0,
"randomEnemy": "&"
}
]

View File

@@ -0,0 +1,380 @@
[
{
"warId": 4506,
"actorName": "我军",
"actorId": 0,
"dataId": 0,
"relation": 0,
"outIndex": 0,
"dirction": 2,
"x": 2,
"y": 6,
"var": 0,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4506,
"actorName": "我军",
"actorId": 0,
"dataId": 0,
"relation": 0,
"outIndex": 1,
"dirction": 2,
"x": 3,
"y": 6,
"var": 1,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4506,
"actorName": "我军",
"actorId": 0,
"dataId": 0,
"relation": 0,
"outIndex": 2,
"dirction": 2,
"x": 4,
"y": 6,
"var": 2,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4506,
"actorName": "我军",
"actorId": 0,
"dataId": 0,
"relation": 0,
"outIndex": 3,
"dirction": 2,
"x": 2,
"y": 5,
"var": 3,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4506,
"actorName": "我军",
"actorId": 0,
"dataId": 0,
"relation": 0,
"outIndex": 4,
"dirction": 2,
"x": 3,
"y": 5,
"var": 4,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4506,
"actorName": "我军",
"actorId": 0,
"dataId": 0,
"relation": 0,
"outIndex": 5,
"dirction": 2,
"x": 4,
"y": 5,
"var": 5,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4506,
"actorName": "我军",
"actorId": 0,
"dataId": 0,
"relation": 0,
"outIndex": 6,
"dirction": 2,
"x": 2,
"y": 4,
"var": 6,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4506,
"actorName": "我军",
"actorId": 0,
"dataId": 0,
"relation": 0,
"outIndex": 7,
"dirction": 2,
"x": 3,
"y": 4,
"var": 7,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4506,
"actorName": "我军",
"actorId": 0,
"dataId": 0,
"relation": 0,
"outIndex": 8,
"dirction": 2,
"x": 4,
"y": 4,
"var": 8,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4506,
"actorName": "敌军",
"actorId": 0,
"dataId": 2001,
"relation": 2,
"outIndex": 0,
"dirction": 1,
"x": 11,
"y": 6,
"var": 2001,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4506,
"actorName": "敌军",
"actorId": 0,
"dataId": 2002,
"relation": 2,
"outIndex": 1,
"dirction": 1,
"x": 12,
"y": 6,
"var": 2002,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0,
"randomEnemy": "305&312"
},
{
"warId": 4506,
"actorName": "敌军",
"actorId": 0,
"dataId": 2003,
"relation": 2,
"outIndex": 2,
"dirction": 1,
"x": 13,
"y": 6,
"var": 2003,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0,
"randomEnemy": "317&314&318&320&321"
},
{
"warId": 4506,
"actorName": "敌军",
"actorId": 0,
"dataId": 2004,
"relation": 2,
"outIndex": 3,
"dirction": 1,
"x": 11,
"y": 5,
"var": 2004,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0,
"randomEnemy": "321&333&334&335"
},
{
"warId": 4506,
"actorName": "敌军",
"actorId": 0,
"dataId": 2005,
"relation": 2,
"outIndex": 4,
"dirction": 1,
"x": 12,
"y": 5,
"var": 2005,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4506,
"actorName": "敌军",
"actorId": 0,
"dataId": 2006,
"relation": 2,
"outIndex": 5,
"dirction": 1,
"x": 13,
"y": 5,
"var": 2006,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0,
"randomEnemy": "321&333&334&335"
},
{
"warId": 4506,
"actorName": "敌军",
"actorId": 0,
"dataId": 2007,
"relation": 2,
"outIndex": 6,
"dirction": 1,
"x": 11,
"y": 4,
"var": 2007,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0,
"randomEnemy": "&"
},
{
"warId": 4506,
"actorName": "敌军",
"actorId": 0,
"dataId": 2008,
"relation": 2,
"outIndex": 7,
"dirction": 1,
"x": 12,
"y": 4,
"var": 2008,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0,
"randomEnemy": "340&341&342"
},
{
"warId": 4506,
"actorName": "敌军",
"actorId": 0,
"dataId": 2009,
"relation": 2,
"outIndex": 8,
"dirction": 1,
"x": 13,
"y": 4,
"var": 2009,
"lv": 0,
"hide": 0,
"initial_ai": 1,
"attribute": "&",
"skill": 0,
"seid": "&",
"star": 0,
"spine": 0,
"randomEnemy": "301&306&307"
}
]