--[[
Version 2.4
Last updated 19/1/2026
Damage formula:
baseDmg(1 + ∑additive_buffs) * (1 + ∏multiplicative_buffs)

Additive buffs are first calculated, via (1 + buff1% + buff2% + buff3%) etc, THEN multiplicative buffs via (1+buff1%)(1+buff2%)(1+buff3%)

Copy & Paste this into any online Lua run website and it should work, or press the funny green button > fork on this website

Credits to DyslecxicIvern (StillBornInTheWomb) and Inter (Inter_Nerd) for finding out the specifics of damage buffs

Calculator made & maintained by Firewatch (navihurricane)
---------------------------------------------
Theortical DPS: DPS without any RPM or crit chance
Effective DPS: DPS with reload and crit factored in
Miniboss DPS: Effective DPS but for minibosses as they take 2.5x crit and 1/4 crit chance

Visionary's launcher is not affected by damage buffs, only Decapitation (and its 10x, so 1500 damage)
Im not including arm implants shove because its dumb
]]
local input = {
    ---- BASE STATS ----
    baseDmg            = 95,      -- Base damage per shot
    RPM                = 1350,      -- Rounds per minute (or Swings per Minute if you're calculating melee)
    reloadTime         = 1,      -- Reload time in seconds, please do the math yourself for how much reload time you have with other buffs, ignore with melee
    magSize            = 54,       -- Magazine size (number of rounds), ignore with melee
    
    melee              = false,    -- Set to true for melee
    
    ---- DAMAGE MODIFIERS  ----
    headshot           = false,    -- 1.15x damage multiplier unless deadshot is active
    dmr                = false,    -- Enable if your gun has additional headshot multi
    dmr_headshot       = 0.15,     -- Most are 0.15, only the bolt action is 0.85

    melee_heavy_attack = false,    -- 2x damage multiplier for melee heavy attacks
    
    ---- SPECIALISATIONS ----
    -- Assault
    assault_passive     = false,    -- +0.15 headshot multi
    
    hairtrigger_passive = false,    -- +15% damage
    medipak_passive     = false,    -- +35% damage
    mtm_passive         = false,    -- +25% damage

    assault_t4         = false,    -- 6% crit
    
    hair_trigger       = false,    -- Increases RPM by 20%
    shred              = false,    -- +75% damage
    bulletstorm        = false,    -- Increases RPM by 20%

    -- Specialist
    stun_viewfinder    = false,    -- 1.35x damage

    -- Avenger
    jjj                = false,    -- 1.5x damage
    guardian_of_exile  = false,    -- +12.5% damage per ally not sheltered (capped at 5)
    guardian_of_exile_allies = 0,  -- Number of allies (0-5)
    
    -- Tower
    die_hard           = false,    -- +20% damage, melee only
    fury_road          = false,    -- +25% damage
    berserk_mode       = false,    -- +50% damage

    -- Archangel
    adrenaline_shot    = false,    -- +50% damage
    berserker_essence  = false,    -- Forces critical hits (100% crit chance)

    -- Visionary
    stigmatization     = false,    -- 1.2x damage multiplier
    elucidation        = false,    -- 1.4x damage multiplier
    castigation        = false,    -- 1.5x damage multiplier

    ---- SKILL DECKS ----
    -- Contractor
    vek_elite_operative = false,   -- +75% damage
    enforcer_serg_major = false,   -- +95% damage
    merc_vet_agent     = false,    -- +40% damage

    -- Sharpshooter
    pinpoint_precision = false,    -- 3x damage multiplier, 140% crit chance
    deadshot           = false,    -- Replaces headshot 1.15x with 1.4x, remember to turn on headshot
    leg_meta           = false,    -- 1.35x damage multiplier

    -- Frontliner
    hellion            = false,    -- +55% damage
    savage             = false,    -- +25% damage

    -- Gunslinger
    fistful_of_dollars = false,    -- +20% damage
    fan_the_hammer     = false,    -- Increases RPM by 35%
    i_won_the_west     = false,    -- +50% damage
    desperado          = false,    -- +25% crit chance

    -- Juggernaut
    hasVET             = false,    -- +15% damage

    -- Utilitarian
    adaptive_arsenal   = false,    -- 1.25x damage multiplier
    arm_implants_melee_fists = false, -- +40% damage
    bl_headhunter_gear = false,    -- +55% damage

    -- Vanguard
    barbarian          = false,    -- +20% damage
    singular_strike    = false,    -- 5x damage with melee_heavy_attack
    flashing_blade     = false,    -- 2x damage

    -- Wildcard
    foak_base          = false,    -- Critical hits deal 4x instead of 3x
    foak_diamonds      = false,    -- 1.44x damage multiplier
    foak_clubs         = false,    -- +44% crit chance
    foak_jackpot       = false,    -- 1.44x damage + 44% crit chance
    full_house         = false,    -- +40% damage
    royal_flush        = false,    -- +35% damage, modifies Boundary of Death, +15% crit chance
    ace_high           = false,    -- +12% crit chance

    ---- EXTRAS (Select ONE per Category) ----
    -- Boundary of Death
    boundary_of_death  = false,    -- >75% HP: 1x damage
    bod_75             = false,    -- ≤75% HP: 1.25x (2.5x with royal_flush)
    bod_50             = false,    -- ≤50% HP: 2.5x (2.5x with royal_flush)
    bod_25             = false,    -- ≤25% HP: 5x damage
    bod_rolled_4       = false,    -- Rolled 4: 4x damage

    rend_heaven        = false,    -- [1 + (anomaly_damage/100)]x
    rend_heaven_value  = 55,        -- Put damage here, ie. King would be "55" and the calculator will show 1.55x
    life_and_death     = false,    -- 4x damage

    -- All In
    all_in             = false,    -- <375 Credits: 1x damage
    all_in_375         = false,    -- >375 Credits: 1.1x damage
    all_in_500         = false,     -- >500 Credits: 1.2x damage
    all_in_1000        = false,    -- >1000 Credits: 1.5x damage
}

function calculateDamage(input)
    local baseDmg = input.baseDmg or 0
    local baseRPM = input.RPM or 0
    local reloadTime = input.reloadTime or 2.0
    local magSize = input.magSize or 30
    local critChance = 0
    local additiveBuffs = 0
    local multiplicativeBuffs = 1

    -- Calculate Crit Chance
    if input.berserker_essence then critChance = critChance + 1 end
    if input.pinpoint_precision then critChance = critChance + 1.4 end
    if input.desperado then critChance = critChance + 0.25 end
    if input.ace_high then critChance = critChance + 0.12 end
    if input.foak_clubs then critChance = critChance + 0.44 end
    if input.royal_flush then critChance = critChance + 0.15 end
    if input.foak_jackpot then critChance = critChance + 0.44 end
    if input.assault_t4 then critChance = critChance + 0.06 end

    -- Additive Buffs
    if input.royal_flush then additiveBuffs = additiveBuffs + 0.35 end
    if input.full_house then additiveBuffs = additiveBuffs + 0.40 end

    if input.hairtrigger_passive then additiveBuffs = additiveBuffs + 0.15 end
    if input.medipak_passive then additiveBuffs = additiveBuffs + 0.35 end
    if input.mtm_passive then additiveBuffs = additiveBuffs + 0.25 end

    if input.vek_elite_operative then additiveBuffs = additiveBuffs + 0.75 end
    if input.enforcer_serg_major then additiveBuffs = additiveBuffs + 0.95 end
    if input.merc_vet_agent then additiveBuffs = additiveBuffs + 0.4 end
    if input.shred then additiveBuffs = additiveBuffs + 0.75 end
    if input.fury_road then additiveBuffs = additiveBuffs + 0.25 end
    if input.adrenaline_shot then additiveBuffs = additiveBuffs + 0.5 end
    if input.i_won_the_west then additiveBuffs = additiveBuffs + 0.5 end
    if input.hasVET then additiveBuffs = additiveBuffs + 0.15 end
    if input.hellion then additiveBuffs = additiveBuffs + 0.55 end
    if input.savage then additiveBuffs = additiveBuffs + 0.25 end
    if input.bl_headhunter_gear then additiveBuffs = additiveBuffs + 0.55 end
    if input.fistful_of_dollars then additiveBuffs = additiveBuffs + 0.2 end
    if input.barbarian then additiveBuffs = additiveBuffs + 0.2 end
    if input.die_hard then additiveBuffs = additiveBuffs + 0.2 end
    if input.arm_implants_melee_fists then additiveBuffs = additiveBuffs + 0.4 end
    if input.berserk_mode then additiveBuffs = additiveBuffs + 0.5 end

    -- Special cases
    if input.guardian_of_exile then
        local alliesNotSheltered = math.min(input.guardian_of_exile_allies or 0, 5)
        additiveBuffs = additiveBuffs + (0.125 * alliesNotSheltered)
    end
    if input.soultaker then
        local soulstacks = math.min(input.soultaker_stacks or 0, 3)
        additiveBuffs = additiveBuffs + (0.1 * soulstacks)
    end

    -- Multiplicative Buffs
    local critMulti = input.foak_base and 4.0 or 3.0
    local minibosscritmulti = critMulti
    local headshot_multi = input.headshot and (input.deadshot and 1.4 or 1.15) or 1
    local n_headshot_multi = input.vek_elite_operative and headshot_multi + 0.25 or headshot_multi
    local final_headshot = n_headshot_multi + (input.dmr and input.dmr_headshot or 0) + (input.assault_passive and 0.15 or 0) or 0
    multiplicativeBuffs = multiplicativeBuffs * final_headshot

    if input.all_in_375 then multiplicativeBuffs = multiplicativeBuffs * 1.1
    elseif input.all_in_500 then multiplicativeBuffs = multiplicativeBuffs * 1.2
    elseif input.all_in_1000 then multiplicativeBuffs = multiplicativeBuffs * 1.5 end

    local bod_multi = 1.0
    if input.royal_flush then
        if input.bod_75 or input.bod_50 then bod_multi = 2.5
        elseif input.bod_25 then bod_multi = 5.0
        elseif input.boundary_of_death then bod_multi = 1.0 end
    else
        if input.bod_75 then bod_multi = 1.25
        elseif input.bod_50 then bod_multi = 2.5
        elseif input.bod_25 then bod_multi = 5.0 end
    end
    multiplicativeBuffs = multiplicativeBuffs * bod_multi
    if input.bod_rolled_4 then multiplicativeBuffs = multiplicativeBuffs * 4.0 end
    if input.life_and_death then multiplicativeBuffs = multiplicativeBuffs * 4 end
    if input.rend_heaven then multiplicativeBuffs = multiplicativeBuffs * (1 + input.rend_heaven_value/100) end

    if input.flashing_blade then multiplicativeBuffs = multiplicativeBuffs * 2 end
    if input.stigmatization then multiplicativeBuffs = multiplicativeBuffs * 1.2 end
    if input.castigation then multiplicativeBuffs = multiplicativeBuffs * 1.5 end
    if input.elucidation then multiplicativeBuffs = multiplicativeBuffs * 1.4 end
    if input.hardware_upgrade then multiplicativeBuffs = multiplicativeBuffs * 1.6 end
    if input.leg_meta then multiplicativeBuffs = multiplicativeBuffs * 1.4 end
    if input.foak_diamonds then multiplicativeBuffs = multiplicativeBuffs * 1.44 end
    if input.adaptive_arsenal then multiplicativeBuffs = multiplicativeBuffs * 1.25 end
    if input.stun_viewfinder then multiplicativeBuffs = multiplicativeBuffs * 1.35 end
    if input.jjj and input.melee then multiplicativeBuffs = multiplicativeBuffs * 1.5 end
    if input.melee_heavy_attack then
        multiplicativeBuffs = multiplicativeBuffs * (input.singular_strike and 5 or 2)
    end
    if input.foak_jackpot then multiplicativeBuffs = multiplicativeBuffs * 1.44 end

    -- RPM Modifiers
    local RPM = 1
    if input.hair_trigger then RPM = RPM + 0.2 or 0 end
    if input.fan_the_hammer then RPM = RPM + 0.35 or 0 end
    if input.bulletstorm then RPM = RPM + 0.2 or 0 end
    local RPM = RPM * baseRPM

    -- Calculate Final Values
    -- Get this annoying shit out of the way first to simplify stuff
    local baseAdditive = baseDmg * (1 + additiveBuffs)
    
    -- Damage
    local nonCritDamage = math.ceil(baseAdditive * multiplicativeBuffs)
    local critDamage = math.ceil(baseAdditive * multiplicativeBuffs * critMulti)
    local minicritDamage = math.ceil(baseAdditive * multiplicativeBuffs * minibosscritmulti)
    local overflow_crit = math.min(critChance, 1)
    local weightedDamage = (overflow_crit * critDamage + (1 - overflow_crit) * nonCritDamage)
    
    -- Miniboss thingy because laz i HATE balancing.....
    local minibossCritChance = critChance / 4  -- Halved by 4 for miniboss
    local minibossWeightedDamage = (minibossCritChance * minicritDamage + (1 - minibossCritChance) * nonCritDamage)
    -- Damage multi
    local add_multi = (1 + additiveBuffs) * multiplicativeBuffs
    
    -- DPS + RPM stuff
    local effectiveRPM = input.melee and input.RPM or (RPM > 0 and (RPM * magSize) / (magSize + (reloadTime * RPM / 60)) or 0)
    local effectiveDPS = (RPM > 0 and (weightedDamage * RPM) / 60 or 0) 
    local advancedDPS = (effectiveRPM > 0 and (weightedDamage * effectiveRPM) / 60 or 0) -- effective dps
    local minibossDPS = (effectiveRPM > 0 and (minibossWeightedDamage * effectiveRPM) / 60 or 0)

    return {
        baseDmg = baseDmg,
        baseRPM = baseRPM,
        reloadTime = reloadTime,
        magSize = magSize,
        critChance = critChance,
        minibossCritChance = minibossCritChance,
        baseAdditive = baseAdditive,
        melee = input.melee,
        additiveBuffs = additiveBuffs,
        multiplicativeBuffs = multiplicativeBuffs,
        RPM = RPM,
        effectiveRPM = effectiveRPM,
        nonCritDamage = nonCritDamage,
        critDamage = critDamage,
        weightedDamage = weightedDamage,
        minibossWeightedDamage = minibossWeightedDamage,
        effectiveDPS = effectiveDPS,
        advancedDPS = advancedDPS,
        minibossDPS = minibossDPS,
        add_multi = add_multi,
        final_headshot = final_headshot
    }
end

function printDamageResults(input, results)
    print("\nDAMAGE CALCULATION")
    print("----------------------------")

    -- Base Values
    print("\nBASE VALUES")
    print(string.format("%-24s%5d", "Base Damage:", results.baseDmg))
    if not input.melee then
        print(string.format("%-24s%5d", "Base RPM:", results.baseRPM))
        print(string.format("%-24s%5.1f", "Reload Time (s):", results.reloadTime))
        print(string.format("%-24s%5d", "Magazine Size:", results.magSize))
    end
    print(string.format("%-24s%5.1f%%", "Crit Chance:", results.critChance * 100))
    print(string.format("%-24s%5.1f%%", "Miniboss Crit Chance:", results.minibossCritChance * 100))

    -- Additive Buffs
    print("\nADDITIVE BUFFS")
    if results.additiveBuffs > 0 then
        if input.hairtrigger_passive then print(string.format("%-24s+%4d%%", "• Hair Trigger Passive:", 15)) end
        if input.medipak_passive then print(string.format("%-24s+%4d%%", "• Medipak Passive:", 35)) end
        if input.mtm_passive then print(string.format("%-24s+%4d%%", "• MTM Passive:", 25)) end
        if input.max_soultaker then print(string.format("%-24s+%4d%%", "• Soultaker:", 30)) end
        if input.royal_flush then print(string.format("%-24s+%4d%%", "• Royal Flush:", 35)) end
        if input.full_house then print(string.format("%-24s+%4d%%", "• Full House:", 40)) end
        if input.vek_elite_operative then print(string.format("%-24s+%4d%%", "• VEK Elite Operative:", 75)) end
        if input.enforcer_serg_major then print(string.format("%-24s+%4d%%", "• Enforcer Serg. Maj.:", 95)) end
        if input.merc_vet_agent then print(string.format("%-24s+%4d%%", "• MERC Veteran Agent:", 40)) end
        if input.shred then print(string.format("%-24s+%4d%%", "• Shred:", 75)) end
        if input.fury_road then print(string.format("%-24s+%4d%%", "• Fury Road:", 25)) end
        if input.adrenaline_shot then print(string.format("%-24s+%4d%%", "• Adrenaline Shot:", 50)) end
        if input.i_won_the_west then print(string.format("%-24s+%4d%%", "• I Won The West:", 50)) end
        if input.hasVET then print(string.format("%-24s+%4d%%", "• V.E.T. Suit:", 15)) end
        if input.hellion then print(string.format("%-24s+%4d%%", "• Hellion:", 55)) end
        if input.savage then print(string.format("%-24s+%4d%%", "• Savage:", 25)) end
        if input.bl_headhunter_gear then print(string.format("%-24s+%4d%%", "• Headhunter Gear:", 55)) end
        if input.fistful_of_dollars then print(string.format("%-24s+%4d%%", "• Fistful of Dollars:", 20)) end
        if input.barbarian then print(string.format("%-24s+%4d%%", "• Barbarian:", 20)) end
        if input.die_hard then print(string.format("%-24s+%4d%%", "• Die Hard:", 20)) end
        if input.arm_implants_melee_fists then print(string.format("%-24s+%4d%%", "• Arm Implants:", 40)) end
        if input.berserk_mode then print(string.format("%-24s+%4d%%", "• Berserk Mode:", 50)) end
        if input.guardian_of_exile then
            local allies = math.min(input.guardian_of_exile_allies or 0, 5)
            print(string.format("%-24s+%6.1f%%", "• Guardian (" .. allies .. " allies):", 12.5 * allies))
        end
        if input.soultaker then
            local soulstacks = math.min(input.soultaker_stacks or 0, 3)
            print(string.format("%-24s+%4d%%", "• Soultaker (".. soulstacks .." stack):", 10 * soulstacks))
        end
    else
        print(string.format("%-24s%s", "• None", ""))
    end
    print(string.format("%-24s%.2fx", "\nTotal Additive:", 1 + results.additiveBuffs))

    -- Multiplicative Buffs
    print("\nMULTIPLICATIVE BUFFS")
    local hasMultiBuffs = false

    --[[
    if input.berserker_essence or input.pinpoint_precision then
        local crit_label = (input.berserker_essence and "Berserker" or "PP") .. (input.foak_base and " + FOAK" or "")
        print(string.format("%-24s%4.2fx", "• Critical Hit (" .. crit_label .. "):", input.foak_base and 4.0 or 3.0))
        hasMultiBuffs = true
    end
    ]]

    if input.headshot then
        if input.deadshot then
            print(string.format("%-24s%4.2fx", "• Deadshot" .. (input.dmr and "+DMR" or "") .. (input.assault_passive and "+ASS" or "") .. ":", results.final_headshot))
        else
            print(string.format("%-24s%4.2fx", "• Headshot" .. (input.dmr and "+DMR" or "") .. (input.assault_passive and "+ASS" or "") .. ":", results.final_headshot))
        end
        hasMultiBuffs = true
    end

    if input.all_in_375 or input.all_in_500 or input.all_in_1000 then
        local creditThresholds = {
            {multiplier = 1.1, label = ">375 Credits", active = input.all_in_375},
            {multiplier = 1.2, label = ">500 Credits", active = input.all_in_500},
            {multiplier = 1.5, label = ">1000 Credits", active = input.all_in_1000}
        }
        for _, threshold in ipairs(creditThresholds) do
            if threshold.active then
                print(string.format("%-24s%4.2fx", "• " .. threshold.label .. ":", threshold.multiplier))
                hasMultiBuffs = true
            end
        end
    elseif input.all_in then
        print(string.format("%-24s%4.2fx", "• No Credits:", 1.00))
        hasMultiBuffs = true
    end

    if input.boundary_of_death or input.bod_75 or input.bod_50 or input.bod_25 or input.bod_rolled_4 then
        local hpThresholds = input.royal_flush and {
            {multiplier = 1, label = ">75% HP", active = input.boundary_of_death},
            {multiplier = 2.5, label = "≤75% or ≤50% HP (Royal)", active = input.bod_75 or input.bod_50},
            {multiplier = 5.0, label = "≤25% HP (Royal)", active = input.bod_25}
        } or {
            {multiplier = 1, label = ">75% HP", active = input.boundary_of_death},
            {multiplier = 1.25, label = "≤75% HP", active = input.bod_75},
            {multiplier = 2.5, label = "≤50% HP", active = input.bod_50},
            {multiplier = 5.0, label = "≤25% HP", active = input.bod_25}
        }
        for _, threshold in ipairs(hpThresholds) do
            if threshold.active then
                print(string.format("%-24s%4.2fx", "• " .. threshold.label .. ":", threshold.multiplier))
                hasMultiBuffs = true
            end
        end
        if input.bod_rolled_4 then
            print(string.format("%-24s%4.2fx", "• Rolled 4:", 4.0))
            hasMultiBuffs = true
        end
    end

    if input.jjj then print(string.format("%-24s%4.2fx", "• Jujutsu Kaisen:", 1.5)) hasMultiBuffs = true end
    if input.stigmatization then print(string.format("%-24s%4.2fx", "• Stigmatization:", 1.2)) hasMultiBuffs = true end
    if input.castigation then print(string.format("%-24s%4.2fx", "• Castigation:", 1.5)) hasMultiBuffs = true end
    if input.elucidation then print(string.format("%-24s%4.2fx", "• Elucidation:", 1.4)) hasMultiBuffs = true end
    if input.hardware_upgrade then print(string.format("%-24s%4.2fx", "• Hardware Upgrade:", 1.6)) hasMultiBuffs = true end
    if input.leg_meta then print(string.format("%-24s%4.2fx", "• Leg Meta:", 1.4)) hasMultiBuffs = true end
    if input.foak_diamonds then print(string.format("%-24s%4.2fx", "• Diamond:", 1.44)) hasMultiBuffs = true end
    if input.stun_viewfinder then print(string.format("%-24s%4.2fx", "• Stun Viewfinder:", 1.35)) hasMultiBuffs = true end
    if input.melee_heavy_attack then
        print(string.format("%-24s%4.2fx", "• " .. (input.singular_strike and "Singular Strike" or "Heavy Attack") .. ":", input.singular_strike and 5 or 2))
        hasMultiBuffs = true
    end
    if input.adaptive_arsenal then print(string.format("%-24s%4.2fx", "• Adaptive Arsenal:", 1.25)) hasMultiBuffs = true end
    if input.flashing_blade then print(string.format("%-24s%4.2fx", "• Flashing Blade:", 2)) hasMultiBuffs = true end
    if input.life_and_death then print(string.format("%-24s%4.2fx", "• Life and Death:", 4))hasMultiBuffs = true end
    if input.rend_heaven then print(string.format("%-24s%4.2fx", "• Rend Heaven:", (1+input.rend_heaven_value/100))) hasMultiBuffs = true end

    if not hasMultiBuffs then print(string.format("%-24s%s", "• None", "")) end
    print(string.format("%-24s%4.2fx", "\nTotal Multiplicative:", results.multiplicativeBuffs))

    -- Crit Chance Modifiers
    print("\nCRIT CHANCE MODIFIERS")
    if results.critChance > 0 then
        if input.assault_t4 then print(string.format("%-24s+%4d%%", "• T4 Passive:", 6)) end
        if input.desperado then print(string.format("%-24s+%4d%%", "• Desperado:", 25)) end
        if input.ace_high then print(string.format("%-24s+%4d%%", "• Ace High:", 12)) end
        if input.foak_clubs then print(string.format("%-24s+%4d%%", "• Four of a Kind (Clubs):", 44)) end
        if input.foak_jackpot then print(string.format("%-24s%4d%%", "• Four of a Kind (Jackpot):", 44)) end
        if input.royal_flush then print(string.format("%-24s+%4d%%", "• Royal Flush:", 15)) end
        if input.berserker_essence then print(string.format("%-24s%4d%%", "• Berserker Essence:", 100)) end
        if input.pinpoint_precision then print(string.format("%-24s%4d%%", "• Pinpoint Precision:", 100)) end
    else
        print(string.format("%-24s%s", "• None", ""))
    end
    
    -- RPM Modifiers
    if not input.melee then
        print("\nRPM MODIFIERS")
        if input.hair_trigger or input.fan_the_hammer or input.bulletstorm then
            if input.hair_trigger then print(string.format("%-24s+%4d%%", "• Hair Trigger:", 20)) end
            if input.bulletstorm then print(string.format("%-24s+%4d%%", "• Bulletstorm:", 20)) end
            if input.fan_the_hammer then print(string.format("%-24s+%4d%%", "• Fan The Hammer:", 35)) end
        else
            print(string.format("%-24s%s", "• None", ""))
        end
    end

    -- Final Calculations
    print("\nFINAL CALCULATIONS")
    if not input.melee then
        print(string.format("%-24s%5d", "  Final RPM:", math.floor(results.RPM + 0.5)))
    end
    print(string.format("%-24s%.2fx", "  Final Multiplier:", results.add_multi))

    print("\nDAMAGE METRICS:")
    print(string.format("%-24s%5.1f", "  Non-Critical Damage:", results.nonCritDamage))
    print(string.format("%-24s%5.1f", "  Critical Damage:", results.critDamage))
    print(string.format("%-24s%5.1f", "  Effective Damage:", results.weightedDamage))
    print(string.format("%-24s%5.1f", "  Miniboss ED:", results.minibossWeightedDamage))
    
    print("\nPERFORMANCE METRICS:")
    if not input.melee then
        print(string.format("%-24s%5.1f", "  Effective RPM:", results.effectiveRPM))
    else
        print(string.format("%-24s%5.1f", "  Swing Rate:", results.effectiveRPM)) 
    end
    print(string.format("%-24s%5.1f", "  Theoretical DPS:", results.effectiveDPS))
    print(string.format("%-24s%5.1f", "  Effective DPS:", results.advancedDPS))
    print(string.format("%-24s%5.1f", "  Miniboss DPS:", results.minibossDPS))

    print("\n----------------------------")
end

local results = calculateDamage(input)
printDamageResults(input, results)

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: