示例#1
0
        public static Cycle GetCycle(bool needsDisplayCalculations, CastingState castingState, Cycle baseCycle)
        {
            Cycle cycle = Cycle.New(needsDisplayCalculations, castingState);
            cycle.Name = baseCycle.Name;
            cycle.AreaEffect = baseCycle.AreaEffect;

            // uptime
            float fightDuration = castingState.CalculationOptions.FightDuration;
            float effectDuration = Solver.MirrorImageDuration;
            float effectCooldown = Solver.MirrorImageCooldown;
            int activations = 0;
            float total;
            if (fightDuration < effectDuration)
            {
                total = fightDuration;
                activations = 1;
            }
            else
            {
                total = effectDuration;
                activations = 1;
                fightDuration -= effectDuration;
                int count = (int)(fightDuration / effectCooldown);
                total += effectDuration * count;
                activations += count;
                fightDuration -= effectCooldown * count;
                fightDuration -= effectCooldown - effectDuration;
                if (fightDuration > 0) 
                {
                    total += fightDuration;
                    activations++;
                }
            }          

            Spell mirrorImage = castingState.GetSpell(SpellId.MirrorImage);
           
            // activations * gcd in fightDuration
            float gcd = castingState.Solver.BaseGlobalCooldown + castingState.CalculationOptions.LatencyGCD;

            cycle.AddCycle(needsDisplayCalculations, baseCycle, (castingState.CalculationOptions.FightDuration - activations * gcd) / baseCycle.CastTime);
            cycle.CastTime += activations * gcd;
            cycle.costPerSecond += activations * (int)(0.10 * SpellTemplate.BaseMana[castingState.CalculationOptions.PlayerLevel]);
            //effectDamagePerSecond += (mirrorImage.AverageDamage + spellPower * mirrorImage.DamagePerSpellPower) / mirrorImage.CastTime;
            cycle.damagePerSecond += total * mirrorImage.AverageDamage / mirrorImage.CastTime;
            cycle.DpsPerSpellPower += total * mirrorImage.DamagePerSpellPower / mirrorImage.CastTime;
            cycle.Calculate();

            cycle.Note = baseCycle.Note;

            return cycle;
        }
示例#2
0
        public static Cycle GetCycle(bool needsDisplayCalculations, CastingState castingState, Cycle baseCycle)
        {
            Cycle cycle = Cycle.New(needsDisplayCalculations, castingState);
            cycle.Name = "Mage Ward+" + baseCycle.Name;

            Spell MageWard = castingState.GetSpell(SpellId.MageWard);

            // 1 ward every 30 seconds

            cycle.AreaEffect = baseCycle.AreaEffect;
            cycle.AddSpell(needsDisplayCalculations, MageWard, 1);
            cycle.AddCycle(needsDisplayCalculations, baseCycle, (30 - MageWard.CastTime) / baseCycle.CastTime);
            cycle.Calculate();

            cycle.Note = baseCycle.Note;

            return cycle;
        }
示例#3
0
        public static Cycle GetCycle(bool needsDisplayCalculations, CastingState castingState, Cycle baseCycle, bool averaged)
        {
            Cycle cycle = Cycle.New(needsDisplayCalculations, castingState);
            cycle.Name = baseCycle.Name;
            cycle.AreaEffect = baseCycle.AreaEffect;

            Spell FlameOrb = castingState.GetSpell(SpellId.FlameOrb);

            // 1 flame orb in 15 seconds
            // 1 flame orb in 60 seconds (averaged)

            cycle.AddSpell(needsDisplayCalculations, FlameOrb, 1);
            cycle.AddCycle(needsDisplayCalculations, baseCycle, ((averaged ? 60 : 15) - FlameOrb.CastTime) / baseCycle.CastTime);
            cycle.Calculate();

            cycle.Note = baseCycle.Note;

            return cycle;
        }
