RiftMayhem/Assets/Scripts/Drops/EquipmentDropTable.cs

270 lines
8.8 KiB
C#

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<WeightedEquipmentType> possibleEquipment = new List<WeightedEquipmentType>();
[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<CoinDrop>();
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<EquippableItemDrop>();
if (dropComponent != null)
{
dropComponent.itemDrop = item;
}
else
{
Debug.LogError("Equipment drop prefab doesn't have EquippableItemDrop component!");
Destroy(dropObject);
}
}
private int GetPlayerLevel()
{
RiftPlayer player = FindFirstObjectByType<RiftPlayer>();
if (player == null) return GameDifficultyController.Instance.GetCurrentDifficultyLevel() + 1;
return player.character.level.currentLevel;
}
#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<EquippableItemDrop>() == 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
}