feat(gvg): 征战中原锁定对手

This commit is contained in:
luying
2023-02-01 09:45:05 +08:00
parent 4035645772
commit b727249106
12 changed files with 635 additions and 36 deletions

View File

@@ -1,12 +1,17 @@
import { Application, BackendSession, ChannelService, HandlerService } from "pinus";
import { GVG_PERIOD, STATUS } from "../../../consts";
import { GVG_ITEM, GVG_PERIOD, ITEM_CHANGE_REASON, STATUS, VESTIGE_OPP_STATUS } from "../../../consts";
import { GVGLeagueModel } from "../../../db/GVGLeague";
import { GVGUserItemModel } from "../../../db/GVGUserItem";
import { GVGVestigeLockModel } from "../../../db/GVGVestigeLock";
import { GVGVestigeRankModel } from "../../../db/GVGVestigeRank";
import { GVGVestigeRecModel } from "../../../db/GVGVestigeRec";
import { HeroModel } from "../../../db/Hero";
import { RoleModel } from "../../../db/Role";
import { GVGVestigeOppLineup } from "../../../domain/gvgField/returnData";
import { gameData } from "../../../pubUtils/data";
import { resResult } from "../../../pubUtils/util";
import { checkVestige, getOppPlayerByRanks, refreshVestigeOppRanks } from "../../../services/gvg/gvgFightService";
import { checkVestige, checkVestigeOppStatus, checkVestigeRank, generateAttackInfo, generateDefenseInfo, getOppDetailData, getOppPlayerByRanks, getVestigeUsedHeroes, isRobot, refreshVestigeOppRanks } from "../../../services/gvg/gvgFightService";
import { addGVGReward, handleGVGCost } from "../../../services/gvg/gvgItemService";
import { getGroupIdOfServer, getGVGPeriodData } from "../../../services/gvg/gvgService";
import { getAllServerName } from "../../../services/redisService";
@@ -42,7 +47,7 @@ export class GVGProduceHandler {
let dicRankMap = gameData.gvgVestige.get(vestigeId);
if(!dicRankMap) return resResult(STATUS.DIC_DATA_NOT_FOUND);
let myVestigateRank = await GVGVestigeRankModel.findRankByRole(vestigeId, roleId); // 我在这个遗迹的排名
let myVestigateRank = await GVGVestigeRankModel.findByRole(vestigeId, roleId); // 我在这个遗迹的排名
if(!myVestigateRank) {
let role = await RoleModel.findByRoleId(roleId, 'roleId');
let oppRanks = refreshVestigeOppRanks(-1);
@@ -53,6 +58,7 @@ export class GVGProduceHandler {
let lineupCe = lineup.reduce((pre, cur) => pre + cur.ce, 0);
let oppPlayers = await getOppPlayerByRanks(serverId, groupId, vestigeId, oppRanks);
let usedHeroes = await getVestigeUsedHeroes(roleId, vestigeId);
return resResult(STATUS.SUCCESS, {
vestigeId,
@@ -60,7 +66,8 @@ export class GVGProduceHandler {
score,
lineup, lineupCe,
oppPlayers,
refreshCnt
refreshCnt,
usedHeroes
})
}
@@ -75,7 +82,7 @@ export class GVGProduceHandler {
const serverId: number = session.get('serverId');
let { vestigeId, roleId: targetRoleId, rank } = msg;
let myVestigateRank = await GVGVestigeRankModel.findRankByRole(vestigeId, roleId); // 我在这个遗迹的排名
let myVestigateRank = await GVGVestigeRankModel.findByRole(vestigeId, roleId); // 我在这个遗迹的排名
const serverNames = await getAllServerName();
@@ -90,7 +97,7 @@ export class GVGProduceHandler {
let dicWarJson = gameData.warJson.get(dicWar.dispatchJsonId);
result.setRobot(dicGVGVestige, dicWarJson, serverNames[serverId]);
} else {
let hisVestigateRank = await GVGVestigeRankModel.findRankByRole(vestigeId, roleId); // 我在这个遗迹的排名
let hisVestigateRank = await GVGVestigeRankModel.findByRole(vestigeId, roleId);
if(!hisVestigateRank) return resResult(STATUS.GVG_VESTIGE_TARGET_NOT_FOUND);
let role = await RoleModel.findByRoleId(hisVestigateRank.roleId, 'roleId roleName serverId guildName title lv heads head spines spine frames frame')
@@ -109,8 +116,57 @@ export class GVGProduceHandler {
}
// 选择对手
async chooseOpp(msg: { vestigeId: number, rank: number, myRank: number }, session: BackendSession) {
async chooseOpp(msg: { vestigeId: number, roleId: string, rank: number, myRank: number }, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let serverId = session.get('serverId');
let guildCode = session.get('guildCode');
let sid = session.get('sid');
let { vestigeId, roleId: targetRoleId, rank, myRank } = msg;
let { configId, period } = getGVGPeriodData();
if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD);
let dicRank = gameData.gvgVestige.get(vestigeId)?.get(rank);
if(!dicRank) return resResult(STATUS.DIC_DATA_NOT_FOUND);
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
// 检查对手排名/自己排名
if(!checkVestigeRank(myRank, rank)) return resResult(STATUS.GVG_VESTIGE_RANK_ERR);
const hasItem = await GVGUserItemModel.checkItemCnt(configId, myLeague.leagueCode, roleId, GVG_ITEM.FIGHT_COIN, 1);
if(!hasItem) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH);
let groupId = await getGroupIdOfServer(serverId);
let status = await checkVestigeOppStatus(configId, groupId, vestigeId, roleId, myRank, targetRoleId, rank); // 锁
if(status != VESTIGE_OPP_STATUS.BATTLE) {
let oppRanks = refreshVestigeOppRanks(myRank);
let oppPlayers = await getOppPlayerByRanks(serverId, groupId, vestigeId, oppRanks);
return resResult(STATUS.SUCCESS, { status, oppPlayers });
}
// 扣征战令
const costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, [{ id: GVG_ITEM.FIGHT_COIN, count: 1 }], [], ITEM_CHANGE_REASON.GVG_VESTIGE_START);
if(!costResult) {
await GVGVestigeLockModel.releaseLock(groupId, vestigeId, rank);
return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH);
}
// 获取征战令对应奖励
const leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, dicRank.battleLeagueReward, dicRank.battleReward, ITEM_CHANGE_REASON.GVG_VESTIGE_START);
// 创建rec
const attackInfo = await generateAttackInfo(roleId, myRank);
const defenseInfo = await generateDefenseInfo(targetRoleId, vestigeId, rank);
const rec = await GVGVestigeRecModel.createRec(configId, vestigeId, groupId, attackInfo, defenseInfo, leagueGoods);
const oppDetail = await getOppDetailData(rec);
return resResult(STATUS.SUCCESS, {
battleCode: rec.battleCode,
time: rec.checkTime,
...oppDetail
});
}
// 出战界面撤退

View File

@@ -1,15 +1,20 @@
// 征战中原相关
import { GVG_PERIOD } from "../../consts";
import { GVG_PERIOD, STATUS, VESTIGE_OPP_STATUS } from "../../consts";
import { ArtifactModel } from "../../db/Artifact";
import { GVGVestigeModel } from "../../db/GVGVestige";
import { GVGVestigeRankModel } from "../../db/GVGVestigeRank";
import { GVGVestigeLockModel } from "../../db/GVGVestigeLock";
import { GVGVestigeRankModel, GVGVestigeRankType } from "../../db/GVGVestigeRank";
import { GVGVestigeRecType } from "../../db/GVGVestigeRec";
import { HeroModel } from "../../db/Hero";
import { RoleType } from "../../db/Role";
import { RoleModel, RoleType } from "../../db/Role";
import { OppDetailData, OppDetailHeroData, OppPlayerHeroInfo, OppPlayerInfo } from "../../domain/gvgField/gvgDb";
import { GVGVestigeOppPlayer } from "../../domain/gvgField/returnData";
import { gameData, getGVGVestigeRange } from "../../pubUtils/data";
import { getTimeFun } from "../../pubUtils/timeUtil";
import { getRandEelm, getRandValueByMinMax } from "../../pubUtils/util";
import { getRandEelm, getRandValueByMinMax, resResult } from "../../pubUtils/util";
import { getNumberArr, uniqueArr } from "../ladderService";
import { getHeroesAttributes } from "../playerCeService";
import { calLineupScore } from "../pvpService";
import { getAllServerName } from "../redisService";
import { getGroupIdOfServer, getGVGServerType } from "./gvgService";
@@ -65,6 +70,7 @@ function randomRank(min: number, max: number, len: number) {
return getRandEelm(arr, len);
}
// 根据ranks获取oppPlayer显示数据
export async function getOppPlayerByRanks(serverId: number, groupId: number, vestigeId: number, ranks: number[]) {
let serverNames = await getAllServerName();
let opps = await GVGVestigeRankModel.findByRanks(groupId, vestigeId, ranks);
@@ -86,4 +92,123 @@ export async function getOppPlayerByRanks(serverId: number, groupId: number, ves
}
return result;
}
}
// 获取其他遗迹里使用过的武将
export async function getVestigeUsedHeroes(roleId: string, curVestigeId: number) {
let myDatas = await GVGVestigeRankModel.findAllByRole(roleId);
let result: number[] = [];
for(let { vestigeId, lineup = [] } of myDatas) {
if(vestigeId == curVestigeId) continue;
result.push(...lineup.map(cur => cur.actorId));
}
return result;
}
// 检查我的排名是否可以挑战对方的排名
export function checkVestigeRank(myRank: number, targetRank: number) {
let dicRange = getGVGVestigeRange(myRank);
if(!dicRange) return false;
if(myRank == targetRank || targetRank == 0) return false;
// 是否可以挑战最前的几个排名
if(dicRange.topChallengeFrom <= targetRank && dicRange.topChallengeTo >= targetRank) return true;
if(dicRange.rangeBeforeTo == -1) {
if(dicRange.rangeBeforeFrom < targetRank && myRank > targetRank) return true;
} else {
if(dicRange.rangeBeforeFrom < targetRank && dicRange.rangeBeforeTo >= targetRank) return true;
}
if(dicRange.rangeAfterTo == -1) {
if(dicRange.rangeAfterFrom < targetRank && myRank > targetRank) return true;
} else {
if(dicRange.rangeAfterFrom < targetRank && dicRange.rangeAfterTo >= targetRank) return true;
}
return false;
}
export function isRobot(roleId: string) {
if(!roleId) roleId = '';
return roleId.startsWith('robot');
}
export async function checkVestigeOppStatus(configId: number, groupId: number, vestigeId: number, roleId: string, myRank: number, targetRoleId: string, rank: number) {
let myData = await GVGVestigeRankModel.findByRole(vestigeId, roleId);
if(myData?.rank != myRank) return VESTIGE_OPP_STATUS.MY_RANK_CHANGE;
if(isRobot(targetRoleId)) {
let targetData = await GVGVestigeRankModel.findByRank(vestigeId, rank);
if(targetData) return VESTIGE_OPP_STATUS.OPP_RANK_CHANGE;
} else {
let targetData = await GVGVestigeRankModel.findByRole(vestigeId, targetRoleId);
if(targetData?.rank != rank) return VESTIGE_OPP_STATUS.OPP_RANK_CHANGE;
}
let lockResult = await GVGVestigeLockModel.chooseOppLock(groupId, vestigeId, rank, configId, roleId, targetRoleId);
if(!lockResult) return VESTIGE_OPP_STATUS.OPP_IS_LOCKED;
return VESTIGE_OPP_STATUS.BATTLE;
}
// 生成防守数据
export async function generateDefenseInfo(roleId: string, vestigeId: number, rank: number) {
if(isRobot(roleId)) {
let dicRank = gameData.gvgVestige.get(vestigeId)?.get(rank); // 调用之前已经验证过了
let dicWar = gameData.war.get(dicRank?.warId);
let dicWarJson = gameData.warJson.get(dicWar?.dispatchJsonId);
if(!dicWarJson) return null;
let heroes: OppPlayerHeroInfo[] = [];
for(let json of dicWarJson) {
if(json.relation == 2) {
let hero = new OppPlayerHeroInfo();
hero.setByWarJson(json);
heroes.push(hero);
}
}
let info = new OppPlayerInfo();
info.initByRobot(dicRank, heroes, true);
return info;
} else {
let playerVestigeData = await GVGVestigeRankModel.findByRole(vestigeId, roleId);
if(!playerVestigeData) return null;
let lineup = playerVestigeData.lineup||[];
let hids = lineup.map(cur => cur.actorId);
let role = await RoleModel.findByRoleId(playerVestigeData.roleId, 'roleId roleName heads head frames frame spines spine title lv');
let heroes = await HeroModel.findByHidRange(hids, playerVestigeData.roleId, 'hid skinId lv star colorStar quality');
let info = new OppPlayerInfo();
info.initByPlayer(playerVestigeData.rank, role, heroes, lineup, true);
return info;
}
}
export async function generateAttackInfo(roleId: string, rank: number) {
let role = await RoleModel.findByRoleId(roleId, 'roleId roleName heads head frames frame spines spine title lv');
let info = new OppPlayerInfo();
info.initByPlayer(rank, role, [], [], false);
return info;
}
export async function getOppDetailData(rec: GVGVestigeRecType) {
let isRobot = rec.defenseInfo.isRobot;
let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(rec.defenseInfo.oldRank);
let result = new OppDetailData();
if(!isRobot) {
const dicWar = gameData.war.get(dicLadderDifficultRatio.gkId);
const dicWarJson = gameData.warJson.get(dicWar.dispatchJsonId);
const defenseInfo = rec.defenseInfo.heroes||[];
const hids = defenseInfo.map(cur => cur.hid);
const heroes = await HeroModel.findByHidRange(hids, rec.defenseRoleId, 'hid lv quality star colorStar');
const artifactSeids = heroes.map(hero => hero.artifact);
const artifacts = await ArtifactModel.findbySeqIds(rec.defenseRoleId, artifactSeids);
result.setByPlayer(dicWarJson, defenseInfo, heroes, artifacts);
let attrByHid = await getHeroesAttributes(rec.defenseRoleId);
for(let [hid, attribute] of attrByHid) {
result.setAttribute(hid, attribute.getAttributesToString());
}
}
return result;
}

