diff --git a/game-server/app/servers/battle/handler/pvpHandler.ts b/game-server/app/servers/battle/handler/pvpHandler.ts index 07eb68b5b..0a09e8e27 100644 --- a/game-server/app/servers/battle/handler/pvpHandler.ts +++ b/game-server/app/servers/battle/handler/pvpHandler.ts @@ -9,12 +9,13 @@ import { SystemConfigModel } from '../../../db/SystemConfig' import { PvpDefenseModel, PvpDefenseType, OppPlayers } from '../../../db/PvpDefense'; import { oppHeroesDefenseInter, pvpEndParamInter } from '../../../pubUtils/interface'; +import { PVP_HERO_POS, ROBOT_NAME } from '../../../consts'; + +import { HeroType, HeroModel } from '../../../db/Hero'; import { CeAttrNumber } from '../../../db/generalField'; import { checkBattleHeroesByHid } from '../../../services/normalBattleService'; import { BattleRecordModel } from '../../../db/BattleRecord'; -import { HeroModel, HeroType } from '../../../db/Hero'; -import { PVP_HERO_POS, ROBOT_NAME } from '../../../consts'; - +import { PvpRecordModel, HeroesRecord } from '../../../db/PvpRecord'; export default function(app: Application) { return new PvpHandler(app); } @@ -177,14 +178,13 @@ export class PvpHandler { return resResult(STATUS.BATTLE_STATUS_WRONG); } - let flag = 1; // 对比hero信息 let { record: { heroes: dbHeroes, oppRoleId, pos } } = BattleRecord; + + let flag = 1; // 对比hero信息 for(let {hid} of myHeroes) { if(dbHeroes.indexOf(hid) == -1) flag = 0; } - if(!flag) { - return resResult(STATUS.BATTLE_INFO_VALIDATE_ERR); - } + if(!flag) return resResult(STATUS.BATTLE_INFO_VALIDATE_ERR); // 更新军功 let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); @@ -196,8 +196,10 @@ export class PvpHandler { const dicOpp = gameData.pvpOpponent.get(pos); let plusScore = getPlusScore(winStreakNum); + let myHeroRecords = new Array(); let showHeroScores = new Array<{hid: number, addScore: number, plusScore: number, score: number}>(); - for(let { hid, damage, heal, hurt } of myHeroes) { + let addSumScore = 0; + for(let { hid, damage, heal, underDamage } of myHeroes) { let curHeroScore = heroScores.find(cur => cur.hid == hid); if(isSuccess) { if(!curHeroScore) { @@ -208,7 +210,7 @@ export class PvpHandler { } else { curHeroScore.score += dicOpp.score + plusScore; } - score += dicOpp.score + plusScore; + addSumScore += dicOpp.score + plusScore; showHeroScores.push({ hid, addScore: dicOpp.score, plusScore, score: curHeroScore.score }); @@ -219,7 +221,31 @@ export class PvpHandler { }); winStreakNum = 0; } + const myHero = await HeroModel.findByHidAndRole(hid, roleId, 'quality star colorStar lv'); + let { quality, star, colorStar, lv} = myHero; + myHeroRecords.push({ + hid, quality, star, colorStar, lv, damage, heal, underDamage + }); } + + let oppHeroRecords = new Array(); + for(let { hid, damage, heal, underDamage } of myHeroes) { + if(curOpp.isRobot) { + let dicHero = gameData.hero.get(hid); + let { quality, initialStars: star } = dicHero; + oppHeroRecords.push({ + hid, quality, star, colorStar: 0, lv: 0, damage, heal, underDamage + }); + } else { + const myHero = await HeroModel.findByHidAndRole(hid, roleId, 'quality star colorStar lv'); + let { quality, star, colorStar, lv} = myHero; + oppHeroRecords.push({ + hid, quality, star, colorStar, lv, damage, heal, underDamage + }); + } + } + + score += addSumScore; let pLv = getLvByScore(heroScores); // 刷新对手 @@ -235,7 +261,19 @@ export class PvpHandler { $set: { status: isSuccess?1:2 } }, true); - // TODO 记录战报 + let oppRole; + if(curOpp.isRobot) { + oppRole = { ...curOpp.robot, title: 1, topFiveCe: curOpp.robot.defCe}; + } else { + oppRole = await RoleModel.findByRoleId(oppRoleId); + } + + // TODO 战报记录方法抽象 + await PvpRecordModel.createRec({roleId1: roleId, roleId2: oppRoleId, warId: BattleRecord.battleId, attackInfo: { + roleId, roleName, lv: role.lv, sHid: role.sHid, headHid: role.headHid, title: role.title, ce: role.topFiveCe, heroes: myHeroRecords, isSuccess, score: isSuccess?addSumScore:0 + }, defenseInfo: { + roleId: oppRole.roleId, roleName: oppRole.roleName, lv: oppRole.lv, sHid: oppRole.sHid, headHid: oppRole.headHid, title: oppRole.title, ce: oppRole.topFiveCe, heroes: myHeroRecords, isSuccess: !isSuccess, score: 0 + }}) return resResult(STATUS.SUCCESS, { battleCode, isSuccess, diff --git a/shared/db/Item.ts b/shared/db/Item.ts index ae591f756..45aa80159 100644 --- a/shared/db/Item.ts +++ b/shared/db/Item.ts @@ -1,7 +1,7 @@ import BaseModel from './BaseModel'; import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose'; -// const _ = require('underscore'); -const Transaction = require('mongoose-transactions'); +const _ = require('underscore'); +// const Transaction = require('mongoose-transactions'); @index({ roleId: 1, id: 1 }) @index({ seqId: 1 }) @modelOptions({ schemaOptions: { id: false } }) @@ -50,59 +50,59 @@ export default class Item extends BaseModel { return items; } - // public static async decreaseItems(roleId: string, items: Array<{ id: number, count: number, ratio?: number }>, lean = true) { - // let updateItems = new Array<{ id: number, count: number, ratio?: number }>(), hasError: boolean = false, result = new Array(); - // for (let { id, count, ratio } of items) { - // let rec: ItemType; - // if (!ratio) { - // rec = await ItemModel.findOneAndUpdate({ roleId, id, count: { $gte: count } }, { $inc: { count: -1 * count } }, { new: true }).lean(lean); - // } else { - // rec = await ItemModel.findOneAndUpdate({ roleId, id }, { $inc: { count: ratio * count } }, { new: true, upsert: true }).lean(lean); - // } - // if (!!rec) { - // let index = _.findIndex(result,{id}) - // if (!!result[index]) { - // result[index] = { id: rec.id, count: rec.count } - // } else { - // result.push({ id: rec.id, count: rec.count }); - // } - // updateItems.push({ id, count, ratio }); - // } else { - // hasError = true; break; - // } - // } - // if (hasError) { // 数量不足 - // for (let { id, count, ratio } of updateItems) { - // if (!ratio) ratio = -1; - // await ItemModel.findOneAndUpdate({ roleId, id }, { $inc: { count: -ratio * count } }, { new: true }).lean(lean); - // } - // return { hasError: true } - // } else { - // return { hasError: false, result } - // } - // } - public static async decreaseItems(roleId: string, items: Array<{ id: number, count: number, ratio?: number}>, lean = true) { - const transaction = new Transaction(); - let hasError: boolean = false, result = new Array(); - try { - for (let { id, count, ratio } of items) { - if (ratio) ratio = -1; - await transaction.update({ roleId, id, count: { $gte: count } }, { $inc: { count: ratio * count } }, { new: true}); - const rec: ItemType = await transaction.findOneAndUpdate({ roleId, id, count: { $gte: count } }, { $inc: { count: ratio * count } }, { new: true}).lean(lean); - if (!!rec) { - result.push({ id: rec.id, count: rec.count }); - } else { - hasError = true; break; - } + public static async decreaseItems(roleId: string, items: Array<{ id: number, count: number, ratio?: number }>, lean = true) { + let updateItems = new Array<{ id: number, count: number, ratio?: number }>(), hasError: boolean = false, result = new Array(); + for (let { id, count, ratio } of items) { + let rec: ItemType; + if (!ratio) { + rec = await ItemModel.findOneAndUpdate({ roleId, id, count: { $gte: count } }, { $inc: { count: -1 * count } }, { new: true }).lean(lean); + } else { + rec = await ItemModel.findOneAndUpdate({ roleId, id }, { $inc: { count: ratio * count } }, { new: true, upsert: true }).lean(lean); } - await transaction.run(); - return {hasError, result}; - } catch (error) { - await transaction.rollback().catch(console.error); - transaction.clean(); - return {error}; + if (!!rec) { + let index = _.findIndex(result,{id}) + if (!!result[index]) { + result[index] = { id: rec.id, count: rec.count } + } else { + result.push({ id: rec.id, count: rec.count }); + } + updateItems.push({ id, count, ratio }); + } else { + hasError = true; break; + } + } + if (hasError) { // 数量不足 + for (let { id, count, ratio } of updateItems) { + if (!ratio) ratio = -1; + await ItemModel.findOneAndUpdate({ roleId, id }, { $inc: { count: -ratio * count } }, { new: true }).lean(lean); + } + return { hasError: true } + } else { + return { hasError: false, result } } } + // public static async decreaseItems(roleId: string, items: Array<{ id: number, count: number, ratio?: number}>, lean = true) { + // const transaction = new Transaction(); + // let hasError: boolean = false, result = new Array(); + // try { + // for (let { id, count, ratio } of items) { + // if (ratio) ratio = -1; + // await transaction.update({ roleId, id, count: { $gte: count } }, { $inc: { count: ratio * count } }, { new: true}); + // const rec: ItemType = await transaction.findOneAndUpdate({ roleId, id, count: { $gte: count } }, { $inc: { count: ratio * count } }, { new: true}).lean(lean); + // if (!!rec) { + // result.push({ id: rec.id, count: rec.count }); + // } else { + // hasError = true; break; + // } + // } + // await transaction.run(); + // return {hasError, result}; + // } catch (error) { + // await transaction.rollback().catch(console.error); + // transaction.clean(); + // return {error}; + // } + // } public static async deleteAccount(roleId: string) { let result = await ItemModel.deleteMany({ roleId }); diff --git a/shared/db/PvpRecord.ts b/shared/db/PvpRecord.ts new file mode 100644 index 000000000..390507a2a --- /dev/null +++ b/shared/db/PvpRecord.ts @@ -0,0 +1,72 @@ +import BaseModel from './BaseModel'; +import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose'; + + +export class HeroesRecord { + @prop({ required: true, default: 0 }) + hid: number; // 武将id + @prop({ required: true, default: 0 }) + quality: number; // 品质 + @prop({ required: true, default: 0 }) + star: number; // 星级 + @prop({ required: true, default: 0 }) + colorStar: number; // 觉醒 + @prop({ required: true, default: 0 }) + lv: number; // 等级 + @prop({ required: true, default: 0 }) + damage: number; // 伤害 + @prop({ required: true, default: 0 }) + heal: number; // 治疗 + @prop({ required: true, default: 0 }) + underDamage: number; // 承伤 +} + +export class PlayerInfo { + @prop({ required: true }) + roleId: string; // 角色 id + @prop({ required: true }) + roleName: string; // 角色 名 + @prop({ required: true, default: 0 }) + lv: number; // 等级 + @prop({ required: true, default: 0 }) + sHid: number; // 形象 + @prop({ required: true, default: 0 }) + headHid: number; // 头像 + @prop({ required: true, default: 0 }) + title: number; // 爵位 + @prop({ required: true, default: 0 }) + ce: number; // 最高五人战力 + @prop({ required: true, default: false }) + isSuccess: boolean; // 是否胜利 + @prop({ required: true, default: 0 }) + score: number; // 获得的总积分 + @prop({ required: true, type: HeroesRecord, default: [], _id: false }) + heroes: HeroesRecord[]; // 获得的总积分 +} + +@index({ roleId1: 1, updatedAt: -1 }) +@index({ roleId2: 1, updatedAt: -1 }) + +export default class PvpRecord extends BaseModel { + @prop({ required: true }) + roleId1: string; // 角色 id + @prop({ required: true }) + roleId2: string; // 角色 id + + @prop({ required: true, default: 0 }) + warId: number; // 这一关使用的地图 + @prop({ required: true, type: PlayerInfo, default: {}, _id: false }) + attackInfo: PlayerInfo; // 攻方信息 + @prop({ required: true, type: PlayerInfo, default: {}, _id: false }) + defenseInfo: PlayerInfo; // 守方信息 + + + public static async createRec(param: { roleId1: string, roleId2: string, warId: number, attackInfo: PlayerInfo, defenseInfo: PlayerInfo}, lean = true) { + const result = await PvpRecordModel.findOneAndUpdate({}, param, { new: true, upsert: true }).lean(); + return result; + } +} + +export const PvpRecordModel = getModelForClass(PvpRecord); + +export interface PvpRecordType extends Pick, keyof PvpRecord>{}; \ No newline at end of file diff --git a/shared/pubUtils/interface.ts b/shared/pubUtils/interface.ts index ed0ba1e51..5bbcb0e3b 100644 --- a/shared/pubUtils/interface.ts +++ b/shared/pubUtils/interface.ts @@ -94,5 +94,5 @@ export interface pvpEndParamInter { hid: number; damage: number; heal: number; - hurt: number; + underDamage: number; } \ No newline at end of file