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
{
///
/// 新手引导管理器
///
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;
///
/// 是否任意点击
///
private bool isAnyClick;
///
/// 点击引导按钮
///
private bool isClickButton;
///
/// 战斗按钮是否显示
///
public bool IsFightButtonShow;
///
/// 是否引导中
///
public bool IsGuiding { get { return null != curStep && curStep.IsGuiding; } }
#region 引导特殊控制参数
///
/// 控制地板点击
///
public bool IsControlFloor = false;
///
/// 指定地板索引
///
public int FloorIndex = -1;
///
/// 是否响应任意点击
///
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;
}
///
/// 初始化引导
///
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
}
///
/// 完成指定引导步骤
///
///
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);
}
///
/// 结束引导
///
public void EndGuide(bool isReEnterMain)
{
if (IsGuiding)
curStep.EndGuide();
curStep = null;
UIManager.Instance.CloseWindow(UINameConst.UI_Guide);
UIManager.Instance.CloseWindow(UINameConst.UI_GuideTip);
}
///
/// 获取任意点击
///
///
public bool GetAnyClick()
{
if (isAnyClick)
{
isAnyClick = false;
return true;
}
return false;
}
///
/// 点击指定引导按钮
///
///
public bool GetClickButton()
{
if (isClickButton)
{
isClickButton = false;
return true;
}
return false;
}
///
/// 设置点击引导按钮状态
///
public void SetClickButtonState()
{
isClickButton = true;
}
///
/// 判断引导步骤是否完成
///
///
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);
}
///
/// 引导Debug
///
///
public static void Debug(string content)
{
DebugUtil.Log($"(新手引导){content}");
}
///
/// 服务器保存的引导id转字符串
///
///
///
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 私有方法
///
/// 创建引导步骤
///
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}");
}
}
}
///
/// 引导组是否完成
///
///
///
private bool IsCompleted(int groupId)
{
int id = GetServerSaveId(groupId);
return id == (completeGroupId & id);
}
///
/// 获取服务器存储的id
///
///
private int GetServerSaveId(int groupId)
{
int res = 1;
for (int i = 0; i < groupId - 1; ++i)
{
res <<= 1;
}
return res;
}
///
/// 引导过程中的任意点击事件
///
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();
}*/
}
///
/// 通过条件触发开始引导
///
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
}
}