import { ABI_TYPE } from "../../consts/constModules/abilityConst"; import { PUSH_ROUTE, ROUGELIKE_SKILLTYPE, ROUGE_EFFECT_TYPE, ROUGE_EFFECT_TYPE_KIND, ROUGE_LIKE_CARD_TYPE, ROUGE_SLOT_LIMIT } from "../../consts"; import { RougelikeCardModel, RougelikeCardPara, RougelikeCardType } from "../../db/RougelikeCard"; import { Card, RougelikeCharaModel, RougelikeCharaPara, RougelikeCharaType } from "../../db/RougelikeChara"; import { RougelikeRecordModel } from "../../db/RougelikeRecord"; import { gameData, getRougeEffectTypeKind } from "../../pubUtils/data"; import { DicRougePassiveCardPlan } from "../../pubUtils/dictionary/DicRougePassiveCardPlan"; import { getRandEelm } from "../../pubUtils/util"; import { RougelikeTechModel } from "../../db/RougelikeTech"; import { getAuthorTypeCardNum } from "./rougeService"; import * as util from 'util'; import { DicRougePassiveCard } from "../../pubUtils/dictionary/DicRougePassiveCard"; import { sendMessageToUserWithSuc } from "../pushService"; export class holyId { cardCode: string; cardId: number; useCount: number; } export class RougeEffect { roleId: string; gameCode: string; sid: string; newEffect: { effectType: number, effectParam: number[], cardCode?: string }[] = []; holyMap = new Map(); updateHolyMap = new Map(); updateCharaMap = new Map(); updateCardMap = new Map(); dbCharas: RougelikeCharaType[] = []; dbCards: RougelikeCardType[] = []; constructor(roleId: string, gameCode: string, sid?: string) { this.roleId = roleId || ''; this.gameCode = gameCode || ''; this.sid = sid || ''; } /** * 根据类型获取effectId * @param effectTypes * @param holyIds * @returns */ public async getEffectData(effectTypes: number[], holyIds?: holyId[]) { let kinds = getRougeEffectTypeKind(effectTypes); if (kinds.includes(ROUGE_EFFECT_TYPE_KIND.HOLY)) { if (!holyIds || holyIds.length == 0) { const dbCards = await RougelikeCardModel.findByGameCodeAndType(this.gameCode, ROUGE_LIKE_CARD_TYPE.HOLY); holyIds = dbCards.map((cur) => { return { cardCode: cur.cardCode, cardId: cur.cardId, useCount: cur.useCount || 0 } }); } if (!holyIds || holyIds.length == 0) return { newEffect: this.newEffect, holyMap: this.holyMap }; for (const { cardCode, cardId, useCount } of holyIds) { let effectIds = gameData.rougeHolyCard.get(cardId)?.effectId || []; if (effectIds.length == 0) continue; for (const effectId of effectIds) { const effectDataOne = gameData.rougeEffect.get(effectId); if (!effectDataOne) continue; const effectParam = effectDataOne.effectParam || []; for (let effectType of effectTypes) { if (effectType != effectDataOne.effectType || 0) continue; this.newEffect.push({ effectType, effectParam, cardCode }); this.holyMap.set(cardCode, { cardCode, cardId, useCount }) } } } } if (kinds.includes(ROUGE_EFFECT_TYPE_KIND.TECH)) { let tech = await RougelikeTechModel.findByRoleId(this.roleId, 'effectIds'); for (let effectId of (tech?.effectIds || [])) { const effectDataOne = gameData.rougeEffect.get(effectId); if (!effectDataOne) continue; for (let effectType of effectTypes) { if (effectType != effectDataOne.effectType || 0) continue; this.newEffect.push({ effectType, effectParam: effectDataOne.effectParam || [] }); } } } return { newEffect: this.newEffect, holyMap: this.holyMap } } /* ** * 获取圣物时生效 * @param gameCode */ public async getEffectImmediate(holyIds?: holyId[]) { let result: { charas?: Map, cards?: Map } = {}; this.dbCharas = await RougelikeCharaModel.findByGameCode(this.gameCode); this.dbCards = await RougelikeCardModel.findByGameCode(this.gameCode); await this.getEffectData([ ROUGE_EFFECT_TYPE.HOLY_CHARA_SLOT_UNLOCK_ALL, //2002 ROUGE_EFFECT_TYPE.HOLY_CHARA_SLOT_UNLOCK_RAND, //2003 ROUGE_EFFECT_TYPE.HOLY_PASSIVE_UPDATE_RAND, //2006 ROUGE_EFFECT_TYPE.HOLY_UPDATE_PASSIVE_BY_LV, //2012 ROUGE_EFFECT_TYPE.HOLY_REPAIRE_HOLY, //2015 ROUGE_EFFECT_TYPE.HOLY_CHARA_SLOT_UNLOCK_POINT,//2023 ], holyIds) await this.getCharaSlot(); await this.getRandCharaSlot(); await this.getRandomCardLv() await this.getPassiveLv(); await this.getRecoveryHoly(); await this.getSlotUnlockPoint() result = { charas: this.updateCharaMap, cards: this.updateCardMap }; return result; } // 获得该圣物时,所有学员立刻解锁X个特性槽 2002 private async getCharaSlot() { if (this.newEffect.length == 0 || this.dbCharas.length == 0) return; for (const { effectParam, effectType, cardCode } of this.newEffect) { if (effectType != ROUGE_EFFECT_TYPE.HOLY_CHARA_SLOT_UNLOCK_ALL) continue; if (effectParam.length == 0) continue; let isUseCount = false; if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; for (let val of this.dbCharas) { let { charaCode, cards = [] } = val; let unlockNum = effectParam[0] || 0; for (let i = 0; i < unlockNum; i++) { unlockNum = effectParam[0] || 0; if (cards.length >= ROUGE_SLOT_LIMIT) continue; for (let index = 0; index < ROUGE_SLOT_LIMIT; index++) { if (cards.find(cur => cur.index == index) != undefined || unlockNum == 0) continue; cards.push({ index, cardCode: '', cardId: 0 }); this.updateCharaMap.set(charaCode, val); unlockNum--; isUseCount = true; } } } if (isUseCount) this.updateHolyMapUseCount(this.holyMap.get(cardCode)); } } private updateHolyMapUseCount(holy: { cardCode: string, cardId: number, useCount: number }) { let { cardCode, useCount = 0, cardId } = (holy || {}); if (!cardId || !cardCode) return; let val = this.dbCards.find(cur => cur.cardCode == cardCode); if (val == undefined) return; useCount = (useCount + 1) >= 0 ? (useCount + 1) : 0 this.updateCardMap.set(cardCode, { ...val, useCount }); this.holyMap.set(cardCode, { cardCode, cardId, useCount }); } // 获得该圣物时,随机解锁X个学员的Y个特性槽 2003 private async getRandCharaSlot() { if (this.newEffect.length == 0 || this.dbCharas.length == 0) return; for (const { effectParam, effectType, cardCode } of this.newEffect) { if (effectType != ROUGE_EFFECT_TYPE.HOLY_CHARA_SLOT_UNLOCK_RAND) continue; if (effectParam.length == 0) continue; let isUseCount = false; if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; const randomNum = effectParam[0] || 0; let unlockNum = effectParam[1] || 0; this.dbCharas.sort((a, b) => { if (a.seqId < b.seqId) return -1; if (a.seqId > b.seqId) return 1; return 0; }); let charas = getRandEelm(this.dbCharas.slice(0, 6).filter(cur => cur.cards.length < ROUGE_SLOT_LIMIT), randomNum); for (let val of charas) { unlockNum = effectParam[1] || 0; let { charaCode, cards = [] } = val; for (let index = 0; index < ROUGE_SLOT_LIMIT; index++) { if (cards.find(cur => cur.index == index) != undefined || unlockNum == 0) continue; cards.push({ index, cardCode: '', cardId: 0 }); this.updateCharaMap.set(charaCode, val); unlockNum--; isUseCount = true; } } if (isUseCount) this.updateHolyMapUseCount(this.holyMap.get(cardCode)); } } // 随机升级X个已装备的特性 2006 private async getRandomCardLv() { if (this.newEffect.length == 0 || this.dbCards.length == 0) return; let pushCards: RougelikeCardType[] = []; for (const { effectParam, effectType, cardCode } of this.newEffect) { if (effectType != ROUGE_EFFECT_TYPE.HOLY_PASSIVE_UPDATE_RAND) continue; if (effectParam.length == 0) continue; if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; const randomNum = effectParam[0] || 0; let random = this.dbCards.filter(cur => cur.type == ROUGE_LIKE_CARD_TYPE.PASSIVE && cur.charaId && cur.charaId != 0); let newRandom: RougelikeCardType[] = []; for (let cur of random) { // if (cur.type != ROUGE_LIKE_CARD_TYPE.PASSIVE || cur.charaId == 0) continue; let passiveCardDataMap = this.getPassiveData(cur.cardId); if (!passiveCardDataMap.has(cur.lv + 1)) continue; newRandom.push({ ...cur, cardId: passiveCardDataMap.get(cur.lv + 1).id, lv: cur.lv + 1 }); } if (newRandom && newRandom.length > 0) { let cards = getRandEelm(newRandom, randomNum); cards.forEach(async cur => { this.updateCardMap.set(cur.cardCode, cur), await this.updateCharaCards(cur, cardCode, cur.cardId); }); pushCards.push(...cards); this.updateHolyMapUseCount(this.holyMap.get(cardCode)); } } if (pushCards.length > 0) { await sendMessageToUserWithSuc(this.roleId, PUSH_ROUTE.ROUGE_PASSIVE_CARD_UP_LV, { upLvCards: pushCards }, this.sid); } } private getPassiveData(cardId: number) { let passiveCardDataMap = new Map() const passiveCardData = gameData.rougePassiveCard.get(cardId); if (!passiveCardData) return passiveCardDataMap; const passiveCardByGroupData = gameData.rougePassiveCardByGroup.get(passiveCardData.group || 0); if (passiveCardByGroupData.length == 0 || passiveCardByGroupData.length == 1) return passiveCardDataMap; passiveCardDataMap = passiveCardByGroupData.reduce((result, cur) => { result.set(cur.lv, cur); return result; }, new Map()); return passiveCardDataMap; } // 获得该圣物时立即升级所有X星特性卡 2012 private async getPassiveLv() { if (this.newEffect.length == 0) return; let pushCards: RougelikeCardType[] = []; for (const { effectParam, effectType, cardCode } of this.newEffect) { if (effectType != ROUGE_EFFECT_TYPE.HOLY_UPDATE_PASSIVE_BY_LV) continue; if (effectParam.length == 0) continue; let isUseCount = false; if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; const level = effectParam[0] || 0; for (let val of this.dbCards) { let { lv, cardId, cardCode } = val; if (lv != level) continue; let passiveCardDataMap = this.getPassiveData(cardId); if (!passiveCardDataMap.has(lv + 1)) continue; let id = passiveCardDataMap.get(lv + 1).id; this.updateCardMap.set(cardCode, { ...val, lv: lv + 1, cardId: passiveCardDataMap.get(lv + 1).id }); pushCards.push({ ...val, lv: lv + 1, cardId: passiveCardDataMap.get(lv + 1).id }); if (val.charaId && val.charaId > 0) { await this.updateCharaCards(val, cardCode, id); } isUseCount = true; } if (isUseCount) this.updateHolyMapUseCount(this.holyMap.get(cardCode)); } if (pushCards.length > 0) { await sendMessageToUserWithSuc(this.roleId, PUSH_ROUTE.ROUGE_PASSIVE_CARD_UP_LV, { upLvCards: pushCards }, this.sid); } } private async updateCharaCards(val: RougelikeCardType, cardCode: string, id: number) { for (let obj of this.dbCharas) { if (obj.charaId != val.charaId) continue; for (let card of (obj.cards || [])) { if (card.cardCode != cardCode) continue; card.cardId = id; } this.updateCharaMap.set(obj.charaCode, obj); } } // 获得该圣物时,随机修复X个已损毁的圣物 2015 private async getRecoveryHoly() { if (this.newEffect.length == 0) return; for (const { effectParam, effectType, cardCode } of this.newEffect) { if (effectType != ROUGE_EFFECT_TYPE.HOLY_REPAIRE_HOLY) continue; if (effectParam.length == 0) continue; let isUseCount = false; if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; const num = effectParam[0] || 0; let canRandomCards: RougelikeCardType[] = [] this.dbCards.forEach(cur => { const { cardCode, cardId, useCount = 0, type } = cur; const holyCardData = gameData.rougeHolyCard.get(cardId); let tempUseCount = holyCardData?.useCount || 0; if (tempUseCount > 0 && useCount > 0 && type == ROUGE_LIKE_CARD_TYPE.HOLY) canRandomCards.push(cur); }) let randomCards = getRandEelm(canRandomCards, num); for (let val of randomCards) { let { cardCode, cardId } = val; val.useCount -= 1; this.updateCardMap.set(cardCode, val); if (this.holyMap.has(cardCode)) this.holyMap.set(cardCode, { cardCode, cardId, useCount: val.useCount }); isUseCount = true; } if (isUseCount) this.updateHolyMapUseCount(this.holyMap.get(cardCode)); } } //2023 private async getSlotUnlockPoint() { if (this.newEffect.length == 0) return; for (const { effectParam, effectType, cardCode } of this.newEffect) { if (effectType != ROUGE_EFFECT_TYPE.HOLY_CHARA_SLOT_UNLOCK_POINT) continue; if (effectParam.length == 0) continue; let isUseCount = false; if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; const num = effectParam[0] || 0; const index = effectParam[0] || 0; for (let val of this.dbCharas) { let { cards = [], charaCode } = val if (cards.find(cur => cur.index == index) == undefined) { cards.push({ index, cardCode: '', cardId: 0 }); this.updateCharaMap.set(charaCode, val); isUseCount = true; } } if (isUseCount) this.updateHolyMapUseCount(this.holyMap.get(cardCode)); } } // 和圣物相关maxhp public async getEffectMaxHp() { let addRatio = 0; await this.getEffectData([ ROUGE_EFFECT_TYPE.HOLY_CHARA_MAIN_ATTR_UP_BY_COIN, // 2005 ROUGE_EFFECT_TYPE.HOLY_CHARA_MAIN_ATTR_UP, // 2020 ROUGE_EFFECT_TYPE.TECH_CHARA_MAIN_ATTR_UP, // 3001 ]) addRatio = await this.getMaxHpByCoin(); addRatio += await this.getMaxHpByBase(); await updateCards([...this.updateCardMap.values()]); return addRatio; } // 每有X个试炼币,全员基础属性id提高Y 2005 private async getMaxHpByCoin() { let addRatio = 0; const dbRecord = await RougelikeRecordModel.findByGameCode(this.gameCode); let coinTotal = dbRecord?.coin || 0; if (this.newEffect.length == 0) return addRatio; for (const { effectParam, effectType, cardCode } of this.newEffect) { if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; if (effectType != ROUGE_EFFECT_TYPE.HOLY_CHARA_MAIN_ATTR_UP_BY_COIN) continue; if (effectParam.length == 0) continue; const count = effectParam[0] || 0; const id = effectParam[1] || 0; const value = effectParam[2] || 0; if (count == 0 || id != ABI_TYPE.ABI_HP || value == 0) continue; addRatio += Math.floor(coinTotal / count * value) this.updateHolyMapUseCount(this.holyMap.get(cardCode)); } return addRatio; } // 基础属性Id&num 2020 private async getMaxHpByBase() { let addRatio = 0; if (this.newEffect.length == 0) return addRatio; for (const { effectParam, effectType, cardCode } of this.newEffect) { if (effectType != ROUGE_EFFECT_TYPE.HOLY_CHARA_MAIN_ATTR_UP && effectType != ROUGE_EFFECT_TYPE.TECH_CHARA_MAIN_ATTR_UP) continue; if (effectParam.length == 0) continue; if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; const id = effectParam[0] || 0; const value = effectParam[1] || 0; if (id != ABI_TYPE.ABI_HP || value == 0) continue; addRatio += value; this.updateHolyMapUseCount(this.holyMap.get(cardCode)); } return addRatio; } } // 每场战斗结束后,学员恢复血量上限X%的生命 2001 export async function getCharaHp(roleId: string, gameCode: string) { let hpRatio = 0; let rougeEffect = new RougeEffect(roleId, gameCode); let { newEffect, holyMap } = await rougeEffect.getEffectData([ ROUGE_EFFECT_TYPE.HOLY_CHARA_HP_RECOVERY_UP,// 2001 ]); if (newEffect.length == 0) return hpRatio; for (const { effectType, effectParam, cardCode } of newEffect) { if (effectParam.length == 0) continue; if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; hpRatio += (effectParam[0] || 0); await updateHolyUseCount(holyMap.get(cardCode), gameCode) } return hpRatio; } // 战斗胜利后,获得的试炼币增加X 2004 export async function getAddCoin(roleId: string, gameCode: string, nodeType: number) { let coinRatio = 0, coinAdd = 0; let rougeEffect = new RougeEffect(roleId, gameCode); let { newEffect, holyMap } = await rougeEffect.getEffectData([ ROUGE_EFFECT_TYPE.HOLY_COIN_UP, //2004 ROUGE_EFFECT_TYPE.TECH_COIN_UP_BY_NODE_TYPE, //3007 ]); if (newEffect.length == 0) return { coinRatio, coinAdd }; for (const { effectType, effectParam, cardCode } of newEffect) { if (effectParam.length == 0) continue; if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; if (effectType == ROUGE_EFFECT_TYPE.HOLY_COIN_UP) { const type = effectParam[0] || 0; const value = effectParam[1] || 0; if (type == 1) coinAdd += value; else if (type == 2) coinRatio += value; await updateHolyUseCount(holyMap.get(cardCode), gameCode) } if (effectType == ROUGE_EFFECT_TYPE.TECH_COIN_UP_BY_NODE_TYPE) { let [value = 0, ...targetNodeType] = effectParam; if (targetNodeType && targetNodeType.includes(nodeType)) coinRatio += value; } } return { coinRatio, coinAdd }; } // 获得圣物后,X流派特性卡的权重增加Y 2007 export async function getAddPassiveWeight(roleId: string, gameCode: string, authorType: number) { let addPassiveWeight = 0; let rougeEffect = new RougeEffect(roleId, gameCode); let { newEffect, holyMap } = await rougeEffect.getEffectData([ ROUGE_EFFECT_TYPE.HOLY_PASSIVE_WEIGHT_UP_BY_AUTHOR,//2007 ]); if (newEffect.length == 0) return addPassiveWeight; for (const { effectParam, cardCode } of newEffect) { if (effectParam.length == 0) continue; if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; const type = effectParam[0] || 0; const value = effectParam[1] || 0; if (type != authorType) continue; addPassiveWeight += value; await updateHolyUseCount(holyMap.get(cardCode), gameCode) } return addPassiveWeight; } // 非boss战斗失败视为胜利,并且满血复活 2009 export async function getNoBossRecoveryHp(roleId: string, gameCode: string) { let rougeEffect = new RougeEffect(roleId, gameCode); let { newEffect, holyMap } = await rougeEffect.getEffectData([ ROUGE_EFFECT_TYPE.HOLY_REVIVE_ALL,//2009 ]); if (newEffect.length == 0) return false; for (const { effectParam, cardCode } of newEffect) { if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; await updateHolyUseCount(holyMap.get(cardCode), gameCode) return true; } return false; // 拿到true 将所有学员更新和hp=maxHp } // 战斗胜利后若有学员死亡,则满血复活X名死亡学员 2010 export async function getBattleRecoveryNum(roleId: string, gameCode: string) { let recoveryNum = 0; let rougeEffect = new RougeEffect(roleId, gameCode); let { newEffect, holyMap } = await rougeEffect.getEffectData([ ROUGE_EFFECT_TYPE.HOLY_REVIVE_CHARA_RAND,//2010 ]); if (newEffect.length == 0) return recoveryNum; for (const { effectParam, cardCode } of newEffect) { if (effectParam.length == 0) continue; if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; recoveryNum += (effectParam[0] || 0) await updateHolyUseCount(holyMap.get(cardCode), gameCode) } return recoveryNum; } // 试炼商店中所有商品X折出售 2011 export async function getShopDiscount(roleId: string, gameCode: string) { let discount = 100; let rougeEffect = new RougeEffect(roleId, gameCode); let { newEffect, holyMap } = await rougeEffect.getEffectData([ ROUGE_EFFECT_TYPE.HOLY_SHOP_DISCOUNT,//2011 ]); if (newEffect.length == 0) return discount; for (const { effectParam, cardCode } of newEffect) { if (effectParam.length == 0) continue; if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; const tempDiscount = effectParam[0] || 0; discount *= (tempDiscount / 100); await updateHolyUseCount(holyMap.get(cardCode), gameCode) } return Math.floor(discount); } // 下次选择特性卡时必定出现X星特性卡 2013 export async function getChooseQualityPassives(roleId: string, gameCode: string, passiveCards: DicRougePassiveCardPlan[]) { let targetPassives: DicRougePassiveCardPlan[] = []; let rougeEffect = new RougeEffect(roleId, gameCode); let { newEffect, holyMap } = await rougeEffect.getEffectData([ ROUGE_EFFECT_TYPE.HOLY_PASSIVE_CHOOSE_FIX,//2013 ]); if (newEffect.length == 0) return targetPassives; for (const { effectParam, cardCode } of newEffect) { let isUseCount = false; if (effectParam.length == 0) continue; if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; const level = effectParam[0] || 0; for (let val of passiveCards) { const { cardId } = val; const passiveCardData = gameData.rougePassiveCard.get(cardId); if (level != passiveCardData?.lv || 0) continue; targetPassives.push(val); isUseCount = true; } if (isUseCount) await updateHolyUseCount(holyMap.get(cardCode), gameCode); } return targetPassives; } // 下次选择特性卡时可多选X张特性卡 2014 export async function getAddChoosePassive(roleId: string, gameCode: string) { let addChooseNum = 0; let rougeEffect = new RougeEffect(roleId, gameCode); let { newEffect, holyMap } = await rougeEffect.getEffectData([ ROUGE_EFFECT_TYPE.HOLY_PASSIVE_CHOOSE_NUM_UP,//2014 ]); for (const { effectParam, cardCode } of newEffect) { if (effectParam.length == 0) continue; if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; const num = effectParam[0] || 0; addChooseNum += num; await updateHolyUseCount(holyMap.get(cardCode), gameCode); } return addChooseNum } // 获得该圣物后,所有角色解锁X号位置的特性槽 2023 export async function getSlotUnlockPoint(roleId: string, gameCode: string, dbCharas: RougelikeCharaPara[]) { let isUpdate = false; let rougeEffect = new RougeEffect(roleId, gameCode); let { newEffect, holyMap } = await rougeEffect.getEffectData([ ROUGE_EFFECT_TYPE.HOLY_CHARA_SLOT_UNLOCK_POINT,//2023 ]); for (const { effectParam, cardCode } of newEffect) { if (effectParam.length == 0) continue; let isUseCount = false; if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; const index = effectParam[0] || 0; for (let { cards = [] } of dbCharas) { if (cards.find(cur => cur.index == index) == undefined) { isUpdate = true cards.push({ index, cardCode: '', cardId: 0 }); isUseCount = true; } } if (isUseCount) await updateHolyUseCount(holyMap.get(cardCode), gameCode); } return { isUpdate, dbCharas }; } // 休整点额外恢复上限X%的生命 2017 3006 export async function getRecoveryExtendHp(roleId: string, gameCode: string) { let hpRatio = 0; let rougeEffect = new RougeEffect(roleId, gameCode); let { newEffect, holyMap } = await rougeEffect.getEffectData([ ROUGE_EFFECT_TYPE.HOLY_RECOVERY_POINT_UP, // 2017 ROUGE_EFFECT_TYPE.TECH_RECOVERY_POINT_UP, // 3006 ]); if (newEffect.length == 0) return hpRatio; for (const { effectType, effectParam, cardCode } of newEffect) { if (effectParam.length == 0) continue; if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; hpRatio += (effectParam[0] || 0); await updateHolyUseCount(holyMap.get(cardCode), gameCode); } return hpRatio; } // 休整点特训价格X折 2018 3009 export async function getTrainCardDiscount(roleId: string, gameCode: string) { let discount = 100; let rougeEffect = new RougeEffect(roleId, gameCode); let { newEffect, holyMap } = await rougeEffect.getEffectData([ ROUGE_EFFECT_TYPE.HOLY_TRAIN_POINT_DISCOUNT, // 2018 ROUGE_EFFECT_TYPE.TECH_TRAIN_POINT_DISCOUNT, // 3009 ]); if (newEffect.length == 0) return discount; for (const { effectParam, cardCode } of newEffect) { if (effectParam.length == 0) continue; if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; const tempDiscount = effectParam[0] || 0; discount *= (tempDiscount / 100); await updateHolyUseCount(holyMap.get(cardCode), gameCode); } return Math.floor(discount); } // 初始获得试炼币&圣物 3003 3005 export async function getEffectWhenGameStart(roleId: string, gameCode: string, authorType: number) { let rougeEffect = new RougeEffect(roleId, gameCode); let addCoin = 0, cardIds: number[] = []; let { newEffect } = await rougeEffect.getEffectData([ ROUGE_EFFECT_TYPE.TECH_INIT_HOLY_BY_AUTHOR, ROUGE_EFFECT_TYPE.TECH_INIT_COIN, ]); if (newEffect.length == 0) return { addCoin, cardIds }; for (const { effectType, effectParam } of newEffect) { if (effectParam.length == 0) continue; if (effectType == ROUGE_EFFECT_TYPE.TECH_INIT_HOLY_BY_AUTHOR) { for (let cardId of effectParam) { let dicCard = gameData.rougeHolyCard.get(cardId); if (!dicCard || dicCard.authorType != authorType) continue; cardIds.push(cardId); } } if (effectType == ROUGE_EFFECT_TYPE.TECH_INIT_COIN) addCoin += effectParam[0]; } return { addCoin, cardIds }; } // 是否可以选择技能卡 3004 export async function checkCanChooseSkillCard(roleId: string, gameCode: string, skillId: number, cards: Card[]) { let rougeEffect = new RougeEffect(roleId, gameCode); let { newEffect } = await rougeEffect.getEffectData([ ROUGE_EFFECT_TYPE.TECH_CAN_CHOOSE_SKILL_CARD, // 3004 ]); let dicSkillCard = gameData.rougeSkillCard.get(skillId); if (!dicSkillCard) return false; let { authorType, skillType } = dicSkillCard; let num = getAuthorTypeCardNum(authorType, cards); let curParam = newEffect.find(({ effectParam }) => { return effectParam[1] == skillType; }); if (!curParam || num < curParam.effectParam[0]) return false; return true; } // 是否可以重置 export async function checkCanReRandomReward(roleId: string, gameCode: string, rewardType: number) { let rougeEffect = new RougeEffect(roleId, gameCode); let { newEffect } = await rougeEffect.getEffectData([ ROUGE_EFFECT_TYPE.TECH_PASSIVE_RANDOM_AGAIN, // 3008 ]); let curParam = newEffect.find(({ effectParam }) => { return effectParam[0] == rewardType; }); if (!curParam) return { canReRandom: false, costCoin: 0 } return { canReRandom: true, costCoin: curParam.effectParam[1] || 0 }; } export function getHolyCardIsUse(holy: { cardId: number, useCount: number, cardCode: string }) { const { useCount = 0, cardId, cardCode } = (holy || {}); if (!cardCode) return true;//法阵不存在cardCode if (!cardId) return; const holyCardData = gameData.rougeHolyCard.get(cardId) if (!holyCardData) return; if ((holyCardData?.useCount || 0) <= useCount) return; return true } export async function updateHolyUseCount(holy: { cardId: number, useCount: number, cardCode: string }, gameCode: string) { const { cardId, cardCode } = (holy || {}); if (!cardId || !cardCode) return; await RougelikeCardModel.updateByCode(gameCode, cardCode, { $inc: { useCount: 1 } }) } export async function updateCards(updateCards: RougelikeCardPara[]) { if (updateCards.length == 0) return; await RougelikeCardModel.bulkWriteUpdate(updateCards) }