using Kryz.CharacterStats.Examples; using System.Collections.Generic; using System.Linq; using UnityEngine; [System.Serializable] public class WeightedEquipmentType { public EquippableItemTypeDefinition equipmentType; public float weight = 1f; public DifficultyLevels lowestPossibleDifficulty = DifficultyLevels.E; public DifficultyLevels highestPossibleDifficulty = DifficultyLevels.SS; public int LowestDifficultyDrop => (int)lowestPossibleDifficulty; public int HighestDifficultyDrop => (int)highestPossibleDifficulty; } public class EquipmentDropTable : MonoBehaviour { [Header("Drop Settings")] [SerializeField] private int dropChance = 50; // Percentage chance to drop equipment [SerializeField] private EquippableItemGenerator.ItemTier minTier = EquippableItemGenerator.ItemTier.Common; [SerializeField] private EquippableItemGenerator.ItemTier maxTier = EquippableItemGenerator.ItemTier.Rare; [Header("Equipment Types")] [SerializeField] private List possibleEquipment = new List(); [Header("Coin Drop")] [SerializeField] private GameObject coinPrefab; [SerializeField] private int coinAmount = 10; [SerializeField] private GameEvent_Int onCoinDrop; [Header("Prefabs")] [SerializeField] private GameObject equipmentDropPrefab; // Should have EquippableItemDrop component [Header("Level Scaling")] [SerializeField] private bool usePlayerLevel = true; [SerializeField] private int fixedLevel = 1; public void DropLoot() { Vector3 dropPosition = transform.position; dropPosition.y = 0f; // Always drop coins DropCoins(dropPosition); // Roll for equipment drop if (ShouldDropEquipment()) { DropRandomEquipment(dropPosition); } } private void DropCoins(Vector3 position) { if (coinPrefab == null) return; GameObject coinDrop = Instantiate(coinPrefab, position, transform.rotation); CoinDrop coinDropComponent = coinDrop.GetComponent(); if (coinDropComponent != null) { // Apply difficulty scaling if available int finalAmount = coinAmount; if (GameDifficultyController.Instance != null) { finalAmount = Mathf.RoundToInt(coinAmount * (1 + GameConstants.GameBalancing.IncreasedCoinDropBasedOnDifficultyMultiplier * GameDifficultyController.Instance.GetCurrentDifficultyLevel())); } coinDropComponent.Init(finalAmount); onCoinDrop?.Raise(finalAmount); } } private bool ShouldDropEquipment() { if (possibleEquipment.Count == 0) return false; // Apply difficulty scaling to drop chance if available float finalDropChance = dropChance; if (GameDifficultyController.Instance != null) { finalDropChance *= (1 + GameConstants.GameBalancing.IncreasedItemDropBasedOnDifficultyMultiplier * GameDifficultyController.Instance.GetCurrentDifficultyLevel()); } return Random.Range(0f, 100f) < finalDropChance; } private void DropRandomEquipment(Vector3 position) { // Select random equipment type based on weights EquippableItemTypeDefinition selectedType = GetRandomWeightedEquipmentType(); if (selectedType == null) return; // Generate random tier within range EquippableItemGenerator.ItemTier randomTier = GetRandomTier(); // Determine item level int itemLevel = usePlayerLevel ? GetPlayerLevel() : fixedLevel; // Generate the item using your existing generator EquippableItemInstance generatedItem = EquippableItemGenerator.Instance.GenerateFromEquipmentType( selectedType, randomTier, itemLevel ); // Create the interactable drop SpawnEquipmentDrop(generatedItem, position); Debug.Log($"Dropped {randomTier} {selectedType.GetDisplayName()} (Level {itemLevel})"); } private EquippableItemTypeDefinition GetRandomWeightedEquipmentType() { int currentDifficulty = GameDifficultyController.Instance?.GetCurrentDifficultyLevel() ?? 0; // Filter equipment types for current difficulty and null checks var validEquipment = possibleEquipment.Where(e => e.equipmentType != null && e.LowestDifficultyDrop <= currentDifficulty && e.HighestDifficultyDrop >= currentDifficulty ).ToList(); if (validEquipment.Count == 0) { Debug.LogWarning($"No equipment available for difficulty level {currentDifficulty}"); return null; } // Calculate total weight for valid equipment float totalWeight = validEquipment.Sum(e => e.weight); if (totalWeight <= 0) { // If no weights, pick randomly from valid equipment return validEquipment[Random.Range(0, validEquipment.Count)].equipmentType; } // Weighted random selection float randomValue = Random.Range(0f, totalWeight); float currentWeight = 0f; foreach (var equipment in validEquipment) { currentWeight += equipment.weight; if (randomValue <= currentWeight) { return equipment.equipmentType; } } return validEquipment[0].equipmentType; // Fallback } private EquippableItemGenerator.ItemTier GetRandomTier() { int minTierValue = (int)minTier; int maxTierValue = (int)maxTier; int randomTierValue = Random.Range(minTierValue, maxTierValue + 1); return (EquippableItemGenerator.ItemTier)randomTierValue; } private void SpawnEquipmentDrop(EquippableItemInstance item, Vector3 position) { if (equipmentDropPrefab == null) { Debug.LogError("Equipment drop prefab is not assigned!"); return; } GameObject dropObject = Instantiate(equipmentDropPrefab, position, transform.rotation); EquippableItemDrop dropComponent = dropObject.GetComponent(); if (dropComponent != null) { dropComponent.itemDrop = item; } else { Debug.LogError("Equipment drop prefab doesn't have EquippableItemDrop component!"); Destroy(dropObject); } } private int GetPlayerLevel() { // Replace this with your actual player level system // For example: return PlayerController.Instance.Level; return 1; // Placeholder } #region Editor Testing [ContextMenu("Test Drop")] private void TestDrop() { if (Application.isPlaying) { DropLoot(); } else { Debug.Log("Test drop only works in play mode"); } } [ContextMenu("Validate Setup")] private void ValidateSetup() { int issues = 0; int currentDifficulty = GameDifficultyController.Instance?.GetCurrentDifficultyLevel() ?? 0; if (possibleEquipment.Count == 0) { Debug.LogWarning("No equipment types configured"); issues++; } int validForCurrentDifficulty = 0; foreach (var equipment in possibleEquipment) { if (equipment.equipmentType == null) { Debug.LogWarning("Found null equipment type reference"); issues++; } else if (equipment.LowestDifficultyDrop <= currentDifficulty && equipment.HighestDifficultyDrop >= currentDifficulty) { validForCurrentDifficulty++; } } if (validForCurrentDifficulty == 0 && possibleEquipment.Count > 0) { Debug.LogWarning($"No equipment types are valid for current difficulty level {currentDifficulty}"); issues++; } if (equipmentDropPrefab == null) { Debug.LogWarning("Equipment drop prefab not assigned"); issues++; } else if (equipmentDropPrefab.GetComponent() == null) { Debug.LogWarning("Equipment drop prefab missing EquippableItemDrop component"); issues++; } if (coinPrefab == null) { Debug.LogWarning("Coin prefab not assigned"); issues++; } if (issues == 0) { Debug.Log($"Equipment drop table setup is valid! {validForCurrentDifficulty} equipment types available for current difficulty."); } else { Debug.LogWarning($"Found {issues} setup issues"); } } #endregion }