diff --git a/game-server/app/servers/guild/handler/cityActivityHandler.ts b/game-server/app/servers/guild/handler/cityActivityHandler.ts index 2364d226f..637dedb8e 100644 --- a/game-server/app/servers/guild/handler/cityActivityHandler.ts +++ b/game-server/app/servers/guild/handler/cityActivityHandler.ts @@ -1,7 +1,10 @@ import { Application, ChannelService, BackendSession } from "pinus"; -import { GUILD_ACTIVITY_TYPE, STATUS } from "../../../consts"; +import { GUILD_ACTIVITY_TYPE, STATUS, CITY_STATUS } from "../../../consts"; import { resResult } from "../../../pubUtils/util"; import { getGuildActivityStatus } from "../../../services/guildActivityService"; +import { GuildActivityCityModel } from "../../../db/GuildActivityCity"; +import { CityParam } from "../../../domain/battleField/guildActivity"; +import { gameData } from "../../../pubUtils/data"; export default function (app: Application) { return new CityActivityHandler(app); @@ -18,16 +21,74 @@ export class CityActivityHandler { // 进入诸侯混战 async getCityActivity(msg: {}, session: BackendSession) { - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); + // const roleId = session.get('roleId'); + // const roleName = session.get('roleName'); const serverId = session.get('serverId'); const guildCode = session.get('guildCode'); let statusResult = getGuildActivityStatus(this.aid); if(!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + const dbCities = await GuildActivityCityModel.getAllCities(serverId); + + let cities = new Array(); + for(let [ cityId, dic ] of gameData.cityActivity) { + let param = new CityParam(cityId); + let curCity = dbCities.find(cur => cur.cityId == cityId); + + let preCity = dic.preCity; + if(preCity && preCity.length) { + let hasGuardCity = dbCities.find(cur => { + return preCity.includes(cur.cityId) && cur.guardGuildCode == guildCode; + }); + if(!!hasGuardCity) { + param.status = CITY_STATUS.CAN_DECLARE; + } + } else { + param.status = CITY_STATUS.CAN_DECLARE; + } + + if(curCity) { + if(curCity.guardGuildCode == guildCode) { + param.status = CITY_STATUS.GUARD; + } else if (curCity.declareGuilds.includes(guildCode)) { + param.status = CITY_STATUS.DECLARED; + } + param.guardGuildCode = curCity.guardGuildCode; + param.guardGuildName = curCity.guardGuildName; + param.declareCount = curCity.declareCount; + } + cities.push(param); + } + return resResult(STATUS.SUCCESS, { ...statusResult, + cities }); } + + // 获取单个城池状态 + async getCityStatus(msg: {}, session: BackendSession) { + + } + + // 宣战 + async declareCity(msg: {}, session: BackendSession) { + + } + + // 开始挑战 + async checkBattle(msg: {}, session: BackendSession) { + + } + + // 上报城门受到伤害 + async hitGate(msg: {}, session: BackendSession) { + + } + + // 结束挑战 + async battleEnd(msg: {}, session: BackendSession) { + + } } \ No newline at end of file diff --git a/game-server/app/servers/guild/handler/gateActivityHandler.ts b/game-server/app/servers/guild/handler/gateActivityHandler.ts index cc059635e..d61dfe05f 100644 --- a/game-server/app/servers/guild/handler/gateActivityHandler.ts +++ b/game-server/app/servers/guild/handler/gateActivityHandler.ts @@ -11,7 +11,7 @@ import { GuildActivityCityModel } from "../../../db/GuildActivityCity"; import { RoleModel, RoleType } from "../../../db/Role"; import { GuildModel } from "../../../db/Guild"; import { RankParam, GuildRankParam } from "../../../domain/rank"; -import { setRank, getGuildKeyName, getRankScore, getRank, getUnionRank } from "../../../services/redisService"; +import { setRank, getGuildKeyName, getRankScore, setGuildActivityRank, delGuildActivityRank } from "../../../services/redisService"; import { REDIS_KEY } from "../../../consts"; import { addActive } from "../../../services/guildService"; import { gameData } from "../../../pubUtils/data"; @@ -95,7 +95,7 @@ export class GateActivityHandler { obj.pushMembers(guildCode, serverId, roleId, userGuild.job); // 返回当前军团总军功 - let guildScore = await getRankScore(REDIS_KEY.GUILD_ACTIVITY, serverId, guildCode); + let guildScore = await getRankScore(REDIS_KEY.GATE_ACTIVITY, serverId, guildCode); // 前一天中位数战力 let medianCe = await getMedianCe(serverId); @@ -140,12 +140,12 @@ export class GateActivityHandler { let role = await RoleModel.findByRoleId(roleId); let { lv, vLv, head, frame, spine, title } = role; let userParam = new RankParam(roleName, lv, vLv, head, frame, spine, title); - let myScore = await setRank(getGuildKeyName(REDIS_KEY.USER_GUILD_ACTIVITY, guildCode), serverId, roleId, score, Date.now(), userParam); + let myScore = await setGuildActivityRank(REDIS_KEY.USER_GATE_ACTIVITY, guildCode, serverId, roleId, score, Date.now(), userParam); let guild = await GuildModel.findByCode(guildCode, serverId); let leader = guild.leader; let params = new GuildRankParam(guild.icon, guild.name, guild.lv, leader); - let guildScore = await setRank(REDIS_KEY.GUILD_ACTIVITY, serverId, guild.code, score, Date.now(), params, true); + let guildScore = await setRank(REDIS_KEY.GATE_ACTIVITY, serverId, guild.code, score, Date.now(), params, true); // 更新数据库 let rec = await UserGuildActivityRecModel.pushRecord(code, newRecords); @@ -185,8 +185,8 @@ export class GateActivityHandler { pinus.app.rpc.chat.guildRemote.pushGateHp.toServer(chatSid, guildCode, { gateHp }); // 返回当前军团总军功 - let guildScore = await getRankScore(REDIS_KEY.GUILD_ACTIVITY, serverId, guildCode); - let myScore = await getRankScore(getGuildKeyName(REDIS_KEY.USER_GUILD_ACTIVITY, guildCode), serverId, roleId, true); + let guildScore = await getRankScore(REDIS_KEY.GATE_ACTIVITY, serverId, guildCode); + let myScore = await getRankScore(getGuildKeyName(REDIS_KEY.USER_GATE_ACTIVITY, guildCode), serverId, roleId, true); return resResult(STATUS.SUCCESS, { code, @@ -234,19 +234,19 @@ export class GateActivityHandler { let role = await RoleModel.findByRoleId(roleId); let { lv, vLv, head, frame, spine, title } = role; let userParam = new RankParam(roleName, lv, vLv, head, frame, spine, title); - await setRank(getGuildKeyName(REDIS_KEY.USER_GUILD_ACTIVITY, guildCode), serverId, roleId, score, Date.now(), userParam); + await setGuildActivityRank(REDIS_KEY.USER_GATE_ACTIVITY, guildCode, serverId, roleId, score, Date.now(), userParam); let guild = await GuildModel.findByCode(guildCode, serverId); let leader = guild.leader; let params = new GuildRankParam(guild.icon, guild.name, guild.lv, leader); - await setRank(REDIS_KEY.GUILD_ACTIVITY, serverId, guild.code, score, Date.now(), params, true); + await setRank(REDIS_KEY.GATE_ACTIVITY, serverId, guild.code, score, Date.now(), params, true); } // 发放活跃 await addActive(roleId, serverId, GUILD_POINT_WAYS.ACTIVITY); //获得活跃值 // 返回当前军团总军功 - let guildScore = await getRankScore(REDIS_KEY.GUILD_ACTIVITY, serverId, guildCode); - let myScore = await getRankScore(getGuildKeyName(REDIS_KEY.USER_GUILD_ACTIVITY, guildCode), serverId, roleId, true); + let guildScore = await getRankScore(REDIS_KEY.GATE_ACTIVITY, serverId, guildCode); + let myScore = await getRankScore(getGuildKeyName(REDIS_KEY.USER_GATE_ACTIVITY, guildCode), serverId, roleId, true); let gateHp = obj.getGateHpAndInc(guildCode); obj.delMemberRecord(code); @@ -308,6 +308,18 @@ export class GateActivityHandler { let { aid } = msg; let dic = gameData.guildActivity.get(aid); await guildActivityStart(dic); + + let map = new Map(); + let guilds = await GuildModel.findAllGuild('serverId code'); + for(let { serverId, code } of guilds) { + if(map.has(serverId)) { + map.get(serverId).push(code); + } else { + map.set(serverId, [code]); + } + } + await delGuildActivityRank(map); + return resResult(STATUS.SUCCESS); } diff --git a/game-server/app/services/guildActivityService.ts b/game-server/app/services/guildActivityService.ts index f64418435..237e20157 100644 --- a/game-server/app/services/guildActivityService.ts +++ b/game-server/app/services/guildActivityService.ts @@ -146,7 +146,7 @@ export function getRecordScore(aid: number, record: { round: number, dataId: num */ export async function getGuildActivityRank(guildCode: string, serverId: number, roleId?: string, roleName?: string) { - let guildRankResult = await getUnionRank(REDIS_KEY.GUILD_ACTIVITY, serverId, guildCode); + let guildRankResult = await getUnionRank(REDIS_KEY.GATE_ACTIVITY, serverId, guildCode); let guildRank = new Array(); for(let { rank, code, name, num } of guildRankResult.ranks) { let param = new SimpleGuildRankParam(rank, code, name, num); @@ -161,7 +161,7 @@ export async function getGuildActivityRank(guildCode: string, serverId: number, myGuildRank = new SimpleGuildRankParam(0, guildCode, guild.name, 0); } - let memberRankResult = await getRank(getGuildKeyName(REDIS_KEY.USER_GUILD_ACTIVITY, guildCode), serverId, roleId); + let memberRankResult = await getRank(getGuildKeyName(REDIS_KEY.USER_GATE_ACTIVITY, guildCode), serverId, roleId); let memberRank = new Array(); for(let { rank, roleId, roleName, num } of memberRankResult.ranks) { let param = new SimpleRoleRankParam(rank, roleId, roleName, num); @@ -236,8 +236,8 @@ export async function gateActivitySettleReward(guildCode: string, serverId: numb let { gateHp, members } = obj.getObj(guildCode, serverId); members = uniq(members, cur => cur.roleId); - let rank = await getMyUnionRank(REDIS_KEY.GUILD_ACTIVITY, serverId, guildCode); - let guildScore = await getRankScore(REDIS_KEY.GUILD_ACTIVITY, serverId, guildCode); + let rank = await getMyUnionRank(REDIS_KEY.GATE_ACTIVITY, serverId, guildCode); + let guildScore = await getRankScore(REDIS_KEY.GATE_ACTIVITY, serverId, guildCode); let rewards = getGuildAuctionRewards(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY, rank); @@ -251,7 +251,7 @@ export async function gateActivitySettleReward(guildCode: string, serverId: numb }); // 结算功勋等奖励 let dic = gameData.guildActivity.get(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY); - let memberRankResult = await getRank(getGuildKeyName(REDIS_KEY.USER_GUILD_ACTIVITY, guildCode), serverId, ''); + let memberRankResult = await getRank(getGuildKeyName(REDIS_KEY.USER_GATE_ACTIVITY, guildCode), serverId, ''); for(let { rank, roleId, num: myScore } of memberRankResult.ranks) { let honour = dic.honour + myScore * GUILDACTIVITY.GATEACTIVITY_HONOUR_RATIO; let honourObj = getHonourObject(Math.floor(honour)); diff --git a/game-server/app/services/redisService.ts b/game-server/app/services/redisService.ts index 58afa9a13..1589ec2b4 100644 --- a/game-server/app/services/redisService.ts +++ b/game-server/app/services/redisService.ts @@ -37,13 +37,13 @@ export async function initAllRank() { export async function initRank(serverId: number) { // console.log('*****', 'initRank') const client: Redis.RedisClient = redisClient(); + await setRankRedisFromDb(REDIS_KEY.TOWER_RANK, serverId); + await setRankRedisFromDb(REDIS_KEY.GUILD_ACTIVE_RANK, serverId); await client.expireAsync(getKeyName(REDIS_KEY.TOWER_RANK, serverId), 30 * 24 * 60 * 60); await client.expireAsync(REDIS_KEY.PVP_RANK, 30 * 24 * 60 * 60); await client.expireAsync(REDIS_KEY.USER_INFO, 30 * 24 * 60 * 60); await client.expireAsync(REDIS_KEY.GUILD_INFO, 30 * 24 * 60 * 60); await client.expireAsync(getKeyName(REDIS_KEY.GUILD_ACTIVE_RANK, serverId), 30 * 24 * 60 * 60); - await setRankRedisFromDb(REDIS_KEY.TOWER_RANK, serverId); - await setRankRedisFromDb(REDIS_KEY.GUILD_ACTIVE_RANK, serverId); } @@ -66,8 +66,8 @@ export async function initSingleRank(key: string) { export async function initSingleRankWithServer(key: string, serverId: number) { await redisClient().delAsync(getKeyName(key, serverId)); - await redisClient().expireAsync(key, 30 * 24 * 60 * 60); await setRankRedisFromDb(key, serverId); + await redisClient().expireAsync(key, 30 * 24 * 60 * 60); } /** @@ -110,7 +110,7 @@ export async function existsRank(key: string, serverId: number) { * @param serverId 服务器id * @param plus 后面再加 */ -export function getKeyName(key: string, serverId?: number, plus: string = '') { +function getKeyName(key: string, serverId?: number, plus: string = '') { let newKey = ''; if(serverId) { newKey = `${key}:${serverId}`; @@ -564,14 +564,16 @@ function redisClient() { async function updateRankAtom(key: string, serverId: number, field: string, score: number, timestamp: number) { let originKey = getKeyName(key, serverId); let timeKey = getKeyName(key, serverId, 'time'); - await redisClient().expireatAsync(originKey, getNextHourPoint(5)); - await redisClient().expireatAsync(timeKey, getNextHourPoint(5)); let timelen = 10; let pow = Math.pow(10, timelen + 1); let newScore = await redisClient().zincrbyAsync(originKey, score, field); await redisClient().zaddAsync(timeKey, pow - 1 - Math.floor(timestamp/1000), field); + + await redisClient().expireatAsync(originKey, getNextHourPoint(5)); + await redisClient().expireatAsync(timeKey, getNextHourPoint(5)); + return newScore; } @@ -579,13 +581,13 @@ async function generateUnionRank(key: string, serverId: number) { let unionKey = getKeyName(key, serverId, 'union'); // 联合的key let existsKey = await redisClient().existsAsync(unionKey); if(!existsKey) { - await redisClient().expireatAsync(unionKey, 10); // 10秒更新一次 let originKey = getKeyName(key, serverId); let timeKey = getKeyName(key, serverId, 'time'); let timelen = 10; let pow = Math.pow(10, timelen + 1); await redisClient().zunionstoreAsync(unionKey, 2, originKey, timeKey, 'WEIGHTS', pow, 1); + await redisClient().expireAsync(unionKey, 10); // 10秒更新一次 } return unionKey; } @@ -640,7 +642,14 @@ export async function getRankScore(key: string, serverId: number, field: string, if(needDecode) { score = decodeScoreWithTime(score.toString()); } - return score; + return parseInt(score.toString()); +} + +export async function setGuildActivityRank(key: string, guildCode: string, serverId: number, roleId: string, score: number, time: number, userParam: RankParam) { + let nkey = getGuildKeyName(key, guildCode); + let nScore = await setRank(nkey, serverId, roleId, score, time, userParam); + await redisClient().expireatAsync(getKeyName(nkey, serverId), getNextHourPoint(5)) + return nScore } /** @@ -651,4 +660,20 @@ export async function getRankScore(key: string, serverId: number, field: string, export function getGuildKeyName(key: string, guildCode: string) { return `${key}:${guildCode}`; } + +/** + * debug接口使用,直接删除排行榜数据 + * @param params serverId => guildCodes + */ +export async function delGuildActivityRank(params: Map) { + for(let [serverId, guildCodes] of params) { + await redisClient().delAsync(getKeyName(REDIS_KEY.GATE_ACTIVITY, serverId)); + await redisClient().delAsync(getKeyName(REDIS_KEY.GATE_ACTIVITY, serverId, 'time')); + await redisClient().delAsync(getKeyName(REDIS_KEY.GATE_ACTIVITY, serverId, 'union')); + + for(let guildCode of guildCodes) { + await redisClient().delAsync(getKeyName(getGuildKeyName(REDIS_KEY.USER_GATE_ACTIVITY, guildCode), serverId)); + } + } +} /**************** 军团活动排行end */ \ No newline at end of file diff --git a/shared/consts/constModules/guildConst.ts b/shared/consts/constModules/guildConst.ts index 836602485..7f944ce45 100644 --- a/shared/consts/constModules/guildConst.ts +++ b/shared/consts/constModules/guildConst.ts @@ -165,3 +165,11 @@ export enum ENEMIES_TYPE { LITTLE_BOSS = 3, // 小boss BOSS = 4, // 大boss } + +// 城池对于我的军团的状态 +export enum CITY_STATUS { + NOT_OPEN = 0, // 未开放 + CAN_DECLARE = 1, // 可宣战 + DECLARED = 2, // 已宣战 + GUARD = 3 // 已占领 +} \ No newline at end of file diff --git a/shared/consts/constModules/sysConst.ts b/shared/consts/constModules/sysConst.ts index 4dfdce6e2..6043ae520 100644 --- a/shared/consts/constModules/sysConst.ts +++ b/shared/consts/constModules/sysConst.ts @@ -232,8 +232,8 @@ export const REDIS_KEY = { DB_GAME: 'db_game', // 服务器列表 ONLINE_USERS: 'onlineUsers', // 在线用户情况 CHANNEL_SERVERS: 'chat:channelServers', // 渠道对应的 chat 服务器 Id, - USER_GUILD_ACTIVITY: 'usrGuildAct', - GUILD_ACTIVITY: 'guildAct', + USER_GATE_ACTIVITY: 'usrGateAct', + GATE_ACTIVITY: 'gateAct', } // 各排行榜对应hash的key @@ -241,8 +241,8 @@ export const REDIS_RANK_TO_INFO = new Map([ [REDIS_KEY.TOWER_RANK, REDIS_KEY.USER_INFO], [REDIS_KEY.PVP_RANK, REDIS_KEY.USER_INFO], [REDIS_KEY.GUILD_ACTIVE_RANK, REDIS_KEY.GUILD_INFO], - [REDIS_KEY.GUILD_ACTIVITY, REDIS_KEY.GUILD_INFO], - [REDIS_KEY.USER_GUILD_ACTIVITY, REDIS_KEY.USER_INFO] + [REDIS_KEY.GATE_ACTIVITY, REDIS_KEY.GUILD_INFO], + [REDIS_KEY.USER_GATE_ACTIVITY, REDIS_KEY.USER_INFO] ]); export const FUNC_OPT_TYPE = { diff --git a/shared/db/GuildActivityCity.ts b/shared/db/GuildActivityCity.ts index 33f87fb42..0bc19329b 100644 --- a/shared/db/GuildActivityCity.ts +++ b/shared/db/GuildActivityCity.ts @@ -15,7 +15,7 @@ export default class GuildActivityCity extends BaseModel { declareGuilds: string[]; // 宣战的公会的code @prop({ required: true, default: 0 }) - declareCnt: number; // 宣战数量 + declareCount: number; // 宣战数量 @prop({ required: true }) guardGuildCode: string; // 占领的军团的code @@ -24,12 +24,20 @@ export default class GuildActivityCity extends BaseModel { guardGuildName: string; // 占领的军团名 + // 每天宣战一次 + public static async getAllCities(serverId: number) { + let today = getTodayZeroDate(); + let rec: GuildActivityCityType[] = await GuildActivityCityModel.find({ serverId, createdAt: { $gte: today }}).lean(); + + return rec; + } + // 每天宣战一次 public static async declare(serverId: number, cityId: number, guildCode: string) { let today = getTodayZeroDate(); let rec: GuildActivityCityType = await GuildActivityCityModel.findOneAndUpdate( { serverId, cityId, createdAt: { $gte: today }, declareGuilds: { $nin: [guildCode] }}, - { $setOnInsert: { cityId }, $push: { declareGuilds: guildCode }, $inc: {declareCnt: 1 } }, + { $setOnInsert: { cityId }, $push: { declareGuilds: guildCode }, $inc: {declareCount: 1 } }, {new: true, upsert: true}).lean(); return rec; diff --git a/shared/domain/battleField/guildActivity.ts b/shared/domain/battleField/guildActivity.ts index e3c9ce3ab..733529211 100644 --- a/shared/domain/battleField/guildActivity.ts +++ b/shared/domain/battleField/guildActivity.ts @@ -1,6 +1,7 @@ import { GUILDACTIVITY } from "../../pubUtils/dicParam"; import { SimpleGuildRankParam, SimpleRoleRankParam } from '../rank' import { prop } from "@typegoose/typegoose"; +import { CITY_STATUS } from "../../consts"; export class GateMembersRec { roleId: string; @@ -100,4 +101,16 @@ export class Member { roleId: string; // 玩家id @prop({required: true}) job: number; // 在军团的职位 -} \ No newline at end of file +} + +export class CityParam { + cityId: number = 0; // 城池id + guardGuildCode: string = ''; // 占领军团id + guardGuildName: string = ''; // 占领军团名 + declareCount: number = 0; // 宣战数 + status: number = CITY_STATUS.NOT_OPEN; // 城池对于我军状态 + + constructor(cityId: number) { + this.cityId = cityId; + } +} \ No newline at end of file diff --git a/shared/domain/rank.ts b/shared/domain/rank.ts index 2a13bdd56..e43c5d39c 100644 --- a/shared/domain/rank.ts +++ b/shared/domain/rank.ts @@ -90,4 +90,29 @@ export class SimpleRoleRankParam { this.roleName = roleName; this.num = num; } +} + +export class KeyName { + key: string; + serverId?: number; + guildCode?: string; + + constructor(key: string) { + this.key = key; + } + + getName() { + let res = this.key; + if(this.serverId) res += `:${this.serverId}`; + if(this.guildCode) res += `:${this.guildCode}`; + return res; + } + + getNameWithPlus(...plus: string[]) { + let res = this.getName(); + for(let p of plus) { + res += `:${p}`; + } + return res; + } } \ No newline at end of file diff --git a/shared/pubUtils/data.ts b/shared/pubUtils/data.ts index 9b1252cd8..135e31232 100644 --- a/shared/pubUtils/data.ts +++ b/shared/pubUtils/data.ts @@ -62,6 +62,7 @@ import { dicGuildActivity, DicGuildActivity } from './dictionary/DicGuildActivit import { dicGateActivityPoint } from './dictionary/DicGateActivityPoint'; import { dicGuildAuction } from './dictionary/DicGuildAuction'; import { getCutDay } from "./timeUtil"; +import { dicCityActivity } from "./dictionary/DicCityActivity"; export const gameData = { blurprtCompose: dicBlueprtCompose, @@ -146,7 +147,8 @@ export const gameData = { figureCondition: figureCondition, guildActivity: dicGuildActivity, gateActivityPoint: dicGateActivityPoint, - guildAuction: dicGuildAuction + guildAuction: dicGuildAuction, + cityActivity: dicCityActivity }; // 在此提供一些原先在gamedata中提供的方法,以便更方便获取gameData数据 diff --git a/shared/pubUtils/dictionary/DicCityActivity.ts b/shared/pubUtils/dictionary/DicCityActivity.ts index bdbc7abd0..c74776f44 100644 --- a/shared/pubUtils/dictionary/DicCityActivity.ts +++ b/shared/pubUtils/dictionary/DicCityActivity.ts @@ -10,6 +10,8 @@ export interface DicCityActivity { readonly type: number; // 下一次自动宣战城池 readonly nextCity: number; + // 上一个可解锁的 + readonly preCity: number[]; // 难度系数 readonly difficult: number; // 相应的出兵表 @@ -24,6 +26,7 @@ let arr = JSON.parse(str); export const dicCityActivity = new Map(); arr.forEach(o => { + o.preCity = parseNumberList(o.preCity); dicCityActivity.set( o.id, o ); }); arr = undefined; \ No newline at end of file diff --git a/shared/resource/jsons/dic_zyz_cityActivity.json b/shared/resource/jsons/dic_zyz_cityActivity.json index dc30d5c50..2408bc144 100644 --- a/shared/resource/jsons/dic_zyz_cityActivity.json +++ b/shared/resource/jsons/dic_zyz_cityActivity.json @@ -3,6 +3,7 @@ "id": 1, "name": "汉中", "type": 1, + "preCity": 0, "nextCity": 7, "difficult": 90, "warid": 7002, @@ -12,6 +13,7 @@ "id": 2, "name": "南中", "type": 1, + "preCity": 0, "nextCity": 7, "difficult": 90, "warid": 7002, @@ -21,6 +23,7 @@ "id": 3, "name": "柴桑", "type": 1, + "preCity": 0, "nextCity": 8, "difficult": 90, "warid": 7002, @@ -30,6 +33,7 @@ "id": 4, "name": "会稽", "type": 1, + "preCity": 0, "nextCity": 8, "difficult": 90, "warid": 7002, @@ -39,6 +43,7 @@ "id": 5, "name": "太原", "type": 1, + "preCity": 0, "nextCity": 9, "difficult": 90, "warid": 7002, @@ -48,6 +53,7 @@ "id": 6, "name": "巨鹿", "type": 1, + "preCity": 0, "nextCity": 9, "difficult": 90, "warid": 7002, @@ -57,6 +63,7 @@ "id": 7, "name": "成都", "type": 2, + "preCity": "1&2", "nextCity": 10, "difficult": 100, "warid": 7002, @@ -66,6 +73,7 @@ "id": 8, "name": "建业", "type": 2, + "preCity": "3&4", "nextCity": 10, "difficult": 100, "warid": 7002, @@ -75,6 +83,7 @@ "id": 9, "name": "邺城", "type": 2, + "preCity": "5&6", "nextCity": 10, "difficult": 100, "warid": 7002, @@ -84,6 +93,7 @@ "id": 10, "name": "洛阳", "type": 3, + "preCity": "7&8&9", "nextCity": 0, "difficult": 110, "warid": 7002,