public float GetMaxTimeQueued(Spell spell) { if (Cooldowns.ContainsKey(spell)) { return -Cooldowns[spell]; } // This method answers the qusetion, "If my spell is being cast now, // how long could it have been since it queued up to be cast?" // // We know if there are lower priority spells that have already been // cast, it was not queued before that. So we backtrack until we // find a lower priority spell. // // Lower index == higher priority. float t = 0; int newPriority = Mommy.Priorities.IndexOf(spell); for (int i = SeriesTimes.Count; --i >= 0; ) { t += SeriesTimes[i]; if (SeriesPriorities[i] > newPriority) { return t; } } return Elapsed; }
public void AddSpell(Spell spell, float timeAdvance, bool hit) { Elapsed += timeAdvance; Series.Add(spell); SeriesTimes.Add(timeAdvance); SeriesPriorities.Add(Mommy.Priorities.IndexOf(spell)); SeriesHits.Add(hit); foreach (Spell key in new List<Spell>(Cooldowns.Keys)) { Cooldowns[key] -= timeAdvance; } }
public CastingState(CharacterCalculationsWarlock mommy, Spell precedingSpell, float probability) { Mommy = mommy; Probability = probability; Cooldowns = new Dictionary<Spell, float>(); SeriesPriorities = new List<int>(); Series = new List<Spell>(); SeriesTimes = new List<float>(); SeriesHits = new List<bool>(); if (precedingSpell != null) { Elapsed = precedingSpell.GetAvgTimeUsed(); } }
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; }
public float AddCastsForRegen(float timeRemaining, float manaRemaining, Spell spammedSpell) { // getting our cast time is not safe until the backdraft multilpier // has been set. fortunetly that's easy to "calculate" // BackdraftMultiplier = 1f; // The number of needed lifetaps is obtained by solving this // system of equations: // // spamCasts * spamMana + ltCasts * ltMana = manaRemaining // spamCasts * spamCast + ltCasts * ltCast = timeRemaining float latency = Mommy.CalcOpts.Latency; float a = spammedSpell.ManaCost; float b = ManaCost; float c = manaRemaining; float d = spammedSpell.GetAvgTimeUsed(); float e = GetAvgTimeUsed(); float f = timeRemaining; float toAdd = Math.Max(0f, (c * d - a * f) / (b * d - a * e)); NumCasts += toAdd; if (toAdd > 0 && !Mommy.CastSpells.ContainsKey("Life Tap")) { Mommy.CastSpells.Add("Life Tap", this); } return toAdd; }
/// <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); }
public bool LastCastHit(Spell spell) { return SeriesHits[Series.LastIndexOf(spell)]; }
public bool IsPriorityOrdered(Spell s1, Spell s2) { int i1 = Priorities.IndexOf(s1); int i2 = Priorities.IndexOf(s2); return (i1 < i2 && i1 != -1) || (i1 != -1 && i2 == -1); }