diff --git a/game-server/app/servers/guild/handler/gvgBattleHandler.ts b/game-server/app/servers/guild/handler/gvgBattleHandler.ts index 67ac39c10..3bfc0e656 100644 --- a/game-server/app/servers/guild/handler/gvgBattleHandler.ts +++ b/game-server/app/servers/guild/handler/gvgBattleHandler.ts @@ -7,19 +7,23 @@ import { Application, BackendSession, ChannelService, HandlerService, pinus } fr import { resResult, genCode } from "../../../pubUtils/util"; import { GVGLeagueModel } from '../../../db/GVGLeague'; import { checkGVGPeriod, getGroupIdOfServer, getGVGConfig, getGVGPeriodData, getGVGServerType } from '../../../services/gvg/gvgService'; -import { addBattleRankScore, calBattleScoreByCe, checkAreaIsInCity, checkGVGBattleStart, checkMoveStatus, getBattleRanks, getBirthAreaOfCity, getGVGWarId, getOppHeroes, initRobots, pushTeamMoveMessage, teamBreak } from '../../../services/gvg/gvgBattleService'; +import { addBattleRankScore, calBattleScoreByCe, checkAreaIsInCity, checkGVGBattleStart, checkMoveStatus, getBattleRanks, getBirthAreaOfCity, getGVGWarId, getOppHeroes, getTechReviveMinus, initRobots, pushTeamMoveMessage } from '../../../services/gvg/gvgBattleService'; import { getGVGBattleData } from '../../../services/gvg/gvgBattleMemory'; import { GVGBattleRecModel } from '../../../db/GVGBattleRec'; import { getFightTimeByPeriod } from '../../../services/gvg/gvgFightService'; -import { gameData } from '../../../pubUtils/data'; +import { gameData, getReviveGold } from '../../../pubUtils/data'; import { getAllServerName } from '../../../services/redisService'; import { checkBattleHeroesByHid } from '../../../services/normalBattleService'; import { SaveTeamParam, SaveTeamUpdateParam } from '../../../domain/gvgField/gvgDb'; -import { STATUS } from '../../../consts'; +import { GVG_ITEM, ITEM_CHANGE_REASON, STATUS } from '../../../consts'; import { GVGHeroInfo } from '../../../domain/dbGeneral'; import { ArtifactModel } from '../../../db/Artifact'; import { getHeroesAttributes } from '../../../services/playerCeService'; import { addRoleToAreaChannel, addRoleToAreaTeamChannel, addRoleToGVGCityChannel, leaveGVGAreaChannel, leaveGVGAreaTeamChannel, leaveGVGCityTeamChannel } from '../../../services/chatChannelService'; +import { nowSeconds } from '../../../pubUtils/timeUtil'; +import { GVGUserItemModel } from '../../../db/GVGUserItem'; +import { handleGVGCost } from '../../../services/gvg/gvgItemService'; +import { getGoldObject, handleCost } from '../../../services/role/rewardService'; export default function (app: Application) { new HandlerService(app, {}); @@ -294,7 +298,7 @@ export class GVGBattleHandler { let groupId = await getGroupIdOfServer(serverId); let serverType = await getGVGServerType(serverId); - let myTeam = await GVGTeamModel.findByTeamCode(roleId, teamCode); + let myTeam = await GVGTeamModel.findMyTeamByCode(roleId, teamCode); if(!myTeam) return resResult(STATUS.GVG_TEAM_NOT_FOUND); if(myTeam.cityId != cityId) return resResult(STATUS.GVG_BATTLE_IS_NOT_IN_CITY); @@ -331,7 +335,7 @@ export class GVGBattleHandler { let groupId = await getGroupIdOfServer(serverId); let serverType = await getGVGServerType(serverId); - let team = await GVGTeamModel.findByTeamCode(roleId, teamCode); + let team = await GVGTeamModel.findMyTeamByCode(roleId, teamCode); let checkResult = checkMoveStatus(team, cityId, areaId); if(checkResult.code != 0) return resResult(checkResult); @@ -355,7 +359,7 @@ export class GVGBattleHandler { let groupId = await getGroupIdOfServer(serverId); let serverType = await getGVGServerType(serverId); - let team = await GVGTeamModel.findByTeamCode(roleId, teamCode); + let team = await GVGTeamModel.findMyTeamByCode(roleId, teamCode); if(!team) return resResult(STATUS.GVG_BATTLE_TEAM_NOT_FOUND); if(team.cityId != cityId && team.areaId != areaId) return resResult(STATUS.GVG_BATTLE_IS_NOT_IN_CITY); @@ -379,7 +383,7 @@ export class GVGBattleHandler { let groupId = await getGroupIdOfServer(serverId); let serverType = await getGVGServerType(serverId); - let myTeam = await GVGTeamModel.findByTeamCode(roleId, teamCode); + let myTeam = await GVGTeamModel.findMyTeamByCode(roleId, teamCode); if(!myTeam) return resResult(STATUS.GVG_TEAM_NOT_FOUND); let dicAreaPoint = gameData.gvgAreaPoint.get(pointId); @@ -403,7 +407,7 @@ export class GVGBattleHandler { let groupId = await getGroupIdOfServer(serverId); let serverType = await getGVGServerType(serverId); - let myTeam = await GVGTeamModel.findByTeamCode(roleId, teamCode); + let myTeam = await GVGTeamModel.findMyTeamByCode(roleId, teamCode); if(!myTeam) return resResult(STATUS.GVG_TEAM_NOT_FOUND); let dicAreaPoint = gameData.gvgAreaPoint.get(pointId); if(dicAreaPoint.areaId != myTeam.areaId) return resResult(STATUS.GVG_POINT_NOT_AREA); @@ -468,8 +472,8 @@ export class GVGBattleHandler { let { win, fail } = gameData.gvgBattleDurabilityMinus; let attackScore = calBattleScoreByCe(isSuccess, attackTeam.lineupCe); let defenseScore = calBattleScoreByCe(!isSuccess, defenseTeam.lineupCe); - attackTeam = await GVGTeamModel.battleEndAttack(attackTeam.teamCode, isSuccess? -win: -fail, attackScore, getBirthAreaOfCity(city, attackTeam.leagueCode)); - defenseTeam = await GVGTeamModel.battleEndDefense(defenseTeam.teamCode, isSuccess? -fail: -win, defenseScore, getBirthAreaOfCity(city, defenseTeam.leagueCode)); + attackTeam = await GVGTeamModel.battleEndAttack(attackTeam.teamCode, isSuccess? -win: -fail, attackScore, getBirthAreaOfCity(city, attackTeam.leagueCode), await getTechReviveMinus(configId, attackTeam.leagueCode)); + defenseTeam = await GVGTeamModel.battleEndDefense(defenseTeam.teamCode, isSuccess? -fail: -win, defenseScore, getBirthAreaOfCity(city, defenseTeam.leagueCode), await getTechReviveMinus(configId, defenseTeam.leagueCode)); if(defenseTeam.curTeamBreak && defenseTeam.originPointId > 0 && !attackTeam.curTeamBreak) { // 打败的对手原来占领着一个位置,现在这个位置是你的了 attackTeam = await GVGTeamModel.settlePoint(attackTeam.teamCode, defenseTeam.originPointId); } @@ -490,6 +494,7 @@ export class GVGBattleHandler { // teamCode: 要使用道具的队伍 async useItem(msg: { cityId: number, itemId: number, teamCode: string }, session: BackendSession) { const { itemId, teamCode } = msg; + // const targetTeam = await GVGTeamModel.findByCode(teamCode); // ! 检查道具是否存在 // ! 检查道具是否可以使用在该队伍 const team = await GVGTeamModel.findOneAndUpdate({ teamCode }, {}).lean(); @@ -499,11 +504,38 @@ export class GVGBattleHandler { // 复活队伍 async reviveTeam(msg: { cityId: number, teamCode: string }, session: BackendSession) { + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const guildCode = session.get('guildCode'); + const { teamCode } = msg; - // ! 检查该队伍是否可以复活,可以的话更新队伍状态 - const team = await GVGTeamModel.findOneAndUpdate({ teamCode }, {}).lean(); + let { configId, period } = getGVGPeriodData(); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let team = await GVGTeamModel.findMyTeamByCode(roleId, teamCode); + if(!team) return resResult(STATUS.GVG_TEAM_NOT_FOUND); + if(team.restartTime < nowSeconds()) return resResult(STATUS.GVG_TEAM_NOT_NEED_REVIVE); + + let userData = await GVGUserDataModel.findByRole(configId, myLeague.leagueCode, roleId); + let reviveCnt = userData?.reviveCnt||0; + + const hasItem = await GVGUserItemModel.checkItemCnt(configId, myLeague.leagueCode, roleId, GVG_ITEM.REVIVE_COIN, 1); + if(hasItem) { + const costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, [{ id: GVG_ITEM.REVIVE_COIN, count: 1 }], [], ITEM_CHANGE_REASON.GVG_REVIVE); + if(!costResult) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); + } else { + let gold = getReviveGold(reviveCnt + 1); + const costResult = await handleCost(roleId, sid, [getGoldObject(gold)], ITEM_CHANGE_REASON.GVG_REVIVE); + if(!costResult) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); + userData = await GVGUserDataModel.addReviveCnt(configId, myLeague.leagueCode, roleId, 1); + reviveCnt = userData?.reviveCnt||0; + } + team = await GVGTeamModel.reviveTeam(teamCode); + // 更新成功返回队伍信息 - return resResult(STATUS.SUCCESS, { team }); + return resResult(STATUS.SUCCESS, { reviveCnt, curTeam: new MyTeamInfo(team) }); } // 获取战报 diff --git a/game-server/app/services/gvg/gvgBattleService.ts b/game-server/app/services/gvg/gvgBattleService.ts index 760f06981..ec522f59b 100644 --- a/game-server/app/services/gvg/gvgBattleService.ts +++ b/game-server/app/services/gvg/gvgBattleService.ts @@ -118,11 +118,19 @@ export function calBattleScoreByCe(isSuccess: boolean, lineupCe: number) { return isSuccess? winScore: 0; } -export async function teamBreak(city: GVGCityType, team: GVGTeamType) { - if(team.durability > 0) return team - let areaId = getBirthAreaOfCity(city, team.leagueCode); - team = await GVGTeamModel.teamBreak(team.teamCode, team.isRobot, team.maxDurability, areaId); - return team; +export async function getTechReviveMinus(configId: number, leagueCode: string) { + let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, leagueCode); + let minusCd = 0; + let activeTech = leaguePrepare?.activeTech||[]; + for(let techId of activeTech) { + let dicTech = gameData.gvgTech.get(techId); + if(dicTech && dicTech.type == GVG_TECH_TYPE.BATTLE_REVIVE_GAP) { + minusCd = dicTech.param[0]; + } + } + let cd = GVG.GVG_DEFAULT_REVIVE_CD - minusCd; + if(cd < 0) cd = 0; + return cd; } export function getGVGWarId(defenseTeam: GVGTeamType) { diff --git a/shared/consts/constModules/gvgConst.ts b/shared/consts/constModules/gvgConst.ts index 91f738e80..8d3f4b780 100644 --- a/shared/consts/constModules/gvgConst.ts +++ b/shared/consts/constModules/gvgConst.ts @@ -69,13 +69,14 @@ export enum GVG_ITEM_TYPE { } export enum GVG_ITEM { - WHEAT = 1, // 小麦 - CORN = 2, // 粟米 - RICE = 3, // 水稻 - PRODUCE_COIN = 10, // 内政令 - FIGHT_COIN = 11, // 征战令 - BATTLE_FEAT = 12, // 战功 - KNIFE = 14, // 诸葛连弩 + WHEAT = 1, // 小麦 + CORN = 2, // 粟米 + RICE = 3, // 水稻 + PRODUCE_COIN = 10, // 内政令 + FIGHT_COIN = 11, // 征战令 + BATTLE_FEAT = 12, // 战功 + REVIVE_COIN = 13, // 复活令 + KNIFE = 14, // 诸葛连弩 } export enum GVG_RESOURCE_TYPE { diff --git a/shared/consts/constModules/sysConst.ts b/shared/consts/constModules/sysConst.ts index 2587a3ef2..f265ad3d5 100644 --- a/shared/consts/constModules/sysConst.ts +++ b/shared/consts/constModules/sysConst.ts @@ -1128,6 +1128,7 @@ export enum ITEM_CHANGE_REASON { GVG_VESTIGE_END = 171, // gvg征战中原挑战 GVG_VESTIGE_RECEIVE_RANK = 172, // gvg征战中原领取排行榜奖励 GVG_TECH_SEND_KNIFE = 173, // gvg点科技树发放诸葛连弩 + GVG_REVIVE = 174, // gvg复活队伍 } export enum TA_EVENT { diff --git a/shared/consts/statusCode.ts b/shared/consts/statusCode.ts index 9337d354e..f4c58caa5 100644 --- a/shared/consts/statusCode.ts +++ b/shared/consts/statusCode.ts @@ -378,6 +378,7 @@ export const STATUS = { GVG_TEAM_NOT_SAME_AREA: { code: 21415, simStr: '对方不在同一个区域内' }, GVG_POINT_HAS_SETTLED: { code: 21416, simStr: '该据点已经有其他队伍驻守' }, GVG_POINT_NOT_AREA: { code: 21417, simStr: '您不在该积分点所在区域' }, + GVG_TEAM_NOT_NEED_REVIVE: { code: 21418, simStr: '此队伍不需要复活' }, // 通用 30000 - 30099 DIC_DATA_NOT_FOUND: { code: 30000, simStr: '数据表未找到' }, diff --git a/shared/db/GVGTeam.ts b/shared/db/GVGTeam.ts index 649aa2d15..9473f4cb7 100644 --- a/shared/db/GVGTeam.ts +++ b/shared/db/GVGTeam.ts @@ -150,8 +150,14 @@ export default class GVGTeam extends BaseModel { return teams; } - // 获取我的编队 - public static async findByTeamCode(roleId: string, teamCode: string, select = '') { + // 获取某个玩家的某个的编队 + public static async findMyTeamByCode(roleId: string, teamCode: string, select = '') { + const res: GVGTeamType = await GVGTeamModel.findOne({ roleId, teamCode }).select(select).lean(); + return res; + } + + // 获取编队 + public static async findByCode(roleId: string, teamCode: string, select = '') { const res: GVGTeamType = await GVGTeamModel.findOne({ roleId, teamCode }).select(select).lean(); return res; } @@ -256,31 +262,31 @@ export default class GVGTeam extends BaseModel { } // 结算挑战方 - public static async battleEndAttack(teamCode: string, hpInc: number, playerScoreInc: number, rebirthAreaId: number) { + public static async battleEndAttack(teamCode: string, hpInc: number, playerScoreInc: number, rebirthAreaId: number, reviveCd: number) { let team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $inc: { durability: hpInc, score: playerScoreInc } }, { new: true }).lean(); if(team.durability <= 0) { let originPointId = team.pointId; - team = await GVGTeamModel.teamBreak(teamCode, team.isRobot, team.maxDurability, rebirthAreaId); + team = await GVGTeamModel.teamBreak(teamCode, team.isRobot, team.maxDurability, rebirthAreaId, reviveCd); team.originPointId = originPointId; } return team; } // 结算防守方 - public static async battleEndDefense(teamCode: string, hpInc: number, playerScoreInc: number, rebirthAreaId: number) { + public static async battleEndDefense(teamCode: string, hpInc: number, playerScoreInc: number, rebirthAreaId: number, reviveCd: number) { let team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { defenseTime: nowSeconds() + GVG.GVG_DEFAULT_DEFENSE_CD, lockTime: 0, lockTeamCode: '' }, $inc: { durability: hpInc, score: playerScoreInc } }, { new: true }).lean(); if(team.durability <= 0) { let originPointId = team.pointId; - team = await GVGTeamModel.teamBreak(teamCode, team.isRobot, team.maxDurability, rebirthAreaId); + team = await GVGTeamModel.teamBreak(teamCode, team.isRobot, team.maxDurability, rebirthAreaId, reviveCd); team.originPointId = originPointId; } return team; } // 队伍进入修整器 - public static async teamBreak(teamCode: string, isRobot: boolean, maxDurability: number, areaId: number) { + public static async teamBreak(teamCode: string, isRobot: boolean, maxDurability: number, areaId: number, reviveCd: number) { if(!isRobot) { - const team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { restartTime: nowSeconds() + GVG.GVG_DEFAULT_DEFENSE_CD, stopMoveTime: nowSeconds(), areaId, durability: maxDurability } }, { new: true }).lean(); + const team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { restartTime: nowSeconds() - reviveCd, stopMoveTime: nowSeconds(), areaId, durability: maxDurability } }, { new: true }).lean(); team.curTeamBreak = true; return team; } else { @@ -332,6 +338,11 @@ export default class GVGTeam extends BaseModel { return team; } + // 复活 + public static async reviveTeam(teamCode: string) { + let team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { restartTime: 0 } }, { new: true }).lean(); + return team; + } } export const GVGTeamModel = getModelForClass(GVGTeam); diff --git a/shared/db/GVGUserData.ts b/shared/db/GVGUserData.ts index c4c7c4b89..199f9bcca 100644 --- a/shared/db/GVGUserData.ts +++ b/shared/db/GVGUserData.ts @@ -79,6 +79,9 @@ export default class GVGUserData extends BaseModel { @prop({ required: false }) cityId: number; // 城池id + @prop({ required: false }) + reviveCnt: number; // 城池id + public static async findByRole(configId: number, leagueCode: string, roleId: string) { const result: GVGUserDataType = await GVGUserDataModel.findOneAndUpdate({ configId, leagueCode, roleId }, {}, { new: true, upsert: true}).lean(); return result; @@ -130,6 +133,11 @@ export default class GVGUserData extends BaseModel { return result; } + public static async addReviveCnt(configId: number, leagueCode: string, roleId: string, cnt: number) { + const result: GVGUserDataType = await GVGUserDataModel.findOneAndUpdate({ configId, leagueCode, roleId }, { $inc: { reviveCnt: cnt } }, { new: true, upsert: true}).lean(); + return result; + } + } export const GVGUserDataModel = getModelForClass(GVGUserData); diff --git a/shared/domain/gvgField/returnData.ts b/shared/domain/gvgField/returnData.ts index f5f189f5d..fed561085 100644 --- a/shared/domain/gvgField/returnData.ts +++ b/shared/domain/gvgField/returnData.ts @@ -42,6 +42,7 @@ class LeaguePlayerData { // 奖励相关 receivedLv: number = 0; // 奖励领到几级 tasks: GVGTask[] = []; // 如果没有达成的任务就不放在这个数组里面 + reviveCnt: number = 0; // 使用元宝复活的次数 } class LeagueResource { @@ -129,6 +130,7 @@ export class GVGMainData { if(userData) { this.myInfo.job = userData?.job||0; this.myInfo.receivedLv = userData?.receivedLv||0; + this.myInfo.reviveCnt = userData?.reviveCnt||0; } this.myInfo.tasks = tasks; } diff --git a/shared/pubUtils/data.ts b/shared/pubUtils/data.ts index 64b309745..fc1f76e23 100644 --- a/shared/pubUtils/data.ts +++ b/shared/pubUtils/data.ts @@ -337,6 +337,7 @@ export const gameData = { gvgBattleDurabilityMinus: { win: 0, fail: 0 }, gvgTeamDurability: new Map(), gvgPointByAreaId: dicGVGPointsByAreaId, + gvgReviveGold: new Map(), }; // 在此提供一些原先在gamedata中提供的方法,以便更方便获取gameData数据 @@ -1230,6 +1231,21 @@ function parseGVGTeamDurability() { } +function parseGVGReviveCoin() { + let arr = decodeArrayListStr(param.GVG.GVG_REVIVE_GOLD); + for(let [_cnt, _gold] of arr) { + let cnt = parseInt(_cnt); + let gold = parseInt(_gold); + gameData.gvgReviveGold.set(cnt, gold); + gameData.gvgReviveGold.set('max', gold); + } +} + +export function getReviveGold(cnt: number) { + if(gameData.gvgReviveGold.has(cnt)) return gameData.gvgReviveGold.get(cnt)||0; + return gameData.gvgReviveGold.get('max')||0; +} + // 初始加载 function initDatas() { parseDicParam(); @@ -1255,6 +1271,7 @@ function parseDicParam() { parseGVGVestigeCnt(); parseGVGDurabilityMinus(); parseGVGTeamDurability(); + parseGVGReviveCoin(); } /**