using System; using System.Collections.Generic; using asap.core; using cfg; using UnityEngine; using UnityEngine.Assertions; using GameCore; public class EventShootingRangeData : IChainPackData { private RawData _data = new RawData(); private readonly Tables _tables = GContext.container.Resolve(); private readonly TbPack _pack = GContext.container.Resolve().TbPack; private readonly TbEventPackManager _eventPackManager = GContext.container.Resolve().TbEventPackManager; private readonly TbEventShootingRangeMain _shootingRangeMainTable = GContext.container.Resolve().TbEventShootingRangeMain; public const string Key = "EventShootingRangeData", PackRedPointId = "EventShooting.Pack", EntranceRedPointId = "EventShooting.Enter"; private const int SlotCount = 6; public int EventId => _data.EventId; public int RedirectId => _data.RedirectId; public int AmmoCount => _data.AmmoCount; public bool HasBeenOpened { get => _data.HasBeenOpened; set => _data.HasBeenOpened = value; } public TimeSpan RemainingTime => DateTime.Parse((_tables.TbFishingEvent[_data.EventId].TimeDefinition as LimitedTime)?.EndTime) - ZZTimeHelper.UtcNow(); public bool IsActive => _tables.TbFishingEvent.DataMap.ContainsKey(_data.EventId) && _tables.TbFishingEventCycleItem2.DataMap.ContainsKey(_data.CycleId) && _tables.TbEventShootingRangeMain.DataMap.ContainsKey(_data.RedirectId) && _tables.TbEventPackManager.DataMap.ContainsKey(_tables .TbEventShootingRangeMain[_data.RedirectId].PackId) && RemainingTime.TotalSeconds > 0 && ZZTimeHelper.UtcNow() >= DateTime.Parse((_tables.TbFishingEvent[_data.EventId].TimeDefinition as LimitedTime) ?.StartTime); public EventShootingRangeMain EventShootingRange => GContext.container.Resolve().TbEventShootingRangeMain[RedirectId]; public EventShootingRangeStage CurrentStage => _tables.TbEventShootingRangeStage[EventShootingRange.StageList[CurrentStageIdx]]; public int CurrentStageIdx => _data.CurrentStageIdx % EventShootingRange.StageList.Count; public int RoundCount => _data.CurrentStageIdx / EventShootingRange.StageList.Count; // public bool IsGameDepleted => // _data.CurrentStageIdx < 0 || _data.CurrentStageIdx >= EventShootingRange.StageList.Count; public bool IsGrandPrizeAllowed => CurrentStageShootCount >= CurrentStage.MinAttempts - 1; public bool IsFinalStage => CurrentStageIdx == EventShootingRange.StageList.Count - 1; public int CurrentStageShootCount { get { int count = 0; var flag = _data.RewardFlag; while (flag > 0) { count += (int)(flag & 1); flag >>= 1; } return count; } } private List ChainList => _tables.TbEventPackManager[_tables.TbEventShootingRangeMain[_data.RedirectId].PackId] .VIPPackList[0]; public int ChainListCount => ChainList.Count; public bool IsChainPackDepleted => _data.ChainProgress >= ChainListCount; public bool IsEndGame => _data.ChainProgress > ChainList.Count - SlotCount; public bool DoNeedPackRedPoint { get { if (!IsChainPackDepleted && ChainProgress < ChainListCount) return _pack[_eventPackManager[EventShootingRange.PackId].VIPPackList[0][ChainProgress]].IAPID == 0; return false; } } public bool DoNeedEntranceRedPoint => !HasBeenOpened || _data.AmmoCount >= CycleItem.RedDot; public int ChainProgress { get => _data.ChainProgress; set => _data.ChainProgress = value; } public Pack[] NormalPacks { get { // return [_tables.TbPack[EventShootingRange.PackId2], _tables.TbPack[EventShootingRange.PackId2 + 1] var normalPackIds = _tables.TbEventPackManager[EventShootingRange.PackId2].VIPPackList[0]; var packs = new Pack[normalPackIds.Count]; for (int i = 0; i < normalPackIds.Count; i++) { packs[i] = _tables.TbPack[normalPackIds[i]]; } return packs; } } public string AmmoIconUrl => GContext.container.Resolve().TbItem[CycleItem.ID].Icon; public string AmmoNameUrl => GContext.container.Resolve().TbItem[CycleItem.ID].Name_l10n_key; public List GetTokenProgressRewardAfterAddingToken(int tokenAdded) { throw new NotImplementedException(); } public FishingEventCycleItem2 CycleItem => _tables.TbFishingEventCycleItem2[_data.CycleId]; #region UI Resources public string ChainPackPanelUrl => _shootingRangeMainTable[RedirectId].ChainPackPanel; public string PackPanelUrl => _shootingRangeMainTable[RedirectId].PackPanel; public string InfoPanelUrl => _shootingRangeMainTable[RedirectId].InfoPanel; public string MainPanelUrl => _shootingRangeMainTable[RedirectId].EventPanel; public string RewardPanelUrl => _shootingRangeMainTable[RedirectId].EventRewardPanel; public string ShootingRangeAct => _shootingRangeMainTable[RedirectId].Scene; public string EntranceIcon => _shootingRangeMainTable[RedirectId].IconEvent; public string PackIcon => _shootingRangeMainTable[RedirectId].IconPackage; public string TransitionPanelUrl => _shootingRangeMainTable[RedirectId].TransPanel; #endregion public int AmmoId => CycleItem.ItemId; public string RedPointKey => throw new NotImplementedException(); public int GetChainProgressBySlotIdx(int slotIdx) { // Debug.Log($"Progress: {ChainProgress}"); int res; if (_data.ChainProgress > ChainList.Count - SlotCount) res = ChainList.Count - SlotCount + slotIdx; else res = _data.ChainProgress + slotIdx; Assert.IsTrue(res < ChainList.Count, $"Progress {res} out of range: {ChainListCount}"); return res; } public void UpdateData(FishingEvent e) { if (EventId == e.ID) return; _data = new RawData { EventId = e.ID, CycleId = e.RedirectID, RedirectId = _tables.TbFishingEventCycleItem2[e.RedirectID].RedirectID, AmmoCount = _tables.TbFishingEventCycleItem2[e.RedirectID].WelcomeGift, HasBeenOpened = false }; UploadData(); } public void LoadData(string s) { _data = Newtonsoft.Json.JsonConvert.DeserializeObject(s); // _data.EventId = 0; // Debug.Log($"ShootingRangeDataLoaded: {s}"); } public void UploadData() { var message = Newtonsoft.Json.JsonConvert.SerializeObject(_data); // Debug.Log($"ShootingRangeDataUploaded: {message}"); PlayFabMgr.Instance.UpdateUserDataValue(Key, message); } public void AddAmmo(int count) { _data.AmmoCount += count; GContext.container.Resolve().SaveTransitionData(_data.EventId, _data.AmmoCount); UploadData(); } public int PickRandomIndex(IList weightList) { Assert.IsTrue(weightList is { Count: >= 1 }, "WeightList contains no weight."); var acc = new List { weightList[0] }; for (int i = 1; i < weightList.Count; i++) acc.Add(weightList[i] + acc[i - 1]); int random = UnityEngine.Random.Range(0, acc[^1]); for (int i = 0; i < acc.Count; i++) { if (random < acc[i]) { return i; } } return -1; } /// /// Checkout to next stage. /// /// False if next stage is out of range. public void SwitchToNextStage() { _data.CurrentStageIdx++; // _data.CurrentStageIdx %= EventShootingRange.StageList.Count; ResetRewardFlag(); ResetTargetFlag(); // return _data.CurrentStageIdx < EventShootingRange.StageList.Count; } public void SwitchToStage(int n) { _data.CurrentStageIdx = n; ResetRewardFlag(); ResetTargetFlag(); } public Pack GetChainPackByChainProgress(int chainProgress) { return _tables.TbPack[ChainList[chainProgress]]; } public void OnBuySuccess() { if (ChainProgress >= ChainListCount) { Debug.LogError($"Trying to buy pack no.{ChainProgress} while there are/is only {ChainListCount} packs."); return; } _data.ChainProgress++; } #if UNITY_EDITOR public void ResetData() { _data.AmmoCount = 200; ResetRewardFlag(); ResetTargetFlag(); _data.CurrentStageIdx = 11; UploadData(); Debug.Log("Data reset."); } #endif #region Flags public void ResetRewardFlag() { _data.RewardFlag = 0; } /// /// Check if reward No.idx in current stage is claimed. /// /// Index of current reward. Starts with 0. /// True if this reward is collected. public bool IsRewardCollected(int idx) { Assert.IsTrue(idx < CurrentStage.DropId.Count, $"Attempting to get reward{idx} status, while we have only {CurrentStage.DropId.Count} rewards."); long idxFlag = (long)1 << idx; return (_data.RewardFlag & idxFlag) == idxFlag; } public void SetRewardCollected(int idx) { Assert.IsTrue(idx < CurrentStage.DropId.Count, $"Attempting to set reward{idx} as got, while we have only {CurrentStage.DropId.Count} rewards."); _data.RewardFlag |= (long)1 << idx; } public void ResetTargetFlag() { _data.TargetFlag = 0; } public bool IsTargetHit(int idx) { /*Assert.IsTrue(idx < CurrentStage.DropId.Count, $"Attempting to get target{idx} status, while we have only {CurrentStage.DropId.Count} targets."); Assert.IsTrue(false, "JP wins!"); Assert.IsTrue(false, $"Attempting to get target{idx} status, while we have only {CurrentStage.DropId.Count} targets.");*/ if (idx >= CurrentStage.DropId.Count) Debug.LogWarning($"尝试获取{idx}号靶子的状态,但是咱只有{CurrentStage.DropId.Count}个Drop。这很奇怪。"); long idxFlag = (long)1 << idx; return (_data.TargetFlag & idxFlag) == idxFlag; } public void SetTargetHit(int idx) { // Assert.IsTrue(idx < CurrentStage.DropId.Count, // $"Attempting to get target{idx} status, while we have only {CurrentStage.DropId.Count} targets."); if (idx >= CurrentStage.DropId.Count) Debug.LogWarning($"尝试打击{idx}号靶子,但是咱只有{CurrentStage.DropId.Count}个Drop。这很奇怪。"); _data.TargetFlag |= ((long)1 << idx); } public int GetHitTargetCount() { int count = 0; long num = _data.TargetFlag; while (num != 0) { num &= num - 1; count++; } return count; } public List GetItemsByPackDropId(int dropId) { throw new NotImplementedException(); } #endregion private struct RawData { public int EventId; public int CycleId; public int RedirectId; public int AmmoCount; /// /// Used in flag fashion. /// public long RewardFlag; /// /// Used in flag fashion. /// public long TargetFlag; /// /// Stage index that starts from 0. May exceed total stage count, indicating how many rounds player has counted. /// public int CurrentStageIdx; public int ChainProgress; public bool HasBeenOpened; } }