Elitist Jerks
Register
Blogs
Forums


Go Back   Elitist Jerks » Class Mechanics » Paladins

Reply
 
LinkBack Thread Tools
Old 02/03/09, 1:03 PM   #1
Left
Don Flamenco
 
Left's Avatar
 
Draenei Paladin
 
Darkspear
FCFS (Retribution) modeling script

Following some discussion of late in the Ret Paladin thread, I decided that I was interested enough in the philosophical problem of prioritizing FCFS rotations that I would take a crack at some scripting to model different scenarios for Retribution FCFS rotations. The purpose of this script is not to provide another DPS calculator for Ret paladins, but rather to serve as a validation tool for Exemplar, Redcape, and anyone else who is trying to develop an FCFS priority system. The script runs a simulation which can be used to verify or disprove various assumptions about FCFS. However, I have no intention of developing it into a full-featured, user-friendly program. (If someone else wants to take it and do that, more power to them.)

Currently posted is version 2 of the script.

The script is written in Python, and can be edited and executed relatively easily by downloading and installing the free Python development environment. (I don't really know much of the innards of Python; I'm just using it because it is very easy to script in and because I used it last summer for some rogue theorycraft work regarding poison application.)

Basically, what the script does is use some user-defined values to simulate a basic FCFS rotation over a period of time. So far, what I have is a hard-coded priority list with no delay logic built in. To change the FCFS priority, you have to edit the code of the script. Latency is now incorporated as well as damage estimatation. The FCFS priority is still hardcoded.

Retribution FCFS Simulation Script v002:
print 'FCFS Cycle Modeling for Retribution Paladins'
print 'v002'
print ''
###############################################################
#                       USER VARIABLES
#
# Set the value of the variables in this section according to
# your particular gear setup, target, and personal preference.
###############################################################

# FCFS abbreviations:
#   J = Judgement
#   Hammer = Hammer of Wrath
#   CS = Crusader Strike
#   Cons = Consecrate
#   DS = Divine Storm
#   Exo = Exorcism
#   HW = Holy Wrath
#   DP = Divine Plea
#   SoB = Reseal w/ Seal of Blood

# Damage values of each ability
## All but HW pulled from Redcape's spreadsheet
## HW is a total guess
dmgJ = 13229
dmgCS = 5024        ## Includes Seal of Blood damage
dmgCons = 5809
dmgDS = 6381        ## Includes Seal of Blood damage
dmgExo = 3802
dmgHW = 2800
dmgHammer = 6818
dmgDP = 0
dmgSoB = 0

# Undead/demon target?
undead = True

# Below 20%? (IE, use hammer of wrath?)
hammer = False

# Gear options
fourPieceT7 = True
consGlyph = True

# Latency options [in seconds]
latency = 0.000

# Simulation options [in seconds]
step = 0.1
runTime = 30.0

###############################################################
#                       PROGRAM VARIABLES
#
# Don't change these unless you know what you're doing.
# 
###############################################################

# Global cooldown
gcd = 1.5 + latency

# Cooldowns for each ability
if fourPieceT7:
    cooldownJ = 7 + latency
else:
    cooldownJ = 8 + latency

cooldownHammer = 6 + latency
cooldownCS = 6 + latency

if consGlyph:
    cooldownCons = 10 + latency
else:
    cooldownCons = 8 + latency

cooldownDS = 10 + latency
cooldownExo = 15 + latency
cooldownHW = 30 + latency
cooldownDP = 60 + latency
cooldownSoB = 90

# Time variable
time = 0

# Variables for tracking when each ability was last executed
#   Initialized to the negative of their cooldown + 1, ie,
#   they are off cooldown to start with
#   (Exception is Seal of Blood, which is assumed to be used
#    ~5 seconds before combat actually begins)
lastJ = -(cooldownJ + 1)
lastCS = -(cooldownCS + 1)
lastCons = -(cooldownCons + 1)
lastDS = -(cooldownDS + 1)
lastExo = -(cooldownExo + 1)
lastHW = -(cooldownHW + 1)
lastHammer = -(cooldownHammer + 1)
lastDP = -(cooldownDP + 1)
lastSoB = -5.0

# Variables for tracking when each ability was first executed
#   Initialized to 0.0 seconds to create proper variable type
#   (Exception is Seal of Blood, which is assumed to be used
#    ~5 seconds before combat actually begins)
firstJ = 0.0
firstCS = 0.0
firstCons = 0.0
firstDS = 0.0
firstExo = 0.0
firstHW = 0.0
firstHammer = 0.0
firstDP = 0.0
firstSoB = -5.0

# Time at which the last ability, of any sort, was used
#   Initialized to be one GCD before simulation start
lastAbilityTime = -gcd

# Name of last ability used
lastAbility = ''

# Variables for tracking how many times each ability is used
numJ = 0
numCS = 0
numCons = 0
numDS = 0
numExo = 0
numHW = 0
numHammer = 0
numDP = 0
numSoB = 0

###############################################################
#                       SIMULATION
#
# Here's where the simulation actually occurs.
# 
###############################################################

