예제 #1
0
        // This technique assumes that if you pick a random time during filler
        // spell(s) or downtime, the "cooldowns" remaining on the rest of your
        // spells are all equally likely to be at any value. This is unrealistic
        // (e.g. it's impossible for them all to be at their full value), but
        // for some classes is a reasonable approximation.
        private void RecordCollisionDelays(CastingState state)
        {
            float pRemaining = 1f;

            foreach (Spell spell in Priorities)
            {
                float p = spell.GetQueueProbability(state);
                if (p == 0f)
                {
                    continue;
                }

                List <CastingState> nextStates =
                    spell.SimulateCast(state, p * pRemaining);
                foreach (CastingState nextState in nextStates)
                {
                    if (nextState.Probability > .0001f)
                    {
                        // Only calculate if the probabilty of the state is
                        // large enough to make any difference at all.
                        RecordCollisionDelays(nextState);
                    }
                }
                if (p == 1f)
                {
                    return;
                }

                pRemaining *= 1f - p;
            }

            //System.Console.WriteLine(state.ToString());
        }
예제 #2
0
        private void RecordCollisionDelays(CastingState state)
        {
            // This technique assumes that if you pick a random time during filler
            // spell(s) or downtime, the "cooldowns" remaining on the rest of your
            // spells are all equally likely to be at any value. This is unrealistic
            // (e.g. it's impossible for them all to be at their full value), but
            // for some classes is a reasonable approximation.
            float pRemaining = 1f;

            foreach (Spell spell in Priorities)
            {
                float p = spell.GetQueueProbability(state);
                if (p == 0f)
                {
                    continue;
                }

                List <CastingState> nextStates = spell.SimulateCast(state, p * pRemaining);
                foreach (CastingState nextState in nextStates)
                {
                    if (nextState.Probability > .0001f)
                    {
                        // Only calculate if the probabilty of the state is
                        // large enough to make any difference at all.
                        RecordCollisionDelays(nextState);
                    }
                }
                if (p == 1f)
                {
                    return;
                }

                pRemaining *= 1f - p;
            }
        }
예제 #3
0
        public CastingState(CastingState toCopy)
        {
            Mommy            = toCopy.Mommy;
            Probability      = toCopy.Probability;
            Cooldowns        = new Dictionary <Spell, float>(toCopy.Cooldowns);
            SeriesPriorities = new List <int>(toCopy.SeriesPriorities);
            Series           = new List <Spell>(toCopy.Series);
            SeriesTimes      = new List <float>(toCopy.SeriesTimes);
            SeriesHits       = new List <bool>(toCopy.SeriesHits);

            BackdraftCharges  = toCopy.BackdraftCharges;
            MoltenCoreCharges = toCopy.MoltenCoreCharges;
        }
예제 #4
0
        public CastingState(CastingState toCopy)
        {
            Mommy = toCopy.Mommy;
            Probability = toCopy.Probability;
            Cooldowns = new Dictionary<Spell, float>(toCopy.Cooldowns);
            SeriesPriorities = new List<int>(toCopy.SeriesPriorities);
            Series = new List<Spell>(toCopy.Series);
            SeriesTimes = new List<float>(toCopy.SeriesTimes);
            SeriesHits = new List<bool>(toCopy.SeriesHits);

            BackdraftCharges = toCopy.BackdraftCharges;
            MoltenCoreCharges = toCopy.MoltenCoreCharges;
        }
예제 #5
0
        public float GetUprate(CastingState state, Spell spell)
        {
            // Assumes the effect == requeue time.
            // If this method is going to be called, be sure to enable RecordMissesSeparately.
            Debug.Assert(RecordMissesSeparately);

            float castTime = spell.GetCastTime(state);
            if (state.Cooldowns.ContainsKey(this))
            {
                float cooldown = state.Cooldowns[this] - castTime;
                if (cooldown <= 0 || !state.LastCastHit(this))
                {
                    return 0f;
                }
                else
                {
                    return 1f;
                }
            }

            float maxQueued = castTime;
            if (Mommy.IsPriorityOrdered(spell, this))
            {
                maxQueued += state.GetMaxTimeQueued(this);
            }
            float unqueuable = (state.Elapsed + castTime) - maxQueued;
            float chanceQueued = Math.Min(maxQueued / (GetAvgRequeueTime() - unqueuable), 1f);
            return 1 - chanceQueued;
        }
예제 #6
0
 private float MaybeApplyBackdraft(float time, CastingState state)
 {
     if (state != null
         && state.BackdraftCharges > 0
         && MySpellTree == SpellTree.Destruction)
     {
         time /= 1f + Mommy.Talents.Backdraft * .1f;
     }
     return time;
 }
예제 #7
0
        public float GetCastTime(CastingState state)
        {
            if (BaseCastTime == 0f)
            {
                return 0f;
            }

            float avg = 0f;
            foreach (WeightedStat h in Mommy.Haste)
            {
                avg += h.Chance * BaseCastTime / h.Value;
            }
            return MaybeApplyBackdraft(avg, state);
        }
예제 #8
0
 public float GetTimeUsed(CastingState state)
 {
     return MaybeApplyBackdraft(GetTimeUsed(BaseCastTime, GCDBonus, Mommy.Haste, Mommy.CalcOpts.Latency), state);
 }
예제 #9
0
        private void PopulateNextState(List<CastingState> results, CastingState stateBeforeCast, float timeUsed, float cooldownAfterAdvance, float p, bool isHit)
        {
            CastingState nextState = new CastingState(stateBeforeCast);
            nextState.Probability *= p;
            nextState.AddSpell(this, timeUsed, isHit);
            nextState.Cooldowns[this] = cooldownAfterAdvance;

            if (MySpellTree == SpellTree.Destruction && nextState.BackdraftCharges > 0)
            {
                --nextState.BackdraftCharges;
            }

            results.Add(nextState);
        }
