Kay, I throw this script into the pool for discussion.
! = indicates that me:get_weapon_delay() is used to calculate the values (switches after 50 hits!)
sd = standard deviation
hps = hits/s
Med = Median
kpm = kill per minute
Code: Select all
auxbox_next_line = 0
function auxbox()
auxbox_lm_dpscalc () -- has to be called always
d:auxbox_clear();
auxbox_next_line = 0
auxbox_lm_time() -- Total Time : 00:00:00
auxbox_lm_hits() -- Total Hits : XXX
auxbox_lm_kills() -- Total Kills: XXX
auxbox_lm_xp_gained() -- XP gained : XXX
auxbox_lm_xpps() -- XP/sec : XXX
auxbox_lm_xppm() -- XP/min : XXX
auxbox_lm_dmg() -- Total dmg : XXX
auxbox_lm_dps() -- Dps from total Values: XXX
auxbox_blank_line()
auxbox_lm_mean_dmg() -- mean: XXX dmg YYY dps
auxbox_lm_sd_dmg() -- sd : XXX dmg YYY dps
auxbox_lm_median_dmg() -- med : XXX dmg YYY dps
auxbox_lm_minmax_dmg() -- min : XXX dmg YYY dps
-- max : XXX dmg YYY dps
auxbox_lm_last4dmg() -- dmg : XXX XXX XXX XXX
auxbox_blank_line()
auxbox_lm_mean_hps() -- mean: XXX hps
auxbox_lm_sd_hps() -- sd : XXX hps
auxbox_lm_median_hps() -- med : XXX hps
auxbox_lm_minmax_hps() -- min : XXX hps
-- max : XXX hps
auxbox_lm_last4hps() -- hps : XXX XXX XXX XXX
auxbox_blank_line()
auxbox_lm_mean_xp() -- mean: XXX xp YYY xps
auxbox_lm_sd_xp() -- sd : XXX xp YYY xps
auxbox_lm_median_xp() -- med : XXX xp YYY xps
auxbox_lm_minmax_xp() -- min : XXX xp YYY xps
-- max : XXX xp YYY xps
auxbox_lm_last4xp() -- xp : XXX XXX XXX XXX
auxbox_blank_line()
auxbox_lm_mean_kpm() -- mean: XXX kpm
auxbox_lm_sd_kpm() -- sd : XXX kpm
auxbox_lm_median_kpm() -- med : XXX kpm
auxbox_lm_minmax_kpm() -- min : XXX kpm
-- max : XXX kpm
auxbox_lm_last4kpm() -- kpm : XXX XXX XXX XXX
end
function auxbox_prop_line(prop_name, prop_val)
local filler = string.rep(" ", 25 - string.len(prop_name) - string.len(prop_val))
auxbox_next_line = auxbox_next_line + 1
d:auxbox_set_line(auxbox_next_line, string.format("%s %s %s", prop_name, filler, prop_val))
end
function auxbox_blank_line()
auxbox_next_line = auxbox_next_line + 1
end
old_build = {me:get_float_str(),
me:get_float_dex(),
me:get_float_intel(),
wl:get_full_name(me.weapon),
wl:get_full_name(me.shield),
wl:get_full_name(me.armour),
wl:get_full_name(me.boots),
wl:get_full_name(me.gloves),
wl:get_full_name(me.hat),
wl:get_full_name(me.trousers),
wl:get_full_name(me.ring1),
wl:get_full_name(me.ring2),
wl:get_full_name(me.amulet),
wl:get_full_name(me.sigil1),
wl:get_full_name(me.sigil2),
wl:get_full_name(me.sigil3)}
lm_last_dpst = g_dpst
lm_dmg_log = {}
lm_dmgtime_log = {}
lm_hit_count = 0
lm_last_xp = me.xp
lm_xp_log = {}
lm_xptime_log = {}
lm_kill_count = 0
function auxbox_lm_dpscalc ()
local new_build = {me:get_float_str(),
me:get_float_dex(),
me:get_float_intel(),
wl:get_full_name(me.weapon),
wl:get_full_name(me.shield),
wl:get_full_name(me.armour),
wl:get_full_name(me.boots),
wl:get_full_name(me.gloves),
wl:get_full_name(me.hat),
wl:get_full_name(me.trousers),
wl:get_full_name(me.ring1),
wl:get_full_name(me.ring2),
wl:get_full_name(me.amulet),
wl:get_full_name(me.sigil1),
wl:get_full_name(me.sigil2),
wl:get_full_name(me.sigil3)}
for i=1,#old_build do
if old_build[i] ~= new_build[i] then
table.remove (old_build, i)
table.insert (old_build, i, new_build[i])
for i,v in pairs(lm_dmg_log) do
lm_dmg_log[i]=nil
end
for i,v in pairs(lm_dmgtime_log) do
lm_dmgtime_log[i]=nil
end
for i,v in pairs(lm_xp_log) do
lm_dmg_log[i]=nil
end
for i,v in pairs(lm_xptime_log) do
lm_dmgtime_log[i]=nil
end
lm_hit_count = 0
lm_kill_count = 0
end
end
if lm_hit_count == 0 then
lm_hunt_start = os.clock()
lm_last_killtime = os.clock()
lm_dmg_start = g_dpst
lm_xp_start = me.xp
end
lm_hunt_time = os.clock() - lm_hunt_start
lm_total_dmg = g_dpst - lm_dmg_start
lm_xp_gained = me.xp - lm_xp_start
local lm_dmgtime_dif
local lm_dmg_dif
if lm_last_dpst ~= g_dpst then
if lm_hit_count >= 1 then
lm_dmgtime_dif = os.clock() - lm_last_hittime
lm_dmg_dif = g_dpst - lm_last_dpst
--if lm_dmgtime_dif > (me:get_weapon_delay() / 1000) * 0.5 then
if lm_dmgtime_dif < (me:get_weapon_delay() / 1000) * 1.5 then
table.insert(lm_dmgtime_log, 1, lm_dmgtime_dif)
table.insert(lm_dmg_log, 1, lm_dmg_dif)
end
--end
end
lm_last_hittime = os.clock()
lm_last_dpst = g_dpst
lm_hit_count = lm_hit_count + 1
end
local lm_xptime_dif
local lm_xp_dif
if lm_last_xp ~= me.xp and lm_hit_count >= 1 then
lm_kill_count = lm_kill_count + 1
lm_xptime_dif = os.clock() - lm_last_killtime
table.insert(lm_xptime_log, 1, lm_xptime_dif)
lm_last_killtime = os.clock()
lm_xp_dif = me.xp - lm_last_xp
table.insert(lm_xp_log, 1, lm_xp_dif)
lm_last_xp = me.xp
end
local temp_lm_dmgtime_log={} -- for median time
local lm_dmgtime_count = 0
lm_max_hps = -math.huge -- for max time
lm_min_hps = math.huge -- for min time
lm_dmgtime_sum = 0
if lm_dmgtime_log[1] ~= nil then
for i,v in pairs(lm_dmgtime_log) do
if type(v) == 'number' then
lm_dmgtime_sum = lm_dmgtime_sum + v
lm_dmgtime_count = lm_dmgtime_count + 1
table.insert(temp_lm_dmgtime_log, v) -- for median time
lm_min_hps = 1 / (math.max(lm_max_hps, v))
lm_max_hps = 1 / (math.min(lm_min_hps, v))
if lm_dmgtime_count >= 500 then
table.remove(lm_dmgtime_log, 500)
end
end
end
lm_mean_hps = 1 / ((lm_dmgtime_sum / lm_dmgtime_count))
else
lm_mean_hps = 0
lm_max_hps = 0
lm_min_hps = 0
end
-- standard deviation time
local dmgtime_vm
local lm_dmgtime_sum_sd = 0
local lm_dmgtime_count_sd = 0
if lm_dmgtime_log[2] ~= nil then
for i,v in pairs(lm_dmgtime_log) do
if type(v) == 'number' then
dmgtime_vm = v - lm_mean_hps
lm_dmgtime_sum_sd = lm_dmgtime_sum_sd + (dmgtime_vm * dmgtime_vm)
lm_dmgtime_count_sd = lm_dmgtime_count_sd + 1
end
end
lm_sd_hps = 1 / (math.sqrt(lm_dmgtime_sum_sd / (lm_dmgtime_count_sd-1)))
else
lm_sd_hps = 0
end
-- median time
if temp_lm_dmgtime_log[50] ~= nil then
table.sort(temp_lm_dmgtime_log)
asterisk = " "
-- If we have an even number of table elements or odd.
if math.fmod(#temp_lm_dmgtime_log,2) == 0 then
-- return mean value of middle two elements
lm_median_hps = 1 / ((temp_lm_dmgtime_log[#temp_lm_dmgtime_log/2] + temp_lm_dmgtime_log[(#temp_lm_dmgtime_log/2)+1]) / 2)
else
-- return middle element
lm_median_hps = 1 / (temp_lm_dmgtime_log[math.ceil(#temp_lm_dmgtime_log/2)])
end
else
if wl:is_weapon(me.shield)==true then
lm_median_hps = 1 / ((me:get_weapon_delay()/1000)) * 1.6
else
lm_median_hps = 1 / (me:get_weapon_delay()/1000)
end
asterisk = "!"
end
-- mean/max/min damage
local temp_lm_dmg_log={} -- for median dmg
lm_dmg_sum = 0
lm_dmg_count = 0
lm_max_dmg = -math.huge -- for max dmg
lm_min_dmg = math.huge -- for min dmg
if lm_dmg_log[1] ~= nil then
for i,v in pairs(lm_dmg_log) do
if type(v) == 'number' then
lm_dmg_sum = lm_dmg_sum + v
lm_dmg_count = lm_dmg_count + 1
table.insert(temp_lm_dmg_log, v) -- for median dmg
lm_max_dmg = math.max(lm_max_dmg, v)
lm_min_dmg = math.min(lm_min_dmg, v)
if lm_dmg_count >= 500 then
table.remove(lm_dmg_log, 500)
end
end
end
lm_mean_dmg = (lm_dmg_sum / lm_dmg_count)
else
lm_mean_dmg = 0
lm_max_dmg = 0
lm_min_dmg = 0
end
-- mean dps
lm_mean_dps = lm_mean_dmg * lm_median_hps
-- standard deviation damage
local vm
local sum_sd = 0
local count_sd = 0
if lm_dmg_log[2] ~= nil then
for i,v in pairs(lm_dmg_log) do
if type(v) == 'number' then
vm = v - lm_mean_dmg
sum_sd = sum_sd + (vm * vm)
count_sd = count_sd + 1
end
end
lm_sd_dmg = math.sqrt(sum_sd / (count_sd-1))
else
lm_sd_dmg = 0
end
-- standard deviation dps
lm_sd_dps = lm_sd_dmg * lm_median_hps
-- median damage
if temp_lm_dmg_log[1] ~= nil then
table.sort(temp_lm_dmg_log)
-- If we have an even number of table elements or odd.
if math.fmod(#temp_lm_dmg_log,2) == 0 then
-- return mean value of middle two elements
lm_median_dmg = ( temp_lm_dmg_log[#temp_lm_dmg_log/2] + temp_lm_dmg_log[(#temp_lm_dmg_log/2)+1] ) / 2
else
-- return middle element
lm_median_dmg = temp_lm_dmg_log[math.ceil(#temp_lm_dmg_log/2)]
end
else
lm_median_dmg = 0
end
-- median dps
lm_median_dps = lm_median_dmg * lm_median_hps
-- min dps
lm_min_dps = lm_min_dmg * lm_median_hps
-- max dps
lm_max_dps = lm_max_dmg * lm_median_hps
--------------------------------------------------------------------------------
local temp_lm_xptime_log={} -- for median time
local lm_xptime_count = 0
lm_max_kpm = -math.huge -- for max time
lm_min_kpm = math.huge -- for min time
lm_xptime_sum = 0
if lm_xptime_log[1] ~= nil then
for i,v in pairs(lm_xptime_log) do
if type(v) == 'number' then
lm_xptime_sum = lm_xptime_sum + v
lm_xptime_count = lm_xptime_count + 1
table.insert(temp_lm_xptime_log, v) -- for median time
lm_min_kpm = 1 / (math.max(lm_max_kpm, v))
lm_max_kpm = 1 / (math.min(lm_min_kpm, v))
if lm_xptime_count >= 500 then
table.remove(lm_xptime_log, 500)
end
end
end
lm_mean_kpm = (1 / ((lm_xptime_sum / lm_xptime_count))) * 60
else
lm_mean_kpm = 0
lm_max_kpm = 0
lm_min_kpm = 0
end
-- standard deviation time
local xptime_vm
local lm_xptime_sum_sd = 0
local lm_xptime_count_sd = 0
if lm_xptime_log[2] ~= nil then
for i,v in pairs(lm_xptime_log) do
if type(v) == 'number' then
xptime_vm = v - lm_mean_kpm
lm_xptime_sum_sd = lm_xptime_sum_sd + (xptime_vm * xptime_vm)
lm_xptime_count_sd = lm_xptime_count_sd + 1
end
end
lm_sd_kpm = (1 / (math.sqrt(lm_xptime_sum_sd / (lm_xptime_count_sd-1)))) * 60
else
lm_sd_kpm = 0
end
-- median time
if temp_lm_xptime_log[2] ~= nil then
table.sort(temp_lm_xptime_log)
-- If we have an even number of table elements or odd.
if math.fmod(#temp_lm_xptime_log,2) == 0 then
-- return mean value of middle two elements
lm_median_kpm = (1 / ((temp_lm_xptime_log[#temp_lm_xptime_log/2] + temp_lm_xptime_log[(#temp_lm_xptime_log/2)+1]) / 2)) * 60
else
-- return middle element
lm_median_kpm = (1 / (temp_lm_xptime_log[math.ceil(#temp_lm_xptime_log/2)])) * 60
end
else
lm_median_kpm = 0
end
-- mean/max/min xp
local temp_lm_xp_log={} -- for median xp
lm_xp_sum = 0
lm_xp_count = 0
lm_max_xp = -math.huge -- for max xp
lm_min_xp = math.huge -- for min xp
if lm_xp_log[1] ~= nil then
for i,v in pairs(lm_xp_log) do
if type(v) == 'number' then
lm_xp_sum = lm_xp_sum + v
lm_xp_count = lm_xp_count + 1
table.insert(temp_lm_xp_log, v) -- for median xp
lm_max_xp = math.max(lm_max_xp, v)
lm_min_xp = math.min(lm_min_xp, v)
if lm_xp_count >= 500 then
table.remove(lm_xp_log, 500)
end
end
end
lm_mean_xp = (lm_xp_sum / lm_xp_count)
else
lm_mean_xp = 0
lm_max_xp = 0
lm_min_xp = 0
end
-- mean, min, max kpm
lm_mean_xps = lm_mean_xp * (lm_median_kpm / 60)
lm_min_xps = lm_min_xp * (lm_median_kpm / 60)
lm_max_xps = lm_max_xp * (lm_median_kpm / 60)
-- standard deviation xp
local xpvm
local xpsum_sd = 0
local xpcount_sd = 0
if lm_xp_log[2] ~= nil then
for i,v in pairs(lm_xp_log) do
if type(v) == 'number' then
xpvm = v - lm_mean_xp
xpsum_sd = xpsum_sd + (xpvm * xpvm)
xpcount_sd = xpcount_sd + 1
end
end
lm_sd_xp = math.sqrt(xpsum_sd / (xpcount_sd-1))
else
lm_sd_xp = 0
end
-- standard deviation kpm
lm_sd_xps = lm_sd_xp * (lm_median_kpm / 60)
-- median xp
if temp_lm_xp_log[1] ~= nil then
table.sort(temp_lm_xp_log)
-- If we have an even number of table elements or odd.
if math.fmod(#temp_lm_xp_log,2) == 0 then
-- return mean value of middle two elements
lm_median_xp = ( temp_lm_xp_log[#temp_lm_xp_log/2] + temp_lm_xp_log[(#temp_lm_xp_log/2)+1] ) / 2
else
-- return middle element
lm_median_xp = temp_lm_xp_log[math.ceil(#temp_lm_xp_log/2)]
end
else
lm_median_xp = 0
end
-- median kpm
lm_median_xps = lm_median_xp * (lm_median_kpm / 60)
end
function auxbox_lm_hits()
auxbox_prop_line("Total Hits :", string.format("%d",lm_hit_count))
end
function auxbox_lm_time()
h = math.floor(lm_hunt_time / 60 / 60)
m = math.floor((lm_hunt_time / 60 / 60 - h) * 60)
s = math.floor(((lm_hunt_time / 60 / 60 - h) * 60 - m) * 60)
--ms = ((((lm_hunt_time / 60 / 60 - h) * 60 - m) * 60) - s) * 1000
auxbox_prop_line("Total Time :", string.format("%02.f:%02.f:%02.f", h, m, s))
end
function auxbox_lm_dmg()
auxbox_prop_line("Total Dmg :", string.format("%d",lm_total_dmg))
end
function auxbox_lm_dps()
auxbox_prop_line("Total Dps :", string.format("%d",lm_total_dmg/lm_hunt_time))
end
function auxbox_lm_mean_dmg()
auxbox_prop_line("Mean :", string.format("%4.f dmg %4.f%s dps", lm_mean_dmg, lm_mean_dps, asterisk))
end
function auxbox_lm_sd_dmg()
auxbox_prop_line("Sd :", string.format("%4.f dmg %4.f%s dps", lm_sd_dmg, lm_sd_dps, asterisk))
end
function auxbox_lm_median_dmg()
auxbox_prop_line("Med :", string.format("%4.f dmg %4.f%s dps", lm_median_dmg, lm_median_dps, asterisk))
end
function auxbox_lm_minmax_dmg()
auxbox_prop_line("Min :", string.format("%4.f dmg %4.f%s dps", lm_min_dmg, lm_min_dps, asterisk))
auxbox_prop_line("Max :", string.format("%4.f dmg %4.f%s dps", lm_max_dmg, lm_max_dps, asterisk))
end
function auxbox_lm_last4dmg()
local hit1, hit2, hit3, hit4
if lm_dmg_log[1] ~= nill then hit1 = lm_dmg_log[1] else hit1 = 0 end
if lm_dmg_log[2] ~= nill then hit2 = lm_dmg_log[2] else hit2 = 0 end
if lm_dmg_log[3] ~= nill then hit3 = lm_dmg_log[3] else hit3 = 0 end
if lm_dmg_log[4] ~= nill then hit4 = lm_dmg_log[4] else hit4 = 0 end
auxbox_prop_line("dmg :", string.format("%4.f %4.f %4.f %4.f", hit4, hit3, hit2, hit1))
end
function auxbox_lm_mean_hps()
auxbox_prop_line("Mean :", string.format("%.2f hps", lm_mean_hps))
end
function auxbox_lm_sd_hps()
auxbox_prop_line("Sd :", string.format("%.2f hps", lm_sd_hps))
end
function auxbox_lm_median_hps()
auxbox_prop_line("Med :", string.format("%.2f%s hps", lm_median_hps, asterisk))
end
function auxbox_lm_minmax_hps()
auxbox_prop_line("Min :", string.format("%4.2f hps", lm_min_hps))
auxbox_prop_line("Max :", string.format("%4.2f hps", lm_max_hps))
end
function auxbox_lm_last4hps()
local hit1, hit2, hit3, hit4
if lm_dmgtime_log[1] ~= nill then hit1 = 1 / lm_dmgtime_log[1] else hit1 = 0 end
if lm_dmgtime_log[2] ~= nill then hit2 = 1 / lm_dmgtime_log[2] else hit2 = 0 end
if lm_dmgtime_log[3] ~= nill then hit3 = 1 / lm_dmgtime_log[3] else hit3 = 0 end
if lm_dmgtime_log[4] ~= nill then hit4 = 1 / lm_dmgtime_log[4] else hit4 = 0 end
auxbox_prop_line("hps :", string.format("%4.2f %4.2f %4.2f %4.2f", hit4, hit3, hit2, hit1))
end
function auxbox_lm_kills()
auxbox_prop_line("Total Kills :", string.format("%d", lm_kill_count))
end
function auxbox_lm_xp_gained()
auxbox_prop_line("Total XP :", string.format("%d", lm_xp_gained))
end
function auxbox_lm_xpps()
auxbox_prop_line("Total XP/s :", string.format("%d", lm_xp_gained / lm_hunt_time))
end
function auxbox_lm_xppm()
auxbox_prop_line("Total XP/min:", string.format("%d", lm_xp_gained / lm_hunt_time * 60))
end
function auxbox_lm_mean_xp()
auxbox_prop_line("Mean :", string.format("%4.f xp %4.f xps", lm_mean_xp, lm_mean_xps))
end
function auxbox_lm_sd_xp()
auxbox_prop_line("Sd :", string.format("%4.f xp %4.f xps", lm_sd_xp, lm_sd_xps))
end
function auxbox_lm_median_xp()
auxbox_prop_line("Med :", string.format("%4.f xp %4.f xps", lm_median_xp, lm_median_xps))
end
function auxbox_lm_minmax_xp()
auxbox_prop_line("Min :", string.format("%4.f xp %4.f xps", lm_min_xp, lm_min_xps))
auxbox_prop_line("Max :", string.format("%4.f xp %4.f xps", lm_max_xp, lm_max_xps))
end
function auxbox_lm_last4xp()
local kill1, kill2, kill3, kill4
if lm_xp_log[1] ~= nill then kill1 = lm_xp_log[1] else kill1 = 0 end
if lm_xp_log[2] ~= nill then kill2 = lm_xp_log[2] else kill2 = 0 end
if lm_xp_log[3] ~= nill then kill3 = lm_xp_log[3] else kill3 = 0 end
if lm_xp_log[4] ~= nill then kill4 = lm_xp_log[4] else kill4 = 0 end
auxbox_prop_line("xp :", string.format("%4.f %4.f %4.f %4.f", kill4, kill3, kill2, kill1))
end
function auxbox_lm_mean_kpm()
auxbox_prop_line("Mean :", string.format("%d kpm", lm_mean_kpm))
end
function auxbox_lm_sd_kpm()
auxbox_prop_line("Sd :", string.format("%d kpm", lm_sd_kpm))
end
function auxbox_lm_median_kpm()
auxbox_prop_line("Med :", string.format("%d kpm", lm_median_kpm))
end
function auxbox_lm_minmax_kpm()
auxbox_prop_line("Min :", string.format("%d kpm", lm_min_kpm))
auxbox_prop_line("Max :", string.format("%d kpm", lm_max_kpm))
end
function auxbox_lm_last4kpm()
local kill1, hit2, hit3, hit4
if lm_xptime_log[1] ~= nill then kill1 = 1 / lm_xptime_log[1] * 60 else kill1 = 0 end
if lm_xptime_log[2] ~= nill then kill2 = 1 / lm_xptime_log[2] * 60 else kill2 = 0 end
if lm_xptime_log[3] ~= nill then kill3 = 1 / lm_xptime_log[3] * 60 else kill3 = 0 end
if lm_xptime_log[4] ~= nill then kill4 = 1 / lm_xptime_log[4] * 60 else kill4 = 0 end
auxbox_prop_line("kpm :", string.format("%4.0f %4.0f %4.0f %4.0f", kill4, kill3, kill2, kill1))
end
P.S.: Script resets on weapon change and collects 500 data points for damage to do statistics - I guess you can increase the amount without performance issues.
P.P.S.: Never trust any statistics you haven't cheesed yourself!
Edit: now with last 5 hits
Edit: hits after 150% of weapon delay will be neglected in time statistics
Edit: hits under 50% of weapon delay will be added to the next hit - experimental (dual wielding gives me a headache)