357 lines
15 KiB
TypeScript
357 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 })
|
||
lv: number; // 玩家等级
|
||
|
||
@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 })
|
||
groupKey: string; // 战区
|
||
|
||
@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(teamCode: string, cityId: number, areaId: number, groupKey: string) {
|
||
let team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: { cityId, areaId, fromAreaId: areaId, pointId: 0, groupKey } }, { new: true }).lean();
|
||
return team;
|
||
}
|
||
|
||
// 离开队伍
|
||
public static async leaveCity(roleId: string) {
|
||
let res = await GVGTeamModel.updateMany({ roleId }, { $set: { cityId: 0, areaId: 0, pointId: 0 } });
|
||
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 findByRoleAndIndex(roleId: string, index: number, select = '') {
|
||
const teams: GVGTeamType = await GVGTeamModel.findOne({ roleId, index }).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(teamCode: string, update: GVGTeamUpdate) {
|
||
const team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ teamCode }, { $set: update }, { new: true }).lean();
|
||
return team;
|
||
}
|
||
|
||
public static async findRobotTeams(groupKey: string, cityId: number) {
|
||
const team: GVGTeamType[] = await GVGTeamModel.find({ groupKey, cityId, isRobot: true }).lean();
|
||
return team;
|
||
}
|
||
|
||
// 每赛季初刷新机器人
|
||
public static async initRobots(configId: number, groupKey: string, cityId: number, dicPoints: DicGVGAreaPoint[], lv: number) {
|
||
let teams: GVGTeamType[] = [];
|
||
for(let { pointId, areaId, name, head, spine, ce, durability } of dicPoints) {
|
||
let team: GVGTeamType = await GVGTeamModel.findOneAndUpdate({ groupKey, cityId, areaId, pointId }, {
|
||
$setOnInsert: {teamCode: genCode(8), maxDurability: durability, roleName: name, head, spine, frame: EXTERIOR.EXTERIOR_FACECASE, lineupCe: ce, isRobot: true, lv, isBroken: false, startMoveTime: 0, stopMoveTime: 0, guildCode: '', leagueCode: '', leagueName: '', fromAreaId: areaId,
|
||
}, $set: { configId, durability }
|
||
}, { new: true, upsert: true }).lean();
|
||
teams.push(team);
|
||
}
|
||
return teams;
|
||
}
|
||
|
||
public static async findCatapultTeams(groupKey: string, cityId: number) {
|
||
const team: GVGTeamType[] = await GVGTeamModel.find({ groupKey, cityId, isRobot: true, isCatapult: true }).lean();
|
||
return team;
|
||
}
|
||
|
||
// 生成投石车
|
||
public static async initCatapult(configId: number, groupKey: string, cityId: number, leagueCode: string, leagueName: string, areaIds: number[], atk: number, durability: number, lv: number) {
|
||
await GVGTeamModel.bulkWrite(areaIds.map(areaId => {
|
||
return {
|
||
updateOne: {
|
||
filter: { groupKey, 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, lv,
|
||
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(groupKey, 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, pointId: 0 } }, { 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(configId: number, groupKey: string, cityId: number, areaId: number) {
|
||
const team: GVGTeamType[] = await GVGTeamModel.find({ configId, groupKey, 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, groupKey: string, pointId: number) {
|
||
return await GVGTeamModel.exists({ configId, groupKey, 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>; // 将所有字段变成可选项
|