View File

@@ -73,6 +73,7 @@ export enum GVG_ITEM {
CORN = 2, // 粟米
RICE = 3, // 水稻
PRODUCE_COIN = 10, // 内政令
FIGHT_COIN = 11, // 征战令
BATTLE_FEAT = 12, // 战功
}
@@ -114,4 +115,19 @@ export enum GVG_REC_ID {
VESTIGE_RANK = 5, // 联军每日的征战排名
LEAGUE_JOIN_GUILD = 6, // 军团加入联军
LEAGUE_QUIT_GUILD = 7, // 军团退出联军
}
}
// 遗迹选择对手状态
export enum VESTIGE_OPP_STATUS {
BATTLE = 1, // 可以挑战
OPP_IS_LOCKED = 2, // 对手被挑战
OPP_RANK_CHANGE = 3, // 对手排名变化
MY_RANK_CHANGE = 4, // 自己排名变化
}
export enum VESTIGE_STATUS {
NO = 0, // 无战场
CHECK = 1, // 出兵中
BATTLE = 2, // 战斗中
COMPLETE = 3, // 战斗结束
}

View File

@@ -1092,6 +1092,7 @@ export enum ITEM_CHANGE_REASON {
GVG_RECEIVE_BOX = 167, // 领取宝箱
GVG_RECEIVE_LV = 168, // 领取等级奖励
GVG_RECEIVE_TASK = 169, // 领取任务奖励
GVG_VESTIGE_START = 170, // gvg征战中原挑战
}
export enum TA_EVENT {

View File

@@ -336,8 +336,11 @@ export const STATUS = {
GVG_TASK_HAS_RECEIVED: { code: 21330, simStr: '任务已领取过' },
GVG_BATTLE_CITY_FULL: { code: 21331, simStr: '城市已满员' },
GVG_BATTLE_TEAM_INVALID: { code: 21332, simStr: '无效的队伍' },
GVG_VESTIGE_ERR: { code: 21333, simStr: '今日未开放该遗迹' },
GVG_VESTIGE_TARGET_NOT_FOUND: { code: 21334, simStr: '对手未找到' },
// GVG征战中原
GVG_VESTIGE_ERR: { code: 21350, simStr: '今日未开放该遗迹' },
GVG_VESTIGE_TARGET_NOT_FOUND: { code: 21351, simStr: '对手未找到' },
GVG_VESTIGE_RANK_ERR: { code: 21352, simStr: '该排名玩家不可挑战' },
// 通用 30000 - 30099
DIC_DATA_NOT_FOUND: { code: 30000, simStr: '数据表未找到' },

View File

@@ -0,0 +1,59 @@
// 征战中原对手锁
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { getZeroPoint, nowSeconds } from '../pubUtils/timeUtil';
import { GVG } from '../pubUtils/dicParam';
@index({ day: 1, groupId: 1, vestigeId: 1, rank: 1 })
export default class GVGVestigeLock extends BaseModel {
@prop({ required: true })
configId: number; // 赛期
@prop({ required: true })
day: number; // 每天5点
@prop({ required: true })
groupId: number; // 战区id
@prop({ required: true })
vestigeId: number; // 遗迹id
@prop({ required: true })
rank: number; // 排名
@prop({ required: true })
unlockTime: number; // 锁定到什么时候
@prop({ required: true })
attackRoleId: string; // 锁定到什么时候
@prop({ required: true })
defenseRoleId: string; // 锁定到什么时候
public static async chooseOppLock(groupId: number, vestigeId: number, rank: number, configId: number, attackRoleId: string, defenseRoleId: string ) {
return await this.lock(groupId, vestigeId, rank, configId, attackRoleId, defenseRoleId, nowSeconds() + GVG.GVG_VESTIGE_PREPARE_COUNTDOWN);
}
private static async lock(groupId: number, vestigeId: number, rank: number, configId: number, attackRoleId: string, defenseRoleId: string, unlockTime: number) {
let day = getZeroPoint();
await GVGVestigeLockModel.findOneAndUpdate({ day, groupId, vestigeId, rank }, { $setOnInsert: { configId, unlockTime: 0 } }, { upsert: true });
let result: GVGVestigeLockType = await GVGVestigeLockModel.findOneAndUpdate({
day, groupId, vestigeId, rank, unlockTime: { $lt: nowSeconds() }
}, { $set: { unlockTime, attackRoleId, defenseRoleId } }, { new: true }).lean();
return result;
}
public static async releaseLock(groupId: number, vestigeId: number, rank: number) {
let day = getZeroPoint();
let result: GVGVestigeLockType = await GVGVestigeLockModel.findOneAndUpdate({ day, groupId, vestigeId, rank }, { $set: { unlockTime: 0 } }, { new: true }).lean();
return result;
}
}
export const GVGVestigeLockModel = getModelForClass(GVGVestigeLock);
export interface GVGVestigeLockType extends Pick<DocumentType<GVGVestigeLock>, keyof GVGVestigeLock> {
id: number;
};
export type GVGVestigeLockUpdate = Partial<GVGVestigeLockType>; // 将所有字段变成可选项

View File

@@ -3,7 +3,7 @@ import { index, getModelForClass, prop, DocumentType, mongoose, Ref } from '@typ
import Role, { RoleType } from './Role';
import { getZeroPoint } from '../pubUtils/timeUtil';
class Lineup {
export class Lineup {
@prop({ required: true })
actorId: number; // 武将
@prop({ required: true })
@@ -60,12 +60,24 @@ export default class GVGVestigeRank extends BaseModel {
@prop({ required: true, default: 0 })
refreshCnt: number; // 刷新次数
public static async findRankByRole(vestigeId: number, roleId: string) {
public static async findAllByRole(roleId: string) {
let today = getZeroPoint();
let result: GVGVestigeRankType[] = await GVGVestigeRankModel.find({ day: today, roleId }).lean();
return result;
}
public static async findByRole(vestigeId: number, roleId: string) {
let today = getZeroPoint();
let result: GVGVestigeRankType = await GVGVestigeRankModel.findOne({ day: today, vestigeId, roleId }).lean();
return result;
}
public static async findByRank(vestigeId: number, rank: number) {
let today = getZeroPoint();
let result: GVGVestigeRankType = await GVGVestigeRankModel.findOne({ day: today, vestigeId, rank }).lean();
return result;
}
public static async initRank(configId: number, vestigeId: number, groupId: number, role: RoleType, oppRanks: number[]) {
let today = getZeroPoint();
let doc = new GVGVestigeRankModel();

View File

@@ -0,0 +1,76 @@
// 征战中原对手锁
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { OppPlayerInfo } from '../domain/gvgField/gvgDb';
import { genCode } from '../pubUtils/util';
import { VESTIGE_STATUS } from '../consts';
class LeagueGood {
@prop({ required: true })
itemType: number;
@prop({ required: true })
id: number;
@prop({ required: true })
count: number
}
@index({ day: 1, groupId: 1, vestigeId: 1, rank: 1 })
export default class GVGVestigeRec extends BaseModel {
@prop({ required: true })
battleCode: string; // 唯一code
@prop({ required: true })
attackRoleId: string; // 攻方玩家id
@prop({ required: true })
defenseRoleId: string; // 守方玩家id
@prop({ required: true })
groupId: number; // 战区id
@prop({ required: true })
vestigeId: number; // 遗迹id
@prop({ required: true })
status: number; // 1-出兵中 2-挑战中 3-挑战完毕 4-取消
@prop({ required: true })
checkTime: number; // 开始出兵的时间13位时间戳
@prop({ required: true })
battleTime: number; // 开始挑战的时间13位时间
@prop({ required: true })
endTime: number; // 结束时间13位时间戳
@prop({ required: true, type: () => OppPlayerInfo, default: {}, _id: false })
attackInfo: OppPlayerInfo; // 攻方信息
@prop({ required: true, type: () => OppPlayerInfo, default: {}, _id: false })
defenseInfo: OppPlayerInfo; // 守方信息
@prop({ required: true, type: () => LeagueGood, default: [], _id: false })
leagueGoods: LeagueGood[]; // 奖励
@prop({ required: true, default: false })
hasRpl: boolean; // 是否存在对应录像
public static async createRec(configId: number, vestigeId: number, groupId: number, attackInfo: OppPlayerInfo, defenseInfo: OppPlayerInfo, leagueGoods: LeagueGood[]) {
const battleCode = genCode(10);
const result: GVGVestigeRecType = await GVGVestigeRecModel.findOneAndUpdate({ battleCode }, {
$set: { configId, vestigeId, groupId, attackRoleId: attackInfo.roleId, defenseRoleId: defenseInfo.roleId, status: VESTIGE_STATUS.CHECK, checkTime: Date.now(), attackInfo, defenseInfo, leagueGoods }
}, { new: true, upsert: true }).lean();
return result;
}
}
export const GVGVestigeRecModel = getModelForClass(GVGVestigeRec);
export interface GVGVestigeRecType extends Pick<DocumentType<GVGVestigeRec>, keyof GVGVestigeRec> {
id: number;
};
export type GVGVestigeRecUpdate = Partial<GVGVestigeRecType>; // 将所有字段变成可选项

View File

@@ -0,0 +1,219 @@
import { prop } from "@typegoose/typegoose";
import { ArtifactModelType } from "../../db/Artifact";
import { Lineup } from "../../db/GVGVestigeRank";
import { HeroType, Talent } from "../../db/Hero";
import { RoleType } from "../../db/Role";
import { gameData } from "../../pubUtils/data";
import { EXTERIOR, GVG } from "../../pubUtils/dicParam";
import { DicGVGVestige } from "../../pubUtils/dictionary/DicGVGVestige";
import { dicWarJson, DicWarJson } from "../../pubUtils/dictionary/DicWarJson";
export class OppPlayerHeroInfo {
@prop({ required: true })
hid: number; // 武将id
@prop({ required: true })
skinId: number; // 皮肤id
@prop({ required: true })
quality: number; // 品质
@prop({ required: true })
star: number; // 星级
@prop({ required: true })
colorStar: number; // 彩星
@prop({ required: true })
lv: number; // 等级
@prop({ required: true })
dataId: number; // 出兵表上所占位置
@prop({ required: true })
order: number; // 行动顺序
setByWarJson(warJson: DicWarJson) {
this.hid = warJson.actorId;
this.skinId = warJson.actorId;
this.lv = warJson.lv;
this.dataId = warJson.dataId;
this.order = warJson.outIndex;
let dicHero = gameData.hero.get(warJson.actorId);
if(dicHero) {
this.quality = dicHero.quality;
if(this.quality == 4) {
this.star = 6;
this.colorStar = warJson.star;
} else {
this.star = warJson.star;
this.colorStar = 0;
}
}
}
setByDefenseHero(hero: HeroType, lineup: Lineup[]) {
this.hid = hero.hid;
this.skinId = hero.skinId;
this.quality = hero.quality;
this.star = hero.star;
this.colorStar = hero.colorStar;
this.lv = hero.lv;
let curLineup = lineup.find(cur => cur.actorId == hero.hid);
if(curLineup) {
this.dataId = curLineup.dataId;
this.order = curLineup.order;
}
}
}
// ladderMatchRec
export class OppPlayerInfo {
@prop({ required: true })
oldRank: number = 0; // 原排名
@prop({ required: true })
newRank: number = 0; // 交换后的排名
@prop({ required: true })
roleId: string = ''; // 角色 id
@prop({ required: true })
roleName: string = GVG.GVG_ROBOT_NAME; // 角色 名
@prop({ required: true, default: 0 })
lv: number = 1; // 等级
@prop({ required: true, default: EXTERIOR.EXTERIOR_FACE })
head: number = EXTERIOR.EXTERIOR_FACE; // 头像
@prop({ required: true, default: EXTERIOR.EXTERIOR_FACECASE })
frame: number = EXTERIOR.EXTERIOR_FACECASE; // 相框
@prop({ required: true, default: EXTERIOR.EXTERIOR_APPEARANCE })
spine: number = EXTERIOR.EXTERIOR_APPEARANCE; // 形象
@prop({ required: true, default: 0 })
title: number = 1; // 爵位
@prop({ required: true, default: 0 })
ce: number = 0; // 防守战力
@prop({ required: true, default: false })
isSuccess: boolean = false; // 是否胜利
@prop({ required: true, default: [], type: OppPlayerHeroInfo, _id: false })
heroes: OppPlayerHeroInfo[] = []; // 武将
@prop({ required: true })
isRobot: boolean = false; // 原排名
initByPlayer(rank: number, role: RoleType, heroes: HeroType[], lineup: Lineup[], isSuccess: boolean ) {
this.oldRank = rank;
this.newRank = rank;
this.roleId = role.roleId;
this.roleName = role.roleName;
this.head = role.head;
this.frame = role.frame;
this.spine = role.spine;
this.title = role.title;
this.lv = role.lv;
this.isSuccess = isSuccess;
for(let hero of heroes) {
let obj = new OppPlayerHeroInfo();
obj.setByDefenseHero(hero, lineup);
this.ce += hero.ce;
this.heroes.push(obj);
}
this.isRobot = false;
}
initByRobot(dic: DicGVGVestige, heroes: OppPlayerHeroInfo[], isSuccess: boolean) {
this.oldRank = dic.rank;
this.newRank = dic.rank;
this.roleId = `robot${this.oldRank}`;
this.head = dic.head;
this.spine = dic.spine;
this.ce = dic.ce;
this.lv = dic.level;
this.isSuccess = isSuccess;
this.heroes = heroes;
this.isRobot = true;
}
}
class HeroArtifact {
@prop({ required: true })
artifactId: number;
@prop({ required: true })
lv: number;
}
export class OppDetailHeroData {
actorId: number = 0; // 武将id
skinId: number = 0; // 皮肤idfashions表的heroId
actorName: string = ''; // 武将名
dataId: number = 0; // 出兵表唯一id
relation: number = 0; // 地方还是我方
dirction: number = 0; // 方向
outIndex: number = 0; // 玩家设置的出场顺序即order字段
x: number = 0; // 战场x坐标
y: number = 0; // 战场y坐标
var: number = 0; // 变量
lv: number = 0; // 等级
hide: number = 0; // 是否隐藏
initial_ai: number = 0; // ai类型
attribute: string = ''; // 武将属性,格式 id&val|id&val|...这里的次级属性都是没有除1000的值
star: number = 0; // 星级
colorStar: number = 0; // 彩星
quality: number = 0; // 品质
job: number = 0; // 职业
skill: string = ''; // 技能
seid: string = ''; // 技能
spine: string = ''; // 动画
talent: Talent[] = [];
subHid: number = 0; // 副将
artifact: HeroArtifact[] = [];
constructor(warJson: DicWarJson, defensHero: OppPlayerHeroInfo, hero: HeroType, artifacts: ArtifactModelType[]) {
this.dataId = warJson.dataId;
this.relation = warJson.relation;
this.dirction = warJson.dirction;
this.initial_ai = warJson.initial_ai;
this.x = warJson.x;
this.y = warJson.y;
this.var = warJson.var;
this.hide = warJson.hide;
this.skill = warJson.skill;
this.seid = warJson.seid;
this.spine = warJson.spine;
let dicHero = gameData.hero.get(warJson.actorId);
if(dicHero) this.job = dicHero.jobid;
if(defensHero) {
this.outIndex = defensHero.order;
if(hero) {
this.actorId = hero.hid;
this.skinId = hero.skinId;
this.actorName = hero.hName;
this.lv = hero.lv;
this.star = hero.star;
this.colorStar = hero.colorStar;
let skin = hero.skins.find(cur => cur.enable);
if(skin) this.talent = skin.talent;
this.job = hero.job;
this.subHid = hero.subHid;
let artifact = artifacts.find(cur => cur.seqId == hero.artifact);
if(artifact) this.artifact.push({ artifactId: artifact.artifactId, lv: artifact.lv });
}
}
}
setAttribute(attribute: string) {
this.attribute = attribute;
}
}
export class OppDetailData{
heroes: OppDetailHeroData[] = [];
lineupCe: number = 0;
setByPlayer(dicWarJson: DicWarJson[], defenseHeroes: OppPlayerHeroInfo[], heroes: HeroType[], artifacts: ArtifactModelType[]) {
for(let warJson of dicWarJson) {
let defenseHero = defenseHeroes.find(cur => cur.dataId == warJson.dataId);
let curHero = heroes.find(cur => cur.hid == defenseHero.hid);
let hero = new OppDetailHeroData(warJson, defenseHero, curHero, artifacts);
this.heroes.push(hero);
this.lineupCe += curHero.ce;
}
}
setAttribute(hid: number, attribute: string) {
let hero = this.heroes.find(cur => cur.actorId == hid);
if(hero) hero.setAttribute(attribute);
}
}

View File

@@ -1172,15 +1172,15 @@ function parseGVGVestigeCnt() {
}
export function getGVGVestigeRange(myRank: number) {
let latestRank: DicGVGVestigeRange;
let lastRank: DicGVGVestigeRange;
for(let dic of gameData.gvgVestigeRange) {
latestRank = dic;
lastRank = dic;
let { rankMin, rankMax } = dic;
if((rankMin < myRank && (rankMax >= myRank || rankMax == -1))) {
return dic;
}
}
return latestRank
return lastRank
}
// 初始加载

View File

@@ -394,5 +394,7 @@ export const GVG = {
GVG_FIELD_TYPE_RATIO: '1&5%|2&10%|3&10%', // 全联盟的特殊格子上限百分比a%的格子为小麦这个1&a|2&b|3&c
GVG_SP_FIELD_RATIO: '10%&30%', // 分配给玩家的时候有多少特殊格子 min&max 填最大最小百分比即可
GVG_REFRESH_TIME: 5, // 0
GVG_ROBOT_NAME: '遗迹守护者', // 0
GVG_ROBOT_NAME: '遗迹守护者', // 0,
GVG_VESTIGE_PREPARE_COUNTDOWN: 120, //
GVG_VESTIGE_BATTLE_COUNTDOWN: 300, //
};

View File

@@ -11,7 +11,9 @@
"value": 100,
"reward": "31002&5000",
"leagueReward": "12&100",
"ripeTime": 43200
"ripeTime": 43200,
"getWays": "&",
"info_1": "&"
},
{
"id": 2,
@@ -25,7 +27,9 @@
"value": 150,
"reward": "31002&5001",
"leagueReward": "12&150",
"ripeTime": 36000
"ripeTime": 36000,
"getWays": "&",
"info_1": "&"
},
{
"id": 3,
@@ -39,7 +43,9 @@
"value": 200,
"reward": "31002&5002",
"leagueReward": "12&150",
"ripeTime": 43200
"ripeTime": 43200,
"getWays": "&",
"info_1": "&"
},
{
"id": 4,
@@ -53,7 +59,9 @@
"value": 15,
"reward": "31002&5003",
"leagueReward": "12&200",
"ripeTime": 0
"ripeTime": 0,
"getWays": "&",
"info_1": "&"
},
{
"id": 5,
@@ -67,7 +75,9 @@
"value": 20,
"reward": "31002&5004",
"leagueReward": "12&300",
"ripeTime": 0
"ripeTime": 0,
"getWays": "&",
"info_1": "&"
},
{
"id": 6,
@@ -81,7 +91,9 @@
"value": 30,
"reward": "31002&5005",
"leagueReward": "12&300",
"ripeTime": 0
"ripeTime": 0,
"getWays": "&",
"info_1": "&"
},
{
"id": 7,
@@ -95,7 +107,9 @@
"value": 25,
"reward": "31002&5006",
"leagueReward": "12&200",
"ripeTime": 0
"ripeTime": 0,
"getWays": "&",
"info_1": "&"
},
{
"id": 8,
@@ -109,7 +123,9 @@
"value": 30,
"reward": "31002&5007",
"leagueReward": "12&300",
"ripeTime": 0
"ripeTime": 0,
"getWays": "&",
"info_1": "&"
},
{
"id": 9,
@@ -123,7 +139,9 @@
"value": 40,
"reward": "31002&5008",
"leagueReward": "12&300",
"ripeTime": 0
"ripeTime": 0,
"getWays": "&",
"info_1": "&"
},
{
"id": 10,
@@ -137,7 +155,9 @@
"value": 0,
"reward": "&",
"leagueReward": "&",
"ripeTime": 0
"ripeTime": 0,
"getWays": "&",
"info_1": "&"
},
{
"id": 11,
@@ -151,7 +171,9 @@
"value": 0,
"reward": "&",
"leagueReward": "&",
"ripeTime": 0
"ripeTime": 0,
"getWays": "&",
"info_1": "&"
},
{
"id": 12,
@@ -165,7 +187,9 @@
"value": 0,
"reward": "&",
"leagueReward": "&",
"ripeTime": 0
"ripeTime": 0,
"getWays": "62&63",
"info_1": "&"
},
{
"id": 13,
@@ -179,7 +203,9 @@
"value": 0,
"reward": "&",
"leagueReward": "&",
"ripeTime": 0
"ripeTime": 0,
"getWays": "&",
"info_1": "&"
},
{
"id": 14,
@@ -193,7 +219,9 @@
"value": 0,
"reward": "&",
"leagueReward": "&",
"ripeTime": 0
"ripeTime": 0,
"getWays": "&",
"info_1": "&"
},
{
"id": 15,
@@ -207,6 +235,8 @@
"value": 0,
"reward": "&",
"leagueReward": "&",
"ripeTime": 0
"ripeTime": 0,
"getWays": "&",
"info_1": "&"
}
]