示例#4
0
        public static Cycle GetCycle(bool needsDisplayCalculations, CastingState castingState, Cycle baseCycle)
        {
            Cycle cycle = Cycle.New(needsDisplayCalculations, castingState);
            cycle.Name = baseCycle.Name;
            cycle.AreaEffect = baseCycle.AreaEffect;

            Spell Combustion = castingState.GetSpell(SpellId.Combustion);

            // 1 combustion in 10 seconds
            // the dot duplication is currently calculated in individual spells
            // consider splitting that out for display purposes

            cycle.AddSpell(needsDisplayCalculations, Combustion, 1);
            cycle.AddCycle(needsDisplayCalculations, baseCycle, (10 - Combustion.CastTime) / baseCycle.CastTime);
            cycle.Calculate();

            cycle.Note = baseCycle.Note;

            return cycle;
        }
示例#5
0
 public void AddToCycle(Solver solver, Cycle cycle, Spell rawSpell, float weight0, float weight1, float weight2, float weight3, float weight4)
 {
     MageTalents mageTalents = solver.MageTalents;
     float weight = weight0 + weight1 + weight2 + weight3 + weight4;
     cycle.CastTime += weight * rawSpell.CastTime;
     cycle.CastProcs += weight * rawSpell.CastProcs;
     cycle.CastProcs2 += weight * rawSpell.CastProcs2;
     cycle.NukeProcs += weight * rawSpell.NukeProcs;
     cycle.NukeProcs2 += weight * rawSpell.NukeProcs2;
     cycle.Ticks += weight * rawSpell.Ticks;
     cycle.HitProcs += weight * rawSpell.HitProcs;
     cycle.CritProcs += weight * rawSpell.CritProcs;
     cycle.TargetProcs += weight * rawSpell.TargetProcs;
     cycle.costPerSecond += weight * rawSpell.AverageCost;
     cycle.DamageProcs += weight * rawSpell.HitProcs;
     float multiplier = (weight * rawSpell.AdditiveSpellModifier + arcaneBlastDamageMultiplier * (weight1 + 2 * weight2 + 3 * weight3 + 4 * weight4)) / rawSpell.AdditiveSpellModifier;
     cycle.DpsPerSpellPower += multiplier * rawSpell.DamagePerSpellPower;
     //cycle.DpsPerMastery += multiplier * rawSpell.DamagePerMastery;
     cycle.damagePerSecond += multiplier * rawSpell.AverageDamage;
     cycle.threatPerSecond += multiplier * rawSpell.AverageThreat;
 }
