public async Task <SimcSpell> GeneratePlayerSpellAsync(uint playerLevel, uint spellId) { var spellData = await _simcUtilityService.GetRawSpellDataAsync(spellId); var itemSpell = new SimcSpell() { SpellId = spellData.Id, Name = spellData.Name, School = spellData.School, MinRange = spellData.MinRange, MaxRange = spellData.MaxRange, Cooldown = spellData.Cooldown, Gcd = spellData.Gcd, Category = spellData.Category, CategoryCooldown = spellData.CategoryCooldown, Charges = spellData.Charges, ChargeCooldown = spellData.ChargeCooldown, MaxTargets = spellData.MaxTargets, Duration = spellData.Duration, MaxStacks = spellData.MaxStack, ProcChance = spellData.ProcChance, InternalCooldown = spellData.InternalCooldown, Rppm = spellData.Rppm, CastTime = spellData.CastTime }; // Add power costs foreach (var power in spellData.SpellPowers) { itemSpell.PowerCosts.Add(power.AuraId, power.PercentCost); } // Add the RPPM modifiers var rppmModifiers = await _simcUtilityService.GetSpellRppmModifiersAsync(spellData.Id); foreach (var modifier in rppmModifiers) { var newRppmModifier = new SimcSpellRppmModifier() { RppmIsHasted = modifier.ModifierType == RppmModifierType.RPPM_MODIFIER_HASTE, RppmIsSpecModified = modifier.ModifierType == RppmModifierType.RPPM_MODIFIER_SPEC, RppmCoefficient = modifier.Coefficient, RppmSpec = modifier.ModifierType == RppmModifierType.RPPM_MODIFIER_SPEC ? modifier.Type : 0 }; itemSpell.RppmModifiers.Add(newRppmModifier); } // Populate the spell effects foreach (var spellEffect in spellData.Effects) { // Populate the trigger spell if one exists. SimcSpell triggerSpell = null; if (spellEffect.TriggerSpellId > 0) { triggerSpell = await GeneratePlayerSpellAsync(playerLevel, spellEffect.TriggerSpellId); } // Get the scale budget var spellScalingClass = _simcUtilityService.GetScaleClass(spellEffect.ScalingType); double budget = 0; if (spellScalingClass != PlayerScaling.PLAYER_NONE) { // Cap the scaling level if needed if (spellData.MaxScalingLevel > 0) { playerLevel = Math.Min(playerLevel, (uint)spellData.MaxScalingLevel); } var scaleIndex = _simcUtilityService.GetClassId(spellScalingClass); var scaledValue = await _simcUtilityService.GetSpellScalingMultiplierAsync(scaleIndex, (int)playerLevel); budget = scaledValue; } itemSpell.Effects.Add(new SimcSpellEffect() { Id = spellEffect.Id, EffectIndex = spellEffect.EffectIndex, EffectType = spellEffect.EffectType, EffectSubType = spellEffect.EffectSubType, ScalingType = spellEffect.ScalingType, Coefficient = spellEffect.Coefficient, SpCoefficient = spellEffect.SpCoefficient, Delta = spellEffect.Delta, Amplitude = spellEffect.Amplitude, Radius = spellEffect.Radius, RadiusMax = spellEffect.RadiusMax, BaseValue = spellEffect.BaseValue, TriggerSpellId = spellEffect.TriggerSpellId, TriggerSpell = triggerSpell, ScaleBudget = budget }); } // Add the conduit info var conduitRanks = await _simcUtilityService.GetSpellConduitRanksAsync(spellData.Id); foreach (var rank in conduitRanks) { if (itemSpell.ConduitId == 0) { itemSpell.ConduitId = rank.ConduitId; } itemSpell.ConduitRanks.Add(rank.Rank, rank.Value); } return(itemSpell); }