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

465 lines
15 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.Area;
using Gameplay.Level;
using Gameplay.Net;
using Gameplay.Skill;
using Gameplay.SubSystems;
using NLDPB;
using PhxhSDK;
using System;
using System.Collections.Generic;
namespace Gameplay.Guide
{
/// <summary>
/// 新手引导管理器
/// </summary>
public class GuideManager : Singlenton<GuideManager>, IInitable, IUpdatable
{
/// <summary>
/// 引导组第一步的id
/// </summary>
private const int GUIDE_GROUP_FIRST_STEP_ID = 1;
#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>
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 IsUseSkillSuccess = true;
/// <summary>
/// 是否响应任意点击
/// </summary>
public bool IsEnableAnyClick = true;
#endregion
public void Init()
{
isInitGuide = false;
InputManager.Instance.OnAnyClick += OnAnyClick;
}
public void Update(float deltaTime)
{/*
if (!Instance.IsGuiding)
return;
if (!LevelManager.Instance.IsInLevel)
return;
if (null == LevelManager.Instance.CurrentLevel)
return;
if (!LevelManager.Instance.CurrentLevel.isInBattle)
return;
if (!LevelManager.Instance.CurrentLevel.IsPause())
return;
AreaManager.instance.LogicUpdate(deltaTime);
SkillManager.instance.playerSkillManager.LogicUpdate(deltaTime);*/
}
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();
completeGroupId = (int)Actor.Instance.Logic.GetCount((uint)LogicID.NewGuideProgress); // 服务器所在新手引导组id
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(GuideStepBase step)
{
/*if (null == curGroup)
return;
if (step != curGroup.CurStep)
{
DebugUtil.LogError("要完成的引导步骤不是当前步骤");
EndGuide(true);
return;
}
NetHelper.SaveGuideProgress(LogicID.NewGuideProgress, curGroup.CurStep.Cfg.Id); // 完成引导步骤,保存服务器
DebugUtil.Log($"<color=#00FA9A>完成引导步骤服务器保存引导id:{curGroup.CurStep.Cfg.Id}</color>");
queueTime.Clear();
if (curGroup.IsComplete)
{
DebugUtil.Log($"<color=#00FA9A>完成引导组组id:{curGroup.GroupId}</color>");
int nextGroupId = curGroup.NextGroupId;
if (dicGuideCfg.TryGetValue(nextGroupId, out List<DataGuideCfg> listCfg))
{
curGroup = new(nextGroupId, listCfg, true);
curGroup.BeginGuide();
}
else
EndGuide(false);
}
else
{
if (curGroup.CurStep.Cfg.IsComplete)
DebugUtil.Log($"<color=#00FA9A>提前完成引导组组id:{curGroup.GroupId}</color>");
curGroup.BeginNextStep();
}*/
}
/// <summary>
/// 结束引导
/// </summary>
public void EndGuide(bool isReEnterMain)
{
if (IsGuiding)
curStep.EndGuide();
RecoverState();
curStep = null;
UIManager.Instance.CloseWindow(UINameConst.UI_Guide);
UIManager.Instance.CloseWindow(UINameConst.UI_GuideTip);
if (isReEnterMain)
{
if (LevelManager.Instance.IsInLevel)
{
LevelManager.Instance.ExitLevelChangeMainFunc = () =>
{
GameStateManager.Instance.ChangeState(new GameStateMainScene());
return false;
};
LevelManager.Instance.TryExitLevel(false, null, true);
}
else
GameStateManager.Instance.ChangeState(new GameStateMainScene());
}
}
/// <summary>
/// 跳过当前引导组
/// </summary>
/// <param name="isReEnterMain"></param>
public void SkipCurGuideGroup()
{/*
if (null == curGroup)
return;
if (!dicGuideCfg.TryGetValue(curGroup.GroupId, out List<DataGuideCfg> listCfg))
{
DebugUtil.LogError("要完成的引导组不存在");
return;
}
NetHelper.SaveGuideProgress(LogicID.NewGuideProgress, listCfg[^1].Id); // 跳过引导步骤,保存服务器
DebugUtil.Log($"<color=#00FA9A>跳过引导组服务器保存引导id:{listCfg[^1].Id}</color>");
EndGuide(false);*/
}
/// <summary>
/// 跳过所有引导
/// </summary>
public void SkipAllGuide()
{
DebugUtil.Log("跳过所有引导");
GuideConfig guideConfig = TableManager.Instance.Tables.GuideConfig;
DataGuideCfg cfg = guideConfig.DataList[^1];
NetHelper.SaveGuideProgress(LogicID.NewGuideProgress, cfg.Id);
EndGuide(true);
}
/// <summary>
/// 显示跳过所有引导提示
/// </summary>
public void ShowSkipAllGuide()
{
UITipsManager.ShowConfirmTwo(CommonUtils.GetLocalizeText("Guide_SkipAllTitle"), // 脱离卡死
CommonUtils.GetLocalizeText("Guide_SkipAllContent"), // 是否强制跳过新手引导?(选择【跳过】便不再触发新手引导)
CommonUtils.GetLocalizeText("Skip"), // 跳过
CommonUtils.GetLocalizeText("Not"), // 否
() => { SkipAllGuide(); });
}
/// <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);
}
#region 私有方法
/// <summary>
/// 引导组是否完成
/// </summary>
/// <param name="groupId"></param>
/// <returns></returns>
private bool IsCompleted(int groupId)
{
return 1 == (completeGroupId & groupId);
}
/// <summary>
/// 是否是引导组的第一步
/// </summary>
/// <returns></returns>
private bool IsFirstStep(DataGuideCfg dataGuideCfg)
{
return GUIDE_GROUP_FIRST_STEP_ID == dataGuideCfg.Id;
}
/// <summary>
/// 获取应该引导的引导组id
/// </summary>
/// <returns></returns>
private int GetGuideGroupId(int completeStepId)
{
return 0;
/*
GuideConfig guideConfig = TableManager.Instance.Tables.GuideConfig;
if (guideConfig.DataList.Count <= 0)
return 0;
if (completeStepId >= guideConfig.DataList[^1].Id) // 大于等于最后一步的id
return 0; // 跳过引导
DataGuideCfg completeCfg = null;
if (0 != completeStepId && 1 != completeStepId)
completeCfg = guideConfig.Get(completeStepId); // 已经完成的引导步骤配置
if (null == completeCfg) // 没有获取到不是存在的配置id可能修改过id
{
foreach (DataGuideCfg guideCfg in TableManager.Instance.Tables.GuideConfig.DataList)
{
if (guideCfg.Id >= completeStepId)
{
completeCfg = guideCfg;
break;
}
}
}
bool isGroupComplete = false; // 当前步骤所在引导组是否完成
DataGuideCfg nextCfg = guideConfig.Get(completeCfg.NextId);
if (null == nextCfg)
return 0; // 没有下一步了
else if (nextCfg.GroupId != completeCfg.GroupId) // 该步骤是该组最后一步,表示整组完成
isGroupComplete = true;
else
{
foreach (DataGuideCfg cfg in TableManager.Instance.Tables.GuideConfig.DataList)
{
if (cfg.GroupId != completeCfg.GroupId)
continue;
if (cfg.IsComplete && cfg.Id <= completeCfg.Id)
{
DebugUtil.Log($"<color=#00FA9A>引导步骤{completeStepId}所在组{cfg.GroupId}的{cfg.Id}步骤完成,该组完成</color>");
isGroupComplete = true;
break;
}
}
}
if (isGroupComplete) // 该组完成,取下一组
{
DataGuideCfg dataGuideCfg = guideConfig.Get(completeCfg.NextId);
while (null != dataGuideCfg)
{
if (dataGuideCfg.GroupId == completeCfg.GroupId)
{
if (0 == dataGuideCfg.NextId) // 下一组id为0表示最后一组
return 0;
dataGuideCfg = guideConfig.Get(dataGuideCfg.NextId);
continue;
}
return dataGuideCfg.GroupId;
}
return 0;
}
else
return completeCfg.GroupId; // 该组没有完成,重来
*/
}
/// <summary>
/// 设置引导状态
/// </summary>
private void SetGuideState()
{
UIManager.Instance.IsEnableBack = false;
}
/// <summary>
/// 还原状态
/// </summary>
private void RecoverState()
{
UIManager.Instance.IsEnableBack = true;
}
/// <summary>
/// 引导过程中的任意点击事件
/// </summary>
private void OnAnyClick()
{
if (!IsGuiding)
return;
if (!IsEnableAnyClick)
return;
if (LoadingManager.Instance.IsRuning)
return;
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();
}
}
#endregion
/// <summary>
/// 创建引导步骤
/// </summary>
private GuideStepBase CreateGuideStep(DataGuideCfg cfg)
{
switch (cfg.GuideType)
{
case E_GuideType.ClickFloor:
return null;
case E_GuideType.ClickRole:
return null;
default:
{
throw new Exception($"新手引导,未处理类型:{cfg.GuideType}");
}
}
}
/// <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
{
SetGuideState();
curStep = CreateGuideStep(guideCfg);
//curStep.BeginGuide();
}
catch (Exception e)
{
DebugUtil.LogError($"跳过引导,错误信息:{e}");
RecoverState();
}
}
}
}