示例#6
0
        public void AddToCycle(Solver solver, Cycle cycle, Spell rawSpell, float weight0, float weight1, float weight2, float weight3, float weight4)
        {
            MageTalents mageTalents = solver.MageTalents;
            float weight = weight0 + weight1 + weight2 + weight3 + weight4;
            float hasteMultiplier = (rawSpell.CastTime - rawSpell.Latency) / (rawSpell.BaseCastTime);
            // if some are below gcd then we have to use different calculations
            if (hasteMultiplier * (rawSpell.BaseCastTime - castTimeMultiplier * 0.4f) <= Math.Max(hasteMultiplier * rawSpell.GlobalCooldown, Spell.GlobalCooldownLimit))
            {
                float channelReduction;
                cycle.CastTime += weight0 * CalculateCastTime(cycle.CastingState, rawSpell.InterruptProtection, rawSpell.CritRate, false, rawSpell.BaseCastTime, out channelReduction);
                cycle.CastTime += weight1 * CalculateCastTime(cycle.CastingState, rawSpell.InterruptProtection, rawSpell.CritRate, false, rawSpell.BaseCastTime - castTimeMultiplier * 0.1f, out channelReduction);
                cycle.CastTime += weight2 * CalculateCastTime(cycle.CastingState, rawSpell.InterruptProtection, rawSpell.CritRate, false, rawSpell.BaseCastTime - castTimeMultiplier * 0.2f, out channelReduction);
                cycle.CastTime += weight3 * CalculateCastTime(cycle.CastingState, rawSpell.InterruptProtection, rawSpell.CritRate, false, rawSpell.BaseCastTime - castTimeMultiplier * 0.3f, out channelReduction);
                cycle.CastTime += weight4 * CalculateCastTime(cycle.CastingState, rawSpell.InterruptProtection, rawSpell.CritRate, false, rawSpell.BaseCastTime - castTimeMultiplier * 0.4f, out channelReduction);
            }
            else
            {
                cycle.CastTime += weight * rawSpell.CastTime - castTimeMultiplier * (weight1 * 0.1f + weight2 * 0.2f + weight3 * 0.3f + weight4 * 0.4f) * hasteMultiplier;
            }
            cycle.CastProcs += weight * rawSpell.CastProcs;
            cycle.CastProcs2 += weight * rawSpell.CastProcs2;
            cycle.NukeProcs += weight * rawSpell.NukeProcs;
            cycle.NukeProcs2 += weight * rawSpell.NukeProcs2;
            cycle.Ticks += weight * rawSpell.Ticks;
            cycle.HitProcs += weight * rawSpell.HitProcs;
            cycle.CritProcs += weight * rawSpell.CritProcs;
            cycle.TargetProcs += weight * rawSpell.TargetProcs;
            cycle.DamageProcs += weight * rawSpell.HitProcs;

            double roundCost = Math.Round(rawSpell.BaseCost * rawSpell.CostAmplifier);
            cycle.costPerSecond += (1 - solver.ClearcastingChance) * (weight0 * (float)Math.Floor(roundCost * rawSpell.CostModifier) + weight1 * (float)Math.Floor(roundCost * (rawSpell.CostModifier + arcaneBlastManaMultiplier)) + weight2 * (float)Math.Floor(roundCost * (rawSpell.CostModifier + 2 * arcaneBlastManaMultiplier)) + weight3 * (float)Math.Floor(roundCost * (rawSpell.CostModifier + 3 * arcaneBlastManaMultiplier)) + weight4 * (float)Math.Floor(roundCost * (rawSpell.CostModifier + 4 * arcaneBlastManaMultiplier)));
            cycle.costPerSecond -= weight * rawSpell.CritRate * rawSpell.BaseCost * 0.15f * mageTalents.MasterOfElements;
            //cycle.costPerSecond -= weight * BaseUntalentedCastTime / 60f * solver.BaseStats.ManaRestoreFromBaseManaPPM * solver.CalculationOptions.BaseMana;

            float multiplier = (weight * rawSpell.AdditiveSpellModifier + arcaneBlastDamageMultiplier * (weight1 + 2 * weight2 + 3 * weight3 + 4 * weight4)) / rawSpell.AdditiveSpellModifier;
            cycle.DpsPerSpellPower += multiplier * rawSpell.DamagePerSpellPower;
            cycle.DpsPerCrit += multiplier * rawSpell.DamagePerCrit;
            //cycle.DpsPerMastery += multiplier * rawSpell.DamagePerMastery;
            cycle.damagePerSecond += multiplier * rawSpell.AverageDamage;
            cycle.threatPerSecond += multiplier * rawSpell.AverageThreat;
        }
