1. 重构卡牌配置定义,明确Field类型为装备卡并支持单卡多词条 2. 添加装备卡判断和词条计数工具函数 3. 新增EquipListComp装备列表组件 4. 更新aui.plist和预制体UI资源适配新装备系统 5. 补充多词条装备示例配置
466 lines
26 KiB
TypeScript
466 lines
26 KiB
TypeScript
import * as exp from "constants"
|
||
import { HeroInfo, HeroList, HType } from "./heroSet"
|
||
import { FightSet, SKILL_CARD_WAVES } from "./GameSet"
|
||
import { oops } from "db://oops-framework/core/Oops"
|
||
import { SkillOverrides, TGroup } from "./SkillSet"
|
||
|
||
class I18nString {
|
||
constructor(private key: string, private params?: any[]) { }
|
||
private getTranslated(): string {
|
||
let str = oops.language.getLangByID(this.key) || this.key;
|
||
if (this.params && this.params.length > 0) {
|
||
for (let i = 0; i < this.params.length; i++) {
|
||
str = str.replace(`{${i}}`, String(this.params[i]));
|
||
}
|
||
}
|
||
return str;
|
||
}
|
||
toString() { return this.getTranslated(); }
|
||
valueOf() { return this.getTranslated(); }
|
||
toJSON() { return this.getTranslated(); }
|
||
get length() { return this.toString().length; }
|
||
}
|
||
const t = (key: string, ...params: any[]) => new I18nString(key, params) as unknown as string;
|
||
|
||
/** 卡牌大类定义 */
|
||
export enum CardType {
|
||
Hero = 1,
|
||
Skill = 2,
|
||
SpecialUpgrade = 3,
|
||
SpecialRefresh = 4,
|
||
}
|
||
/** 卡牌大类定义 */
|
||
export enum CKind {
|
||
Hero = 1, //英雄
|
||
Skill = 2, //技能
|
||
Card = 3, //卡牌
|
||
Potion = 4, //药水
|
||
}
|
||
|
||
/** 技能卡触发类型 */
|
||
export enum CardSkillType {
|
||
Interval = 1, // 间隔定时触发 (战斗中每隔N秒执行)
|
||
Field = 2, // 驻场技能 (被动光环)
|
||
BattleStart = 3, // 战斗开始时触发一次
|
||
BattleEnd = 4, // 战斗结束时触发一次
|
||
HeroDead = 5, // 场上己方英雄死亡时触发
|
||
HeroCall = 6, // 场上己方英雄召唤上场时触发
|
||
}
|
||
|
||
/**
|
||
* 卡牌技能触发类型
|
||
* - 命名对齐英雄侧 SkillTriggerType,便于跨模块认知统一
|
||
* - 枚举值从 1 开始,避免 0 的 falsy 坑(if (trigger_type) 判断出错)
|
||
*/
|
||
export enum CardTriggerType {
|
||
Instant = 1, // 即时触发:使用后立即生效一次
|
||
Interval = 2, // 定时循环:战斗中按 t_inv 间隔重复触发
|
||
Field = 3, // 驻场光环(俗称「装备」):被动生效,由 field 数组驱动,支持单卡多词条
|
||
FightStart = 4, // 战斗开始时触发
|
||
FightEnd = 5, // 战斗结束时触发(每波结束)
|
||
HeroDead = 6, // 场上己方英雄死亡时触发
|
||
HeroCall = 7, // 英雄上场时触发(主角召唤 + 技能召唤 + 复活)
|
||
}
|
||
|
||
/**
|
||
* 卡池等级占位枚举(已废弃分层语义)。
|
||
* 新机制下所有英雄卡均属 LV1,不再使用卡池升级。
|
||
* 保留枚举仅为兼容历史代码引用。
|
||
*/
|
||
export enum CardLV {
|
||
LV1 = 1,
|
||
LV2 = 2,
|
||
LV3 = 3,
|
||
LV4 = 4,
|
||
LV5 = 5,
|
||
}
|
||
|
||
/** 通用卡牌配置 */
|
||
export interface CardConfig {
|
||
uuid: number
|
||
type: CardType
|
||
cost: number
|
||
weight: number
|
||
kind: CKind
|
||
pool_lv: CardLV
|
||
wave?: number // 针对技能卡:仅在指定波次(wave)才能抽到
|
||
hero_lv?: number
|
||
card_lv?: number
|
||
base_pool_lv?: number
|
||
|
||
// 技能卡扩展属性
|
||
skill?: number // 关联的技能 UUID
|
||
icon?: string // 图标ID(可选,优先使用;未设置时按 trigger_type 从 SkillSet/FieldSkillSet 自动取)
|
||
name?: string // 卡牌名称
|
||
info?: string // 卡牌描述信息
|
||
is_inst?: boolean // 是否即时起效
|
||
t_times?: number // 触发次数
|
||
t_inv?: number // 触发间隔(秒)
|
||
keep_waves?: number // 维持的波次数(-1表示持续到战斗结束,0或undefined表示仅本波次)
|
||
overrides?: SkillOverrides // 技能参数覆写(如自定义伤害ap、buff值、金币数等)
|
||
field?: number[] // 装备词条数组:驻场光环卡(trigger_type=Field)的属性词条,支持单卡多词条(如 [7002, 7004, 7005] 同时提供攻击/暴击/暴伤)
|
||
|
||
/** 触发类型(必填,技能卡专用;功能卡/英雄卡可缺省) */
|
||
trigger_type?: CardTriggerType;
|
||
/**
|
||
* 事件型触发的全局次数上限(仅 FightStart/FightEnd/HeroDead/HeroCall 有效)
|
||
* 默认 Infinity;达到上限后销毁节点
|
||
* 注意:与 t_times 语义不同——t_times 控制每波内 Interval 的次数
|
||
*/
|
||
trigger_limit?: number;
|
||
|
||
/**
|
||
* 动态升级卡专属:目标英雄实体 eid(运行时唯一)。
|
||
* 仅当 type === CardType.SpecialUpgrade 且该卡由 buildDrawCards 动态生成时使用。
|
||
* 使用该卡时精确升级场上对应 eid 的英雄实体。
|
||
*/
|
||
target_hero_eid?: number;
|
||
}
|
||
|
||
/** 升级卡折扣表(已废弃,保留以兼容历史引用) */
|
||
export const CardsUpSet: Record<number, number> = {
|
||
1: 50,
|
||
2: 100,
|
||
3: 150,
|
||
4: 200,
|
||
5: 250,
|
||
}
|
||
|
||
/** 卡池升级每波减免金额(已废弃,保留以兼容历史引用) */
|
||
export const CARD_POOL_UPGRADE_DISCOUNT_PER_WAVE = 10
|
||
/** 卡池默认初始等级(已废弃,所有卡牌统一 LV1) */
|
||
export const CARD_POOL_INIT_LEVEL = CardLV.LV1
|
||
/** 卡池等级上限(已废弃,所有卡牌统一 LV1) */
|
||
export const CARD_POOL_MAX_LEVEL = CardLV.LV1
|
||
/** 英雄最高等级限制(已废弃,统一由 FightSet.HERO_MAX_LV 控制) */
|
||
export const CARD_HERO_MAX_LEVEL = 1
|
||
|
||
/** 基础卡池(英雄、技能、功能) */
|
||
export const CardPoolList: CardConfig[] = [];
|
||
|
||
// 动态生成英雄卡池:所有英雄统一生成 lv1 卡牌
|
||
HeroList.forEach(uuid => {
|
||
const hero = HeroInfo[uuid];
|
||
if (!hero) return;
|
||
|
||
const baseCost = FightSet.BASE_COST;
|
||
const baseWeight = 25;
|
||
|
||
CardPoolList.push({
|
||
uuid: hero.uuid,
|
||
type: CardType.Hero,
|
||
cost: baseCost,
|
||
weight: baseWeight,
|
||
pool_lv: CardLV.LV1,
|
||
kind: CKind.Hero,
|
||
hero_lv: 1,
|
||
base_pool_lv: 1,
|
||
});
|
||
});
|
||
|
||
// 添加非英雄卡牌 (技能、功能卡)
|
||
// 体系:wave 由 SKILL_CARD_WAVES 统一配置,每档强度递增(Field 靠 field uuid 区分数值,Interval 靠 overrides 覆写)
|
||
// wave→card_lv 映射由 SKILL_CARD_WAVES 索引+1 自动生成(wave 1→lv1, wave 5→lv2, wave 8→lv3)
|
||
const waveToCardLv: Record<number, number> = {};
|
||
SKILL_CARD_WAVES.forEach((w, i) => { waveToCardLv[w] = i + 1; });
|
||
|
||
const SkillCardData: any[] = [
|
||
// ==================== wave 1 档(基础强度) ====================
|
||
// --- 驻场卡(Field) ---
|
||
|
||
{ uuid: 8701, skill: 0, wave: SKILL_CARD_WAVES[0], name: "战后恢复", info: "战斗结束生命回复量+10%", is_inst: false, keep_waves: -1, field: [7001], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8702, skill: 0, wave: SKILL_CARD_WAVES[0], name: "攻击加成", info: "英雄攻击力+10%", is_inst: false, keep_waves: -1, field: [7002], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8703, skill: 0, wave: SKILL_CARD_WAVES[0], name: "击晕加成", info: "英雄击晕概率+10%", is_inst: false, keep_waves: -1, field: [7003], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8704, skill: 0, wave: SKILL_CARD_WAVES[0], name: "暴击加成", info: "英雄暴击率+10%", is_inst: false, keep_waves: -1, field: [7004], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8705, skill: 0, wave: SKILL_CARD_WAVES[0], name: "暴伤加成", info: "英雄暴击伤害+20%", is_inst: false, keep_waves: -1, field: [7005], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8706, skill: 0, wave: SKILL_CARD_WAVES[0], name: "攻速加成", info: "英雄攻击速度+10%", is_inst: false, keep_waves: -1, field: [7006], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8707, skill: 0, wave: SKILL_CARD_WAVES[0], name: "生命加成", info: "英雄最大生命+10%", is_inst: false, keep_waves: -1, field: [7007], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8708, skill: 0, wave: SKILL_CARD_WAVES[0], name: "风怒加成", info: "英雄风怒概率+10%", is_inst: false, keep_waves: -1, field: [7008], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8709, skill: 0, wave: SKILL_CARD_WAVES[0], name: "穿刺加成", info: "英雄穿刺概率+10%", is_inst: false, keep_waves: -1, field: [7009], trigger_type: CardTriggerType.Field },
|
||
|
||
{ uuid: 8710, skill: 0, wave: SKILL_CARD_WAVES[0], name: "金币收益", info: "每回合金币收益+1", is_inst: false, keep_waves: -1, field: [7010], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8711, skill: 0, wave: SKILL_CARD_WAVES[0], name: "出售强化", info: "卖出英雄金币+1", is_inst: false, keep_waves: -1, field: [7011], trigger_type: CardTriggerType.Field },
|
||
// --- 多词条装备示例(一张卡自带多条属性词条) ---
|
||
{ uuid: 8720, skill: 0, wave: SKILL_CARD_WAVES[0], name: "勇者护符", info: "英雄攻击力+10%, 暴击率+10%, 暴击伤害+20%", is_inst: false, keep_waves: -1, field: [7002, 7004, 7005], trigger_type: CardTriggerType.Field },
|
||
|
||
// ==================== wave 5 档(强度 ×2) ====================
|
||
// --- 驻场卡(field uuid +200,对应 FieldSkillSet 72xx 段) ---
|
||
{ uuid: 8751, skill: 0, wave: SKILL_CARD_WAVES[1], name: "战后恢复+", info: "战斗结束生命回复量+20%", is_inst: false, keep_waves: -1, field: [7201], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8752, skill: 0, wave: SKILL_CARD_WAVES[1], name: "攻击加成+", info: "英雄攻击力+20%", is_inst: false, keep_waves: -1, field: [7202], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8753, skill: 0, wave: SKILL_CARD_WAVES[1], name: "击晕加成+", info: "英雄击晕概率+20%", is_inst: false, keep_waves: -1, field: [7203], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8754, skill: 0, wave: SKILL_CARD_WAVES[1], name: "暴击加成+", info: "英雄暴击率+20%", is_inst: false, keep_waves: -1, field: [7204], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8755, skill: 0, wave: SKILL_CARD_WAVES[1], name: "暴伤加成+", info: "英雄暴击伤害+40%", is_inst: false, keep_waves: -1, field: [7205], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8756, skill: 0, wave: SKILL_CARD_WAVES[1], name: "攻速加成+", info: "英雄攻击速度+20%", is_inst: false, keep_waves: -1, field: [7206], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8757, skill: 0, wave: SKILL_CARD_WAVES[1], name: "生命加成+", info: "英雄最大生命+20%", is_inst: false, keep_waves: -1, field: [7207], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8758, skill: 0, wave: SKILL_CARD_WAVES[1], name: "风怒加成+", info: "英雄风怒概率+20%", is_inst: false, keep_waves: -1, field: [7208], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8759, skill: 0, wave: SKILL_CARD_WAVES[1], name: "穿刺加成+", info: "英雄穿刺概率+20%", is_inst: false, keep_waves: -1, field: [7209], trigger_type: CardTriggerType.Field },
|
||
// --- 范围攻击卡(ap 递增,间隔缩短) ---
|
||
{ uuid: 8261, skill: 6201, wave: SKILL_CARD_WAVES[1], name: "雷墙+", info: "召唤雷墙阻挡敌人,有概率击晕", is_inst: false, t_inv: 5, keep_waves: -1, trigger_type: CardTriggerType.Interval, overrides: { ap: 150 } },
|
||
{ uuid: 8262, skill: 6202, wave: SKILL_CARD_WAVES[1], name: "火墙+", info: "召唤火墙阻挡敌人,有概率击晕", is_inst: false, t_inv: 5, keep_waves: -1, trigger_type: CardTriggerType.Interval, overrides: { ap: 150 } },
|
||
{ uuid: 8263, skill: 6203, wave: SKILL_CARD_WAVES[1], name: "飓风+", info: "召唤飓风攻击敌人,有概率击晕", is_inst: false, t_inv: 5, keep_waves: -1, trigger_type: CardTriggerType.Interval, overrides: { ap: 150 } },
|
||
{ uuid: 8264, skill: 6204, wave: SKILL_CARD_WAVES[1], name: "水墙+", info: "召唤水墙阻挡敌人,有概率击晕", is_inst: false, t_inv: 5, keep_waves: -1, trigger_type: CardTriggerType.Interval, overrides: { ap: 150 } },
|
||
{ uuid: 8265, skill: 6205, wave: SKILL_CARD_WAVES[1], name: "风墙+", info: "召唤风墙困住敌人,有概率击晕", is_inst: false, t_inv: 5, keep_waves: -1, trigger_type: CardTriggerType.Interval, overrides: { ap: 150 } },
|
||
{ uuid: 8266, skill: 6206, wave: SKILL_CARD_WAVES[1], name: "陨石术+", info: "召唤陨石范围攻击敌人,有概率击晕", is_inst: false, t_inv: 5, keep_waves: -1, trigger_type: CardTriggerType.Interval, overrides: { ap: 150 } },
|
||
|
||
|
||
{ uuid: 8760, skill: 0, wave: SKILL_CARD_WAVES[1], name: "金币收益+", info: "每回合金币收益+2", is_inst: false, keep_waves: -1, field: [7210], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8761, skill: 0, wave: SKILL_CARD_WAVES[1], name: "购买优惠+", info: "购买卡牌费用-2金币", is_inst: false, keep_waves: -1, field: [7212], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8762, skill: 0, wave: SKILL_CARD_WAVES[1], name: "刷新优惠", info: "刷新卡牌费用-1金币", is_inst: false, keep_waves: -1, field: [7213], trigger_type: CardTriggerType.Field },
|
||
// --- 多词条装备示例(一张卡自带多条属性词条) ---
|
||
{ uuid: 8770, skill: 0, wave: SKILL_CARD_WAVES[1], name: "守卫护甲", info: "英雄最大生命+20%, 战后生命回复+20%, 攻速+20%", is_inst: false, keep_waves: -1, field: [7207, 7201, 7206], trigger_type: CardTriggerType.Field },
|
||
|
||
|
||
// ==================== wave 8 档(强度 ×3) ====================
|
||
// --- 驻场卡(field uuid +400,对应 FieldSkillSet 74xx 段) ---
|
||
{ uuid: 8801, skill: 0, wave: SKILL_CARD_WAVES[2], name: "战后恢复++", info: "战斗结束生命回复量+30%", is_inst: false, keep_waves: -1, field: [7401], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8802, skill: 0, wave: SKILL_CARD_WAVES[2], name: "攻击加成++", info: "英雄攻击力+30%", is_inst: false, keep_waves: -1, field: [7402], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8803, skill: 0, wave: SKILL_CARD_WAVES[2], name: "击晕加成++", info: "英雄击晕概率+30%", is_inst: false, keep_waves: -1, field: [7403], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8804, skill: 0, wave: SKILL_CARD_WAVES[2], name: "暴击加成++", info: "英雄暴击率+30%", is_inst: false, keep_waves: -1, field: [7404], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8805, skill: 0, wave: SKILL_CARD_WAVES[2], name: "暴伤加成++", info: "英雄暴击伤害+60%", is_inst: false, keep_waves: -1, field: [7405], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8806, skill: 0, wave: SKILL_CARD_WAVES[2], name: "攻速加成++", info: "英雄攻击速度+30%", is_inst: false, keep_waves: -1, field: [7406], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8807, skill: 0, wave: SKILL_CARD_WAVES[2], name: "生命加成++", info: "英雄最大生命+30%", is_inst: false, keep_waves: -1, field: [7407], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8808, skill: 0, wave: SKILL_CARD_WAVES[2], name: "风怒加成++", info: "英雄风怒概率+30%", is_inst: false, keep_waves: -1, field: [7408], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8809, skill: 0, wave: SKILL_CARD_WAVES[2], name: "穿刺加成++", info: "英雄穿刺概率+30%", is_inst: false, keep_waves: -1, field: [7409], trigger_type: CardTriggerType.Field },
|
||
|
||
{ uuid: 8361, skill: 6201, wave: SKILL_CARD_WAVES[2], name: "雷墙++", info: "召唤雷墙阻挡敌人,有概率击晕", is_inst: false, t_inv: 4, keep_waves: -1, trigger_type: CardTriggerType.Interval, overrides: { ap: 250 } },
|
||
{ uuid: 8362, skill: 6202, wave: SKILL_CARD_WAVES[2], name: "火墙++", info: "召唤火墙阻挡敌人,有概率击晕", is_inst: false, t_inv: 4, keep_waves: -1, trigger_type: CardTriggerType.Interval, overrides: { ap: 250 } },
|
||
{ uuid: 8363, skill: 6203, wave: SKILL_CARD_WAVES[2], name: "飓风++", info: "召唤飓风攻击敌人,有概率击晕", is_inst: false, t_inv: 4, keep_waves: -1, trigger_type: CardTriggerType.Interval, overrides: { ap: 250 } },
|
||
{ uuid: 8364, skill: 6204, wave: SKILL_CARD_WAVES[2], name: "水墙++", info: "召唤水墙阻挡敌人,有概率击晕", is_inst: false, t_inv: 4, keep_waves: -1, trigger_type: CardTriggerType.Interval, overrides: { ap: 250 } },
|
||
{ uuid: 8365, skill: 6205, wave: SKILL_CARD_WAVES[2], name: "风墙++", info: "召唤风墙困住敌人,有概率击晕", is_inst: false, t_inv: 4, keep_waves: -1, trigger_type: CardTriggerType.Interval, overrides: { ap: 250 } },
|
||
{ uuid: 8366, skill: 6206, wave: SKILL_CARD_WAVES[2], name: "陨石术++", info: "召唤陨石范围攻击敌人,有概率击晕", is_inst: false, t_inv: 4, keep_waves: -1, trigger_type: CardTriggerType.Interval, overrides: { ap: 250 } },
|
||
|
||
|
||
{ uuid: 8810, skill: 0, wave: SKILL_CARD_WAVES[2], name: "金币收益++", info: "每回合金币收益+3", is_inst: false, keep_waves: -1, field: [7410], trigger_type: CardTriggerType.Field },
|
||
|
||
{ uuid: 8811, skill: 0, wave: SKILL_CARD_WAVES[2], name: "召唤强化++", info: "召唤触发技能次数+1", is_inst: false, keep_waves: -1, field: [7014], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8812, skill: 0, wave: SKILL_CARD_WAVES[2], name: "死亡强化++", info: "死亡触发技能次数+1", is_inst: false, keep_waves: -1, field: [7015], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8813, skill: 0, wave: SKILL_CARD_WAVES[2], name: "开场强化++", info: "战斗开始触发技能次数+1", is_inst: false, keep_waves: -1, field: [7016], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8814, skill: 0, wave: SKILL_CARD_WAVES[2], name: "结束强化++", info: "战斗结束触发技能次数+1", is_inst: false, keep_waves: -1, field: [7017], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8815, skill: 0, wave: SKILL_CARD_WAVES[2], name: "攻击强化++", info: "攻击触发技能次数+1", is_inst: false, keep_waves: -1, field: [7018], trigger_type: CardTriggerType.Field },
|
||
{ uuid: 8816, skill: 0, wave: SKILL_CARD_WAVES[2], name: "受击强化++", info: "被攻击触发技能次数+1", is_inst: false, keep_waves: -1, field: [7019], trigger_type: CardTriggerType.Field },
|
||
// --- 多词条装备示例(一张卡自带多条属性词条) ---
|
||
{ uuid: 8820, skill: 0, wave: SKILL_CARD_WAVES[2], name: "神圣之刃", info: "英雄攻击力+30%, 暴击率+30%, 暴击伤害+60%, 攻速+30%", is_inst: false, keep_waves: -1, field: [7402, 7404, 7405, 7406], trigger_type: CardTriggerType.Field },
|
||
// --- 范围攻击卡(ap 最高,间隔最短) ---
|
||
];
|
||
|
||
SkillCardData.forEach(data => {
|
||
const cardLv = waveToCardLv[data.wave] ?? 1;
|
||
CardPoolList.push({
|
||
uuid: data.uuid,
|
||
skill: data.skill || undefined,
|
||
type: CardType.Skill,
|
||
cost: 0,
|
||
weight: 10,
|
||
pool_lv: CardLV.LV1,
|
||
wave: data.wave,
|
||
kind: CKind.Skill,
|
||
card_lv: cardLv,
|
||
name: data.name,
|
||
info: data.info,
|
||
icon: data.icon,
|
||
is_inst: data.is_inst,
|
||
t_times: data.t_times || (data.is_inst ? 1 : 999),
|
||
t_inv: data.t_inv || 0,
|
||
keep_waves: data.keep_waves,
|
||
field: data.field,
|
||
overrides: data.overrides,
|
||
trigger_type: data.trigger_type,
|
||
trigger_limit: data.trigger_limit,
|
||
});
|
||
});
|
||
|
||
|
||
export enum SpecialRefreshHeroType {
|
||
Any = 0,
|
||
Melee = 1,
|
||
Ranged = 2,
|
||
}
|
||
|
||
/** 升级功能卡完整配置(作为动态升级卡的基础模板) */
|
||
export interface SpecialUpgradeCardConfig extends CardConfig {
|
||
name: string
|
||
info: string
|
||
/** 模板字段:currentLv=0 表示动态卡(实际值由 target_hero_eid 对应的英雄决定) */
|
||
currentLv: number
|
||
/** 模板字段:targetLv=0 表示"+1 级"(实际目标等级 = 当前等级 + 1) */
|
||
targetLv: number
|
||
}
|
||
|
||
/** 刷新功能卡完整配置 */
|
||
export interface SpecialRefreshCardConfig extends CardConfig {
|
||
name: string
|
||
info: string
|
||
refreshLv: number
|
||
refreshHeroType: SpecialRefreshHeroType
|
||
}
|
||
|
||
/**
|
||
* 升级卡模板。
|
||
* 仅有 7001 一条记录,作为动态升级卡的基础配置(cost/weight/name/info)。
|
||
* 实际使用时由 MissionCardComp.buildDrawCards 根据场上英雄动态生成 CardConfig,
|
||
* 通过 target_hero_eid 字段绑定具体英雄实体。
|
||
*/
|
||
export const SpecialUpgradeCardList: Record<number, SpecialUpgradeCardConfig> = {
|
||
7001: {
|
||
uuid: 7001, type: CardType.SpecialUpgrade, cost: 10, weight: 18, pool_lv: CardLV.LV1, kind: CKind.Card, name: t("scard_name_7001"), info: t("scard_info_7001"),
|
||
currentLv: 0, targetLv: 0,
|
||
},
|
||
}
|
||
|
||
export const SpecialRefreshCardList: Record<number, SpecialRefreshCardConfig> = {
|
||
7101: {
|
||
uuid: 7101, type: CardType.SpecialRefresh, cost: 3, weight: 14, pool_lv: CardLV.LV1, kind: CKind.Card, name: t("scard_name_7101"), info: t("scard_info_7101"),
|
||
refreshLv: 0, refreshHeroType: SpecialRefreshHeroType.Melee,
|
||
},
|
||
7102: {
|
||
uuid: 7102, type: CardType.SpecialRefresh, cost: 3, weight: 14, pool_lv: CardLV.LV1, kind: CKind.Card, name: t("scard_name_7102"), info: t("scard_info_7102"),
|
||
refreshLv: 0, refreshHeroType: SpecialRefreshHeroType.Ranged,
|
||
},
|
||
7103: {
|
||
uuid: 7103, type: CardType.SpecialRefresh, cost: 4, weight: 12, pool_lv: CardLV.LV1, kind: CKind.Card, name: t("scard_name_7103"), info: t("scard_info_7103"),
|
||
refreshLv: 0, refreshHeroType: SpecialRefreshHeroType.Any,
|
||
},
|
||
}
|
||
|
||
|
||
/** 规范等级到合法区间(保留以兼容历史调用,新机制下统一返回 LV1) */
|
||
const clampCardLv = (lv: number): CardLV => {
|
||
return CardLV.LV1;
|
||
}
|
||
|
||
// ============ 装备(光环类技能卡)语义化封装 ============
|
||
// 说明:不新增 CardType / CKind,以 trigger_type=Field 且 field 非空作为装备识别标志,
|
||
// 复用现有 CardConfig.field: number[] 天然支持单卡多词条(一张装备自带多条属性加成)。
|
||
|
||
/**
|
||
* 判断卡牌是否为「装备」(光环类技能卡)。
|
||
* 判定条件:trigger_type 为 Field,且 field 数组非空。
|
||
*/
|
||
export const isEquipmentCard = (card: CardConfig): boolean => {
|
||
return card.trigger_type === CardTriggerType.Field
|
||
&& !!card.field
|
||
&& card.field.length > 0;
|
||
}
|
||
|
||
/**
|
||
* 获取装备卡的属性词条数量。
|
||
* 非装备卡返回 0;装备卡返回 field 数组长度。
|
||
*/
|
||
export const getEquipmentFieldCount = (card: CardConfig): number => {
|
||
return isEquipmentCard(card) ? (card.field?.length ?? 0) : 0;
|
||
}
|
||
|
||
/** 单次按权重抽取一张卡 */
|
||
const weightedPick = (cards: CardConfig[]): CardConfig | null => {
|
||
if (cards.length === 0) return null
|
||
const totalWeight = cards.reduce((total, card) => total + card.weight, 0)
|
||
let random = Math.random() * totalWeight
|
||
for (const card of cards) {
|
||
random -= card.weight
|
||
if (random <= 0) return card
|
||
}
|
||
return cards[cards.length - 1]
|
||
}
|
||
|
||
/** 连续抽取 count 张卡,允许重复或通过 unique 剔除重复 */
|
||
const pickCards = (cards: CardConfig[], count: number, unique: boolean = false): CardConfig[] => {
|
||
if (cards.length === 0 || count <= 0) return []
|
||
const selected: CardConfig[] = []
|
||
let available = [...cards]
|
||
while (selected.length < count) {
|
||
if (available.length === 0) break
|
||
const pick = weightedPick(available)
|
||
if (!pick) break
|
||
selected.push(pick)
|
||
if (unique) {
|
||
available = available.filter(c => c.uuid !== pick.uuid)
|
||
}
|
||
}
|
||
return selected
|
||
}
|
||
|
||
/**
|
||
* 获取基础卡池(已废弃 lv 参数,新机制下返回完整卡池)。
|
||
* @param lv 历史遗留参数,不再生效
|
||
* @param onlyCurrentLv 历史遗留参数,不再生效
|
||
*/
|
||
export const getCardPoolByLv = (lv: number, onlyCurrentLv: boolean = false): CardConfig[] => {
|
||
return CardPoolList;
|
||
}
|
||
|
||
const normalizeTypeFilter = (type: CardType | CardType[]): Set<CardType> => {
|
||
const list = Array.isArray(type) ? type : [type]
|
||
return new Set<CardType>(list)
|
||
}
|
||
|
||
/**
|
||
* 常规发牌:前 3 英雄 + 后 1 其他;支持按类型过滤。
|
||
* @param lv 历史遗留参数,不再生效
|
||
* @param type 限定卡牌类型
|
||
* @param onlyCurrentLv 历史遗留参数,不再生效
|
||
*/
|
||
export const getCardsByLv = (
|
||
lv: number,
|
||
type?: CardType | CardType[],
|
||
onlyCurrentLv: boolean = false
|
||
): CardConfig[] => {
|
||
const pool = getCardPoolByLv(lv, onlyCurrentLv)
|
||
if (type !== undefined) {
|
||
const typeSet = normalizeTypeFilter(type)
|
||
const filteredPool = pool.filter(card => typeSet.has(card.type))
|
||
return pickCards(filteredPool, 4)
|
||
}
|
||
const heroPool = pool.filter(card => card.type === CardType.Hero)
|
||
const otherPool = pool.filter(card => card.type !== CardType.Hero)
|
||
const heroes = pickCards(heroPool, 3)
|
||
const others = pickCards(otherPool, 1)
|
||
return [...heroes, ...others]
|
||
}
|
||
|
||
/**
|
||
* 通用按规则抽卡(已废弃 lv/targetPoolLv/onlyCurrentLv 参数,仅为兼容保留)。
|
||
*/
|
||
export const drawCardsByRule = (
|
||
lv: number,
|
||
options: {
|
||
count?: number
|
||
onlyCurrentLv?: boolean
|
||
type?: CardType | CardType[]
|
||
heroType?: HType
|
||
heroLv?: number
|
||
targetPoolLv?: number
|
||
wave?: number
|
||
unique?: boolean
|
||
} = {}
|
||
): CardConfig[] => {
|
||
const count = Math.max(0, Math.floor(options.count ?? 4))
|
||
let pool = getCardPoolByLv(lv, options.onlyCurrentLv ?? false)
|
||
if (options.type !== undefined) {
|
||
const typeSet = normalizeTypeFilter(options.type)
|
||
pool = pool.filter(card => typeSet.has(card.type))
|
||
}
|
||
if (options.heroType !== undefined || options.heroLv !== undefined) {
|
||
pool = pool.filter(card => {
|
||
if (card.type !== CardType.Hero) return false
|
||
const hero = HeroInfo[card.uuid]
|
||
if (!hero) return false
|
||
if (options.heroType !== undefined && hero.type !== options.heroType) return false
|
||
if (options.heroLv !== undefined && card.hero_lv !== options.heroLv) return false
|
||
return true
|
||
})
|
||
}
|
||
|
||
// 如果传入了波次并且是技能卡,则根据 wave 过滤
|
||
if (options.wave !== undefined) {
|
||
pool = pool.filter(card => {
|
||
if (card.type === CardType.Skill) {
|
||
return card.wave === options.wave;
|
||
}
|
||
return true;
|
||
})
|
||
}
|
||
|
||
const picked = pickCards(pool, count, options.unique)
|
||
return picked
|
||
}
|