2024-04-23 18:02:13 +08:00
|
|
|
|
using cfg.DialogueCfg;
|
2024-04-24 12:59:23 +08:00
|
|
|
|
using Cysharp.Threading.Tasks;
|
2024-04-23 18:02:13 +08:00
|
|
|
|
using Framework;
|
|
|
|
|
|
using Gameplay;
|
|
|
|
|
|
using PhxhSDK;
|
|
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
2024-04-29 14:22:22 +08:00
|
|
|
|
using System.Linq;
|
2024-04-23 18:02:13 +08:00
|
|
|
|
using Random = UnityEngine.Random;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 台词管理器
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class DialogueManager : Singlenton<DialogueManager>, IInitable
|
|
|
|
|
|
{
|
2024-04-29 17:20:40 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 台词播放记录数据
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private class DialoguePlayData
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 台词对应次数字典
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public Dictionary<int, int> DicCount;
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 上一次日期
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public DateTime LastTime;
|
|
|
|
|
|
|
|
|
|
|
|
public DialoguePlayData()
|
|
|
|
|
|
{
|
|
|
|
|
|
DicCount = new();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void SetNewTime(DateTime dateTime)
|
|
|
|
|
|
{
|
|
|
|
|
|
LastTime = dateTime;
|
|
|
|
|
|
DicCount.Clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 台词播放记录数据key
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private const string DIALOGUE_PLAY_DATA = "Dialogue_play_data";
|
2024-04-23 18:02:13 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 台词配置数据,key:角色id, value:台词配置数据
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private Dictionary<int, List<DataDialogueCfg>> dicDialogueData;
|
2024-04-23 18:10:19 +08:00
|
|
|
|
/// <summary>
|
2024-04-29 14:22:22 +08:00
|
|
|
|
/// 角色台词对应的权重字典,key:角色id,value: subKey:台词id,subValue:台词权重
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private Dictionary<int, Dictionary<int, float>> dicDialogueWeight;
|
|
|
|
|
|
/// <summary>
|
2024-04-29 17:20:40 +08:00
|
|
|
|
/// 台词播放记录数据
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private DialoguePlayData dialoguePlayData;
|
|
|
|
|
|
/// <summary>
|
2024-04-23 18:10:19 +08:00
|
|
|
|
/// 是否初始化
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private bool isInit;
|
2024-04-23 18:02:13 +08:00
|
|
|
|
|
|
|
|
|
|
#region 临时数据
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 符合条件的台词数据
|
|
|
|
|
|
/// </summary>
|
2024-04-29 14:22:22 +08:00
|
|
|
|
private readonly List<DataDialogueCfg> listDialogueData = new();
|
|
|
|
|
|
private readonly List<float> listDialogueWeight = new();
|
2024-04-23 18:02:13 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
public void Init()
|
|
|
|
|
|
{
|
2024-04-23 18:10:19 +08:00
|
|
|
|
isInit = false;
|
2024-04-23 18:02:13 +08:00
|
|
|
|
dicDialogueData = new();
|
2024-04-29 14:22:22 +08:00
|
|
|
|
dicDialogueWeight = new();
|
2024-04-29 17:20:40 +08:00
|
|
|
|
dialoguePlayData = StorageMgr.Instance.GetStorage<DialoguePlayData>(DIALOGUE_PLAY_DATA);
|
2024-04-23 18:10:19 +08:00
|
|
|
|
|
|
|
|
|
|
EventManager.Instance.Register(EventManager.EventName.AllConfigLoad, InitData);
|
2024-04-23 18:02:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Release()
|
|
|
|
|
|
{
|
2024-04-23 18:10:19 +08:00
|
|
|
|
EventManager.Instance.Unregister(EventManager.EventName.AllConfigLoad, InitData);
|
|
|
|
|
|
|
|
|
|
|
|
isInit = false;
|
2024-04-24 12:59:23 +08:00
|
|
|
|
|
2024-04-23 18:02:13 +08:00
|
|
|
|
dicDialogueData.Clear();
|
|
|
|
|
|
dicDialogueData = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 播放台词
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="roleId"></param>
|
|
|
|
|
|
/// <param name="dialogueType"></param>
|
2024-04-29 17:20:40 +08:00
|
|
|
|
/// <param name="callback"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2024-04-28 13:48:16 +08:00
|
|
|
|
public async UniTask<Audio> PlayDiaogue(int roleId, E_DialogueType dialogueType, Action<string> callback = null)
|
2024-04-23 18:02:13 +08:00
|
|
|
|
{
|
2024-04-29 14:22:22 +08:00
|
|
|
|
#region 校验
|
2024-04-23 18:10:19 +08:00
|
|
|
|
if (!isInit)
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("数据未初始化");
|
2024-04-24 12:59:23 +08:00
|
|
|
|
return null;
|
2024-04-23 18:10:19 +08:00
|
|
|
|
}
|
2024-04-29 14:22:22 +08:00
|
|
|
|
#endregion
|
2024-04-23 18:02:13 +08:00
|
|
|
|
|
2024-04-29 17:20:40 +08:00
|
|
|
|
#region 每日重置次数,后续应该通过跨天事件触发
|
|
|
|
|
|
DateTime curTime = CommonUtils.GetCurTime(CommonUtils.E_TimeType.Server);
|
|
|
|
|
|
if (curTime.Hour > TableManager.Instance.Tables.GlobalConfig.DailyChangeHour && // 超过5点
|
|
|
|
|
|
curTime.Day != dialoguePlayData.LastTime.Day) // 不是同一天
|
|
|
|
|
|
{
|
|
|
|
|
|
dialoguePlayData.SetNewTime(curTime);
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 获取需要播放的台词,根据优先级,台词类型,播放次数,条件
|
2024-04-23 18:02:13 +08:00
|
|
|
|
if (!dicDialogueData.TryGetValue(roleId, out List<DataDialogueCfg> listCfg))
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("没有该角色的台词数据");
|
2024-04-24 12:59:23 +08:00
|
|
|
|
return null;
|
2024-04-23 18:02:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-04-29 14:22:22 +08:00
|
|
|
|
listDialogueData.Clear();
|
2024-04-24 12:59:23 +08:00
|
|
|
|
int minPriority = int.MaxValue; // 值越小优先级越高
|
2024-04-23 18:02:13 +08:00
|
|
|
|
foreach (DataDialogueCfg cfg in listCfg)
|
|
|
|
|
|
{
|
2024-04-24 12:59:23 +08:00
|
|
|
|
if (cfg.Priority > minPriority) // 优先级不足,排除
|
2024-04-23 18:02:13 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
if (!cfg.DialogueType.Contains(dialogueType)) // 不是所需类型,排除
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
2024-04-29 17:20:40 +08:00
|
|
|
|
if (cfg.DayPlayCount > 0 && // 0表示无限次
|
|
|
|
|
|
dialoguePlayData.DicCount.TryGetValue(cfg.DialogueId, out int count) &&
|
|
|
|
|
|
count >= cfg.DayPlayCount) // 超过播放次数
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
2024-04-23 18:02:13 +08:00
|
|
|
|
if (!IsCheckValid(roleId, cfg)) // 条件不满足,排除
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
2024-04-24 12:59:23 +08:00
|
|
|
|
if (cfg.Priority < minPriority)
|
2024-04-23 18:02:13 +08:00
|
|
|
|
{
|
2024-04-24 12:59:23 +08:00
|
|
|
|
minPriority = cfg.Priority;
|
2024-04-29 14:22:22 +08:00
|
|
|
|
listDialogueData.Clear();
|
2024-04-23 18:02:13 +08:00
|
|
|
|
}
|
2024-04-29 14:22:22 +08:00
|
|
|
|
listDialogueData.Add(cfg);
|
2024-04-23 18:02:13 +08:00
|
|
|
|
}
|
2024-04-24 12:59:23 +08:00
|
|
|
|
#endregion
|
2024-04-23 18:02:13 +08:00
|
|
|
|
|
2024-04-29 14:22:22 +08:00
|
|
|
|
if (listDialogueData.Count <= 0)
|
2024-04-23 18:02:13 +08:00
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("没有满足条件要播放的台词");
|
2024-04-24 12:59:23 +08:00
|
|
|
|
return null;
|
2024-04-23 18:02:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-04-29 14:22:22 +08:00
|
|
|
|
#region 根据权重随机台词
|
|
|
|
|
|
DataDialogueCfg playCfg;
|
|
|
|
|
|
listDialogueWeight.Clear();
|
|
|
|
|
|
if (dicDialogueWeight.TryGetValue(roleId, out Dictionary<int, float> dicWeight))
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (DataDialogueCfg cfg in listDialogueData)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (dicWeight.TryGetValue(cfg.DialogueId, out float weight))
|
|
|
|
|
|
listDialogueWeight.Add(weight);
|
|
|
|
|
|
else
|
|
|
|
|
|
listDialogueWeight.Add(1f);
|
|
|
|
|
|
}
|
|
|
|
|
|
playCfg = listDialogueData[RandomIndexByWeight()];
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
playCfg = listDialogueData[Random.Range(0, listDialogueData.Count)];
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 设置其他的权重
|
|
|
|
|
|
if (dicWeight != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (DataDialogueCfg cfg in listDialogueData)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (dicWeight.TryGetValue(cfg.DialogueId, out float weight) && weight <= 0f)
|
|
|
|
|
|
dicWeight[cfg.DialogueId] = 0.3f; // TODO 需要全局配置
|
|
|
|
|
|
else
|
|
|
|
|
|
dicWeight[cfg.DialogueId] = 1f;
|
|
|
|
|
|
}
|
|
|
|
|
|
dicWeight[playCfg.DialogueId] = 0f; // 当前使用的权重置为0
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
2024-04-23 18:02:13 +08:00
|
|
|
|
|
2024-04-29 17:20:40 +08:00
|
|
|
|
#region 记录播放次数
|
|
|
|
|
|
if (playCfg.DayPlayCount > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
dialoguePlayData.DicCount.TryGetValue(playCfg.DialogueId, out int count);
|
|
|
|
|
|
dialoguePlayData.DicCount[playCfg.DialogueId] = count + 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2024-04-28 13:48:16 +08:00
|
|
|
|
DebugUtil.Log($"播放台词{playCfg.DialogueId}, 优先级{playCfg.Priority}"); // 测试Log
|
2024-04-24 12:59:23 +08:00
|
|
|
|
int audioId = await AudioManager.Instance.PlayAudio(playCfg.Voice);
|
|
|
|
|
|
|
2024-04-28 13:48:16 +08:00
|
|
|
|
callback?.Invoke(CommonUtils.GetLocalizeText(playCfg.TextLocal));
|
|
|
|
|
|
|
2024-04-24 12:59:23 +08:00
|
|
|
|
return AudioManager.Instance.GetAudioByID(AudioType.SOUND, audioId);
|
2024-04-23 18:02:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 检查台词是否有效
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
private bool IsCheckValid(int roleId, DataDialogueCfg dataDialogueCfg)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (E_DialogueType dialogueType in dataDialogueCfg.DialogueType)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!IsCheckValidByOne(roleId, dialogueType))
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 检查个单个条件是否有效
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="roleId"></param>
|
|
|
|
|
|
/// <param name="dataDialogueCfg"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
private bool IsCheckValidByOne(int roleId, E_DialogueType dialogueType)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (dialogueType)
|
|
|
|
|
|
{
|
|
|
|
|
|
case E_DialogueType.Morning: // 上午
|
|
|
|
|
|
{
|
|
|
|
|
|
DateTime dateTime = CommonUtils.GetCurTime(CommonUtils.E_TimeType.Server);
|
|
|
|
|
|
return dateTime.Hour >= 6 && dateTime.Hour < 16;
|
|
|
|
|
|
}
|
|
|
|
|
|
case E_DialogueType.Afternoon:
|
|
|
|
|
|
{
|
|
|
|
|
|
DateTime dateTime = CommonUtils.GetCurTime(CommonUtils.E_TimeType.Server);
|
|
|
|
|
|
return dateTime.Hour >= 16 && dateTime.Hour < 21;
|
|
|
|
|
|
}
|
|
|
|
|
|
case E_DialogueType.Evening:
|
|
|
|
|
|
{
|
|
|
|
|
|
DateTime dateTime = CommonUtils.GetCurTime(CommonUtils.E_TimeType.Server);
|
|
|
|
|
|
return dateTime.Hour >= 21 && dateTime.Hour < 23;
|
|
|
|
|
|
}
|
|
|
|
|
|
case E_DialogueType.Midnight:
|
|
|
|
|
|
{
|
|
|
|
|
|
DateTime dateTime = CommonUtils.GetCurTime(CommonUtils.E_TimeType.Server);
|
|
|
|
|
|
return dateTime.Hour < 6 || dateTime.Hour >= 23;
|
|
|
|
|
|
}
|
|
|
|
|
|
case E_DialogueType.PlayerBirthday:
|
2024-04-29 17:20:40 +08:00
|
|
|
|
{
|
|
|
|
|
|
DateTime kanbanbanBirth = new(2024, 4, 29); // 测试玩家生日
|
|
|
|
|
|
return CommonUtils.IsBirth(kanbanbanBirth);
|
|
|
|
|
|
}
|
2024-04-23 18:02:13 +08:00
|
|
|
|
case E_DialogueType.KanbanbanBirthday:
|
2024-04-29 17:20:40 +08:00
|
|
|
|
{
|
|
|
|
|
|
DateTime kanbanbanBirth = new(2024, 4, 29); // 测试看板娘生日
|
|
|
|
|
|
return CommonUtils.IsBirth(kanbanbanBirth);
|
|
|
|
|
|
}
|
2024-04-23 18:02:13 +08:00
|
|
|
|
case E_DialogueType.Fetters:
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogWarning("记录一下,等待处理");
|
|
|
|
|
|
return false; // Todo
|
|
|
|
|
|
}
|
|
|
|
|
|
case E_DialogueType.Awaken:
|
|
|
|
|
|
{
|
2024-04-24 14:52:18 +08:00
|
|
|
|
CharacterDataInfo characterDataInfo = CharacterDataInfoManager.Instance.GetCharacterInfo((uint)roleId);
|
|
|
|
|
|
if (characterDataInfo == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("未获取到角色");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return characterDataInfo.IsMaxAwake(); // 是否满觉醒
|
2024-04-23 18:02:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
default: // 其余条件默认满足
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-04-23 18:10:19 +08:00
|
|
|
|
|
2024-04-29 14:22:22 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 根据权重随机一个索引
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
private int RandomIndexByWeight()
|
|
|
|
|
|
{
|
|
|
|
|
|
float totalWeight = listDialogueWeight.Sum();
|
|
|
|
|
|
float randomWeight = Random.Range(0, 1f) * totalWeight;
|
|
|
|
|
|
|
|
|
|
|
|
totalWeight = 0f;
|
|
|
|
|
|
for (int i = 0; i < listDialogueWeight.Count; ++i)
|
|
|
|
|
|
{
|
|
|
|
|
|
totalWeight += listDialogueWeight[i];
|
|
|
|
|
|
if (randomWeight <= totalWeight)
|
|
|
|
|
|
return i;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-04-23 18:10:19 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 初始化数据
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void InitData()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (isInit)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
foreach (DataDialogueCfg data in TableManager.Instance.Tables.DialogueConfig.DataList)
|
|
|
|
|
|
{
|
2024-04-29 14:22:22 +08:00
|
|
|
|
#region 构造台词数据字典
|
|
|
|
|
|
if (!dicDialogueData.TryGetValue(data.Id, out List<DataDialogueCfg> listCfg))
|
|
|
|
|
|
{
|
|
|
|
|
|
listCfg = new List<DataDialogueCfg>();
|
|
|
|
|
|
dicDialogueData[data.Id] = listCfg;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
listCfg.Add(data);
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 构造台词权重字典
|
|
|
|
|
|
if (!dicDialogueWeight.TryGetValue(data.Id, out Dictionary<int, float> dicWeight))
|
2024-04-23 18:10:19 +08:00
|
|
|
|
{
|
2024-04-29 14:22:22 +08:00
|
|
|
|
dicWeight = new Dictionary<int, float>();
|
|
|
|
|
|
dicDialogueWeight[data.Id] = dicWeight;
|
2024-04-23 18:10:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-04-29 14:22:22 +08:00
|
|
|
|
dicWeight[data.DialogueId] = 1f; // 所有台词初始权重为1f
|
|
|
|
|
|
#endregion
|
2024-04-23 18:10:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
isInit = true;
|
|
|
|
|
|
}
|
2024-04-23 18:02:13 +08:00
|
|
|
|
}
|