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(new EventPinballTokenUpdateData()); GContext.container.Resolve().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(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 m_RewardList = new List(); public List 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().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(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(); 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(); 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(); 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().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().SaveTransitionData(m_PinballData.EventID, m_PinballData.Token); UpdateLuckyValueAndWeight(); GContext.container.Resolve().ClearGuide(""); // 同步数据 SyncData(); return pinballMain; } public EventPinballMain GetNextPinballData() { // 获取当前开放并符合解锁条件的弹珠活动ID FishingEventData fishingEventData = GContext.container.Resolve(); 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(); 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 m_PointWeightList = new List(); 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 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 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 MagnificationList = new List(); 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; } }