Files
ZYZ/game-server/app/servers/guild/handler/gvgBattleHandler.ts
2023-03-09 11:02:40 +08:00

813 lines
40 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { GVGRecModel, GVGRecType } from '../../../db/GVGRec';
import { GVGAreaInMap, GVGTeamInList, GVGTeamInListOnPoint, GVGTeamSpineInMap, LeagueGood, MyTeamInfo, MyTeamSimpleInfo } from '../../../domain/gvgField/returnData';
import { GVGTeamModel, GVGTeamType, GVGTeamUpdate } from '../../../db/GVGTeam';
import { GVGUserDataModel } from '../../../db/GVGUserData';
import { GVGCityModel, GVGCityType } from '../../../db/GVGCity';
import { Application, BackendSession, ChannelService, HandlerService, pinus } from "pinus";
import { resResult, genCode, getRandSingleEelm } from "../../../pubUtils/util";
import { GVGLeagueModel } from '../../../db/GVGLeague';
import { getGroupKey, getGVGConfig, getGVGPeriodData, getGVGServerType } from '../../../services/gvg/gvgService';
import { redisAddBattleScore, battleEndSendMessage, calBattleScoreByCe, checkAreaIsInCity, checkGVGBattleStart, checkMoveStatus, getBattleRanksByCity, getBirthAreaOfCity, getGVGWarId, getOppHeroes, getTechKnifeHurt, getTechReviveMinus, initRobots, pushTeamMoveMessage, getGVGCitiesInfo, leaveCity, refreshTeams, checkEnterCityTime, generNewLineup, getBattleRank, checkSettleStatus } from '../../../services/gvg/gvgBattleService';
import { getGVGBattleData } from '../../../services/gvg/gvgBattleMemory';
import { GVGBattleRecModel } from '../../../db/GVGBattleRec';
import { getFightTimeByPeriod } from '../../../services/gvg/gvgFightService';
import { gameData, getReviveGold } from '../../../pubUtils/data';
import { getAllServerName } from '../../../services/redisService';
import { checkBattleHeroesByHid } from '../../../services/normalBattleService';
import { SaveTeamParam, SaveTeamUpdateParam } from '../../../domain/gvgField/gvgDb';
import { GVG_AREA_TYPE, GVG_ATTACK_TYPE, GVG_ITEM, GVG_PERIOD, GVG_POINT_TYPE, GVG_REC_TYPE, ITEM_CHANGE_REASON, PUSH_ROUTE, REDIS_KEY, STATUS } from '../../../consts';
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';
import { GVGCityAreaPointModel } from '../../../db/GVGCityAreaPoint';
import { Rank } from '../../../services/rankService';
import { LeagueRankInfo, RoleRankInfo } from '../../../domain/rank';
import { addBattleEndRec } from '../../../services/gvg/gvgRecService';
import { RoleModel } from '../../../db/Role';
import { EXTERIOR, GVG } from '../../../pubUtils/dicParam';
import { sendMessageToGVGAreaByTeamWithSuc, sendMessageToUserWithSuc } from '../../../services/pushService';
export default function (app: Application) {
new HandlerService(app, {});
return new GVGBattleHandler(app);
}
export class GVGBattleHandler {
channelService: ChannelService;
constructor(private app: Application) {
this.channelService = app.get('channelService');
}
// 获取我的编队信息
async getTeams(msg: {}, session: BackendSession) {
const roleId = session.get('roleId');
const teams = await GVGTeamModel.findByRole(roleId, '-_id teamCode index head frame spine lineup')
return resResult(STATUS.SUCCESS, { teams: teams.map(team => new MyTeamSimpleInfo(team)) });
}
// 保存队伍
// index: 队伍索引位置
// head: 头像
// frame: 相框
// spine: 形象
// lineup: 阵容
async saveTeam(msg: SaveTeamParam, session: BackendSession) {
const roleId = session.get('roleId');
const serverId = session.get('serverId');
const roleName = session.get('roleName');
const guildCode = session.get('guildCode');
const { cityId, index, head, spine, frame, lineup } = msg;
let { configId, period } = getGVGPeriodData();
if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD);
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
let { leagueCode, name: leagueName } = myLeague;
let durability = gameData.gvgTeamDurability.get(index)||0;
let groupKey = await getGroupKey(serverId);
let updateParam: SaveTeamUpdateParam = { index, head, spine, frame, configId, groupKey }
if(lineup) {
let { isOK, heroes } = await checkBattleHeroesByHid(roleId, lineup.map(cur => cur.actorId));
if(!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND);
let { newLineup, newLineupCe } = await generNewLineup(roleId, heroes, lineup);
updateParam.lineup = newLineup;
updateParam.lineupCe = newLineupCe;
}
let originTeam = await GVGTeamModel.findByRoleAndIndex(roleId, index, 'cityId');
if(!originTeam && cityId > 0) {
let city = await GVGCityModel.increaseTeam(configId, groupKey, cityId, roleId);
updateParam.cityId = cityId;
updateParam.areaId = getBirthAreaOfCity(city, leagueCode)
}
let role = await RoleModel.findByRoleId(roleId, 'lv');
const team = await GVGTeamModel.saveTeam(roleId, index, updateParam, { roleName, serverId, leagueCode, leagueName, durability, maxDurability: durability, lv: role.lv });
if (!team) {
return resResult(STATUS.GVG_SAVE_TEAM_FAILED);
}
if(cityId > 0) {
let teamObj = getGVGBattleData(groupKey);
teamObj.enterCity(team);
}
return resResult(STATUS.SUCCESS, { curTeam: new MyTeamSimpleInfo(team) });
}
// 获取城池信息
async getCity(msg: { cityId: number }, session: BackendSession) {
const serverId = session.get('serverId');
const guildCode = session.get('guildCode');
const { cityId } = msg;
let { configId, period } = getGVGPeriodData();
let { startFightTime, endFightTime } = getFightTimeByPeriod(period);
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
let groupKey = await getGroupKey(serverId);
let guardCity = await GVGCityModel.findByCityId(configId + 1, groupKey, cityId);
if(!guardCity) guardCity = await GVGCityModel.findByCityId(configId, groupKey, cityId);
const { guardLeague: leagueCode = '', guardLeagueName: name = '', guardLeagueIcon: icon = 0, players = [] } = guardCity||{};
let ourTeamCnt = 0, oppTeamCnt = 0;
for(let { leagueCode, teamCnt } of players) {
myLeague.leagueCode == leagueCode? (ourTeamCnt+= teamCnt): (oppTeamCnt += teamCnt);
}
return resResult(STATUS.SUCCESS, {
cityId,
guardLeague: { leagueCode, name, icon },
guardStartTime: startFightTime - GVG.GVG_GUARD_START_TIME,
startTime: startFightTime,
endTime: endFightTime,
ourTeamCnt,
oppTeamCnt,
});
}
// 进入城池之前的检查
async checkMyTeam(msg: { cityId: number }, session: BackendSession) {
const roleId = session.get('roleId');
const serverId = session.get('serverId');
const guildCode = session.get('guildCode');
const { cityId } = msg;
let hasSettled = false, otherCityId = 0;
let { configId, period } = getGVGPeriodData();
if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD);
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
let groupKey = await getGroupKey(serverId);
let teams = await refreshTeams(configId, groupKey, roleId, myLeague);
// 玩家队伍信息中城池id不一致说明玩家已经进入了其他城池
for(let { cityId: teamCityId } of teams) {
if(teamCityId > 0 && teamCityId != cityId) {
hasSettled = true; otherCityId = teamCityId; break;
}
}
return resResult(STATUS.SUCCESS, { hasSettled, cityId: otherCityId });
}
// 进入城池
async enterCity(msg: { cityId: number }, session: BackendSession) {
const roleId = session.get('roleId');
const sid = session.get('sid');
const roleName = session.get('roleName');
const serverId = session.get('serverId');
const guildCode = session.get('guildCode');
const { cityId } = msg;
let { configId, period } = getGVGPeriodData();
if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD);
let groupKey = await getGroupKey(serverId);
let city = await GVGCityModel.findByCityId(configId, groupKey, cityId);
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
if(!checkEnterCityTime(city, myLeague.leagueCode)) return resResult(STATUS.GVG_NOT_ENTER_CITY_TIME);
// 初始化本城池的守擂机器人
await initRobots(configId, groupKey, city||{ cityId, guardLeague: '' });
// 每赛季初自己的几支队伍恢复耐久、城市、顺便更新一下自己的玩家名、联军
let teams = await refreshTeams(configId, groupKey, roleId, myLeague);
if(await GVGTeamModel.checkLockTeam(roleId, cityId)) return resResult(STATUS.GVG_BATTLE_TEAM_LOCK_ENTERY_CITY);
let gvgUserData = await GVGUserDataModel.findByRole(configId, myLeague.leagueCode, roleId);
let originCityId = gvgUserData?.cityId||0;
// 检测是否已经在城池中,玩家不在这个城池中时进行处理
if (originCityId != cityId) {
if(gvgUserData?.cityId > 0) { // 如果leaveCity没有退出成功玩家还遗留在上一座城中做一下处理
await leaveCity(true, roleId, serverId, guildCode, myLeague);
}
const roleTeamCnt = await GVGTeamModel.getTeamCntByRole(roleId);
city = await GVGCityModel.increasePlayer(configId, groupKey, cityId, roleId, myLeague.leagueCode, roleTeamCnt);
if(!city) return resResult(STATUS.GVG_BATTLE_CITY_FULL);
gvgUserData = await GVGUserDataModel.changeCity(configId, myLeague.leagueCode, roleId, cityId);
}
let teamResult: MyTeamInfo[] = [];
for(let team of teams) { // 有可能多个编队有的在城池中(驻守),有点不在(新编)
let originCityId = team.cityId||0;
if(originCityId == cityId) {
teamResult.push(new MyTeamInfo(team));
continue;
};
let areaId = getBirthAreaOfCity(city, myLeague.leagueCode);
team = await GVGTeamModel.enterCity(team.teamCode, cityId, areaId, groupKey);
if(!team) continue;
// 更新内存队伍信息
let teamObj = getGVGBattleData(groupKey);
teamObj.enterCity(team);
teamResult.push(new MyTeamInfo(team))
}
const { ranks, myRank } = await getBattleRanksByCity(configId, groupKey, cityId, myLeague);
await leaveGVGCityTeamChannel(roleId, sid);
await addRoleToGVGCityChannel(roleId, groupKey, cityId, sid);
return resResult(STATUS.SUCCESS, {
cityId,
ranks, myRank,
recs: [],
teams: teamResult,
});
}
// 离开城池
async leaveCity(msg: { cityId: number }, session: BackendSession) {
const roleId = session.get('roleId');
const sid = session.get('sid');
const guildCode = session.get('guildCode');
const serverId = session.get('serverId');
const { cityId } = msg;
let { configId, period } = getGVGPeriodData();
// 检测是否已经在城池中
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
let gvgUserData = await GVGUserDataModel.findByRole(configId, myLeague.leagueCode, roleId);
if (!gvgUserData) {
return resResult(STATUS.GVG_USER_NOT_FOUND);
}
if (gvgUserData.cityId != cityId) {
return resResult(STATUS.GVG_USER_NOT_IN_CITY);
}
// 更新玩家城池和队伍城池
await leaveCity(false, roleId, serverId, guildCode, myLeague);
await leaveGVGAreaChannel(roleId, sid);
await leaveGVGAreaTeamChannel(roleId, sid);
await leaveGVGCityTeamChannel(roleId, sid);
return resResult(STATUS.SUCCESS);
}
// 获取区域上的队伍
async getAreaTeams(msg: { cityId: number, areaIds: number[] }, session: BackendSession) {
const roleId = session.get('roleId');
const sid = session.get('sid');
const serverId = session.get('serverId');
const { cityId, areaIds } = msg;
if(!checkAreaIsInCity(cityId, areaIds)) return resResult(STATUS.GVG_AREA_NOT_IN_CITY);
let groupKey = await getGroupKey(serverId);
let serverNames = await getAllServerName();
let teamObj = getGVGBattleData(groupKey);
let result: GVGTeamSpineInMap[] = [];
for(let areaId of areaIds) {
let teams = teamObj.findTeamsByArea(areaId);
for(let team of teams) {
result.push(new GVGTeamSpineInMap(team, serverNames))
}
}
// 加入频道
await leaveGVGAreaChannel(roleId, sid);
await addRoleToAreaChannel(roleId, groupKey, areaIds, sid);
return resResult(STATUS.SUCCESS, { cityId, spines: result });
}
// 点击自己的编队获取区域列表
async getAreaOfMyTeam(msg: { cityId: number, teamCode: string }, session: BackendSession) {
const roleId = session.get('roleId');
const sid = session.get('sid');
const serverId = session.get('serverId');
const { cityId, teamCode } = msg;
let groupKey = await getGroupKey(serverId);
let { configId } = getGVGPeriodData();
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);
let teams = await GVGTeamModel.findByAreaId(configId, groupKey, cityId, myTeam.areaId);
let points: GVGTeamInListOnPoint[] = [], players: GVGTeamInList[] = [];
let pointIds = gameData.gvgPointByAreaId.get(myTeam.areaId)||[];
for(let pointId of pointIds) {
let team = teams.find(cur => cur.pointId == pointId);
let obj = new GVGTeamInListOnPoint(pointId, !!team, team);
points.push(obj);
}
for(let team of teams) {
if(team.pointId == 0) {
let obj = new GVGTeamInList(team);
players.push(obj);
}
}
await leaveGVGAreaTeamChannel(roleId, sid);
await addRoleToAreaTeamChannel(roleId, groupKey, myTeam.areaId, sid);
return resResult(STATUS.SUCCESS, {
cityId, areaId: myTeam.areaId, points, players
});
}
// 开始移动
// 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;
let groupKey = await getGroupKey(serverId);
let team = await GVGTeamModel.findMyTeamByCode(roleId, teamCode);
let checkResult = checkMoveStatus(team, cityId, areaId);
if(checkResult.code != 0) return resResult(checkResult);
team = await GVGTeamModel.startMove(teamCode, areaId, team.areaId);
// 更新内存数据
let teamObj = getGVGBattleData(groupKey);
teamObj.move(teamCode, areaId, team.fromAreaId, team.startMoveTime, team.stopMoveTime);
await addRoleToAreaTeamChannel(roleId, groupKey, areaId, sid);
await pushTeamMoveMessage(team);
return resResult(STATUS.SUCCESS, { areaId, cityId, stopMoveTime: team.stopMoveTime, moveCdTime: team.moveCdTime });
}
// 停止移动
// 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;
let groupKey = await getGroupKey(serverId);
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);
team = await GVGTeamModel.stopMove(teamCode, areaId);
// 更新内存数据
let teamObj = getGVGBattleData(groupKey);
teamObj.move(teamCode, areaId, 0, team.startMoveTime, team.stopMoveTime);
await leaveGVGAreaTeamChannel(roleId, sid);
await addRoleToAreaTeamChannel(roleId, groupKey, areaId, sid);
return resResult(STATUS.SUCCESS, { areaId, cityId, curTeam: new MyTeamInfo(team) });
}
// 队伍入驻积分点
async teamSettle(msg: { cityId: number, areaId: number, pointId: number, teamCode: string }, session: BackendSession) {
const roleId = session.get('roleId');
const serverId = session.get('serverId');
const { cityId, areaId, pointId, teamCode } = msg;
let { configId, period } = getGVGPeriodData();
if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD);
let groupKey = await getGroupKey(serverId);
let myTeam = await GVGTeamModel.findMyTeamByCode(roleId, teamCode);
if(!myTeam) return resResult(STATUS.GVG_TEAM_NOT_FOUND);
let checkResult = checkSettleStatus(myTeam);
if(checkResult.code != 0) return resResult(checkResult);
let dicAreaPoint = gameData.gvgAreaPoint.get(pointId);
if(dicAreaPoint.areaId != myTeam.areaId) return resResult(STATUS.GVG_POINT_NOT_AREA);
if(dicAreaPoint.type != GVG_POINT_TYPE.ROBOT) return resResult(STATUS.GVG_POINT_TYPE_ERR);
let point = await GVGCityAreaPointModel.settlePoint(cityId, areaId, pointId, myTeam);
if(!point) return resResult(STATUS.GVG_POINT_HAS_SETTLED);
const curTeam = await GVGTeamModel.settlePoint(teamCode, pointId);
let teamObj = getGVGBattleData(groupKey);
teamObj.teamSettle(roleId, teamCode, pointId);
// addTeamSettleRec(curTeam);
await sendMessageToGVGAreaByTeamWithSuc(groupKey, curTeam.areaId, PUSH_ROUTE.GVG_AREA_POINT_CHANGE, {
cityId: curTeam.cityId, areaId: curTeam.areaId, targetPointId: pointId, originPointId: myTeam.pointId, point: new GVGTeamInListOnPoint(curTeam.pointId, true, curTeam)
});
return resResult(STATUS.SUCCESS, { curTeam: new MyTeamInfo(curTeam) });
}
// 队伍离开积分点
async teamLeave(msg: { cityId: number, areaId: number, pointId: number, teamCode: string }, session: BackendSession) {
const roleId = session.get('roleId');
const serverId = session.get('serverId');
const { pointId, teamCode } = msg;
let { configId, period } = getGVGPeriodData();
if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD);
let groupKey = await getGroupKey(serverId);
let myTeam = await GVGTeamModel.findMyTeamByCode(roleId, teamCode);
if(!myTeam) return resResult(STATUS.GVG_TEAM_NOT_FOUND);
let checkResult = checkSettleStatus(myTeam);
if(checkResult.code != 0) return resResult(checkResult);
let dicAreaPoint = gameData.gvgAreaPoint.get(pointId);
if(dicAreaPoint.areaId != myTeam.areaId) return resResult(STATUS.GVG_POINT_NOT_AREA);
const curTeam = await GVGTeamModel.settlePoint(teamCode, 0);
await GVGCityAreaPointModel.leavePoint(configId, groupKey, teamCode);
let teamObj = getGVGBattleData(groupKey);
teamObj.teamSettle(roleId, teamCode, 0);
await sendMessageToGVGAreaByTeamWithSuc(groupKey, curTeam.areaId, PUSH_ROUTE.GVG_AREA_POINT_CHANGE, {
cityId: curTeam.cityId, areaId: curTeam.areaId, targetPointId: pointId, originPointId: myTeam.pointId, point: new GVGTeamInListOnPoint(curTeam.pointId, true, curTeam)
});
return resResult(STATUS.SUCCESS, { curTeam: new MyTeamInfo(curTeam) });
}
// 队伍开始攻击
// teamCode: 攻击方队伍
// oppoTeamCode: 防守方队伍
async battleStart(msg: { cityId: number, teamCode: string, oppoTeamCode: string, pointId: number }, session: BackendSession) {
const roleId = session.get('roleId');
const serverId = session.get('serverId');
const { teamCode, oppoTeamCode } = msg;
let { configId, period } = getGVGPeriodData();
if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD);
let { startFightTime } = getFightTimeByPeriod(period);
if(startFightTime > nowSeconds()) return resResult(STATUS.GVG_NOT_BATTLE_TIME);
let groupKey = await getGroupKey(serverId);
let { attackTeam, defenseTeam } = await GVGTeamModel.findBattleTeams(teamCode, oppoTeamCode);
let checkStatus = checkGVGBattleStart(roleId, attackTeam, defenseTeam);
if(checkStatus.code != 0) return resResult(checkStatus);
const warId = getGVGWarId(defenseTeam);
const battleRecord = await GVGBattleRecModel.createRec(configId, groupKey, warId, attackTeam, defenseTeam);
attackTeam = await GVGTeamModel.battleStartLockAttack(teamCode);
defenseTeam = await GVGTeamModel.battleStartLockDefense(oppoTeamCode, teamCode);
// 内存处理
let teamObj = getGVGBattleData(groupKey);
teamObj.setTime(attackTeam.teamCode, attackTeam);
teamObj.setTime(defenseTeam.teamCode, defenseTeam);
let heroes = getOppHeroes(warId, defenseTeam.isRobot, defenseTeam.lineup)
return resResult(STATUS.SUCCESS, { battleCode: battleRecord.battleCode, warId, isRobot: defenseTeam.isRobot, heroes, curTeam: new MyTeamInfo(attackTeam), oppTeam: new MyTeamInfo(defenseTeam) });
}
// 队伍停止攻击
async battleEnd(msg: { cityId: number, battleCode: string, isSuccess: boolean }, session: BackendSession) {
const serverId = session.get('serverId');
const { cityId, battleCode, isSuccess } = msg;
let { configId, period } = getGVGPeriodData();
const record = await GVGBattleRecModel.findByBattleCode(battleCode);
if(!record) return resResult(STATUS.GVG_BATTLEREC_NOT_FOUND);
if(record.battleEndTime > 0) return resResult(STATUS.GVG_BATTLEREC_HAS_SUMMIT);
let { attackTeam, defenseTeam } = await GVGTeamModel.findBattleTeams(record.attackTeam.teamCode, record.defenseTeam.teamCode);
let attackOriginId = attackTeam.pointId;
if(defenseTeam.lockTeamCode != attackTeam.teamCode) return resResult(STATUS.GVG_LOCK_TIME_OUT)
let groupKey = await getGroupKey(serverId);
let city = await GVGCityModel.findByCityId(configId, groupKey, cityId);
if (!city) return resResult(STATUS.GVG_CITY_NOT_FOUND);
// 计算并更新两支队伍耐久
let { win, fail } = gameData.gvgBattleDurabilityMinus;
attackTeam = await GVGTeamModel.battleEndAttack(attackTeam.teamCode, isSuccess? -win: -fail, getBirthAreaOfCity(city, attackTeam.leagueCode), await getTechReviveMinus(groupKey, configId, attackTeam.leagueCode));
defenseTeam = await GVGTeamModel.battleEndDefense(defenseTeam.teamCode, isSuccess? -fail: -win, getBirthAreaOfCity(city, defenseTeam.leagueCode), GVG.GVG_DEFAULT_DEFENSE_CD, await getTechReviveMinus(groupKey, configId, defenseTeam.leagueCode));
if(defenseTeam.curTeamBreak && defenseTeam.originPointId > 0 && !defenseTeam.isCatapult) { // 打败的对手原来占领着一个位置,现在这个位置是你的了
if(!attackTeam.curTeamBreak) {
let settleResult = await GVGCityAreaPointModel.settlePoint(cityId, attackTeam.areaId, defenseTeam.originPointId, attackTeam, defenseTeam.isRobot? '': defenseTeam.teamCode);
if(settleResult) attackTeam = await GVGTeamModel.settlePoint(attackTeam.teamCode, defenseTeam.originPointId);
} else {
await GVGCityAreaPointModel.leavePoint(configId, groupKey, defenseTeam.teamCode);
}
}
if(attackTeam.curTeamBreak && attackTeam.originPointId) {
await GVGCityAreaPointModel.leavePoint(configId, groupKey, attackTeam.teamCode);
}
if(defenseTeam.curTeamBreak) {
let attackScore = calBattleScoreByCe(isSuccess, defenseTeam.lineupCe);
let attackCurTeamBreak = attackTeam.curTeamBreak;
attackTeam = await GVGTeamModel.addScore(attackTeam.teamCode, attackScore, 0);
attackTeam.curTeamBreak = attackCurTeamBreak;
await redisAddBattleScore(attackTeam, attackScore);
}
// 更新内存
let teamObj = getGVGBattleData(groupKey);
teamObj.battleEnd([attackTeam, defenseTeam]);
// 更新rec
let rec = await GVGBattleRecModel.battleEnd(battleCode, isSuccess, attackTeam, defenseTeam);
await battleEndSendMessage(groupKey, cityId, defenseTeam, {...attackTeam, originPointId: attackOriginId}, GVG_ATTACK_TYPE.PLAYER);
addBattleEndRec(rec);
return resResult(STATUS.SUCCESS, { curTeam: new MyTeamInfo(attackTeam), oppTeam: new MyTeamInfo(defenseTeam) });
}
// 使用道具
// teamCode: 要使用道具的队伍
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);
let groupKey = await getGroupKey(serverId);
let { attackTeam, defenseTeam } = await GVGTeamModel.findBattleTeams(teamCode, oppoTeamCode);
let attackOriginId = attackTeam.pointId;
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, groupKey, cityId);
if (!city) return resResult(STATUS.GVG_CITY_NOT_FOUND);
let hurt = await getTechKnifeHurt(configId, attackTeam.leagueCode);
defenseTeam = await GVGTeamModel.battleEndDefense(oppoTeamCode, -hurt, getBirthAreaOfCity(city, defenseTeam.leagueCode), 0, await getTechReviveMinus(groupKey, configId, defenseTeam.leagueCode));
if(defenseTeam.curTeamBreak && defenseTeam.originPointId > 0 && !defenseTeam.isCatapult) { // 打败的对手原来占领着一个位置,现在这个位置是你的了
if(!attackTeam.curTeamBreak) {
let settleResult = await GVGCityAreaPointModel.settlePoint(cityId, attackTeam.areaId, defenseTeam.originPointId, attackTeam, defenseTeam.isRobot? '': defenseTeam.teamCode);
if(settleResult) attackTeam = await GVGTeamModel.settlePoint(attackTeam.teamCode, defenseTeam.originPointId);
} else {
await GVGCityAreaPointModel.leavePoint(configId, groupKey, defenseTeam.teamCode);
}
}
if(defenseTeam.curTeamBreak) {
let attackScore = calBattleScoreByCe(true, defenseTeam.lineupCe);
await redisAddBattleScore(attackTeam, attackScore);
}
// 更新内存
let teamObj = getGVGBattleData(groupKey);
teamObj.battleEnd([attackTeam, defenseTeam]);
await battleEndSendMessage(groupKey, cityId, defenseTeam, {...attackTeam, originPointId: attackOriginId}, GVG_ATTACK_TYPE.KNIFE);
return resResult(STATUS.SUCCESS, { curTeam: new MyTeamInfo(attackTeam), oppTeam: new MyTeamInfo(defenseTeam) });
}
// 复活队伍
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 groupKey = await getGroupKey(serverId);
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);
// 更新内存
let teamObj = getGVGBattleData(groupKey);
teamObj.battleEnd([team]);
// 更新成功返回队伍信息
return resResult(STATUS.SUCCESS, { reviveCnt, curTeam: new MyTeamInfo(team) });
}
// 获取战报
// type: 战报类型
async getRecs(msg: { type: number }, session: BackendSession) {
const roleId = session.get('roleId');
const serverId = session.get('serverId');
const guildCode = session.get('guildCode');
const { type } = msg;
// 根据 type 获取战报
let { configId, period } = getGVGPeriodData();
let groupKey = await getGroupKey(serverId);
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
let recs: GVGRecType[] = [];
if(type == GVG_REC_TYPE.BATTLE_BY_CITY) {
recs = await GVGRecModel.findBattleRecByGroup(configId, groupKey);
} else if (type == GVG_REC_TYPE.BATTLE_BY_LEAGUE) {
recs = await GVGRecModel.findBattleRecByLeague(configId, myLeague.leagueCode);
} else if (type == GVG_REC_TYPE.BATTLE_BY_ROLE) {
recs = await GVGRecModel.findBattleRecByRole(configId, roleId, myLeague.leagueCode);
}
return resResult(STATUS.SUCCESS, { recs });
}
// 获取概况
async getOverview(msg: {}, session: BackendSession) {
const serverId = session.get('serverId');
let { configId } = getGVGPeriodData();
let groupKey = await getGroupKey(serverId);
let serverType = await getGVGServerType(serverId);
const cities = await GVGCityModel.findByConfigAndGroup(configId, groupKey);
const points = await GVGCityAreaPointModel.findByConfig(configId, groupKey);
let result: { cityId: number, guardLeagueName: string, areas: { areaId: number, points: { pointId: number, guardLeagueName: string }[] }[] }[] = [];
for(let [ cityId, { mapType, battleAreaIds }] of gameData.gvgCity) {
if(mapType != serverType) continue;
let city = cities.find(cur => cur.cityId == cityId);
let areas: { areaId: number, points: {pointId: number, guardLeagueName: string }[]}[] = [];
for(let areaId of battleAreaIds) {
let pointIds = gameData.gvgPointByAreaId.get(areaId)||[];
let pointArrs: { pointId: number, guardLeagueName: string }[] = [];
for(let pointId of pointIds) {
let dicAreaPoint = gameData.gvgAreaPoint.get(pointId);
if(!dicAreaPoint) continue;
let playerPoint = points.find(cur => cur.pointId == pointId);
pointArrs.push({ pointId, guardLeagueName: playerPoint? (playerPoint.leagueName||"无"): dicAreaPoint.name });
}
if(pointArrs.length > 0) areas.push({ areaId, points: pointArrs });
}
result.push({ cityId, guardLeagueName: city?.guardLeagueName||'', areas });
}
return resResult(STATUS.SUCCESS, { cities: result });
}
// 排行榜
async getRanks(msg: {}, session: BackendSession) {
const serverId = session.get('serverId');
const guildCode = session.get('guildCode');
const roleId = session.get('roleId');
let { configId } = getGVGPeriodData();
let groupKey = await getGroupKey(serverId);
let cities = await getGVGCitiesInfo(configId, groupKey);
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
let { myRank: myLeagueRank, ranks: leagueRanks } = await getBattleRank(REDIS_KEY.GVG_BATTLE_LEAGUE_RANK, { configId, groupKey }, { leagueCode: myLeague.leagueCode });
let { myRank: myMemberRank, ranks: memberRanks } = await getBattleRank(REDIS_KEY.GVG_BATTLE_RANK, { configId, groupKey }, { roleId });
return resResult(STATUS.SUCCESS, {
cities, leagueRanks, myLeagueRank, memberRanks, myMemberRank
})
}
async debugStartSchedule() {
let { countdownTime } = getGVGPeriodData();
pinus.app.rpc.guild.guildRemote.setPeriodTime.broadcast(nowSeconds(), countdownTime);
await pinus.app.rpc.systimer.systimerRemote.gvgBattleStartSchedule.broadcast();
return resResult(STATUS.SUCCESS);
}
async debugEndSchedule() {
pinus.app.rpc.guild.guildRemote.resetPeriodTime.broadcast();
await pinus.app.rpc.systimer.systimerRemote.gvgBattleEndSchedule.broadcast();
return resResult(STATUS.SUCCESS);
}
async debugAddRobots(msg: { cityId: number, teamCnt: number }, session: BackendSession) {
const serverId = session.get('serverId');
const { cityId, teamCnt } = msg;
const { configId } = getGVGConfig();
const groupKey = await getGroupKey(serverId);
const teamObj = getGVGBattleData(groupKey);
const teams: any[] = [];
const areaIds = gameData.gvgCity.get(cityId)?.areaIds||[];
for(let i = 0; i < teamCnt; i++) {
let areaId = getRandSingleEelm(areaIds);
teams.push({ configId, groupKey, roleId: 'test', roleName: 'test' + i, serverId, lv: 100, teamCode: genCode(8), index: 3, leagueCode: 'test', leagueName: 'test' + i, guildCode: 'test', areaId, cityId, pointId: 0, head: EXTERIOR.EXTERIOR_FACE, frame: EXTERIOR.EXTERIOR_FACECASE, spine: EXTERIOR.EXTERIOR_APPEARANCE, durability: 100, maxDurability: 100, restartTime: nowSeconds(), attackTime: nowSeconds(), lockTime: nowSeconds(), startMoveTime: nowSeconds(), stopMoveTime: nowSeconds(), moveCdTime: nowSeconds(), defenseTime: nowSeconds(), lineupCe: 100000 })
}
await GVGTeamModel.insertMany(teams);
teamObj.enterCity(...teams);
return resResult(STATUS.SUCCESS);
}
private moveInterval: NodeJS.Timer;
private attackInterval: NodeJS.Timer;
async debugMoveRobots(msg: { cityId: number, frequency: number }, session: BackendSession) {
const serverId = session.get('serverId');
const { cityId, frequency } = msg;
const { configId } = getGVGConfig();
const groupKey = await getGroupKey(serverId);
const teamObj = getGVGBattleData(groupKey);
const serverNames = await getAllServerName();
if(this.moveInterval) {
clearInterval(this.moveInterval);
}
let fun = async () => {
let teams = teamObj.findTeamsByRole('test');
for(let i = 0; i < teams.length; i++) {
let teamMem = teams[i];
setTimeout(async () => {
let fromAreaId = teamMem.areaId;
let dicArea = gameData.gvgArea.get(fromAreaId);
// 更新内存数据
let toAreaId = getRandSingleEelm(dicArea.relateArea);
let team = await GVGTeamModel.startMove(teamMem.teamCode, toAreaId, fromAreaId);
// 更新内存数据
let teamObj = getGVGBattleData(groupKey);
teamObj.move(teamMem.teamCode, toAreaId, team.fromAreaId, team.startMoveTime, team.stopMoveTime);
await pushTeamMoveMessage(team);
}, i * 100);
}
};
await fun();
this.moveInterval = setInterval(fun, frequency)
return resResult(STATUS.SUCCESS)
}
async debugAttacks(msg: { cityId: number, frequency: number }, session: BackendSession) {
const roleId = session.get('roleId');
const serverId = session.get('serverId');
const sid = session.get('sid');
const { cityId, frequency } = msg;
const { configId } = getGVGConfig();
const groupKey = await getGroupKey(serverId);
const teamObj = getGVGBattleData(groupKey);
const serverNames = await getAllServerName();
if(this.attackInterval) {
clearInterval(this.attackInterval);
}
let fun = async () => {
for(let areaId of teamObj.findAreas()) {
let teams = teamObj.findTeamsByArea(areaId);
let areaTeams = teams.map(team => new GVGTeamInList(team as any));
await sendMessageToGVGAreaByTeamWithSuc(teamObj.groupKey, areaId, PUSH_ROUTE.GVG_TEAM_ATTACKED, {
cityId, areaId, attackType: GVG_ATTACK_TYPE.PLAYER, teams: areaTeams
});
let myTeams = teams.filter(team => team.roleId == roleId).map(team => new GVGTeamInList(team as any));
if(myTeams.length > 0) await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.GVG_MY_TEAM_ATTACKED, {
cityId, areaId, attackType: GVG_ATTACK_TYPE.PLAYER, teams: myTeams
}, sid);
}
};
await fun();
this.attackInterval = setInterval(fun, frequency)
return resResult(STATUS.SUCCESS)
}
async debugStopMoveRobot(msg: { cityId: number }, session: BackendSession) {
if(this.moveInterval) {
clearInterval(this.moveInterval);
}
if(this.attackInterval) {
clearInterval(this.attackInterval);
}
return resResult(STATUS.SUCCESS);
}
}