修复已知问题
This commit is contained in:
+9
-2
@@ -100,7 +100,8 @@ namespace GeometryTD.CustomComponent
|
||||
_runtime.NodeId = nodeId;
|
||||
_runtime.NodeType = nodeType;
|
||||
_runtime.SequenceIndex = sequenceIndex;
|
||||
GameEntry.InventoryGeneration.ConfigureRunContext(runSeed, sequenceIndex);
|
||||
_runtime.NextDropOrdinal = 0;
|
||||
_runtime.NextRewardOrdinal = 0;
|
||||
_runtime.CombatRunResourceStore.InitializeForCombat(level);
|
||||
for (int i = 0; i < phases.Count; i++)
|
||||
{
|
||||
@@ -201,7 +202,13 @@ namespace GeometryTD.CustomComponent
|
||||
enemy,
|
||||
_runtime.PhaseLoopRuntime.DisplayPhaseIndex,
|
||||
_coordinator.ResolveCurrentThemeType());
|
||||
EnemyDropResult result = GameEntry.InventoryGeneration.ResolveEnemyDrop(context);
|
||||
int nextDropOrdinal = _runtime.NextDropOrdinal;
|
||||
EnemyDropResult result = GameEntry.InventoryGeneration.ResolveEnemyDrop(
|
||||
context,
|
||||
_runtime.RunSeed,
|
||||
_runtime.SequenceIndex,
|
||||
ref nextDropOrdinal);
|
||||
_runtime.NextDropOrdinal = nextDropOrdinal;
|
||||
_runtime.CombatRunResourceStore.AddEnemyDefeatedReward(result.Coin, result.Gold);
|
||||
_runtime.CombatRunResourceStore.AddEnemyDefeatedLoot(result.LootItem);
|
||||
}
|
||||
|
||||
+2
@@ -60,6 +60,8 @@ namespace GeometryTD.CustomComponent
|
||||
_runtime.NodeId = 0;
|
||||
_runtime.NodeType = RunNodeType.None;
|
||||
_runtime.SequenceIndex = -1;
|
||||
_runtime.NextDropOrdinal = 0;
|
||||
_runtime.NextRewardOrdinal = 0;
|
||||
}
|
||||
|
||||
public void CleanupAllCombatEntities()
|
||||
|
||||
+2
@@ -34,5 +34,7 @@ namespace GeometryTD.CustomComponent
|
||||
public int NodeId { get; set; }
|
||||
public RunNodeType NodeType { get; set; }
|
||||
public int SequenceIndex { get; set; }
|
||||
public int NextDropOrdinal { get; set; }
|
||||
public int NextRewardOrdinal { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
+8
-2
@@ -36,6 +36,9 @@ namespace GeometryTD.CustomComponent
|
||||
CombatSettlementContext settlementContext,
|
||||
int displayPhaseIndex,
|
||||
LevelThemeType themeType,
|
||||
int runSeed,
|
||||
int sequenceIndex,
|
||||
ref int nextRewardOrdinal,
|
||||
RewardSelectFormUseCase rewardSelectFormUseCase,
|
||||
Action<RewardSelectItemRawData> onRewardSelected,
|
||||
Action onGiveUp)
|
||||
@@ -48,7 +51,10 @@ namespace GeometryTD.CustomComponent
|
||||
IReadOnlyList<TowerCompItemData> candidateItems = GameEntry.InventoryGeneration.BuildRewardCandidates(
|
||||
displayPhaseIndex,
|
||||
themeType,
|
||||
RewardSelectDisplayCount);
|
||||
RewardSelectDisplayCount,
|
||||
runSeed,
|
||||
sequenceIndex,
|
||||
ref nextRewardOrdinal);
|
||||
if (candidateItems == null || candidateItems.Count <= 0)
|
||||
{
|
||||
settlementContext.Flags.ShouldOpenRewardSelection = false;
|
||||
@@ -60,7 +66,7 @@ namespace GeometryTD.CustomComponent
|
||||
candidateItems,
|
||||
displayCount: RewardSelectDisplayCount,
|
||||
refreshCost: 0,
|
||||
allowRefreshOnce: false,
|
||||
allowRotateOnce: false,
|
||||
allowGiveUp: false,
|
||||
tipText: "基地满血奖励:请选择 1 个组件");
|
||||
|
||||
|
||||
+7
@@ -16,16 +16,23 @@ namespace GeometryTD.CustomComponent
|
||||
}
|
||||
|
||||
Coordinator.EnsureRewardSelectFormUseCaseBound();
|
||||
int nextRewardOrdinal = Runtime.NextRewardOrdinal;
|
||||
if (!Runtime.CombatSettlementService.TryPrepareRewardSelection(
|
||||
Runtime.SettlementContext,
|
||||
Runtime.PhaseLoopRuntime.DisplayPhaseIndex,
|
||||
Coordinator.ResolveCurrentThemeType(),
|
||||
Runtime.RunSeed,
|
||||
Runtime.SequenceIndex,
|
||||
ref nextRewardOrdinal,
|
||||
Runtime.RewardSelectFormUseCase,
|
||||
Coordinator.OnFullBaseHpRewardSelected,
|
||||
Coordinator.OnFullBaseHpRewardGiveUp))
|
||||
{
|
||||
Coordinator.ChangeState(new CombatFinishFormState(Runtime, Coordinator));
|
||||
return;
|
||||
}
|
||||
|
||||
Runtime.NextRewardOrdinal = nextRewardOrdinal;
|
||||
}
|
||||
|
||||
public override void OnExit()
|
||||
|
||||
@@ -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;
|
||||
|
||||
+25
-37
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user