Files
ZYZ/game-server/app/services/battle/rougeEffectService.ts
2023-09-14 20:56:09 +08:00

701 lines
30 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<string, { cardCode: string, cardId: number, useCount: number }>();
updateHolyMap = new Map<string, RougelikeCardType>();
updateCharaMap = new Map<string, RougelikeCharaType>();
updateCardMap = new Map<string, RougelikeCardType>();
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<string, RougelikeCharaType>, cards?: Map<string, RougelikeCardType> } = {};
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, 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<number, DicRougePassiveCard>()
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<number, DicRougePassiveCard>());
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)
}