# Here's a more complex test, using a hard coded priority system
print 'Simulating', runTime, 'seconds of FCFS'
while time <= runTime:
    # Check for Global Cooldown
    if round(time-lastAbilityTime,2) < gcd:
        time += step
        continue
    # Priority 0.5: Reseal if past 120 seconds
    if round(time-lastSoB,2) >= 120.0:
        print 'Seal of Blood Expired! Refreshing...'
        numSoB += 1
        lastSoB = time
        lastAbility = 'Seal of Blood'
    # Priority 1: Judgement
    elif round(time-lastJ,2) >= cooldownJ:
        numJ += 1
        if numJ == 1: firstJ = time
        lastJ = time
        lastAbility = 'Judgement'
##    # Test case: Delay for judgement if within 0.5 sec
##    elif round(time-lastJ,2) >= (cooldownJ-0.5):
##        # Just wait it out
##        time += step
##        continue
    # Priority 1.5: Hammer of Wrath (below 20%)
    elif (round(time-lastHammer,2) >= cooldownCS) and hammer:
        numHammer += 1
        if numHammer == 1: firstHammer = time
        lastHammer = time
        lastAbility = 'Hammer of Wrath'
    # Priority 2: Crusader Strike
    elif round(time-lastCS,2) >= cooldownCS:
        numCS += 1
        if numCS == 1: firstCS = time
        lastCS = time
        lastAbility = 'Crusader Strike'
    # Priority 3: Consecrate
    elif round(time-lastCons,2) >= cooldownCons:
        numCons += 1
        if numCons == 1: firstCons = time
        lastCons = time
        lastAbility = 'Consecrate'
    # Priority 4: Divine Storm
    elif round(time-lastDS,2) >= cooldownDS:
        numDS += 1
        if numDS == 1: firstDS = time
        lastDS = time
        lastAbility = 'Divine Storm'
    # Priority 5: Exorcism
    elif (round(time-lastExo,2) >= cooldownExo) and undead:
        numExo += 1
        if numExo == 1: firstExo = time
        lastExo = time
        lastAbility = 'Exorcism'
    # Priority 6: Holy Wrath
    elif (round(time-lastHW,2) >= cooldownHW) and undead:
        numHW += 1
        if numHW == 1: firstHW = time
        lastHW = time
        lastAbility = 'Holy Wrath'
    # Priority 7: Divine Plea
    elif round(time-lastDP,2) >= cooldownDP:
        numDP += 1
        if numDP == 1: firstDP = time
        lastDP = time
        lastAbility = 'Divine Plea' 
    # Priority 8: Reseal
    elif round(time-lastSoB,2) >= cooldownSoB:
        numSoB += 1
        lastSoB = time
        lastAbility = 'Seal of Blood'   
    # If nothing was off cooldown...
    else:
        time += step
        continue

    # Clean up after using an ability
    # Comment this next line if you want to improve execution speed
    print 'Used', lastAbility, 'at', time, 'sec' 
    lastAbilityTime = time  
    time += step

gcdUsed = numJ + numCS + numCons + numDS + numExo + numHW + numHammer + numDP + numSoB

print ''
print 'END SIMULATION'
print '---Cooldowns Remaining---'
print 'Judgement:', max(round(cooldownJ-(runTime-lastJ),2),0), 'sec'
print 'Crusader Strike:', max(round(cooldownCS-(runTime-lastCS),2),0), 'sec'
print 'Consecrate:', max(round(cooldownCons-(runTime-lastCons),2),0), 'sec'
print 'Divine Storm:', max(round(cooldownDS-(runTime-lastDS),2),0), 'sec'
print 'Exorcism:', max(round(cooldownExo-(runTime-lastExo),2),0), 'sec'
print 'Holy Wrath:', max(round(cooldownHW-(runTime-lastHW),2),0), 'sec'
print 'Hammer of Wrath:', max(round(cooldownHammer-(runTime-lastHammer),2),0), 'sec'
print 'Divine Plea:', max(round(cooldownDP-(runTime-lastDP),2),0), 'sec'
print ''

print 'RESULTS:'
print 'GCD density:', round((gcdUsed*gcd)/(runTime),4)*100,'%'
print ''
print '---Abilities Used---'
print 'Judgement:', numJ
print 'Crusader Strike:', numCS
print 'Consecrate:', numCons, '(',numCons*cooldownCons, 'ticks)'
print 'Divine Storm:', numDS
print 'Exorcism:', numExo
print 'Holy Wrath:', numHW
print 'Hammer of Wrath:', numHammer
print 'Divine Plea:', numDP
print 'Seal of Blood:', numSoB
print ''

print '---Average Usage Interval---'
if numJ > 1:
    print 'Judgement:', round((lastJ-firstJ)/(numJ-1),2), 'sec'
if numCS > 1:
    print 'Crusader Strike:', round((lastCS-firstCS)/(numCS-1),2), 'sec'
if numCons > 1:
    print 'Consecrate:', round((lastCons-firstCons)/(numCons-1),2), 'sec'
if numDS > 1:
    print 'Divine Storm:', round((lastDS-firstDS)/(numDS-1),2), 'sec'
if numExo > 1:
    print 'Exorcism:', round((lastExo-firstExo)/(numExo-1),2), 'sec'
if numHW > 1:
    print 'Holy Wrath:', round((lastHW-firstHW)/(numHW-1),2), 'sec'
if numHammer > 1:
    print 'Hammer of Wrath:', round((lastHammer-firstHammer)/(numHammer-1),2), 'sec'
if numDP> 1:
    print 'Divine Plea:', round((lastDP-firstDP)/(numDP-1),2), 'sec'
