NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Gameplay/Guide/GuideManager.cs

376 lines
11 KiB
C#
Raw Normal View History

2024-05-22 16:31:29 +08:00
using cfg.GuideCfg;
2024-05-22 15:41:05 +08:00
using Framework;
2024-10-11 15:46:57 +08:00
using Framework.Condition;
using Gameplay.Level;
2024-06-05 14:04:26 +08:00
using Gameplay.Net;
using Gameplay.SubSystems;
2024-06-05 14:04:26 +08:00
using NLDPB;
2024-05-22 15:41:05 +08:00
using PhxhSDK;
2024-06-28 17:34:50 +08:00
using System;
2024-05-22 15:41:05 +08:00
using System.Collections.Generic;
2025-04-08 16:03:25 +08:00
using UnityEngine;
2024-05-22 15:41:05 +08:00
2024-05-29 16:36:30 +08:00
namespace Gameplay.Guide
2024-05-22 15:41:05 +08:00
{
2024-05-22 16:31:29 +08:00
/// <summary>
2024-05-29 16:36:30 +08:00
/// 新手引导管理器
2024-05-22 16:31:29 +08:00
/// </summary>
2025-04-08 14:07:20 +08:00
public sealed class GuideManager : Singlenton<GuideManager>, IInitable, IUpdatable
2024-05-24 19:11:19 +08:00
{
#region 兜底强制跳过引导机制
/// <summary>
2024-10-12 13:34:27 +08:00
/// 2秒内点击n次弹出强制跳过引导
/// </summary>
2024-10-12 12:54:52 +08:00
private readonly Queue<DateTime> queueTime = new();
/// <summary>
/// 强制跳过引导检测时间(秒)
/// </summary>
private const double SKIP_GUIDE_CHECK_TIME = 2d;
#endregion
2025-04-07 14:51:11 +08:00
2024-10-11 15:46:57 +08:00
/// <summary>
2025-04-07 18:08:08 +08:00
/// 未完成的引导步骤,注册的开始条件记录在这,key:reactionId,value:引导步骤配置
2024-10-11 15:46:57 +08:00
/// </summary>
2025-04-07 18:08:08 +08:00
private Dictionary<int, DataGuideCfg> dicReaction;
2024-10-11 15:46:57 +08:00
/// <summary>
2025-04-07 19:15:35 +08:00
/// 完成的引导步骤id
/// </summary>
private HashSet<int> setCompleteId;
/// <summary>
2025-04-07 18:08:08 +08:00
/// 当前的引导步骤
2024-10-11 15:46:57 +08:00
/// </summary>
2025-04-07 18:08:08 +08:00
private GuideStepBase curStep;
2024-10-18 18:13:23 +08:00
/// <summary>
2025-04-07 18:08:08 +08:00
/// 完成的引导组id
/// </summary>
2025-04-07 18:08:08 +08:00
private int completeGroupId;
2025-04-07 14:51:11 +08:00
/// <summary>
2025-04-07 18:08:08 +08:00
/// 是否初始化引导
2025-04-07 14:51:11 +08:00
/// </summary>
2025-04-07 18:08:08 +08:00
private bool isInitGuide;
2025-04-08 16:03:25 +08:00
/// <summary>
/// 是否任意点击
/// </summary>
private bool isAnyClick;
2025-04-08 19:05:57 +08:00
/// <summary>
/// 点击引导按钮
/// </summary>
private bool isClickButton;
2025-04-24 13:48:07 +08:00
/// <summary>
/// 战斗按钮是否显示
/// </summary>
public bool IsFightButtonShow;
2024-05-29 16:36:30 +08:00
/// <summary>
/// 是否引导中
/// </summary>
2025-04-07 18:08:08 +08:00
public bool IsGuiding { get { return null != curStep && curStep.IsGuiding; } }
2024-05-24 19:11:19 +08:00
#region 引导特殊控制参数
2024-07-03 14:07:54 +08:00
/// <summary>
/// 控制地板点击
/// </summary>
2024-07-04 16:06:01 +08:00
public bool IsControlFloor = false;
2024-07-01 13:08:37 +08:00
/// <summary>
/// 指定地板索引
/// </summary>
public int FloorIndex = -1;
2024-07-04 13:48:56 +08:00
/// <summary>
2024-10-18 18:13:23 +08:00
/// 是否响应任意点击
/// </summary>
public bool IsEnableAnyClick = true;
#endregion
2024-07-01 13:08:37 +08:00
2024-05-29 16:36:30 +08:00
public void Init()
2024-05-24 19:11:19 +08:00
{
2025-04-07 18:08:08 +08:00
isInitGuide = false;
2024-12-04 14:27:43 +08:00
InputManager.Instance.OnAnyClick += OnAnyClick;
2024-05-29 16:36:30 +08:00
}
2024-05-29 13:04:51 +08:00
public void Update(float deltaTime)
2025-04-08 16:03:25 +08:00
{
2025-04-08 19:05:57 +08:00
if (!IsGuiding)
return;
2025-04-08 16:03:25 +08:00
isAnyClick = false;
}
2024-05-29 16:36:30 +08:00
public void Release()
{
if (null != InputManager.Instance)
InputManager.Instance.OnAnyClick -= OnAnyClick;
2025-04-07 18:08:08 +08:00
isInitGuide = false;
2024-05-24 19:11:19 +08:00
}
2024-05-29 16:36:30 +08:00
/// <summary>
2025-04-07 18:08:08 +08:00
/// 初始化引导
2024-05-29 16:36:30 +08:00
/// </summary>
2025-04-07 18:08:08 +08:00
public void InitGuide()
2024-05-24 19:11:19 +08:00
{
2024-06-05 13:13:11 +08:00
#if GUIDE
2025-04-07 18:08:08 +08:00
if (isInitGuide)
2024-12-04 14:27:43 +08:00
return;
2024-10-11 19:22:18 +08:00
2025-04-07 18:08:08 +08:00
dicReaction = new();
2025-04-08 14:07:20 +08:00
setCompleteId = new();
2025-04-09 19:33:00 +08:00
completeGroupId = (int)Actor.Instance.Logic.GetCount((uint)LogicID.NewGuideProgress); // 服务器所在新手引导组id
2025-04-09 15:29:24 +08:00
Debug(PhxhSDK.Utils.Format("初始新手引导当前服务器保存id{0}", SeverGuideIdToString(completeGroupId)));
2025-04-07 18:08:08 +08:00
foreach (DataGuideCfg cfg in TableManager.Instance.Tables.GuideConfig.DataList)
{
if (IsCompleted(cfg.GroupId)) // 已完成跳过
2024-12-04 14:27:43 +08:00
continue;
2024-10-17 12:33:34 +08:00
2025-04-07 18:08:08 +08:00
dicReaction[ConditionReactor.Instance.AddReaction(cfg.BeginCondition, OnBeginGuideByCondition)] = cfg;
2024-10-11 17:17:54 +08:00
}
2025-04-07 18:08:08 +08:00
isInitGuide = true;
2024-06-05 13:13:11 +08:00
#endif
2024-05-24 19:11:19 +08:00
}
2024-05-24 15:07:50 +08:00
2024-05-29 16:36:30 +08:00
/// <summary>
/// 完成指定引导步骤
/// </summary>
/// <param name="step"></param>
2025-04-08 14:07:20 +08:00
public void CompleteStep()
2024-05-29 16:36:30 +08:00
{
2025-04-08 14:07:20 +08:00
if (null == curStep)
2024-05-29 16:36:30 +08:00
{
EndGuide(true);
2024-05-29 13:04:51 +08:00
2024-05-29 16:36:30 +08:00
return;
}
2024-05-29 13:04:51 +08:00
2025-04-08 14:07:20 +08:00
setCompleteId.Add(curStep.Cfg.Id);
if (curStep.Cfg.IsFinalStep)
2024-05-29 16:36:30 +08:00
{
2025-04-08 14:07:20 +08:00
setCompleteId.Clear();
2025-04-08 16:03:25 +08:00
completeGroupId |= GetServerSaveId(curStep.Cfg.GroupId); // 按位存
2025-04-08 14:07:20 +08:00
NetHelper.SaveGuideProgress(LogicID.NewGuideProgress, completeGroupId); // 完成引导步骤,保存服务器
2025-04-09 15:29:24 +08:00
Debug(PhxhSDK.Utils.Format("服务器保存引导组id:{0}服务器实际保存id:{1}", curStep.Cfg.GroupId.ToString(),
SeverGuideIdToString(completeGroupId)));
2024-05-29 16:36:30 +08:00
}
2025-04-08 14:07:20 +08:00
queueTime.Clear();
curStep = null;
EventManager.Instance.Send(EventManager.EventName.Guide_Progress_Change);
2024-05-29 16:36:30 +08:00
}
2024-05-22 16:31:29 +08:00
2024-05-29 16:36:30 +08:00
/// <summary>
/// 结束引导
/// </summary>
2024-06-06 14:41:02 +08:00
public void EndGuide(bool isReEnterMain)
2024-05-22 16:31:29 +08:00
{
2024-05-29 16:36:30 +08:00
if (IsGuiding)
2025-04-07 18:08:08 +08:00
curStep.EndGuide();
2024-05-22 16:31:29 +08:00
2025-04-07 18:08:08 +08:00
curStep = null;
2024-05-29 16:36:30 +08:00
UIManager.Instance.CloseWindow(UINameConst.UI_Guide);
UIManager.Instance.CloseWindow(UINameConst.UI_GuideTip);
2024-05-22 16:31:29 +08:00
}
2025-04-08 16:03:25 +08:00
/// <summary>
/// 获取任意点击
/// </summary>
/// <returns></returns>
public bool GetAnyClick()
{
if (isAnyClick)
{
isAnyClick = false;
return true;
}
return false;
}
2025-04-08 19:05:57 +08:00
/// <summary>
/// 点击指定引导按钮
/// </summary>
/// <returns></returns>
public bool GetClickButton()
{
if (isClickButton)
{
isClickButton = false;
return true;
}
return false;
}
/// <summary>
/// 设置点击引导按钮状态
/// </summary>
public void SetClickButtonState()
{
isClickButton = true;
}
2024-10-14 12:20:28 +08:00
/// <summary>
/// 判断引导步骤是否完成
/// </summary>
/// <returns></returns>
2025-04-07 19:15:35 +08:00
public bool IsStepComplete(int guideId)
2024-10-14 12:20:28 +08:00
{
2025-04-07 19:15:35 +08:00
DataGuideCfg cfg = TableManager.Instance.Tables.GuideConfig.Get(guideId);
if (null == cfg)
return false;
if (IsCompleted(cfg.GroupId))
return true;
2024-10-14 12:20:28 +08:00
2025-04-07 19:15:35 +08:00
return setCompleteId.Contains(guideId);
2024-10-14 12:20:28 +08:00
}
2025-04-08 14:15:34 +08:00
/// <summary>
/// 引导Debug
/// </summary>
/// <param name="content"></param>
public static void Debug(string content)
{
2025-04-08 16:03:25 +08:00
DebugUtil.Log($"<color=#00FA9A>(新手引导){content}</color>");
2025-04-08 14:15:34 +08:00
}
2025-04-09 15:29:24 +08:00
/// <summary>
/// 服务器保存的引导id转字符串
/// </summary>
/// <param name="guideId"></param>
/// <returns></returns>
public string SeverGuideIdToString(int guideId)
{
int id = 1;
int value = 1;
2025-04-16 14:01:44 +08:00
while (value > 0 && value <= guideId)
2025-04-09 15:29:24 +08:00
{
PhxhSDK.Utils.Append(id.ToString());
PhxhSDK.Utils.Append(",");
value <<= 1;
++id;
}
return PhxhSDK.Utils.GetStringBuilderToString();
}
2024-12-04 14:27:43 +08:00
#region 私有方法
2025-04-08 16:03:25 +08:00
/// <summary>
/// 创建引导步骤
/// </summary>
private GuideStepBase CreateGuideStep(DataGuideCfg cfg)
{
switch (cfg.GuideType)
{
case E_GuideType.ClickFloor: // 点击地板
return ClickFloorGuide.Create(cfg);
case E_GuideType.ClickCharacter: // 点击角色(根据角色点击地板)
return ClickCharacterGuide.Create(cfg);
case E_GuideType.ClickEnemy: // 点击敌人(根据敌人点击地板)
return ClickEnemyGuide.Create(cfg);
case E_GuideType.ArrowTip: // 指示UI提示
return ArrowUITipGuide.Create(cfg);
2025-04-08 19:05:57 +08:00
case E_GuideType.ClickButton: // 点击引导按钮
return ClickButtonGuide.Create(cfg);
case E_GuideType.LevelCancelSelectUnit: // 关卡取消单位选中
return LevelCancelSelectUnitGuide.Create(cfg);
2025-04-08 16:03:25 +08:00
default:
{
throw new Exception($"新手引导,未处理类型:{cfg.GuideType}");
}
}
}
2024-05-29 16:36:30 +08:00
/// <summary>
2025-04-07 18:08:08 +08:00
/// 引导组是否完成
2024-12-04 14:27:43 +08:00
/// </summary>
2025-04-07 18:08:08 +08:00
/// <param name="groupId"></param>
2024-12-04 14:27:43 +08:00
/// <returns></returns>
2025-04-07 18:08:08 +08:00
private bool IsCompleted(int groupId)
2024-12-04 14:27:43 +08:00
{
2025-04-08 19:05:57 +08:00
int id = GetServerSaveId(groupId);
return id == (completeGroupId & id);
2025-04-08 16:03:25 +08:00
}
/// <summary>
/// 获取服务器存储的id
/// </summary>
/// <returns></returns>
private int GetServerSaveId(int groupId)
{
int res = 1;
for (int i = 0; i < groupId - 1; ++i)
{
2025-04-09 15:29:24 +08:00
res <<= 1;
2025-04-08 16:03:25 +08:00
}
return res;
2024-05-22 16:31:29 +08:00
}
/// <summary>
/// 引导过程中的任意点击事件
/// </summary>
private void OnAnyClick()
2025-04-08 16:03:25 +08:00
{
if (!IsGuiding)
return;
2024-10-18 18:13:23 +08:00
if (!IsEnableAnyClick)
return;
if (LoadingManager.Instance.IsRuning)
return;
2025-04-08 16:03:25 +08:00
isAnyClick = true;
EventManager.Instance.Send(EventManager.EventName.Guide_Any_Click);
/*
DateTime curTime = CommonUtils.GetCurTime(CommonUtils.E_TimeType.Local);
queueTime.Enqueue(curTime);
2024-10-12 17:13:17 +08:00
while (queueTime.TryPeek(out DateTime firstTime))
{
TimeSpan timeSpan = curTime - firstTime;
if (timeSpan.TotalSeconds < SKIP_GUIDE_CHECK_TIME)
break;
queueTime.Dequeue();
2024-10-12 17:13:17 +08:00
}
2024-10-12 12:53:49 +08:00
if (TableManager.Instance.Tables.GlobalConfig.SkipGuideClickCount <= queueTime.Count)
{
2024-10-12 12:53:49 +08:00
DebugUtil.Log($"{SKIP_GUIDE_CHECK_TIME}秒内连续点击{TableManager.Instance.Tables.GlobalConfig.SkipGuideClickCount}次,弹出强制跳过新手引导提示");
queueTime.Clear();
2024-10-12 12:46:58 +08:00
ShowSkipAllGuide();
2025-04-08 14:15:34 +08:00
}*/
}
2025-04-07 19:15:35 +08:00
2025-04-07 18:08:08 +08:00
/// <summary>
/// 通过条件触发开始引导
/// </summary>
private void OnBeginGuideByCondition(bool conditionResult, object callBackParam, int reactionID)
{
if (!conditionResult)
return;
if (!dicReaction.TryGetValue(reactionID, out DataGuideCfg guideCfg))
return;
ConditionReactor.Instance.RemoveReaction(reactionID);
dicReaction.Remove(reactionID);
try
{
2025-04-07 19:15:35 +08:00
curStep = CreateGuideStep(guideCfg);
2025-04-08 14:07:20 +08:00
curStep.StartGuide();
2025-04-07 18:08:08 +08:00
}
catch (Exception e)
{
DebugUtil.LogError($"跳过引导,错误信息:{e}");
}
}
2025-04-08 16:03:25 +08:00
#endregion
2024-05-22 15:41:05 +08:00
}
2024-05-24 19:11:19 +08:00
}