Files
back_cantanBuilding/Assets/Scripts/DataCenter/EventPinballDataManager.cs
2026-05-26 16:15:54 +08:00

1000 lines
30 KiB
C#

using asap.core;
using cfg;
using GameCore;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace game
{
public class EventPinballDataManager
{
#if UNITY_EDITOR
private bool m_IsCheckCondition = true;
private bool m_IsSyncData = true;
private int m_DefaultToken = 100;
#else
private bool m_IsCheckCondition = true;
private bool m_IsSyncData = true;
private int m_DefaultToken = 0;
#endif
#region
private int m_BonusResponseNumber = 10; // 相应次数
public int BonusResponseNumber { set => m_BonusResponseNumber = value; }
private int m_CumulativeResponseNumber = 0;
public int CumulativeResponseNumber
{
get => m_CumulativeResponseNumber;
set
{
m_CumulativeResponseNumber = value;
FishingPinballAct.Publish(new EventPinballUpdateBonusCircularProgress());
}
}
public bool IsAddScoreValid()
{
return m_CumulativeResponseNumber < m_BonusResponseNumber;
}
public float GetBonusResponseRatio()
{
if (m_BonusResponseNumber <= 0) return 0f;
return (float)m_CumulativeResponseNumber / m_BonusResponseNumber;
}
private int m_AccumulatedTriggerCount = 0; // 埋点用
public int AccumulatedTriggerCount
{
get => m_AccumulatedTriggerCount;
set => m_AccumulatedTriggerCount = value;
}
#endregion
#region
public int GetToken()
{
if (m_PinballData != null)
return m_PinballData.Token;
return 0;
}
public void AddToken(int count)
{
if (m_PinballData != null)
{
m_PinballData.Token += count;
}
else
{
GetFreshPinballData();
if (m_PinballData == null) return;
m_PinballData.Token += count;
}
if (m_PinballData.Token > 0) RedPointManager.Instance.SetRedPointState(RedPointName.Home_Pinball, true);
else RedPointManager.Instance.SetRedPointState(RedPointName.Home_Pinball, false);
FishingPinballAct.Publish<EventPinballTokenUpdateData>(new EventPinballTokenUpdateData());
GContext.container.Resolve<FishingEventData>().SaveTransitionData(m_PinballData.EventID, m_PinballData.Token);
SyncData();
}
//public bool ConsumeTokensDefault()
//{
// EventPinballMain pinballMain = GetCurrentEventPinballMain();
// int magnification = GetCurMagnification();
// bool isEnough = ConsumeTokens(pinballMain.SpinRequire * magnification);
// if (isEnough == false)
// {
// ToastPanel.Show(LocalizationMgr.GetText("UI_ToastPanel_103"));
// }
// return isEnough;
//}
public bool ConsumeTokens(int count)
{
bool isEnough = IsEnough(count);
if (isEnough == false) return false;
m_PinballData.ConsumedToken += count;
m_PinballData.TotalConsumedToken += count;
AddToken(-count);
return isEnough;
}
public bool IsEnough(int spend)
{
if (m_PinballData == null) return false;
return (m_PinballData.Token - spend) >= 0;
}
#endregion
#region
public void ClearTemporaryData()
{
m_IsMultipleMax = false;
CumulativeResponseNumber = 0;
AccumulatedTriggerCount = 0;
ClearTemporaryScore();
ClearTemporaryConsumedToken();
}
public void SyncTemporaryData()
{
SyncTemporaryScore();
SyncTemporaryTokens();
}
private int m_TemporaryScore = 0;
public int TemporaryScore { get => m_TemporaryScore; }
//public int GetTotalScores()
//{
// return m_PinballData.Scores + m_TemporaryScore;
//}
public void ClearTemporaryScore()
{
m_TemporaryScore = 0;
}
public void AddTemporaryScore(int score)
{
m_TemporaryScore += score;
}
public void MultiplyTemporaryScore(int multiple)
{
m_TemporaryScore *= multiple;
}
public void SyncTemporaryScore()
{
if (m_TemporaryScore > 0)
{
//m_PinballData.Scores += m_TemporaryScore;
m_PinballData.TotalScores += m_TemporaryScore;
}
}
public void ReturnConsumedToken()
{
AddToken(m_TemporaryConsumedToken);
}
private int m_TemporaryConsumedToken = 0;
public int TemporaryConsumedToken { get => m_TemporaryConsumedToken; }
public void ClearTemporaryConsumedToken()
{
m_TemporaryConsumedToken = 0;
}
public bool ConsumeTemporaryTokensDefault()
{
EventPinballMain pinballMain = GetCurrentEventPinballMain();
int magnification = GetCurMagnification();
bool isEnough = ConsumeTemporaryTokens(pinballMain.SpinRequire * magnification);
//if (isEnough == false)
//{
// ToastPanel.Show(LocalizationMgr.GetText("UI_ToastPanel_103"));
//}
return isEnough;
}
public bool ConsumeTemporaryTokens(int count)
{
bool isEnough = IsEnough(count);
if (isEnough == false) return false;
ConsumeTokens(count);
m_TemporaryConsumedToken += count;
FishingPinballAct.Publish<EventPinballTokenUpdateData>(new EventPinballTokenUpdateData());
return isEnough;
}
public void SyncTemporaryTokens()
{
//if (m_TemporaryConsumedToken > 0)
//{
// int consumedToken = m_TemporaryConsumedToken;
// //m_TemporaryConsumedToken = 0;
// ConsumeTokens(consumedToken);
//}
}
private bool m_IsMultipleMax = false;
public bool IsMultipleMax { get => m_IsMultipleMax; set => m_IsMultipleMax = value; }
#endregion
#region
private int m_MagnificationListIndex = 0;
public void ResetMagnification()
{
EventPinballMain pinballMain = GetCurrentEventPinballMain();
int magnification = GetCurMagnification();
bool isEnough = IsEnough(pinballMain.SpinRequire * magnification);
if (isEnough == false)
{
int count = m_PinballData.MagnificationList.Count;
int index = 0;
for (int i = count - 1; i >= 0; --i)
{
int tmpMagnification = m_PinballData.MagnificationList[i];
if (IsEnough(pinballMain.SpinRequire * tmpMagnification))
{
index = i;
break;
}
}
m_MagnificationListIndex = index;
}
FishingPinballAct.Publish(new EventPinballResetMagnification());
}
public int GetCurMagnification()
{
if (m_PinballData == null) return -1;
return m_PinballData.MagnificationList[m_MagnificationListIndex];
}
public bool IsMaxMagnification()
{
if (m_PinballData == null) return false;
return IsCurMaxMagnification();// m_MagnificationListIndex == (m_PinballData.MagnificationList.Count - 1);
}
bool IsCurMaxMagnification()
{
if (m_PinballData == null) return false;
EventPinballMain pinballMain = GetCurrentEventPinballMain();
int count = m_PinballData.MagnificationList.Count;
int tmpIndex = m_MagnificationListIndex + 1;
if (tmpIndex >= count)
{
return true;
}
int magnification = m_PinballData.MagnificationList[tmpIndex];
return !IsEnough(pinballMain.SpinRequire * magnification);
}
public void ScrollToTheNextMagnification()
{
if (m_PinballData == null) return;
EventPinballMain pinballMain = GetCurrentEventPinballMain();
int count = m_PinballData.MagnificationList.Count;
int tmpIndex = m_MagnificationListIndex + 1;
if (tmpIndex >= count)
{
tmpIndex = 0;
}
int magnification = m_PinballData.MagnificationList[tmpIndex];
bool isEnough = IsEnough(pinballMain.SpinRequire * magnification);
if (isEnough)
{
m_MagnificationListIndex = tmpIndex;
}
else
{
m_MagnificationListIndex = 0;
}
}
private List<float> m_RewardList = new List<float>();
public List<float> RewardList { get => m_RewardList; }
public void InitRewardList()
{
m_RewardList.Clear();
int count = m_TbEventPinballReward.DataList.Count;
for (int i = 0; i < count; ++i)
{
var item = m_TbEventPinballReward.DataList[i];
m_RewardList.Add(item.SpinPoint);
}
}
//private int m_RewardIndex, m_RewardMaxIndex;
//public int RewardIndex { get => m_RewardIndex; }
//public int RewardMaxIndex { get => m_RewardMaxIndex; }
//public void CalculateReward()
//{
// if (m_PinballData == null) return;
// m_RewardIndex = FindInsertionIndex(m_RewardList, m_PinballData.Scores);
// m_RewardMaxIndex = m_TbEventPinballReward.DataList.Count - 1;
//}
//public void AddScore(int score)
//{
// if (m_PinballData == null) return;
// m_PinballData.Scores += score;
// m_PinballData.TotalScores += score;
//}
#endregion
#region
public void ActivateEvent(FishingEvent fishingEvent)
{
if (fishingEvent == null) return;
if (!Init()) return;
if (m_PinballData == null) GetFreshPinballData();
else FixPinballData();
//if (m_PinballData != null)
{
int pinballMainID = fishingEvent.RedirectID;
EventPinballMain pinballMain = m_TbEventPinballMain.GetOrDefault(pinballMainID);
var data = GContext.container.Resolve<FishingEventData>().ChainPackWithProgressMigrationData;
if (fishingEvent.ID != data.EventId)
data.UpdateData(fishingEvent.ID, pinballMain.PackId);
}
}
public void GetDataFromServer(string json)
{
if (string.IsNullOrEmpty(json))
{
GameDebug.LogWarning("EventPinball get data from server has encountered empty data.");
return;
}
try
{
m_PinballData = Newtonsoft.Json.JsonConvert.DeserializeObject<EventPinballData>(json);
}
catch (Exception e)
{
GameDebug.LogWarning("EventPinball deserialize data has failed. Exception: " + e.ToString());
return;
}
if (!Init()) return;
}
public int FixPinballData()
{
if (m_PinballData == null) return 0;
// 获取当前开放并符合解锁条件的弹珠活动ID
FishingEventData fishingEventData = GContext.container.Resolve<FishingEventData>();
FishingEvent fishingEvent = fishingEventData.GetEventByTypeAndSubType(4, 6, m_IsCheckCondition);
if (fishingEvent == null) return ClearData();
int eventID = fishingEvent.ID;
int pinballMainID = fishingEvent.RedirectID;
if (pinballMainID < 0) return ClearData();
if (eventID != m_PinballData.EventID || pinballMainID != m_PinballData.PinballMainID) return ClearData();
return 0;
}
public TimeSpan RemainingTime
{
get => DateTime.Parse((m_Tables.TbFishingEvent[m_PinballData.EventID].TimeDefinition as LimitedTime).EndTime)
- ZZTimeHelper.UtcNow();
}
public int ClearData()
{
if (m_PinballData == null) return 0;
m_PinballData.Clear();
m_PinballData = null;
return 0;
}
public void SyncData()
{
if (!m_IsSyncData) return;
PlayFabMgr.Instance.UpdateUserDataValue(EventPinballConfig.SAVE_DATA_KEY, Newtonsoft.Json.JsonConvert.SerializeObject(m_PinballData));
}
#endregion
#region
public bool Init()
{
InitTables();
m_IsSimulatorMode = false;
return true;
}
#endregion
#region Table Data
private Tables m_Tables;
private TbEventPinballMain m_TbEventPinballMain;
private TbEventPinballPoint m_TbEventPinballPoint;
private TbEventPinballReward m_TbEventPinballReward;
private void InitTables()
{
m_Tables = GContext.container.Resolve<Tables>();
if (m_Tables == null) return;
m_TbEventPinballMain = m_Tables.TbEventPinballMain;
m_TbEventPinballPoint = m_Tables.TbEventPinballPoint;
m_TbEventPinballReward = m_Tables.TbEventPinballReward;
InitRewardList();
}
public EventPinballReward GetEventPinballReward(int index)
{
return m_TbEventPinballReward.DataList[index];
}
#endregion
#region UI
private UIType m_UIPanel = null, m_InfoPanel = null;
public void ClearUIData()
{
m_UIPanel = null;
m_InfoPanel = null;
}
public void InitUIData()
{
GetUIPanel();
GetInfoPanel();
}
public UIType GetUIPanel()
{
if (m_UIPanel == null)
{
var data = GetCurrentEventPinballMain();
m_UIPanel = new UIType(data.UIPanel);
}
return m_UIPanel;
}
public UIType GetInfoPanel()
{
if (m_InfoPanel == null)
{
var data = GetCurrentEventPinballMain();
m_InfoPanel = new UIType(data.InfoPanel);
}
return m_InfoPanel;
}
#endregion
#region
private EventPinballData m_PinballData;
public EventPinballData PinballData { get { return m_PinballData; } }
public EventPinballMain GetFreshPinballData()
{
// 获取当前开放并符合解锁条件的弹珠活动ID
FishingEventData fishingEventData = GContext.container.Resolve<FishingEventData>();
FishingEvent fishingEvent = fishingEventData.GetEventByTypeAndSubType(4, 6, m_IsCheckCondition);
if (fishingEvent == null) return null;
int eventID = fishingEvent.ID;
int pinballMainID = fishingEvent.RedirectID;
if (pinballMainID < 0) return null;
// 获取当前弹珠活动数据
EventPinballMain pinballMain = m_TbEventPinballMain.GetOrDefault(pinballMainID);
if (pinballMain == null) return null;
int token = m_DefaultToken;
if (m_PinballData != null) m_PinballData.Clear();
m_PinballData = null;
token = GContext.container.Resolve<FishingEventData>().GetInitWelcomeGift(eventID);
m_PinballData = new EventPinballData();
m_PinballData.EventID = eventID;
m_PinballData.PinballMainID = pinballMainID;
m_PinballData.Force = 0f;
m_PinballData.SpinPoint = 0;
m_PinballData.Scores = 0;
m_PinballData.Multiple = 0;
m_PinballData.IsOver = false;
m_PinballData.Token = token;
m_PinballData.ConsumedToken = 0;
m_PinballData.TotalConsumedToken = 0;
m_PinballData.TotalScores = 0;
m_PinballData.Round = 0;
m_PinballData.LuckyValue = (float)pinballMain.InitialLuck;
m_PinballData.RewardIndex = 0;
m_PinballData.RewardMaxIndex = m_TbEventPinballReward.DataList.Count - 1;
EventPinballReward curReward = GetEventPinballReward(m_PinballData.RewardIndex);
m_PinballData.CurDropID = curReward.DropID;
EventPinballReward lastReward = GetEventPinballReward(m_PinballData.RewardMaxIndex);
m_PinballData.FinalDropID = lastReward.DropID;
m_PinballData.MagnificationList.AddRange(pinballMain.SpinMag.ToArray());
GContext.container.Resolve<FishingEventData>().SaveTransitionData(m_PinballData.EventID, m_PinballData.Token);
UpdateLuckyValueAndWeight();
GContext.container.Resolve<GuideDataCenter>().ClearGuide("");
// 同步数据
SyncData();
return pinballMain;
}
public EventPinballMain GetNextPinballData()
{
// 获取当前开放并符合解锁条件的弹珠活动ID
FishingEventData fishingEventData = GContext.container.Resolve<FishingEventData>();
FishingEvent fishingEvent = fishingEventData.GetEventByTypeAndSubType(4, 6, m_IsCheckCondition);
if (fishingEvent == null) return null;
int eventID = fishingEvent.ID;
int pinballMainID = fishingEvent.RedirectID;
if (pinballMainID < 0) return null;
if (eventID != m_PinballData.EventID || pinballMainID != m_PinballData.PinballMainID) return GetFreshPinballData();
// 获取当前弹珠活动数据
EventPinballMain pinballMain = m_TbEventPinballMain.GetOrDefault(pinballMainID);
if (pinballMain == null) return null;
m_PinballData.EventID = eventID;
m_PinballData.PinballMainID = pinballMainID;
m_PinballData.IsOver = false;
m_PinballData.ConsumedToken = 0;
UpdateLuckyValueAndWeight();
// 同步数据
SyncData();
return pinballMain;
}
public EventPinballMain ContinueGame()
{
if (m_PinballData == null) return GetFreshPinballData();
// 获取当前开放并符合解锁条件的弹珠活动ID
FishingEventData fishingEventData = GContext.container.Resolve<FishingEventData>();
FishingEvent fishingEvent = fishingEventData.GetEventByTypeAndSubType(4, 6, m_IsCheckCondition);
if (fishingEvent == null) return null;
int eventID = fishingEvent.ID;
int pinballMainID = fishingEvent.RedirectID;
if (pinballMainID < 0) return null;
if (eventID != m_PinballData.EventID || pinballMainID != m_PinballData.PinballMainID) return GetFreshPinballData();
// 获取当前弹珠活动数据
EventPinballMain pinballMain = m_TbEventPinballMain.GetOrDefault(pinballMainID);
if (pinballMain == null) return null;
//UpdateLuckyValueAndWeight();
return pinballMain;
}
public List<float> m_PointWeightList = new List<float>();
public EventPinballPoint UpdateLuckyValueAndWeight()
{
if (m_TbEventPinballPoint == null) return null;
m_PointWeightList.Clear();
float luckyValue = m_PinballData.LuckyValue;
int count = m_TbEventPinballPoint.DataList.Count;
float total = 0;
for (int i = 0; i < count; ++i)
{
EventPinballPoint item = m_TbEventPinballPoint.DataList[i];
float weight = item.Weight + luckyValue * item.LuckParameter;
total += weight;
float tmp = total;
m_PointWeightList.Add(tmp);
}
float randomValue = UnityEngine.Random.Range(0f, total);
int index = FindInsertionIndex(m_PointWeightList, randomValue);
EventPinballPoint target = m_TbEventPinballPoint.DataList[index];
if (float.MaxValue - target.DeltaLuck <= m_PinballData.LuckyValue)
{
m_PinballData.LuckyValue = 0;
}
else
{
m_PinballData.LuckyValue += target.DeltaLuck;
if (m_PinballData.LuckyValue < 0f)
{
m_PinballData.LuckyValue = 0f;
}
}
m_PinballData.SpinPoint = target.SpinPoint;
return target;
}
public int FindInsertionIndex(List<float> sortedList, float target)
{
if (sortedList == null || sortedList.Count == 0)
{
Debug.LogError("---- EventPinballDataManager->FindInsertionIndex 数组为空");
return -1;
}
if (target < sortedList[0])
{
return 0;
}
if (target >= sortedList[sortedList.Count - 1])
{
return -1;
}
// 使用二分查找算法
int left = 0;
int right = sortedList.Count - 1;
int result = -1;
while (left <= right)
{
int mid = left + (right - left) / 2;
if (sortedList[mid] > target)
{
if (mid > 0 && target > sortedList[mid - 1] && target < sortedList[mid])
{
result = mid;
break;
}
right = mid - 1;
}
else
{
if (mid < sortedList.Count - 1 && target >= sortedList[mid] && target < sortedList[mid + 1])
{
result = mid + 1;
break;
}
left = mid + 1;
}
}
return result;
}
public float GetRandomForce(float ratio)
{
EventPinballPoint target = m_TbEventPinballPoint.GetOrDefault(m_PinballData.SpinPoint);
EventPinballMain pinballMain = GetCurrentEventPinballMain();
float failMaxDist = pinballMain.FailMaxDist;
if (ratio <= failMaxDist)
{
return pinballMain.FailMaxForce;
}
int count = target.ForceLv.Count;
List<float> forceList = target.ForceLv[count - 1];
ratio = (ratio - failMaxDist) / 1 - failMaxDist; // 归一化到0-1之间
float subRatio = 1f / count; // 每个等级的比例
for (int i = 0; i < count; ++i)
{
if (ratio <= subRatio * (i + 1))
{
forceList = target.ForceLv[i];
break;
}
}
count = forceList.Count;
int index = UnityEngine.Random.Range(0, count);
return forceList[index];
}
public void InitGameRound()
{
//SetRewardList();
//CalculateReward();
ResetMagnification();
ClearTemporaryData();
m_PinballData.Force = 0f;
PinballData.Multiple = 0;
}
public EventPinballMain GetCurrentEventPinballMain()
{
if (m_PinballData == null) return GetFreshPinballData();
return m_TbEventPinballMain.GetOrDefault(m_PinballData.PinballMainID);
}
#endregion
#region
public string GetSaveKey(string key)
{
if (m_PinballData == null) return key;
return m_PinballData.EventID + "-" + m_PinballData.PinballMainID + "-" + key;
}
public bool HasSaveKey(string key)
{
return PlayerPrefs.HasKey(GetSaveKey(key));
}
public void SaveData(string key, string value)
{
PlayerPrefs.SetString(GetSaveKey(key), value);
PlayerPrefs.Save();
}
#endregion
#region
public bool IsRedDotDisplayed()
{
if (m_PinballData == null) return false;
return m_PinballData.Token > 0;
}
#endregion
#region (/)
public bool m_IsSimulatorMode = false;
public bool IsSimulatorMode
{
get => m_IsSimulatorMode;
set
{
if (m_IsSimulatorMode != value)
{
m_IsSimulatorMode = value;
FishingPinballAct.Publish(new EventPinballSyncOperatingModeData()
{
IsSimulatorMode = value
});
}
}
}
#endregion
#region IO
public string GetSaveFilepath(string filename)
{
return Path.Combine(Application.persistentDataPath, filename);
}
#endregion
}
public class EventPinballData
{
public int EventID { get; set; }
public int PinballMainID { get; set; }
public float Force { get; set; }
public int SpinPoint { get; set; }
public int Scores { get; set; }
public int Multiple { get; set; }
public bool IsOver { get; set; }
public int Token { get; set; }
public int ConsumedToken { get; set; }
public int TotalScores { get; set; }
public int TotalConsumedToken { get; set; }
public int Round { get; set; }
public float LuckyValue { get; set; }
public int RewardIndex { get; set; }
public int RewardMaxIndex { get; set; }
public int CurDropID { get; set; }
public int FinalDropID { get; set; }
public List<int> MagnificationList = new List<int>();
public void Clear()
{
MagnificationList.Clear();
ClearAllLocalData();
}
public void ClearAllLocalData()
{
//if (PlayerPrefs.HasKey(LocalKey) == false) return;
//PlayerPrefs.DeleteKey(LocalKey);
}
}
public enum EventPinballBonusType
{
TypeScore,
TypeMultiple
}
public enum EventPinballTrackType
{
TypeEnter,
TypeExit
}
public enum EventPinballState
{
Prepare,
Running,
Ended
}
public enum EventPinballSwitcherState
{
Open,
Close
}
public class EventPinballSwitcherOpen
{
}
public class EventPinballSwitcherClose
{
}
public class EventPinballEnergyArrowData
{
public float Energy;
}
public class EventPinballEnergyArrowRestoreData
{
}
public class EventPinballUpdateBonusCircularProgress
{
}
public class EventPinballTokenUpdateData
{
}
public class EventPinballBasicScore
{
public int Score;
}
public class EventPinballBasicScoreHideData
{
}
public class EventPinballBasicScoreShowData
{
}
public class EventPinballResetMagnification
{
}
public class EventPinballRewardUpdateData
{
public int Scores;
}
public class EventPinballSpringUpdateData
{
public float Ratio;
}
public class EventPinballPlayArrowBreathAnimData
{
}
public class EventPinballStopArrowBreathAnimData
{
}
public class EventPinballPlayLightOnAnimData
{
}
public class EventPinballResumePelletData
{
}
public class EventPinballResetPelletStatusData
{
}
public class EventPinballLaunchPelletData
{
public float Force;
}
public class EventPinballShowPopupData
{
public int Scores;
public EventPinballBonusType BonusType;
public bool IsMultipleMax;
}
public class EventPinballHidePopupData
{
}
public class EventPinballShowMultipleTextData
{
public EventPinballBonusType BonusType;
public Vector3 Position;
public string Tips;
public int Scores;
public bool IsMultipleMax;
}
public class EventPinballRewardDisplayUpdateData
{
public int RewardId;
public int RewardIndex;
public int FromScore;
public int TargetScore;
public int LevelScore;
public float FromRatio;
public float TargetRatio;
public int DropId;
public int RewardDisplayDropId;
}
public class EventPinballSyncOperatingModeData
{
public bool IsSimulatorMode;
}
public class EventPinballHideWidgetMultipleEffectData
{
}
public class EventPinballShowWidgetScoreEffect2Data
{
}
public class EventPinballHideFiringPinData
{
}
public class EventPinballShowFiringPinData
{
}
public class EventPinballHideCircularRotationalAnim
{
}
public class EventPinballShowCircularRotationalAnim
{
}
public class EventPinballLaunchPelletStatusData
{
}
public class EventPinballSetDummyPelletData
{
public PinballPellet Pellet;
}
public class EventPinballConfig
{
public const string CSVFileName = "pinball.csv";
public const string SAVE_DATA_KEY = "epbdk"; // event pinball data key
public const int MultipleMax = 10;
}
}