122 lines
3.9 KiB
C#
122 lines
3.9 KiB
C#
using Godot;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
public static class GateRequirementGenerator
|
|
{
|
|
public static void ApplyGateRequirements(Layer[] layers)
|
|
{
|
|
List<string> availableResources = new List<string>();
|
|
|
|
foreach (Layer layer in layers)
|
|
{
|
|
GateRequirementOptions options = BuildRequirementOptions(layer, availableResources);
|
|
ApplyLayerRequirements(layer, options);
|
|
}
|
|
}
|
|
|
|
private static GateRequirementOptions BuildRequirementOptions(Layer layer, List<string> availableResources)
|
|
{
|
|
GateRequirementOptions options = new GateRequirementOptions();
|
|
|
|
foreach (string resource in layer.currentResources)
|
|
{
|
|
if (availableResources.Contains(resource)) continue;
|
|
|
|
availableResources.Add(resource);
|
|
}
|
|
|
|
bool addedNewItem;
|
|
do
|
|
{
|
|
addedNewItem = false;
|
|
|
|
foreach (ItemData item in GameData.availableItems.Values)
|
|
{
|
|
if (options.PossibleIngredients.Any(existing => existing.Id == item.Id)) continue;
|
|
if (!CanCraftItem(item, availableResources)) continue;
|
|
|
|
options.PossibleIngredients.Add(item);
|
|
availableResources.Add(item.Id);
|
|
options.LowestCraftTime = Mathf.Min(options.LowestCraftTime, item.CraftTime);
|
|
options.HighestCraftTime = Mathf.Max(options.HighestCraftTime, item.CraftTime);
|
|
|
|
addedNewItem = true;
|
|
}
|
|
} while (addedNewItem);
|
|
|
|
return options;
|
|
}
|
|
|
|
private static bool CanCraftItem(ItemData item, List<string> availableResources)
|
|
{
|
|
return item.Inputs.All(input => availableResources.Contains(input.Item));
|
|
}
|
|
|
|
private static void ApplyLayerRequirements(Layer layer, GateRequirementOptions options)
|
|
{
|
|
double goalCraftTime = GetGoalCraftTime(layer, options);
|
|
int ingredientAmount = Mathf.Clamp(1 + layer.level / 3, 1, 4);
|
|
float craftTimeModifier = 0f;
|
|
|
|
for (int i = 0; i < ingredientAmount; i++)
|
|
{
|
|
List<ItemData> validIngredients = GetValidIngredients(layer, options, goalCraftTime, craftTimeModifier);
|
|
if (validIngredients.Count == 0)
|
|
{
|
|
i--;
|
|
craftTimeModifier += 0.05f;
|
|
continue;
|
|
}
|
|
|
|
AddGateIngredient(layer, validIngredients);
|
|
craftTimeModifier = 0f;
|
|
}
|
|
}
|
|
|
|
private static double GetGoalCraftTime(Layer layer, GateRequirementOptions options)
|
|
{
|
|
return Mathf.Lerp(
|
|
options.LowestCraftTime,
|
|
options.HighestCraftTime,
|
|
Mathf.Clamp(layer.level / (float)GameData.ruinSize, 0, 1)
|
|
);
|
|
}
|
|
|
|
private static List<ItemData> GetValidIngredients(
|
|
Layer layer,
|
|
GateRequirementOptions options,
|
|
double goalCraftTime,
|
|
float craftTimeModifier
|
|
)
|
|
{
|
|
double craftTimeLower = goalCraftTime - goalCraftTime * craftTimeModifier;
|
|
double craftTimeUpper = goalCraftTime + goalCraftTime * craftTimeModifier;
|
|
|
|
return options.PossibleIngredients
|
|
.Where(item =>
|
|
item.CraftTime >= craftTimeLower &&
|
|
item.CraftTime <= craftTimeUpper &&
|
|
!layer.gateIngredients.Any(ingredient => ingredient.Item == item.Id))
|
|
.ToList();
|
|
}
|
|
|
|
private static void AddGateIngredient(Layer layer, List<ItemData> validIngredients)
|
|
{
|
|
ItemData item = validIngredients[GameData.rand.Next(validIngredients.Count)];
|
|
|
|
layer.gateIngredients.Add(new Ingredient
|
|
{
|
|
Item = item.Id,
|
|
Amount = GameData.rand.Next(3 + layer.level * 2, 9 + layer.level * 4)
|
|
});
|
|
}
|
|
|
|
private class GateRequirementOptions
|
|
{
|
|
public List<ItemData> PossibleIngredients = new List<ItemData>();
|
|
public double HighestCraftTime = 0;
|
|
public double LowestCraftTime = double.MaxValue;
|
|
}
|
|
}
|