public StateFury GetState(int BSProc, bool BSHasted, double BTCD, double WWCD, int transition) { string name = string.Format( #if TRANSTYPE "BSProc {0}{1},BTCD {2:" + FORMAT + "},WWCD {3:" + FORMAT + "}, TransitionType{4}", #else "BSProc {0}{1},BTCD {2:" + FORMAT + "},WWCD {3:" + FORMAT + "}", #endif BSProc, BSHasted ? "+" : "-", BTCD, #if TRANSTYPE WWCD, transition); #else WWCD); #endif StateFury state; if (!stateDictionary.TryGetValue(name, out state)) { state = new StateFury() { Name = name, BTCooldown = BTCD, WWCooldown = WWCD, BSHasted = BSHasted, BSProcced = BSProc, #if TRANSTYPE transitionType = transition #endif }; stateDictionary[name] = state; } return(state); }
protected override List <StateTransition <Skills.Ability> > GetStateTransitions(State <Skills.Ability> state) { StateFury s = state as StateFury; List <StateTransition <Skills.Ability> > list = new List <StateTransition <Skills.Ability> >(); Rawr.DPSWarr.Rotation.AbilWrapper BT = Rot.GetWrapper <Skills.BloodThirst>(); Rawr.DPSWarr.Rotation.AbilWrapper WW = Rot.GetWrapper <Skills.WhirlWind>(); Rawr.DPSWarr.Rotation.AbilWrapper BS = Rot.GetWrapper <Skills.BloodSurge>(); Rawr.DPSWarr.Rotation.AbilWrapper HS = Rot.GetWrapper <Skills.HeroicStrike>(); /*bool forceDelay = false; * if (s.WWCooldown != 0 && s.BTCooldown != 0 && s.BSProcced > 0) * { * double slamDuration = (s.BSHasted ? HastedGCD : LatentGCD); * if (s.WWCooldown < slamDuration) * { * double WWtimeDelayed = slamDuration - s.WWCooldown; * double WWpercentLost = WWtimeDelayed / WW.ability.Cd; * double dmgLost = WW.ability.DamageOnUse * WWpercentLost; * double numHSesOnDelay = s.WWCooldown / WhiteInterval * HSPerc; * * if (s.BTCooldown < s.WWCooldown + LatentGCD) // if delaying lets us WW>BT * { * numHSesOnDelay = (s.WWCooldown + LatentGCD) / WhiteInterval * HSPerc; * * double BTtimeDelayed = slamDuration + LatentGCD - s.BTCooldown; * double BTpercentLost = BTtimeDelayed / BT.ability.Cd; * dmgLost += BT.ability.DamageOnUse * BTpercentLost; * } * * double slamDmgGained = 0; * } * }*/ if (s.WWCooldown <= 0) { #region Whirlwind double transDuration = LatentGCD; double newBTCD = Math.Max(0, s.BTCooldown - transDuration); double newWWCD = WW.ability.Cd - transDuration; double numHSes = transDuration / WhiteInterval; BloodSurgeMatrix _mat = new BloodSurgeMatrix(this.BS1Proc, this.BS2Proc); _mat.SetBaseChance(WWMatrix.ProcChances(1) + WWMatrix.ProcChances(2)); _mat.AddAbility(HS.ability.MHAtkTable.AnyLand * this.HSPerc, numHSes); double[] actual = { _mat.ProcChances(0), _mat.ProcChances(1), _mat.ProcChances(2) }; double chanceProc = (1 - WW.ability.MHAtkTable.AnyLand * BS1Proc) * (1 - WW.ability.OHAtkTable.AnyLand * BS1Proc); double[] test = { chanceProc *Math.Pow(1 - HS.ability.MHAtkTable.AnyLand * BS1Proc * HSPerc, numHSes), (1 - chanceProc * Math.Pow(1 - HS.ability.MHAtkTable.AnyLand * BS1Proc * HSPerc, numHSes)) * (1 - BS2Proc), (1 - chanceProc * Math.Pow(1 - HS.ability.MHAtkTable.AnyLand * BS1Proc * HSPerc, numHSes)) * BS2Proc, }; DelegateStateTransition.newTransitionChance del0 = () => { return(chanceProc * Math.Pow(1 - HSProcChance * HSPerc, numHSes)); }; DelegateStateTransition.newTransitionChance del1 = () => { return((1 - chanceProc * Math.Pow(1 - HSProcChance * HSPerc, numHSes)) * (1 - BS2Proc)); }; DelegateStateTransition.newTransitionChance del2 = () => { return((1 - chanceProc * Math.Pow(1 - HSProcChance * HSPerc, numHSes)) * BS2Proc); }; //double WWProc = (1 - BS1Proc * WW.ability.MHAtkTable.AnyLand) * (1 - BS1Proc * WW.ability.OHAtkTable.AnyLand); //double HSProc = BS1Proc * HS.ability.MHAtkTable.AnyLand; //double both = WWProc * Math.Pow(1 - HSProc, numHSes); // if WW is up, use it list.Add(new DelegateStateTransition() { Ability = WW.ability, TransitionDuration = transDuration, TargetState = GetState(2, true, newBTCD, newWWCD, 2), myDel = del2, }); // if BS procs 1 list.Add(new DelegateStateTransition() { Ability = WW.ability, TransitionDuration = transDuration, TargetState = GetState((s.BSHasted ? 2 : 1), s.BSHasted, newBTCD, newWWCD, 1), myDel = del1, }); // if BS doesn't proc list.Add(new DelegateStateTransition() { Ability = WW.ability, TransitionDuration = transDuration, TargetState = GetState(s.BSProcced, s.BSHasted, newBTCD, newWWCD, 0), myDel = del0 }); #endregion } else if (s.BTCooldown <= 0) { #region BloodThirst double transDuration = LatentGCD; double newBTCD = BT.ability.Cd - transDuration; double newWWCD = Math.Max(0, s.WWCooldown - transDuration); double numHSes = transDuration / WhiteInterval; double chanceProc = (1 - BT.ability.MHAtkTable.AnyLand * BS1Proc); double[] test = { chanceProc *Math.Pow(1 - HS.ability.MHAtkTable.AnyLand * BS1Proc, HSPerc), chanceProc *Math.Pow(1 - HS.ability.MHAtkTable.AnyLand * BS1Proc, HSPerc) * (1 - BS2Proc), chanceProc *Math.Pow(1 - HS.ability.MHAtkTable.AnyLand * BS1Proc, HSPerc) * BS2Proc }; DelegateStateTransition.newTransitionChance del0 = () => { return(chanceProc * Math.Pow(1 - HSProcChance * HSPerc, numHSes)); }; DelegateStateTransition.newTransitionChance del1 = () => { return((1 - chanceProc * Math.Pow(1 - HSProcChance * HSPerc, numHSes)) * (1 - BS2Proc)); }; DelegateStateTransition.newTransitionChance del2 = () => { return((1 - chanceProc * Math.Pow(1 - HSProcChance * HSPerc, numHSes)) * BS2Proc); }; // if BS procs 2 list.Add(new DelegateStateTransition() { Ability = BT.ability, TransitionDuration = transDuration, TargetState = GetState(2, true, newBTCD, newWWCD, 2), myDel = del2 }); // if BS procs 1 list.Add(new DelegateStateTransition() { Ability = BT.ability, TransitionDuration = transDuration, TargetState = GetState((s.BSHasted ? 2 : 1), s.BSHasted, newBTCD, newWWCD, 1), myDel = del1 }); // if BS doesn't proc list.Add(new DelegateStateTransition() { Ability = BT.ability, TransitionDuration = transDuration, TargetState = GetState(s.BSProcced, s.BSHasted, newBTCD, newWWCD, 0), myDel = del0 }); #endregion } else if (s.BSProcced > 0) { #region Slam double transDuration = (s.BSHasted ? HastedGCD : LatentGCD); double newBTCD = Math.Max(0, s.BTCooldown - transDuration); double newWWCD = Math.Max(0, s.WWCooldown - transDuration); double numHSes = transDuration / WhiteInterval; double chanceProc = 1; double[] test = { Math.Pow(1 - HS.ability.MHAtkTable.AnyLand * BS1Proc, HSPerc), Math.Pow(1 - HS.ability.MHAtkTable.AnyLand * BS1Proc, HSPerc) * (1 - BS2Proc), Math.Pow(1 - HS.ability.MHAtkTable.AnyLand * BS1Proc, HSPerc) * BS2Proc }; DelegateStateTransition.newTransitionChance del0 = () => { return(chanceProc * Math.Pow(1 - HSProcChance * HSPerc, numHSes)); }; DelegateStateTransition.newTransitionChance del1 = () => { return((1 - chanceProc * Math.Pow(1 - HSProcChance * HSPerc, numHSes)) * (1 - BS2Proc)); }; DelegateStateTransition.newTransitionChance del2 = () => { return((1 - chanceProc * Math.Pow(1 - HSProcChance * HSPerc, numHSes)) * BS2Proc); }; // if HS procs 2 list.Add(new DelegateStateTransition() { Ability = BS.ability, TransitionDuration = transDuration, TargetState = GetState(2, true, newBTCD, newWWCD, 2), myDel = del2 }); // if HS procs 1 list.Add(new DelegateStateTransition() { Ability = BS.ability, TransitionDuration = transDuration, TargetState = GetState(s.BSProcced, // if we had 2 and then procced, we're at 2. If we had 1 and then procced, we're at 1 (s.BSProcced == 2), // if we're at 2 before, we're still hasted. If we're at 1 before, we lost the haste before we procced newBTCD, newWWCD, 1), myDel = del1 }); // if HS doesn't proc list.Add(new DelegateStateTransition() { Ability = BS.ability, TransitionDuration = transDuration, TargetState = GetState(s.BSProcced - 1, // num procs decreases (s.BSProcced == 2), // haste falls off if we were at 1 newBTCD, newWWCD, 0), myDel = del0 }); #endregion } else { double transDuration = Math.Min(s.BTCooldown, s.WWCooldown); double numHSes = transDuration / WhiteInterval; double chanceProc = 1; double[] test = { Math.Pow(1 - HS.ability.MHAtkTable.AnyLand * BS1Proc, HSPerc), Math.Pow(1 - HS.ability.MHAtkTable.AnyLand * BS1Proc, HSPerc) * (1 - BS2Proc), Math.Pow(1 - HS.ability.MHAtkTable.AnyLand * BS1Proc, HSPerc) * BS2Proc }; DelegateStateTransition.newTransitionChance del0 = () => { return(chanceProc * Math.Pow(1 - HSProcChance * HSPerc, numHSes)); }; DelegateStateTransition.newTransitionChance del1 = () => { return((1 - chanceProc * Math.Pow(1 - HSProcChance * HSPerc, numHSes)) * (1 - BS2Proc)); }; DelegateStateTransition.newTransitionChance del2 = () => { return((1 - chanceProc * Math.Pow(1 - HSProcChance * HSPerc, numHSes)) * BS2Proc); }; list.Add(new DelegateStateTransition() { Ability = null, TransitionDuration = transDuration, TargetState = GetState(2, true, s.BTCooldown - transDuration, s.WWCooldown - transDuration, 2), myDel = del2 }); // if HS procs 1 list.Add(new DelegateStateTransition() { Ability = null, TransitionDuration = transDuration, TargetState = GetState((s.BSHasted ? 2 : 1), s.BSHasted, s.BTCooldown - transDuration, s.WWCooldown - transDuration, 1), myDel = del1 }); // if HS doesn't proc list.Add(new DelegateStateTransition() { Ability = null, TransitionDuration = transDuration, TargetState = GetState(s.BSProcced, s.BSHasted, s.BTCooldown - transDuration, s.WWCooldown - transDuration, 0), myDel = del0 }); } // Test to make sure probabilities aren't messed up double prob = 0; foreach (StateTransition <Skills.Ability> st in list) { prob += st.TransitionProbability; StateFury sf = (StateFury)st.TargetState; if (s.BSHasted == sf.BSHasted && s.BSProcced == sf.BSProcced && s.BTCooldown == sf.BTCooldown && //s.WhiteCooldown == sf.WhiteCooldown && s.WWCooldown == sf.WWCooldown) { //int j = 0; //break } } if (prob != 1) { //int j = 0; //break } return(list); }