Module:Sandbox/User:Sfoxrs/sgb: Difference between revisions
Jump to navigation
Jump to search
m (1 revision imported) |
|
(No difference)
|
Latest revision as of 21:23, 4 November 2021
Documentation for this module may be created at Module:Sandbox/User:Sfoxrs/sgb/doc
-- <pre>
local p = {}
local htnmlext = require('Module:Mw.html extension')
local yesno = require ("Module:Yesno")
local lang = mw.getContentLanguage()
function p.main(frame)
local invokeArgs = frame.args
local args = frame:getParent().args
return p._main( invokeArgs, args )
end
function p._main(invokeArgs,args)
local ad = tonumber(args.AD) or 0
local rangedlvl = tonumber(args.ranged) or 0
local preciseRank = tonumber(args.precise) or 0
local equilibriumRank = tonumber(args.eq) or 0
local weaponSwitch = args.weaponSwitch
local eqSwitchRank = tonumber(args.eqswitch) or -1
local ruthlessRank = tonumber(args.ruthless) or 0
local ruthlessStacks = tonumber(args.rstacks) or 0
local bitingRank = tonumber(args.biting) or 0
local bitingLevel20 = args.bitinglvl20
local eof = args.eof
local revengeStacks = tonumber(args.revengeStacks) or 0
local shieldType = args.shieldType
local hexhunter = args.hexhunter
local bolts = args.bolts
local seers = args.seers
local rangedCape = args.rangedCape
local maxhp = tonumber(args.maxhp) or 0
local currenthp = tonumber(args.currenthp) or 0
local pocket = args.pocket
local ring = args.ring
local potion = args.potion
local berserkBloodEssence = args.essence or ""
local prayer = args.prayer
local aura = args.aura
local vuln = args.vuln
local slayerPerk = args.slayerPerk
local slayerAbility = args.slayerAbility
local spider = args.spider
local swiftness = args.swiftness
local splitSoul = args.splitSoul or ""
local aos = args.aos or ""
local nArrowsSplitSoul = args.nArrowsSplitSoul or ""
local needle = args.needle
local bFury = tonumber(args.dhrelic) or 0
local ripper = args.ripper
local telosBeam = args.telosBeam
local npc = args.npc
return calculateDamage(ad,rangedlvl,preciseRank,equilibriumRank,weaponSwitch,eqSwitchRank,ruthlessRank,ruthlessStacks,bitingRank,bitingLevel20,eof,revengeStacks,shieldType,hexhunter,bolts,seers,rangedCape,maxhp,currenthp,pocket,ring,potion,berserkBloodEssence,prayer,aura,vuln,slayerPerk,slayerAbility,spider,swiftness,splitSoul,aos,nArrowsSplitSoul,needle,bFury,ripper,telosBeam,npc)
end
function calculateDamage(ad,rangedlvl,preciseRank,equilibriumRank,weaponSwitch,eqSwitchRank,ruthlessRank,ruthlessStacks,bitingRank,bitingLevel20,eof,revengeStacks,shieldType,hexhunter,bolts,seers,rangedCape,maxhp,currenthp,pocket,ring,potion,berserkBloodEssence,prayer,aura,vuln,slayerPerk,slayerAbility,spider,swiftness,splitSoul,aos,nArrowsSplitSoul,needle,bFury,ripper,telosBeam,npc)
-- calculate effective level and Ability damage (AD)
local lvlMult = 1
local lvlAdd = 0
if(potion=="Elder overload potion") then lvlMult = 1.17; lvlAdd = 5
elseif(potion=="Supreme overload potion" or potion=="Supreme ranging potion") then lvlMult = 1.16; lvlAdd = 4
elseif(potion=="Overload") then lvlMult = 1.15; lvlAdd = 3
end
local lvlAura = 0
if(aura=="Reckless") then lvlAura = 0.1 end
local rangedlvlEff = rangedlvl
if(potion=="Supreme ranging potion") then
rangedlvlEff = math.floor(rangedlvl*lvlMult+lvlAdd)
if(berserkBloodEssence=="Yes") then -- 133 stats at level 99 (with or without reckless)
rangedlvlEff = rangedlvlEff + math.floor(rangedlvl*1.14+2) - rangedlvl
end
elseif(potion=="None") then
rangedlvlEff = math.floor(rangedlvl*(lvlAura + lvlMult))
if(berserkBloodEssence=="Yes") then -- 123 stats at level 99 with reckless (114 without)
rangedlvlEff = rangedlvlEff + math.floor(rangedlvl*1.14+2) - rangedlvl
end
else --overloads
rangedlvlEff = math.floor(rangedlvl*(lvlAura + lvlMult)+lvlAdd)
end
local prayerMod = 1
if(prayer=="Desolation") then prayerMod = 1.12
elseif(prayer=="Anguish") then prayerMod = 1.10
elseif(prayer=="Leech Range Strength + Amulet of zealots") then prayerMod = 1.18
elseif(prayer=="Overpowering Force + Amulet of zealots") then prayerMod = 1.16
elseif(prayer=="Rigour") then prayerMod = 1.08
end
--local adEff = math.floor(ad*prayerMod)
local adEff = ad
if(hexhunter=="Yes") then adEff = math.floor(ad*1.125) end
-- base sgb arrow range %s
local arrowFixedPercent = {80,80,80,80,80}
local arrowVarPercent = {120,160,133,106,80}
-- sgb as damage from AD
local arrowFixedBase = {0,0,0,0,0}
local arrowVarBase = {0,0,0,0,0}
-- sgb arrows as damage from ADeff
local arrowFixed = {0,0,0,0,0}
local arrowVar = {0,0,0,0,0}
-- split soul based damages
local arrowFixedECB = {0,0,0,0,0}
local arrowVarECB = {0,0,0,0,0}
--base
for arrow = 1,5 do
arrowFixedBase[arrow] = math.floor(adEff*arrowFixedPercent[arrow]/100)
arrowVarBase[arrow] = math.floor(adEff*arrowVarPercent[arrow]/100)
arrowFixed[arrow] = math.floor(arrowFixedBase[arrow]*prayerMod) -- prayerMod applied here
arrowVar[arrow] = math.floor(arrowVarBase[arrow]*prayerMod) -- prayerMod applied here
end
--boosted
for arrow = 1,5 do
arrowFixed[arrow] = arrowFixed[arrow] + 4*(rangedlvlEff - rangedlvl)
arrowVar[arrow] = arrowVar[arrow] + 4*(rangedlvlEff - rangedlvl)
end
--revenge EOF
if(eof=="Yes") then
local revengeMod = 0
if(shieldType=="Shield") then revengeMod = 0.10
elseif(shieldType=="Repriser") then revengeMod = 0.05
else revengeMod = 0
end
for arrow = 1,5 do
arrowVar[arrow] = math.floor(arrowVar[arrow]*(1+revengeStacks*revengeMod))
end
end
--precise
local Aprecise = math.floor(.015*preciseRank*(arrowFixed[1]+arrowVar[1]))
arrowFixed[1] = arrowFixed[1] + Aprecise
for arrow = 2,5 do arrowFixed[arrow] = arrowFixed[1] end
arrowVar[1] = arrowVar[1] - Aprecise
arrowVar[2] = 2*arrowFixed[1]
arrowVar[3] = math.floor(5/3*arrowFixed[1])
arrowVar[4] = math.floor(4/3*arrowFixed[1])
arrowVar[5] = 1*arrowFixed[1]
-- calculate p forced crit
local bitingMod = 0
if(bitingLevel20=="Yes") then bitingMod = 1 end
local pForcedCrit = .02*bitingRank*(1+.1*bitingMod)
if(pocket=="Grimoire" or pocket=="Grimshaw" or pocket=="Grimshaw (superior)") then pForcedCrit = pForcedCrit + 0.12 end
if(ring=="Reaver's ring") then pForcedCrit = pForcedCrit + 0.05
elseif(ring=="Stalker's ring") then pForcedCrit = pForcedCrit + 0.03
end
--calculate pNatCrit
local pNatCrit = {0,0,0,0,0}
for arrow = 1,5 do
pNatCrit[arrow] = math.floor(.05*(arrowFixed[arrow]+arrowVar[arrow]))/arrowVar[arrow]
end
--equilibrium (aura overrides perk)
for arrow = 1,5 do
if(aura=="Equilibrium") then
arrowFixed[arrow] = arrowFixed[arrow] + math.floor(.25*arrowVar[arrow])
arrowVar[arrow] = math.floor((1-.50)*arrowVar[arrow])
else
local eqRankEffective = equilibriumRank
if(weaponSwitch=="Yes" and arrow>1) then eqRankEffective = eqSwitchRank end
arrowFixed[arrow] = arrowFixed[arrow] + math.floor(.03*eqRankEffective*arrowVar[arrow])
arrowVar[arrow] = math.floor((1-.04*eqRankEffective)*arrowVar[arrow])
end
end
--calculate hits after vuln/swiftness/aura/ruthless/scrim
local ruthlessMod = 0.005*ruthlessRank*ruthlessStacks
local vulnMod = 0
if(vuln=="Yes") then vulnMod = 0.1 end
local slayerPerkMod = 0
if(slayerPerk=="Yes") then slayerPerkMod = 0.07 end
local slayerAbilityMod = 0
if(slayerAbility=="Yes") then slayerAbilityMod = 0.15 end
local spiderMod = 0
if(spider=="2%") then spiderMod = 0.02
elseif(spider=="3%") then spiderMod = 0.03
end
local swiftnessMod = 0
if(swiftness=="Yes" or swiftness=="Yes \(cast on last few ticks\)") then swiftnessMod = 0.5 end
local auraMod = 0
if(aura=="Mahjarrat") then auraMod = 0.05
elseif(aura=="Reckless" and (swiftness=="Yes \(cast on last few ticks\)" or swiftness=="No")) then auraMod = 0.1
elseif(aura=="Reckless" and swiftness=="Yes") then auraMod = 0
end
local pocketMod = 0
if(pocket=="Scrimshaw of cruelty" or pocket=="Grimshaw") then pocketMod = 0.05
elseif(pocket=="Superior scrimshaw of cruelty" or pocket=="Grimshaw (superior)") then pocketMod = 0.0666
end
local needleMod = 0
if(needle=="Yes") then needleMod = 0.07 end
local berserkersFury = bFury/100
local ripperDemonPassive = 0
if(ripper=="Yes") then ripperDemonPassive = math.max(0,.05*(1-currenthp/maxhp)) end
local telosRedBeamMod = 0
local telosBlackBeamMod = 0
if(telosBeam=="Player is in black beam \(Phases 2 or 5\)") then telosBlackBeamMod=-0.30
elseif(telosBeam=="Telos is in black beam \(Phase 2\)") then telosBlackBeamMod=-0.20
elseif(telosBeam=="Player is in red beam \(Phase 3\)") then telosRedBeamMod=0.30
elseif(telosBeam=="Player is in red beam; Telos is in black beam \(Phase 5\)") then telosRedBeamMod=0.30; telosBlackBeamMod=-0.20
elseif(telosBeam=="Player is not in red beam; Telos is in black beam \(Phase 5\)") then telosBlackBeamMod=-0.20
end
local finalMod = (1+ruthlessMod) * (1+vulnMod) * (1+slayerPerkMod) * (1+slayerAbilityMod) * (1+spiderMod) * (1+swiftnessMod) * (1+auraMod) * (1+pocketMod) * (1+needleMod) * (1+berserkersFury) * (1+ripperDemonPassive) * (1+telosRedBeamMod) * (1+telosBlackBeamMod)
local finalModECB = finalMod/((1+telosRedBeamMod) * (1+telosBlackBeamMod)) --split soul damage is based on pre telos beam damage modifiers
local natCritMin = {0,0,0,0,0}
local forcedCritMin = {0,0,0,0,0}
local natCritMinECB = {0,0,0,0,0}
local forcedCritMinECB = {0,0,0,0,0}
for arrow = 1,5 do
--damage for ecb
arrowFixedECB[arrow] = math.floor(arrowFixed[arrow] * finalModECB)
arrowVarECB[arrow] = math.floor(arrowVar[arrow] * finalModECB)
natCritMinECB[arrow] = math.floor(arrowFixedECB[arrow] + (1-pNatCrit[arrow])*arrowVarECB[arrow])
forcedCritMinECB[arrow] = math.floor(arrowFixedECB[arrow]+0.95*arrowVarECB[arrow])
--sgb arrow damage
arrowFixed[arrow] = math.floor(arrowFixed[arrow] * finalMod)
arrowVar[arrow] = math.floor(arrowVar[arrow] * finalMod)
natCritMin[arrow] = math.floor(arrowFixed[arrow] + (1-pNatCrit[arrow])*arrowVar[arrow])
forcedCritMin[arrow] = math.floor(arrowFixed[arrow]+0.95*arrowVar[arrow])
end
--bolts EOF
local seersMod = 0
if(eof=="Yes" and seers=="Yes") then seersMod = 1 end
local rangedCapeMod = 0
if(eof=="Yes" and rangedCape=="Yes") then rangedCapeMod = 1 end
local boltProcChance = 0
local rubyProcChance = 0 -- for specifically rubys
local boltDamageMultiplier = 0 -- dragonstone are a seperate hit
local rubyBoltDamage = 0 --specifically ruby bolt damage
local uncappedRubyBoltDamage = 0 -- specifically uncapped ruby bolt damage (post softcap)
local rubyBoltDamageECB = 0 --specifically ruby bolt damage for split soul
local uncappedRubyBoltDamageECB = 0 -- specifically uncapped ruby bolt damage (post softcap) for split soul
local softCapMax = 10000
if(pocket=="Grimoire") then softCapMax = 15000 end
local softcap = softCapMax
local ratiohp = currenthp/maxhp
if(ratiohp<0.5) then softcap = math.floor(softCapMax*2*ratiohp) end
if(eof=="Yes" and bolts=="Diamond") then
boltProcChance = (5+2*seersMod)*(1+0.2*rangedCapeMod)/100
boltDamageMultiplier = 0.15
elseif(eof=="Yes" and bolts=="Dragonstone") then
boltProcChance = (5+2*seersMod)*(1+0.2*rangedCapeMod)/100
boltDamageMultiplier = 0.25
elseif(eof=="Yes" and bolts=="Onyx") then
boltProcChance = (10+2*seersMod)*(1+0.2*rangedCapeMod)/100
boltDamageMultiplier = 0.25
elseif(eof=="Yes" and bolts=="Ruby") then
rubyProcChance = math.max(0.01,(5+2*seersMod-math.floor(currenthp/1000000))*(1+0.2*rangedCapeMod)/100)
rubyBoltDamage = math.min(math.floor(math.max(1,math.floor(20*ratiohp))/100*currenthp),softcap)*finalMod
uncappedRubyBoltDamage = rubyBoltDamage
uncappedRubyBoltDamageECB = rubyBoltDamage/finalMod*finalModECB
if(potion~="None" or (potion=="None" and berserkBloodEssence=="Yes") or prayer~="None" or aura=="Reckless") then
if(pocket=="Grimoire") then rubyBoltDamage = math.min(15000,uncappedRubyBoltDamage)
else rubyBoltDamage = math.min(12000,uncappedRubyBoltDamage)
end
else
rubyBoltDamage=math.min(10000,uncappedRubyBoltDamage)
end
end
local arrowFixedBeforeBolts = {0,0,0,0,0}
local arrowVarBeforeBolts = {0,0,0,0,0}
local arrowFixedBoltProcOnly = {0,0,0,0,0}
local arrowVarBoltProcOnly = {0,0,0,0,0}
local natCritMinBoltProcOnly = {0,0,0,0,0}
local forcedCritMinBoltProcOnly = {0,0,0,0,0}
--diamond, dragonstone, onyx. ruby done after regular average
for arrow = 1,5 do
arrowFixedBeforeBolts[arrow] = arrowFixed[arrow]
arrowVarBeforeBolts[arrow] = arrowVar[arrow]
if(eof=="Yes" and (bolts=="Diamond" or bolts=="Dragonstone" or bolts=="Onyx")) then
--arrowFixed[arrow] = boltProcChance*math.floor(arrowFixed[arrow]*(1+boltDamageMultiplier)) + (1-boltProcChance)*arrowFixed[arrow]
--arrowVar[arrow] = boltProcChance*math.floor(arrowVar[arrow]*(1+boltDamageMultiplier)) + (1-boltProcChance)*arrowVar[arrow]
arrowFixedBoltProcOnly[arrow] = math.floor(arrowFixedBeforeBolts[arrow]*(1+boltDamageMultiplier))
arrowVarBoltProcOnly[arrow] = math.floor(arrowVarBeforeBolts[arrow]*(1+boltDamageMultiplier))
natCritMinBoltProcOnly[arrow] = math.floor(arrowFixedBoltProcOnly[arrow] + (1-pNatCrit[arrow])*arrowVarBoltProcOnly[arrow])
forcedCritMinBoltProcOnly[arrow] = math.floor(arrowFixedBoltProcOnly[arrow]+0.95*arrowVarBoltProcOnly[arrow])
end
end
--damage caps
local critCap = 12000
if(pocket=="Grimoire") then critCap = 15000 end
local nonCap = 10000
--calculate probability of hits above caps
local pForcedCritCap = {0,0,0,0,0}
local pNaturalCritCap = {0,0,0,0,0}
local pNonCritCap = {0,0,0,0,0}
local pForcedCritCapBoltProcOnly = {0,0,0,0,0}
local pNaturalCritCapBoltProcOnly = {0,0,0,0,0}
local pNonCritCapBoltProcOnly = {0,0,0,0,0}
for arrow = 1,5 do
--normal sgb arrows
pForcedCritCap[arrow] = (critCap - forcedCritMin[arrow])/(arrowFixed[arrow]+arrowVar[arrow] - forcedCritMin[arrow])
pNaturalCritCap[arrow] = (critCap - natCritMin[arrow])/(arrowFixed[arrow]+arrowVar[arrow] - natCritMin[arrow])
pNonCritCap[arrow] = (nonCap - arrowFixed[arrow])/(natCritMin[arrow] - arrowFixed[arrow])
--diamond, dragonstone, onyx bolt procs
pForcedCritCapBoltProcOnly[arrow] = (critCap - forcedCritMinBoltProcOnly[arrow])/(arrowFixedBoltProcOnly[arrow]+arrowVarBoltProcOnly[arrow] - forcedCritMinBoltProcOnly[arrow])
pNaturalCritCapBoltProcOnly[arrow] = (critCap - natCritMinBoltProcOnly[arrow])/(arrowFixedBoltProcOnly[arrow]+arrowVarBoltProcOnly[arrow] - natCritMinBoltProcOnly[arrow])
pNonCritCapBoltProcOnly[arrow] = (nonCap - arrowFixedBoltProcOnly[arrow])/(natCritMinBoltProcOnly[arrow] - arrowFixedBoltProcOnly[arrow])
end
--calculate average damages
local arrowAverage = {0,0,0,0,0}
for arrow = 1,5 do
--diamond, dragonstone, onyx bolt proc
arrowAverage[arrow] = arrowAverage[arrow] + boltProcChance*pForcedCrit*(math.max(0,math.min(1-pForcedCritCapBoltProcOnly[arrow],1))*critCap + math.min(math.max(0,pForcedCritCapBoltProcOnly[arrow]),1)*(math.min(critCap,forcedCritMinBoltProcOnly[arrow]) + math.min(critCap,(arrowFixedBoltProcOnly[arrow]+arrowVarBoltProcOnly[arrow])))/2)
arrowAverage[arrow] = arrowAverage[arrow] + boltProcChance*(1-pForcedCrit)*(pNatCrit[arrow])*(math.max(0,math.min(1-pNaturalCritCapBoltProcOnly[arrow],1))*critCap + math.min(math.max(0,pNaturalCritCapBoltProcOnly[arrow]),1)*(math.min(natCritMinBoltProcOnly[arrow],critCap) + math.min(critCap,(arrowFixedBoltProcOnly[arrow]+arrowVarBoltProcOnly[arrow])))/2)
arrowAverage[arrow] = arrowAverage[arrow] + boltProcChance*(1-pForcedCrit)*(1-pNatCrit[arrow])*(math.max(0,math.min(1-pNonCritCapBoltProcOnly[arrow],1))*nonCap + math.min(math.max(0,pNonCritCapBoltProcOnly[arrow]),1)*(math.min(nonCap,arrowFixedBoltProcOnly[arrow]) + math.min(nonCap,natCritMinBoltProcOnly[arrow]))/2)
--no bolt proc (lines above this should be 0 if no bolts or ruby bolts)
arrowAverage[arrow] = arrowAverage[arrow] + (1-boltProcChance)*pForcedCrit*(math.max(0,math.min(1-pForcedCritCap[arrow],1))*critCap + math.min(math.max(0,pForcedCritCap[arrow]),1)*(math.min(critCap,forcedCritMin[arrow]) + math.min(critCap,(arrowFixed[arrow]+arrowVar[arrow])))/2)
arrowAverage[arrow] = arrowAverage[arrow] + (1-boltProcChance)*(1-pForcedCrit)*(pNatCrit[arrow])*(math.max(0,math.min(1-pNaturalCritCap[arrow],1))*critCap + math.min(math.max(0,pNaturalCritCap[arrow]),1)*(math.min(natCritMin[arrow],critCap) + math.min(critCap,(arrowFixed[arrow]+arrowVar[arrow])))/2)
arrowAverage[arrow] = arrowAverage[arrow] + (1-boltProcChance)*(1-pForcedCrit)*(1-pNatCrit[arrow])*(math.max(0,math.min(1-pNonCritCap[arrow],1))*nonCap + math.min(math.max(0,pNonCritCap[arrow]),1)*(math.min(nonCap,arrowFixed[arrow]) + math.min(nonCap,natCritMin[arrow]))/2)
end
--average for ruby bolts
if(bolts=="Ruby") then
for arrow = 1,5 do arrowAverage[arrow] = rubyProcChance*rubyBoltDamage + (1-rubyProcChance)*arrowAverage[arrow] end
end
--calculate ecb average damages
-- FUNCTIONS for ecb defined below calculateDamage()
local ecbAverage = {0,0,0,0,0}
local minSoulSplitSplat = 2
if(splitSoul=="Yes") then
if(nArrowsSplitSoul=="Arrows 1-5") then minSoulSplitSplat = 1 end
for arrow = minSoulSplitSplat,5 do
arrowMin = arrowFixedECB[arrow]
arrowMax = arrowFixedECB[arrow] + arrowVarECB[arrow]
fCritMin = forcedCritMinECB[arrow]
ecbAverage[arrow] = avgDmgSplitSoulCalc(arrowMin,arrowMax,fCritMin,arrowMax,pForcedCrit,aos,vulnMod,slayerPerkMod,slayerAbilityMod,spiderMod)
if(bolts=="Ruby") then --no diff in arrow 1 vs 2-5 here at the moment
local rubyBoltSplitSoulDamage = dmgSplitSoulSingleValueCalc(uncappedRubyBoltDamageECB,aos,vulnMod,slayerPerkMod,slayerAbilityMod,spiderMod)
if(arrow==1) then ecbAverage[arrow] = (rubyProcChance*rubyBoltSplitSoulDamage + (1-rubyProcChance)*ecbAverage[arrow])
else ecbAverage[arrow] = (rubyProcChance*rubyBoltSplitSoulDamage + (1-rubyProcChance)*ecbAverage[arrow])
end
end
end
end
--display min/max of arrows
local arrowMinHit = {0,0,0,0,0}
local arrowMaxHit = {0,0,0,0,0}
for arrow = 1,5 do
if(bolts=="No" or eof=="No") then
arrowMinHit[arrow] = arrowFixed[arrow]
arrowMaxHit[arrow] = arrowFixed[arrow]+arrowVar[arrow]
elseif(bolts~="Ruby") then
arrowMinHit[arrow] = math.min(arrowFixedBoltProcOnly[arrow],arrowFixedBeforeBolts[arrow])
arrowMaxHit[arrow] = math.max(arrowFixedBoltProcOnly[arrow]+arrowVarBoltProcOnly[arrow],arrowFixedBeforeBolts[arrow]+arrowVarBeforeBolts[arrow])
elseif(bolts=="Ruby") then
arrowMinHit[arrow] = math.min(arrowFixed[arrow],rubyBoltDamage)
arrowMaxHit[arrow] = math.max(arrowFixed[arrow]+arrowVar[arrow],rubyBoltDamage)
end
end
--create arrow damage table
local resultsDiv = mw.html.create( 'div' )
local resultsTable = mw.html.create( 'table' )
resultsTable:addClass( 'wikitable' )
:addClass( 'align-center-1 align-center-2 align-center-3 align-center-4 align-center-5 align-center-6 align-center-7 align-center-8 align-center-9' )
:tag( 'caption' )
:wikitext( 'Average damage for individual arrows as well as the combined average damage for the total number of arrows that land.' )
:IF(splitSoul=="No")
:css('text-align', 'left')
:END()
:tag( 'tr' )
:tag( 'th' )
:wikitext( 'Arrow Damages' )
:IF(splitSoul=="No")
:attr( 'colspan', 5 )
:ELSE()
:attr( 'colspan', 9 )
:END()
:done()
:done()
:tag( 'tr' )
:tag( 'th' )
:wikitext( 'Arrow' )
:attr( 'rowspan', 2 )
:done()
:tag( 'th' )
:wikitext( 'Individual Arrow Damages' )
:IF(splitSoul=="No")
:attr( 'colspan', 3 )
:ELSE()
:attr( 'colspan', 5 )
:END()
:done()
:tag( 'th' )
:wikitext( 'Total Average Damage over n Arrows' )
:IF(splitSoul=="No")
:attr( 'rowspan', 2 )
:ELSE()
:attr( 'colspan', 3 )
:END()
:done()
:done()
:tag( 'tr' )
:tag( 'th' )
:wikitext( 'Minimum')
:done()
:tag( 'th' )
:wikitext( 'Maximum')
:done()
:tag( 'th' )
:wikitext( 'Average')
:done()
:IF(splitSoul=="Yes")
:tag( 'th' )
:wikitext( 'Average from Split Soul')
:done()
:tag( 'th' )
:wikitext( 'Average from Arrow + Split Soul')
:done()
:tag( 'th' )
:wikitext( 'Average from n Arrows')
:done()
:tag( 'th' )
:wikitext( 'Average from Split Soul over n Arrows')
:done()
:tag( 'th' )
:wikitext( 'Average from n Arrows + Split Soul')
:done()
:END()
:done()
:done()
local sumAverage = 0
local ecbSumAverage = 0
for arrow = 1,5 do
sumAverage = sumAverage + arrowAverage[arrow]
ecbSumAverage = ecbSumAverage + ecbAverage[arrow]
resultsTable:tag( 'tr' )
:tag( 'td' )
:wikitext ( string.format("%d",arrow) )
:done()
:tag( 'td' )
:wikitext ( string.format("%s",lang:formatNum(math.floor(arrowMinHit[arrow]+0.5)) ))
:done()
:tag( 'td' )
:wikitext ( string.format("%s",lang:formatNum(math.floor(arrowMaxHit[arrow]+0.5)) ))
:done()
:tag( 'td' )
:wikitext ( string.format("%s",lang:formatNum(math.floor(arrowAverage[arrow]+0.5)) ))
:done()
:IF(splitSoul=="Yes")
:tag( 'td' )
:wikitext ( string.format("%s",lang:formatNum(math.floor(ecbAverage[arrow]+0.5)) ))
:done()
:tag( 'td' )
:wikitext ( string.format("%s",lang:formatNum(math.floor(arrowAverage[arrow]+ecbAverage[arrow])) ))
:done()
:END()
:tag( 'td' )
:wikitext ( string.format("%s",lang:formatNum(math.floor(sumAverage+0.5)) ))
:done()
:IF(splitSoul=="Yes")
:tag( 'td' )
:wikitext ( string.format("%s",lang:formatNum(math.floor(ecbSumAverage+0.5)) ))
:done()
:tag( 'td' )
:wikitext ( string.format("%s",lang:formatNum(math.floor(sumAverage+ecbSumAverage+0.5)) ))
:done()
:END()
:done()
end
--create arrays based on NPC size
local pArrow1NoBlock = {0.840,0.473,0.144,0.141,0.045,0.083,0.026,0.057,0.017,0.043,0.013}
local pArrow2NoBlock = {0.160,0.420,0.398,0.327,0.193,0.222,0.124,0.168,0.091,0.135,0.071}
local pArrow3NoBlock = {0.000,0.100,0.342,0.324,0.324,0.281,0.250,0.240,0.203,0.208,0.171}
local pArrow4NoBlock = {0.000,0.007,0.106,0.170,0.282,0.231,0.277,0.227,0.247,0.210,0.219}
local pArrow5NoBlock = {0.000,0.000,0.010,0.038,0.155,0.182,0.323,0.308,0.441,0.404,0.526}
local pArrow1Block = {0.840,0.473,0.144,0.010,0.000}
local pArrow2Block = {0.160,0.420,0.398,0.106,0.000}
local pArrow3Block = {0.000,0.100,0.342,0.342,0.000}
local pArrow4Block = {0.000,0.007,0.106,0.398,0.000}
local pArrow5Block = {0.000,0.000,0.010,0.144,1.000}
local npcSizeDiv = mw.html.create( 'div' )
local npcSizeTable = mw.html.create( 'table' )
npcSizeTable:addClass( 'wikitable' )
:addClass( 'align-center-1 align-center-2 align-center-3 align-center-4 align-center-5' )
:tag( 'caption' )
:wikitext( 'Average damage based on the NPC size. In general, damage increases with the NPC size.' )
:IF(splitSoul=="No")
:css('text-align', 'left')
:END()
:tag( 'tr' )
:tag( 'th' )
:wikitext( 'Damage based on size of Target' )
:IF(splitSoul=="Yes")
:attr( 'colspan', 5 )
:ELSE()
:attr( 'colspan', 3 )
:END()
:done()
:done()
:tag( 'tr' )
:tag( 'th' )
:wikitext( 'NPC Size' )
:done()
:tag( 'th' )
:wikitext( 'Expected number of Arrows' )
:done()
:tag( 'th' )
:wikitext( 'Average Damage')
:done()
:IF(splitSoul=="Yes")
:tag( 'th' )
:wikitext( 'Average from Split Soul')
:done()
:tag( 'th' )
:wikitext( 'Total Average')
:done()
:END()
:done()
:done()
if(npc=="No \(Non-blocking\)") then
for size = 1,11 do
local sizeArrowAvg = pArrow1NoBlock[size]*arrowAverage[1]+pArrow2NoBlock[size]*(arrowAverage[1]+arrowAverage[2])+pArrow3NoBlock[size]*(arrowAverage[1]+arrowAverage[2]+arrowAverage[3])+pArrow4NoBlock[size]*(arrowAverage[1]+arrowAverage[2]+arrowAverage[3]+arrowAverage[4])+pArrow5NoBlock[size]*(arrowAverage[1]+arrowAverage[2]+arrowAverage[3]+arrowAverage[4]+arrowAverage[5])
local ecbSizeArrowAvg = pArrow1NoBlock[size]*ecbAverage[1]+pArrow2NoBlock[size]*(ecbAverage[1]+ecbAverage[2])+pArrow3NoBlock[size]*(ecbAverage[1]+ecbAverage[2]+ecbAverage[3])+pArrow4NoBlock[size]*(ecbAverage[1]+ecbAverage[2]+ecbAverage[3]+ecbAverage[4])+pArrow5NoBlock[size]*(ecbAverage[1]+ecbAverage[2]+ecbAverage[3]+ecbAverage[4]+ecbAverage[5])
local nArrows = pArrow1NoBlock[size]*1+pArrow2NoBlock[size]*2+pArrow3NoBlock[size]*3+pArrow4NoBlock[size]*4+pArrow5NoBlock[size]*5
npcSizeTable:tag( 'tr' )
:tag( 'td' )
:wikitext ( string.format("%dx%d",size,size) )
:done()
:tag( 'td' )
:wikitext ( string.format("%.2f",nArrows) )
:done()
:tag( 'td' )
:wikitext ( string.format("%s",lang:formatNum(math.floor(sizeArrowAvg+0.5)) ))
:done()
:IF(splitSoul=="Yes")
:tag( 'td' )
:wikitext ( string.format("%s",lang:formatNum(math.floor(ecbSizeArrowAvg+0.5)) ))
:done()
:tag( 'td' )
:wikitext ( string.format("%s",lang:formatNum(math.floor(sizeArrowAvg+ecbSizeArrowAvg+0.5)) ))
:done()
:END()
:done()
end
elseif(npc=="Yes \(Blocking\)") then
for size = 1,4 do
local sizeArrowAvg = pArrow1Block[size]*arrowAverage[1]+pArrow2Block[size]*(arrowAverage[1]+arrowAverage[2])+pArrow3Block[size]*(arrowAverage[1]+arrowAverage[2]+arrowAverage[3])+pArrow4Block[size]*(arrowAverage[1]+arrowAverage[2]+arrowAverage[3]+arrowAverage[4])+pArrow5Block[size]*(arrowAverage[1]+arrowAverage[2]+arrowAverage[3]+arrowAverage[4]+arrowAverage[5])
local ecbSizeArrowAvg = pArrow1Block[size]*ecbAverage[1]+pArrow2Block[size]*(ecbAverage[1]+ecbAverage[2])+pArrow3Block[size]*(ecbAverage[1]+ecbAverage[2]+ecbAverage[3])+pArrow4Block[size]*(ecbAverage[1]+ecbAverage[2]+ecbAverage[3]+ecbAverage[4])+pArrow5Block[size]*(ecbAverage[1]+ecbAverage[2]+ecbAverage[3]+ecbAverage[4]+ecbAverage[5])
local nArrows = pArrow1Block[size]*1+pArrow2Block[size]*2+pArrow3Block[size]*3+pArrow4Block[size]*4+pArrow5Block[size]*5
npcSizeTable:tag( 'tr' )
:tag( 'td' )
:wikitext ( string.format("%dx%d",size,size) )
:done()
:tag( 'td' )
:wikitext ( string.format("%.2f",nArrows) )
:done()
:tag( 'td' )
:wikitext ( string.format("%s",lang:formatNum(math.floor(sizeArrowAvg+0.5)) ))
:done()
:IF(splitSoul=="Yes")
:tag( 'td' )
:wikitext ( string.format("%s",lang:formatNum(math.floor(ecbSizeArrowAvg+0.5)) ))
:done()
:tag( 'td' )
:wikitext ( string.format("%s",lang:formatNum(math.floor(sizeArrowAvg+ecbSizeArrowAvg+0.5)) ))
:done()
:END()
:done()
end
local sizeArrowAvg = pArrow1Block[5]*arrowAverage[1]+pArrow2Block[5]*(arrowAverage[1]+arrowAverage[2])+pArrow3Block[5]*(arrowAverage[1]+arrowAverage[2]+arrowAverage[3])+pArrow4Block[5]*(arrowAverage[1]+arrowAverage[2]+arrowAverage[3]+arrowAverage[4])+pArrow5Block[5]*(arrowAverage[1]+arrowAverage[2]+arrowAverage[3]+arrowAverage[4]+arrowAverage[5])
local ecbSizeArrowAvg = pArrow1Block[5]*ecbAverage[1]+pArrow2Block[5]*(ecbAverage[1]+ecbAverage[2])+pArrow3Block[5]*(ecbAverage[1]+ecbAverage[2]+ecbAverage[3])+pArrow4Block[5]*(ecbAverage[1]+ecbAverage[2]+ecbAverage[3]+ecbAverage[4])+pArrow5Block[5]*(ecbAverage[1]+ecbAverage[2]+ecbAverage[3]+ecbAverage[4]+ecbAverage[5])
local nArrows = pArrow1Block[5]*1+pArrow2Block[5]*2+pArrow3Block[5]*3+pArrow4Block[5]*4+pArrow5Block[5]*5
npcSizeTable:tag( 'tr' )
:tag( 'td' )
:wikitext ( "5x5+" )
:done()
:tag( 'td' )
:wikitext ( string.format("%.2f",nArrows) )
:done()
:tag( 'td' )
:wikitext ( string.format("%s",lang:formatNum(math.floor(sizeArrowAvg+0.5)) ))
:done()
:IF(splitSoul=="Yes")
:tag( 'td' )
:wikitext ( string.format("%s",lang:formatNum(math.floor(ecbSizeArrowAvg+0.5)) ))
:done()
:tag( 'td' )
:wikitext ( string.format("%s",lang:formatNum(math.floor(sizeArrowAvg+ecbSizeArrowAvg+0.5)) ))
:done()
:END()
:done()
end
--return results (table)
resultsDiv:node(tostring(resultsTable))
npcSizeDiv:node(tostring(npcSizeTable))
return resultsDiv, npcSizeTable
--return arrowFixedECB[1]," ",arrowVarECB[1]," ",arrowFixedECB[2]," ",arrowVarECB[2]
--return arrowFixed[1]," ",arrowVar[1]," ",arrowFixedECB[1]," ",arrowVarECB[1]
--return rubyBoltDamage," ", uncappedRubyBoltDamage," ", uncappedRubyBoltDamageECB
--return dmgSplitSoulSingleValueCalc(rubyBoltDamage)," ",dmgSplitSoulSingleValueCalc(uncappedRubyBoltDamage)," ",dmgSplitSoulSingleValueCalc(uncappedRubyBoltDamageECB)
--local check1 = avgDmgSplitSoulCalc(1000,5000,2000,5000,.2,aos,.1,.07,.15)
--local check2 = dmgSplitSoulOverRangeCalc(1000,5000,aos,.1,.07,.15)
--local check3 = dmgSplitSoulSingleValueCalc(3000,aos,.1,.07,.15)
--return check1," ",check2," ",check3
end
-----------------------------------------------------------------------------------------
--calculate ecb spec damages
-----------------------------------------------------------------------------------------
function avgDmgSplitSoulCalc(minHitRange,maxHitRange,fCritMinRange,fCritMaxRange,probFCrit,aosEff,ecbVulnMod,ecbSlayerPerkMod,ecbSlayerAbilityMod,ecbSpiderMod)
local avgDmgSplitSoul = 0
--non-forced crit
local splitSoulDamageRangeNonFCrit = dmgSplitSoulOverRangeCalc(minHitRange,maxHitRange,aosEff,ecbVulnMod,ecbSlayerPerkMod,ecbSlayerAbilityMod,ecbSpiderMod)
avgDmgSplitSoul = avgDmgSplitSoul + ((1-probFCrit) * splitSoulDamageRangeNonFCrit / (maxHitRange-minHitRange+1))
--forced crit
local splitSoulDamageRangeFCrit = dmgSplitSoulOverRangeCalc(fCritMinRange,fCritMaxRange,aosEff,ecbVulnMod,ecbSlayerPerkMod,ecbSlayerAbilityMod,ecbSpiderMod)
avgDmgSplitSoul = avgDmgSplitSoul + (probFCrit * splitSoulDamageRangeFCrit / (fCritMaxRange-fCritMinRange+1))
return avgDmgSplitSoul
end
function dmgSplitSoulOverRangeCalc(minHitRange,maxHitRange,aosEff,ecbVulnMod,ecbSlayerPerkMod,ecbSlayerAbilityMod,ecbSpiderMod)
local damageFromSpec = 0
for n = minHitRange,maxHitRange do
local amountHealed = (math.floor(math.min(2000,n)*.1) + math.floor(math.max(0,math.min(2000,n-2000))*.05) + math.floor(math.max(0,n-4000)*.0125))
local avgIncreaseHealed = math.floor(amountHealed*.375)
if(aosEff=="No") then damageFromSpec = damageFromSpec + math.floor(math.floor(math.floor(math.floor( math.floor(amountHealed*4) * (1+ecbVulnMod)) * (1+ecbSlayerPerkMod)) * (1+ecbSlayerAbilityMod)) * (1+ecbSpiderMod))
elseif(aosEff=="Yes") then damageFromSpec = damageFromSpec + math.floor(math.floor(math.floor(math.floor( (.5*math.floor(amountHealed*4) + .5*math.floor((amountHealed+avgIncreaseHealed)*4)) * (1+ecbVulnMod)) * (1+ecbSlayerPerkMod)) * (1+ecbSlayerAbilityMod)) *(1+ecbSpiderMod))
end
end
return damageFromSpec
end
function dmgSplitSoulSingleValueCalc(n,aosEff,ecbVulnMod,ecbSlayerPerkMod,ecbSlayerAbilityMod,ecbSpiderMod)
local amountHealed = (math.floor(math.min(2000,n)*.1) + math.floor(math.max(0,math.min(2000,n-2000))*.05) + math.floor(math.max(0,n-4000)*.0125))
local avgIncreaseHealed = math.floor(amountHealed*.375)
local damageFromSpec = 0
if(aosEff=="No") then damageFromSpec = math.floor(math.floor(math.floor(math.floor( math.floor(amountHealed*4) * (1+ecbVulnMod)) * (1+ecbSlayerPerkMod)) * (1+ecbSlayerAbilityMod)) * (1+ecbSpiderMod))
elseif(aosEff=="Yes") then damageFromSpec = math.floor(math.floor(math.floor(math.floor( (.5*math.floor(amountHealed*4) + .5*math.floor((amountHealed+avgIncreaseHealed)*4)) * (1+ecbVulnMod)) * (1+ecbSlayerPerkMod)) * (1+ecbSlayerAbilityMod)) * (1+ecbSpiderMod))
end
return damageFromSpec
end
-----------------------------------------------------------------------------------------
return p
-- </nowiki>