Files
heros/assets/script/game/common/config/Guide.ts
2025-08-25 17:28:02 +08:00

290 lines
9.7 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.

import { oops } from "db://oops-framework/core/Oops";
import { smc } from "../SingletonModuleComp";
import { GameEvent } from "./GameEvent";
import { UIID } from "./GameUIConfig";
/** 引导步骤类型枚举 */
export enum GuideStepType {
/** 点击操作 */
CLICK = "click",
/** 拖拽操作 */
DRAG = "drag",
/** 显示提示 */
TIP = "tip",
/** 等待操作 */
WAIT = "wait",
}
export const finishCurrGuide=(key:number)=>{
if(key==0){
oops.message.dispatchEvent(GameEvent.GuideEnd,key)
}else{
if(smc.guides[key-1]===1&&smc.guides[key]===0){
oops.message.dispatchEvent(GameEvent.GuideEnd,key)
}
}
}
export const startGuide=(key:number)=>{
if(smc.guides[key-1]===1&&smc.guides[key]===0){
oops.message.dispatchEvent(GameEvent.GuideStart,key)
}
}
/** 引导步骤配置接口 */
export interface IGuideStep {
/** 步骤ID */
id: string;
/** 步骤类型 */
type: GuideStepType;
/** 目标节点路径(用于查找目标节点) */
key: number;
targetPath?: string;
tipParent?: string;
/** 提示文本 */
tipText?: string;
/** 提示文本偏移 */
tipOffset?: { x: number, y: number };
/** 手指动画位置偏移 */
handOffset?: { x: number, y: number };
/** 下一步骤ID */
nextStep?: string;
/** 是否可跳过 */
skippable?: boolean;
/** 触发条件 */
condition?: () => boolean;
/** 对应的UI界面ID */
uiId?: UIID;
/** 等待时间 */
waitTime?: number;
/** 结束事件 */
end_event?: string;
/** 是否禁用输入 */
noInput?: boolean;
}
/** 引导配置数据 */
export const GuideConfig: { [key: number]: IGuideStep } = {
0: {
id: "welcome", type: GuideStepType.WAIT,key:0,
targetPath: "root/gui/LayerUI/role_controller/mission_home/start/name",
tipText: "欢迎来到游戏",
handOffset: { x: 42, y: -45 }, tipOffset: { x: 0, y: 600 },
nextStep: "start_battle", waitTime: 2, end_event: "click", noInput: true,
},
1: {
id: "start_battle", type: GuideStepType.CLICK,key:1,
targetPath: "root/gui/LayerUI/role_controller/mission_home/start/name",
tipText: "让我们抵御兽人的入侵吧!",
handOffset: { x: 42, y: -45 }, tipOffset: { x: 0, y: 200 },
// 42 45是手指的偏移量 0 0是提示的偏移量
},
2: {
id: "hero_page", type: GuideStepType.CLICK,key:2,
// 使用相对路径,从场景根节点开始查找
targetPath: "root/gui/LayerUI/role_controller/mission_home/btns/heros",
tipText: "去招募更多英雄增强队伍吧",
handOffset: { x: 42, y: -45 }, tipOffset: { x: 0, y: 200 },
},
3: {
id: "to_hero_info", type: GuideStepType.CLICK,key:3,
// 使用相对路径,从场景根节点开始查找
targetPath: "root/gui/LayerUI/role_controller/mission_home/heros_page",
tipText: "选择可以解锁的英雄吧",
handOffset: { x: 42, y: -45 }, tipOffset: { x: 0, y: 200 } // 向上偏移50像素避免遮挡
},
4: {
id: "do_hero_info", type: GuideStepType.CLICK,key:4,
// 使用相对路径,从场景根节点开始查找
targetPath: "root/gui/LayerUI/Hinfo/unLock",
tipText: "招募这个英雄",
handOffset: { x: 42, y: -45 }, tipOffset: { x: 0, y: 200 }// 向上偏移50像素避免遮挡
},
5: {
id: "up_lv_hero", type: GuideStepType.CLICK,key:5,
// 使用相对路径,从场景根节点开始查找
targetPath: "root/gui/LayerUI/Hinfo/upBtn",
tipText: "升级强化这个英雄",
handOffset: { x: 42, y: -45 },tipOffset: { x: 0, y: 200 } // 向上偏移50像素避免遮挡
},
6: {
id: "close_hinfo", type: GuideStepType.CLICK,key:6,
// 使用相对路径,从场景根节点开始查找
targetPath: "root/gui/LayerUI/Hinfo/back",
tipText: "返回",
handOffset: { x: 42, y: -45 },tipOffset: { x: 0, y: 200 } // 向上偏移50像素避免遮挡
},
7: {
id: "to_mission", type: GuideStepType.CLICK,key:7,
// 使用相对路径,从场景根节点开始查找
targetPath: "root/gui/LayerUI/role_controller/mission_home/btns/fight",
tipText: "再次进入战斗",
handOffset: { x: 42, y: -45 }, tipOffset: { x: 0, y: 200 },
},
8: {
id: "to_add_hero", type: GuideStepType.CLICK,key:8,
// 使用相对路径,从场景根节点开始查找
targetPath: "root/gui/LayerUI/role_controller/mission_home/readyheros/hero3",
tipText: "添加上阵英雄",
handOffset: { x: 42, y: -45 }, tipOffset: { x: 0, y: 200 },
},
9: {
id: "to_hero_select", type: GuideStepType.CLICK,key:9,
// 使用相对路径,从场景根节点开始查找
targetPath: "root/gui/LayerUI/hero_select/main/view/heros/hero2",
tipText: "选择英雄",
handOffset: { x: 42, y: -45 }, tipOffset: { x: 0, y: 200 },
},
10: {
id: "start_battle", type: GuideStepType.CLICK,key:10,
targetPath: "root/gui/LayerUI/role_controller/mission_home/start/name",
tipText: "享受你的游戏!",
handOffset: { x: 42, y: -45 }, tipOffset: { x: 0, y: 200 },
// 42 45是手指的偏移量 0 0是提示的偏移量
},
};
/** 引导配置数组(用于兼容性) */
export const GuideConfigArray: IGuideStep[] = Object.values(GuideConfig);
/** 结束事件到引导索引的映射 */
export const EndEventToKey: { [key: string]: number[] } = {
[GameEvent.UpdateFightHero]: [4],
[GameEvent.MonDead]: [1],
[GameEvent.HeroLvUp]: [5],
// 示例:一个事件对应多个引导步骤
// [GameEvent.BattleStart]: [2, 3, 4], // 战斗开始时触发多个引导
// [GameEvent.LevelUp]: [5, 6, 7], // 升级时触发多个引导
// [GameEvent.HeroUnlock]: [8, 9], // 解锁英雄时触发多个引导
// [GameEvent.MissionComplete]: [10, 11, 12], // 任务完成时触发多个引导
}
/** 通过 end_event 查找引导索引数组 */
export function findGuidesByEndEvent(event: string): number[] {
return EndEventToKey[event] || [];
}
/** 通过 end_event 查找引导索引(保持向后兼容) */
export function findGuideByEndEvent(event: string): number | undefined {
const guides = EndEventToKey[event];
return guides && guides.length > 0 ? guides[0] : undefined;
}
/** 通过引导ID查找引导索引 */
export function findGuideIndexById(guideId: string): number {
for (const [key, guide] of Object.entries(GuideConfig)) {
if (guide.id === guideId) {
return parseInt(key);
}
}
return -1;
}
/** 通过引导ID查找引导配置 */
export function findGuideById(guideId: string): IGuideStep | undefined {
for (const guide of Object.values(GuideConfig)) {
if (guide.id === guideId) {
return guide;
}
}
return undefined;
}
/** 通过数字ID查找引导配置 */
export function findGuideByNumberId(numberId: number): IGuideStep | undefined {
return GuideConfig[numberId];
}
/** 获取所有引导ID列表 */
export function getAllGuideIds(): number[] {
return Object.keys(GuideConfig).map(key => parseInt(key));
}
/** 获取引导配置总数 */
export function getGuideConfigCount(): number {
return Object.keys(GuideConfig).length;
}
/**
* 使用示例如何使用新的数字ID配置格式
*
* 1. 配置格式:
* export const GuideConfig: { [key: number]: IGuideStep } = {
* 0: { id: "welcome", ... },
* 1: { id: "start_battle", ... },
* 2: { id: "hero_page", ... },
* }
*
* 2. 通过数字ID查找引导
* const guide = findGuideByNumberId(0); // 直接通过数字ID查找
*
* 3. 通过字符串ID查找引导
* const guide = findGuideById("welcome"); // 通过字符串ID查找
*
* 4. 获取引导的数字索引:
* const index = findGuideIndexById("welcome"); // 返回 0
*
* 5. 事件映射配置:
* export const EndEventToKey: { [key: string]: number[] } = {
* [GameEvent.BattleStart]: [2, 3, 4], // 一个事件对应多个引导
* }
*
* 6. 启动引导:
* oops.message.dispatchEvent(GameEvent.GuideStart, 0); // 启动ID为0的引导
*
* 7. 优势:
* - 数字ID与 smc.guides 数组索引完全对应
* - 支持一个事件触发多个引导
* - 向后兼容,现有代码无需大幅修改
* - 便于扩展新的引导步骤
* - 数组索引从0开始符合编程习惯
*/
/** 引导管理器配置 */
export interface IGuideManagerConfig {
/** 是否启用引导 */
enabled: boolean;
/** 引导配置文件路径 */
configPath: string;
/** 引导进度保存键 */
progressKey: string;
/** 默认引导ID */
defaultGuideId: string;
/** 引导层优先级 */
layerPriority: number;
}
/** 默认引导管理器配置 */
export const DefaultGuideConfig: IGuideManagerConfig = {
enabled: true,
configPath: "config/Guide",
progressKey: "guide_progress",
defaultGuideId: "welcome",
layerPriority: 1000
};
/** 引导事件类型 */
export enum GuideEventType {
/** 引导开始 */
GUIDE_START = "guide_start",
/** 引导步骤完成 */
STEP_COMPLETE = "step_complete",
/** 引导跳过 */
GUIDE_SKIP = "guide_skip",
/** 引导完成 */
GUIDE_COMPLETE = "guide_complete",
/** 引导错误 */
GUIDE_ERROR = "guide_error"
}
/** 引导步骤状态 */
export enum GuideStepStatus {
/** 未开始 */
NOT_STARTED = "not_started",
/** 进行中 */
IN_PROGRESS = "in_progress",
/** 已完成 */
COMPLETED = "completed",
/** 已跳过 */
SKIPPED = "skipped"
}