Files
2026-05-26 16:15:54 +08:00

356 lines
12 KiB
C#

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<Tables>();
private readonly TbPack _pack = GContext.container.Resolve<Tables>().TbPack;
private readonly TbEventPackManager _eventPackManager = GContext.container.Resolve<Tables>().TbEventPackManager;
private readonly TbEventShootingRangeMain _shootingRangeMainTable =
GContext.container.Resolve<Tables>().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<Tables>().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<int> 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<Tables>().TbItem[CycleItem.ID].Icon;
public string AmmoNameUrl => GContext.container.Resolve<Tables>().TbItem[CycleItem.ID].Name_l10n_key;
public List<int> 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($"<color=#f18c0a>Progress: {ChainProgress}</color>");
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<RawData>(s);
// _data.EventId = 0;
// Debug.Log($"<color=#4d90fe>ShootingRangeDataLoaded: {s}</color>");
}
public void UploadData()
{
var message = Newtonsoft.Json.JsonConvert.SerializeObject(_data);
// Debug.Log($"<color=#4d90fe>ShootingRangeDataUploaded: {message}</color>");
PlayFabMgr.Instance.UpdateUserDataValue(Key, message);
}
public void AddAmmo(int count)
{
_data.AmmoCount += count;
GContext.container.Resolve<FishingEventData>().SaveTransitionData(_data.EventId, _data.AmmoCount);
UploadData();
}
public int PickRandomIndex(IList<int> weightList)
{
Assert.IsTrue(weightList is { Count: >= 1 }, "WeightList contains no weight.");
var acc = new List<int> { 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;
}
/// <summary>
/// Checkout to next stage.
/// </summary>
/// <returns>False if next stage is out of range.</returns>
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("<color=#4d90fe>Data reset.</color>");
}
#endif
#region Flags
public void ResetRewardFlag()
{
_data.RewardFlag = 0;
}
/// <summary>
/// Check if reward No.idx in current stage is claimed.
/// </summary>
/// <param name="idx">Index of current reward. Starts with 0.</param>
/// <returns>True if this reward is collected.</returns>
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<ItemData> GetItemsByPackDropId(int dropId)
{
throw new NotImplementedException();
}
#endregion
private struct RawData
{
public int EventId;
public int CycleId;
public int RedirectId;
public int AmmoCount;
/// <summary>
/// Used in flag fashion.
/// </summary>
public long RewardFlag;
/// <summary>
/// Used in flag fashion.
/// </summary>
public long TargetFlag;
/// <summary>
/// Stage index that starts from 0. May exceed total stage count, indicating how many rounds player has counted.
/// </summary>
public int CurrentStageIdx;
public int ChainProgress;
public bool HasBeenOpened;
}
}