示例#7
0
        public Cycle GetCycle(CycleId cycleId)
        {
            //Cycle c = Cycles[(int)cycleId];
            //if (c != null) return c;
            Cycle c = null;
            //if (Cycles.TryGetValue((int)cycleId, out c)) return c;
            for (int i = 0; i < CyclesCount; i++)
            {
                Cycle cycle = Cycles[i];
                if (cycle.CycleId == cycleId) return cycle;
            }

            if (CalculationOptions.AdvancedHasteProcs)
            {
                c = GetAveragedHasteCycle(cycleId);
            }

            if (c == null)
            {
                c = GetNewCycle(cycleId);
            }
            if (c != null)
            {
                if (cycleId != CycleId.ArcaneManaNeutral) // if cycle is based on other cycles make sure we don't double count mixins
                {
                    if (UseMageWard)
                    {
                        c = MageWardCycle.GetCycle(Solver.NeedsDisplayCalculations, this, c);
                    }
                    if (CalculationOptions.MirrorImage == 1)
                    {
                        c = MirrorImageCycle.GetCycle(Solver.NeedsDisplayCalculations, this, c);
                    }
                    if (FlameOrb)
                    {
                        // add flame orb mix-in
                        c = FlameOrbCycle.GetCycle(Solver.NeedsDisplayCalculations, this, c, false);
                    }
                    if (CalculationOptions.PlayerLevel >= 81 && CalculationOptions.FlameOrb == 1)
                    {
                        c = FlameOrbCycle.GetCycle(Solver.NeedsDisplayCalculations, this, c, true);
                    }
                    if (Combustion)
                    {
                        // add combustion mix-in
                        c = CombustionCycle.GetCycle(Solver.NeedsDisplayCalculations, this, c);
                    }
                }

                c.CycleId = cycleId;
                //Cycles[(int)cycleId] = c;
                //Cycles.Add(c);
                if (CyclesCount >= Cycles.Length)
                {
                    int length = 2 * Cycles.Length;
                    Cycle[] destinationArray = new Cycle[length];
                    Array.Copy(Cycles, 0, destinationArray, 0, CyclesCount);
                    Cycles = destinationArray;
                }
                Cycles[CyclesCount++] = c;
            }

            return c;
        }
        private void CycleGeneratorComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            string armor;
            Solver solver;
            CalculationOptionsMage calculationOptions = character.CalculationOptions as CalculationOptionsMage;
            CalculationsMage calculations = (CalculationsMage)Calculations.Instance;

            switch ((string)((ComboBoxItem)CycleGeneratorComboBox.SelectedItem).Content)
            {
                case "Arcane":
                default:
                    armor = "Mage Armor";
                    solver = new Solver(character, calculationOptions, false, false, false, 0, armor, false, false, false, false, true, false, false);
                    solver.Initialize(null);
                    castingState = new CastingState(solver, 0, false, 0);
                    generator = new ArcaneCycleGeneratorBeta(castingState, true, false, false, false);
                    break;
                case "Arcane Dragonwrath":
                    armor = "Mage Armor";
                    solver = new Solver(character, calculationOptions, false, false, false, 0, armor, false, false, false, false, true, false, false);
                    solver.Initialize(null);
                    castingState = new CastingState(solver, 0, false, 0);
                    generator = new ArcaneCycleGeneratorLegendary(castingState, true, false, false, false);
                    break;
                case "Arcane Hyper Regen":
                    armor = "Mage Armor";
                    solver = new Solver(character, calculationOptions, false, false, false, 0, armor, false, false, false, false, true, false, false);
                    solver.Initialize(null);
                    castingState = new CastingState(solver, 0, false, 0);
                    generator = new ArcaneCycleGeneratorBeta(castingState, true, false, false, true);
                    break;
                case "Arcane AOE":
                    armor = "Mage Armor";
                    solver = new Solver(character, calculationOptions, false, false, false, 0, armor, false, false, false, false, true, false, false);
                    solver.Initialize(null);
                    castingState = new CastingState(solver, 0, false, 0);
                    generator = new ArcaneAOECycleGenerator(castingState, true, false, false);
                    break;
                case "Frost":
                    armor = "Molten Armor";
                    solver = new Solver(character, calculationOptions, false, false, false, 0, armor, false, false, false, false, true, false, false);
                    solver.Initialize(null);
                    castingState = new CastingState(solver, 0, false, 0);
                    generator = new FrostCycleGeneratorBeta(castingState, false, 0.0f, false, 0.0f);
                    break;
                case "Frost+Deep Freeze":
                    armor = "Molten Armor";
                    solver = new Solver(character, calculationOptions, false, false, false, 0, armor, false, false, false, false, true, false, false);
                    solver.Initialize(null);
                    castingState = new CastingState(solver, 0, false, 0);
                    generator = new FrostCycleGeneratorBeta(castingState, true, 30.0f, false, 0.0f);
                    break;
                case "Frost+Freeze":
                    armor = "Molten Armor";
                    solver = new Solver(character, calculationOptions, false, false, false, 0, armor, false, false, false, false, true, false, false);
                    solver.Initialize(null);
                    castingState = new CastingState(solver, 0, false, 0);
                    generator = new FrostCycleGeneratorBeta(castingState, false, 0.0f, true, 25.0f);
                    break;
                case "Frost+Freeze+Deep Freeze":
                    armor = "Molten Armor";
                    solver = new Solver(character, calculationOptions, false, false, false, 0, armor, false, false, false, false, true, false, false);
                    solver.Initialize(null);
                    castingState = new CastingState(solver, 0, false, 0);
                    generator = new FrostCycleGeneratorBeta(castingState, true, 30.0f, true, 25.0f);
                    break;
            }

            if (castingState == null || generator == null)
            {
                return;
            }

            if (character.Ranged != null)
            {
                wand = new WandTemplate(solver, (MagicSchool)character.Ranged.Item.DamageType, character.Ranged.Item.MinDamage, character.Ranged.Item.MaxDamage, character.Ranged.Item.Speed).GetSpell(castingState);
            }

            StringBuilder sb = new StringBuilder();

            sb.AppendLine(generator.StateDescription);

            sb.AppendLine();
            for (int i = 0; i < generator.ControlOptions.Length; i++)
            {
                sb.Append(i);
                sb.Append(": ");
                sb.Append(generator.StateList[Array.IndexOf(generator.ControlIndex, i)]);
                sb.Append(": ");
                List<int> keys = new List<int>();
                foreach (var kvp in generator.SpellMap[i])
                {
                    keys.Add(generator.SpellList.IndexOf(kvp.Key));
                }
                keys.Sort();
                foreach (var key in keys)
                {
                    sb.Append(key);
                    sb.Append("=");
                    sb.Append(generator.SpellList[key]);
                    sb.Append("  ");
                }
                sb.AppendLine();
            }

            sb.AppendLine();
            sb.AppendLine("Transitions:");
            sb.AppendLine();

            for (int i = 0; i < generator.ControlOptions.Length; i++)
            {
                foreach (var kvp in generator.SpellMap[i])
                {
                    sb.Append(i);
                    sb.Append(": ");
                    sb.Append(kvp.Key);
                    sb.Append(" => ");

                    List<int> list = new List<int>();
                    for (int s = 0; s < generator.ControlIndex.Length; s++)
                    {
                        if (generator.ControlIndex[s] == i)
                        {
                            foreach (CycleControlledStateTransition transition in generator.StateList[s].Transitions)
                            {
                                string n;
                                if (transition.Spell != null)
                                {
                                    n = transition.Spell.Name;
                                }
                                else
                                {
                                    n = "Pause";
                                }
                                if (n == kvp.Key)
                                {
                                    int target = generator.ControlIndex[transition.TargetState.Index];
                                    if (!list.Contains(target))
                                    {
                                        list.Add(target);
                                    }
                                }
                            }
                        }
                    }

                    list.Sort();
                    sb.Append(string.Join(",", list));

                    sb.AppendLine();
                }
            }


            Description.Text = sb.ToString();
            ControlString.Text = generator.ConvertCycleNameInternalToEasy(new string('0', generator.ControlOptions.Length));

            //ControlString.SelectAll();
            ControlString.Focus();

            Calculate_Click(null, null);        
        }
