equip type definition updates for stat rules

This commit is contained in:
Pedro Gomes 2025-09-25 17:21:01 +01:00
parent b0c635aaf5
commit 415e29576b
4 changed files with 379 additions and 71 deletions

View File

@ -25,16 +25,11 @@ public class EquippableItemTypeDefinition : ScriptableObject
[SerializeField] private string resourcesPath = ""; // e.g., "Armor/Helmets"
[Header("Stat Rules")]
[SerializeField] private StatDefinition[] allowedStats = new StatDefinition[0];
[SerializeField] private StatDefinition[] forbiddenStats = new StatDefinition[0];
[SerializeField] private StatDefinition[] mandatoryStats = new StatDefinition[0];
[SerializeField] private StatWeightModifier[] statWeightModifiers = new StatWeightModifier[0];
[SerializeField] private StatAvailabilityWeightAndRolls[] statRules = new StatAvailabilityWeightAndRolls[0];
[Header("Generation Settings")]
[SerializeField] private bool canBeGenerated = true;
[SerializeField] private float baseGenerationWeight = 1f;
[SerializeField] private int minStatRolls = 1;
[SerializeField] private int maxStatRolls = 3;
// Public read-only properties
public string EquipmentKey => equipmentKey;
@ -48,14 +43,9 @@ public class EquippableItemTypeDefinition : ScriptableObject
public Sprite[] AvailableIcons => availableIcons;
public bool UseResourcesFolder => useResourcesFolder;
public string ResourcesPath => resourcesPath;
public StatDefinition[] AllowedStats => allowedStats;
public StatDefinition[] ForbiddenStats => forbiddenStats;
public StatDefinition[] MandatoryStats => mandatoryStats;
public StatWeightModifier[] StatWeightModifiers => statWeightModifiers;
public StatAvailabilityWeightAndRolls[] StatRules => statRules;
public bool CanBeGenerated => canBeGenerated;
public float BaseGenerationWeight => baseGenerationWeight;
public int MinStatRolls => minStatRolls;
public int MaxStatRolls => maxStatRolls;
// Cached icons from resources
private Sprite[] resourceIcons;
@ -86,17 +76,6 @@ public class EquippableItemTypeDefinition : ScriptableObject
shortName = displayName.Length > 8 ? displayName.Substring(0, 8) : displayName;
}
// Ensure min/max stat rolls make sense
if (minStatRolls > maxStatRolls)
{
maxStatRolls = minStatRolls;
}
if (minStatRolls < 0)
{
minStatRolls = 0;
}
// Ensure base generation weight is positive
if (baseGenerationWeight < 0f)
{
@ -108,6 +87,73 @@ public class EquippableItemTypeDefinition : ScriptableObject
{
Debug.LogWarning($"EquipmentTypeDefinition '{name}': Using resources folder, manual icon array will be ignored.");
}
// Auto-populate stat rules if array is empty or incomplete
ValidateStatRules();
}
private void ValidateStatRules()
{
#if UNITY_EDITOR
// Only populate in editor, not at runtime
if (Application.isPlaying) return;
// Load all stat definitions from Resources
StatDefinition[] allStats = Resources.LoadAll<StatDefinition>("StatDefinitions");
if (allStats.Length == 0) return;
// Check if we need to update the stat rules array
bool needsUpdate = false;
HashSet<StatDefinition> existingStats = new HashSet<StatDefinition>(statRules.Select(r => r.stat).Where(s => s != null));
foreach (var stat in allStats)
{
if (!existingStats.Contains(stat))
{
needsUpdate = true;
break;
}
}
if (needsUpdate)
{
// Create new array with all stats
List<StatAvailabilityWeightAndRolls> newStatRules = new List<StatAvailabilityWeightAndRolls>();
// Keep existing rules that are still valid
foreach (var existingRule in statRules)
{
if (existingRule.stat != null && allStats.Contains(existingRule.stat))
{
newStatRules.Add(existingRule);
}
}
// Add missing stats with default values
foreach (var stat in allStats)
{
if (!existingStats.Contains(stat))
{
newStatRules.Add(new StatAvailabilityWeightAndRolls
{
stat = stat,
isAllowed = true, // Default to allowed
isMandatory = false,
weightMultiplier = stat.DefaultWeight,
minStatRoll = 0f,
maxStatRoll = 100f
});
}
}
// Sort alphabetically by stat key for consistency
newStatRules.Sort((a, b) => string.Compare(a.stat.StatKey, b.stat.StatKey, System.StringComparison.OrdinalIgnoreCase));
statRules = newStatRules.ToArray();
Debug.Log($"EquipmentTypeDefinition '{name}': Updated stat rules with {newStatRules.Count} stats");
}
#endif
}
// Utility methods
@ -152,32 +198,41 @@ public class EquippableItemTypeDefinition : ScriptableObject
public bool IsStatAllowed(StatDefinition stat)
{
// Check if explicitly forbidden
if (forbiddenStats.Contains(stat))
return false;
// If allowedStats is specified, stat must be in it
if (allowedStats.Length > 0)
return allowedStats.Contains(stat);
// If no explicit allowed list, allow by default (unless forbidden)
return true;
var rule = statRules.FirstOrDefault(r => r.stat == stat);
return rule?.isAllowed ?? false; // Default to not allowed if no rule found
}
public bool IsStatMandatory(StatDefinition stat)
{
return mandatoryStats.Contains(stat);
var rule = statRules.FirstOrDefault(r => r.stat == stat);
return rule?.isMandatory ?? false;
}
public float GetStatWeightMultiplier(StatDefinition stat)
{
var modifier = statWeightModifiers.FirstOrDefault(m => m.stat == stat);
return modifier != null ? modifier.weightMultiplier : 1f;
var rule = statRules.FirstOrDefault(r => r.stat == stat);
return rule?.weightMultiplier ?? 1f;
}
public (float min, float max) GetStatRollRange(StatDefinition stat)
{
var rule = statRules.FirstOrDefault(r => r.stat == stat);
if (rule != null)
return (rule.minStatRoll, rule.maxStatRoll);
return (0f, 100f); // Default range
}
public int GetRandomStatRollCount()
{
return Random.Range(minStatRolls, maxStatRolls + 1);
// Count how many stats are allowed and could potentially roll
int allowedStatsCount = statRules.Count(r => r.isAllowed);
int mandatoryStatsCount = statRules.Count(r => r.isMandatory);
// Ensure we at least roll mandatory stats, but allow for more
int minRolls = Mathf.Max(1, mandatoryStatsCount);
int maxRolls = Mathf.Max(minRolls, Mathf.Min(allowedStatsCount, GameConstants.EquipmentStatRules.ItemTotalStats));
return Random.Range(minRolls, maxRolls + 1);
}
private void LoadIconsFromResources()
@ -201,6 +256,17 @@ public class EquippableItemTypeDefinition : ScriptableObject
var icon = GetRandomIcon();
Debug.Log($"{name}: Random icon = {(icon != null ? icon.name : "None")}");
}
[ContextMenu("Update Stat Rules")]
private void ForceUpdateStatRules()
{
#if UNITY_EDITOR
// Force update by clearing and repopulating
statRules = new StatAvailabilityWeightAndRolls[0];
ValidateStatRules();
UnityEditor.EditorUtility.SetDirty(this);
#endif
}
}
[System.Serializable]
@ -209,6 +275,7 @@ public class StatWeightModifier
public StatDefinition stat;
public float weightMultiplier = 1f;
}
[System.Serializable]
public class StatAvailabilityWeightAndRolls
{

View File

@ -23,36 +23,144 @@ MonoBehaviour:
availableIcons: []
useResourcesFolder: 1
resourcesPath: Armor/Helmets
allowedStats:
- {fileID: 11400000, guid: 8a59fbc0a19857b48a0789d4b4115ea4, type: 2}
- {fileID: 11400000, guid: 6093187f425cccc43b5fa829db293893, type: 2}
- {fileID: 11400000, guid: e6da017ba613adf4d82d9b6a214c6c7c, type: 2}
- {fileID: 11400000, guid: 79006f60ae538ad4ca179ee739f39232, type: 2}
- {fileID: 11400000, guid: f1c964d3ea9c1d349bb5111b11accade, type: 2}
- {fileID: 11400000, guid: a50126674c634ef49b4986605ee42baa, type: 2}
- {fileID: 11400000, guid: ec3548202e941294da429cd3083937c0, type: 2}
forbiddenStats:
- {fileID: 11400000, guid: de18f1cd5c7345243a127dbf50a1c714, type: 2}
- {fileID: 11400000, guid: 88595dcd80f9c614b8bd7d8218fb5951, type: 2}
- {fileID: 11400000, guid: 0886a83f3dd15114487850e54518829d, type: 2}
- {fileID: 11400000, guid: d318a3662a3ccf04f9f193a818cc3361, type: 2}
- {fileID: 11400000, guid: a19f2ac40579e5d4aa0713f43fcfa276, type: 2}
- {fileID: 11400000, guid: 332d0dbee9590e24e9ad5166dd75ef69, type: 2}
- {fileID: 11400000, guid: aa214c2ad3c962447b486ecf16c9c950, type: 2}
- {fileID: 11400000, guid: 8dcb92f2ee1026241a3bc051a42f91f5, type: 2}
- {fileID: 11400000, guid: 4e90e0c058763a143b3ec657351fcace, type: 2}
- {fileID: 11400000, guid: d9561a8f85fc81f43961fa58de0cd088, type: 2}
- {fileID: 11400000, guid: 1407df369cf076445a1619597e085e1c, type: 2}
mandatoryStats:
- {fileID: 11400000, guid: 8a59fbc0a19857b48a0789d4b4115ea4, type: 2}
statWeightModifiers:
statRules:
- stat: {fileID: 11400000, guid: d9561a8f85fc81f43961fa58de0cd088, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: 8a59fbc0a19857b48a0789d4b4115ea4, type: 2}
isAllowed: 1
isMandatory: 1
weightMultiplier: 2
- stat: {fileID: 11400000, guid: 6093187f425cccc43b5fa829db293893, type: 2}
weightMultiplier: 1.5
minStatRoll: 1
maxStatRoll: 3
- stat: {fileID: 11400000, guid: de18f1cd5c7345243a127dbf50a1c714, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: 0886a83f3dd15114487850e54518829d, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: 332d0dbee9590e24e9ad5166dd75ef69, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: 8dcb92f2ee1026241a3bc051a42f91f5, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: 4e90e0c058763a143b3ec657351fcace, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: ec3548202e941294da429cd3083937c0, type: 2}
isAllowed: 1
isMandatory: 0
weightMultiplier: 0.25
minStatRoll: 0.01
maxStatRoll: 0.05
- stat: {fileID: 11400000, guid: d318a3662a3ccf04f9f193a818cc3361, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: a19f2ac40579e5d4aa0713f43fcfa276, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: d52b20e3f02ba8946bf37a7470beafd0, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: aa214c2ad3c962447b486ecf16c9c950, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: 63eee8f1286035f4a80356bcfad289b6, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: 1e63fcf4ac1c02c4e9b9bd62f0243f05, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: 79006f60ae538ad4ca179ee739f39232, type: 2}
isAllowed: 1
isMandatory: 0
weightMultiplier: 1
minStatRoll: 1
maxStatRoll: 2
- stat: {fileID: 11400000, guid: 6093187f425cccc43b5fa829db293893, type: 2}
isAllowed: 1
isMandatory: 0
weightMultiplier: 1.25
minStatRoll: 1
maxStatRoll: 3
- stat: {fileID: 11400000, guid: a50126674c634ef49b4986605ee42baa, type: 2}
isAllowed: 1
isMandatory: 0
weightMultiplier: 1
minStatRoll: 1
maxStatRoll: 2
- stat: {fileID: 11400000, guid: e6da017ba613adf4d82d9b6a214c6c7c, type: 2}
isAllowed: 1
isMandatory: 0
weightMultiplier: 1
minStatRoll: 1
maxStatRoll: 3
- stat: {fileID: 11400000, guid: f1c964d3ea9c1d349bb5111b11accade, type: 2}
isAllowed: 1
isMandatory: 0
weightMultiplier: 1
minStatRoll: 1
maxStatRoll: 3
- stat: {fileID: 11400000, guid: 1407df369cf076445a1619597e085e1c, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: 599541ff1aaa6c848a732f9a97e5f1c4, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: 7895ba1f0b9a732488642046ee62c8a6, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: 88595dcd80f9c614b8bd7d8218fb5951, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
canBeGenerated: 1
baseGenerationWeight: 1
minStatRolls: 1
maxStatRolls: 3

View File

@ -23,11 +23,144 @@ MonoBehaviour:
availableIcons: []
useResourcesFolder: 1
resourcesPath: Armor/Shoulders
allowedStats: []
forbiddenStats: []
mandatoryStats: []
statWeightModifiers: []
statRules:
- stat: {fileID: 11400000, guid: d9561a8f85fc81f43961fa58de0cd088, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: 8a59fbc0a19857b48a0789d4b4115ea4, type: 2}
isAllowed: 1
isMandatory: 1
weightMultiplier: 2
minStatRoll: 1
maxStatRoll: 3
- stat: {fileID: 11400000, guid: de18f1cd5c7345243a127dbf50a1c714, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: 0886a83f3dd15114487850e54518829d, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: 332d0dbee9590e24e9ad5166dd75ef69, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: 8dcb92f2ee1026241a3bc051a42f91f5, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: 4e90e0c058763a143b3ec657351fcace, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: ec3548202e941294da429cd3083937c0, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0.01
maxStatRoll: 0.05
- stat: {fileID: 11400000, guid: d318a3662a3ccf04f9f193a818cc3361, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: a19f2ac40579e5d4aa0713f43fcfa276, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: d52b20e3f02ba8946bf37a7470beafd0, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: aa214c2ad3c962447b486ecf16c9c950, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: 63eee8f1286035f4a80356bcfad289b6, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: 1e63fcf4ac1c02c4e9b9bd62f0243f05, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: 79006f60ae538ad4ca179ee739f39232, type: 2}
isAllowed: 1
isMandatory: 0
weightMultiplier: 1
minStatRoll: 1
maxStatRoll: 2
- stat: {fileID: 11400000, guid: 6093187f425cccc43b5fa829db293893, type: 2}
isAllowed: 1
isMandatory: 0
weightMultiplier: 1.25
minStatRoll: 1
maxStatRoll: 3
- stat: {fileID: 11400000, guid: a50126674c634ef49b4986605ee42baa, type: 2}
isAllowed: 1
isMandatory: 0
weightMultiplier: 1
minStatRoll: 1
maxStatRoll: 2
- stat: {fileID: 11400000, guid: e6da017ba613adf4d82d9b6a214c6c7c, type: 2}
isAllowed: 1
isMandatory: 0
weightMultiplier: 1
minStatRoll: 1
maxStatRoll: 3
- stat: {fileID: 11400000, guid: f1c964d3ea9c1d349bb5111b11accade, type: 2}
isAllowed: 1
isMandatory: 0
weightMultiplier: 1
minStatRoll: 1
maxStatRoll: 3
- stat: {fileID: 11400000, guid: 1407df369cf076445a1619597e085e1c, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: 599541ff1aaa6c848a732f9a97e5f1c4, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: 7895ba1f0b9a732488642046ee62c8a6, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
- stat: {fileID: 11400000, guid: 88595dcd80f9c614b8bd7d8218fb5951, type: 2}
isAllowed: 0
isMandatory: 0
weightMultiplier: 0
minStatRoll: 0
maxStatRoll: 100
canBeGenerated: 1
baseGenerationWeight: 1
minStatRolls: 1
maxStatRolls: 3

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: b7d57fbc93b54ee4cb5a2dc567254d6a
guid: 9044a1de874c1294bbd261141af44093
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000