Files
pixelheros/assets/script/game/common/config/SCardSet.ts
panFD c59ba45b5b refactor: 统一将游戏内的「波次」术语替换为「回合」
本次提交将全项目中所有与「波次」相关的术语、注释、配置描述、UI文本全部替换为「回合」,包括:
1.  技能卡牌、怪物刷新、经济系统的相关注释与变量名
2.  配置表中的波次相关常量与描述文本
3.  UI预制体中的波次显示文本
4.  所有相关的文档注释与接口说明

统一术语后,游戏的关卡流程描述将更符合常规肉鸽游戏的表达习惯,避免与「波次」字面含义混淆,提升代码可读性与团队协作一致性。
2026-08-09 14:51:48 +08:00

138 lines
9.7 KiB
TypeScript
Raw Permalink 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.
/**
* @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;
}