static private bool GenerateCardEffect(System.Random random, IHistogram model, CreatureModelIndex creatureModels, CardEffectDescription effectDesc, EffectType effect, double minBudget, double maxBudget, bool positive) { IProceduralEffectGenerator effectGen = ProceduralUtils.GetProceduralGenerator(effect); effectGen.SetupParameters(random, model, creatureModels, minBudget, maxBudget); effectDesc.effectType = effectGen.Generate(); // Adjust budgets minBudget /= effectDesc.effectType.PowerLevel(); maxBudget /= effectDesc.effectType.PowerLevel(); if (minBudget > maxBudget) { double temp = minBudget; minBudget = maxBudget; maxBudget = temp; } // Always allow for default targetting (multiplier 1.0x) if (maxBudget < 1.0) { maxBudget = 1.0; } TargetType targetType = TargetType.CREATURES; SortedSet <TargetType> validTargets = CardEnums.GetValidFlags <TargetType>(effect); SortedSet <TargettingType> allowableTargetting = new SortedSet <TargettingType>(); SortedSet <QualifierType> allowableQualifiers = new SortedSet <QualifierType>(); while (validTargets.Count > 0 && allowableTargetting.Count == 0) { targetType = ProceduralUtils.GetRandomValue(random, model, validTargets); validTargets.Remove(targetType); switch (effectDesc.effectType.GetAlignment()) { case Alignment.POSITIVE: if (positive) { allowableTargetting = ProceduralUtils.GetTargettingByAlignment(Alignment.POSITIVE); allowableQualifiers = ProceduralUtils.GetQualifiersByAlignment(Alignment.NEUTRAL); allowableQualifiers.UnionWith(ProceduralUtils.GetQualifiersByAlignment(Alignment.POSITIVE)); allowableQualifiers.IntersectWith(CardEnums.GetValidFlags <QualifierType>(targetType)); if (allowableQualifiers.Count > 0) { allowableTargetting.UnionWith(ProceduralUtils.GetTargettingByAlignment(Alignment.NEUTRAL)); } } else { allowableTargetting = ProceduralUtils.GetTargettingByAlignment(Alignment.NEGATIVE); allowableQualifiers = ProceduralUtils.GetQualifiersByAlignment(Alignment.NEGATIVE); allowableQualifiers.IntersectWith(CardEnums.GetValidFlags <QualifierType>(targetType)); if (allowableQualifiers.Count > 0) { allowableTargetting.UnionWith(ProceduralUtils.GetTargettingByAlignment(Alignment.NEUTRAL)); } } break; case Alignment.NEGATIVE: if (positive) { allowableTargetting = ProceduralUtils.GetTargettingByAlignment(Alignment.NEGATIVE); allowableQualifiers = ProceduralUtils.GetQualifiersByAlignment(Alignment.NEUTRAL); allowableQualifiers.UnionWith(ProceduralUtils.GetQualifiersByAlignment(Alignment.NEGATIVE)); allowableQualifiers.IntersectWith(CardEnums.GetValidFlags <QualifierType>(targetType)); if (allowableQualifiers.Count > 0) { allowableTargetting.UnionWith(ProceduralUtils.GetTargettingByAlignment(Alignment.NEUTRAL)); } } else { allowableTargetting = ProceduralUtils.GetTargettingByAlignment(Alignment.POSITIVE); allowableQualifiers = ProceduralUtils.GetQualifiersByAlignment(Alignment.POSITIVE); allowableQualifiers.IntersectWith(CardEnums.GetValidFlags <QualifierType>(targetType)); if (allowableQualifiers.Count > 0) { allowableTargetting.UnionWith(ProceduralUtils.GetTargettingByAlignment(Alignment.NEUTRAL)); } } break; default: if (positive) { allowableTargetting = new SortedSet <TargettingType>((TargettingType[])Enum.GetValues(typeof(TargettingType))); allowableQualifiers = new SortedSet <QualifierType>((QualifierType[])Enum.GetValues(typeof(QualifierType))); allowableQualifiers.IntersectWith(CardEnums.GetValidFlags <QualifierType>(targetType)); } else { allowableTargetting = new SortedSet <TargettingType>(); } break; } allowableTargetting.IntersectWith(CardEnums.GetValidFlags <TargettingType>(targetType)); allowableTargetting.IntersectWith(CardEnums.GetValidFlags <TargettingType>(effectDesc.triggerCondition)); // Special case // Up to can never be a downside because you can choose 0 targets if (!positive) { allowableTargetting.Remove(TargettingType.UP_TO_TARGET); allowableTargetting.Remove(TargettingType.UP_TO_TARGET_ALLY); allowableTargetting.Remove(TargettingType.UP_TO_TARGET_ENEMY); } } // Could not find any valid targetting to achieve the desired alignment if (allowableTargetting.Count == 0) { SortedSet <TargetType> targets = CardEnums.GetValidFlags <TargetType>(effect); Debug.Log("Wasn't able to generate targets for effect <" + effect.ToString() + ">"); return(false); } // Attempt to narrow down the targetting pool SortedSet <TargettingType> targettingWithinBudget = new SortedSet <TargettingType>(allowableTargetting.Intersect(ProceduralUtils.GetTargettingWithinBudget(maxBudget))); if (targettingWithinBudget.Count > 0) { allowableTargetting = targettingWithinBudget; } else { Debug.Log("Unable to narrow down targetting types for <" + effect.ToString() + ", " + targetType.ToString() + "> for budget " + maxBudget); } TargettingType targettingType = ProceduralUtils.GetRandomValue(random, model, allowableTargetting); IProceduralTargettingGenerator targettingGen = ProceduralUtils.GetProceduralGenerator(targettingType); targettingGen.SetupParameters(targetType, random, model, minBudget, maxBudget); effectDesc.targettingType = targettingGen.Generate(); // Adjust budgets minBudget /= effectDesc.targettingType.PowerLevel(); maxBudget /= effectDesc.targettingType.PowerLevel(); if (minBudget > maxBudget) { double temp = minBudget; minBudget = maxBudget; maxBudget = temp; } if (effectDesc.targettingType is IQualifiableTargettingDescription qualifiable) { // Generate a possible qualifier // Attempt to narrow down the qualifier pool SortedSet <QualifierType> qualifiersWithinBudget = new SortedSet <QualifierType>(allowableQualifiers.Intersect(ProceduralUtils.GetQualifiersWithinBudget(maxBudget))); if (targettingWithinBudget.Count > 0) { allowableQualifiers = qualifiersWithinBudget; } else { Debug.Log("Unable to narrow down qualifier types for <" + effect.ToString() + ", " + targetType.ToString() + "> for budget " + maxBudget); } QualifierType qualifier = ProceduralUtils.GetRandomValue(random, model, allowableQualifiers); if (qualifier != QualifierType.NONE) { IProceduralQualifierGenerator qualifierGen = ProceduralUtils.GetProceduralGenerator(qualifier); qualifierGen.SetupParameters(random, model, minBudget, maxBudget); qualifiable.qualifier = qualifierGen.Generate(); } } return(true); }