Files
pixelheros/assets/script/game/common/config/CardSet.ts
panw 958aa0a9d2 feat(i18n): 为英雄、技能和成就添加本地化支持
在多个配置文件中引入本地化函数,将硬编码的文本替换为从语言文件获取的键值。
添加了对应的中文字符串到语言文件,支持游戏内多语言切换。
2026-04-29 09:47:32 +08:00

258 lines
11 KiB
TypeScript

import * as exp from "constants"
import { HeroInfo, HType } from "./heroSet"
import { FightSet } from "./GameSet"
import { oops } from "db://oops-framework/core/Oops"
const t = (key: string) => oops.language.getLangByID(key);
/** 卡牌大类定义 */
export enum CardType {
Hero = 1,
Skill = 2,
SpecialUpgrade = 3,
SpecialRefresh = 4,
}
/** 卡牌大类定义 */
export enum CKind {
Hero = 1, //英雄
Skill = 2, //技能
Card = 3, //卡牌
Potion = 4, //药水
}
/** 卡池等级定义 */
export enum CardLV {
LV1 = 1,
LV2 = 2,
LV3 = 3,
}
/** 通用卡牌配置 */
export interface CardConfig {
uuid: number
type: CardType
cost: number
weight: number
kind: CKind
pool_lv: CardLV
hero_lv?: number
card_lv?:number
// 技能卡扩展属性
name?: string // 卡牌名称
info?: string // 卡牌描述信息
is_inst?: boolean // 是否即时起效
t_times?: number // 触发次数
t_inv?: number // 触发间隔(秒)
}
export const CardsUpSet: Record<number, number> = {
1: 50,
2: 100,
3: 150,
4: 200,
5: 250,
}
/**初始coin数 */
export const CardInitCoins = 11
/** 卡池升级每波减免金额 */
export const CARD_POOL_UPGRADE_DISCOUNT_PER_WAVE = 10
/** 卡池默认初始等级 */
export const CARD_POOL_INIT_LEVEL = CardLV.LV1
/** 卡池等级上限 */
export const CARD_POOL_MAX_LEVEL = CardLV.LV3
/** 英雄最高等级限制 */
export const CARD_HERO_MAX_LEVEL = 1
/** 基础卡池(英雄、技能、功能) */
export const CardPoolList: CardConfig[] = [
{ uuid: 5001, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5101, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5201, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5301, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5003, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5102, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5302, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5002, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 2, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5103, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 2, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5202, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 2, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5004, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 2, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5104, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 2, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5303, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 2, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5105, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 3, kind: CKind.Hero, hero_lv: 1 },
{ uuid: 5304, type: CardType.Hero, cost: 10, weight: 25, pool_lv: 3, kind: CKind.Hero, hero_lv: 1 },
// 技能卡牌 (以增益/辅助为主,因为在备战期没有敌人)
{ uuid: 6401, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, get name(){return t("skill_name_6401")}, get info(){return t("skill_info_6401")}, is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6402, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, get name(){return t("skill_name_6402")}, get info(){return t("skill_info_6402")}, is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6403, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, get name(){return t("skill_name_6403")}, get info(){return t("skill_info_6403")}, is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6404, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, get name(){return t("skill_name_6404")}, get info(){return t("skill_info_6404")}, is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6405, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 2, kind: CKind.Skill, card_lv: 1, get name(){return t("skill_name_6405")}, get info(){return t("skill_info_6405")}, is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6406, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 2, kind: CKind.Skill, card_lv: 1, get name(){return t("skill_name_6406")}, get info(){return t("skill_info_6406")}, is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6304, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 3, kind: CKind.Skill, card_lv: 1, get name(){return t("skill_name_6304")}, get info(){return t("skill_info_6304")}, is_inst: true, t_times: 1, t_inv: 0 },
{ uuid: 6305, type: CardType.Skill, cost: 10, weight: 20, pool_lv: 3, kind: CKind.Skill, card_lv: 1, get name(){return t("skill_name_6305")}, get info(){return t("skill_info_6305")}, is_inst: true, t_times: 1, t_inv: 0 },
// { uuid: 7101, type: CardType.SpecialRefresh, cost: 1, weight: 12, pool_lv: 1 ,kind: CKind.Card },
// { uuid: 7102, type: CardType.SpecialRefresh, cost: 1, weight: 12, pool_lv: 1 ,kind: CKind.Card },
// { uuid: 7103, type: CardType.SpecialRefresh, cost: 1, weight: 12, pool_lv: 1 ,kind: CKind.Card },
]
export enum SpecialRefreshHeroType {
Any = 0,
Melee = 1,
Ranged = 2,
}
/** 升级功能卡完整配置 */
export interface SpecialUpgradeCardConfig extends CardConfig {
name: string
info: string
currentLv: number
targetLv: number
}
/** 刷新功能卡完整配置 */
export interface SpecialRefreshCardConfig extends CardConfig {
name: string
info: string
refreshLv: number
refreshHeroType: SpecialRefreshHeroType
}
/** 功能卡定义表 */
export const SpecialUpgradeCardList: Record<number, SpecialUpgradeCardConfig> = {
7001: { uuid: 7001,type: CardType.SpecialUpgrade,cost: 6,weight: 16,pool_lv: CardLV.LV1,kind:CKind.Card,get name(){return t("scard_name_7001")},get info(){return t("scard_info_7001")},
currentLv: 1, targetLv: 2,
},
7002: { uuid: 7002,type: CardType.SpecialUpgrade,cost: 6,weight: 14,pool_lv: CardLV.LV2,kind:CKind.Card,get name(){return t("scard_name_7002")},get info(){return t("scard_info_7002")},
currentLv: 2, targetLv: 3,
},
}
export const SpecialRefreshCardList: Record<number, SpecialRefreshCardConfig> = {
7101: { uuid: 7101,type: CardType.SpecialRefresh,cost: 4,weight: 14,pool_lv: CardLV.LV1,kind:CKind.Card,get name(){return t("scard_name_7101")},get info(){return t("scard_info_7101")},
refreshLv: 0, refreshHeroType: SpecialRefreshHeroType.Melee,
},
7102: { uuid: 7102,type: CardType.SpecialRefresh,cost: 4,weight: 14,pool_lv: CardLV.LV1,kind:CKind.Card,get name(){return t("scard_name_7102")},get info(){return t("scard_info_7102")},
refreshLv: 0, refreshHeroType: SpecialRefreshHeroType.Ranged,
},
7103: { uuid: 7103,type: CardType.SpecialRefresh,cost: 5,weight: 12,pool_lv: CardLV.LV2,kind:CKind.Card,get name(){return t("scard_name_7103")},get info(){return t("scard_info_7103")},
refreshLv: 3, refreshHeroType: SpecialRefreshHeroType.Any,
},
}
/** 规范等级到合法区间 [LV1, LV6] */
const clampCardLv = (lv: number): CardLV => {
const value = Math.floor(lv)
if (value < CARD_POOL_INIT_LEVEL) return CARD_POOL_INIT_LEVEL
if (value > CARD_POOL_MAX_LEVEL) return CARD_POOL_MAX_LEVEL
return value as CardLV
}
/** 单次按权重抽取一张卡 */
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 张卡,允许重复 */
const pickCards = (cards: CardConfig[], count: number): CardConfig[] => {
if (cards.length === 0 || count <= 0) return []
const selected: CardConfig[] = []
while (selected.length < count) {
const pick = weightedPick(cards)
if (!pick) break
selected.push(pick)
}
return selected
}
/** 获取指定等级可出现的基础卡池 */
export const getCardPoolByLv = (lv: number, onlyCurrentLv: boolean = false): CardConfig[] => {
const cardLv = clampCardLv(lv)
if (onlyCurrentLv) {
return CardPoolList.filter(card => card.pool_lv === cardLv)
}
return CardPoolList.filter(card => card.pool_lv <= cardLv)
}
const normalizeTypeFilter = (type: CardType | CardType[]): Set<CardType> => {
const list = Array.isArray(type) ? type : [type]
return new Set<CardType>(list)
}
/** 常规发牌:前 3 英雄 + 后 1 其他;支持按类型和等级模式过滤 */
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]
}
export const drawCardsByRule = (
lv: number,
options: {
count?: number
onlyCurrentLv?: boolean
type?: CardType | CardType[]
heroType?: HType
heroLv?: number
targetPoolLv?: number
} = {}
): CardConfig[] => {
const count = Math.max(0, Math.floor(options.count ?? 4))
const onlyCurrentLv = options.onlyCurrentLv ?? false
let pool = getCardPoolByLv(lv, onlyCurrentLv)
if (options.type !== undefined) {
const typeSet = normalizeTypeFilter(options.type)
pool = pool.filter(card => typeSet.has(card.type))
}
if (options.targetPoolLv !== undefined) {
// 如果指定了目标卡池等级,则强制从所有配置中筛选该等级的卡牌,无视当前的卡池等级限制
pool = CardPoolList.filter(card => card.pool_lv === options.targetPoolLv)
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
})
}
const picked = pickCards(pool, count)
return picked
}