geometry-tower-defense-base/src-ref/CustomComponent/InventoryGeneration/RewardCandidateBuilder.cs

101 lines
3.4 KiB
C#

using System;
using System.Collections.Generic;
using GeometryTD.DataTable;
using GeometryTD.Definition;
using UnityEngine;
using Random = System.Random;
namespace GeometryTD.CustomComponent
{
public sealed class RewardCandidateBuilder
{
private readonly DropPoolRoller _dropPoolRoller;
public RewardCandidateBuilder(DropPoolRoller dropPoolRoller)
{
_dropPoolRoller = dropPoolRoller;
}
public IReadOnlyList<TowerCompItemData> BuildCandidates(
int displayPhaseIndex,
LevelThemeType themeType,
int candidateCount,
Func<InventoryGenerationRandomContext> createRandomContext,
Func<DROutGameDropPool, RarityType, InventoryGenerationRandomContext, TowerCompItemData> buildRewardItem)
{
int resolvedCount = Mathf.Max(0, candidateCount);
if (resolvedCount <= 0)
{
return Array.Empty<TowerCompItemData>();
}
List<TowerCompItemData> candidates = new List<TowerCompItemData>(resolvedCount);
HashSet<long> selectedPoolEntryKeys = new HashSet<long>();
int maxAttempts = Mathf.Max(resolvedCount * 6, resolvedCount);
int phaseIndex = Mathf.Max(1, displayPhaseIndex);
int attempts = 0;
while (candidates.Count < resolvedCount && attempts < maxAttempts)
{
attempts++;
InventoryGenerationRandomContext randomContext = createRandomContext();
Random random = randomContext.CreateRandom();
if (!_dropPoolRoller.TryRollRow(
phaseIndex,
themeType,
random,
out DROutGameDropPool selectedRow,
out RarityType selectedRarity) || selectedRow == null)
{
break;
}
if (!selectedPoolEntryKeys.Add(BuildSelectionKey(selectedRow.Id, selectedRarity)))
{
continue;
}
TowerCompItemData candidate = buildRewardItem(selectedRow, selectedRarity, randomContext);
if (candidate == null)
{
continue;
}
candidates.Add(candidate);
}
attempts = 0;
while (candidates.Count < resolvedCount && attempts < maxAttempts)
{
attempts++;
InventoryGenerationRandomContext randomContext = createRandomContext();
Random random = randomContext.CreateRandom();
if (!_dropPoolRoller.TryRollRow(
phaseIndex,
themeType,
random,
out DROutGameDropPool selectedRow,
out RarityType selectedRarity) || selectedRow == null)
{
break;
}
TowerCompItemData candidate = buildRewardItem(selectedRow, selectedRarity, randomContext);
if (candidate == null)
{
continue;
}
candidates.Add(candidate);
}
return candidates;
}
private static long BuildSelectionKey(int rowId, RarityType rarity)
{
return ((long)rowId << 32) | (uint)rarity;
}
}
}