1. 新增SkillOverrides的num字段配置,支持自定义技能额外施法次数 2. 修改施法次数计算逻辑,优先使用技能卡override配置的num值 3. 更新两张二技能卡和一张三技能卡的配置,实现双发/三发效果
138 lines
9.1 KiB
TypeScript
138 lines
9.1 KiB
TypeScript
/**
|
||
* @file SCardSet.ts
|
||
* @description 技能卡池独立配置
|
||
*
|
||
* 职责:
|
||
* 维护所有技能卡(CardType.Skill)的原始数据,并构建为标准 CardConfig[]。
|
||
*
|
||
* 设计:
|
||
* - 技能卡不再按 wave 过滤,所有技能卡均可被抽取。
|
||
* - 所有技能卡均按次数触发(t_times),不再永久存在。
|
||
* - card_lv 直接显式配置,不再依赖 wave 推导。
|
||
* - 数值基线高于普通英雄普攻(ap:100),通过 overrides 附加 ap/crt/frz/stun/bck 等效果。
|
||
*
|
||
* 依赖:
|
||
* - CardSet —— CardConfig / CardType / CKind / CardTriggerType
|
||
* - SkillSet —— SkillOverrides
|
||
*/
|
||
import { CardConfig, CardType, CKind, CardTriggerType } from "./CardSet";
|
||
import { SkillOverrides } from "./SkillSet";
|
||
|
||
/** 技能卡原始数据(平铺字段,构建后转为 CardConfig) */
|
||
interface SkillCardRaw {
|
||
uuid: number;
|
||
skill: number;
|
||
card_lv: number;
|
||
name: string;
|
||
info: string;
|
||
icon?: string; // 图标ID(对应 ui6 图集 frame 名)
|
||
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 1 · 基础单体(ap:150,附加差异化效果) ====================
|
||
// --- 刀剑系:暴击 ---
|
||
{ uuid: 8101, skill: 6001, card_lv: 1, icon: "Sword-FA_WP_Main_Sword_003_PurpleSilver", name: "飞剑", info: "造成攻击力150%的伤害,25%暴击", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 150, crt: 25 } },
|
||
{ uuid: 8102, skill: 6002, card_lv: 1, icon: "Sword-FA_WP_Main_Sword_009_GraySilver", name: "飞刀", info: "造成攻击力150%的伤害,25%暴击", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 150, crt: 25 } },
|
||
{ uuid: 8103, skill: 6003, card_lv: 1, icon: "Sword-FA_WP_Main_Sword_019_WoodSilver", name: "匕首", info: "造成攻击力150%的伤害,25%暴击", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 150, crt: 25 } },
|
||
// --- 斧锤系:击退 ---
|
||
{ uuid: 8104, skill: 6004, card_lv: 1, icon: "Axe-FA_WP_Main_Axe_004_WoodGray", name: "飞斧", info: "造成攻击力150%的伤害,25%击退", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 150, bck: 25 } },
|
||
{ uuid: 8107, skill: 6007, card_lv: 1, icon: "Blunt-FA_WP_Main_Blunt_002_Wood", name: "飞棒", info: "造成攻击力150%的伤害,25%击退", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 150, bck: 25 } },
|
||
{ uuid: 8111, skill: 6011, card_lv: 1, icon: "Blunt-FA_WP_Main_Blunt_005_Gray", name: "飞锤", info: "造成攻击力150%的伤害,25%击退", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 150, bck: 25 } },
|
||
{ uuid: 8112, skill: 6012, card_lv: 1, icon: "Axe-FA_WP_Main_Axe_002_WoodGray", name: "飞斧·重", info: "造成攻击力150%的伤害,25%击退", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 150, bck: 25 } },
|
||
// --- 枪矛系:穿透(多命中1次) ---
|
||
{ uuid: 8105, skill: 6005, card_lv: 1, icon: "Spear-FA_WP_Main_Spear_010_MetalBlue", name: "飞枪", info: "造成攻击力150%的伤害,可贯穿2个目标", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 150, hit_count: 2 } },
|
||
{ uuid: 8106, skill: 6006, card_lv: 2, icon: "Stat_Attack_01", name: "突刺·双", info: "一次释放2发,造成攻击力180%的伤害,可贯穿2个目标", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 180, hit_count: 2, num: 1 } },
|
||
// --- 远程射击系:高暴击 ---
|
||
{ uuid: 8108, skill: 6008, card_lv: 1, icon: "Stat_RangedAttack", name: "射击", info: "造成攻击力150%的伤害,30%暴击", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 150, crt: 30 } },
|
||
{ uuid: 8109, skill: 6009, card_lv: 1, icon: "Stat_RangedAttack", name: "蓝箭", info: "造成攻击力150%的伤害,30%暴击", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 150, crt: 30 } },
|
||
{ uuid: 8110, skill: 6010, card_lv: 1, icon: "Stat_RangedAttack", name: "火箭", info: "造成攻击力150%的伤害,30%暴击", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 150, crt: 30 } },
|
||
// --- 魔球系:击晕 ---
|
||
{ uuid: 8113, skill: 6013, card_lv: 1, icon: "Sub_Item-FA_WP_Sub_MagicBall_001_Blue", name: "蓝魔球", info: "造成攻击力150%的伤害,25%击晕", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 150, stun: 25 } },
|
||
{ uuid: 8114, skill: 6014, card_lv: 1, icon: "Sub_Item-FA_WP_Sub_MagicBall_001_Purple", name: "紫魔球", info: "造成攻击力150%的伤害,25%击晕", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 150, stun: 25 } },
|
||
// --- 药瓶系:冰冻 ---
|
||
{ uuid: 8115, skill: 6015, card_lv: 1, icon: "Sub_Item-FA_WP_Sub_Potion_001_Green", name: "绿药瓶", info: "造成攻击力150%的伤害,25%冰冻", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 150, frz: 25 } },
|
||
{ uuid: 8116, skill: 6016, card_lv: 1, icon: "Sub_Item-FA_WP_Sub_Potion_001_Red", name: "红药瓶", info: "造成攻击力150%的伤害,25%冰冻", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 150, frz: 25 } },
|
||
|
||
// ==================== card_lv 2 · 中阶范围(ap:200,群体附加) ====================
|
||
{ uuid: 8201, skill: 6101, card_lv: 2, icon: "Stat_FireDamage", name: "火球·双", info: "一次释放2发,造成攻击力200%的伤害,30%暴击,可命中2个目标", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 200, crt: 30, num: 1 } },
|
||
{ uuid: 8202, skill: 6102, card_lv: 2, icon: "Stat_Mana", name: "飓风", info: "造成攻击力200%的伤害,30%击晕,可命中2个目标", is_inst: false, t_times: 3, t_inv: 5, trigger_type: CardTriggerType.Interval, overrides: { ap: 200, stun: 30 } },
|
||
|
||
// ==================== card_lv 3 · 高阶范围(ap:250,群体附加) ====================
|
||
{ uuid: 8301, skill: 6201, card_lv: 3, icon: "Stat_SplashDamage", name: "陨石雨", info: "一次释放3发,每发造成攻击力250%的范围伤害,40%击晕", is_inst: false, t_times: 4, t_inv: 4, trigger_type: CardTriggerType.Interval, overrides: { ap: 250, stun: 40, num: 2 } },
|
||
];
|
||
|
||
/**
|
||
* 技能卡池(已构建为标准 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,
|
||
kind: CKind.Skill,
|
||
card_lv: data.card_lv,
|
||
icon: data.icon,
|
||
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;
|
||
}
|