Files
pixelheros/assets/script/game/common/config/ICardSet.ts
panFD afbb349c25 feat(shop): 新增商品/药品卡池与商店系统
1. 新增ICardSet.ts定义商品卡池配置,包含基础/高级恢复类、属性强化类道具
2. 为MissionCardComp添加商品商店逻辑,支持购买记录追踪与显隐切换
3. 重构ItemListComp为通用商店列表组件,适配装备与商品两种商店类型
2026-07-22 21:42:00 +08:00

137 lines
6.1 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.
/**
* @file ICardSet.ts
* @description 商品/药品卡池独立配置
*
* 职责:
* 定义所有商品/药品卡的静态数据与技能卡池SCardSet和装备卡池EquipSet分离。
* 商品/药品为一次性消耗品,购买后立即触发一次 buff 效果(如治疗、护盾、属性强化等)。
*
* 设计:
* - 参考 SCardSet.ts 结构,但商品是"只触发一次的 buff 技能",而非"多次触发的攻击技能"。
* - trigger_type 统一为 Instant即时触发
* - t_times 固定为 1只触发一次
* - kind 为 CKind.Potion药水类
*
* 依赖:
* - CardSet —— CardConfig / CardType / CKind / CardLV / CardTriggerType
* - SkillSet —— SkillOverrides
*/
import { CardConfig, CardType, CardLV, CKind, CardTriggerType } from "./CardSet";
import { SkillOverrides } from "./SkillSet";
/** 商品/药品卡原始数据(平铺字段,构建后转为 CardConfig */
interface ItemCardRaw {
uuid: number;
skill: number; // 关联的技能 UUIDbuff 技能)
name: string;
info: string;
cost: number; // 购买价格
weight: number; // 抽取权重
overrides?: SkillOverrides; // 技能参数覆写(如自定义治疗量、护盾值等)
}
const ItemCardData: ItemCardRaw[] = [
// ==================== 基础恢复类 ====================
{ uuid: 9101, skill: 6302, name: "治疗药水", info: "恢复全体友方 300 点生命", cost: 3, weight: 20 },
{ uuid: 9102, skill: 6301, name: "护盾药水", info: "为全体友方添加护盾,可抵挡 3 次伤害", cost: 4, weight: 15 },
{ uuid: 9103, skill: 6303, name: "金币袋", info: "立即获得 5 金币", cost: 2, weight: 15, overrides: { gold: 5 } },
// ==================== 属性强化类(单次触发) ====================
{ uuid: 9111, skill: 6401, name: "攻击药剂", info: "全体友方攻击力提升 5 点", cost: 3, weight: 12 },
{ uuid: 9112, skill: 6402, name: "生命药剂", info: "全体友方最大生命值提升 20 点", cost: 3, weight: 12 },
{ uuid: 9113, skill: 6403, name: "暴击药剂", info: "全体友方暴击率提升 10%", cost: 3, weight: 12 },
{ uuid: 9114, skill: 6404, name: "暴伤药剂", info: "全体友方暴击伤害提升 20%", cost: 3, weight: 12 },
{ uuid: 9115, skill: 6405, name: "击晕药剂", info: "全体友方击晕概率提升 10%", cost: 3, weight: 12 },
{ uuid: 9116, skill: 6408, name: "穿刺药剂", info: "全体友方穿透概率提升 20%", cost: 3, weight: 12 },
{ uuid: 9117, skill: 6409, name: "风怒药剂", info: "全体友方风怒次数提升 1 次", cost: 3, weight: 12 },
// ==================== 高级恢复类 ====================
{ uuid: 9201, skill: 6302, name: "高级治疗药水", info: "恢复全体友方 600 点生命", cost: 6, weight: 8, overrides: { ap: 600 } },
{ uuid: 9202, skill: 6301, name: "高级护盾药水", info: "为全体友方添加护盾,可抵挡 6 次伤害", cost: 8, weight: 6, overrides: { ap: 6 } },
{ uuid: 9203, skill: 6303, name: "大金币袋", info: "立即获得 12 金币", cost: 5, weight: 6, overrides: { gold: 12 } },
// ==================== 高级属性强化类 ====================
{ uuid: 9211, skill: 6401, name: "高级攻击药剂", info: "全体友方攻击力提升 10 点", cost: 6, weight: 5, overrides: { ap: 10 } },
{ uuid: 9212, skill: 6402, name: "高级生命药剂", info: "全体友方最大生命值提升 40 点", cost: 6, weight: 5, overrides: { ap: 40 } },
{ uuid: 9213, skill: 6403, name: "高级暴击药剂", info: "全体友方暴击率提升 20%", cost: 6, weight: 5, overrides: { ap: 2 } },
{ uuid: 9214, skill: 6404, name: "高级暴伤药剂", info: "全体友方暴击伤害提升 40%", cost: 6, weight: 5, overrides: { ap: 2 } },
];
/**
* 商品/药品卡池(已构建为标准 CardConfig[])。
* 所有商品卡统一配置:
* - type: Skill复用技能卡体系由 MissSkillsComp 统一处理)
* - kind: Potion药水类用于区分
* - trigger_type: Instant即时触发只生效一次
* - t_times: 1只触发一次
* - is_inst: true即时起效
*/
export const ItemCardList: CardConfig[] = ItemCardData.map(data => ({
uuid: data.uuid,
skill: data.skill,
type: CardType.Skill,
cost: data.cost,
weight: data.weight,
pool_lv: CardLV.LV1,
kind: CKind.Potion,
card_lv: 1,
name: data.name,
info: data.info,
is_inst: true,
t_times: 1,
t_inv: 0,
keep_waves: 0,
overrides: data.overrides,
trigger_type: CardTriggerType.Instant,
}));
/**
* 按权重抽取一张商品卡(带权重随机)。
*/
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 drawItemCards(count: number): CardConfig[] {
const safeCount = Math.max(0, Math.floor(count));
if (ItemCardList.length === 0 || safeCount <= 0) return [];
const picked: CardConfig[] = [];
let available = [...ItemCardList];
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(ItemCardList);
if (!fallback) break;
filled.push(fallback);
}
return filled;
}
/**
* 按 UUID 查找商品卡配置
* @param uuid 商品卡 UUID
*/
export function findItemCardByUuid(uuid: number): CardConfig | undefined {
return ItemCardList.find(e => e.uuid === uuid);
}