示例#9
0
 private void AddSpellsFromCycle(Cycle cycle, double weight)
 {
     foreach (var spell in cycle.Spell)
     {
         Spell.Add(new SpellData() { Spell = spell.Spell, DotUptime = spell.DotUptime, Weight = (float)weight * spell.Weight });
     }
 }
示例#10
0
 public void AddCycle(bool needsDisplayCalculations, Cycle cycle, double weight)
 {
     if (needsDisplayCalculations)
     {
         AddSpellsFromCycle(cycle, weight);
     }
     CastTime += weight * cycle.CastTime;
     CastProcs += weight * cycle.CastProcs;
     CastProcs2 += weight * cycle.CastProcs2;
     NukeProcs += weight * cycle.NukeProcs;
     NukeProcs2 += weight * cycle.NukeProcs2;
     Ticks += weight * cycle.Ticks;
     HitProcs += weight * cycle.HitProcs;
     CritProcs += weight * cycle.CritProcs;
     IgniteProcs += weight * cycle.IgniteProcs;
     DotProcs += weight * cycle.DotProcs;
     TargetProcs += weight * cycle.TargetProcs;
     DamageProcs += weight * cycle.DamageProcs;
     Absorbed += weight * cycle.Absorbed;
     costPerSecond += weight * cycle.CastTime * cycle.costPerSecond;
     damagePerSecond += weight * cycle.CastTime * cycle.damagePerSecond;
     threatPerSecond += weight * cycle.CastTime * cycle.threatPerSecond;
     DpsPerSpellPower += weight * cycle.CastTime * cycle.DpsPerSpellPower;
     DpsPerMastery += weight * cycle.CastTime * cycle.DpsPerMastery;
     DpsPerCrit += weight * cycle.CastTime * cycle.DpsPerCrit;
 }
