Module:Crystal Shield (perk) calculator

From WIDEVERSE Wiki
Jump to navigation Jump to search

Documentation for this module may be created at Module:Crystal Shield (perk) calculator/doc

-- <pre>
local p = {}

local yesno = require ("Module:Yesno")

function p.main(frame)
    math.randomseed(os.time())
    local args = frame:getParent().args
    
    local min_hit = tonumber(args.minHit) or 0
    local max_hit = tonumber(args.maxHit) or 0    
    local t_AR = tonumber(args.t_AR) or 0
    local gearLevel20 = yesno(args.level20) or false

    local tAbsorb = 16 -- absorption phase 
    local tCooldown = 100 -- cooldown phase (tShield = 50 not defined on its own for this as this assumes the pool will always be depleted)
    local proc = .1
    if gearLevel20 then
        proc = .11
    end
    
    local csDamage = 0
    local totalDamage = 0
    local averageDamageBetweenProcs = {0,0,0,0}
    local averageDamageRatioOverTime = {0,0,0,0}
    
    local pastHits = 0 --hits that failed to proc 
    local absorbHits = 0 --hits that are done during the absorbption phase (tAbsorb)
    local reducedAbsorbHits = 0 --hits that are to be used for the pool (floored after *.05*perkRank)
    local cooldownHits = 0 --hits that are done during the cooldown phase (tCooldown)
    local nHitsAbsorb = math.ceil(tAbsorb/t_AR)
    local nHitsCooldown = math.ceil((tCooldown-tAbsorb)/t_AR)
    
    
    local res = ""
    
    if min_hit > max_hit then
        return "The minimum hit must not be higher than the maximum hit."
    end
    
    for perkRank = 1,4 do
        csDamage=0
        totalDamage=0
        for n = 0,999 do
            pastHits=0
            absorbHits=0
            reducedAbsorbHits=0
            cooldownHits=0
            for iHitsNoProc = 1,n do
                local randomHit = math.floor(math.random(min_hit,max_hit))
                pastHits = pastHits + randomHit
            end
            for iHitsAbsorb = 1,nHitsAbsorb do
                local randomHit = math.floor(math.random(min_hit,max_hit))
                absorbHits = absorbHits + randomHit
                reducedAbsorbHits = reducedAbsorbHits + math.floor(.05*perkRank*randomHit)
            end
            
            for iHitsCooldown = 1,nHitsCooldown do
                local randomHit = math.floor(math.random(min_hit,max_hit))
                cooldownHits = cooldownHits + randomHit
            end
            
            csDamage = csDamage + (math.pow(1-proc,n)*proc * (pastHits + absorbHits - reducedAbsorbHits + cooldownHits))
            totalDamage = totalDamage + (math.pow(1-proc,n)*proc * (pastHits + absorbHits + cooldownHits))
            
            --averageDamageBetweenProcs[perkRank] = averageDamageBetweenProcs[perkRank] + (math.pow(1-proc,n)*proc * (pastHits + absorbHits - reducedAbsorbHits + cooldownHits) / (pastHits + absorbHits + cooldownHits) )
        end
        averageDamageRatioOverTime[perkRank] = averageDamageRatioOverTime[perkRank] + csDamage/totalDamage
    end
    
    for perkRank = 1,4 do
        res = res .. "Average damage reduction from Crystal Shield (perk) " .. perkRank .. " : " .. string.format("%2.2f",(1-averageDamageRatioOverTime[perkRank])*100) .. "%<br/>"
    end
    --[[
    res = res .. "<br/>"
        for perkRank = 1,3 do
        res = res .. "Average damage reduction between procs from Crystal Shield (perk) " .. perkRank .. " : " .. string.format("%2.2f",(1-averageDamageBetweenProcs[perkRank])*100) .. "%<br/>"
    end
    --]]
    
    return res
end

return p