diff --git a/game-server/app/servers/guild/handler/gvgBattleHandler.ts b/game-server/app/servers/guild/handler/gvgBattleHandler.ts index 3bfc0e656..ca9467cc0 100644 --- a/game-server/app/servers/guild/handler/gvgBattleHandler.ts +++ b/game-server/app/servers/guild/handler/gvgBattleHandler.ts @@ -7,7 +7,7 @@ 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, getTechReviveMinus, initRobots, pushTeamMoveMessage } from '../../../services/gvg/gvgBattleService'; +import { addBattleRankScore, battleEndSendMessage, calBattleScoreByCe, checkAreaIsInCity, checkGVGBattleStart, checkMoveStatus, getBattleRanks, getBirthAreaOfCity, getGVGWarId, getOppHeroes, getTechKnifeHurt, getTechReviveMinus, initRobots, pushTeamMoveMessage } from '../../../services/gvg/gvgBattleService'; import { getGVGBattleData } from '../../../services/gvg/gvgBattleMemory'; import { GVGBattleRecModel } from '../../../db/GVGBattleRec'; import { getFightTimeByPeriod } from '../../../services/gvg/gvgFightService'; @@ -329,6 +329,7 @@ export class GVGBattleHandler { // areaId: 要移动的目标据点 id async startMove(msg: { cityId: number, areaId: number, teamCode: string }, session: BackendSession) { const roleId = session.get('roleId'); + const sid = session.get('sid'); const serverId = session.get('serverId'); const { areaId, cityId, teamCode } = msg; @@ -345,6 +346,7 @@ export class GVGBattleHandler { let teamObj = getGVGBattleData(groupId, serverType); teamObj.move(teamCode, areaId, team.fromAreaId, team.startMoveTime, team.stopMoveTime); + await addRoleToAreaTeamChannel(roleId, groupId, serverType, areaId, sid); await pushTeamMoveMessage(team); return resResult(STATUS.SUCCESS, { areaId, cityId, stopMoveTime: team.stopMoveTime }); } @@ -353,6 +355,7 @@ export class GVGBattleHandler { // areaId: 移动到的目标据点 id async stopMove(msg: { cityId: number, areaId: number, teamCode: string }, session: BackendSession) { const roleId = session.get('roleId'); + const sid = session.get('sid'); const serverId = session.get('serverId'); const { areaId, cityId, teamCode } = msg; @@ -368,6 +371,8 @@ export class GVGBattleHandler { let teamObj = getGVGBattleData(groupId, serverType); teamObj.move(teamCode, areaId, 0, team.startMoveTime, team.stopMoveTime); + await leaveGVGAreaTeamChannel(roleId, sid); + await addRoleToAreaTeamChannel(roleId, groupId, serverType, areaId, sid); return resResult(STATUS.SUCCESS, { areaId, cityId, curTeam: new MyTeamInfo(team) }); } @@ -470,46 +475,85 @@ 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), await getTechReviveMinus(configId, attackTeam.leagueCode)); - defenseTeam = await GVGTeamModel.battleEndDefense(defenseTeam.teamCode, isSuccess? -fail: -win, defenseScore, getBirthAreaOfCity(city, defenseTeam.leagueCode), await getTechReviveMinus(configId, defenseTeam.leagueCode)); + attackTeam = await GVGTeamModel.battleEndAttack(attackTeam.teamCode, isSuccess? -win: -fail, getBirthAreaOfCity(city, attackTeam.leagueCode), await getTechReviveMinus(configId, attackTeam.leagueCode)); + defenseTeam = await GVGTeamModel.battleEndDefense(defenseTeam.teamCode, isSuccess? -fail: -win, 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); } - await addBattleRankScore(attackTeam, attackScore); - await addBattleRankScore(defenseTeam, defenseScore); + if(defenseTeam.curTeamBreak) { + let attackScore = calBattleScoreByCe(isSuccess, defenseTeam.lineupCe); + await addBattleRankScore(attackTeam, attackScore); + } // 更新内存 let teamObj = getGVGBattleData(groupId, serverType); teamObj.battleEnd([attackTeam, defenseTeam]); // 更新rec await GVGBattleRecModel.battleEnd(battleCode, isSuccess); - + await battleEndSendMessage(groupId, serverType, cityId, defenseTeam, attackTeam); return resResult(STATUS.SUCCESS, { curTeam: new MyTeamInfo(attackTeam) }); } // 使用道具 // 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(); - // ! 根据 item 使用效果更新 team - return resResult(STATUS.SUCCESS, { team }); + async useItem(msg: { cityId: number, itemId: number, teamCode: string, oppoTeamCode: string }, session: BackendSession) { + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const guildCode = session.get('guildCode'); + const serverId = session.get('serverId'); + const { cityId, itemId, teamCode, oppoTeamCode } = msg; + + if(itemId != GVG_ITEM.KNIFE) return resResult(STATUS.GVG_ITEM_CANNOT_USE); + + let { configId, period } = getGVGPeriodData(); + // if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); // TODO 测试临时注 + + let groupId = await getGroupIdOfServer(serverId); + let serverType = await getGVGServerType(serverId); + + let { attackTeam, defenseTeam } = await GVGTeamModel.findBattleTeams(teamCode, oppoTeamCode); + let checkStatus = checkGVGBattleStart(roleId, attackTeam, defenseTeam); + if(checkStatus.code != 0) return resResult(checkStatus); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, [{ id: GVG_ITEM.KNIFE, count: 1 }], [], ITEM_CHANGE_REASON.GVG_USE_ITEM); + if(!costResult) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); + + let city = await GVGCityModel.findByCityId(configId, groupId, serverType, cityId); + if (!city) return resResult(STATUS.GVG_CITY_NOT_FOUND); + + defenseTeam = await GVGTeamModel.battleEndDefense(teamCode, await getTechKnifeHurt(configId, attackTeam.leagueCode), 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); + } + if(defenseTeam.curTeamBreak) { + let attackScore = calBattleScoreByCe(true, defenseTeam.lineupCe); + await addBattleRankScore(attackTeam, attackScore); + } + + // 更新内存 + let teamObj = getGVGBattleData(groupId, serverType); + teamObj.battleEnd([attackTeam, defenseTeam]); + + await battleEndSendMessage(groupId, serverType, cityId, defenseTeam, attackTeam); + + return resResult(STATUS.SUCCESS, { curTeam: new MyTeamInfo(attackTeam) }); } // 复活队伍 async reviveTeam(msg: { cityId: number, teamCode: string }, session: BackendSession) { const roleId = session.get('roleId'); const sid = session.get('sid'); + const serverId = session.get('serverId'); const guildCode = session.get('guildCode'); const { teamCode } = msg; let { configId, period } = getGVGPeriodData(); + let groupId = await getGroupIdOfServer(serverId); + let serverType = await getGVGServerType(serverId); let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); @@ -534,6 +578,10 @@ export class GVGBattleHandler { } team = await GVGTeamModel.reviveTeam(teamCode); + // 更新内存 + let teamObj = getGVGBattleData(groupId, serverType); + teamObj.battleEnd([team]); + // 更新成功返回队伍信息 return resResult(STATUS.SUCCESS, { reviveCnt, curTeam: new MyTeamInfo(team) }); } diff --git a/game-server/app/services/checkParam.ts b/game-server/app/services/checkParam.ts index 01a0e10d5..55cb26038 100644 --- a/game-server/app/services/checkParam.ts +++ b/game-server/app/services/checkParam.ts @@ -1498,8 +1498,8 @@ export function checkRouteParam(route: string, msg: any) { } case "guild.gvgBattleHandler.useItem": { - if(!checkNaturalNumbers(msg.itemId)) return false; - if(!checkNaturalStrings(msg.teamCode)) return false; + if(!checkNaturalNumbers(msg.cityId, msg.itemId)) return false; + if(!checkNaturalStrings(msg.teamCode, msg.oppoTeamCode)) return false; break; } case "guild.gvgBattleHandler.reviveTeam": diff --git a/game-server/app/services/gvg/gvgBattleService.ts b/game-server/app/services/gvg/gvgBattleService.ts index ec522f59b..70c8bba32 100644 --- a/game-server/app/services/gvg/gvgBattleService.ts +++ b/game-server/app/services/gvg/gvgBattleService.ts @@ -17,7 +17,7 @@ import { dispatch } from "../../pubUtils/dispatcher"; import { Rank } from "../rankService"; import { LeagueRankInfo, RoleRankInfo } from "../../domain/rank"; import { findKeys, getAllServerName } from "../redisService"; -import { sendMessageToChannel, sendMessageToCityWithSuc, sendMessageToGVGAreaByTeamWithSuc, sendMessageToGVGAreaWithSuc, sendMessageToGVGCityWithSuc } from "../pushService"; +import { sendMessageToGVGAreaByTeamWithSuc, sendMessageToGVGAreaWithSuc, sendMessageToGVGCityWithSuc } from "../pushService"; import { sendMailToLeagueByContent } from "../mailService"; @@ -118,6 +118,7 @@ export function calBattleScoreByCe(isSuccess: boolean, lineupCe: number) { return isSuccess? winScore: 0; } +// 复活cd export async function getTechReviveMinus(configId: number, leagueCode: string) { let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, leagueCode); let minusCd = 0; @@ -125,7 +126,7 @@ export async function getTechReviveMinus(configId: number, leagueCode: string) { 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]; + minusCd += dicTech.param[0]; } } let cd = GVG.GVG_DEFAULT_REVIVE_CD - minusCd; @@ -133,6 +134,20 @@ export async function getTechReviveMinus(configId: number, leagueCode: string) { return cd; } +// 诸葛连弩的伤害 +export async function getTechKnifeHurt(configId: number, leagueCode: string) { + let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, leagueCode); + let hurt = 0; + let activeTech = leaguePrepare?.activeTech||[]; + for(let techId of activeTech) { + let dicTech = gameData.gvgTech.get(techId); + if(dicTech && dicTech.type == GVG_TECH_TYPE.BATTLE_ITEM_KNIFE) { + if(dicTech.param[2] > hurt) hurt = dicTech.param[2]; + } + } + return hurt +} + export function getGVGWarId(defenseTeam: GVGTeamType) { if(!defenseTeam.isRobot) return GVG.GVG_CITY_BGMAP_GKID; // 玩家防守地图 if(!defenseTeam.isCatapult) return GVG.GVG_CATAPULT_WARJSON; // 投石车使用 @@ -369,9 +384,10 @@ export async function gvgBattleEnd() { // —————————— 推送相关 —————————— // // 推送 export async function battleEndSendMessage(groupId: number, serverType: number, cityId: number, defenseTeam: GVGTeamType, attackTeam: GVGTeamType) { + let areaId = defenseTeam.curTeamBreak? defenseTeam.fromAreaId: defenseTeam.areaId; // 推送伤害 - await sendMessageToGVGAreaByTeamWithSuc(groupId, serverType, defenseTeam.areaId, PUSH_ROUTE.GVG_TEAM_ATTACKED, { - cityId, areaId: defenseTeam.areaId, attackType: 3, teams: [new GVGTeamInList(defenseTeam), new GVGTeamInList(attackTeam)] + await sendMessageToGVGAreaByTeamWithSuc(groupId, serverType, areaId, PUSH_ROUTE.GVG_TEAM_ATTACKED, { + cityId, areaId, attackType: 3, teams: [new GVGTeamInList(defenseTeam), new GVGTeamInList(attackTeam)] }); await pushTeamBeHurtMessage(defenseTeam, attackTeam); await pushTeamBeHurtMessage(attackTeam); @@ -381,15 +397,15 @@ export async function battleEndSendMessage(groupId: number, serverType: number, export async function pushTeamBeHurtMessage(team: GVGTeamType, replaceTeam?: GVGTeamType) { if(team.curTeamBreak && team.originPointId > 0) { - await sendMessageToGVGAreaByTeamWithSuc(team.groupId, team.serverType, team.originPointId, PUSH_ROUTE.GVG_AREA_POINT_CHANGE, { - cityId: team.cityId, areaId: team.originPointId, point: new GVGTeamInListOnPoint(team.originPointId, replaceTeam && !replaceTeam.curTeamBreak, replaceTeam) + await sendMessageToGVGAreaByTeamWithSuc(team.groupId, team.serverType, team.fromAreaId, PUSH_ROUTE.GVG_AREA_POINT_CHANGE, { + cityId: team.cityId, areaId: team.fromAreaId, point: new GVGTeamInListOnPoint(team.originPointId, replaceTeam && !replaceTeam.curTeamBreak, replaceTeam) }); } await pushTeamMoveMessage(team); if(team.isRobot && team.isBroken) { await sendMessageToGVGAreaByTeamWithSuc(team.groupId, team.serverType, team.fromAreaId, PUSH_ROUTE.GVG_PLAYER_LEAVE_AREA, { - cityId: team.cityId, areaId: team.areaId, teamCode: team.teamCode + cityId: team.cityId, areaId: team.fromAreaId, teamCode: team.teamCode }); } } @@ -402,7 +418,7 @@ export async function pushTeamMoveMessage(team: GVGTeamType) { }); } if(team.areaId > 0) { - await sendMessageToGVGAreaByTeamWithSuc(team.groupId, team.serverType, team.fromAreaId, PUSH_ROUTE.GVG_PLAYER_AREA_ADD, { + await sendMessageToGVGAreaByTeamWithSuc(team.groupId, team.serverType, team.areaId, PUSH_ROUTE.GVG_PLAYER_AREA_ADD, { cityId: team.cityId, areaId: team.fromAreaId, player: new GVGTeamInList(team) }); } diff --git a/shared/consts/constModules/sysConst.ts b/shared/consts/constModules/sysConst.ts index f265ad3d5..fba7de426 100644 --- a/shared/consts/constModules/sysConst.ts +++ b/shared/consts/constModules/sysConst.ts @@ -1129,6 +1129,7 @@ export enum ITEM_CHANGE_REASON { GVG_VESTIGE_RECEIVE_RANK = 172, // gvg征战中原领取排行榜奖励 GVG_TECH_SEND_KNIFE = 173, // gvg点科技树发放诸葛连弩 GVG_REVIVE = 174, // gvg复活队伍 + GVG_USE_ITEM = 175, // gvg使用连弩 } export enum TA_EVENT { diff --git a/shared/db/GVGTeam.ts b/shared/db/GVGTeam.ts index 9473f4cb7..b5cab78a1 100644 --- a/shared/db/GVGTeam.ts +++ b/shared/db/GVGTeam.ts @@ -134,7 +134,7 @@ export default class GVGTeam extends BaseModel { // 玩家切换城池更新队伍信息 public static async enterCity(roleId: string, cityId: number, areaId: number, groupId: number, serverType: number) { - const res = await GVGTeamModel.updateMany({ roleId }, { cityId, areaId, pointId: 0, groupId, serverType }).lean(); + const res = await GVGTeamModel.updateMany({ roleId }, { cityId, areaId, fromAreaId: areaId, pointId: 0, groupId, serverType }).lean(); return !!res['ok']; } @@ -157,8 +157,8 @@ export default class GVGTeam extends BaseModel { } // 获取编队 - public static async findByCode(roleId: string, teamCode: string, select = '') { - const res: GVGTeamType = await GVGTeamModel.findOne({ roleId, teamCode }).select(select).lean(); + public static async findByCode(teamCode: string, select = '') { + const res: GVGTeamType = await GVGTeamModel.findOne({ teamCode }).select(select).lean(); return res; } @@ -169,7 +169,7 @@ export default class GVGTeam extends BaseModel { } public static async stopMove(teamCode: string, areaId: number) { - const res: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { areaId, fromAreaId: 0, stopMoveTime: nowSeconds() } }, { new: true }).lean(); + const res: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { areaId, stopMoveTime: nowSeconds() } }, { new: true }).lean(); return res; } @@ -210,7 +210,7 @@ export default class GVGTeam extends BaseModel { filter: { groupId, serverType, cityId, areaId, pointId }, update: { $setOnInsert: { teamCode: genCode(8), maxDurability: durability, roleName: name, head, spine, frame: EXTERIOR.EXTERIOR_FACECASE, lineupCe: ce, isRobot: true, - isBroken: false, startMoveTime: 0, stopMoveTime: 0, guildCode: '', leagueCode: '', leagueName: '' + isBroken: false, startMoveTime: 0, stopMoveTime: 0, guildCode: '', leagueCode: '', leagueName: '', fromAreaId: areaId, }, $set: { configId, durability } }, upsert: true } @@ -233,7 +233,7 @@ export default class GVGTeam extends BaseModel { update: { $setOnInsert: { teamCode: genCode(8), maxDurability: durability, captapultAtk: atk, leagueCode, leagueName, roleName: GVG.GVG_CATAPULT_NAME, head: GVG.GVG_CATAPULT_HEAD, spine: GVG.GVG_CATAPULT_SPINE, frame: EXTERIOR.EXTERIOR_FACECASE, lineupCe: GVG.GVG_CATAPULT_CE, - isRobot: true, isCatapult: true, + isRobot: true, isCatapult: true, fromAreaId: areaId, isBroken: false, startMoveTime: 0, stopMoveTime: 0, guildCode: '', pointId: 0, roleId: GVG_CATAPULT }, $set: { configId, durability } }, upsert: true @@ -262,35 +262,35 @@ export default class GVGTeam extends BaseModel { } // 结算挑战方 - 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(); + public static async battleEndAttack(teamCode: string, hpInc: number, rebirthAreaId: number, reviveCd: number) { + let team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $inc: { durability: hpInc } }, { new: true }).lean(); if(team.durability <= 0) { let originPointId = team.pointId; - team = await GVGTeamModel.teamBreak(teamCode, team.isRobot, team.maxDurability, rebirthAreaId, reviveCd); + team = await GVGTeamModel.teamBreak(teamCode, team.isRobot, team.maxDurability, rebirthAreaId, team.areaId, reviveCd); team.originPointId = originPointId; } return team; } // 结算防守方 - 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(); + public static async battleEndDefense(teamCode: string, hpInc: 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 } }, { new: true }).lean(); if(team.durability <= 0) { let originPointId = team.pointId; - team = await GVGTeamModel.teamBreak(teamCode, team.isRobot, team.maxDurability, rebirthAreaId, reviveCd); + team = await GVGTeamModel.teamBreak(teamCode, team.isRobot, team.maxDurability, rebirthAreaId, team.areaId, reviveCd); team.originPointId = originPointId; } return team; } // 队伍进入修整器 - public static async teamBreak(teamCode: string, isRobot: boolean, maxDurability: number, areaId: number, reviveCd: number) { + public static async teamBreak(teamCode: string, isRobot: boolean, maxDurability: number, areaId: number, fromAreaId: number, reviveCd: number) { if(!isRobot) { - const team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { restartTime: nowSeconds() - reviveCd, stopMoveTime: nowSeconds(), areaId, durability: maxDurability } }, { new: true }).lean(); + const team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { restartTime: nowSeconds() - reviveCd, stopMoveTime: nowSeconds(), areaId, fromAreaId, durability: maxDurability } }, { new: true }).lean(); team.curTeamBreak = true; return team; } else { - const team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { durability: 0, isBroken: true } }, { new: true }).lean(); + const team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { fromAreaId, durability: 0, isBroken: true } }, { new: true }).lean(); team.curTeamBreak = true; return team; }