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

376 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using cfg.GuideCfg;
using Framework;
using Framework.Condition;
using Gameplay.Level;
using Gameplay.Net;
using Gameplay.SubSystems;
using NLDPB;
using PhxhSDK;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Gameplay.Guide
{
/// <summary>
/// 新手引导管理器
/// </summary>
public sealed class GuideManager : Singlenton<GuideManager>, IInitable, IUpdatable
{
#region 兜底强制跳过引导机制
/// <summary>
/// 2秒内点击n次弹出强制跳过引导
/// </summary>
private readonly Queue<DateTime> queueTime = new();
/// <summary>
/// 强制跳过引导检测时间(秒)
/// </summary>
private const double SKIP_GUIDE_CHECK_TIME = 2d;
#endregion
/// <summary>
/// 未完成的引导步骤,注册的开始条件记录在这,key:reactionId,value:引导步骤配置
/// </summary>
private Dictionary<int, DataGuideCfg> dicReaction;
/// <summary>
/// 完成的引导步骤id
/// </summary>
private HashSet<int> setCompleteId;
/// <summary>
/// 当前的引导步骤
/// </summary>
private GuideStepBase curStep;
/// <summary>
/// 完成的引导组id
/// </summary>
private int completeGroupId;
/// <summary>
/// 是否初始化引导
/// </summary>
private bool isInitGuide;
/// <summary>
/// 是否任意点击
/// </summary>
private bool isAnyClick;
/// <summary>
/// 点击引导按钮
/// </summary>
private bool isClickButton;
/// <summary>
/// 战斗按钮是否显示
/// </summary>
public bool IsFightButtonShow;
/// <summary>
/// 是否引导中
/// </summary>
public bool IsGuiding { get { return null != curStep && curStep.IsGuiding; } }
#region 引导特殊控制参数
/// <summary>
/// 控制地板点击
/// </summary>
public bool IsControlFloor = false;
/// <summary>
/// 指定地板索引
/// </summary>
public int FloorIndex = -1;
/// <summary>
/// 是否响应任意点击
/// </summary>
public bool IsEnableAnyClick = true;
#endregion
public void Init()
{
isInitGuide = false;
InputManager.Instance.OnAnyClick += OnAnyClick;
}
public void Update(float deltaTime)
{
if (!IsGuiding)
return;
isAnyClick = false;
}
public void Release()
{
if (null != InputManager.Instance)
InputManager.Instance.OnAnyClick -= OnAnyClick;
isInitGuide = false;
}
/// <summary>
/// 初始化引导
/// </summary>
public void InitGuide()
{
#if GUIDE
if (isInitGuide)
return;
dicReaction = new();
setCompleteId = new();
completeGroupId = (int)Actor.Instance.Logic.GetCount((uint)LogicID.NewGuideProgress); // 服务器所在新手引导组id
Debug(PhxhSDK.Utils.Format("初始新手引导当前服务器保存id{0}", SeverGuideIdToString(completeGroupId)));
foreach (DataGuideCfg cfg in TableManager.Instance.Tables.GuideConfig.DataList)
{
if (IsCompleted(cfg.GroupId)) // 已完成跳过
continue;
dicReaction[ConditionReactor.Instance.AddReaction(cfg.BeginCondition, OnBeginGuideByCondition)] = cfg;
}
isInitGuide = true;
#endif
}
/// <summary>
/// 完成指定引导步骤
/// </summary>
/// <param name="step"></param>
public void CompleteStep()
{
if (null == curStep)
{
EndGuide(true);
return;
}
setCompleteId.Add(curStep.Cfg.Id);
if (curStep.Cfg.IsFinalStep)
{
setCompleteId.Clear();
completeGroupId |= GetServerSaveId(curStep.Cfg.GroupId); // 按位存
NetHelper.SaveGuideProgress(LogicID.NewGuideProgress, completeGroupId); // 完成引导步骤,保存服务器
Debug(PhxhSDK.Utils.Format("服务器保存引导组id:{0}服务器实际保存id:{1}", curStep.Cfg.GroupId.ToString(),
SeverGuideIdToString(completeGroupId)));
}
queueTime.Clear();
curStep = null;
EventManager.Instance.Send(EventManager.EventName.Guide_Progress_Change);
}
/// <summary>
/// 结束引导
/// </summary>
public void EndGuide(bool isReEnterMain)
{
if (IsGuiding)
curStep.EndGuide();
curStep = null;
UIManager.Instance.CloseWindow(UINameConst.UI_Guide);
UIManager.Instance.CloseWindow(UINameConst.UI_GuideTip);
}
/// <summary>
/// 获取任意点击
/// </summary>
/// <returns></returns>
public bool GetAnyClick()
{
if (isAnyClick)
{
isAnyClick = false;
return true;
}
return false;
}
/// <summary>
/// 点击指定引导按钮
/// </summary>
/// <returns></returns>
public bool GetClickButton()
{
if (isClickButton)
{
isClickButton = false;
return true;
}
return false;
}
/// <summary>
/// 设置点击引导按钮状态
/// </summary>
public void SetClickButtonState()
{
isClickButton = true;
}
/// <summary>
/// 判断引导步骤是否完成
/// </summary>
/// <returns></returns>
public bool IsStepComplete(int guideId)
{
DataGuideCfg cfg = TableManager.Instance.Tables.GuideConfig.Get(guideId);
if (null == cfg)
return false;
if (IsCompleted(cfg.GroupId))
return true;
return setCompleteId.Contains(guideId);
}
/// <summary>
/// 引导Debug
/// </summary>
/// <param name="content"></param>
public static void Debug(string content)
{
DebugUtil.Log($"<color=#00FA9A>(新手引导){content}</color>");
}
/// <summary>
/// 服务器保存的引导id转字符串
/// </summary>
/// <param name="guideId"></param>
/// <returns></returns>
public string SeverGuideIdToString(int guideId)
{
int id = 1;
int value = 1;
while (value > 0 && value <= guideId)
{
PhxhSDK.Utils.Append(id.ToString());
PhxhSDK.Utils.Append(",");
value <<= 1;
++id;
}
return PhxhSDK.Utils.GetStringBuilderToString();
}
#region 私有方法
/// <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);
case E_GuideType.ClickButton: // 点击引导按钮
return ClickButtonGuide.Create(cfg);
case E_GuideType.LevelCancelSelectUnit: // 关卡取消单位选中
return LevelCancelSelectUnitGuide.Create(cfg);
default:
{
throw new Exception($"新手引导,未处理类型:{cfg.GuideType}");
}
}
}
/// <summary>
/// 引导组是否完成
/// </summary>
/// <param name="groupId"></param>
/// <returns></returns>
private bool IsCompleted(int groupId)
{
int id = GetServerSaveId(groupId);
return id == (completeGroupId & id);
}
/// <summary>
/// 获取服务器存储的id
/// </summary>
/// <returns></returns>
private int GetServerSaveId(int groupId)
{
int res = 1;
for (int i = 0; i < groupId - 1; ++i)
{
res <<= 1;
}
return res;
}
/// <summary>
/// 引导过程中的任意点击事件
/// </summary>
private void OnAnyClick()
{
if (!IsGuiding)
return;
if (!IsEnableAnyClick)
return;
if (LoadingManager.Instance.IsRuning)
return;
isAnyClick = true;
EventManager.Instance.Send(EventManager.EventName.Guide_Any_Click);
/*
DateTime curTime = CommonUtils.GetCurTime(CommonUtils.E_TimeType.Local);
queueTime.Enqueue(curTime);
while (queueTime.TryPeek(out DateTime firstTime))
{
TimeSpan timeSpan = curTime - firstTime;
if (timeSpan.TotalSeconds < SKIP_GUIDE_CHECK_TIME)
break;
queueTime.Dequeue();
}
if (TableManager.Instance.Tables.GlobalConfig.SkipGuideClickCount <= queueTime.Count)
{
DebugUtil.Log($"{SKIP_GUIDE_CHECK_TIME}秒内连续点击{TableManager.Instance.Tables.GlobalConfig.SkipGuideClickCount}次,弹出强制跳过新手引导提示");
queueTime.Clear();
ShowSkipAllGuide();
}*/
}
/// <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
{
curStep = CreateGuideStep(guideCfg);
curStep.StartGuide();
}
catch (Exception e)
{
DebugUtil.LogError($"跳过引导,错误信息:{e}");
}
}
#endregion
}
}