if numSoB> 0:       # Seal of Blood is a special case
    print 'Seal of Blood:', round((lastSoB-firstSoB)/(numSoB),2), 'sec'
print ''

print '---Damage---'
print 'Judgement:', numJ*dmgJ
print 'Crusader Strike:', numCS*dmgCS
print 'Consecrate:', numCons*dmgCons
print 'Divine Storm:', numDS*dmgDS
print 'Exorcism:', numExo*dmgExo
print 'Holy Wrath:', numHW*dmgHW
print 'Hammer of Wrath:', numHammer*dmgHammer
totDamage = numJ*dmgJ + numCS*dmgCS + numCons*dmgCons + numDS*dmgDS + numExo*dmgExo + numHW*dmgHW + numHammer*dmgHammer
avgDPS = (totDamage*1.0)/runTime
print 'TOTAL:', totDamage
print 'DPS:', round(avgDPS,2)
print '(NOTE: Does not include any estimate of white DPS)'
Changelog
v001
  • Created script
v002
  • Added latency modeling via increased GCD and other cooldowns, as per Exemplar's suggestion
  • Added Divine Plea and the capability to reseal
  • Added a crude damage estimator
  • Improved usage interval calculations as per Dokb's suggestion
  • Hard coded resealing-specific priority into the FCFS system
  • Hard coded an optional delay-to-judge option in the FCFS system (uncomment code to enable)

Sample Output:
  • 30 second runtime
  • J > CS > Cons > DS > Exo > HW
  • Undead/demon target = TRUE
  • Hammer of Wrath not used
  • 4pT7 = TRUE
  • Consecrate Glyph = TRUE

>>> 
FCFS Cycle Modeling for Retribution Paladins
v002

Simulating 30.0 seconds of FCFS
Used Judgement at 0 sec
Used Crusader Strike at 1.5 sec
Used Consecrate at 3.0 sec
Used Divine Storm at 4.5 sec
Used Exorcism at 6.0 sec
Used Judgement at 7.5 sec
Used Crusader Strike at 9.0 sec
Used Holy Wrath at 10.5 sec
Used Divine Plea at 12.0 sec
Used Consecrate at 13.5 sec
Used Judgement at 15.0 sec
Used Crusader Strike at 16.5 sec
Used Divine Storm at 18.0 sec
Used Exorcism at 21.0 sec
Used Judgement at 22.5 sec
Used Crusader Strike at 24.0 sec
Used Consecrate at 25.5 sec
Used Divine Storm at 28.0 sec
Used Judgement at 29.5 sec

END SIMULATION
---Cooldowns Remaining---
Judgement: 6.5 sec
Crusader Strike: 0.0 sec
Consecrate: 5.5 sec
Divine Storm: 8.0 sec
Exorcism: 6.0 sec
Holy Wrath: 10.5 sec
Hammer of Wrath: 0 sec
Divine Plea: 42.0 sec

RESULTS:
GCD density: 95.0 %

---Abilities Used---
Judgement: 5
Crusader Strike: 4
Consecrate: 3 ( 30.0 ticks)
Divine Storm: 3
Exorcism: 2
Holy Wrath: 1
Hammer of Wrath: 0
Divine Plea: 1
Seal of Blood: 0

---Average Usage Interval---
Judgement: 7.38 sec
Crusader Strike: 7.5 sec
Consecrate: 11.25 sec
Divine Storm: 11.75 sec
Exorcism: 15.0 sec

---Damage---
Judgement: 66145
Crusader Strike: 20096
Consecrate: 17427
Divine Storm: 19143
Exorcism: 7604
Holy Wrath: 2800
Hammer of Wrath: 0
TOTAL: 133215
DPS: 4440.5
(NOTE: Does not include any estimate of white DPS)
Average interval problem went away in v002 due to a new way to calculate it.

I'll post some runtime results from v002 further down in the thread.

Please feel free to take and modify this code as needed, or to request specific setups to be run, etc. Please post bug reports, etc, to this thread. If I get some time, I'll try to refine the modeling in a useful way, but since this is currently my lunch break project at work it won't necessarily happen very fast.

Note that you may also be interested in Zengir's work, as he has put together a similar program in .NET which more fully supports rotations and priority systems. At the time of this writing, this post links to his latest version.

Last edited by Left : 02/10/09 at 1:24 PM. Reason: Added a link to Zengir's work

Offline
Reply With Quote
Old 02/03/09, 2:42 PM   #2
Dokb
Glass Joe
 
Dwarf Paladin
 
Ner'zhul (EU)
Average usage interval

Regarding the average usage interval, I see a simple way to estimate it.

You'd have to record the first time an ability is used and the last time it is used. Then you would calculate : (timeLastUsed - timeFirstUsed)/(numberUsed-1). The -1 is to prevent what is happening right now, since you will always end up calculating the average use on a time period where the last ability used is the one concerned.

To do so in your script, you would have to add two variables per ability. One for the timeFirstUsed, and one to inform the script if the ability has been used.

For example, if you want to do it for J, you could add in variables :

timeFirstUsedJ = 0
firstJ = 1
Then when you simulate the J priority :

if round(time-timeJ,2) >= cooldownJ:
        numJ += 1
        timeJ = time
        #Records when you use J for the first time
        if firstJ = 1
              timeFirstUsedJ = time
              firstJ = 0
        lastAbility = 'Judgement'
