修复已知问题

This commit is contained in:
2026-03-13 14:55:17 +08:00
parent aa44170d56
commit 777c58b812
11 changed files with 346 additions and 97 deletions
@@ -10,9 +10,17 @@ namespace GeometryTD.CustomComponent
public sealed class DropPoolRoller
{
private const float RarityCurveScalePhase = 30f;
private static readonly RarityType[] OrderedRarities =
{
RarityType.White,
RarityType.Green,
RarityType.Blue,
RarityType.Purple,
RarityType.Red
};
private readonly List<DROutGameDropPool> _eligibleRowBuffer = new();
private readonly Dictionary<RarityType, float> _rarityWeightBuffer = new();
private readonly float[] _rarityWeightBuffer = new float[OrderedRarities.Length];
private readonly IDataTable<DROutGameDropPool> _dropPoolTable;
public DropPoolRoller(IDataTable<DROutGameDropPool> dropPoolTable)
@@ -50,9 +58,8 @@ namespace GeometryTD.CustomComponent
int totalWeight = 0;
DROutGameDropPool fallbackRow = null;
for (int i = 0; i < _eligibleRowBuffer.Count; i++)
foreach (var row in _eligibleRowBuffer)
{
DROutGameDropPool row = _eligibleRowBuffer[i];
if (!IsEligibleAtPhase(row, selectedRarity, displayPhaseIndex))
{
continue;
@@ -107,9 +114,8 @@ namespace GeometryTD.CustomComponent
{
_eligibleRowBuffer.Clear();
for (int i = 0; i < allRows.Length; i++)
foreach (var row in allRows)
{
DROutGameDropPool row = allRows[i];
if (row == null)
{
continue;
@@ -131,15 +137,18 @@ namespace GeometryTD.CustomComponent
private RarityType RollRarity(int displayPhaseIndex, Random random)
{
_rarityWeightBuffer.Clear();
for (int i = 0; i < _rarityWeightBuffer.Length; i++)
{
_rarityWeightBuffer[i] = 0f;
}
float phaseT = Mathf.Clamp01((displayPhaseIndex - 1) / RarityCurveScalePhase);
for (int i = 0; i < _eligibleRowBuffer.Count; i++)
foreach (var row in _eligibleRowBuffer)
{
DROutGameDropPool row = _eligibleRowBuffer[i];
for (int rarityIndex = (int)RarityType.White; rarityIndex <= (int)RarityType.Red; rarityIndex++)
for (int rarityIndex = 0; rarityIndex < OrderedRarities.Length; rarityIndex++)
{
RarityType rarity = (RarityType)rarityIndex;
RarityType rarity = OrderedRarities[rarityIndex];
if (!IsEligibleAtPhase(row, rarity, displayPhaseIndex))
{
continue;
@@ -157,22 +166,14 @@ namespace GeometryTD.CustomComponent
continue;
}
float rarityWeight = rowWeight * curveWeight;
if (_rarityWeightBuffer.TryGetValue(rarity, out float existingWeight))
{
_rarityWeightBuffer[rarity] = existingWeight + rarityWeight;
}
else
{
_rarityWeightBuffer[rarity] = rarityWeight;
}
_rarityWeightBuffer[rarityIndex] += rowWeight * curveWeight;
}
}
float totalWeight = 0f;
foreach (var pair in _rarityWeightBuffer)
for (int rarityIndex = 0; rarityIndex < _rarityWeightBuffer.Length; rarityIndex++)
{
totalWeight += Mathf.Max(0f, pair.Value);
totalWeight += Mathf.Max(0f, _rarityWeightBuffer[rarityIndex]);
}
if (totalWeight <= 0f)
@@ -182,18 +183,21 @@ namespace GeometryTD.CustomComponent
float randomWeight = (float)(random.NextDouble() * totalWeight);
float cumulativeWeight = 0f;
foreach (var pair in _rarityWeightBuffer)
for (int rarityIndex = 0; rarityIndex < _rarityWeightBuffer.Length; rarityIndex++)
{
cumulativeWeight += Mathf.Max(0f, pair.Value);
cumulativeWeight += Mathf.Max(0f, _rarityWeightBuffer[rarityIndex]);
if (randomWeight <= cumulativeWeight)
{
return pair.Key;
return OrderedRarities[rarityIndex];
}
}
foreach (var pair in _rarityWeightBuffer)
for (int rarityIndex = 0; rarityIndex < _rarityWeightBuffer.Length; rarityIndex++)
{
return pair.Key;
if (_rarityWeightBuffer[rarityIndex] > 0f)
{
return OrderedRarities[rarityIndex];
}
}
return RarityType.None;
@@ -201,9 +205,9 @@ namespace GeometryTD.CustomComponent
private static bool IsEligibleAtPhase(DROutGameDropPool row, int displayPhaseIndex)
{
for (int rarityIndex = (int)RarityType.White; rarityIndex <= (int)RarityType.Red; rarityIndex++)
for (int rarityIndex = 0; rarityIndex < OrderedRarities.Length; rarityIndex++)
{
RarityType rarity = (RarityType)rarityIndex;
RarityType rarity = OrderedRarities[rarityIndex];
if (IsEligibleAtPhase(row, rarity, displayPhaseIndex))
{
return true;
@@ -12,11 +12,6 @@ namespace GeometryTD.CustomComponent
{
public sealed class InventoryGenerationComponent : GameFrameworkComponent
{
private int _runSeed;
private int _nodeSequenceIndex = -1;
private int _nextDropOrdinal;
private int _nextRewardOrdinal;
private readonly List<DRShopPrice> _shopPriceRows = new();
private IDataTable<DRShopPrice> _shopPriceTable;
private IDataTable<DROutGameDropPool> _dropPoolTable;
@@ -28,21 +23,17 @@ namespace GeometryTD.CustomComponent
private RewardCandidateBuilder _rewardCandidateBuilder;
private OutGameDropItemBuilder _outGameDropItemBuilder;
public void ConfigureRunContext(int runSeed, int sequenceIndex)
{
_runSeed = runSeed;
_nodeSequenceIndex = sequenceIndex;
_nextDropOrdinal = 0;
_nextRewardOrdinal = 0;
}
public List<GoodsItemRawData> BuildShopGoods(int goodsCount, int runSeed = 0, int sequenceIndex = -1)
{
EnsureShopBuilder();
return _shopGoodsBuilder.BuildGoods(goodsCount, runSeed, sequenceIndex);
}
public EnemyDropResult ResolveEnemyDrop(in EnemyDropContext context)
public EnemyDropResult ResolveEnemyDrop(
in EnemyDropContext context,
int runSeed,
int sequenceIndex,
ref int nextDropOrdinal)
{
DREnemy enemy = context.Enemy;
if (enemy == null)
@@ -56,9 +47,10 @@ namespace GeometryTD.CustomComponent
? Mathf.Clamp01(enemy.DropPercent * 0.01f)
: Mathf.Clamp01(enemy.DropPercent);
int dropOrdinal = AllocateDropOrdinal();
int dropOrdinal = nextDropOrdinal;
nextDropOrdinal++;
InventoryGenerationRandomContext randomContext =
new(_runSeed, _nodeSequenceIndex, InventoryTagSourceType.Drop, dropOrdinal);
new(runSeed, sequenceIndex, InventoryTagSourceType.Drop, dropOrdinal);
Random random = randomContext.CreateRandom();
if (enemy.DropGold > 0 && dropRate > 0f && random.NextDouble() <= dropRate)
@@ -84,15 +76,30 @@ namespace GeometryTD.CustomComponent
public IReadOnlyList<TowerCompItemData> BuildRewardCandidates(
int displayPhaseIndex,
LevelThemeType themeType,
int candidateCount)
int candidateCount,
int runSeed,
int sequenceIndex,
ref int nextRewardOrdinal)
{
RewardCandidateBuilder rewardCandidateBuilder = EnsureRewardCandidateBuilder();
return rewardCandidateBuilder.BuildCandidates(
int rewardOrdinal = nextRewardOrdinal;
IReadOnlyList<TowerCompItemData> candidates = rewardCandidateBuilder.BuildCandidates(
displayPhaseIndex,
themeType,
candidateCount,
CreateNextRewardRandomContext,
BuildRewardCandidateItem);
nextRewardOrdinal = rewardOrdinal;
return candidates;
InventoryGenerationRandomContext CreateNextRewardRandomContext()
{
return new InventoryGenerationRandomContext(
runSeed,
sequenceIndex,
InventoryTagSourceType.Reward,
rewardOrdinal++);
}
}
private void EnsureShopTables()
@@ -205,25 +212,6 @@ namespace GeometryTD.CustomComponent
return EnsureOutGameDropItemBuilder().TryBuildItem(selectedRow, selectedRarity, randomContext, out droppedItem);
}
private int AllocateDropOrdinal()
{
return _nextDropOrdinal++;
}
private int AllocateRewardOrdinal()
{
return _nextRewardOrdinal++;
}
private InventoryGenerationRandomContext CreateNextRewardRandomContext()
{
return new InventoryGenerationRandomContext(
_runSeed,
_nodeSequenceIndex,
InventoryTagSourceType.Reward,
AllocateRewardOrdinal());
}
private TowerCompItemData BuildRewardCandidateItem(
DROutGameDropPool row,
RarityType rarity,