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;
namespace Gameplay.Guide
{
///
/// 新手引导管理器
///
public sealed class GuideManager : Singlenton, IInitable, IUpdatable
{
#region 兜底强制跳过引导机制
///
/// 2秒内点击n次,弹出强制跳过引导
///
private readonly Queue queueTime = new();
///
/// 强制跳过引导检测时间(秒)
///
private const double SKIP_GUIDE_CHECK_TIME = 2d;
#endregion
///
/// 未完成的引导步骤,注册的开始条件记录在这,key:reactionId,value:引导步骤配置
///
private Dictionary dicReaction;
///
/// 完成的引导步骤id
///
private HashSet setCompleteId;
///
/// 当前的引导步骤
///
private GuideStepBase curStep;
///
/// 完成的引导组id
///
private int completeGroupId;
///
/// 是否初始化引导
///
private bool isInitGuide;
///
/// 是否引导中
///
public bool IsGuiding { get { return null != curStep && curStep.IsGuiding; } }
#region 引导特殊控制参数
///
/// 控制地板点击
///
public bool IsControlFloor = false;
///
/// 指定地板索引
///
public int FloorIndex = -1;
///
/// 使用技能成功
///
public bool IsUseSkillSuccess = true;
///
/// 是否响应任意点击
///
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;
}
///
/// 初始化引导
///
public void InitGuide()
{
#if GUIDE
if (isInitGuide)
return;
dicReaction = new();
setCompleteId = new();
completeGroupId = 0;// (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
}
///
/// 完成指定引导步骤
///
///
public void CompleteStep()
{
if (null == curStep)
{
EndGuide(true);
return;
}
setCompleteId.Add(curStep.Cfg.Id);
if (curStep.Cfg.IsFinalStep)
{
setCompleteId.Clear();
completeGroupId &= curStep.Cfg.GroupId; // 按位存
NetHelper.SaveGuideProgress(LogicID.NewGuideProgress, completeGroupId); // 完成引导步骤,保存服务器
DebugUtil.Log($"完成引导id:{curStep.Cfg.Id},服务器保存引导组id:{curStep.Cfg.GroupId},服务器实际保存id:{completeGroupId}");
}
queueTime.Clear();
curStep = null;
EventManager.Instance.Send(EventManager.EventName.Guide_Progress_Change);
}
///
/// 结束引导
///
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());
}
}
///
/// 跳过当前引导组
///
///
public void SkipCurGuideGroup()
{/*
if (null == curGroup)
return;
if (!dicGuideCfg.TryGetValue(curGroup.GroupId, out List listCfg))
{
DebugUtil.LogError("要完成的引导组不存在");
return;
}
NetHelper.SaveGuideProgress(LogicID.NewGuideProgress, listCfg[^1].Id); // 跳过引导步骤,保存服务器
DebugUtil.Log($"跳过引导组,服务器保存引导id:{listCfg[^1].Id}");
EndGuide(false);*/
}
///
/// 跳过所有引导
///
public void SkipAllGuide()
{
DebugUtil.Log("跳过所有引导");
GuideConfig guideConfig = TableManager.Instance.Tables.GuideConfig;
DataGuideCfg cfg = guideConfig.DataList[^1];
NetHelper.SaveGuideProgress(LogicID.NewGuideProgress, cfg.Id);
EndGuide(true);
}
///
/// 显示跳过所有引导提示
///
public void ShowSkipAllGuide()
{
UITipsManager.ShowConfirmTwo(CommonUtils.GetLocalizeText("Guide_SkipAllTitle"), // 脱离卡死
CommonUtils.GetLocalizeText("Guide_SkipAllContent"), // 是否强制跳过新手引导?(选择【跳过】便不再触发新手引导)
CommonUtils.GetLocalizeText("Skip"), // 跳过
CommonUtils.GetLocalizeText("Not"), // 否
() => { SkipAllGuide(); });
}
///
/// 判断引导步骤是否完成
///
///
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 私有方法
///
/// 引导组是否完成
///
///
///
private bool IsCompleted(int groupId)
{
return 1 == (completeGroupId & groupId);
}
///
/// 设置引导状态
///
private void SetGuideState()
{
UIManager.Instance.IsEnableBack = false;
}
///
/// 还原状态
///
private void RecoverState()
{
UIManager.Instance.IsEnableBack = true;
}
///
/// 引导过程中的任意点击事件
///
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
///
/// 创建引导步骤
///
private GuideStepBase CreateGuideStep(DataGuideCfg cfg)
{
switch (cfg.GuideType)
{
case E_GuideType.ClickFloor:
return ClickFloorGuide.Create(cfg);
case E_GuideType.ClickRole:
return ClickCharacterGuide.Create(cfg);
default:
{
throw new Exception($"新手引导,未处理类型:{cfg.GuideType}");
}
}
}
///
/// 通过条件触发开始引导
///
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.StartGuide();
}
catch (Exception e)
{
DebugUtil.LogError($"跳过引导,错误信息:{e}");
RecoverState();
}
}
}
}