The simulated average usage interval would then be in the script :
(timeJ-timeFirstUsedJ)/(numJ-1)
By the way, I have never coded anything in python, I might be wrong with how I write the code, but the idea behind is quite clear I believe.

Offline
Reply With Quote
Old 02/03/09, 3:03 PM   #3
Left
Don Flamenco
 
Left's Avatar
 
Draenei Paladin
 
Darkspear
That's an excellent idea. Thanks for pointing it out. After seeing your code (and yes, Python really is that simple; it's why I like it) I think I'd modify it as follows:

    # Priority 1: Judgement
    if round(time-timeJ,2) >= cooldownJ:
        numJ += 1
        if numJ = 1
              timeFirstUsedJ = time
        timeJ = time
        lastAbility = 'Judgement'
numJ provides a natural tracking parameter.

I don't have time to do this now, but I'll see if I can fix it for later.

Offline
Reply With Quote
Old 02/03/09, 3:21 PM   #4
Janraea
Don Flamenco
 
Tauren Druid
 
Dunemaul
Originally Posted by Dokb View Post
Regarding the average usage interval, I see a simple way to estimate it.

You'd have to record the first time an ability is used and the last time it is used. Then you would calculate : (timeLastUsed - timeFirstUsed)/(numberUsed-1). The -1 is to prevent what is happening right now, since you will always end up calculating the average use on a time period where the last ability used is the one concerned.

(code)

By the way, I have never coded anything in python, I might be wrong with how I write the code, but the idea behind is quite clear I believe.
That hardly seems necessary. Running the script with length = 6 hours takes less than two seconds on my (not terribly powerful) computer, and that dwarfs the end-point errors (which are all plus or minus 2, maximum).

I have altered a segment of the code to allow it to avoid CS immediately after Judgement (as some prefer):

while time <= runTime:
    # Check for Global Cooldown
    if round(time-lastAbilityTime,2) < gcd:
        time += step
        continue
    # Priority 1: Judgement
    if round(time-timeJ,2) >= cooldownJ:
        numJ += 1
        timeJ = time
        lastAbility = 'Judgement'
    # Priority 1.5: Hammer of Wrath (below 20%)
    elif (round(time-timeHammer,2) >= cooldownCS) and hammer:
        numHammer += 1
        timeHammer = time
        lastAbility = 'Hammer of Wrath'
    # Priority 2: Crusader Strike 
    elif round(time-timeCS,2) >= cooldownCS and not (lastAbility == 'Judgement' and fourPieceT7 and dontCSafterJ):
        numCS += 1
        timeCS = time
        lastAbility = 'Crusader Strike'
    # Priority 3: Consecrate
    elif round(time-timeCons,2) >= cooldownCons:
        numCons += 1
        timeCons = time
        lastAbility = 'Consecrate'
    # Priority 4: Divine Storm
    elif round(time-timeDS,2) >= cooldownDS:
        numDS += 1
        timeDS = time
        lastAbility = 'Divine Storm'
    # Priority 5: Exorcism
    elif (round(time-timeExo,2) >= cooldownExo) and undead:
        numExo += 1
        timeExo = time
        lastAbility = 'Exorcism'
    # Priority 6: Holy Wrath
    elif (round(time-timeHW,2) >= cooldownHW) and undead:
        numHW += 1
        timeHW = time
        lastAbility = 'Holy Wrath'
    # Priority 2: Crusader Strike just after Judgement with 4T7
    elif round(time-timeCS,2) >= cooldownCS:
        numCS += 1
        timeCS = time
        lastAbility = 'Crusader Strike'
    # If nothing was off cooldown...
    else:
        time += step
        continue

    # Clean up after using an ability
    # Comment this next line if you want to improve execution speed
    print 'Used', lastAbility, 'at', time, 'sec'
    lastAbilityTime = time
    time += step
Behavior is controlled by the dontCSafterJ variable - if it's True, CS is given much lower priority if Judgement was the previous ability.

Some interesting conclusions from using that variable:

1) If Exorcism isn't being used, noCSafterJ increases the number of Judgements used by a few percent, because the partial cds line up better.
2) If Exorcism IS being used, noCSafterJ decreases both CS use and Judgement use.
(With No Exorcism, Consecrate is up 100% of the time if noCSafterJ is activated, by happenstance of gcd timing).

I will leave net numeric conclusions for when I have more time, but here are ability counts for the four cases for a 24-hour long fight:

1) Exo:
Judgement: 11782
Crusader Strike: 11782
Consecrate: 7855 ( 78550 ticks)
Divine Storm: 7854
Exorcism: 5237
Holy Wrath: 2618
2) Exo, noCSafterJ:
Judgement: 11520
Crusader Strike: 11520
Consecrate: 8640 ( 86400 ticks)
Divine Storm: 8640
Exorcism: 5760
Holy Wrath: 2880
3) No Exo:
Judgement: 12056
Crusader Strike: 12056
Consecrate: 8037 ( 80370 ticks)
Divine Storm: 8037
4) No Exo, NoCSafterJ:
Judgement: 12343
Crusader Strike: 12343
Consecrate: 8229 ( 82290 ticks)
Divine Storm: 8229

Edit: Something seems wrong with those number, I'm checking into it >.<
Edit again: Nope, they're fine.

The thing that had me worried was how the judgement count matches up with the cs count on every run. That actually is what should be happening though - we lose a 192 each of DS and Cons for 287 each of Judgement and CS. Seems like a good trade to me.

