Files
ZYZ/shared/db/GVGTeam.ts
T

356 lines
15 KiB
TypeScript

// GVGTeam 数据库表,存储 GVG 队伍信息
import BaseModel from "./BaseModel";
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { genCode } from "../pubUtils/util";
import { nowSeconds } from "../pubUtils/timeUtil";
import { EXTERIOR, GVG } from "../pubUtils/dicParam";
import { DicGVGAreaPoint } from "../pubUtils/dictionary/DicGVGAreaPoint";
import { InitTeamParam, SaveTeamUpdateParam } from "../domain/gvgField/gvgDb";
import { GVGHeroInfo } from "../domain/dbGeneral";
import { GVG_CATAPULT } from "../consts";
@index({ roleId: 1, index: 1 })
@index({ teamCode: 1 })
@index({ cityId: 1, leagueId: 1 })
export default class GVGTeam extends BaseModel {
@prop({ required: true })
configId: number; // 赛季,每赛季在enterCity的时候检测,如果不一样就更新durability那些东西
@prop({ required: true })
roleId: string; // 玩家id
@prop({ required: true })
roleName: string; // 玩家名
@prop({ required: true })
serverId: number; // 小区id
@prop({ required: true })
teamCode: string; // 玩家队伍唯一标识
@prop({ required: true })
index: number; // 队伍id,1-3,玩家的第几个队伍
@prop({ required: true })
leagueCode: string; // 联军
@prop({ required: true })
leagueName: string; // 联军
@prop({ required: true })
guildCode: string; // 军团
@prop({ required: false })
areaId: number;
@prop({ required: false })
cityId: number;
@prop({ required: false })
pointId: number;
@prop({ required: true })
head: number; // 头像
@prop({ required: true })
spine: number; // 形象
@prop({ required: true })
frame: number; // 相框
@prop({ required: true, default: 0 })
durability: number; // 耐久
@prop({ required: true, default: 0 })
maxDurability: number; // 耐久
@prop({ required: true, default: 0 })
restartTime: number; // 修整期倒计时
@prop({ required: true, default: 0 })
attackTime: number; // 进攻冷却时间
@prop({ required: true, default: 0 })
lockTime: number; // 正在被进攻中
@prop({ required: true, default: 0 })
lockTeamCode: string; // 正在被这支队伍进攻中
@prop({ required: true, default: 0 })
fromAreaId: number; // 从那个区域移动
@prop({ required: true, default: 0 })
startMoveTime: number;
@prop({ required: true, default: 0 })
moveCdTime: number; // 移动冷却时间
@prop({ required: true, default: 0 })
stopMoveTime: number; // 移动时间
@prop({ required: true, default: 0 })
defenseTime: number; // 防守保护时间
@prop({ required: true, default: 0 })
battleScore: number; // 积分
@prop({ required: true, default: 0 })
settleScore: number; // 积分
@prop({ required: true, type: () => GVGHeroInfo, _id: false })
lineup: GVGHeroInfo[];
@prop({ required: true })
lineupCe: number;
@prop({ required: true })
groupId: number; // 战区
@prop({ required: true })
serverType: number; // 单服还是跨服
@prop({ required: true, default: false })
isRobot: boolean; // 是否是机器人
@prop({ required: true, default: false })
captapultAtk: number; // 投石车的攻击力
@prop({ required: true, default: false })
isCatapult: boolean; // 是否是投石车
@prop({ required: true, default: false })
isBroken: boolean; // 机器人是否被击破,如果没有被击破,那么这个位置上就还是机器人,如果被击破了,这个位置就空出给玩家
originPointId: number;
curTeamBreak: boolean;
// 创建队伍
public static async saveTeam(roleId: string, index: number, updateParam: SaveTeamUpdateParam, initParam: InitTeamParam) {
const doc = new GVGTeamModel();
const teamCode = genCode(8);
const insert = Object.assign(doc.toJSON(), { ...initParam, teamCode });
delete insert.lineup;
const team: GVGTeamType | null = await GVGTeamModel.findOneAndUpdate({ roleId, index }, { $setOnInsert: insert, $set: updateParam }, { upsert: true, new: true }).lean();
return team;
}
// 玩家切换城池更新队伍信息
public static async enterCity(roleId: string, cityId: number, areaId: number, groupId: number, serverType: number) {
const res = await GVGTeamModel.updateMany({ roleId }, { cityId, areaId, fromAreaId: areaId, pointId: 0, groupId, serverType }).lean();
return !!res['ok'];
}
// 查找角色队伍数
public static async getTeamCntByRole(roleId: string) {
const teams: GVGTeamType[] = await GVGTeamModel.find({ roleId }).select('teamCode').lean();
return teams.length;
}
// 获取我的编队
public static async findByRole(roleId: string, select = '') {
const teams: GVGTeamType[] = await GVGTeamModel.find({ roleId }).select(select).lean();
return teams;
}
// 获取某个玩家的某个的编队
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(teamCode: string, select = '') {
const res: GVGTeamType = await GVGTeamModel.findOne({ teamCode }).select(select).lean();
return res;
}
// 移动
public static async startMove(teamCode: string, areaId: number, fromAreaId: number) {
const res: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { areaId, fromAreaId, stopMoveTime: nowSeconds() + GVG.GVG_DEFAULT_MOVE_CD, moveCdTime: nowSeconds() + GVG.GVG_DEFAULT_MOVE_CD } }, { new: true }).lean();
return res;
}
public static async stopMove(teamCode: string, areaId: number) {
const res: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { areaId, stopMoveTime: nowSeconds() } }, { new: true }).lean();
return res;
}
// 查询挑战和防守的编队
public static async findBattleTeams(teamCode: string, oppoTeamCode: string) {
const teams: GVGTeamType[] = await GVGTeamModel.find({ teamCode: { $in: [ teamCode, oppoTeamCode ] } }).lean();
let attackTeam: GVGTeamType = null, defenseTeam: GVGTeamType = null;
for(let team of teams) {
if(team.teamCode == teamCode) attackTeam = team;
if(team.teamCode == oppoTeamCode) defenseTeam = team;
}
return { attackTeam, defenseTeam }
}
// 每赛季初刷新自己的耐久等东西
public static async refreshByConfig(roleId: string, updateArr: GVGTeamUpdate[]) {
await GVGTeamModel.bulkWrite(updateArr.map(obj => {
return {
updateOne: {
filter: { roleId, teamCode: obj.teamCode },
update: { $set: obj }
}
}
}));
return await GVGTeamModel.findByRole(roleId, '-_id');
}
public static async findRobotTeams(groupId: number, serverType: number, cityId: number) {
const team: GVGTeamType[] = await GVGTeamModel.find({ groupId, serverType, cityId, isRobot: true }).lean();
return team;
}
// 每赛季初刷新机器人
public static async initRobots(configId: number, groupId: number, serverType: number, cityId: number, dicPoints: DicGVGAreaPoint[]) {
await GVGTeamModel.bulkWrite(dicPoints.map(({ pointId, areaId, name, head, spine, ce, durability }) => {
return {
updateOne: {
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: '', fromAreaId: areaId,
}, $set: { configId, durability } },
upsert: true
}
}
}));
return await this.findRobotTeams(groupId, serverType, cityId);
}
public static async findCatapultTeams(groupId: number, serverType: number, cityId: number) {
const team: GVGTeamType[] = await GVGTeamModel.find({ groupId, serverType, cityId, isRobot: true, isCatapult: true }).lean();
return team;
}
// 生成投石车
public static async initCatapult(configId: number, groupId: number, serverType: number, cityId: number, leagueCode: string, leagueName: string, areaIds: number[], atk: number, durability: number) {
await GVGTeamModel.bulkWrite(areaIds.map(areaId => {
return {
updateOne: {
filter: { groupId, serverType, cityId, areaId },
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, fromAreaId: areaId,
isBroken: false, startMoveTime: 0, stopMoveTime: 0, guildCode: '', pointId: 0, roleId: GVG_CATAPULT
}, $set: { configId, durability } },
upsert: true
}
}
}));
return await this.findCatapultTeams(groupId, serverType, cityId);
}
// 攻击方攻击cd
public static async battleStartLockAttack(teamCode: string) {
const team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { attackTime: nowSeconds() + GVG.GVG_DEFAULT_ATTACK_CD } }, { new: true }).lean();
return team;
}
// 防守方锁定cd
public static async battleStartLockDefense(teamCode: string, lockTeamCode: string) {
const team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { lockTime: nowSeconds() + GVG.GVG_DEFAULT_ATTACK_CD, lockTeamCode } }, { new: true }).lean();
return team;
}
// 占领积分点
public static async settlePoint(teamCode: string, pointId: number) {
const team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { pointId } }, { new: true }).lean();
return team;
}
// 结算挑战方
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, team.areaId, reviveCd);
team.originPointId = originPointId;
}
return team;
}
// 结算防守方
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, team.areaId, reviveCd);
team.originPointId = originPointId;
}
return team;
}
// 队伍进入修整器
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, fromAreaId, durability: maxDurability } }, { new: true }).lean();
team.curTeamBreak = true;
return team;
} else {
const team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { fromAreaId, durability: 0, isBroken: true } }, { new: true }).lean();
team.curTeamBreak = true;
return team;
}
}
public static async findByAreaId(groupId: number, serverType: number, cityId: number, areaId: number) {
const team: GVGTeamType[] = await GVGTeamModel.find({ groupId, serverType, cityId, areaId, stopMoveTime: { $lte: nowSeconds() }, isBroken: false }).lean();
return team;
}
public static async findByConfigId(configId: number) {
const team: GVGTeamType[] = await GVGTeamModel.find({ configId, cityId: { $gt: 0 } }).lean();
return team;
}
// 这个编队上是否已经有队伍了
public static async checkPoint(configId: number, groupId: number, serverType: number, pointId: number) {
return await GVGTeamModel.exists({ configId, groupId, serverType, pointId, isBroken: false });
}
// 投石车伤害
public static async attackByCatapult(teamCodes: string[], inc: number, rebirthAreaId: number) {
await GVGTeamModel.updateMany({ teamCode: { $in: teamCodes } }, { $inc: { durability: -inc } });
let brokenTeams: GVGTeamType[] = await GVGTeamModel.find({ teamCode: { $in: teamCodes }, durability: { $lte: 0 } }).lean();
if(brokenTeams.length > 0) {
await GVGTeamModel.bulkWrite(brokenTeams.map(({ teamCode, maxDurability }) => {
return { updateOne: { filter: { teamCode }, update: { $set: { areaId: rebirthAreaId, pointId: 0, durability: maxDurability } }}}
}));
}
let teams: GVGTeamType[] = await GVGTeamModel.find({ teamCode: { $in: teamCodes } }).lean();
return teams.map(team => {
let originTeam = brokenTeams.find(origin => origin.teamCode == team.teamCode);
if(originTeam) {
team.originPointId = originTeam.originPointId;
team.curTeamBreak = originTeam.curTeamBreak;
}
return team
})
}
// 加积分
public static async addScore(teamCode: string, battleScore: number, settleScore: number) {
let team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $inc: { battleScore, settleScore } }, { new: true }).lean();
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);
export interface GVGTeamType extends Pick<DocumentType<GVGTeam>, keyof GVGTeam> {
id: number;
};
export type GVGTeamUpdate = Partial<GVGTeamType>; // 将所有字段变成可选项