示例#11
0
        public List<Cycle> Analyze(CastingState castingState, Cycle wand, System.ComponentModel.BackgroundWorker worker)
        {
            Dictionary<string, Cycle> cycleDict = new Dictionary<string, Cycle>();
            int j;
            // reset
            for (int i = 0; i < ControlValue.Length; i++)
            {
                ControlValue[i] = 0;
            }
            // count total cycles
            int total = 0;
            do
            {
                total++;
                j = ControlValue.Length - 1;
                ControlValue[j]++;
                while (ControlValue[j] >= ControlOptions[j])
                {
                    ControlValue[j] = 0;
                    j--;
                    if (j < 0)
                    {
                        break;
                    }
                    ControlValue[j]++;
                }
            } while (j >= 0);
            // reset
            for (int i = 0; i < ControlValue.Length; i++)
            {
                ControlValue[i] = 0;
            }
            int count = 0;
            do
            {
                if (worker != null && worker.CancellationPending)
                {
                    break;
                }
                if (worker != null && count % 100 == 0)
                {
                    worker.ReportProgress((100 * count) / total, count + "/" + total);
                }
                count++;
                string name = "";
                for (int i = 0; i < ControlValue.Length; i++)
                {
                    name += ControlValue[i].ToString();
                }
                GenericCycle generic = new GenericCycle(name, castingState, StateList, false);
                if (!cycleDict.ContainsKey(generic.SpellDistribution))
                {
                    cycleDict.Add(generic.SpellDistribution, generic);
                }
                // increment control
                j = ControlValue.Length - 1;
                ControlValue[j]++;
                while (ControlValue[j] >= ControlOptions[j])
                {
                    ControlValue[j] = 0;
                    j--;
                    if (j < 0)
                    {
                        break;
                    }
                    ControlValue[j]++;
                }
            } while (j >= 0);

            if (wand != null)
            {
                cycleDict["Wand"] = wand;
            }

            List<Cycle> cyclePalette = new List<Cycle>();

            double maxdps = 0;
            Cycle maxdpsCycle = null;
            foreach (Cycle cycle in cycleDict.Values)
            {
                if (cycle.DamagePerSecond > maxdps)
                {
                    maxdpsCycle = cycle;
                    maxdps = cycle.DamagePerSecond;
                }
            }

            cyclePalette.Add(maxdpsCycle);

            Cycle mindpmCycle;
            do
            {
                Cycle highdpsCycle = cyclePalette[cyclePalette.Count - 1];
            RESTART:
                mindpmCycle = null;
                double mindpm = double.PositiveInfinity;
                foreach (Cycle cycle in cycleDict.Values)
                {
                    double dpm = (cycle.DamagePerSecond - highdpsCycle.DamagePerSecond) / (cycle.ManaPerSecond - highdpsCycle.ManaPerSecond);
                    if (dpm > 0 && dpm < mindpm && cycle.ManaPerSecond < highdpsCycle.ManaPerSecond)
                    {
                        mindpm = dpm;
                        mindpmCycle = cycle;
                    }
                }
                if (mindpmCycle != null)
                {
                    // validate cycle pair theory
                    foreach (Cycle cycle in cycleDict.Values)
                    {
                        double dpm = (cycle.DamagePerSecond - mindpmCycle.DamagePerSecond) / (cycle.ManaPerSecond - mindpmCycle.ManaPerSecond);
                        if (cycle != highdpsCycle && cycle.DamagePerSecond > mindpmCycle.DamagePerSecond && dpm > mindpm + 0.000001)
                        {
                            highdpsCycle = cycle;
                            goto RESTART;
                        }
                    }
                    cyclePalette.Add(mindpmCycle);
                }
            } while (mindpmCycle != null);
            return cyclePalette;
        }
示例#12
0
 public List<Cycle> Analyze(CastingState castingState, Cycle wand)
 {
     return Analyze(castingState, wand, null);
 }