Might be worthwhile to make the loop occasionally skip chunks of gcds (out of range, mechanics of a fight type thing), and see how well the 'noCSafterJ' concept copes with rotation interruptions.. I'll get something on that later.

No Exo, noCSafterJ repeats after 21 seconds, with J>CS>Cons>DS (as I believe is common knowledge now in the main ret thread):
Used Judgement at 0 sec
Used Consecrate at 1.5 sec
Used Crusader Strike at 3.0 sec
Used Divine Storm at 4.5 sec
Used Judgement at 7.0 sec
Used Crusader Strike at 9.0 sec
Used Consecrate at 11.5 sec
Used Judgement at 14.0 sec
Used Divine Storm at 15.5 sec
Used Crusader Strike at 17.0 sec

Used Judgement at 21.0 sec

Last edited by Janraea : 02/03/09 at 3:40 PM.

Offline
Reply With Quote
Old 02/03/09, 5:02 PM   #5
Exemplar
Bald Bull
 
Human Paladin
 
Scarlet Crusade
Off the cuff idea:
You should be able to get a rough approximation of latency by adding a latency variable. Add this variable to cooldown time of all abilities and to the GCD used to cast abilities.

If you want to model Divine Plea and Re-seal, this would be easy. Just give DP a 60 sec cooldown, Seal about a 90 sec (so it starts looking early, but not too early). Then set them to only cast if nothing is under a whole GCD remaining on its cooldown.

Offline
Reply With Quote
Old 02/03/09, 6:41 PM   #6
Dokb
Glass Joe
 
Dwarf Paladin
 
Ner'zhul (EU)
To include latency you could just model it by a fraction of the step.

Say you have 200 ms latency, when you judge, it occurs 200ms later or 2 step later.

You could write it like this (using the judge portion) :
#First line is when you see the J button off cd
if round(time-timeJ,2) >= cooldownJ:
        #This is the time it takes the game to actually cast the J and reset the cd
        time += latency*step
        #Now that the spell is cast, you can record the time it went off, after latency
        numJ += 1
        timeJ = time
        lastAbility = 'Judgement'
latency would be between 0 and whatever. It has to be an integer so that you don't mess up your step. If you need a smaller latency, you'd have to use a smaller step.

Offline
Reply With Quote
Old 02/04/09, 2:49 PM   #7
zengir
Glass Joe
 
Human Paladin
 
Defias Brotherhood (EU)
Hi!

I've been fiddling around with different rotations for a while, and trying to make the best of it with excel-sheets and such, but I got tired of having to type it all in everytime, so I made a simple application for it in C# .NET.

You enter your average damage on JoM, CS, DS, Consecration, melee and SoM, weapon speed, the length of the fight AND your preferred rotation AND your cooldowns on your spells (allowing for 10/8 sec consecration and 7/8 sec judgement)

The output looks like this with very simple numbers, JoM: 7000, CS: 3000, DS: 4500, Cons: 5000, Melee: 3000, SoM: 1000, 3.0 weapon speed (after haste) and fight length 240 seconds:

--------------------------------------
Simulation time: 240 seconds.
Judgement cooldown: 8 seconds.
Priority: jom > cs > ds > cons
Total DPS: 3741,67

Number of casts:
JoM: 29
CS: 36
DS: 22
Cons: 22

Damage and DPS per ability:
JoM DPS: 845,83 - DMG: 203000
CS DPS: 450 - DMG: 108000
DS DPS: 412,5 - DMG: 99000
Cons DPS: 458,33 - DMG: 110000
Melee DPS: 1000 - DMG: 240000
SoM DPS: 575 - DMG: 138000

--------------------------------------

Simulation time: 240 seconds.
Judgement cooldown: 8 seconds.
Priority: cs > jom > ds > cons
Total DPS: 3762,5

Number of casts:
JoM: 28
CS: 39
DS: 22
Cons: 22

--------------------------------------

Simulation time: 240 seconds.
Judgement cooldown: 8 seconds.
Priority: cs > ds > jom > cons
Total DPS: 3772,92

Number of casts:
JoM: 28
CS: 37
DS: 23
Cons: 23

--------------------------------------

The same calculations with a 7 second judgement shows the following:


--------------------------------------
Simulation time: 240 seconds.
Judgement cooldown: 7 seconds.
Priority: jom > cs > ds > cons
Total DPS: 3877,08

Number of casts:
JoM: 34
CS: 34
DS: 23
Cons: 22

--------------------------------------

Simulation time: 240 seconds.
Judgement cooldown: 7 seconds.
Priority: cs > jom > ds > cons
Total DPS: 3908,33

Number of casts:
JoM: 33
CS: 39
DS: 22
Cons: 22

--------------------------------------

Simulation time: 240 seconds.
Judgement cooldown: 7 seconds.
Priority: cs > ds > jom > cons
Total DPS: 3877,08

Number of casts:
JoM: 31
CS: 38
DS: 23
Cons: 23

--------------------------------------

Theese numbers might not be correct, since I'm not really sure about the average damage on the different abilites. I haven't really raided much, so I don't have much WWS-data to go by, and the numbers I get from Redcape's sheet seem a bit too high. They are suggesting that I'd do around 5k DPS, but I'm only in heroic/emblem/10-man gear, and I'm usually ending up around 3,5k DPS in 25-mans. I'd be happy to run a few simulations with some "real" numbers if anyone has any good data.

