Module:Sandbox/User:CephHunter/Ruby bolts
Documentation for this module may be created at Module:Sandbox/User:CephHunter/Ruby bolts/doc
-- <nowiki>
require( 'Module:Mw.html extension' )
local chart = require( 'Module:Chart data' )
local yesno = require( 'Module:Yesno' )
local commas = require( 'Module:Addcommas' )._add
local p = {}
local function round( num )
return math.floor( num * 10 + 0.5 ) / 10
end
local function fnum( num )
return commas( round( num ) )
end
local function damage( maxHp, currentHp, cap )
local dmgPercent = math.max( 1, math.floor( 20 * currentHp / maxHp ) ) / 100
local dmg = math.floor( dmgPercent * currentHp )
return math.min( dmg, cap )
end
local function triggerChance( seers, rangeCape, attackSpeed, currentHp )
local cooldown = 10 -- ticks. 6 seconds
local pc = 0.05 -- Proc chance
if seers then
pc = pc + 0.02
end
if rangeCape then
pc = pc * 1.2
end
pc = math.max( 0, pc - math.floor( currentHp / 1e6 ) / 100 )
if attackSpeed then
local c = math.floor( (cooldown - 1) / attackSpeed ) -- Blocked count
-- Calculate average chain length
-- https://www.wolframalpha.com/input/?i=1%2Fsum%28%28n%2Bc%29+*+p*%281-p%29%5E%28n-1%29%2C+n%3D1..inf%29
return 1 / (c + 1 / pc)
end
return pc
end
function p.main( frame )
return p._main( frame:getParent().args )
end
function p._main( args )
local lookup_toggle = yesno( args.lookup_toggle or false )
local max_hp = tonumber( args.max_hp or 100000 )
local monster_Name = args.monster_Name or ''
local current_hp = math.min( tonumber( args.current_hp or 50000 ), max_hp )
local critical = yesno( args.critical or false )
local your_hp = tonumber( args.your_hp or 10000 )
local seers = yesno( args.seers or true )
local ranged_Cape = yesno( args.ranged_Cape or true )
local cap = critical and 12000 or 10000
if lookup_toggle == true then
local data = mw.smw.ask{
'[[' .. monster_Name .. ']]',
'?NPC life points'
}
if data and data[1] and data[1]['NPC life points'] then
max_hp = data[1]['NPC life points']
else
return "Can't find any data for monster '" .. monster_Name .. "'."
end
end
local plot = chart.newChart{ type='scatter' }
:setDimensions( '60em', '45em', '300px', '300px', true )
:setTitle( 'Average damage increase when procced VS your average damage per hit' )
:setXLabel( 'Monster HP' )
:setYLabel( 'Damage increase [%]' )
for _, i in ipairs{ 1000, 2000, 3000, 4000, 6000, 8000, 10000, 12000, 15000} do
plot:newDataSet{
data = chart.generateXYFromFunc( function(x)
return ((damage( max_hp, x, cap ) - i)/ i) * 100
end, 0, max_hp, math.max( 1000, max_hp / 500 ) ),
pointRadius = 0,
label = i
}
end
local procTable = mw.html.create( 'table' ):addClass( 'wikitable' )
procTable:tr()
:th( 'Attack speed' )
:th( 'Average proc rate' )
:tr()
:td( '1 tick' )
:td( fnum( triggerChance( seers, ranged_Cape, 1, current_hp ) * 100 ) .. '%' )
:tr()
:td( '2 ticks' )
:td( fnum( triggerChance( seers, ranged_Cape, 2, current_hp ) * 100 ) .. '%' )
:tr()
:td( '3 ticks' )
:td( fnum( triggerChance( seers, ranged_Cape, 3, current_hp ) * 100 ) .. '%' )
:tr()
:td( '4 ticks' )
:td( fnum( triggerChance( seers, ranged_Cape, 4, current_hp ) * 100 ) .. '%' )
:tr()
:td( '5 ticks' )
:td( fnum( triggerChance( seers, ranged_Cape, 5, current_hp ) * 100 ) .. '%' )
local boltDamage = damage( max_hp, current_hp, cap )
local res = ''
if lookup_toggle then
res = res .. string.format( '%s has %s lp.<br>', monster_Name, fnum( max_hp ) )
end
res = res .. string.format( 'Ruby bolts (e) will deal %s damage at %s life points.<br>', fnum( boltDamage ), fnum( current_hp ) )
res = res .. string.format( 'You will take %s damage.', fnum( math.floor( your_hp * 0.1 ) ) )
res = res .. tostring( procTable )
res = res .. plot
return res
end
return p
-- </nowiki>