diff --git a/game-server/app/servers/activity/handler/gachaHandler.ts b/game-server/app/servers/activity/handler/gachaHandler.ts index ef3493c8a..273438965 100644 --- a/game-server/app/servers/activity/handler/gachaHandler.ts +++ b/game-server/app/servers/activity/handler/gachaHandler.ts @@ -4,18 +4,15 @@ import { STATUS, GACHA_ID, HERO_QUALITY_TYPE, TASK_TYPE, REFRESH_TIME, TIME_OUTP import { gameData } from "../../../pubUtils/data"; import { GachaListReturn, GachaResult, GachaData } from "../../../domain/activityField/gachaField"; import { UserGachaModel } from "../../../db/UserGacha"; -import { refreshGacha, getFloorResult, getResultFromContentId, getGachaList, getVisitedHeroList, getAllHeroByQuality } from "../../../services/activity/gachaService"; +import { refreshGacha, getFloorResult, getGachaList, getVisitedHeroList, getAllHeroByQuality, GachaPull } from "../../../services/activity/gachaService"; import { RoleModel } from "../../../db/Role"; import { HeroModel } from "../../../db/Hero"; -import { RewardInter } from "../../../pubUtils/interface"; import { handleCost, createHeroes, addItems } from "../../../services/rewardService"; import { getZeroPointD, getTimeFun } from "../../../pubUtils/timeUtil"; import { UserGachaRecModel } from "../../../db/UserGachaRec"; import { ActivityModel } from "../../../db/Activity"; import { checkActivityTask, checkTask } from "../../../services/taskService"; import { RECRUIT } from "../../../pubUtils/dicParam"; -import { transPiece } from "../../../pubUtils/itemUtils"; -import { CreateHeroParam } from "../../../domain/roleField/hero"; export default function (app: Application) { return new GachaHandler(app); @@ -61,37 +58,16 @@ export class GachaHandler { if (!dicGacha.count.includes(count)) return resResult(STATUS.WRONG_PARMS); let userGacha = await UserGachaModel.findByRole(roleId, gachaId, activityId); - let { floor, freeCount, hope, point, pickHero, refFreeTime, count: historyCount } = await refreshGacha(dicGacha, userGacha); + userGacha = await refreshGacha(dicGacha, userGacha); + let { freeCount, point, pickHero, refFreeTime, count: historyCount } = userGacha; if ((gachaId == GACHA_ID.ASSIGN || gachaId == GACHA_ID.TIMELIMIT) && !pickHero) return resResult(STATUS.GACHA_NOT_ASSIGN); let userHeroes = await HeroModel.findByRole(roleId); - let items: RewardInter[] = [], heroInfo: CreateHeroParam[] = [], resultList: GachaResult[] = []; - - let activityData = [];//活动需要统计抽中的英雄、碎片品质 - for (let i = 0; i < count; i++) { - // 按照一般概率抽出 - let { dic: { id: base } } = getRandEelmWithWeight(dicGacha.percent); - let contentId = getFloorResult(gachaId, base, floor); - if (contentId == false) return resResult(STATUS.DIC_DATA_NOT_FOUND); - let result = getResultFromContentId(contentId, lv, hope); - - if (result.hid > 0) { - result.setSetPickHero(pickHero); - let hasHero = userHeroes.find(cur => cur.hid == result.hid); - if (hasHero) { // 已有转换为碎片 - activityData.push({ hid: hasHero.hid, quality: hasHero.quality }); - let { pieceId, count } = transPiece(result.hid); - result.transferToPiece(pieceId, count); - items.push({ id: pieceId, count }); - } else { - heroInfo.push({ hid: result.hid, count: 1 })//默认1个英雄 - } - } else { - items.push({ id: result.id, count: result.count }); - } - resultList.push(result); - } + let gachaPull = new GachaPull(gachaId, lv, userHeroes); + gachaPull.setByUserGacha(dicGacha, userGacha); + let { items, heroInfo, resultList, activityData } = gachaPull.pull(count); + let { hope, floor } = gachaPull.getUserGachaParam(userGacha); let costNum = count; if (count == 1 && dicGacha.free.count > 0) { // 单抽的时候免费 @@ -110,6 +86,7 @@ export class GachaHandler { if (!costResult) return resResult(STATUS.GACHA_COST_NOT_ENOUGH); } // 给东西 + console.log('****', heroInfo) let { heroes } = await createHeroes(roleId, roleName, sid, serverId, funcs, heroInfo); await addItems(roleId, roleName, sid, items); // 更新数据 diff --git a/game-server/app/servers/activity/handler/newHeroGachaHandler.ts b/game-server/app/servers/activity/handler/newHeroGachaHandler.ts index 1fd00314a..26dfe45f0 100644 --- a/game-server/app/servers/activity/handler/newHeroGachaHandler.ts +++ b/game-server/app/servers/activity/handler/newHeroGachaHandler.ts @@ -1,13 +1,13 @@ import { Application, BackendSession } from 'pinus'; import { getRandEelmWithWeight, resResult } from '../../../pubUtils/util'; -import { STATUS } from '../../../consts'; +import { STATUS, GACHA_ID } from '../../../consts'; import { getPlayerNewHeroGachaData } from '../../../services/activity/newHeroGachaService'; import { RoleModel } from '../../../db/Role'; import { HeroModel } from '../../../db/Hero'; import { RewardInter } from '../../../pubUtils/interface'; import { CreateHeroParam } from '../../../domain/roleField/hero'; import { GachaResult } from '../../../domain/activityField/gachaField'; -import { getResultFromContentIdNewHeroActivity } from '../../../services/activity/gachaService'; +import { getResultFromContentIdNewHeroActivity, GachaPull } from '../../../services/activity/gachaService'; import { transPiece } from '../../../pubUtils/itemUtils'; import { addItems, createHeroes, handleCost } from '../../../services/rewardService'; import { ActivityNewHeroGachaModel } from '../../../db/ActivityNewHeroGacha'; @@ -55,13 +55,8 @@ export class NewHeroGachaHandler { const { activityId, hid } = msg; const roleId = session.get('roleId'); const serverId = session.get('serverId'); + await ActivityNewHeroGachaModel.selectedHero(serverId, activityId, roleId, hid); - let activityData: ActivityModelType = await ActivityModel.findActivity(activityId); - let { createTime } = await RoleModel.findByRoleId(roleId); - let playerData = new NewHeroGachaData(activityData, createTime); - for (let pageData of playerData.list) { - await ActivityNewHeroGachaModel.selectedHero(serverId, activityId, roleId, pageData.hid, pageData.hid == hid); - } return resResult(STATUS.SUCCESS); } @@ -91,42 +86,10 @@ export class NewHeroGachaHandler { let userHeroes = await HeroModel.findByRole(roleId); - let items: RewardInter[] = [], heroInfo: CreateHeroParam[] = [], resultList: GachaResult[] = []; - - let floorReward = false;//是否中保底奖励 - let activityData = [];//活动需要统计抽中的英雄、碎片品质 - for (let i = 0; i < count; i++) { - let base = 0; - let goodId = 0; - if (floorReward! && (item.count + i >= item.floorCount)) {//保底奖励 - let reward = item.percent[item.floorReward];//{"id":1,"weight":59,"goodId":1} - base = reward.id; - goodId = reward.goodId; - } else {//按照一般概率抽出 - let randomObj = getRandEelmWithWeight(item.percent);//{"dic":{"id":1,"weight":59,"goodId":1},"index":0} - base = randomObj.dic.id; - goodId = randomObj.dic.goodId; - } - - if (base == item.floorReward) {//中了保底 - floorReward = true; - } - let result = getResultFromContentIdNewHeroActivity(base, goodId, lv); - if (result.hid > 0) { - let hasHero = userHeroes.find(cur => cur.hid == result.hid); - if (hasHero) { // 已有转换为碎片 - activityData.push({ hid: hasHero.hid, quality: hasHero.quality }); - let { pieceId, count } = transPiece(result.hid); - result.transferToPiece(pieceId, count); - items.push({ id: pieceId, count }); - } else { - heroInfo.push({ hid: result.hid, count: 1 })//默认1个英雄 - } - } else { - items.push({ id: result.id, count: result.count }); - } - resultList.push(result); - } + let gachaPull = new GachaPull(GACHA_ID.TIMELIMIT, lv, userHeroes); + gachaPull.setByActivity(item); + let { items, heroInfo, resultList, activityData } = gachaPull.pull(count); + let { hasGetFloor, floorCount } = gachaPull.getActivityParam(); // 消耗东西 let cost = item.cost.map(cur => { return { id: cur.id, count: cur.count * count } }); @@ -134,10 +97,7 @@ export class NewHeroGachaHandler { if (!costResult) return resResult(STATUS.ACTIVITY_RES_NOT_ENOUGH); //记录数据 - await ActivityNewHeroGachaModel.addRecord(serverId, activityId, roleId, hid, count, JSON.stringify(resultList)); - if (floorReward) {//抽中保底奖励,重置统计次数 - await ActivityNewHeroGachaModel.resetCount(serverId, activityId, roleId, hid, 0); - } + await ActivityNewHeroGachaModel.addRecord(serverId, activityId, roleId, hid, floorCount, JSON.stringify(resultList), hasGetFloor); // 给东西 let { heroes } = await createHeroes(roleId, roleName, sid, serverId, funcs, heroInfo); diff --git a/game-server/app/services/activity/gachaService.ts b/game-server/app/services/activity/gachaService.ts index 9d35df2f9..fd06004e6 100644 --- a/game-server/app/services/activity/gachaService.ts +++ b/game-server/app/services/activity/gachaService.ts @@ -2,11 +2,17 @@ import { GachaData, Floor, GachaResult, Hope, GachaListReturn } from "../../doma import { ActivityModel } from "../../db/Activity"; import { DicGacha } from "../../pubUtils/dictionary/DicGacha"; import { UserGachaType, UserGachaModel } from "../../db/UserGacha"; -import { shouldRefresh, getRandEelm, getRandEelmWithWeight } from "../../pubUtils/util"; +import { shouldRefresh, getRandEelm, getRandEelmWithWeight, getFloorStatus } from "../../pubUtils/util"; import { REFRESH_TIME, GACHA_TO_FLOOR, GACHA_FLOOR_TYPE, GACHA_CONTENT_TYPE, HERO_QUALITY_TYPE, GACHA_OCCUPY_HID, IT_TYPE, ITID, CONSUME_TYPE, SPECIAL_ATTR, TIME_OUTPUT_TYPE, GACHA_ID } from "../../consts"; import { getTimeFunD, getZeroPointD } from "../../pubUtils/timeUtil"; import { gameData, getDicGachaFloor } from "../../pubUtils/data"; import { RoleModel } from "../../db/Role"; +import { RewardInter } from "../../pubUtils/interface"; +import { CreateHeroParam } from "../../domain/roleField/hero"; +import { UserGuildType } from "../../db/UserGuild"; +import { transPiece } from "../../pubUtils/itemUtils"; +import { HeroType } from "../../db/Hero"; +import { NewHeroGachaItem } from "../../domain/activityField/newHeroGachaField"; /** * 获取招募列表 @@ -82,6 +88,259 @@ export async function getVisitedHeroList(roleId: string) { return visitedHero; } + + +/** + * 抽卡方法 + */ +export class GachaPull { + private gachaType: GACHA_ID; // 抽卡类型 + private dicFloorType: GACHA_FLOOR_TYPE; // 保底类型 金将保底,指定保底 + // 字典 + private dicFloorCount: number; // 保底次数 + private percent: { id: number, weight: number, goodId?: number }[]; + private dicFloor: { id: number, weight: number, goodId?: number }; // 保底的一项,percent中的一项 + // 玩家数据 + private lv: number; // 玩家等级 + private userHeroes: HeroType[]; // 玩家的所有武将 + private floorCount: number = 0; // 记录下的保底次数 + private hasGetFloor: boolean = false; // 玩家是否达到保底 + private hope: Hope[] = []; // 玩家记录的心愿单达成情况 + + constructor(gachaType: GACHA_ID, lv: number, userHeroes: HeroType[]) { + this.gachaType = gachaType; + if(gachaType == GACHA_ID.NORMAL) { // 元宝招募,金色武将保底,按次数给保底,抽到就重新计算次数,单抽也算 + this.dicFloorType = GACHA_FLOOR_TYPE.GOLD; + } else if (gachaType == GACHA_ID.ASSIGN || gachaType == GACHA_ID.TIMELIMIT) { // 求贤若渴,和活动抽卡金色保底,伪随机,n次内给且只给一个,单抽也算 + this.dicFloorType = GACHA_FLOOR_TYPE.ASSIGN; + } + this.userHeroes = userHeroes; + this.lv = lv; + } + + // 一般抽卡setter + public setByUserGacha(dicGacha: DicGacha, userGacha: UserGachaType) { + // 字典方面 + let percent = dicGacha.percent; + // 设置pickup的武将 + let newPercent = []; + for(let { id, weight } of percent) { + if(id == gameData.gachaContentHero.get(0)) { + newPercent.push({ id, weight, goodId: userGacha.pickHero }) + } else { + newPercent.push({ id, weight }); + } + } + this.percent = newPercent; + if(dicGacha.floorReward > 0) { + this.dicFloor = this.percent[dicGacha.floorReward - 1]; + } + this.dicFloorCount = getDicGachaFloor(this.dicFloorType); + // 玩家数据 + let userFloor = userGacha.floor.find(cur => cur.id == this.dicFloorType); + if(userFloor) { + this.floorCount = userFloor.count; + this.hasGetFloor = userFloor.hasGetFloor||false; + } + this.hope = userGacha.hope; + } + // 新武将活动setter + public setByActivity(item: NewHeroGachaItem) { + this.floorCount = item.count; + this.hasGetFloor = item.hasGetFloor; + this.percent = item.percent; + this.dicFloorCount = item.floorCount; + if(item.floorReward >= 0) { + this.dicFloor = item.percent[item.floorReward] + } + } + + private getFloorResult(base: { id: number, weight: number, goodId?: number }) { + if(!this.dicFloor) return base; + + let isTarget = base.id == this.dicFloor.id; // 是否抽到的就是那个保底 + if(this.dicFloorType == GACHA_FLOOR_TYPE.GOLD) { // 元宝招募 橙色 按次数保底,抽到就重计 + if(isTarget || this.floorCount + 1 >= this.dicFloorCount) { + this.floorCount = 0; + return this.dicFloor; + } else { + this.floorCount ++; + return base; + } + } else if (this.dicFloorType == GACHA_FLOOR_TYPE.ASSIGN) { + let result = base; + if(isTarget || this.floorCount + 1 >= this.dicFloorCount) { + if(this.hasGetFloor) { // 已经获得过一次保底了, 不给,换个给 + let { dic } = getRandEelmWithWeight(this.percent.filter(cur => cur.id != this.dicFloor.id)); + result = dic + } else { + this.hasGetFloor = true; + result = this.dicFloor; + } + } + this.floorCount ++; + if(this.floorCount >= this.dicFloorCount) { + this.hasGetFloor = false; + this.floorCount = 0; + } + console.log('******', this.floorCount, this.dicFloorCount, this.hasGetFloor ) + return result; + } else { + return base + } + } + + /** + * 根据contentId获得抽卡结果(包括心愿单) + * @param contentId dic_zyz_gachaContent的id + * @param lv 玩家等级 + * @param hope 玩家心愿单 + */ + private getResultFromContentId(contentId: number, goodId?: number) { + let dic = gameData.gachaContent.get(contentId); + let { type, param, count } = dic; + if (type == GACHA_CONTENT_TYPE.HERO) { + let pool: number[] = []; + if(this.hope.length > 0) { + pool = this.getPoolByHope(this.hope, param[0]); // 根据心愿单获得卡池 + } else { + pool = getAllHeroByQuality(param[0]); // 没有心愿单就根据武将颜色 + } + let hero = getRandEelm(pool); + let result = new GachaResult(contentId); + result.setHero(hero[0]); + if (goodId > 0) { + result.setHero(goodId); + } + return result + } else { + let pool: number[] = []; + if (type == GACHA_CONTENT_TYPE.HERO_PIECE) { + pool = getAllItemByQuality(IT_TYPE.HERO_PIECE, param[0], this.lv); + } else if (type == GACHA_CONTENT_TYPE.BLUEPRT) { + pool = getAllItemByQuality(IT_TYPE.BLUEPRT, param[0], this.lv); + } else if (type == GACHA_CONTENT_TYPE.JEWEL) { + pool = getAllJewelByLv(param[0]); + } else if (type == GACHA_CONTENT_TYPE.TERAPH_MATERIAL) { + pool = param; + } else if (type == GACHA_CONTENT_TYPE.SUIT_PAPER) { + pool = getSuitPaper(this.lv); + } + let item = getRandEelm(pool); + let result = new GachaResult(contentId); + result.setItem(item[0], count); + if (goodId > 0) { + result.setItem(goodId, count); + } + return result; + } + } + + /** + * 心愿 + * @param hope 玩家数据里的心愿单 + * @param qualtiy 武将品质 + */ + private getPoolByHope(hope: Hope[], qualtiy: number) { + if (qualtiy == HERO_QUALITY_TYPE.GOLD) { + let hopeMap = new Map(); + let hasGetHope: number[] = []; + for (let h of hope) { + if (h.hid > 0) { + hopeMap.set(h.id, h); + if (h.hasGet) hasGetHope.push(h.id); + } + } + + let list = gameData.gachaHope.map(cur => { + return { ...cur, hasGet: hopeMap.get(cur.id)?.hasGet || false }; + }) + let { dic: { id, hasGet } } = getRandEelmWithWeight(list); + if (id == 0 || hasGet) { + return getAllHeroByQuality(qualtiy).filter(cur => !hasGetHope.includes(cur)); + } else { + if (hopeMap.has(id)) { + let curHope = hopeMap.get(id); + curHope.hasGet = true; + return [curHope.hid]; + } else { + return getAllHeroByQuality(qualtiy).filter(cur => !hasGetHope.includes(cur)); + } + } + } else { + return getAllHeroByQuality(qualtiy); + } + } + + public pull(count: number) { + let items: RewardInter[] = [], heroInfo: CreateHeroParam[] = [], resultList: GachaResult[] = []; + + let activityData = [];//活动需要统计抽中的英雄、碎片品质 + for (let i = 0; i < count; i++) { + // 按照一般概率抽出 + let { dic } = getRandEelmWithWeight(this.percent); + let { id: contentId, goodId } = this.getFloorResult(dic); // 根据保底替换 + contentId = this.getPurpleFloor(count, i, contentId, resultList); + let result = this.getResultFromContentId(contentId, goodId); + + if (result.hid > 0) { + let hasHero = this.userHeroes.find(cur => cur.hid == result.hid); + if (hasHero) { // 已有转换为碎片 + activityData.push({ hid: hasHero.hid, quality: hasHero.quality }); + let { pieceId, count } = transPiece(result.hid); + result.transferToPiece(pieceId, count); + items.push({ id: pieceId, count }); + } else { + heroInfo.push({ hid: result.hid, count: 1 })//默认1个英雄 + } + } else { + items.push({ id: result.id, count: result.count }); + } + resultList.push(result); + } + + return { items, heroInfo, resultList, activityData } + } + + private getPurpleFloor(count: number, index: number, contentId: number, resultList: GachaResult[]) { + if(this.gachaType == GACHA_ID.NORMAL && count == 10 && index == count - 1) { // 10连到最后一抽 + let { type, param } = gameData.gachaContent.get(contentId); + if(type != GACHA_CONTENT_TYPE.HERO || param[0] < HERO_QUALITY_TYPE.PURPLE) { + let hasPurple = false; + for(let { contentId } of resultList) { + let { type, param } = gameData.gachaContent.get(contentId); + if(type == GACHA_CONTENT_TYPE.HERO && param[0] >= HERO_QUALITY_TYPE.PURPLE) { + hasPurple = true; break; + } + } + if(!hasPurple) { + return gameData.gachaContentHero.get(HERO_QUALITY_TYPE.PURPLE); + } + } + } + return contentId + } + + // 获得需要储存的数据 + // 一般抽卡getter + public getUserGachaParam(userGacha: UserGachaType) { + let floor = userGacha.floor||[]; + let curFloor = floor.find(cur => cur.id == this.dicFloorType); + if(curFloor) { + curFloor.hasGetFloor = this.hasGetFloor; + curFloor.count = this.floorCount; + } else { + floor.push({ id: this.dicFloorType, hasGetFloor: this.hasGetFloor, count: this.floorCount }) + } + return { hope: this.hope, floor } + } + // 活动getter + public getActivityParam() { + return { hasGetFloor: this.hasGetFloor, floorCount: this.floorCount }; + } +} + + /** * @description 获得保底结果 * @param gachaId 招募表id @@ -177,78 +436,6 @@ function getHeroQuality(id: number) { } } -/** - * 根据contentId获得抽卡结果(包括心愿单) - * @param contentId dic_zyz_gachaContent的id - * @param lv 玩家等级 - * @param hope 玩家心愿单 - */ -export function getResultFromContentId(contentId: number, lv: number, hope: Hope[]) { - let dic = gameData.gachaContent.get(contentId); - let { type, param, count } = dic; - if (type == GACHA_CONTENT_TYPE.HERO) { - let pool: number[] = getPoolByHope(hope, param[0]); - - let hero = getRandEelm(pool); - let result = new GachaResult(contentId); - result.setHero(hero[0]); - return result - } else { - let pool: number[] = []; - if (type == GACHA_CONTENT_TYPE.HERO_PIECE) { - pool = getAllItemByQuality(IT_TYPE.HERO_PIECE, param[0], lv); - } else if (type == GACHA_CONTENT_TYPE.BLUEPRT) { - pool = getAllItemByQuality(IT_TYPE.BLUEPRT, param[0], lv); - } else if (type == GACHA_CONTENT_TYPE.JEWEL) { - pool = getAllJewelByLv(param[0]); - } else if (type == GACHA_CONTENT_TYPE.TERAPH_MATERIAL) { - pool = param; - } else if (type == GACHA_CONTENT_TYPE.SUIT_PAPER) { - pool = getSuitPaper(lv); - } - let item = getRandEelm(pool); - let result = new GachaResult(contentId); - result.setItem(item[0], count); - return result; - } -} - -/** - * 心愿 - * @param hope 玩家数据里的心愿单 - * @param qualtiy 武将品质 - */ -function getPoolByHope(hope: Hope[], qualtiy: number) { - if (qualtiy == HERO_QUALITY_TYPE.GOLD) { - let hopeMap = new Map(); - let hasGetHope: number[] = []; - for (let h of hope) { - if (h.hid > 0) { - hopeMap.set(h.id, h); - if (h.hasGet) hasGetHope.push(h.id); - } - } - - let list = gameData.gachaHope.map(cur => { - return { ...cur, hasGet: hopeMap.get(cur.id)?.hasGet || false }; - }) - let { dic: { id, hasGet } } = getRandEelmWithWeight(list); - if (id == 0 || hasGet) { - return getAllHeroByQuality(qualtiy).filter(cur => !hasGetHope.includes(cur)); - } else { - if (hopeMap.has(id)) { - let curHope = hopeMap.get(id); - curHope.hasGet = true; - return [curHope.hid]; - } else { - return getAllHeroByQuality(qualtiy).filter(cur => !hasGetHope.includes(cur)); - } - } - } else { - return getAllHeroByQuality(qualtiy); - } -} - /** * 根据品质获得武将池 * @param quality 品质 diff --git a/game-server/app/services/activity/newHeroGachaService.ts b/game-server/app/services/activity/newHeroGachaService.ts index 3c1f093ac..d31a30105 100644 --- a/game-server/app/services/activity/newHeroGachaService.ts +++ b/game-server/app/services/activity/newHeroGachaService.ts @@ -21,7 +21,7 @@ export async function newHeroGachaActivity(serverId: number, roleId: string) { return null; } let activityData: ActivityModelType = activityDataArray[0]; - let playerRecord: ActivityNewHeroGachaModelType[] = await ActivityNewHeroGachaModel.findData(serverId, activityData.activityId, roleId); + let playerRecord: ActivityNewHeroGachaModelType = await ActivityNewHeroGachaModel.findData(serverId, activityData.activityId, roleId); let { createTime } = await RoleModel.findByRoleId(roleId); let playerData = new NewHeroGachaData(activityData, createTime); playerData.setPlayerRecords(playerRecord); @@ -39,7 +39,7 @@ export async function newHeroGachaActivity(serverId: number, roleId: string) { */ export async function getPlayerNewHeroGachaData(activityId: number, serverId: number, roleId: string) { let activityData: ActivityModelType = await ActivityModel.findActivity(activityId); - let playerRecord: ActivityNewHeroGachaModelType[] = await ActivityNewHeroGachaModel.findData(serverId, activityId, roleId); + let playerRecord: ActivityNewHeroGachaModelType = await ActivityNewHeroGachaModel.findData(serverId, activityId, roleId); let { createTime } = await RoleModel.findByRoleId(roleId); let playerData = new NewHeroGachaData(activityData, createTime); diff --git a/shared/consts/constModules/battleConst.ts b/shared/consts/constModules/battleConst.ts index 0a6d4c290..799bdc14c 100644 --- a/shared/consts/constModules/battleConst.ts +++ b/shared/consts/constModules/battleConst.ts @@ -105,7 +105,7 @@ export const DAILY_CONST = { export const DUNGEON_CONST = { REFRESH_TIME: 5, // 每天加点刷新 - MAX_CNT: 10, // 最大挑战次数 + MAX_CNT: 100, // 最大挑战次数 MAX_BUY_CNT: 10 // 最大购买次数 } diff --git a/shared/consts/constModules/sysConst.ts b/shared/consts/constModules/sysConst.ts index 58c4df58f..50df5564f 100644 --- a/shared/consts/constModules/sysConst.ts +++ b/shared/consts/constModules/sysConst.ts @@ -644,9 +644,9 @@ export enum GACHA_ID { // 抽卡保底类型 export enum GACHA_FLOOR_TYPE { - PURPLE = 1, // 元宝招募,保底紫色 - GOLD = 2, // 元宝招募,保底金色 - ASSIGN = 3, // 求贤若渴,保底指定武将 + PURPLE = 1, // 紫色保底,10连必定会出一个紫的,单抽不算 + GOLD = 2, // 金色武将保底,按次数给保底,抽到就重新计算次数,单抽也算 + ASSIGN = 3, // 求贤若渴,和活动抽卡金色保底,伪随机,n次内给且只给一个,单抽也算 } // 抽卡对应保底类型 diff --git a/shared/db/ActivityNewHeroGacha.ts b/shared/db/ActivityNewHeroGacha.ts index 6fe57e5c6..e8359b72e 100644 --- a/shared/db/ActivityNewHeroGacha.ts +++ b/shared/db/ActivityNewHeroGacha.ts @@ -2,12 +2,16 @@ import BaseModel from './BaseModel'; import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose'; export class Record { + @prop({ required: true }) + hid: number; // 选中的武将id @prop({ required: true }) count: number; // 次数 @prop({ required: true }) reward: string; // 奖励内容 @prop({ required: true }) time: Date; // 抽卡时间 + @prop({ required: true }) + hasGetFloor: boolean; // 是否抽到保底了 } /** @@ -23,44 +27,38 @@ export default class Activity_New_Hero_Gacha extends BaseModel { @prop({ required: true }) roleId: string; // 用户Id @prop({ required: true }) - selected: boolean; // 是否选中默认false - @prop({ required: true }) - hid: number; // 武将id + selectedHid: number; // 玩家选中的武将id @prop({ required: true }) count: number; // 抽卡次数,抽中大奖后重新统计 @prop({ required: true }) records: Record[]; // 抽卡历史记录 + @prop({ required: true }) + hasGetFloor: boolean; // 是否抽到保底了 //重置统计次数 - public static async resetCount(serverId: number, activityId: number, roleId: string, hid: number, count: number) { - let result: ActivityNewHeroGachaModelType = await ActivityNewHeroGachaModel.findOneAndUpdate({ serverId, roleId, activityId, hid }, + public static async resetCount(serverId: number, activityId: number, roleId: string, count: number) { + let result: ActivityNewHeroGachaModelType = await ActivityNewHeroGachaModel.findOneAndUpdate({ serverId, roleId, activityId, }, { $set: { count } }, { upsert: true, new: true }).lean(true); return result; } //抽卡记录 - public static async addRecord(serverId: number, activityId: number, roleId: string, hid: number, count: number, reward: string) { - let result: ActivityNewHeroGachaModelType = await ActivityNewHeroGachaModel.findOneAndUpdate({ serverId, roleId, activityId, hid }, - { $inc: { count }, $push: { records: { count, reward, time: new Date() } } }, { upsert: true, new: true }).lean(true); + public static async addRecord(serverId: number, activityId: number, roleId: string, hid: number, count: number, reward: string, hasGetFloor: boolean) { + let result: ActivityNewHeroGachaModelType = await ActivityNewHeroGachaModel.findOneAndUpdate({ serverId, roleId, activityId }, + { $set: { count, hasGetFloor }, $push: { records: { hid, count, reward, time: new Date(), hasGetFloor } } }, { upsert: true, new: true }).lean(true); return result; } //设置选中武将 - public static async selectedHero(serverId: number, activityId: number, roleId: string, hid: number, selected: boolean) { - let result: ActivityNewHeroGachaModelType[] = await ActivityNewHeroGachaModel.findOneAndUpdate( - { serverId, roleId, activityId, hid }, { $set: { selected } }, { upsert: true, new: true }).lean(true); - return result; - } - - //根据活动id查询活动数据 - public static async findDataByHid(serverId: number, activityId: number, roleId: string, hid: number) { - let result: ActivityNewHeroGachaModelType = await ActivityNewHeroGachaModel.findOne({ serverId, roleId, activityId, hid }).lean(true); + public static async selectedHero(serverId: number, activityId: number, roleId: string, selectedHid: number) { + let result: ActivityNewHeroGachaModelType = await ActivityNewHeroGachaModel.findOneAndUpdate( + { serverId, roleId, activityId }, { $set: { selectedHid } }, { upsert: true, new: true }).lean(true); return result; } //根据活动id查询活动数据 public static async findData(serverId: number, activityId: number, roleId: string) { - let result: ActivityNewHeroGachaModelType[] = await ActivityNewHeroGachaModel.find({ serverId, roleId, activityId }).lean(true); + let result: ActivityNewHeroGachaModelType = await ActivityNewHeroGachaModel.findOne({ serverId, roleId, activityId }).lean(true); return result; } diff --git a/shared/db/UserGacha.ts b/shared/db/UserGacha.ts index 5cd7eed04..df2c9086e 100644 --- a/shared/db/UserGacha.ts +++ b/shared/db/UserGacha.ts @@ -8,6 +8,8 @@ class Floor { id: number; // 保底类型 1-紫将保底 2-金将保底 3-指定将保底 @prop({ required: true }) count: number; // 抽卡次数 + @prop({ required: true }) + hasGetFloor: boolean; // 是否抽到保底了 } /** diff --git a/shared/domain/activityField/gachaField.ts b/shared/domain/activityField/gachaField.ts index db8069186..1c47ac4be 100644 --- a/shared/domain/activityField/gachaField.ts +++ b/shared/domain/activityField/gachaField.ts @@ -4,7 +4,7 @@ import { prop } from '@typegoose/typegoose'; import { UserGachaType } from '../../db/UserGacha'; import { getTimeFun } from '../../pubUtils/timeUtil'; import { DicGacha } from '../../pubUtils/dictionary/DicGacha'; -import { GACHA_OCCUPY_HID } from '../../consts'; +import { GACHA_OCCUPY_HID, GACHA_ID } from '../../consts'; import { gameData } from '../../pubUtils/data'; import { getFloorStatus } from '../../pubUtils/util'; diff --git a/shared/domain/activityField/newHeroGachaField.ts b/shared/domain/activityField/newHeroGachaField.ts index e92fb62db..6402d48cf 100644 --- a/shared/domain/activityField/newHeroGachaField.ts +++ b/shared/domain/activityField/newHeroGachaField.ts @@ -10,6 +10,7 @@ export class NewHeroGachaItem { selected: boolean = false;//选中武将 floorCount: number = 0;//保底最大的次数,一定会出现一次 count: number = 0;//多少次没有抽中 + hasGetFloor: boolean = false; // 是否有抽到保底,伪随机算法,抽到后未到保底次数强制不给 hid: number = 0;//武将id name: string = '';//名字 cost: RewardInter[];//每次抽卡消耗资源 @@ -51,13 +52,14 @@ export class NewHeroGachaData extends ActivityBase { } //解析玩家记录 - public setPlayerRecords(data: ActivityNewHeroGachaModelType[]) { + public setPlayerRecords(data: ActivityNewHeroGachaModelType) { + if (!data) { + return; + } for (let item of this.list) { - let index = data.findIndex(obj => { return obj.hid == item.hid }); - if (index != -1) { - item.count = data[index].count ? data[index].count : 0; - item.selected = data[index].selected ? data[index].selected : false; - } + item.count = data.count ? data.count : 0; + item.hasGetFloor = data.hasGetFloor||false; + item.selected = (data && data.selectedHid == item.hid); } } diff --git a/shared/pubUtils/dictionary/DicGacha.ts b/shared/pubUtils/dictionary/DicGacha.ts index fcb2d9c6d..5b6070945 100644 --- a/shared/pubUtils/dictionary/DicGacha.ts +++ b/shared/pubUtils/dictionary/DicGacha.ts @@ -13,6 +13,8 @@ export interface DicGacha { readonly cost: RewardInter[]; // 概率 readonly percent: { id: number, weight: number }[]; + // 哪一个是大奖 + readonly floorReward: number; } export const dicGacha = new Map(); // id => dic