I'm hoping I'll have the time to finish this little application in the weekend, so I might be uploading somewhere if someone is interested in giving it a go. There's just a few things that needs to be sorted out before I can let someone else use it

(Woah, that's a long first post )

Offline
Reply With Quote
Old 02/04/09, 7:44 PM   #8
dlaiyre
Glass Joe
 
Blood Elf Paladin
 
Dath'Remar
Am I right assuming that we could add Latency to the GCD? (ex gcd=1.8 for 300ms)

Offline
Reply With Quote
Old 02/04/09, 9:59 PM   #9
Dokb
Glass Joe
 
Dwarf Paladin
 
Ner'zhul (EU)
Not really, latency influences the time when the cooldown actually starts. There are three important events when you cast a spell :

-The time your client tells you the cd is over
-The time you launch the spell (client side)
-The time it takes for the server to confirm to your client that the spell is cast (this is where latency comes into play)

The important thing to know is that when you are almost off the gcd or the cd of a spell, your client can send a cast request to the server (this change was done recently, during BC). However, the server still has to confirm that you can (and did) cast the spell, this is the latency we experience. This is also why people like me with an average of 8 ms ping, sometimes have between 100 ms and 300ms of latency while casting a spell. It comes from the server taking time to process the information my client sends.

PS: forgive my english, I am french. If I am not clear enough, I can try to explain it differently.

Offline
Reply With Quote
Old 02/05/09, 2:02 AM   #10
zengir
Glass Joe
 
Human Paladin
 
Defias Brotherhood (EU)
Well, the simple way would be to just make the GCD a bit longer, and I think it would actually be pretty close to the truth.

What happens is probably something like this: (Let's assume 200ms latency and lightning reflexes)

0.00 You press a button to cast a spell.
0.20 The spell get's casted (This includes sending a message to the server, and getting a response)
0.20 Your GCD is started.
1.70 your GCD ends
1.70 You press a button to cast a spell
1.90 The spell get's casted (This includes sending a message to the server, and getting a response)
1.90 Your GCD is started.

The best way to implement it would simply be to add your latency to the timer right before every cast, and only then. That would solve most problems with CD's and GCD, although it will mess things up if you're using melee dmg in your script.

Offline
Reply With Quote
Old 02/06/09, 9:01 AM   #11
zengir
Glass Joe
 
Human Paladin
 
Defias Brotherhood (EU)
I added latency to my application, and some simple calculations shows that there's quite a large amount of DPS lost due to latency. I added latency right before a spell is cast, which should be pretty close to reality.

With average numbers from my latest WWS my tool suggests 4190DPS with a CS>JoM>DS>Cons rotation and 0ms latency in a 240sec fight. With 100ms latency I'm down to 4017DPS, 200ms puts me down another step to 3820DPS.

With a few extra calculations on different sets of gears, different latencies and different lengths of fights my calculations suggests there is about 3-5% of DPS loss for every 100ms latency added, which is quite substantial.

Offline
Reply With Quote
Old 02/06/09, 1:36 PM   #12
Left
Don Flamenco
 
Left's Avatar
 
Draenei Paladin
 
Darkspear
Zengir, I've noticed a similar loss progression with my version of the script. I'd be interested to run some identical test cases with your script and my script and verify that they come up with essentially the same thing. Do you have a link posted to where your script can be downloaded/used? Or do you want to run some cases, let me know the results, and then I can run the same ones?

---------------

As for other tests, I was asked to do a couple of things with the script. One was to verify that any amount of delay prior to judgment was a bad idea in the long run. (IE, to verify that FCFS has no exceptions to the "if something is off cooldown, use it" rule.) To do this, I ran eight tests: with/without 4pT7 vs. with/without delay before judgement, at latency = 0 sec and latency = 0.200 sec. Damage numbers were pulled straight from Redcape's spreadsheet. (Exemplar, I checked yours but I couldn't find where in all those cells you had a damage-per-cast number for the various abilities; all I saw was DPS. Am I missing something?)

All tests were run for a 300 second (5 minute) fight duration. I commented out the simulation log, so only the results came through. In all test cases I assumed an undead target, ie, Exorcism and HW were valid attacks. (This also more accurately simulates 3.1, given the upcoming Exorcism change.) I was using my updated version, v002, of the script, as currently displayed in the first post.

Here are the results (sorry for the wall of text):

Test 1
4pT7 = False
Delay before Judgement (if within 0.5 seconds) = False
Latency = 0.000 sec

RESULTS:
GCD density: 85.0 %

---Abilities Used---
Judgement: 36
Crusader Strike: 45
Consecrate: 27 ( 270.0 ticks)
Divine Storm: 27
Exorcism: 18
Holy Wrath: 9
Hammer of Wrath: 0
Divine Plea: 5
Seal of Blood: 3

---Average Usage Interval---
Judgement: 8.56 sec
Crusader Strike: 6.66 sec
Consecrate: 11.04 sec
Divine Storm: 11.21 sec
Exorcism: 16.88 sec
Holy Wrath: 33.5 sec
Divine Plea: 63.0 sec
Seal of Blood: 97.0 sec

---Damage---
Judgement: 476244
Crusader Strike: 226080
Consecrate: 156843
Divine Storm: 172287
Exorcism: 68436
Holy Wrath: 25200
Hammer of Wrath: 0
TOTAL: 1125090
DPS: 3750.3
(NOTE: Does not include any estimate of white DPS)
Test 2
4pT7 = False
Delay before Judgement (if within 0.5 seconds) = True
Latency = 0.000 sec

RESULTS:
GCD density: 83.0 %

---Abilities Used---
Judgement: 37
Crusader Strike: 37
Consecrate: 28 ( 280.0 ticks)
Divine Storm: 28
Exorcism: 19
Holy Wrath: 9
Hammer of Wrath: 0
Divine Plea: 5
Seal of Blood: 3

---Average Usage Interval---
Judgement: 8.12 sec
Crusader Strike: 8.12 sec
Consecrate: 10.91 sec
Divine Storm: 10.93 sec
Exorcism: 16.11 sec
Holy Wrath: 32.56 sec
Divine Plea: 65.12 sec
Seal of Blood: 95.83 sec

---Damage---
Judgement: 489473
Crusader Strike: 185888
Consecrate: 162652
Divine Storm: 178668
Exorcism: 72238
Holy Wrath: 25200
Hammer of Wrath: 0
TOTAL: 1114119
DPS: 3713.73
(NOTE: Does not include any estimate of white DPS)

Test 3
4pT7 = True
Delay before Judgement (if within 0.5 seconds) = False
Latency = 0.000 sec

RESULTS:
GCD density: 86.0 %

---Abilities Used---
Judgement: 41
Crusader Strike: 41
Consecrate: 27 ( 270.0 ticks)
Divine Storm: 27
Exorcism: 19
Holy Wrath: 9
Hammer of Wrath: 0
Divine Plea: 5
Seal of Blood: 3

---Average Usage Interval---
Judgement: 7.35 sec
Crusader Strike: 7.35 sec
Consecrate: 11.04 sec
Divine Storm: 11.25 sec
Exorcism: 16.28 sec
Holy Wrath: 32.5 sec
Divine Plea: 66.12 sec
Seal of Blood: 95.83 sec

---Damage---
Judgement: 542389
Crusader Strike: 205984
Consecrate: 156843
Divine Storm: 172287
Exorcism: 72238
Holy Wrath: 25200
Hammer of Wrath: 0
TOTAL: 1174941
DPS: 3916.47
(NOTE: Does not include any estimate of white DPS)
Test 4
4pT7 = True
Delay before Judgement (if within 0.5 seconds) = True
Latency = 0.000 sec

RESULTS:
GCD density: 84.5 %

---Abilities Used---
Judgement: 42
Crusader Strike: 42
Consecrate: 26 ( 260.0 ticks)
Divine Storm: 25
Exorcism: 17
Holy Wrath: 9
Hammer of Wrath: 0
Divine Plea: 5
Seal of Blood: 3

---Average Usage Interval---
Judgement: 7.24 sec
Crusader Strike: 7.24 sec
Consecrate: 11.58 sec
Divine Storm: 12.06 sec
Exorcism: 17.59 sec
Holy Wrath: 35.62 sec
Divine Plea: 72.0 sec
Seal of Blood: 96.83 sec

---Damage---
Judgement: 555618
Crusader Strike: 211008
Consecrate: 151034
Divine Storm: 159525
Exorcism: 64634
Holy Wrath: 25200
Hammer of Wrath: 0
TOTAL: 1167019
DPS: 3890.06
(NOTE: Does not include any estimate of white DPS)
Test 5
4pT7 = False
Delay before Judgement (if within 0.5 seconds) = False
Latency = 0.200 sec

RESULTS:
GCD density: 91.8 %

---Abilities Used---
Judgement: 35
Crusader Strike: 43
Consecrate: 26 ( 265.2 ticks)
Divine Storm: 25
Exorcism: 17
Holy Wrath: 9
Hammer of Wrath: 0
Divine Plea: 5
Seal of Blood: 2

---Average Usage Interval---
Judgement: 8.76 sec
Crusader Strike: 7.09 sec
Consecrate: 11.64 sec
Divine Storm: 11.77 sec
Exorcism: 17.34 sec
Holy Wrath: 34.89 sec
Divine Plea: 68.92 sec
Seal of Blood: 97.9 sec

---Damage---
Judgement: 463015
Crusader Strike: 216032
Consecrate: 151034
Divine Storm: 159525
Exorcism: 64634
Holy Wrath: 25200
Hammer of Wrath: 0
TOTAL: 1079440
DPS: 3598.13
(NOTE: Does not include any estimate of white DPS)
Test 6
4pT7 = False
Delay before Judgement (if within 0.5 seconds) = True
Latency = 0.200 sec

RESULTS:
GCD density: 90.67 %

---Abilities Used---
Judgement: 36
Crusader Strike: 36
Consecrate: 27 ( 275.4 ticks)
Divine Storm: 26
Exorcism: 18
Holy Wrath: 9
Hammer of Wrath: 0
Divine Plea: 5
Seal of Blood: 3

---Average Usage Interval---
Judgement: 8.46 sec
Crusader Strike: 8.46 sec
Consecrate: 11.39 sec
Divine Storm: 11.5 sec
Exorcism: 16.72 sec
Holy Wrath: 34.04 sec
Divine Plea: 64.25 sec
Seal of Blood: 99.8 sec

---Damage---
Judgement: 476244
Crusader Strike: 180864
Consecrate: 156843
Divine Storm: 165906
Exorcism: 68436
Holy Wrath: 25200
Hammer of Wrath: 0
TOTAL: 1073493
DPS: 3578.31
(NOTE: Does not include any estimate of white DPS)
Test 7
4pT7 = True
Delay before Judgement (if within 0.5 seconds) = False
Latency = 0.200 sec

RESULTS:
GCD density: 94.07 %

---Abilities Used---
Judgement: 38
Crusader Strike: 38
Consecrate: 27 ( 275.4 ticks)
Divine Storm: 26
Exorcism: 19
Holy Wrath: 10
Hammer of Wrath: 0
Divine Plea: 5
Seal of Blood: 3

---Average Usage Interval---
Judgement: 7.91 sec
Crusader Strike: 7.91 sec
Consecrate: 11.38 sec
Divine Storm: 11.7 sec
Exorcism: 15.78 sec
Holy Wrath: 31.56 sec
Divine Plea: 65.05 sec
Seal of Blood: 95.77 sec

---Damage---
Judgement: 502702
Crusader Strike: 190912
Consecrate: 156843
Divine Storm: 165906
Exorcism: 72238
Holy Wrath: 28000
Hammer of Wrath: 0
TOTAL: 1116601
DPS: 3722.0
(NOTE: Does not include any estimate of white DPS)
Test 8
4pT7 = True
Delay before Judgement (if within 0.5 seconds) = True
Latency = 0.200 sec

RESULTS:
GCD density: 89.53 %

---Abilities Used---
Judgement: 41
Crusader Strike: 41
Consecrate: 22 ( 224.4 ticks)
Divine Storm: 21
Exorcism: 17
Holy Wrath: 8
Hammer of Wrath: 0
Divine Plea: 5
Seal of Blood: 3

---Average Usage Interval---
Judgement: 7.39 sec
Crusader Strike: 7.39 sec
Consecrate: 13.73 sec
Divine Storm: 14.41 sec
Exorcism: 18.02 sec
Holy Wrath: 36.71 sec
Divine Plea: 64.87 sec
Seal of Blood: 97.17 sec

---Damage---
Judgement: 542389
Crusader Strike: 205984
Consecrate: 127798
Divine Storm: 134001
Exorcism: 64634
Holy Wrath: 22400
Hammer of Wrath: 0
TOTAL: 1097206
DPS: 3657.35
(NOTE: Does not include any estimate of white DPS)
In other words, delaying for judgement does cause a small DPS loss in every single case tested. This is a confirmation of FCFS "conventional wisdom." One interesting result is that doing a judgement delay when not using 4pT7 seems to consistently conflict with Crusader Strike coming off cooldown immediately before judgement, thus Crusader Strike's cooldown gets artificially set to Judgement's cooldown. Without the delay, CS and J interweave more easily in a non-4pT7 environment.

Also note that latency in and of itself causes ~100 DPS difference per 0.1 second of latency, at least as modeled here.

Last edited by Left : 02/06/09 at 1:45 PM.

Offline
Reply With Quote
Old 02/06/09, 3:07 PM   #13
Exemplar
Bald Bull
 
Human Paladin
 
Scarlet Crusade
Brilliant. Left, sent you a PM with directions to find average dam per cast in my spreadsheet.

I'm going to try to install Python and run some tests with your script (not that I don't trust your results). Start modeling the new Exo but no HW (3.1 assumptions) in 7 and 8 seconds. Also some borderline cases I was considering while I was staring at manual models. Like if Judge is under 0.5 seconds and Exo is up, skip Exo, but not the other abilities. Or CS. Etc. If I find anything unusual I'll post it here. I suspect it may sometimes be a win to pause that half second, but this is a gut instinct and against common wisdom and all our math to date.

