From 2441a8d473457de80d4bad665d70f77d4209dea3 Mon Sep 17 00:00:00 2001 From: luying Date: Sat, 27 Mar 2021 11:02:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=86=9B=E5=9B=A2=E6=B4=BB=E5=8A=A8=EF=BC=9A?= =?UTF-8?q?=E7=B2=AE=E8=8D=89=E5=85=88=E8=A1=8C=E9=83=A8=E5=88=86=E8=AE=A1?= =?UTF-8?q?=E7=AE=97=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../guild/handler/raceActivityHandler.ts | 85 ++++++- .../guild/remote/guildActivityRemote.ts | 9 +- .../app/services/guildActivityService.ts | 104 +++++++- game-server/app/services/redisService.ts | 37 ++- game-server/app/services/timeTaskService.ts | 24 +- game-server/app/util/routeUtil.ts | 9 +- game-server/config/redis.ts | 2 +- shared/consts/constModules/guildConst.ts | 30 +++ shared/consts/constModules/sysConst.ts | 8 +- shared/domain/battleField/guildActivity.ts | 232 +++++++++++++++--- shared/domain/rank.ts | 11 + shared/pubUtils/data.ts | 21 +- shared/pubUtils/dicParam.ts | 20 +- shared/pubUtils/dictionary/DicRaceActivity.ts | 46 ++++ .../resource/jsons/dic_zyz_cityActivity.json | 28 +-- .../jsons/dic_zyz_gk_guildActivity.json | 26 +- .../resource/jsons/dic_zyz_guildActivity.json | 12 +- .../resource/jsons/dic_zyz_raceActivity.json | 145 +++++++++++ 18 files changed, 765 insertions(+), 84 deletions(-) create mode 100644 shared/pubUtils/dictionary/DicRaceActivity.ts create mode 100644 shared/resource/jsons/dic_zyz_raceActivity.json diff --git a/game-server/app/servers/guild/handler/raceActivityHandler.ts b/game-server/app/servers/guild/handler/raceActivityHandler.ts index d83f818a6..ea97a4cdc 100644 --- a/game-server/app/servers/guild/handler/raceActivityHandler.ts +++ b/game-server/app/servers/guild/handler/raceActivityHandler.ts @@ -1,7 +1,8 @@ import { Application, ChannelService, BackendSession } from "pinus"; -import { GUILD_ACTIVITY_TYPE, STATUS } from "../../../consts"; +import { GUILD_ACTIVITY_TYPE, STATUS, GUILD_ACTIVITY_STATUS } from "../../../consts"; import { resResult } from "../../../pubUtils/util"; -import { getGuildActivityStatus } from "../../../services/guildActivityService"; +import { getGuildActivityStatus, getRaceActivityObj, getRaceActivityRank, getWoodenHorseList, calWoodenHorseAndSend } from "../../../services/guildActivityService"; +import { UserGuildModel } from "../../../db/UserGuild"; export default function (app: Application) { return new RaceActivityHandler(app); @@ -14,11 +15,39 @@ export class RaceActivityHandler { this.channelService = app.get('channelService'); } - private aid = GUILD_ACTIVITY_TYPE.GATE_ACTIVITY; // 蛮夷入侵id + private aid = GUILD_ACTIVITY_TYPE.RACE_ACTIVITY; // 蛮夷入侵id // 进入粮草先行界面 async getRaceActivity(msg: {}, session: BackendSession) { + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + if(!guildCode) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); + + let statusResult = getGuildActivityStatus(this.aid); + if(!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let obj = getRaceActivityObj(); + let woodenHorse = await obj.getWoodenHorse(guildCode, serverId); + if(!woodenHorse) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); + + let events = obj.getEvents(guildCode, woodenHorse.distance); + let ranks = await getRaceActivityRank(guildCode, serverId); + let hasJoin = obj.hasJoin(guildCode, roleId); + + return resResult(STATUS.SUCCESS, { + ...statusResult, + hasJoin, + woodenHorse, + ...ranks, + events + }); + } + + // 加入木马 + async join(msg: {}, session: BackendSession) { + const roleId = session.get('roleId'); const roleName = session.get('roleName'); const serverId = session.get('serverId'); @@ -28,15 +57,57 @@ export class RaceActivityHandler { let statusResult = getGuildActivityStatus(this.aid); if(!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); - + let obj = getRaceActivityObj(); + + let myGuild = await UserGuildModel.getMyGuild(roleId, 'job'); + let woodenHorse = obj.joinWoodenHorse(guildCode, roleId, roleName, myGuild.job); + if(!woodenHorse) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); + + let events = obj.getEvents(guildCode, woodenHorse.distance); + let hasJoin = obj.hasJoin(guildCode, roleId); return resResult(STATUS.SUCCESS, { ...statusResult, - hasJoin: true, - woodenHorse: {}, - guildRank:[] + hasJoin, + woodenHorse, + events }); } + // 打开竞赛页面 + async getRace(msg: {}, session: BackendSession) { + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + if(!guildCode) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); + + let statusResult = getGuildActivityStatus(this.aid); + if(!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + if(statusResult.status != GUILD_ACTIVITY_STATUS.START) { + return resResult(STATUS.GUILD_ACTIVITY_NOT_OPEN); + } + + let obj = getRaceActivityObj(); + let woodenHorse = await obj.getWoodenHorse(guildCode, serverId); + if(!woodenHorse) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); + + let events = obj.getEvents(guildCode, woodenHorse.distance); + let hasJoin = obj.hasJoin(guildCode, roleId); + + let woodenHorseList = await getWoodenHorseList(guildCode, serverId); + + return resResult(STATUS.SUCCESS, { + ...statusResult, + hasJoin, + woodenHorseList, + events + }); + } + + async test(msg: { serverId: number }, session: BackendSession) { + let {serverId} = msg; + await calWoodenHorseAndSend(serverId); + } } \ No newline at end of file diff --git a/game-server/app/servers/guild/remote/guildActivityRemote.ts b/game-server/app/servers/guild/remote/guildActivityRemote.ts index d70f6d92b..a65bad6ed 100644 --- a/game-server/app/servers/guild/remote/guildActivityRemote.ts +++ b/game-server/app/servers/guild/remote/guildActivityRemote.ts @@ -1,5 +1,5 @@ import { Application, ChannelService } from 'pinus'; -import { sendAllGuildRanks, sendGuildActEndMsg } from '../../../services/guildActivityService'; +import { sendAllGuildRanks, sendGuildActEndMsg, calWoodenHorseAndSend } from '../../../services/guildActivityService'; export default function (app: Application) { return new GuildActivityRemote(app); @@ -27,4 +27,11 @@ export class GuildActivityRemote { public async guildActivityEnd(aid: number) { await sendGuildActEndMsg(aid); } + + /** + * 计算粮草先行木马状态并发送 + */ + public async calWoodenHorseAndSend(serverId: number) { + await calWoodenHorseAndSend(serverId); + } } \ No newline at end of file diff --git a/game-server/app/services/guildActivityService.ts b/game-server/app/services/guildActivityService.ts index ee295e0c0..101aacb05 100644 --- a/game-server/app/services/guildActivityService.ts +++ b/game-server/app/services/guildActivityService.ts @@ -6,11 +6,11 @@ import { gameData, getGuildAuctionRewards, getCityActivityRewards } from "../pub import { getCurHourPoint, getCutDay, nowSeconds } from "../pubUtils/timeUtil"; import { GUILD_ACTIVITY_STATUS, GET_POINT_WAYS, GUILD_ACTIVITY_TYPE, REDIS_KEY, AUCTION_SOURCE, MAIL_TYPE, CITY_STATUS } from "../consts"; import { Record, UserGuildActivityRecModel } from "../db/UserGuildActivityRec"; -import { GateMembersRec, GateActivityObject, CityActivityObject, CityParam, Member } from "../domain/battleField/guildActivity"; +import { GateMembersRec, GateActivityObject, CityActivityObject, CityParam, Member, RaceActivityObject, WoodenHorse } from "../domain/battleField/guildActivity"; import { DicGuildActivity } from "../pubUtils/dictionary/DicGuildActivity"; -import { getUnionRank, getRank, getGuildKeyName, getMyUnionRank, getRankScore, getCityKeyName, getAllServers } from "./redisService"; +import { getUnionRank, getRank, getGuildKeyName, getMyUnionRank, getRankScore, getCityKeyName, getAllServers, getUnionRankRange } from "./redisService"; import { GuildModel } from "../db/Guild"; -import { SimpleGuildRankParam, SimpleRoleRankParam } from "../domain/rank"; +import { SimpleGuildRankParam, SimpleRoleRankParam, SimpleGuildRankWithTimeParam } from "../domain/rank"; import { getGuildChannelSid, getWorldChannelSid, getCityChannelSid } from "./chatChannelService"; import { pinus } from "pinus"; import { GuildActivityRecordModel } from "../db/GuildActivityRec"; @@ -21,6 +21,7 @@ import { GuildActivityCityType, GuildActivityCityModel } from "../db/GuildActivi let gateActivityObj: GateActivityObject; let cityActivityObj: CityActivityObject; +let raceActivityObj: RaceActivityObject; export function getGateActivityObj() { if(!gateActivityObj) { gateActivityObj = new GateActivityObject(); @@ -32,7 +33,14 @@ export function getCityActivityObj() { if(!cityActivityObj) { cityActivityObj = new CityActivityObject(); } - return cityActivityObj + return cityActivityObj; +} + +export function getRaceActivityObj() { + if(!raceActivityObj) { + raceActivityObj = new RaceActivityObject(); + } + return raceActivityObj; } /** @@ -159,6 +167,53 @@ export async function getCityActivityRank(guildCode: string, serverId: number, c return rec; } +export async function getRaceActivityRank(guildCode: string, serverId: number) { + let guildKey = REDIS_KEY.RACE_ACTIVITY; + + let obj = getRaceActivityObj(); + let guildRankResult = await getUnionRank(guildKey, serverId, guildCode); + let guildRank = new Array(); + for(let { rank, code, name, num } of guildRankResult.ranks) { + let _obj = await obj.getWoodenHorse(code, serverId); + let param = new SimpleGuildRankWithTimeParam(rank, code, name, num, _obj?_obj.time:0, _obj?_obj.durability:0); + guildRank.push(param); + } + let myGuildRank: SimpleGuildRankWithTimeParam; + if(guildRankResult.myRank) { + let { rank, code, name, num } = guildRankResult.myRank; + let _obj = await obj.getWoodenHorse(code, serverId); + myGuildRank = new SimpleGuildRankWithTimeParam(rank, code, name, num, _obj?_obj.time:0, _obj?_obj.durability:0); + } else { + let guild = await GuildModel.findByCode(guildCode, serverId, 'name'); + let _obj = await obj.getWoodenHorse(guildCode, serverId); + myGuildRank = new SimpleGuildRankWithTimeParam(0, guildCode, guild?.name, 0, _obj?_obj.time:0, _obj?_obj.durability:0); + } + return { guildRank, myGuildRank } +} + +/** + * 获取和自己同屏的5个木牛流马 + * @param guildCode + * @param serverId + */ +export async function getWoodenHorseList(guildCode: string, serverId: number) { + let guildKey = REDIS_KEY.RACE_ACTIVITY; + let obj = getRaceActivityObj(); + let myRank = await getMyUnionRank(guildKey, serverId, guildCode); + let startRank = myRank - 2 > 0? myRank - 2: 1; + let endRank = startRank + 4; + let range = await getUnionRankRange(guildKey, serverId, startRank, endRank); + let woodenHorseList = new Array(); + for(let { code } of range) { + let woodenHorse = await obj.getWoodenHorse(code, serverId); + if(woodenHorse) { + woodenHorseList.push(woodenHorse); + } + } + return woodenHorseList; +} + + /** * 获得军团活动排行榜 * @param guildCode @@ -477,4 +532,45 @@ export function getCityStatus(guildCode: string, cityId: number, preCity: number } } return status; +} + +export async function calWoodenHorseAndSend(serverId: number) { + console.log('calWoodenHorseAndSend'); + let guildKey = REDIS_KEY.RACE_ACTIVITY; + let obj = getRaceActivityObj(); + let { ranks } = await getUnionRank(guildKey, serverId, ''); + let map = new Map(); + let user = new Map(); + + for(let i = 0; i < ranks.length; i++) { + let { code } = ranks[i]; + for(let j = i; j <= i + 2; j++) { + if(j <= ranks.length - 1 && !map.has(j)) { + map.set(j, new Array()); + } + } + user.set(i, code); + for(let [rank, woodenHorseList] of map) { + let woodenHorse = await obj.getWoodenHorse(code, serverId); + if(woodenHorse) { + map.get(rank).push(woodenHorse); + } else { + map.get(rank).push(new WoodenHorse(rank.toString(), 's',0)); + } + let len = map.get(rank).length; + let limit = 5; + if(rank - 2 < 0) limit += rank - 2; + if(rank + 2 > ranks.length - 1) limit -= (rank + 2) - (ranks.length - 1); + + if( len >= limit) { + // 发送 + let roleId = user.get(rank); + console.log('send', roleId, woodenHorseList.length, JSON.stringify(woodenHorseList)); + + map.delete(rank); + } + } + } + + return ; } \ No newline at end of file diff --git a/game-server/app/services/redisService.ts b/game-server/app/services/redisService.ts index e1e73030d..00c32e79a 100644 --- a/game-server/app/services/redisService.ts +++ b/game-server/app/services/redisService.ts @@ -579,14 +579,13 @@ async function updateRankAtom(key: string, serverId: number, field: string, scor return newScore; } -async function generateUnionRank(key: string, serverId: number) { +async function generateUnionRank(key: string, serverId: number, timelen = 10) { let unionKey = getKeyName(key, serverId, 'union'); // 联合的key let existsKey = await redisClient().existsAsync(unionKey); if(!existsKey) { 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秒更新一次 @@ -600,7 +599,7 @@ async function generateUnionRank(key: string, serverId: number) { * @param serverId 区服id * @param roleId 自己的id */ -export async function getUnionRank(key: string, serverId: number, roleId: string, limit = 100) { +export async function getUnionRank(key: string, serverId: number, roleId: string, timelen = 10, limit = 100) { let ranks = [], myRank = null; let unionKey = await generateUnionRank(key, serverId); @@ -627,6 +626,38 @@ export async function getUnionRank(key: string, serverId: number, roleId: string return {ranks, myRank} } +/** + * 获取(分两个zset的)排行的一段排名内的数据 + * @param key 配置在REDIS_KEY中的key + * @param serverId 区服id + * @param startRank 开始排名 + * @param endRank 结束排名 + */ +export async function getUnionRankRange(key: string, serverId: number, startRank: number, endRank: number) { + let ranks = []; + + let unionKey = await generateUnionRank(key, serverId); + const rankFromDb = await redisClient().zrevrangeAsync(unionKey, startRank - 1, endRank - 1, "WITHSCORES"); + + let _key = key.split(':')[0]; + let infoKey = REDIS_RANK_TO_INFO.get(_key)||REDIS_KEY.USER_INFO; + + for(let ii = 0; ii < rankFromDb.length; ii+=2) { + const _roleId = rankFromDb[ii]; + const _score = decodeScoreWithTime(rankFromDb[ii + 1]); + const info = await redisClient().hgetAsync(infoKey, _roleId); + const _userInfo = JSON.parse(info); + const tmp = {..._userInfo, num: _score, rank: Math.floor(ii/2)+1}; + if(infoKey == REDIS_KEY.USER_INFO) { + tmp["roleId"] = _roleId; + } else if(infoKey == REDIS_KEY.GUILD_INFO) { + tmp["code"] = _roleId; + } + ranks.push(tmp); + } + return ranks +} + // 获取我的排名 export async function getMyUnionRank(key: string, serverId: number, roleId: string) { let unionKey = await generateUnionRank(key, serverId); diff --git a/game-server/app/services/timeTaskService.ts b/game-server/app/services/timeTaskService.ts index 68812f0c0..4c95689db 100644 --- a/game-server/app/services/timeTaskService.ts +++ b/game-server/app/services/timeTaskService.ts @@ -7,7 +7,7 @@ import { nowSeconds, getTodayZeroPoint, getAge } from '../pubUtils/timeUtil'; import { getPvpGkWarIds, getPvpRankRewards, getPvpHeroRewards, getResultMaxRank, getTodayGuildActivity } from '../pubUtils/data'; import { deepCopy, getRandomArr, resResult } from '../pubUtils/util'; import { getLvByScore } from './pvpService'; -import { getMyRank, setRank, resetPvpRanks, getAllOnlineRoles, delGuildActivityRank } from './redisService'; +import { getMyRank, setRank, resetPvpRanks, getAllOnlineRoles, delGuildActivityRank, getAllServers } from './redisService'; import { MAIL_TYPE, REDIS_KEY, ADULT_AGE, GUEST_MAX_TIME, ADDICTION_PREVENTION_CODE, GUILD_ACTIVITY_STATUS, GUILD_ACTIVITY_TYPE } from '../consts'; import { RankParam } from '../domain/rank'; import { RoleModel } from '../db/Role'; @@ -24,6 +24,7 @@ import { getGuildActivityByDic, setMedianCe, sendEndMsgToAll } from './guildActi import { sendUngotDividendJob, startGuildAuction, startWorldAuction, stopAuction } from './auctionService'; import { DicGuildActivity } from '../pubUtils/dictionary/DicGuildActivity'; import { GuildModel } from '../db/Guild'; +import { dispatch } from '../util/dispatcher'; const PER_SECOND = 1 * 1000; const PER_DAY = 24 * 60 * 60; @@ -364,11 +365,13 @@ async function guildActivitySchedule() { if(statusResult.status == GUILD_ACTIVITY_STATUS.START) { if(!guildActSecondsJobId) { - let seconds = 10; // 每10秒下发一次 - if(dicGuildActivity.id == GUILD_ACTIVITY_TYPE.RACE_ACTIVITY) { - seconds = 1; + if(dicGuildActivity.id == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) { + guildActSecondsJobId = scheduleJob('guildActivitySeconds', `*/10 * * * * *`, gateActivitySeconds); + } else if(dicGuildActivity.id == GUILD_ACTIVITY_TYPE.CITY_ACTIVITY) { + guildActSecondsJobId = scheduleJob('guildActivitySeconds', `*/10 * * * * *`, cityActivitySeconds); + } else if(dicGuildActivity.id == GUILD_ACTIVITY_TYPE.RACE_ACTIVITY) { + // guildActSecondsJobId = scheduleJob('guildActivitySeconds', `*/1 * * * * *`, raceActivitySeconds); } - guildActSecondsJobId = scheduleJob('guildActivitySeconds', `*/${seconds} * * * * *`, gateActivitySeconds); } if(!guildActEndJobId) { @@ -452,6 +455,17 @@ export async function cityActivitySeconds() { } } +// 每10秒下发一次的任务 +export async function raceActivitySeconds() { + console.log('*****raveActivitySeconds') + let servers = await getAllServers(); // 玩家serverId列表 + let guildServers = pinus.app.getServersByType('guild'); + for(let serverId of servers) { + let sid = dispatch(serverId.toString(), guildServers); + await pinus.app.rpc.guild.guildActivityRemote.calWoodenHorseAndSend.toServer(sid.id, serverId); + } +} + function auctionSchedule() { scheduleJob('startGuildAuction', '0 0 20 20 * ?', startGuildAuction); scheduleJob('startWorldAuction', '0 0 20 30 * ?', startWorldAuction); diff --git a/game-server/app/util/routeUtil.ts b/game-server/app/util/routeUtil.ts index 61a205300..29915badd 100644 --- a/game-server/app/util/routeUtil.ts +++ b/game-server/app/util/routeUtil.ts @@ -72,11 +72,18 @@ export function guild(session: Session, msg: any, app: Application, cb: (err: Er 'guild.cityActivityHandler.checkBattle', 'guild.cityActivityHandler.hitGate', 'guild.cityActivityHandler.battleEnd' - ].indexOf(arg.route) !== -1) { + ].indexOf(arg.route) !== -1) { + if (arg.body.cityId) { rid = arg.body.cityId.toString(); } + } else if (['guild.raceActivityHandler.getRaceActivity', + 'guild.raceActivityHandler.join', + 'guild.raceActivityHandler.getRace', + ]) { + rid = session.get('serverId').toString(); } + } } diff --git a/game-server/config/redis.ts b/game-server/config/redis.ts index 082298b78..ef4c1b427 100644 --- a/game-server/config/redis.ts +++ b/game-server/config/redis.ts @@ -53,7 +53,7 @@ declare module 'redis' { // 返回有序集中指定成员的排名,从大到小 zrevrankAsync(key: string, field: string): Promise; // 命令返回有序集中,指定区间内的成员,从大到小 - zrevrangeAsync(key: string, start: number, end: number): Promise; + zrevrangeAsync(key: string, start: number, end: number, withscores?: string): Promise; // 对有序集合中指定成员的分数加上增量 increment zincrbyAsync(key: string, increment: number, member: string): Promise; // 对有序集合中指定成员的分数加上增量 increment diff --git a/shared/consts/constModules/guildConst.ts b/shared/consts/constModules/guildConst.ts index 580a6d867..dfb02d889 100644 --- a/shared/consts/constModules/guildConst.ts +++ b/shared/consts/constModules/guildConst.ts @@ -174,4 +174,34 @@ export enum CITY_STATUS { CAN_DECLARE = 1, // 可宣战 DECLARED = 2, // 已宣战 GUARD = 3 // 已占领 +} + +// 粮草先行事件表 +export enum RACE_EVENT { + LIANNU = 1, // 连弩 + GUISHOUYINFU = 2, // 鬼手阴符 + FENGCHE = 3, // 风车 + WUGUIBANYUNFU = 4, // 五鬼搬运符 + LUDUN = 5, // 橹盾 + TIANSHIDUNFU = 6, // 天师盾符 + JIASU_1 = 7, // 加速事件 + JIASU_2 = 8, // 加速事件 + HUIFU_1 = 9, // 恢复事件 + JIANSU_1 = 10, // 减速事件 + JIANSU_2 = 11, // 减速事件 + SHANGHAI_1 = 12, // 伤害事件 + ITEM = 13, // 将获得道具 +} + +// 粮草先行事件类型 +export enum RACE_EVENT_TYPE { + DEFAULT = 0, + ITEM = 1, // 发道具 + EVENT = 2, // 事件 +} + +// 粮草先行事件效果类型 +export enum RACE_EVENT_EFFECT_TYPE { + GOOD = 1, // 好事件 + BAD = 2, // 坏事件 } \ No newline at end of file diff --git a/shared/consts/constModules/sysConst.ts b/shared/consts/constModules/sysConst.ts index a026d1db9..0ec602392 100644 --- a/shared/consts/constModules/sysConst.ts +++ b/shared/consts/constModules/sysConst.ts @@ -236,7 +236,7 @@ export const REDIS_KEY = { GATE_ACTIVITY: 'gateAct', // 蛮夷入侵军团排行 USER_CITY_ACTIVITY: 'usrCityAct', // 诸侯混战玩家排行 CITY_ACTIVITY: 'cityAct', // 诸侯混战军团排行 - + RACE_ACTIVITY: 'raceAct', // 粮草先行军团排行 } // 各排行榜对应hash的key @@ -247,7 +247,8 @@ export const REDIS_RANK_TO_INFO = new Map([ [REDIS_KEY.GATE_ACTIVITY, REDIS_KEY.GUILD_INFO], [REDIS_KEY.USER_GATE_ACTIVITY, REDIS_KEY.USER_INFO], [REDIS_KEY.CITY_ACTIVITY, REDIS_KEY.GUILD_INFO], - [REDIS_KEY.USER_CITY_ACTIVITY, REDIS_KEY.USER_INFO] + [REDIS_KEY.USER_CITY_ACTIVITY, REDIS_KEY.USER_INFO], + [REDIS_KEY.RACE_ACTIVITY, REDIS_KEY.GUILD_INFO] ]); export const FUNC_OPT_TYPE = { @@ -351,7 +352,8 @@ export const FILENAME = { DIC_CITY_ACTIVITY: 'dic_zyz_cityActivity', DIC_CHAT_ACCUSE: 'dic_zyz_chat_report', DIC_CHAT_SYSTEM: 'dic_zyz_chat_system', - DIC_CITY_ACTIVITY_REWARD: 'dic_zyz_cityActivityReward' + DIC_CITY_ACTIVITY_REWARD: 'dic_zyz_cityActivityReward', + DIC_RACE_ACTIVITY: 'dic_zyz_raceActivity' } export const WAR_RELATE_TABLES = [ diff --git a/shared/domain/battleField/guildActivity.ts b/shared/domain/battleField/guildActivity.ts index 4838c7cb3..804c6bfe2 100644 --- a/shared/domain/battleField/guildActivity.ts +++ b/shared/domain/battleField/guildActivity.ts @@ -1,7 +1,13 @@ import { GUILDACTIVITY } from "../../pubUtils/dicParam"; -import { SimpleGuildRankParam, SimpleRoleRankParam } from '../rank' +import { SimpleGuildRankParam, SimpleRoleRankParam, GuildRankParam } from '../rank' import { prop } from "@typegoose/typegoose"; -import { CITY_STATUS } from "../../consts"; +import { CITY_STATUS, RACE_EVENT_TYPE, RACE_EVENT_EFFECT_TYPE, REDIS_KEY, RACE_EVENT } from "../../consts"; +import { gameData } from "../../pubUtils/data"; +import { GuildModel } from "../../db/Guild"; +import { getRandEelm, sortArrRandom } from "../../pubUtils/util"; +import { RoleType } from "../../db/Role"; +import { setRank, getMyUnionRank } from "../../services/redisService"; +import { RewardInter } from "../../pubUtils/interface"; export class GateMembersRec { roleId: string; @@ -208,13 +214,98 @@ export class RaceActivityObject { private members: Map> = new Map(); // 每个军团参与的成员 guildCode => [{roleId, job}] private woodenHorses: Map = new Map(); // 每个军团的木牛流马 guildCode => WoodenHorse private events: Map = new Map(); // 每个军团遇到的事件 + private items: Map = new Map(); // 每个玩家的道具 roleId => [{id, count}] - getWoodenHorse(guildCode: string) { - if(!this.woodenHorses.has(guildCode)) { - // this.woodenHorses.set(guildCode, ) + hasJoin(guildCode: string, roleId: string) { + let member = this.members.get(guildCode)||[]; + return member.findIndex(cur => cur.roleId == roleId) != -1; + } + + pushMember(guildCode: string, roleId: string, job: number) { + if(!this.members.has(guildCode)) { + this.members.set(guildCode, []); } - let wh = this.woodenHorses.get(guildCode); + this.members.get(guildCode).push({roleId, job}); + } + joinWoodenHorse(guildCode: string, roleId: string, roleName: string, job: number) { + if(!this.woodenHorses.has(guildCode)) return false; + let woodenHorse = this.woodenHorses.get(guildCode).joinMember(roleId, roleName); + this.pushMember(guildCode, roleId, job); + let events = this.events.get(guildCode)||[]; + return woodenHorse.getCurWoodenHorse(events); + } + + async getWoodenHorse(guildCode: string, serverId: number) { + if(!this.woodenHorses.has(guildCode)) { + this.initEvents(guildCode); + let guild = await GuildModel.findByCode(guildCode, serverId); + if(!guild) return false; + let leader = guild.leader; + let guildRankParam = new GuildRankParam(guild.icon, guild.name, guild.lv, leader); + await setRank(REDIS_KEY.RACE_ACTIVITY, serverId, guild.code, 0, Math.pow(10, 11) - guild.guildCe, guildRankParam, true); + let { name: guildName, guildCe } = guild; + this.woodenHorses.set(guildCode, new WoodenHorse(guildCode, guildName, guildCe)) + } + let woodenHorse = this.woodenHorses.get(guildCode); + let events = this.events.get(guildCode)||[]; + return woodenHorse.getCurWoodenHorse(events); + } + + // 初始进入就随机9个灵球事件 + initEvents(guildCode: string) { + if(!this.events.get(guildCode)) { + this.events.set(guildCode, []); + } + let dicEncounter = gameData.raceActivityEncounter; // 距离=>事件类型 + let goodEventNum = Math.floor(dicEncounter.eventNum/2); + let badEventNum = dicEncounter.eventNum - goodEventNum; + + let dicRaceTypes = gameData.raceTypes.get(RACE_EVENT_TYPE.EVENT); + let goodEvents = getRandEelm(dicRaceTypes.get(RACE_EVENT_EFFECT_TYPE.GOOD), goodEventNum); + let badEvents = getRandEelm(dicRaceTypes.get(RACE_EVENT_EFFECT_TYPE.BAD), badEventNum); + let events = sortArrRandom(goodEvents.concat(badEvents)); + let index = 0; + + for(let [distance, type] of dicEncounter.events) { + if(type == RACE_EVENT_TYPE.ITEM) { + let event = new Event(RACE_EVENT.ITEM, guildCode, guildCode, distance); + this.events.get(guildCode).push(event); + } else if (type == RACE_EVENT_TYPE.EVENT) { + let event = new Event(events[index], guildCode, guildCode, distance); + this.events.get(guildCode).push(event); + index ++; + } + } + } + + getEvents(guildCode: string, distance: number) { + let events = this.events.get(guildCode)||[]; + let result = new Array(); + for(let event of events) { + let { endTime, endDistance } = event; + if(endTime) { + if(Date.now() > endTime) continue; + } + if(endDistance) { + if(distance > endDistance) continue; + } + result.push(event); + } + return result; + } + + handleItem(roleId: string, id: number, inc: number) { + let items = this.items.get(roleId)||[]; + let curItem = items.find(cur => cur.id == id); + if(!curItem && inc < 0) return false; + if(!curItem) { + curItem = { id, count: 0 }; + items.push(curItem); + } + if(curItem.count + inc < 0 ) return false; + curItem.count += inc; + return items; } } @@ -225,15 +316,17 @@ class WoodenHorseMember { // 木牛流马 export class WoodenHorse { - guildCode: string; // 军团code 木马的唯一标识 - guildName: string; // 军团名 - guildCe: number; // 军团战力 - speed: number; // 速度 - durability: number; // 耐久度 - distance: number; // 距离 - time: number; // 到达时间 - memberCnt: number; // 成员人数 - members: WoodenHorseMember[]; // 成员 + guildCode: string = ""; // 军团code 木马的唯一标识 + guildName: string = ""; // 军团名 + guildCe: number = 0; // 军团战力 + speed: number = 0; // 速度 + durability: number = 100; // 耐久度 + distance: number = 0; // 距离 + time: number = 0; // 到达时间 + memberCnt: number = 0; // 成员人数 + members: WoodenHorseMember[] = []; // 成员 + shield: number = 0; // 护盾数量 + shieldTime: number = 0; // 天师盾符 constructor(guildCode: string, guildName: string, guildCe: number) { this.guildCode = guildCode; @@ -241,23 +334,79 @@ export class WoodenHorse { this.guildCe = guildCe; } - calSpeed(events: Event[]) { - let speed = this.speed; + getCurWoodenHorse(events: Event[]) { + this.distance += (Date.now() - this.time) * this.speed; + let effectiveEvents = new Array(); for(let event of events) { - + if(!event.startTime && event.startDistance && this.distance > event.startDistance) { + let startTime = Date.now() - Math.floor((this.distance - event.startDistance) / this.speed); + event.setStartTime(startTime); // 距离生效的事件的实际生效时间,主要用于速度叠加顺序 + } + let isEffective = false; + if(event.startTime <= Date.now() && event.endTime > Date.now()) { + isEffective = true; + } else if (event.startDistance <= this.distance && event.endDistance > this.distance) { + isEffective = true; + } + if(isEffective) { + effectiveEvents.push(event); + } } - return speed; + effectiveEvents.sort((a, b) => a.startTime - b.startTime); + this.speed = this.memberCnt * 1; + for(let { id, count, endTime } of effectiveEvents) { + this.calEvent(id, count, endTime); + } + + return this; } - getWoodenHorse(events: Event[]) { - let newObj = new WoodenHorse(this.guildCode, this.guildName, this.guildCe); - newObj.speed = this.calSpeed(events); - newObj.durability = this.durability; - newObj.distance = this.distance; - newObj.time = this.time; - newObj.memberCnt = this.memberCnt; - newObj.members = this.members; - return newObj; + calEvent(id: number, count: number = 1, endTime?: number) { + let { effect } = gameData.raceActivityEvents.get(id); + + switch (id) { + case RACE_EVENT.LIANNU: + if (this.shieldTime > Date.now()) { + if (this.shield >= count) { + this.shield -= count; + } else { + this.durability -= (count - this.shield) * effect[0]; + } + } + break; + case RACE_EVENT.GUISHOUYINFU: + if (this.shieldTime > Date.now()) this.speed = 0; + break; + case RACE_EVENT.FENGCHE: + case RACE_EVENT.WUGUIBANYUNFU: + this.speed *= Math.pow(1 + effect[0] / 100, count); break; + case RACE_EVENT.LUDUN: + this.shield += count * effect[0]; break; + case RACE_EVENT.TIANSHIDUNFU: + this.shieldTime = endTime; break; + case RACE_EVENT.JIANSU_1: + this.speed *= 1 + effect[0]; break; + case RACE_EVENT.JIANSU_2: + this.speed += effect[0]; break; + case RACE_EVENT.HUIFU_1: + this.durability += effect[0]; break; + case RACE_EVENT.JIANSU_1: + this.speed *= Math.pow(1 - effect[0] / 100, count); break; + case RACE_EVENT.JIANSU_2: + this.speed -= effect[0]; break; + case RACE_EVENT.SHANGHAI_1: + this.durability -= effect[0]; break; + } + } + + + joinMember(roleId: string, roleName: string) { + if(this.members.findIndex(cur => cur.roleId == roleId) == -1) { + this.members.push({ roleId, roleName }); + this.speed++; + this.memberCnt++; + } + return this; } } @@ -268,9 +417,32 @@ export class Event { toGuild: string; startTime?: number; startDistance?: number; - endTimestamp?: number; + endTime?: number; endDistance?: number; - effect: number[]; + count: number = 1; + + constructor(id: number, fromGuild: string, toGuild: string, distance?: number, count?: number) { + let dicEvent = gameData.raceActivityEvents.get(id); + this.id = id; + this.fromGuild = fromGuild; + this.toGuild = toGuild; + + if(distance) { + this.startDistance = distance; + this.endDistance = this.startDistance + dicEvent.continueDistance; + } + if(dicEvent.effectTime) { + this.startTime = Date.now() + dicEvent.effectTime * 1000; + this.endTime = this.startTime + dicEvent.continueTime * 1000; + } + if(count) { + this.count = count; + } + } + + setStartTime(time: number) { + this.startTime = time; + } } export interface GuildGateRankParam { diff --git a/shared/domain/rank.ts b/shared/domain/rank.ts index e43c5d39c..4d77a4818 100644 --- a/shared/domain/rank.ts +++ b/shared/domain/rank.ts @@ -78,6 +78,17 @@ export class SimpleGuildRankParam { } } +export class SimpleGuildRankWithTimeParam extends SimpleGuildRankParam { + time: number; + durability: number; + + constructor(rank: number, code: string, name: string, num: number, time: number, durability: number) { + super(rank, code, name, num); + this.time = time; + this.durability = durability; + } +} + export class SimpleRoleRankParam { rank: number; roleId: string; diff --git a/shared/pubUtils/data.ts b/shared/pubUtils/data.ts index bd78d2c1d..97a2ff417 100644 --- a/shared/pubUtils/data.ts +++ b/shared/pubUtils/data.ts @@ -65,6 +65,10 @@ import { getCutDay } from "./timeUtil"; import { dicCityActivity } from "./dictionary/DicCityActivity"; import { dicChatAccuse } from "./dictionary/DicChatAccuse"; import { dicCityActivityReward } from "./dictionary/DicCityActivityReward"; +import { dicRaceActivity, dicRaceTypes } from './dictionary/DicRaceActivity'; +import { GUILDACTIVITY } from "./dicParam"; +import { decodeIdCntArrayStr } from "./util"; +import { GUILD_SELECT, RACE_EVENT_TYPE } from "../consts"; export const gameData = { blurprtCompose: dicBlueprtCompose, @@ -152,7 +156,10 @@ export const gameData = { guildAuction: dicGuildAuction, cityActivity: dicCityActivity, chatAccuse: dicChatAccuse, - cityActivityReward: dicCityActivityReward + cityActivityReward: dicCityActivityReward, + raceActivityEvents: dicRaceActivity, + raceTypes: dicRaceTypes, + raceActivityEncounter: decodeRaceActivityEncounter(), }; // 在此提供一些原先在gamedata中提供的方法,以便更方便获取gameData数据 @@ -490,4 +497,16 @@ export function getCityActivityRewards(type: number, guildRank: number, rank: nu return cur.guildRank == guildRank && (rank >= cur.min && (rank <= cur.max || cur.max == 0)); }); return dic?dic.honour: 0; +} + +function decodeRaceActivityEncounter() { + let str = GUILDACTIVITY.RACEACTIVITY_ENCOUNTER; + let map = decodeIdCntArrayStr(str, 1); + let newMap = new Map(); + let eventNum = 0; + for(let [key, value] of map) { + if(value == RACE_EVENT_TYPE.EVENT) eventNum ++; + newMap.set(parseInt(key), parseInt(value)); + } + return { events: newMap, eventNum }; } \ No newline at end of file diff --git a/shared/pubUtils/dicParam.ts b/shared/pubUtils/dicParam.ts index fd560414e..d853f1de0 100644 --- a/shared/pubUtils/dicParam.ts +++ b/shared/pubUtils/dicParam.ts @@ -98,13 +98,19 @@ export const GUILDACTIVITY = { GATEACTIVITY_GATEHP: 10000, // 城门血量 GATEACTIVITY_BOSS_DIFFICULT: '1&1.2|2&1.5', // boss类型&难度系数|boss类型&难度系数(1:小boss,2:大boss) RACEACTIVITY_DURABILITY_REWARD: 2, // 每剩余1%耐久度给予X点功勋 + RACEACTIVITY_NORMAL_ITEMS: '1&8&15|3&5&10|5&0&1', // 粮草先行普通道具 + RACEACTIVITY_EVENT_MEMBERCNT: 3, // 粮草先行随机道具获得人数 + RACEACTIVITY_EVENT_ITEMS: '2&1|4&1|6&1', // 粮草先行根据事件随机人可获得道具 }; -export const GUILDAUCTION = { - DIVIDENDRATE: 1, // 分红比例,1表示总金额 100% 分红 - DIVIDENDWEEKENDRATE: 0.2, // 额外分红,周末加成,0.2表示周围额外加成 20% 分红 +export const GUILD_AUCTION = { + DIVIDEND_RATE: 1, // 总金额分红比例,1表示总金额 100% 分红 + DIVIDEND_WEEKEND_RATE: 0.2, // 额外分红,周末加成,0.2表示周围额外加成 20% 分红 AUCTION_PRICE_RISE: 1.1, // 单次竞价价格上涨幅度,1.1表示竞拍每次价格上涨10% - AUCTION_BOSSEXPECT_MAX: 1000, // 演武台预期分红上限 - AUCTION_BOSSEXPECT_MIN: 200, // 演武台预期分红下限 - AUCTION_ACTIVITYEXPECT_MAX: 2000, // 军团活动预期分红上限 - AUCTION_ACTIVITYEXPECT_MIN: 500, // 军团活动预期分红下限 + AUCTION_BOSS_EXPECT_MAX: 1000, // 演武台预期分红上限 + AUCTION_BOSS_EXPECT_MIN: 200, // 演武台预期分红下限 + AUCTION_ACTIVITY_EXPECT_MAX: 2000, // 军团活动预期分红上限 + AUCTION_ACTIVITY_EXPECT_MIN: 500, // 军团活动预期分红下限 +}; +export const BROWSER_DEBUG = { + UNLIMITED_MOVEMENT: 0, // 无限行动 }; diff --git a/shared/pubUtils/dictionary/DicRaceActivity.ts b/shared/pubUtils/dictionary/DicRaceActivity.ts new file mode 100644 index 000000000..54c101ce2 --- /dev/null +++ b/shared/pubUtils/dictionary/DicRaceActivity.ts @@ -0,0 +1,46 @@ +// 粮草先行道具 +import { readJsonFile, parseNumberList } from '../util' +import { FILENAME } from '../../consts' +const _ = require('lodash'); + +export interface DicRaceActivity { + + // 粮草先行道具id + readonly id: number; + // 类型 1-道具 2-事件 + readonly type: number; + // 事件类型 1-好事件 2-坏事件 + readonly effectType: number; + // 效果值 + readonly effect: number[]; + // 持续时间 + readonly continueTime: number; + // 持续距离 + readonly continueDistance: number; + // 生效时间 + readonly effectTime: number; + +} + + +const str = readJsonFile(FILENAME.DIC_RACE_ACTIVITY); +let arr = JSON.parse(str); + +type KeysEnum = { [P in keyof Required]: true }; +const DicRaceKeys: KeysEnum = {id: true, type: true, effectType: true, effect: true, continueTime: true, continueDistance: true, effectTime: true}; + +export const dicRaceActivity = new Map(); +export const dicRaceTypes = new Map>(); + +arr.forEach(o => { + o.effectTime = o.effecttime; + o.effect = parseNumberList(o.effect); + dicRaceActivity.set(o.id, _.pick(o, Object.keys(DicRaceKeys))); + if(!dicRaceTypes.has(o.type)) { + dicRaceTypes.set(o.type, new Map()); + } + if(!dicRaceTypes.get(o.type).has(o.effectType)) { + dicRaceTypes.get(o.type).set(o.effectType, []); + } + dicRaceTypes.get(o.type).get(o.effectType).push(o.id); +}); \ 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 2408bc144..ae47a4ed6 100644 --- a/shared/resource/jsons/dic_zyz_cityActivity.json +++ b/shared/resource/jsons/dic_zyz_cityActivity.json @@ -3,8 +3,8 @@ "id": 1, "name": "汉中", "type": 1, - "preCity": 0, "nextCity": 7, + "preCity": 0, "difficult": 90, "warid": 7002, "hp": 20000 @@ -13,8 +13,8 @@ "id": 2, "name": "南中", "type": 1, - "preCity": 0, "nextCity": 7, + "preCity": 0, "difficult": 90, "warid": 7002, "hp": 20000 @@ -23,8 +23,8 @@ "id": 3, "name": "柴桑", "type": 1, - "preCity": 0, "nextCity": 8, + "preCity": 0, "difficult": 90, "warid": 7002, "hp": 20000 @@ -33,8 +33,8 @@ "id": 4, "name": "会稽", "type": 1, - "preCity": 0, "nextCity": 8, + "preCity": 0, "difficult": 90, "warid": 7002, "hp": 20000 @@ -43,8 +43,8 @@ "id": 5, "name": "太原", "type": 1, - "preCity": 0, "nextCity": 9, + "preCity": 0, "difficult": 90, "warid": 7002, "hp": 20000 @@ -53,8 +53,8 @@ "id": 6, "name": "巨鹿", "type": 1, - "preCity": 0, "nextCity": 9, + "preCity": 0, "difficult": 90, "warid": 7002, "hp": 20000 @@ -63,40 +63,40 @@ "id": 7, "name": "成都", "type": 2, - "preCity": "1&2", "nextCity": 10, + "preCity": "1&2", "difficult": 100, - "warid": 7002, + "warid": 7003, "hp": 30000 }, { "id": 8, "name": "建业", "type": 2, - "preCity": "3&4", "nextCity": 10, + "preCity": "3&4", "difficult": 100, - "warid": 7002, + "warid": 7003, "hp": 30000 }, { "id": 9, "name": "邺城", "type": 2, - "preCity": "5&6", "nextCity": 10, + "preCity": "5&6", "difficult": 100, - "warid": 7002, + "warid": 7003, "hp": 50000 }, { "id": 10, "name": "洛阳", "type": 3, - "preCity": "7&8&9", "nextCity": 0, + "preCity": "7&8&9", "difficult": 110, - "warid": 7002, + "warid": 7004, "hp": 50000 } ] \ No newline at end of file diff --git a/shared/resource/jsons/dic_zyz_gk_guildActivity.json b/shared/resource/jsons/dic_zyz_gk_guildActivity.json index cf574cc41..a3e8c3c98 100644 --- a/shared/resource/jsons/dic_zyz_gk_guildActivity.json +++ b/shared/resource/jsons/dic_zyz_gk_guildActivity.json @@ -16,11 +16,35 @@ "dispatchJsonId": 7002, "script_id": "S_7002", "warType": 10, - "gk_name": "诸侯混战", + "gk_name": "诸侯混战(小)", "bg_img_id": 7002, "lvLimted": 25, "turnLimted": 10, "victoryInfoInUI": "攻破城门", "loseInfoInUI": "我方全部阵亡" + }, + { + "war_id": 7003, + "dispatchJsonId": 7003, + "script_id": "S_7003", + "warType": 10, + "gk_name": "诸侯混战(中)", + "bg_img_id": 7003, + "lvLimted": 25, + "turnLimted": 10, + "victoryInfoInUI": "攻破城门", + "loseInfoInUI": "我方全部阵亡" + }, + { + "war_id": 7004, + "dispatchJsonId": 7004, + "script_id": "S_7004", + "warType": 10, + "gk_name": "诸侯混战(大)", + "bg_img_id": 7004, + "lvLimted": 25, + "turnLimted": 10, + "victoryInfoInUI": "攻破城门", + "loseInfoInUI": "我方全部阵亡" } ] \ No newline at end of file diff --git a/shared/resource/jsons/dic_zyz_guildActivity.json b/shared/resource/jsons/dic_zyz_guildActivity.json index f55f1be99..6a786de7e 100644 --- a/shared/resource/jsons/dic_zyz_guildActivity.json +++ b/shared/resource/jsons/dic_zyz_guildActivity.json @@ -2,9 +2,9 @@ { "id": 1, "name": "蛮夷入侵", - "openDay": "4", + "openDay": "", "duringTime": 900, - "startTime": 15, + "startTime": 16, "startMinute": 15, "countDown": 5, "warid": 7001, @@ -13,7 +13,7 @@ { "id": 2, "name": "诸侯混战", - "openDay": "2&6", + "openDay": "", "duringTime": 900, "startTime": 11, "startMinute": 48, @@ -24,9 +24,9 @@ { "id": 3, "name": "粮草先行", - "openDay": "1&5", - "duringTime": 600, - "startTime": 11, + "openDay": "1&5&6", + "duringTime": 600000, + "startTime": 9, "startMinute": 48, "countDown": 5, "warid": 0, diff --git a/shared/resource/jsons/dic_zyz_raceActivity.json b/shared/resource/jsons/dic_zyz_raceActivity.json new file mode 100644 index 000000000..ee013e085 --- /dev/null +++ b/shared/resource/jsons/dic_zyz_raceActivity.json @@ -0,0 +1,145 @@ +[ + { + "id": 1, + "name": "连弩", + "info": "每个造成0.2%的耐久度伤害", + "type": 0, + "effectType": 0, + "effect": "0.2&", + "continueTime": 0, + "continueDistance": 0, + "effecttime": 5 + }, + { + "id": 2, + "name": "鬼手阴符", + "info": "使用后敌方停止移动,持续5秒", + "type": 0, + "effectType": 0, + "effect": "5&", + "continueTime": 5, + "continueDistance": 0, + "effecttime": 5 + }, + { + "id": 3, + "name": "风车", + "info": "每个增加2%速度,持续5秒", + "type": 0, + "effectType": 0, + "effect": "2&5", + "continueTime": 5, + "continueDistance": 0, + "effecttime": 5 + }, + { + "id": 4, + "name": "五鬼搬运符", + "info": "使用后增加40%速度,持续5秒", + "type": 0, + "effectType": 0, + "effect": "40&5", + "continueTime": 5, + "continueDistance": 0, + "effecttime": 5 + }, + { + "id": 5, + "name": "橹盾", + "info": "使用后抵挡20次连弩攻击", + "type": 0, + "effectType": 0, + "effect": "20&", + "continueTime": 0, + "continueDistance": 0, + "effecttime": 5 + }, + { + "id": 6, + "name": "天师盾符", + "info": "使用后免疫地方攻击,持续10秒", + "type": 0, + "effectType": 0, + "effect": "10&", + "continueTime": 10, + "continueDistance": 0, + "effecttime": 0 + }, + { + "id": 7, + "name": "加速事件", + "info": "神秘符纸,加速20%", + "type": 2, + "effectType": 1, + "effect": "20&", + "continueTime": 0, + "continueDistance": 100, + "effecttime": 0 + }, + { + "id": 8, + "name": "加速事件", + "info": "将士饱食,士气高昂,加速1.5m/S", + "type": 2, + "effectType": 1, + "effect": "1.5&", + "continueTime": 0, + "continueDistance": 100, + "effecttime": 0 + }, + { + "id": 9, + "name": "恢复事件", + "info": "巧匠修补,耐久度恢复15%", + "type": 2, + "effectType": 1, + "effect": "15&", + "continueTime": 0, + "continueDistance": 0, + "effecttime": 0 + }, + { + "id": 10, + "name": "减速事件", + "info": "蜀道泥泞,降速20%", + "type": 2, + "effectType": 2, + "effect": "20&", + "continueTime": 0, + "continueDistance": 100, + "effecttime": 0 + }, + { + "id": 11, + "name": "减速事件", + "info": "栈道被破坏,降速1.5m/s", + "type": 2, + "effectType": 2, + "effect": "1.5&", + "continueTime": 0, + "continueDistance": 100, + "effecttime": 0 + }, + { + "id": 12, + "name": "伤害事件", + "info": "滚石袭击,耐久度降低25%", + "type": 2, + "effectType": 2, + "effect": "25&", + "continueTime": 0, + "continueDistance": 0, + "effecttime": 0 + }, + { + "id": 13, + "name": "添加道具事件", + "info": "增加一定的道具", + "type": 1, + "effectType": 0, + "effect": "&", + "continueTime": 0, + "continueDistance": 0, + "effecttime": 0 + } +] \ No newline at end of file