270 lines
8.8 KiB
C#
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
|
|
} |