예제 #10
0
        public virtual List<CastingState> SimulateCast(CastingState stateBeforeCast, float chanceOfCast)
        {
            // record stats about this spellcast
            float p = chanceOfCast * stateBeforeCast.Probability;
            float timeUsed = GetTimeUsed(stateBeforeCast);
            RecordSimulatedStat("delay", stateBeforeCast.GetMaxTimeQueued(this) / 2f, p);
            RecordSimulatedStat("time used", timeUsed, p);

            // construct the casting state(s) that can result from this cast
            List<CastingState> results = new List<CastingState>();
            float hitChance = Mommy.HitChance;
            if (IsBinary())
            {
                hitChance -= GetResist();
            }
            float newCooldown = Cooldown - timeUsed + GetCastTime(stateBeforeCast);
            if (CanMiss
                && hitChance < 1f
                && (RecordMissesSeparately || Cooldown < RecastPeriod))
            {
                // state when spell hits
                PopulateNextState(results, stateBeforeCast, timeUsed, Math.Max(RecastPeriod - timeUsed, newCooldown), hitChance * chanceOfCast, true);

                // state when spell misses
                if (newCooldown <= 0)
                {
                    // ensure at least 1 spell is cast before this one is
                    // requeued, to allow for travel time + reaction time for
                    // the player to detect the miss
                    newCooldown = .0001f;
                }
                PopulateNextState(results, stateBeforeCast, timeUsed, newCooldown, (1 - hitChance) * chanceOfCast, false);
            }
            else
            {
                PopulateNextState(results, stateBeforeCast, timeUsed, Math.Max(newCooldown, RecastPeriod - timeUsed), chanceOfCast, true);
            }

            return results;
        }
        private void RecordCollisionDelays(CastingState state)
        {
            // This technique assumes that if you pick a random time during filler
            // spell(s) or downtime, the "cooldowns" remaining on the rest of your
            // spells are all equally likely to be at any value. This is unrealistic
            // (e.g. it's impossible for them all to be at their full value), but
            // for some classes is a reasonable approximation.
            float pRemaining = 1f;
            foreach (Spell spell in Priorities)
            {
                float p = spell.GetQueueProbability(state);
                if (p == 0f)
                {
                    continue;
                }

                List<CastingState> nextStates = spell.SimulateCast(state, p * pRemaining);
                foreach (CastingState nextState in nextStates)
                {
                    if (nextState.Probability > .0001f)
                    {
                        // Only calculate if the probabilty of the state is
                        // large enough to make any difference at all.
                        RecordCollisionDelays(nextState);
                    }
                }
                if (p == 1f)
                {
                    return;
                }

                pRemaining *= 1f - p;
            }
        }
예제 #12
0
 public override List<CastingState> SimulateCast(CastingState stateBeforeCast, float chanceOfCast)
 {
     List<CastingState> states = base.SimulateCast(stateBeforeCast, chanceOfCast);
     foreach (CastingState state in states)
     {
         state.Cooldowns.Remove(this);
         if (state.MoltenCoreCharges > 0)
         {
             --state.MoltenCoreCharges;
         }
         else
         {
             state.MoltenCoreCharges = 2;
         }
     }
     return states;
 }
예제 #13
0
 public override float GetQueueProbability(CastingState state)
 {
     if (state.MoltenCoreCharges > 0)
     {
         return 1f;
     }
     else
     {
         return base.GetQueueProbability(state);
     }
 }
예제 #14
0
 public override float GetQueueProbability(CastingState state)
 {
     if (state.BackdraftCharges > 0)
     {
         return 1f;
     }
     else
     {
         return 0f;
     }
 }
예제 #15
0
 /// <summary>
 /// Records the chance that a given spell is cast while immolate is on
 /// the target.
 /// </summary>
 public void RecordUpChance(Spell spell, CastingState state)
 {
     float chance;
     chance = GetUprate(state, spell);
     spell.RecordSimulatedStat("immolate up-chance", chance, state.Probability);
 }
예제 #16
0
 public override List<CastingState> SimulateCast(CastingState stateBeforeCast, float chanceOfCast)
 {
     if (Mommy.Talents.FireAndBrimstone > 0)
     {
         ((Immolate)Mommy.GetSpell("Immolate")).RecordUpChance(this, stateBeforeCast);
     }
     return base.SimulateCast(stateBeforeCast, chanceOfCast);
 }
예제 #17
0
        public override List<CastingState> SimulateCast(CastingState stateBeforeCast, float chanceOfCast)
        {
            List<CastingState> states = base.SimulateCast(stateBeforeCast, chanceOfCast);

            CastingState stateOnHit = states[0];
            if (Mommy.Talents.Backdraft > 0)
            {
                stateOnHit.BackdraftCharges = 3;
            }

            return states;
        }
예제 #18
0
 public virtual float GetQueueProbability(CastingState state)
 {
     if (state.Cooldowns.ContainsKey(this))
     {
         if (state.Cooldowns[this] <= 0)
         {
             return 1f;
         }
         else
         {
             return 0f;
         }
     }
     else
     {
         float maxQueued = state.GetMaxTimeQueued(this);
         float unqueuable = state.Elapsed - maxQueued;
         return Math.Min(maxQueued / (GetAvgRequeueTime() - unqueuable), 1f);
     }
 }