using Godot; using System.Collections.Generic; using System.Linq; public static class GateRequirementGenerator { public static void ApplyGateRequirements(Layer[] layers) { List availableResources = new List(); foreach (Layer layer in layers) { GateRequirementOptions options = BuildRequirementOptions(layer, availableResources); ApplyLayerRequirements(layer, options); } } private static GateRequirementOptions BuildRequirementOptions(Layer layer, List 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 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 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 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 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 PossibleIngredients = new List(); public double HighestCraftTime = 0; public double LowestCraftTime = double.MaxValue; } }