using Kryz.CharacterStats.Examples; using System.Collections.Generic; using UnityEngine; [CreateAssetMenu(fileName = "New Stat Rule Set", menuName = "RiftMayhem/Stat Rule Set")] public class StatRuleSet : ScriptableObject { [Header("Rule Set Info")] public string ruleSetName = "Default Rules"; [TextArea(2, 4)] public string description = "Describe what this rule set does"; [Header("Equipment Type Rules")] public List equipmentRules = new List(); [Header("Weapon Type Rules")] public List weaponRules = new List(); [Header("Global Stat Relationships")] public List relationshipRules = new List(); [Header("Tier Rules")] public List tierRules = new List(); // Method to get effective weights after applying all rules public EquippableItemGenerator.StatWeights GetEffectiveWeights(EquipmentType equipmentType, WeaponType? weaponType, EquippableItemGenerator.ItemTier tier, HashSet alreadyRolledStats = null) { // Start with base weights (you might want to store base weights in the rule set too) EquippableItemGenerator.StatWeights effectiveWeights = new EquippableItemGenerator.StatWeights(); // Apply equipment type rules ApplyEquipmentRules(effectiveWeights, equipmentType); // Apply weapon type rules if it's a weapon if (weaponType.HasValue) { ApplyWeaponRules(effectiveWeights, weaponType.Value); } // Apply tier rules ApplyTierRules(effectiveWeights, tier); // Apply relationship rules based on already rolled stats if (alreadyRolledStats != null) { ApplyRelationshipRules(effectiveWeights, alreadyRolledStats); } return effectiveWeights; } private void ApplyEquipmentRules(EquippableItemGenerator.StatWeights weights, EquipmentType equipmentType) { foreach (var rule in equipmentRules) { if (rule.equipmentType == equipmentType) { rule.ApplyRule(weights); break; // Only apply the first matching rule } } } private void ApplyWeaponRules(EquippableItemGenerator.StatWeights weights, WeaponType weaponType) { foreach (var rule in weaponRules) { if (rule.weaponType == weaponType) { rule.ApplyRule(weights); break; } } } private void ApplyTierRules(EquippableItemGenerator.StatWeights weights, EquippableItemGenerator.ItemTier tier) { foreach (var rule in tierRules) { if (rule.tier == tier) { rule.ApplyRule(weights); } } } private void ApplyRelationshipRules(EquippableItemGenerator.StatWeights weights, HashSet alreadyRolledStats) { foreach (var rule in relationshipRules) { if (alreadyRolledStats.Contains(rule.triggerStat)) { rule.ApplyRule(weights); } } } } [System.Serializable] public class EquipmentTypeRule { public EquipmentType equipmentType; public string ruleName = ""; [Header("Stat Modifications")] public StatModifierRule[] statModifiers; [Header("Mandatory Stats")] public CharacterStatType[] mandatoryStats; [Header("Forbidden Stats")] public CharacterStatType[] forbiddenStats; public void ApplyRule(EquippableItemGenerator.StatWeights weights) { // Apply forbidden stats (set to 0) foreach (CharacterStatType forbiddenStat in forbiddenStats) { SetStatWeight(weights, forbiddenStat, 0f); } // Apply stat modifications foreach (var modifier in statModifiers) { float currentWeight = GetStatWeight(weights, modifier.statType); float newWeight = modifier.modificationType switch { ModificationType.Set => modifier.value, ModificationType.Multiply => currentWeight * modifier.value, ModificationType.Add => currentWeight + modifier.value, _ => currentWeight }; SetStatWeight(weights, modifier.statType, newWeight); } } private float GetStatWeight(EquippableItemGenerator.StatWeights weights, CharacterStatType statType) { return statType switch { CharacterStatType.AttackDamage => weights.attackDamage, CharacterStatType.SpellDamage => weights.spellDamage, CharacterStatType.CritChance => weights.critChance, CharacterStatType.CritDamage => weights.critDamage, CharacterStatType.MaxHealth => weights.maxHealth, CharacterStatType.Armor => weights.armor, CharacterStatType.MagicResistance => weights.magicResistance, CharacterStatType.DodgeChance => weights.dodgeChance, CharacterStatType.BlockChance => weights.blockChance, CharacterStatType.BlockEffectiveness => weights.blockEffectiveness, CharacterStatType.HealthRegen => weights.healthRegen, CharacterStatType.MaxMana => weights.maxMana, CharacterStatType.ManaRegen => weights.manaRegen, CharacterStatType.AttackSpeed => weights.attackSpeed, CharacterStatType.AreaEffectiveness => weights.areaEffectiveness, CharacterStatType.CooldownReduction => weights.cooldownReduction, CharacterStatType.MovementSpeed => weights.movementSpeed, CharacterStatType.ReputationGainIncrease => weights.reputationGain, CharacterStatType.GoldCostReduction => weights.goldCostReduction, // Note: Cunning, Flow, Presence, AuraPower don't seem to be in StatWeights // You might need to add these to StatWeights or handle them separately _ => 0f }; } private void SetStatWeight(EquippableItemGenerator.StatWeights weights, CharacterStatType statType, float value) { switch (statType) { case CharacterStatType.AttackDamage: weights.attackDamage = value; break; case CharacterStatType.SpellDamage: weights.spellDamage = value; break; case CharacterStatType.CritChance: weights.critChance = value; break; case CharacterStatType.CritDamage: weights.critDamage = value; break; case CharacterStatType.MaxHealth: weights.maxHealth = value; break; case CharacterStatType.Armor: weights.armor = value; break; case CharacterStatType.MagicResistance: weights.magicResistance = value; break; case CharacterStatType.DodgeChance: weights.dodgeChance = value; break; case CharacterStatType.BlockChance: weights.blockChance = value; break; case CharacterStatType.BlockEffectiveness: weights.blockEffectiveness = value; break; case CharacterStatType.HealthRegen: weights.healthRegen = value; break; case CharacterStatType.MaxMana: weights.maxMana = value; break; case CharacterStatType.ManaRegen: weights.manaRegen = value; break; case CharacterStatType.AttackSpeed: weights.attackSpeed = value; break; case CharacterStatType.AreaEffectiveness: weights.areaEffectiveness = value; break; case CharacterStatType.CooldownReduction: weights.cooldownReduction = value; break; case CharacterStatType.MovementSpeed: weights.movementSpeed = value; break; case CharacterStatType.ReputationGainIncrease: weights.reputationGain = value; break; case CharacterStatType.GoldCostReduction: weights.goldCostReduction = value; break; } } } [System.Serializable] public class WeaponTypeRule { public WeaponType weaponType; public string ruleName = ""; public StatModifierRule[] statModifiers; public CharacterStatType[] mandatoryStats; public CharacterStatType[] forbiddenStats; public void ApplyRule(EquippableItemGenerator.StatWeights weights) { // Same implementation as EquipmentTypeRule // (Could extract to a base class if you want) } } [System.Serializable] public class StatRelationshipRule { public CharacterStatType triggerStat; public string ruleName = ""; [Header("When this stat is present, modify these:")] public StatModifierRule[] statModifications; public void ApplyRule(EquippableItemGenerator.StatWeights weights) { foreach (var modifier in statModifications) { // Apply modification logic here } } } [System.Serializable] public class TierRule { public EquippableItemGenerator.ItemTier tier; public string ruleName = ""; public StatModifierRule[] statModifiers; public CharacterStatType[] unlockedStats; // Stats that become available at this tier public void ApplyRule(EquippableItemGenerator.StatWeights weights) { foreach (var modifier in statModifiers) { // Apply tier-based modifications } } } [System.Serializable] public class StatModifierRule { public CharacterStatType statType; public ModificationType modificationType; public float value; [Header("Optional: Condition")] public bool useCondition = false; public string conditionDescription = ""; } public enum ModificationType { Set, // Set weight to exact value Multiply, // Multiply current weight Add // Add to current weight }