feat(map): 新增固定波次技能三选一弹窗系统
1. 新增MSkillBoxComp弹窗组件,实现固定波次触发的技能卡选择功能 2. 新增SkillBoxCardConfig配置与SkillBoxPool技能池,支持按波次配置技能 3. 重构MissionCardComp,将技能卡抽取改为固定波次弹窗触发 4. 扩展SingletonModuleComp与MissionComp,添加技能刷新次数持久化逻辑 5. 优化MissSkillsComp,新增SkillBox专属技能加载流程 6. 修复SkillBoxComp,支持自定义技能参数覆盖 7. 调整UIConfig与CardSet配置,适配新的技能卡流程
This commit is contained in:
@@ -73,6 +73,9 @@ export class SingletonModuleComp extends ecs.Comp {
|
||||
max_mission: 4,//最大关卡
|
||||
coin: 0,
|
||||
time: 15 * 60,//游戏时间
|
||||
// 技能三选一弹窗:刷新次数(跨波次保留,广告可叠加)
|
||||
skill_box_refresh_remain: 1, // 初始赠送的刷新次数
|
||||
skill_box_ad_refresh_remain: 0, // 看广告累计的额外次数
|
||||
},
|
||||
scores: {
|
||||
score: 0, // 基础得分
|
||||
|
||||
@@ -2,9 +2,10 @@ import * as exp from "constants"
|
||||
import { HeroInfo, HeroList, HType } from "./heroSet"
|
||||
import { FightSet } from "./GameSet"
|
||||
import { oops } from "db://oops-framework/core/Oops"
|
||||
import { SkillOverrides } from "./SkillSet"
|
||||
|
||||
class I18nString {
|
||||
constructor(private key: string, private params?: any[]) {}
|
||||
constructor(private key: string, private params?: any[]) { }
|
||||
private getTranslated(): string {
|
||||
let str = oops.language.getLangByID(this.key) || this.key;
|
||||
if (this.params && this.params.length > 0) {
|
||||
@@ -52,9 +53,9 @@ export interface CardConfig {
|
||||
kind: CKind
|
||||
pool_lv: CardLV
|
||||
hero_lv?: number
|
||||
card_lv?:number
|
||||
card_lv?: number
|
||||
base_pool_lv?: number
|
||||
|
||||
|
||||
// 技能卡扩展属性
|
||||
name?: string // 卡牌名称
|
||||
info?: string // 卡牌描述信息
|
||||
@@ -62,6 +63,25 @@ export interface CardConfig {
|
||||
t_times?: number // 触发次数
|
||||
t_inv?: number // 触发间隔(秒)
|
||||
}
|
||||
|
||||
/**
|
||||
* 技能卡池专用卡牌配置(MSkillBoxComp 三选一弹窗使用)
|
||||
*
|
||||
* 在普通 CardConfig 基础上扩展:
|
||||
* - s_uuid : 实际生效的 SkillSet 条目 uuid
|
||||
* - t_num : 触发次数(可选,默认从 SkillSet 读取)
|
||||
* - overrides : 参数覆盖,参考 heroSet 中触发技能的 overrides 字段格式
|
||||
*
|
||||
* uuid 范围 9000+ 用于和普通 CardPoolList 区分,MissSkillsComp 据此识别。
|
||||
*/
|
||||
export interface SkillBoxCardConfig extends CardConfig {
|
||||
/** 实际生效的 SkillSet 技能 uuid */
|
||||
s_uuid: number
|
||||
/** 触发次数(可选,默认 1) */
|
||||
t_num?: number
|
||||
/** 技能参数覆盖,参考 SkillOverrides */
|
||||
overrides?: SkillOverrides
|
||||
}
|
||||
export const CardsUpSet: Record<number, number> = {
|
||||
1: 50,
|
||||
2: 100,
|
||||
@@ -88,28 +108,28 @@ export const CardPoolList: CardConfig[] = [];
|
||||
HeroList.forEach(uuid => {
|
||||
const hero = HeroInfo[uuid];
|
||||
if (!hero) return;
|
||||
|
||||
|
||||
const basePoolLv = hero.pool_lv || 1;
|
||||
const baseHeroLv = hero.lv || 1;
|
||||
const baseCost = 5;
|
||||
const baseWeight = 25;
|
||||
|
||||
|
||||
// 生成从 basePoolLv 到 CARD_POOL_MAX_LEVEL 的卡牌
|
||||
for (let pLv = basePoolLv; pLv <= CARD_POOL_MAX_LEVEL; pLv++) {
|
||||
const offset = pLv - basePoolLv;
|
||||
const targetHeroLv = baseHeroLv + offset;
|
||||
|
||||
|
||||
// 英雄的最高等级 是MERGE_MAX-1
|
||||
if (targetHeroLv > FightSet.MERGE_MAX - 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// cost = baseCost * 3^(lv-1): Lv1=5, Lv2=15, Lv3=45
|
||||
let cost = baseCost;
|
||||
if (targetHeroLv > 1) {
|
||||
cost = baseCost * Math.pow(FightSet.MERGE_NEED, targetHeroLv - 1);
|
||||
}
|
||||
|
||||
|
||||
CardPoolList.push({
|
||||
uuid: hero.uuid,
|
||||
type: CardType.Hero,
|
||||
@@ -164,22 +184,27 @@ export interface SpecialRefreshCardConfig extends CardConfig {
|
||||
|
||||
|
||||
export const SpecialUpgradeCardList: Record<number, SpecialUpgradeCardConfig> = {
|
||||
7001: { uuid: 7001,type: CardType.SpecialUpgrade,cost: 10,weight: 16,pool_lv: CardLV.LV1,kind:CKind.Card,name:t("scard_name_7001"),info:t("scard_info_7001"),
|
||||
7001: {
|
||||
uuid: 7001, type: CardType.SpecialUpgrade, cost: 10, weight: 16, pool_lv: CardLV.LV1, kind: CKind.Card, name: t("scard_name_7001"), info: t("scard_info_7001"),
|
||||
currentLv: 1, targetLv: 2,
|
||||
},
|
||||
7002: { uuid: 7002,type: CardType.SpecialUpgrade,cost: 28,weight: 14,pool_lv: CardLV.LV2,kind:CKind.Card,name:t("scard_name_7002"),info:t("scard_info_7002"),
|
||||
7002: {
|
||||
uuid: 7002, type: CardType.SpecialUpgrade, cost: 28, weight: 14, pool_lv: CardLV.LV2, kind: CKind.Card, name: t("scard_name_7002"), info: t("scard_info_7002"),
|
||||
currentLv: 2, targetLv: 3,
|
||||
},
|
||||
}
|
||||
|
||||
export const SpecialRefreshCardList: Record<number, SpecialRefreshCardConfig> = {
|
||||
7101: { uuid: 7101,type: CardType.SpecialRefresh,cost: 3,weight: 14,pool_lv: CardLV.LV1,kind:CKind.Card,name:t("scard_name_7101"),info:t("scard_info_7101"),
|
||||
7101: {
|
||||
uuid: 7101, type: CardType.SpecialRefresh, cost: 3, weight: 14, pool_lv: CardLV.LV1, kind: CKind.Card, name: t("scard_name_7101"), info: t("scard_info_7101"),
|
||||
refreshLv: 0, refreshHeroType: SpecialRefreshHeroType.Melee,
|
||||
},
|
||||
7102: { uuid: 7102,type: CardType.SpecialRefresh,cost: 3,weight: 14,pool_lv: CardLV.LV1,kind:CKind.Card,name:t("scard_name_7102"),info:t("scard_info_7102"),
|
||||
7102: {
|
||||
uuid: 7102, type: CardType.SpecialRefresh, cost: 3, weight: 14, pool_lv: CardLV.LV1, kind: CKind.Card, name: t("scard_name_7102"), info: t("scard_info_7102"),
|
||||
refreshLv: 0, refreshHeroType: SpecialRefreshHeroType.Ranged,
|
||||
},
|
||||
7103: { uuid: 7103,type: CardType.SpecialRefresh,cost: 4,weight: 12,pool_lv: CardLV.LV2,kind:CKind.Card,name:t("scard_name_7103"),info:t("scard_info_7103"),
|
||||
7103: {
|
||||
uuid: 7103, type: CardType.SpecialRefresh, cost: 4, weight: 12, pool_lv: CardLV.LV2, kind: CKind.Card, name: t("scard_name_7103"), info: t("scard_info_7103"),
|
||||
refreshLv: 3, refreshHeroType: SpecialRefreshHeroType.Any,
|
||||
},
|
||||
}
|
||||
@@ -290,3 +315,172 @@ export const drawCardsByRule = (
|
||||
const picked = pickCards(pool, count)
|
||||
return picked
|
||||
}
|
||||
|
||||
/**
|
||||
* 固定波次弹出技能三选一弹窗(MissionCardComp 触发)
|
||||
* 5 个波次:1 / 5 / 10 / 15 / 20
|
||||
*/
|
||||
export const SKILL_BOX_TRIGGER_WAVES: readonly number[] = [1, 5, 10, 15, 20] as const
|
||||
|
||||
/**
|
||||
* 技能卡池(MSkillBoxComp 三选一)
|
||||
*
|
||||
* 5 个硬编码独立池,key 对应触发波次,value 是该波次可刷出的 SkillBoxCardConfig 列表。
|
||||
* 每条配置:
|
||||
* - uuid 唯一且 >= 9000,用于 MissSkillsComp 识别
|
||||
* - s_uuid 指向 SkillSet 中实际生效的技能
|
||||
* - overrides 参考 heroSet 触发技能格式,对技能参数做具体覆盖
|
||||
* - cost 强制 0(免费领取)
|
||||
* - is_inst / t_times / t_inv 控制技能使用后行为
|
||||
*/
|
||||
export const SkillBoxPool: Record<number, SkillBoxCardConfig[]> = {
|
||||
// 第 1 波:基础技能(伤害/治疗/护盾基础数值)
|
||||
1: [
|
||||
{
|
||||
uuid: 9001, type: CardType.Skill, cost: 0, weight: 0, pool_lv: CardLV.LV1, kind: CKind.Skill, card_lv: 1,
|
||||
name: t("skillbox_name_9001"), info: t("skillbox_info_9001"),
|
||||
is_inst: true, t_times: 1, t_inv: 0,
|
||||
s_uuid: 6401, t_num: 1, overrides: { ap: 120 }
|
||||
},
|
||||
{
|
||||
uuid: 9002, type: CardType.Skill, cost: 0, weight: 0, pool_lv: CardLV.LV1, kind: CKind.Skill, card_lv: 1,
|
||||
name: t("skillbox_name_9002"), info: t("skillbox_info_9002"),
|
||||
is_inst: true, t_times: 1, t_inv: 0,
|
||||
s_uuid: 6402, t_num: 1, overrides: { ap: 150 }
|
||||
},
|
||||
{
|
||||
uuid: 9003, type: CardType.Skill, cost: 0, weight: 0, pool_lv: CardLV.LV1, kind: CKind.Skill, card_lv: 1,
|
||||
name: t("skillbox_name_9003"), info: t("skillbox_info_9003"),
|
||||
is_inst: true, t_times: 1, t_inv: 0,
|
||||
s_uuid: 6403, t_num: 1, overrides: { ap: 100, hit_count: 2 }
|
||||
},
|
||||
{
|
||||
uuid: 9004, type: CardType.Skill, cost: 0, weight: 0, pool_lv: CardLV.LV1, kind: CKind.Skill, card_lv: 1,
|
||||
name: t("skillbox_name_9004"), info: t("skillbox_info_9004"),
|
||||
is_inst: true, t_times: 1, t_inv: 0,
|
||||
s_uuid: 6404, t_num: 1, overrides: { ap: 110 }
|
||||
},
|
||||
],
|
||||
// 第 5 波:中级技能(伤害提升,带附加效果)
|
||||
5: [
|
||||
{
|
||||
uuid: 9005, type: CardType.Skill, cost: 0, weight: 0, pool_lv: CardLV.LV2, kind: CKind.Skill, card_lv: 1,
|
||||
name: t("skillbox_name_9005"), info: t("skillbox_info_9005"),
|
||||
is_inst: true, t_times: 1, t_inv: 0,
|
||||
s_uuid: 6405, t_num: 1, overrides: { ap: 130, crt: 10 }
|
||||
},
|
||||
{
|
||||
uuid: 9006, type: CardType.Skill, cost: 0, weight: 0, pool_lv: CardLV.LV2, kind: CKind.Skill, card_lv: 1,
|
||||
name: t("skillbox_name_9006"), info: t("skillbox_info_9006"),
|
||||
is_inst: true, t_times: 1, t_inv: 0,
|
||||
s_uuid: 6406, t_num: 1, overrides: { ap: 140, hit_count: 2 }
|
||||
},
|
||||
{
|
||||
uuid: 9007, type: CardType.Skill, cost: 0, weight: 0, pool_lv: CardLV.LV2, kind: CKind.Skill, card_lv: 1,
|
||||
name: t("skillbox_name_9007"), info: t("skillbox_info_9007"),
|
||||
is_inst: true, t_times: 1, t_inv: 0,
|
||||
s_uuid: 6304, t_num: 1, overrides: { ap: 160 }
|
||||
},
|
||||
{
|
||||
uuid: 9008, type: CardType.Skill, cost: 0, weight: 0, pool_lv: CardLV.LV2, kind: CKind.Skill, card_lv: 1,
|
||||
name: t("skillbox_name_9008"), info: t("skillbox_info_9008"),
|
||||
is_inst: false, t_times: 3, t_inv: 2,
|
||||
s_uuid: 6401, t_num: 3, overrides: { ap: 100 }
|
||||
},
|
||||
],
|
||||
// 第 10 波:高级技能(高伤害/多段/持续)
|
||||
10: [
|
||||
{
|
||||
uuid: 9009, type: CardType.Skill, cost: 0, weight: 0, pool_lv: CardLV.LV3, kind: CKind.Skill, card_lv: 1,
|
||||
name: t("skillbox_name_9009"), info: t("skillbox_info_9009"),
|
||||
is_inst: true, t_times: 1, t_inv: 0,
|
||||
s_uuid: 6305, t_num: 1, overrides: { ap: 200 }
|
||||
},
|
||||
{
|
||||
uuid: 9010, type: CardType.Skill, cost: 0, weight: 0, pool_lv: CardLV.LV3, kind: CKind.Skill, card_lv: 1,
|
||||
name: t("skillbox_name_9010"), info: t("skillbox_info_9010"),
|
||||
is_inst: true, t_times: 1, t_inv: 0,
|
||||
s_uuid: 6405, t_num: 1, overrides: { ap: 220, hit_count: 3, crt: 15 }
|
||||
},
|
||||
{
|
||||
uuid: 9011, type: CardType.Skill, cost: 0, weight: 0, pool_lv: CardLV.LV3, kind: CKind.Skill, card_lv: 1,
|
||||
name: t("skillbox_name_9011"), info: t("skillbox_info_9011"),
|
||||
is_inst: false, t_times: 4, t_inv: 1.5,
|
||||
s_uuid: 6402, t_num: 4, overrides: { ap: 130, frz: 10 }
|
||||
},
|
||||
{
|
||||
uuid: 9012, type: CardType.Skill, cost: 0, weight: 0, pool_lv: CardLV.LV3, kind: CKind.Skill, card_lv: 1,
|
||||
name: t("skillbox_name_9012"), info: t("skillbox_info_9012"),
|
||||
is_inst: true, t_times: 1, t_inv: 0,
|
||||
s_uuid: 6406, t_num: 1, overrides: { ap: 240, bck: 20 }
|
||||
},
|
||||
],
|
||||
// 第 15 波:精英技能(高额暴击/多段)
|
||||
15: [
|
||||
{
|
||||
uuid: 9013, type: CardType.Skill, cost: 0, weight: 0, pool_lv: CardLV.LV3, kind: CKind.Skill, card_lv: 2,
|
||||
name: t("skillbox_name_9013"), info: t("skillbox_info_9013"),
|
||||
is_inst: true, t_times: 1, t_inv: 0,
|
||||
s_uuid: 6304, t_num: 1, overrides: { ap: 280, hit_count: 3 }
|
||||
},
|
||||
{
|
||||
uuid: 9014, type: CardType.Skill, cost: 0, weight: 0, pool_lv: CardLV.LV3, kind: CKind.Skill, card_lv: 2,
|
||||
name: t("skillbox_name_9014"), info: t("skillbox_info_9014"),
|
||||
is_inst: true, t_times: 1, t_inv: 0,
|
||||
s_uuid: 6305, t_num: 1, overrides: { ap: 320, crt: 25 }
|
||||
},
|
||||
{
|
||||
uuid: 9015, type: CardType.Skill, cost: 0, weight: 0, pool_lv: CardLV.LV3, kind: CKind.Skill, card_lv: 2,
|
||||
name: t("skillbox_name_9015"), info: t("skillbox_info_9015"),
|
||||
is_inst: false, t_times: 5, t_inv: 1.2,
|
||||
s_uuid: 6406, t_num: 5, overrides: { ap: 200, hit_count: 2, bck: 30 }
|
||||
},
|
||||
],
|
||||
// 第 20 波:终极技能(全屏/极限数值)
|
||||
20: [
|
||||
{
|
||||
uuid: 9016, type: CardType.Skill, cost: 0, weight: 0, pool_lv: CardLV.LV3, kind: CKind.Skill, card_lv: 3,
|
||||
name: t("skillbox_name_9016"), info: t("skillbox_info_9016"),
|
||||
is_inst: true, t_times: 1, t_inv: 0,
|
||||
s_uuid: 6304, t_num: 1, overrides: { ap: 400, hit_count: 4, crt: 30 }
|
||||
},
|
||||
{
|
||||
uuid: 9017, type: CardType.Skill, cost: 0, weight: 0, pool_lv: CardLV.LV3, kind: CKind.Skill, card_lv: 3,
|
||||
name: t("skillbox_name_9017"), info: t("skillbox_info_9017"),
|
||||
is_inst: true, t_times: 1, t_inv: 0,
|
||||
s_uuid: 6305, t_num: 1, overrides: { ap: 500, crt: 40, frz: 20 }
|
||||
},
|
||||
{
|
||||
uuid: 9018, type: CardType.Skill, cost: 0, weight: 0, pool_lv: CardLV.LV3, kind: CKind.Skill, card_lv: 3,
|
||||
name: t("skillbox_name_9018"), info: t("skillbox_info_9018"),
|
||||
is_inst: true, t_times: 1, t_inv: 0,
|
||||
s_uuid: 6406, t_num: 1, overrides: { ap: 600, hit_count: 5, bck: 50 }
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
/**
|
||||
* 从指定波次的技能池中抽取 N 张卡(加权随机,去重,不足循环补齐)
|
||||
*
|
||||
* @param wave 触发波次(1/5/10/15/20),若该波次无池则返回空数组
|
||||
* @param count 期望返回卡牌数(默认 3)
|
||||
* @returns 抽中的 SkillBoxCardConfig 列表(长度 = count)
|
||||
*/
|
||||
export function getSkillBoxCards(wave: number, count: number = 3): SkillBoxCardConfig[] {
|
||||
const pool = SkillBoxPool[wave] || [];
|
||||
if (pool.length === 0) return [];
|
||||
const result: SkillBoxCardConfig[] = [];
|
||||
const usedIndexes = new Set<number>();
|
||||
for (let i = 0; i < count; i++) {
|
||||
const available: number[] = [];
|
||||
for (let j = 0; j < pool.length; j++) {
|
||||
if (!usedIndexes.has(j)) available.push(j);
|
||||
}
|
||||
// 池内卡片不足时,允许重复
|
||||
const candidates = available.length > 0 ? available : Array.from({ length: pool.length }, (_, k) => k);
|
||||
const pick = candidates[Math.floor(Math.random() * candidates.length)];
|
||||
usedIndexes.add(pick);
|
||||
result.push(pool[pick]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -39,5 +39,5 @@ export var UIConfigData: { [key: number]: UIConfig } = {
|
||||
// [UIID.Talents]: { layer: LayerType.UI, prefab: "gui/element/talents" },
|
||||
[UIID.Mission]: { layer: LayerType.UI, prefab: "gui/element/mission" },
|
||||
[UIID.HInfo]: { layer: LayerType.UI, prefab: "gui/element/hnode" },
|
||||
[UIID.SkillBox]: { layer: LayerType.UI, prefab: "gui/element/skillbox" },
|
||||
[UIID.SkillBox]: { layer: LayerType.UI, prefab: "gui/element/MSkillBox" },
|
||||
}
|
||||
Reference in New Issue
Block a user