Make pricing system aware of SpawnItemsOnUseComponent (#13626)
* Make appraisal tool aware of SpawnItemsOnUseComponent * Move to SpawnItemsOnUseSystem
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
using System.Linq;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Serialization.Manager;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Shared.Storage;
|
||||
@@ -62,7 +62,7 @@ public struct EntitySpawnEntry
|
||||
|
||||
public static class EntitySpawnCollection
|
||||
{
|
||||
private sealed class OrGroup
|
||||
public sealed class OrGroup
|
||||
{
|
||||
public List<EntitySpawnEntry> Entries { get; set; } = new();
|
||||
public float CumulativeProbability { get; set; } = 0f;
|
||||
@@ -84,34 +84,16 @@ public static class EntitySpawnCollection
|
||||
IoCManager.Resolve(ref random);
|
||||
|
||||
var spawned = new List<string?>();
|
||||
var orGroupedSpawns = new Dictionary<string, OrGroup>();
|
||||
var ungrouped = CollectOrGroups(entries, out var orGroupedSpawns);
|
||||
|
||||
// collect groups together, create singular items that pass probability
|
||||
foreach (var entry in entries)
|
||||
foreach (var entry in ungrouped)
|
||||
{
|
||||
// Handle "Or" groups
|
||||
if (!string.IsNullOrEmpty(entry.GroupId))
|
||||
{
|
||||
if (!orGroupedSpawns.TryGetValue(entry.GroupId, out OrGroup? orGroup))
|
||||
{
|
||||
orGroup = new();
|
||||
orGroupedSpawns.Add(entry.GroupId, orGroup);
|
||||
}
|
||||
|
||||
orGroup.Entries.Add(entry);
|
||||
orGroup.CumulativeProbability += entry.SpawnProbability;
|
||||
continue;
|
||||
}
|
||||
|
||||
// else
|
||||
// Check random spawn
|
||||
// ReSharper disable once CompareOfFloatsByEqualityOperator
|
||||
if (entry.SpawnProbability != 1f && !random.Prob(entry.SpawnProbability)) continue;
|
||||
if (entry.SpawnProbability != 1f && !random.Prob(entry.SpawnProbability))
|
||||
continue;
|
||||
|
||||
var amount = entry.Amount;
|
||||
|
||||
if (entry.MaxAmount > amount)
|
||||
amount = random.Next(amount, entry.MaxAmount);
|
||||
var amount = (int) entry.GetAmount(random);
|
||||
|
||||
for (var i = 0; i < amount; i++)
|
||||
{
|
||||
@@ -119,25 +101,25 @@ public static class EntitySpawnCollection
|
||||
}
|
||||
}
|
||||
|
||||
// handle orgroup spawns
|
||||
foreach (var spawnValue in orGroupedSpawns.Values)
|
||||
// Handle OrGroup spawns
|
||||
foreach (var spawnValue in orGroupedSpawns)
|
||||
{
|
||||
// For each group use the added cumulative probability to roll a double in that range
|
||||
double diceRoll = random.NextDouble() * spawnValue.CumulativeProbability;
|
||||
var diceRoll = random.NextDouble() * spawnValue.CumulativeProbability;
|
||||
|
||||
// Add the entry's spawn probability to this value, if equals or lower, spawn item, otherwise continue to next item.
|
||||
var cumulative = 0.0;
|
||||
|
||||
foreach (var entry in spawnValue.Entries)
|
||||
{
|
||||
cumulative += entry.SpawnProbability;
|
||||
if (diceRoll > cumulative) continue;
|
||||
if (diceRoll > cumulative)
|
||||
continue;
|
||||
|
||||
// Dice roll succeeded, add item and break loop
|
||||
var amount = (int) entry.GetAmount(random);
|
||||
|
||||
var amount = entry.Amount;
|
||||
|
||||
if (entry.MaxAmount > amount)
|
||||
amount = random.Next(amount, entry.MaxAmount);
|
||||
|
||||
for (var index = 0; index < amount; index++)
|
||||
for (var i = 0; i < amount; i++)
|
||||
{
|
||||
spawned.Add(entry.PrototypeId);
|
||||
}
|
||||
@@ -148,4 +130,58 @@ public static class EntitySpawnCollection
|
||||
|
||||
return spawned;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Collects all entries that belong together in an OrGroup, and then returns the leftover ungrouped entries.
|
||||
/// </summary>
|
||||
/// <param name="entries">A list of entries that will be collected into OrGroups.</param>
|
||||
/// <param name="orGroups">A list of entries collected into OrGroups.</param>
|
||||
/// <returns>A list of entries that are not in an OrGroup.</returns>
|
||||
public static List<EntitySpawnEntry> CollectOrGroups(IEnumerable<EntitySpawnEntry> entries, out List<OrGroup> orGroups)
|
||||
{
|
||||
var ungrouped = new List<EntitySpawnEntry>();
|
||||
var orGroupsDict = new Dictionary<string, OrGroup>();
|
||||
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
// If the entry is in a group, collect it into an OrGroup. Otherwise just add it to a list of ungrouped
|
||||
// entries.
|
||||
if (!string.IsNullOrEmpty(entry.GroupId))
|
||||
{
|
||||
// Create a new OrGroup if necessary
|
||||
if (!orGroupsDict.TryGetValue(entry.GroupId, out var orGroup))
|
||||
{
|
||||
orGroup = new OrGroup();
|
||||
orGroupsDict.Add(entry.GroupId, orGroup);
|
||||
}
|
||||
|
||||
orGroup.Entries.Add(entry);
|
||||
orGroup.CumulativeProbability += entry.SpawnProbability;
|
||||
}
|
||||
else
|
||||
{
|
||||
ungrouped.Add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
// We don't really need the group IDs anymore, so just return the values as a list
|
||||
orGroups = orGroupsDict.Values.ToList();
|
||||
|
||||
return ungrouped;
|
||||
}
|
||||
|
||||
public static double GetAmount(this EntitySpawnEntry entry, IRobustRandom? random = null, bool getAverage = false)
|
||||
{
|
||||
// Max amount is less or equal than amount, so just return the amount
|
||||
if (entry.MaxAmount <= entry.Amount)
|
||||
return entry.Amount;
|
||||
|
||||
// If we want the average, just calculate the expected amount
|
||||
if (getAverage)
|
||||
return (entry.Amount + entry.MaxAmount) / 2.0;
|
||||
|
||||
// Otherwise get a random value in between
|
||||
IoCManager.Resolve(ref random);
|
||||
return random.Next(entry.Amount, entry.MaxAmount);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user