#!/sw/bin/python2.5
# $Id: catmodel.py 76 2007-06-09 08:23:24Z sas $
from numpy import *
import os
import pylab as p
import matplotlib.axes3d as p3
from random import random
class CatModel:
def computeDps( self, ap, crit, duration = 1000, rip_combolimit = 4,
mob_mitigation = 0.25 ):
pawDps = 56.4
ap_to_dps = 0.0714286
ap_to_rip = 0.24
mangle_bonus = 1.3
ooc_proc = 1./30
str_to_ap = 2.472
agi_to_ap = 1.03
crit_rating_to_crit = 0.0004525
agi_to_crit = 0.000412
base_dmg = ( pawDps + ap * ap_to_dps ) * 1.1 * ( 1 - mob_mitigation )
mangle_dmg = (( 1.6 * base_dmg + 264.0 ) * 1.2 ) * 1.1 * ( 1 - mob_mitigation )
rip_dmg = (( ap * ap_to_rip + 1092.0 ) / 12.0 ) * 1.1
shred_dmg = ( 2.25 * base_dmg + 405 ) * 1.1 * ( 1 - mob_mitigation )
total_dmg = 0.0
energy = 100
mangle_on = 0
rip_on = 0
combo_pts = 0
ooc_on = False
for i in range(duration):
#print 'time: %6i, dmg %5i, energy %3i, combo %i, mangle %2i, rip %2i, ooc %i' % ( i, total_dmg, energy, combo_pts, mangle_on, rip_on, ooc_on )
# energy tick
if i % 2 == 0:
energy += 20
if energy > 100:
energy = 100
mangle_on -= 1
rip_on -= 1
# mangle
if ( mangle_on <= 0 and
energy >= 40 and
combo_pts < rip_combolimit ):
if random() <= crit:
total_dmg += 2.2*mangle_dmg
combo_pts += 2
else:
total_dmg += mangle_dmg
combo_pts += 1
mangle_on = 12
if not ooc_on:
energy -= 40
else:
ooc_on = False
if random() <= ooc_proc:
ooc_on = True
else:
# rip
if ( combo_pts >= rip_combolimit and
energy >= 30 and
rip_on <= 0 ):
rip_on = 12
combo_pts = 0
if not ooc_on:
energy -= 30
else:
ooc_on = False
if random() <= ooc_proc:
ooc_on = True
else:
# shred
if energy >= 42 and mangle_on > 0:
if random() <= crit:
total_dmg += 2.2 * shred_dmg * mangle_bonus
combo_pts += 2
else:
total_dmg += shred_dmg * mangle_bonus
combo_pts += 1
if not ooc_on:
energy -= 42
else:
ooc_on = False
if random() <= ooc_proc:
ooc_on = True
# white damage
if random() <= crit:
total_dmg += 2.2*base_dmg
else:
total_dmg += base_dmg
if random() <= ooc_proc:
ooc_on = True
# rip ticks
if rip_on > 0:
if mangle_on > 0:
total_dmg += rip_dmg * mangle_bonus
else:
total_dmg += rip_dmg
return total_dmg / duration
def plot_ap_crit():
crit, ap = mgrid[28:38, 2000:3000:100]
dps = []
cat = CatModel()
for c in [ i[0] for i in crit ]:
print 'Processing crit chance: ', c
row = []
dps.append( row )
for a in ap[0]:
d = cat.computeDps( ap = a, crit = c/100., duration = 100*1000)
row.append( d )
dps = array( dps )
fig=p.figure()
ax = p3.Axes3D(fig)
ax.plot_wireframe(ap,crit,dps)
ax.set_xlabel('AP')
ax.set_ylabel('Crit')
ax.set_zlabel('dps')
p.savefig('ap_crit.png')
p.show()
import Gnuplot, Gnuplot.funcutils
def plot_agi_str():
crit = arange(30, 40, 2)
ap = arange(2000, 3000, 200)
duration = 10*1000*1000
agi_inc = 50
str_inc = 50
diff = []
cat = CatModel()
for c in crit:
print 'Processing crit chance: ', c
row = []
diff.append( row )
for a in ap:
dps_agi = cat.computeDps( ap = a + agi_inc * 1.03,
crit = c/100. + agi_inc * 0.000412,
duration = duration )
dps_str = cat.computeDps( ap = a + str_inc * 2.472,
crit = c/100.,
duration = duration )
row.append( dps_agi - dps_str )
g = Gnuplot.Gnuplot( debug=1 )
g('set parametric')
g('set data style lines')
g('set hidden')
g('set contour base')
g.title('Agi-Str dps gain')
g.xlabel('AP')
g.ylabel('Crit')
g.splot( Gnuplot.GridData( diff, ap, crit, binary = 0 ) )
g.hardcopy('agi_str.ps', enhanced=1, color=1)
if __name__ == '__main__':
plot_ap_crit()
plot_agi_str()