/** * @file SCardSet.ts * @description 技能卡池独立配置 * * 职责: * 维护所有技能卡(CardType.Skill)的原始数据,并构建为标准 CardConfig[]。 * * 设计: * - 技能卡不再按 wave 过滤,所有技能卡均可被抽取。 * - 所有技能卡均按次数触发(t_times),不再永久存在。 * - card_lv 直接显式配置,不再依赖 wave 推导。 * * 依赖: * - CardSet —— CardConfig / CardType / CKind / CardLV / CardTriggerType * - SkillSet —— SkillOverrides */ import { CardConfig, CardType, CardLV, CKind, CardTriggerType } from "./CardSet"; import { SkillOverrides } from "./SkillSet"; /** 技能卡原始数据(平铺字段,构建后转为 CardConfig) */ interface SkillCardRaw { uuid: number; skill: number; card_lv: number; name: string; info: string; is_inst: boolean; t_times?: number; // 触发次数(未设置时按 is_inst 取默认值:即时=1,定时=3) t_inv?: number; keep_waves?: number; // 维持波次数(默认 0=仅本波次) trigger_type: CardTriggerType; overrides?: SkillOverrides; } const SkillCardData: SkillCardRaw[] = [ // ==================== card_lv 2 档(强度 ×2) ==================== // --- 范围攻击卡(ap 递增,间隔缩短) --- { uuid: 8261, skill: 6201, card_lv: 2, name: "雷墙+", info: "召唤雷墙阻挡敌人,有概率击晕", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 150 } }, { uuid: 8262, skill: 6202, card_lv: 2, name: "火墙+", info: "召唤火墙阻挡敌人,有概率击晕", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 150 } }, { uuid: 8263, skill: 6203, card_lv: 2, name: "飓风+", info: "召唤飓风攻击敌人,有概率击晕", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 150 } }, { uuid: 8264, skill: 6204, card_lv: 2, name: "水墙+", info: "召唤水墙阻挡敌人,有概率击晕", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 150 } }, { uuid: 8265, skill: 6205, card_lv: 2, name: "风墙+", info: "召唤风墙困住敌人,有概率击晕", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 150 } }, { uuid: 8266, skill: 6206, card_lv: 2, name: "陨石术+", info: "召唤陨石范围攻击敌人,有概率击晕", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 150 } }, // ==================== card_lv 3 档(强度 ×3) ==================== { uuid: 8361, skill: 6201, card_lv: 3, name: "雷墙++", info: "召唤雷墙阻挡敌人,有概率击晕", is_inst: false, t_times: 4, t_inv: 4, trigger_type: CardTriggerType.Interval, overrides: { ap: 250 } }, { uuid: 8362, skill: 6202, card_lv: 3, name: "火墙++", info: "召唤火墙阻挡敌人,有概率击晕", is_inst: false, t_times: 4, t_inv: 4, trigger_type: CardTriggerType.Interval, overrides: { ap: 250 } }, { uuid: 8363, skill: 6203, card_lv: 3, name: "飓风++", info: "召唤飓风攻击敌人,有概率击晕", is_inst: false, t_times: 4, t_inv: 4, trigger_type: CardTriggerType.Interval, overrides: { ap: 250 } }, { uuid: 8364, skill: 6204, card_lv: 3, name: "水墙++", info: "召唤水墙阻挡敌人,有概率击晕", is_inst: false, t_times: 4, t_inv: 4, trigger_type: CardTriggerType.Interval, overrides: { ap: 250 } }, { uuid: 8365, skill: 6205, card_lv: 3, name: "风墙++", info: "召唤风墙困住敌人,有概率击晕", is_inst: false, t_times: 4, t_inv: 4, trigger_type: CardTriggerType.Interval, overrides: { ap: 250 } }, { uuid: 8366, skill: 6206, card_lv: 3, name: "陨石术++", info: "召唤陨石范围攻击敌人,有概率击晕", is_inst: false, t_times: 4, t_inv: 4, trigger_type: CardTriggerType.Interval, overrides: { ap: 250 } }, ]; /** * 技能卡池(已构建为标准 CardConfig[])。 * 不再按 wave 过滤,所有技能卡均可被抽取。 */ export const SkillCardList: CardConfig[] = SkillCardData.map(data => { // 触发次数:显式配置优先;未配置时即时=1,定时=3 const defaultTimes = data.is_inst ? 1 : 3; return { uuid: data.uuid, skill: data.skill || undefined, type: CardType.Skill, cost: 0, weight: 10, pool_lv: CardLV.LV1, kind: CKind.Skill, card_lv: data.card_lv, name: data.name, info: data.info, is_inst: data.is_inst, t_times: data.t_times ?? defaultTimes, t_inv: data.t_inv || 0, keep_waves: data.keep_waves ?? 0, overrides: data.overrides, trigger_type: data.trigger_type, } as CardConfig; }); /** * 按权重抽取一张卡(带权重随机)。 */ function weightedPick(cards: CardConfig[]): CardConfig | null { if (cards.length === 0) return null; const totalWeight = cards.reduce((total, card) => total + (card.weight ?? 0), 0); let random = Math.random() * totalWeight; for (const card of cards) { random -= (card.weight ?? 0); if (random <= 0) return card; } return cards[cards.length - 1]; } /** * 按权重抽取 N 张技能卡(unique 保证一次刷新内不重复,不足时允许重复补齐)。 * @param count 需要抽取的数量 */ export function drawSkillCards(count: number): CardConfig[] { const safeCount = Math.max(0, Math.floor(count)); if (SkillCardList.length === 0 || safeCount <= 0) return []; const picked: CardConfig[] = []; let available = [...SkillCardList]; while (picked.length < safeCount) { if (available.length === 0) break; const pick = weightedPick(available); if (!pick) break; picked.push(pick); available = available.filter(c => c.uuid !== pick.uuid); } // 不足时允许重复补齐 const filled = [...picked]; while (filled.length < safeCount) { const fallback = weightedPick(SkillCardList); if (!fallback) break; filled.push(fallback); } return filled; }