Great tool, I plan to use it to enhance the next version of the spreadsheet that I release (with yet more accurate rotation information - probably extrapolating out to 6hrs as recommended earlier in this thread). I highly recommend those using Redcape's excellent spreadsheet also use this to figure out their own real-world rotations.

Offline
Reply With Quote
Old 02/06/09, 7:37 PM   #14
zengir
Glass Joe
 
Human Paladin
 
Defias Brotherhood (EU)
My application can be downloaded here:
RapidShare: Easy Filehosting
I think you need .NET 3.5 framework to run it.

It's far from complete, and not the least bit user-friendly. I made it purely for my own use, but you're all welcome to try it out. It should be pretty self-explanatory, but just send me PM if there's something you're wondering. The same goes if you have any suggestions or requests.

Offline
Reply With Quote
Old 02/07/09, 3:42 PM   #15
 frmorrison
Protector
 
frmorrison's Avatar
 
Ashstrike
Human Paladin
 
No WoW Account
Your application loads, however it has issues with what the priority setting should be. Also, you can enter the same priority for abilities to get strange results.

Also, it should include Exorcism 15 second cooldown.

United States Offline
Reply With Quote
Reply

Go Back   Elitist Jerks » Class Mechanics » Paladins

Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
Envenom Modeling Aldriana Rogues 86 01/25/09 10:53 AM
Script for Rapidly Marking Targets Astrylian User Interface and AddOns 31 02/29/08 8:42 PM
Resizing Quartz cast bars with /script? diospadre User Interface and AddOns 1 01/08/08 6:14 PM
Modeling Flurry with DW and WF Vulajin Public Discussion 38 12/03/06 5:12 PM