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; }
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 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); } }