420 lines
15 KiB
C#
420 lines
15 KiB
C#
using cfg;
|
|
using asap.core;
|
|
using GameCore;
|
|
using SystemRandom = System.Random;
|
|
using UnityEngine;
|
|
using System.Linq;
|
|
using System.Collections.Generic;
|
|
using UnityEngine.Assertions;
|
|
using System;
|
|
using Castle.Core.Internal;
|
|
|
|
public class EventBreakTableContext
|
|
{
|
|
#region Private Table References
|
|
private readonly EventDrillMain _tableMain;
|
|
private readonly EventDrillTunnel[] _tableTunnels;
|
|
private readonly TbEventDrillReward _tableTask;
|
|
private readonly FishingEvent _tableEvent;
|
|
private readonly FishingEventCycleItem2 _tableCycle;
|
|
private readonly Tables _tables = GContext.container.Resolve<Tables>();
|
|
#endregion
|
|
public int TunnelCount => _tableTunnels.Length;
|
|
private readonly PlayerItemData _playerItemData = GContext.container.Resolve<PlayerItemData>();
|
|
public SystemRandom Random;
|
|
public readonly int BlockCountPerTunnel = 8;
|
|
|
|
private EventBreakTableContext(EventDrillMain tableMain, EventDrillTunnel[] tableTunnels, TbEventDrillReward tableTask, FishingEvent tableEvent, FishingEventCycleItem2 tableCycle, Tables tables)
|
|
{
|
|
_tableMain = tableMain;
|
|
_tableTunnels = tableTunnels;
|
|
_tableTask = tableTask;
|
|
_tableEvent = tableEvent;
|
|
_tableCycle = tableCycle;
|
|
_tables = tables;
|
|
}
|
|
|
|
public static EventBreakTableContext ReadTables(int eventId, Tables tables)
|
|
{
|
|
int redirectId, cycleId;
|
|
cycleId = tables.TbFishingEvent[eventId].RedirectID;
|
|
redirectId = tables.TbFishingEventCycleItem2[cycleId].RedirectID;
|
|
var tableEvent = tables.TbFishingEvent[eventId];
|
|
var tableCycle = tables.TbFishingEventCycleItem2[cycleId];
|
|
var tableMain = tables.TbEventDrillMain[redirectId];
|
|
var tableTunnels = tables.TbEventDrillTunnel.DataList.Where(t => tableMain.TunnelList.Contains(t.Tunnel)).ToArray();
|
|
var tableTask = tables.TbEventDrillReward;
|
|
return new EventBreakTableContext(tableMain, tableTunnels, tableTask, tableEvent, tableCycle, tables);
|
|
}
|
|
|
|
#region TaskInfoProcess
|
|
|
|
public EventBreakTaskInfo GetTaskInfo(int taskId, int tunnelIdx, int gemProgress = 0)
|
|
{
|
|
if (!_tableTask.DataMap.TryGetValue(taskId, out var taskTableData))
|
|
{
|
|
Debug.Log($"[EventBreak]Task id {taskId} not found in table.");
|
|
return null;
|
|
}
|
|
int targetItemId = GetItemIdFromDrop(_tableTunnels[tunnelIdx].DropGem);
|
|
if (targetItemId == -1)
|
|
{
|
|
return null;
|
|
}
|
|
// var taskReward = GetBlockDataFromDropId(_tableTask[taskId].DropGem);
|
|
var taskReward = _playerItemData.GetItemDataByDropId(_tableTask[taskId].DropGem)[0];
|
|
return new EventBreakTaskInfo
|
|
{
|
|
TaskId = taskTableData.TaskID,
|
|
TargetItemId = targetItemId,
|
|
Reward = taskReward,
|
|
TotalGemRequired = _tableTask[taskId].TokenRequired,
|
|
CurrentGemProgress = gemProgress
|
|
};
|
|
}
|
|
|
|
public EventBreakTaskInfo GetNextTaskInfo(EventBreakTaskInfo taskInfo)
|
|
{
|
|
Assert.IsTrue(taskInfo.CurrentGemProgress >= taskInfo.TotalGemRequired, "[EventBreak]Current gem progress is less than total gem required.");
|
|
var dataFlag = _tables.TbEventDrillReward.DataMap.TryGetValue(taskInfo.TaskId, out var taskTableData);
|
|
if (!dataFlag)
|
|
{
|
|
Debug.Log($"[Drill]Task id {taskInfo.TaskId} not found in reward table.");
|
|
return null;
|
|
}
|
|
var nextTaskId = taskTableData.NextTarget;
|
|
dataFlag = _tables.TbEventDrillReward.DataMap.TryGetValue(nextTaskId, out var nextTaskTableData);
|
|
if (!dataFlag)
|
|
{
|
|
Debug.Log($"[Drill]Next task id {nextTaskId} not found in reward table, end of mission chain.");
|
|
return null;
|
|
}
|
|
// var taskReward = GetBlockDataFromDropId(nextTaskTableData.DropGem);
|
|
var taskReward = _playerItemData.GetItemDataByDropId(nextTaskTableData.DropGem)[0];
|
|
return new EventBreakTaskInfo
|
|
{
|
|
TaskId = nextTaskId,
|
|
TargetItemId = taskInfo.TargetItemId,
|
|
Reward = taskReward,
|
|
TotalGemRequired = nextTaskTableData.TokenRequired,
|
|
CurrentGemProgress = taskInfo.CurrentGemProgress - taskInfo.TotalGemRequired
|
|
};
|
|
}
|
|
|
|
#endregion
|
|
|
|
public void GetFreshNewModelData(int[] jobSeeds, out int welcomeGift, out DrillJobModel[] drillJobs, out EventBreakTaskInfo[] taskInfoList)
|
|
{
|
|
welcomeGift = _tableCycle.WelcomeGift;
|
|
drillJobs = new DrillJobModel[TunnelCount];
|
|
taskInfoList = new EventBreakTaskInfo[TunnelCount];
|
|
var defaultTaskIds = _tableTunnels.Select(t => t.TaskList).ToArray();
|
|
for (int i = 0; i < TunnelCount; i++)
|
|
{
|
|
drillJobs[i] = GetDrillJob(i, jobSeeds[i]);
|
|
taskInfoList[i] = GetTaskInfo(_tableTunnels[i].TaskList, i);
|
|
}
|
|
}
|
|
|
|
public int GetEntranceRedDotTicketThreshold()
|
|
{
|
|
return _tableCycle.RedDot;
|
|
}
|
|
|
|
public DrillJobModel[] GetDrillJobModels(int[] seeds)
|
|
{
|
|
var res = new DrillJobModel[seeds.Length];
|
|
for (int i = 0; i < seeds.Length; i++)
|
|
res[i] = GetDrillJob(i, seeds[i]);
|
|
return res;
|
|
}
|
|
|
|
public EventBreakTaskInfo[] GetTaskInfoArray((int id, int progress)[] taskData)
|
|
{
|
|
var res = new EventBreakTaskInfo[taskData.Length];
|
|
for (int i = 0; i < taskData.Length; i++)
|
|
{
|
|
// Debug.Log($"[EventBreak]Task init: id {taskData[i].id}, progress {taskData[i].progress}");
|
|
res[i] = GetTaskInfo(taskData[i].id, i, taskData[i].progress);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get DrillJob. Before calling this, do save the seed if necessarry.
|
|
/// </summary>
|
|
/// <param name="idx">In which tunnel</param>
|
|
/// <param name="seed">By what rng seed. If seed is less than table threshold, fallback into initial fixed drops.</param>
|
|
/// <returns>The drill job</returns>
|
|
public DrillJobModel GetDrillJob(int idx, int seed)
|
|
{
|
|
var tunnelData = _tableTunnels[idx];
|
|
var res = new DrillJobModel
|
|
{
|
|
Cost = tunnelData.ItemRequired,
|
|
};
|
|
var rewardBlockDatas = new List<DrillBlockData>();
|
|
var blockDatas = new List<DrillBlockData>();
|
|
for (int i = 0; i < BlockCountPerTunnel; i++)
|
|
blockDatas.Add(DrillBlockData.CreateEmpty());
|
|
SystemRandom rng;
|
|
var gemId = GetItemIdFromDrop(tunnelData.DropGem);
|
|
if (IsSeedFixed(idx, seed))
|
|
{
|
|
rng = new SystemRandom(seed + idx);
|
|
var dropId = tunnelData.FixDropId[seed];
|
|
var items = _playerItemData.GetItemDataByDropId(dropId);
|
|
foreach (var item in items)
|
|
{
|
|
if (item.id == gemId)
|
|
{
|
|
int n = (int)item.count;
|
|
while (n > 0)
|
|
{
|
|
rewardBlockDatas.Add(new DrillBlockData { Item = new ItemData(item.id, 1) });
|
|
n--;
|
|
}
|
|
}
|
|
else
|
|
rewardBlockDatas.Add(new DrillBlockData { Item = item });
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rng = new SystemRandom(seed);
|
|
Assert.IsTrue(idx >= 0 && idx < _tableTunnels.Length, $"Tunnel Index {idx} not within range [0, {_tableTunnels.Length - 1}].");
|
|
var dropIds = GetTunnelDropIds(_tableTunnels[idx], rng);
|
|
Assert.IsTrue(dropIds.Count <= BlockCountPerTunnel, "[EventBreak]Reward count is greater than block count");
|
|
foreach (var dropId in dropIds)
|
|
rewardBlockDatas.AddRange(GetBlockDataFromDropId(dropId, rng, gemId));
|
|
}
|
|
var itemCount = rewardBlockDatas.Count;
|
|
// int i = itemCount;
|
|
// while (i < BlockCountPerTunnel)
|
|
// {
|
|
// blockDatas.Add(DrillBlockData.CreateEmpty());
|
|
// i++;
|
|
// }
|
|
rewardBlockDatas = rewardBlockDatas.OrderBy(x => rng.Next()).ToList();
|
|
if (rewardBlockDatas.IsNullOrEmpty())
|
|
{
|
|
Debug.LogError($"[EventBreak] No reward found in tunnel {idx}");
|
|
res.Blocks = blockDatas.ToArray();
|
|
return res;
|
|
}
|
|
var indicesToPick = Enumerable.Range(0, BlockCountPerTunnel).ToList();
|
|
int idxPicked = rng.Next(0, BlockCountPerTunnel);
|
|
blockDatas[idxPicked] = rewardBlockDatas[0];
|
|
indicesToPick.Remove(idxPicked);
|
|
indicesToPick.Remove(idxPicked + 1);
|
|
indicesToPick.Remove(idxPicked - 1);
|
|
for (int i = 1; i < rewardBlockDatas.Count; i++)
|
|
{
|
|
idxPicked = indicesToPick[rng.Next(0, indicesToPick.Count)];
|
|
blockDatas[idxPicked] = rewardBlockDatas[i];
|
|
indicesToPick.Remove(idxPicked);
|
|
}
|
|
res.Blocks = blockDatas.ToArray();
|
|
return res;
|
|
}
|
|
|
|
public bool IsSeedFixed(int idx, int seed)
|
|
{
|
|
return seed >= 0 && seed < _tableTunnels[idx].FixDropId.Count;
|
|
}
|
|
|
|
public bool DoesSeedNeedInc(int idx, int seed)
|
|
{
|
|
return seed >= 0 && seed < _tableTunnels[idx].FixDropId.Count - 1;
|
|
}
|
|
|
|
private List<ItemData> GetInitTunnelDropIds(EventDrillTunnel tunnel, int fixedDropIdx)
|
|
{
|
|
if (fixedDropIdx < 0 || fixedDropIdx >= tunnel.FixDropId.Count)
|
|
{
|
|
return null;
|
|
}
|
|
return _playerItemData.GetItemDataByDropId(tunnel.FixDropId[fixedDropIdx]);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the drop ids for the tunnel. First drop is the the gem of the tunnel.
|
|
/// </summary>
|
|
/// <param name="tunnel">tunnel data from table</param>
|
|
/// <returns>The dropIds for the tunnel.</returns>
|
|
private List<int> GetTunnelDropIds(EventDrillTunnel tunnel, SystemRandom rng)
|
|
{
|
|
var dropIds = new List<int>();
|
|
dropIds.Add(tunnel.DropGem);
|
|
var count = tunnel.DropCountList[FtMathUtils.GetRandomIdxFromWeightList(tunnel.DropWeightList, rng)];
|
|
while (count > 0)
|
|
{
|
|
dropIds.Add(tunnel.DropItemId);
|
|
count--;
|
|
}
|
|
return dropIds;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Assuming that Random state is set before calling. Will seperate gem.
|
|
/// </summary>
|
|
/// <param name="dropId">The drop id that represents a weighted random item.</param>
|
|
/// <returns>The actual item id and count.</returns>
|
|
private DrillBlockData[] GetBlockDataFromDropId(int dropId, SystemRandom rng, int gemId)
|
|
{
|
|
ItemData item;
|
|
var res = new List<DrillBlockData>();
|
|
if (!_tables.TbDrop.DataMap.TryGetValue(dropId, out var drop))
|
|
{
|
|
Debug.Log($"[EventBreak]Drop id {dropId} not found.");
|
|
return res.ToArray();
|
|
}
|
|
if (drop.Type != DropType.Weight)
|
|
{
|
|
Debug.Log($"[EventBreak]Unsupported drop type {drop.Type} from drop Id {dropId}.");
|
|
return res.ToArray();
|
|
}
|
|
if (rng == null)
|
|
{
|
|
Debug.Log($"[EventBreak]Need random number generator for this drop type.");
|
|
return res.ToArray();
|
|
}
|
|
try
|
|
{
|
|
var idx = FtMathUtils.GetRandomIdxFromWeightList(drop.DropList.DropProbList, rng);
|
|
item = new ItemData(drop.DropList.DropIDList[idx], drop.DropList.DropCountList[idx]);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.LogError($"[EventBreak]Invalid drop id {drop}: {e.Message}\n{e.StackTrace}");
|
|
return res.ToArray();
|
|
}
|
|
_playerItemData.ItemTransition(item);
|
|
if (item.id == gemId)
|
|
for (int i = 0; i < (int)item.count; i++)
|
|
res.Add(new DrillBlockData { Item = new ItemData(id: gemId, count: 1) });
|
|
else
|
|
res.Add(new DrillBlockData { Item = item });
|
|
return res.ToArray();
|
|
}
|
|
|
|
private int GetItemIdFromDrop(int dropId)
|
|
{
|
|
if (!_tables.TbDrop.DataMap.TryGetValue(dropId, out var drop))
|
|
{
|
|
Debug.Log($"[EventBreak]Drop id {dropId} not found.");
|
|
return -1;
|
|
}
|
|
return drop.DropList.DropIDList[0];
|
|
}
|
|
|
|
public EventBreakEntranceData GetEntranceButtonData()
|
|
{
|
|
var res = new EventBreakEntranceData();
|
|
res.BtnIconUrl = _tableMain.Icon;
|
|
res.RedPointTicketThreshold = _tableCycle.RedDot;
|
|
var et = new DateTime();
|
|
var st = new DateTime();
|
|
try
|
|
{
|
|
et = DateTime.Parse((_tableEvent.TimeDefinition as LimitedTime).EndTime);
|
|
st = DateTime.Parse((_tableEvent.TimeDefinition as LimitedTime).StartTime);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.Log($"[EventBreak] {e.Message}\n{e.StackTrace}");
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
res.ExpiryTime = et;
|
|
res.StartTime = st;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
public EventBreakUIData GetUIData()
|
|
{
|
|
return new EventBreakUIData
|
|
{
|
|
MainPanelUrl = _tableMain.UIPanel,
|
|
InfoPanelUrl = _tableMain.InfoPanel,
|
|
ChainPackPanelUrl = _tableMain.ChainPackPanel,
|
|
NormalPackPanelUrl = _tableMain.PackPanel,
|
|
RewardPanelUrl = _tableMain.RewardPanel
|
|
};
|
|
}
|
|
|
|
public EventChainPackInfo GetPackData()
|
|
{
|
|
var chianList = _tables.TbEventPackManager[_tableMain.PackId].VIPPackList[0];
|
|
var expireTime = new DateTime();
|
|
try
|
|
{
|
|
expireTime = DateTime.Parse((_tableEvent.TimeDefinition as LimitedTime).EndTime);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.Log($"[EventBreak] {e.Message}\n{e.StackTrace}");
|
|
return null;
|
|
}
|
|
var chainListIdSet = chianList.ToHashSet();
|
|
var packs = _tables.TbPack.DataList.Where(p => chainListIdSet.Contains(p.ID)).ToArray();//?
|
|
return new EventChainPackInfo()
|
|
{
|
|
ChainList = chianList,
|
|
ExpireTime = expireTime,
|
|
Packs = packs,
|
|
RedPointKey = "eventbreak.pack"
|
|
};
|
|
}
|
|
|
|
public bool[] IsTicketEnough(int ticketCount)
|
|
{
|
|
return _tableTunnels.Select(t => ticketCount >= t.ItemRequired).ToArray();
|
|
}
|
|
|
|
public bool IsItemGem(ItemData item)
|
|
{
|
|
return _tableTunnels.Any(t => GetItemIdFromDrop(t.DropGem) == item.id);
|
|
}
|
|
|
|
public int GetGemIdx(int gemId)
|
|
{
|
|
int idx = 0;
|
|
while (idx < _tableTunnels.Length)
|
|
{
|
|
if (GetItemIdFromDrop(_tableTunnels[idx].DropGem) == gemId)
|
|
return idx;
|
|
idx++;
|
|
}
|
|
return idx;
|
|
}
|
|
|
|
public EventBreakNormalPackInfo GetNormalPackInfo()
|
|
{
|
|
var expireTime = new DateTime();
|
|
try
|
|
{
|
|
expireTime = DateTime.Parse((_tableEvent.TimeDefinition as LimitedTime).EndTime);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.Log($"[EventBreak] {e.Message}\n{e.StackTrace}");
|
|
return null;
|
|
}
|
|
var packList = _tables.TbEventPackManager[_tableMain.PackId2].VIPPackList[0];
|
|
return new EventBreakNormalPackInfo
|
|
{
|
|
EventId = _tableEvent.ID,
|
|
PackLeft = _tables.TbPack[packList[0]],
|
|
PackRight = _tables.TbPack[packList[1]],
|
|
ExpireTime = expireTime,
|
|
};
|
|
}
|
|
|
|
public bool IsItemFishCard(ItemData item)
|
|
{
|
|
return _tables.TbItem[item.id].Type == 5;
|
|
}
|
|
} |