WARFRAME Wiki
WARFRAME Wiki
mNo edit summary
mNo edit summary
Line 2,137: Line 2,137:
 
D1Name, atkStat(D1Value), D2Name, atkStat(D2Value), -- Reload/Ammo; Range/Followthru
 
D1Name, atkStat(D1Value), D2Name, atkStat(D2Value), -- Reload/Ammo; Range/Followthru
 
E1Name, Weapon.StancePolarity and Polarity(Weapon.StancePolarity).." | " or '', pols -- Polarities
 
E1Name, Weapon.StancePolarity and Polarity(Weapon.StancePolarity).." | " or '', pols -- Polarities
)--]=]
+
):gsub('%.00%%','%%')--]=]
   
 
--[==[]===]
 
--[==[]===]

Revision as of 13:57, 16 April 2021


Lua error in Module:Docbunto at line 922: documentation markup for Docbunto not found in Module:Tooltips/tip.
Created with Docbunto

See Also

Code


return {
Ability     = function(name)
    local ability = mw.loadData [[Module:Ability/data]] ["Ability"] [name]
    assert(type(ability) == "table", 'No ability '..name..' found')
    return string.format([==[
<div style="display:inline-block;">
{| class="Tooltip" style="font-family:'Roboto';"|-
|style="padding:0px;"|
{| class="Sub" style="width:500px;"|-
| class="Spacer" style="padding:0;"| [[File:%s|130px]]
| class="Spacer"|
| class="Data" style="line-height:20px; text-align:center; width:64px; padding:2px;"|[[File:%s|48px]]<br/><div style="display:inline-block; margin: 4px 2px 8px 2px;"><div style="display:inline-block; position:relative; top:-2px;">[[File:EnergyIcon32x.png|18px]]</div> <span style="font-size:14px; font-weight:bold;">%s</span></div><br><div style="display:inline-block;"><span style="position:relative;background-color:#272727;color:white;padding:1px 4px;border:2px solid #aaadb4;border-radius:5px;font-size:12px;">%s</span></div>
| class="Spacer"|
| class="Data" style="font-size:13px; line-height:16px; padding:2px 3px 2px 3px; white-space:normal;"|<span style="font-weight:bold; font-size:15px;">%s</span><br/>%s
|}
|}</div>]==], ability["CardImage"], ability["WhiteIcon"], ability["Cost"], ability["Key"] or '∅', ability["Warframe"], ability["Description"])
end,
Mods        = function(name)
    assert(name and name ~= '', "No mod specified")
    local ModData = mw.loadData [[Module:Mods/data]]
    local Mod = ModData["Mods"][name]
    assert(Mod --[[and Mod.Name == name]], "No such mod found (see [[Module:Mods/data]])")
    return '[[File:'..(Mod.Image or "Mod.png")..'|192px]]'
end,
Warframes   = function(name)
    assert(name and name~='', 'No name input')

    local warframe = mw.loadData [[Module:Warframes/data]] ["Warframes"] [name]
    if not warframe or warframe.Name ~= name then
        mw.log('"'..(name or '~nil~')..'" not a key')
        for key, wf in pairs(WarframeData["Warframes"]) do
            if(wf.Name == name) then
                warframe = wf
                break
            end
        end
        assert(warframe, 'No warframe '..name..' found.')
    end

    local function Polarity(pol)
        return '['..'[File:'..(({
            Zenurik  = "Zenurik_Pol_W.png",
            Naramon  = "Naramon_Pol_W.png",
            Vazarin  = "Vazarin_Pol_W.png",
            Penjaga  = "Penjaga_Pol_W.png",
            Exilus   = "Exilus_W.png",
            Madurai  = "Madurai_Pol_W.png",
            Koneksi  = "Koneksi_Pol_W.png",
            Umbra    = "Umbra_Pol_W.png",
            Unairu   = "Unairu_Pol_W.png",
            Aura     = "Aura_Pol_White.png",
            None     = "Spacer.png",
        })[({
            Ability='Zenurik',Bar='Naramon',D='Vazarin',Y='Penjaga',Sila='Penjaga',Sentinel='Penjaga',Precept='Penjaga',
            V='Madurai',O='Koneksi',Core='Koneksi',Fusion='Koneksi',Pengetikan='Koneksi',U='Umbra',Q='Umbra',Ward='Unairu',R='Unairu'
        })[pol]or(pol)] or error(pol))..'|x16px]]'
    end

    local pols = warframe.Polarities
    if pols and pols[1] then
        local p = {}
        for i, v in ipairs(pols) do
            p[i] = Polarity(v)
        end
        pols = table.concat(p)
    else
        pols = 'None'
    end

    local abils
    do
        local abilData = mw.loadData [[Module:Ability/data]]
        local abilities = abilData ["Warframe"] [string.gsub(name, ' Prime', '')]
        local t = {}
        for i, abilname in pairs(abilities or {}) do
            t[i] = '['..'[File:'..(abilData['Ability'][abilname]['WhiteIcon'] or 'panel.png')..'|30px]] '..abilname
        end
        abils = table.concat(t,'<br/>')
    end
    
    return string.format([=[
{| class="Tooltip" |-
|style="padding:0;"|
<div style="position:relative;">
{| class="Sub" |-
| class="Image" style="height:120px; padding-bottom:0;" | [[File:%s|120px]]<div style="position:absolute;top:6px; left:4px; color:white; font-size:16px; font-weight:bold; text-shadow: 0 0 1px #0D1B1C, 0 0 4px #0D1B1C, 1px 1px 2px #0D1B1C, -1px 1px 2px #0D1B1C, 1px -1px 2px #0D1B1C, -1px -1px 2px #0D1B1C;">[[File:MasteryAffinity64.png|28px]]<div style="position:absolute;top:4px; left:%gpx;">%s</div></div>
|-
| class="Spacer" |
|-
| style="padding:0px;" |
{| class="Data" style="font-size:12px;" |-
| class="TableHalf" |<span class="LinkText">Health</span>&nbsp;%s
| class="TableHalf" |<span class="LinkText">Armor</span>&nbsp;%s
|-
| class="TableHalf" |<span class="LinkText">Shield</span>&nbsp;%s
| class="TableHalf" |<span class="LinkText">Energy</span>&nbsp;%s
|-
| style="text-align:center;" colspan=2 |<span class="LinkText">Polarities</span>&nbsp;%s | %s | %s
|}
|-
| class="Spacer" |
|-
| style="padding:0px;" |
{| class="Data" style="font-size:12px;" |-
| class="Data" style="padding:4px; text-align:left;"|%s
|}
|}
</div>
|}
]=],
    warframe.Portrait,
    #((warframe.Mastery or 0)..'') >= 2 and 5 or 9.5,
    warframe.Mastery or 0,
    math.floor(0.5+(warframe.Health or 0)).." ("..math.floor(0.5+(warframe.HealthRank30 or warframe.Health * 3))..")",
    math.floor(0.5+(warframe.Armor  or 0))..(warframe.ArmorRank30 and " ("..math.floor(0.5+(warframe.ArmorRank30))..")" or ''),
    math.floor(0.5+(warframe.Shield or 0)).." ("..math.floor(0.5+(warframe.ShieldRank30 or warframe.Shield * 3))..")",
    math.floor(0.5+(warframe.Energy or 0)).." ("..math.floor(0.5+(warframe.EnergyRank30 or warframe.Energy*1.5))..")",
    warframe.AuraPolarity   and Polarity(warframe.AuraPolarity  ) or 'None',
    warframe.ExilusPolarity and Polarity(warframe.ExilusPolarity) or 'None',
    pols,
    abils
)
    --local module = {n=[[Module:Warframes]],  l={f='tooltip'},}
    --return require(module.n)[module.l.f]{args={name}}

end,
Void        = function(name)
    local module = {n=[[Module:Void]],       l={f='relicTooltip'},
            f={'{| class="Tooltip"\n|-\n|style="padding:0px;"|\n{| class="Relic Sub"\n|-\n|class="Data"|\n','\n|}\n|}'},}
    return module.f[1]..require(module.n)[module.l.f]{args={name}}..module.f[2]
end,
Weapons     = function(name)


--[==[
do
    local module = {n=[[Module:Weapons]],    l={f='weaponTooltip'},
        f={'<div style="display:inline-block;">\n{| class="Tooltip Main"\n|-\n|style="padding:0px;"|','\n|}\n</div>'},}
    return module.f[1]..require(module.n)[module.l.f]{args={name}}..module.f[2]
end
--[===[]==]



    local weapName = name
    assert(weapName, 'No name provided')

local WeaponData = mw.loadData [[Module:Weapons/data]]
local Shared = require [[Module:Shared]]
local Icon = require [[Module:Icon]]

local p = {}


    --there's no "Dark Split-Sword" in m:weapons/data -> setting name to dual sword variant
    if weapName == "Dark Split-Sword" then
        weapName = "Dark Split-Sword (Dual Swords)"
    end

    local 
                     A2Name, A2Value, 

    C1Name, C1Value, C2Name, C2Value, 
    D1Name, D1Value, D2Name, D2Value, 
    E1Name, E1Value
    local titleText = ""
    local hasCharged = false
    local attackType = "Normal"
    local attackText = nil--""
    local space = "&nbsp;"
    local attackBiasText = ""


function p.getWeapon(WeapName)
    local weapon = WeaponData["Weapons"][WeapName]
    
    if weapon ~= nil and weapon.Name == WeapName then
        return weapon
    else
        for key, Weapon in Shared.skpairs(WeaponData["Weapons"]) do
            if(Weapon.Name == WeapName or key == WeapName) then
                return Weapon            
            end
        end
    end

    return nil
end

    local Weapon = assert(p.getWeapon(weapName), "No weapon "..weapName.." found.")
    local cAvailability = false
local function getAttack(Weapon, AttackType)
    if(Weapon == nil or AttackType == nil) then
        return nil
    elseif(type(Weapon) == "string") then
        Weapon = p.getWeapon(Weapon)
    end
    if (AttackType == nil or AttackType == "Normal" or AttackType == "NormalAttack") then
        if(Weapon.NormalAttack ~= nil) then
            return Weapon.NormalAttack
        elseif(Weapon.Damage ~= nil) then 
            return Weapon 
        else 
            return nil
        end
    elseif(AttackType == "Charge" or AttackType == "ChargeAttack") then
        return Weapon.ChargeAttack
    elseif(AttackType == "Area" or AttackType == "AreaAttack") then
        return Weapon.AreaAttack
    elseif(AttackType == "SecondaryArea" or AttackType == "SecondaryAreaAttack") then
        return Weapon.SecondaryAreaAttack
    elseif(AttackType == "Throw" or AttackType == "ThrowAttack") then
        return Weapon.ThrowAttack
    elseif(AttackType == "ChargedThrow" or AttackType == "ChargedThrowAttack") then
        return Weapon.ChargedThrowAttack
    elseif(AttackType == "Secondary" or AttackType == "SecondaryAttack") then
        return Weapon.SecondaryAttack
    elseif(AttackType == "Slam" or AttackType == "SlamAttack") then
        return Weapon.SlamAttack
    elseif(AttackType == "Heavy" or AttackType == "HeavyAttack") then
        return Weapon.HeavyAttack
    else
        return nil
    end
end
local function hasAttack(Weapon, AttackType)
    if(getAttack(Weapon, AttackType) ~= nil) then 
        return true 
    else 
        return nil 
    end
end
local function asMultiplier(val)
    if(val == nil) then
        return "1.0x"
    end
    if val == null then return "" end
    return Shared.round(val, 2, 1).."x"
end
local function getAttackValue(Weapon, Attack, ValName, giveDefault, asString, forTable)
    if(giveDefault == nil) then giveDefault = false end
    if(asString == nil) then asString = false end
    if(forTable == nil) then forTable = false end
    if(Attack == nil) then 
        if(asString) then
            return ""
        else
            return nil 
        end
    end
    local regularVal = Shared.titleCase(ValName)
    if(ValName == "Damage") then
        if(Attack.Damage ~= nil) then
            if(asString) then
                return GetDamageString(Attack, nil)
            else
                return GetDamage(Attack)
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "DamagePlus") then
        if(Attack.Damage ~= nil) then
            if(asString) then
                if(hasMultipleTypes(Attack)) then
                    return GetDamageString(Attack, nil).." ("..GetDamageBiasString(Attack, nil, "")..")"
                else
                    return GetDamageString(Attack, nil)
                end
            else
                return GetDamage(Attack)
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(Shared.contains(Elements, regularVal) or ValName == "Physical" or ValName == "Element") then
        if(Attack.Damage ~= nil) then
            if(asString) then
                if(hasMultipleTypes(Attack)) then
                    return GetDamageString(Attack,  regularVal)
                else
                    return nil
                end
            else
                return GetDamage(Attack,  regularVal)
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "Accuracy") then
        if(Attack.Accuracy ~= nil) then
            return Attack.Accuracy
        elseif(Attack == Weapon.NormalAttack) then
            return Weapon.Accuracy
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "AttackName") then
        if(Attack.AttackName ~= nil) then
            return Attack.AttackName
        elseif(giveDefault) then
            return ""
        else
            return nil
        end
    elseif(ValName == "AmmoCost") then
        if(Attack.AmmoCost ~= nil) then
            if(asString) then
                return Attack.AmmoCost.." ammo per shot"
            else
                return Attack.AmmoCost
            end
        elseif(giveDefault) then
            return 1
        else
            return nil
        end
    elseif(ValName == "BlockAngle") then
        if(Attack.BlockAngle ~= nil) then
            if(asString) then
                return Attack.BlockAngle.."&#176;"
            else
                return Attack.BlockAngle
            end
        else
            return nil
        end
    elseif(ValName == "BurstCount") then
        if(Attack.BurstCount ~= nil) then
            if(asString) then
                local result = Attack.BurstCount.." rounds"
                local dmg = GetDamage(Attack) * Attack.BurstCount
                return result.." ("..Shared.round(dmg, 2, 1).." total damage)"
            else
                return Attack.BurstCount
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "BurstFireRate") then
        if(Attack.BurstFireRate ~= nil) then
            return Attack.BurstFireRate
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "ChargeTime") then
        if(Attack.ChargeTime ~= nil) then
            if(asString) then
                return Shared.round(Attack.ChargeTime, 2, 1).." s"
            else
                return Attack.ChargeTime
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "ComboDur") then
        if(Attack.ComboDur ~= nil) then
            return Attack.ComboDur
        else
            return nil
        end
    elseif(ValName == "CritChance") then -- note there is getValue version
    --search in current attack, then normal, 
        if(Attack.CritChance and Attack.CritChance ~= null) then
            if(asString) then
                return Shared.asPercent(Attack.CritChance)
            else
                return Attack.CritChance
            end
        end
        if(hasAttack(Weapon, "Normal")) then
            local normAtt = getAttack(Weapon, "Normal")
            if(normAtt.CritChance and normAtt.CritChance ~= null and Attack.CritChance ~= null) then
                if(asString) then
                    return Shared.asPercent(normAtt.CritChance)
                else
                    return normAtt.CritChance
                end
            end
        end
        if giveDefault then
            if(asString) then
                return Shared.asPercent(0)
            else
                return 0
            end
        else
            return nil
        end
    elseif(ValName == "CritMultiplier") then -- note there is getValue version
    --search in current attack, then normal, 
        if(Attack.CritMultiplier ~= nil) then
            if(asString) then
                return asMultiplier(Attack.CritMultiplier)
            else
                return Attack.CritMultiplier
            end
        end
        if(hasAttack(Weapon, "Normal")) then
            local normAtt = getAttack(Weapon, "Normal")
            if(normAtt.CritMultiplier ~= nil) then
                if(asString) then
                    return asMultiplier(normAtt.CritMultiplier)
                else
                    return normAtt.CritMultiplier
                end
            end
        end
        if giveDefault then
            if(asString) then
                return asMultiplier(0)
            else
                return 0
            end
        else
            return nil
        end
    elseif(ValName == "DamageBias") then
        if(Shared.tableCount(Attack.Damage) <= 4) then
            if (GetDamageBiasString(Attack, nil, nil, giveDefault)~=nil) then
                return GetDamageBiasString(Attack, nil, nil, giveDefault)
            else
                return ""
            end
        else
            if(asString or giveDefault) then
                return ""
            else
                return nil
            end
        end
    elseif(ValName == "BulletType") then
        if(Attack.ShotType ~= nil) then
            return Attack.ShotType
        elseif(giveDefault) then
            return "Unknown"
        else
            return nil
        end
    elseif(ValName == "Duration") then
        if(Attack.Duration ~= nil) then
            if(asString) then
                return Shared.round(Attack.Duration, 1, 0).." s"
            else
                return Attack.Duration
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "ElementType") then
        if(Attack.Damage ~= nil) then
            for dType, dmg in Shared.skpairs(Attack.Damage) do
                if(not Shared.contains(Physical, dType) or dmg <= 0) then
                    if(asString) then
                        return Icon._Proc(dType)
                    else
                        return dType
                    end
                end
            end
        elseif asString then
            return ""
        else
            return nil
        end
    elseif(ValName =="ElementTypeName") then
        if(Attack.Damage ~= nil) then
            for dType, dmg in Shared.skpairs(Attack.Damage) do
                if(not Shared.contains(Physical, dType) or dmg <= 0) then
                    return dType
                end
            end
        elseif asString then
            return ""
        else
            return nil
        end
    elseif(ValName == "Falloff") then
        if(Attack.Falloff ~= nil) then
            local falloffText = "Full damage up to "..Shared.round(Attack.Falloff.StartRange, 2, 1).." m"
            falloffText = falloffText.."<br/>Min damage at "..Shared.round(Attack.Falloff.EndRange, 2, 1).." m"
            if(Attack.Falloff.Reduction ~= nil) then
                falloffText = falloffText.."<br/>"..Shared.asPercent(Attack.Falloff.Reduction).." max reduction"
            end
            return falloffText
        else
            return nil
        end
    elseif(ValName == "FireRate") then --search in current attack, then normal, then weapon supertable
        local returnVal = 0
        if(Attack.FireRate ~= nil) then
            returnVal = Attack.FireRate
        elseif(hasAttack(Weapon, "Normal")) then
            local normAtt = getAttack(Weapon, "Normal")
            if(normAtt.FireRate ~= nil) then 
                returnVal = normAtt.FireRate
            end            
        elseif(Weapon.FireRate ~= nil) then
            returnVal = Weapon.FireRate
        end
        if(asString) then
            if(Weapon.Type ~= nil and Weapon.Type ~= "Melee" and Weapon.Type ~= "Arch-Melee") then
                if(forTable) then
                    return Shared.round(returnVal, {3, 1}) -- .." rps"
                else
                    return Shared.round(returnVal, {3, 1})..p.doPlural(" round<s> per sec", returnVal)
                end
            else
                return Shared.round(returnVal, {3, 1})
            end
        else
            return returnVal
        end
        if (giveDefault) then
            returnVal = 0
        else
            return nil
        end
    elseif(ValName == "FollowThrough") then
        if(Attack.FollowThrough ~= nil) then
            if(asString) then
                return Shared.asPercent(Attack.FollowThrough,0)
            else
                return Attack.FollowThrough
            end
        else
            return nil
        end
    elseif(ValName == "HeadshotMultiplier") then 
        --search in current attack, then normal, and finally fall back on base weapon value if for some reason that exists
        if(Attack.HeadshotMultiplier ~= nil) then
            if(asString) then
                return asMultiplier(Attack.HeadshotMultiplier)
            else
                return Attack.HeadshotMultiplier
            end
        end
        if(hasAttack(Weapon, "Normal")) then
            local normAtt = getAttack(Weapon, "Normal")
            if(normAtt.HeadshotMultiplier ~= nil) then
                if(asString) then
                    return asMultiplier(normAtt.HeadshotMultiplier)
                else
                    return normAtt.HeadshotMultiplier
                end
            end
        end
        if(Weapon.HeadshotMultiplier ~= nil) then
            if(asString) then
                return asMultiplier(Weapon.HeadshotMultiplier)
            else
                return Weapon.HeadshotMultiplier
            end
        end
        if giveDefault then
            if(Weapon.Type ~= nil) then
                --Setting multiplier based on default for each weapon type
                if(Weapon.Type == "Secondary") then
                    if(Weapon.Class == "Shotgun Sidearm") then
                        return "1.2x"
                    elseif(Weapon.Class == "Crossbow" or Weapon.Class == "Thrown") then
                        return "1.5x"
                    else
                        if(Weapon.Trigger == "Auto") then
                            return "1.2x"
                        else
                            return "1.5x"
                        end
                    end
                elseif(Weapon.Type == "Primary") then
                    if(Weapon.Class == "Shotgun") then
                        return "1.2x"
                    elseif(Weapon.Class == "Bow") then
                        return "2.0x"
                    elseif(Weapon.Class == "Sniper Rifle") then
                        return "1.4x"
                    elseif(Weapon.Class == "Launcher") then
                        return "1.0x"
                    else
                        if(Weapon.Trigger == "Auto") then
                            return "1.2x"
                        else
                            return "1.5x"
                        end
                    end
                end
            end
        else
            return nil
        end
    elseif(ValName == "MeleeRange") then
        if(Attack.MeleeRange ~= nil) then
            if(asString) then
                return Attack.MeleeRange.." m"
            else
                return Attack.MeleeRange
            end
        elseif(giveDefault) then
            if(asString) then
                return "0 m"
            else
                return 0
            end
        else
            return nil
        end
    elseif(ValName == "NoiseLevel") then
        if(Attack.NoiseLevel ~= nil) then
            return Attack.NoiseLevel
        else
            return nil
        end
    elseif(ValName == "PelletCount") then
        if(Attack.PelletCount ~= nil) then
            if(asString) then
                if(Attack.PelletName ~= nil) then
                    return Attack.PelletCount.." "..Attack.PelletName.."s"
                else
                    return Attack.PelletCount.." Pellets"
                end
            else
                return Attack.PelletCount
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "PelletName") then
        if(Attack.PelletCount ~= nil) then
            if(Attack.PelletName ~= nil) then
                return Attack.PelletName
            else
                return "Pellet"
            end
        else
            return nil
        end
    elseif(ValName == "PelletPlus") then
        if(Attack.PelletCount ~= nil) then
            local result = Attack.PelletCount.." ("
            result = result..Shared.round(GetDamage(Attack, nil, true), 2, 1)
            if(Attack.PelletName ~= nil) then
                return result.." damage per "..string.lower(Attack.PelletName)..")"
            else
                return result.." damage per pellet)"
            end
        else
            return nil
        end
    elseif(ValName == "ProjectileSpeed") then
        if(Attack.ShotSpeed ~= nil) then
            if(asString) then
                return Attack.ShotSpeed.." m/s"
            else
                return Attack.ShotSpeed
            end
        elseif(giveDefault) then
            if(asString) then
                return "0 m/s"
            else
                return 0
            end
        else
            return nil
        end
    elseif(ValName == "PunchThrough") then
        if(Attack.PunchThrough ~= nil) then
            if(asString) then
                return Shared.round(Attack.PunchThrough, 2, 1).." m"
            else
                return Attack.PunchThrough
            end
        elseif giveDefault then
            if(asString) then
                return "0 m"
            else
                return 0
            end
        else
            return nil
        end
    elseif(ValName == "Radius") then
        if(Attack.Radius ~= nil) then
            if(asString) then
                return Shared.round(Attack.Radius, 2, 1).." m"
            else
                return Attack.Radius
            end
        elseif giveDefault then
            if(asString) then
                return "0 m"
            else
                return 0
            end
        else
            return nil
        end
    elseif(ValName == "Range") then
        if(Attack.Range ~= nil) then
            if(asString) then
                return Attack.Range.." m"
            else
                return Attack.Range
            end
        elseif(giveDefault) then
            if(asString) then
                return "0 m"
            else
                return 0
            end
        else
            return nil
        end
    elseif(ValName == "Reload") then
        if(Attack.Reload ~= nil) then
            if(asString) then
                return Shared.round(Attack.Reload, 2, 1).." s"
            else
                return Attack.Reload
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "Spool") then
        if(Attack.Spool ~= nil) then
            if(asString) then
                return Attack.Spool.." rounds"
            else
                return Attack.Spool
            end
        else
            return nil
        end
    elseif(ValName == "Stances") then
        return getWeaponStanceList(Weapon)    
    elseif(ValName == "StatusChance") then -- search in current attck, then normal
        if(Attack.StatusChance ~= nil) then
            if(asString) then
                return Shared.asPercent(Attack.StatusChance)
            else
                return Attack.StatusChance
            end
        end
        if(hasAttack(Weapon, "Normal")) then
            local normAtt = getAttack(Weapon, "Normal")
            if(normAtt.StatusChance ~= nil) then
                if(asString) then
                    return Shared.asPercent(normAtt.StatusChance)
                else
                    return normAtt.StatusChance
                end
            end
        end
        if giveDefault then
            if(asString) then
                return Shared.asPercent(0)
            else
                return 0
            end
        else
            return nil
        end
    elseif(ValName == "Trigger") then -- use getValue for tables
    -- search in current attack, then weapon supertable
        if(Attack.Trigger ~= nil) then
            return Attack.Trigger
        end
        if(Weapon.Trigger ~= nil) then
            return Weapon.Trigger
        end
        if giveDefault then
            return "Unknown"
        else
            return nil
        end
    else
        return "ERROR: No such value "..ValName
    end
end
local function getValue(Weapon, ValName, giveDefault, asString, forTable, regenValue)
    if(giveDefault == nil) then giveDefault = false end
    if(asString == nil) then asString = false end
    if(forTable == nil) then forTable = false end
    if(regenValue == nil) then regenValue = false end
    
    if(type(ValName) == "table") then
        local VName1 = ValName[1]
        local VName2 = ValName[2]
        if(VName1 == nil or VName2 == nil) then
            return nil
        end
            
        if(VName1 == "Normal" or VName1 == "NormalAttack") then
            return getAttackValue(Weapon, getAttack(Weapon, "Normal"), VName2, giveDefault, asString, forTable)
        elseif(VName1 == "Area" or VName1 == "AreaAttack") then
            return getAttackValue(Weapon, getAttack(Weapon, "Area"), VName2, giveDefault, asString, forTable)
        elseif(VName1 == "SecondaryArea" or VName1 == "SecondaryAreaAttack") then
            return getAttackValue(Weapon, getAttack(Weapon, "SecondaryArea"), VName2, giveDefault, asString, forTable)
        elseif(VName1 == "Charge" or VName1 == "ChargeAttack") then
            return getAttackValue(Weapon, getAttack(Weapon, "Charge"), VName2, giveDefault, asString, forTable)
        elseif(VName1 == "ChargedThrow" or VName1 == "ChargedThrowAttack") then
            return getAttackValue(Weapon, getAttack(Weapon, "ChargedThrow"), VName2, giveDefault, asString, forTable)
        elseif(VName1 == "Throw" or VName1 == "ThrowAttack") then
            return getAttackValue(Weapon, getAttack(Weapon, "Throw"), VName2, giveDefault, asString, forTable)
        elseif(VName1 == "Secondary" or VName1 == "SecondaryAttack") then
            return getAttackValue(Weapon, getAttack(Weapon, "Secondary"), VName2, giveDefault, asString, forTable)
        elseif(VName1 == "Slam" or VName1 == "SlamAttack") then
            return getAttackValue(Weapon, getAttack(Weapon, "SlamAttack"), VName2, giveDefault, asString, forTable)
        elseif(VName1 == "Heavy" or VName1 == "HeavyAttack") then
            return getAttackValue(Weapon, getAttack(Weapon, "HeavyAttack"), VName2, giveDefault, asString, forTable)
        else
            return "ERROR: No such attack \""..VName1.."\""
        end
    end
    
    if(ValName == "Name") then
        if(Weapon.Name ~= nil) then
            if(forTable) then 
                if (string.find(Weapon.Name,"Atmosphere")~=nil) then
                    return "[["..string.gsub(Weapon.Name,"%s%(Atmosphere%)","").."|"..string.gsub(Weapon.Name,"osphere","").."]]"
                else
                    return "[["..Weapon.Name.."]]"
                end
            else
                return Weapon.Name
            end
        elseif giveDefault then
            return ""
        else
            return nil
        end
    elseif(ValName == "ArsenalOverride") then
        if(Weapon.ArsenalOverride ~= nil) then
            return Weapon.ArsenalOverride
        else
            return nil
        end
    elseif(ValName == "Ammo") then
        forTable = true
        return ((function()
            if(Weapon.Magazine ~= nil) then
                if(asString) then
                    if (forTable) then 
                        return Weapon.Magazine
                    else
                        return Weapon.Magazine.." round(s) per mag"--p.doPlural(" round<s> per mag", Weapon.Magazine)
                    end
                else
                    return Weapon.Magazine
                end
            elseif giveDefault then
                if(asString) then
                    return "0 rounds per mag"
                else
                    return 0
                end
            else
                return nil
            end
        end)()or'')..(function(s)return(s)and('&thinsp;/&thinsp;'..s)or''end)((function()
            local returnVal = 0
            if(Weapon.MaxAmmo ~= nil) then
                returnVal = Weapon.MaxAmmo
            elseif giveDefault then
                if(Weapon.Type ~= nil) then
                    if(Weapon.ReloadStyle == "Regenerate") then
                        returnVal = "Infinite"
                    elseif(Weapon.Type == "Secondary") then
                        returnVal = 210
                    elseif(Weapon.Type == "Primary") then
                        if(Weapon.Class == nil or Weapon.Class == "Rifle") then
                            returnVal = 540
                        elseif(Weapon.Class == "Shotgun") then
                            returnVal = 120
                        elseif(Weapon.Class == "Bow" or Weapon.Class == "Sniper Rifle") then
                            returnVal = 72
                        end
                    end
                end
            else
                return nil
            end
            if(asString) then
                if(returnVal == "Infinite" or returnVal > 0) then
                    if (forTable) then 
                        return returnVal
                    else
                        return returnVal.." rounds"
                    end
                else
                    return nil
                end
            else
                if(returnVal == "Infinite" or returnVal > 0) then
                    return returnVal
                else
                    return nil
                end
            end
        end)())
    elseif(ValName == "AmmoType") then
        if(Weapon.AmmoType ~= nil) then
            return Weapon.AmmoType
        elseif giveDefault then
            if(Weapon.Type ~= nil) then
                if(Weapon.Type == "Secondary") then
                    return "Pistol"
                elseif(Weapon.Type == "Primary") then
                    if(Weapon.Class == nil or Weapon.Class == "Rifle") then
                        return "Rifle"
                    elseif(Weapon.Class == "Shotgun") then
                        return "Shotgun"
                    elseif(Weapon.Class == "Bow") then
                        return "Bow"
                    elseif(Weapon.Class == "Sniper Rifle" or Weapon.Class == "Launcher") then
                        return "Sniper"
                    end
                end
            end
        else
            return nil
        end
    elseif(ValName == "Augment") then
        local augments = getAugments(Weapon)
        if(Shared.tableCount(augments) > 0) then
            local AugString = ""
            for i, Aug in pairs(augments) do
                if(i>1) then AugString = AugString.."<br/>" end
                AugString = AugString.."[["..Aug.Name.."]]"
            end
            return AugString
        else
            return nil
        end
    elseif(ValName == "BlockAngle") then
        if(Weapon.Class ~= nil) then
            if(Weapon.Type == "Melee") then
                if(Weapon.BlockAngle ~= nil) then
                    if(asString) then
                        return Weapon.BlockAngle.."&#176;"
                    else
                        return Weapon.BlockAngle
                    end
                elseif(Weapon.Class == "Claws" or Weapon.Class == "Dagger" or Weapon.Class == "Dual Daggers" or Weapon.Class == "Glaive" or Weapon.Class == "Nunchaku" or Weapon.Class == "Rapier" or Weapon.Class == "Sparring" or Weapon.Class == "Tonfa" or Weapon.Class == "Whip") then
                    if(asString) then
                        return "35&#176;"
                    else
                        return 35
                    end
                elseif(Weapon.Class == "Blade and Whip" or Weapon.Class == "Dual Swords" or Weapon.Class == "Fist" or Weapon.Class == "Gunblade" or Weapon.Class == "Staff" or Weapon.Class == "Sword") then
                    if(asString) then
                        return "60&#176;"
                    else
                        return.6
                    end
                elseif(Weapon.Class == "Hammer" or Weapon.Class == "Heavy Blade" or Weapon.Class == "Machete" or Weapon.Class == "Nikana" or Weapon.Class == "Polearm" or Weapon.Class == "Scythe" or Weapon.Class == "Sword and Shield") then
                    if(asString) then
                        return "85&#176;"
                    else
                        return 85
                    end
                end
            
            else
                return ""
            end
        else
            return ""
        end
    elseif(ValName == "Class") then
        if(Weapon.Class ~= nil) then
            if(asString and Weapon.Type == "Melee") then
                return "[[:Category:"..Weapon.Class.."|"..Weapon.Class.."]]"
            else
                return Weapon.Class
            end
        elseif giveDefault then
            return ""
        else
            return nil
        end
    elseif(ValName == "ComboDur") then
        if(Weapon.ComboDur ~= nil) then
            if(asString) then
                return Weapon.ComboDur.." s"
            else
                return Weapon.ComboDur
            end
        elseif giveDefault and (Weapon.Type ~= nil and Weapon.Type == "Melee") then
            if(asString) then
                return "2.0 s"
            else
                return 2.0
            end
        else
            return nil
        end
    elseif(ValName == "Conclave") then
        if(Weapon.Conclave ~= nil) then
            if(asString) then
                if(Weapon.Conclave) then return "Yes" else return "No" end
            else
                return Weapon.Conclave
            end
        elseif giveDefault then
            return false
        else
            return nil
        end
    elseif(ValName == "Disposition") then
        if(Weapon.Type ~= nil and Weapon.Type == "Arch-Melee" or Weapon.Type == "Emplacement") then return nil end
    
        if(Weapon.Disposition ~= nil) then
            if(asString) then
                if (forTable) then
                    return Weapon.Disposition
                else
                    return Icon._Dis(Weapon.Disposition).."<div style=\"display:inline; position:relative; bottom:2px\">("..Weapon.Disposition..")</div>"
                end
            else
                return Weapon.Disposition
            end
        elseif giveDefault then
            if(asString) then
                return "Unknown"
            else
                return 0
            end
        else
            return nil
        end
    elseif(ValName == "Disposition5") then
        if Weapon.Type == "Arch-Melee" or Weapon.Type == "Emplacement" then return nil end
    
        if Weapon.Disposition then
                if(Weapon.Disposition <  0.7) then return 1
            elseif(Weapon.Disposition <  0.9) then return 2
            elseif(Weapon.Disposition <= 1.1) then return 3
            elseif(Weapon.Disposition <= 1.3) then return 4
            else                                   return 5 end
        elseif giveDefault then
            if(asString) then
                return "Unknown"
            else
                return 0
            end
        else
            return nil
        end
    elseif(ValName == "ExilusPolarity") then
        if(Weapon.ExilusPolarity ~= nil) then
            if(asString) then
                return Icon._Pol(Weapon.ExilusPolarity)
            else
                return Weapon.ExilusPolarity
            end
        elseif giveDefault then
            return "None"
        else
            return nil
        end
    elseif(ValName == "Family") then
        if(Weapon.Family ~= nil) then
            if(asString) then
                if(Weapon.Family ~= nil) then
                    local FamilyString = ""
                    local Family = getFamily(Weapon.Family)
                    for i, Weap in pairs(Family) do
                        if(Weap.Name ~= Weapon.Name) then
                            if(string.len(FamilyString) > 0) then FamilyString = FamilyString.."<br/>" end
                            FamilyString = FamilyString.."[["..Weap.Name.."]]"
                        end
                    end
                    return FamilyString
                end
            else
                return Weapon.Family
            end
        elseif giveDefault then
            return ""
        else
            return nil
        end
    elseif(ValName == "FollowThrough") then
        if(Weapon.FollowThrough ~= nil) then
            if(asString) then
                return Shared.asPercent(Weapon.FollowThrough,0)
            else
                return Weapon.FollowThrough
            end
        else
            return nil
        end
    elseif(ValName == "Image") then
        if(Weapon.Image ~= nil) then
            return Weapon.Image
        elseif giveDefault then
            return "Panel.png"
        else
            return nil
        end
    elseif(ValName == "Introduced") then
        if(Weapon.Introduced ~= nil) then
            if (asString) then
                if (forTable) then
                    return Version._getVersionLink(Weapon.Introduced, nil, "true")
                else
                    -- assuming string value is a valid update version
                    return Version._getVersionLink(Weapon.Introduced)
                end
            else
                return Weapon.Introduced
            end
        elseif giveDefault then
            return ""
        else
            return nil
        end
    elseif(ValName == "HeavyAttack") then
        if(Weapon.HeavyAttack ~= nil) then
            if(asString) then
                if(Weapon.HeavyElement ~= nil) then
                    return Icon._Proc(Weapon.HeavyElement).." "..Shared.round(Weapon.HeavyAttack, 2, 1)
                else
                    return Shared.round(Weapon.HeavyAttack, 2, 1)
                end
            else
                return Weapon.HeavyAttack
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "HeavyElement") then
        if(Weapon.HeavyElement ~= nil) then
            return Weapon.HeavyElement
        elseif giveDefault then
            return ""
        else
            return nil
        end
    elseif(ValName == "WindUp") then
        if(Weapon.WindUp ~= nil) then
            if(asString) then
                return Weapon.WindUp.." s"
            else
                return Weapon.WindUp
            end
        else
            return nil
        end
    elseif(ValName == "HeavySlamAttack") then
        if(Weapon.HeavySlamAttack ~= nil) then
            if(asString) then
                -- heavy slam attack element is the same as normal slam attack element
                if(Weapon.SlamElement ~= nil) then
                    return Icon._Proc(Weapon.SlamElement).." "..Shared.round(Weapon.HeavySlamAttack, 2, 1)
                else
                    return Shared.round(Weapon.HeavySlamAttack, 2, 1)
                end
            else
                return Weapon.HeavySlamAttack
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "HeavySlamElement") then
        if(Weapon.HeavySlamElement ~= nil) then
            return Weapon.HeavySlamElement
        elseif giveDefault then
            return ""
        else
            return nil
        end
    elseif(ValName == "HeavyRadialDmg") then
        if(Weapon.HeavyRadialDmg ~= nil) then
            if(asString) then
                -- heavy slam radial attack element is the same as normal slam radial attack element
                if(Weapon.SlamRadialElement ~= nil) then
                    return Icon._Proc(Weapon.SlamRadialElement).." "..Shared.round(Weapon.HeavyRadialDmg, 2, 1)
                else
                    return Shared.round(Weapon.HeavyRadialDmg, 2, 1)
                end
            else
                return Weapon.HeavyRadialDmg
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "HeavyRadialElement") then
        if(Weapon.HeavyRadialElement ~= nil) then
            return Weapon.HeavyRadialElement
        elseif giveDefault then
            return ""
        else
            return nil
        end
    elseif(ValName == "HeavySlamRadius") then
        if(Weapon.HeavySlamRadius ~= nil) then
            if(asString) then
                return Shared.round(Weapon.HeavySlamRadius, 2, 1).." m"
            else
                return Weapon.HeavySlamRadius
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "Magazine") then
        if(Weapon.Magazine ~= nil) then
            if(asString) then
                if (forTable) then 
                    return Weapon.Magazine
                else
                    return Weapon.Magazine..p.doPlural(" round<s> per mag", Weapon.Magazine)
                end
            else
                return Weapon.Magazine
            end
        elseif giveDefault then
            if(asString) then
                return "0 rounds per mag"
            else
                return 0
            end
        else
            return nil
        end
    elseif(ValName == "Mastery") then
        if(Weapon.Mastery ~= nil) then
            return Weapon.Mastery
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "MaxAmmo") then
        local returnVal = 0
        if(Weapon.MaxAmmo ~= nil) then
            returnVal = Weapon.MaxAmmo
        elseif giveDefault then
            if(Weapon.Type ~= nil) then
                if(Weapon.ReloadStyle == "Regenerate") then
                    returnVal = "Infinite"
                elseif(Weapon.Type == "Secondary") then
                    returnVal = 210
                elseif(Weapon.Type == "Primary") then
                    if(Weapon.Class == nil or Weapon.Class == "Rifle") then
                        returnVal = 540
                    elseif(Weapon.Class == "Shotgun") then
                        returnVal = 120
                    elseif(Weapon.Class == "Bow" or Weapon.Class == "Sniper Rifle") then
                        returnVal = 72
                    end
                end
            end
        else
            return nil
        end
        if(asString) then
            if(returnVal == "Infinite" or returnVal > 0) then
                if (forTable) then 
                    return returnVal
                else
                    return returnVal.." rounds"
                end
            else
                return nil
            end
        else
            if(returnVal == "Infinite" or returnVal > 0) then
                return returnVal
            else
                return nil
            end
        end
    elseif(ValName == "MeleeRange") then
        if(Weapon.MeleeRange ~= nil) then
            if(asString) then
                return Weapon.MeleeRange.." m"
            else
                return Weapon.MeleeRange
            end
        else
            return nil
        end
    elseif(ValName == "NoiseLevel") then
        if(Weapon.NoiseLevel ~= nil) then
            return Weapon.NoiseLevel
        elseif giveDefault then
            if(Weapon.Type ~= nil and Weapon.Type ~= "Melee" and Weapon.Type ~= "Arch-Melee") then
                if(Weapon.Class ~= nil and (Weapon.Class == "Bow" or Weapon.Class == "Thrown")) then
                    return "Silent"
                else
                    return "Alarming"
                end
            else
                return nil
            end
        else
            return nil
        end
    elseif(ValName == "Polarities") then
        if(Weapon.Polarities ~= nil and type(Weapon.Polarities) == "table") then
            if(asString) then
                return p.GetPolarityString(Weapon)
            else
                return Weapon.Polarities
            end
        elseif giveDefault then
            if(asString) then
                return "None"
            else
                return {}
            end
        else
            return nil
        end
    elseif(ValName == "Reload") then
        if(Weapon.Reload ~= nil) then
            if regenValue and Weapon.ReloadStyle == "Regenerate" then
                return Shared.round(Weapon.Magazine / Weapon.Reload, 2, 1)
            elseif(asString) then
                if(Weapon.ReloadStyle ~= nil) then
                    if(Weapon.ReloadStyle == "ByRound" and Weapon.Magazine ~= nil) then
                        local result = Shared.round(Weapon.Reload / Weapon.Magazine, 2, 1).." sec per round"
                        result = result.." ("..Shared.round(Weapon.Reload, 2, 1).."s total)"
                        if(forTable) then result = Shared.round(Weapon.Reload, 2, 1).." s" end
                        return result
                    elseif(Weapon.ReloadStyle == "Regenerate") then
                        local result = Shared.round(Weapon.Reload, 2, 1).." rounds per sec"
                        if(Weapon.Magazine ~= nil) then
                            if (Weapon.ReloadDelay ~= nil) then
                                local reloadDelay = Weapon.ReloadDelay
                                if (Weapon.ReloadDelayEmpty ~= nil) then reloadDelay = Weapon.ReloadDelayEmpty end
                                result = result.." ("..reloadDelay.." + "..Shared.round(Weapon.Magazine / Weapon.Reload, 2, 1).."s total)"
                            else
                                result=result.." ("..Shared.round(Weapon.Magazine / Weapon.Reload, 2, 1).."s total)"
                            end
                            if(forTable) then result=Shared.round(Weapon.Magazine / Weapon.Reload, 2, 1).." s" end
                        end
                        return result
                    end
                end
                return Shared.round(Weapon.Reload, 2, 1).." s"
            else
                return Weapon.Reload
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "SlamAttack") then
        if(Weapon.SlamAttack ~= nil) then
            if(asString) then
                if(Weapon.SlamElement ~= nil) then
                    return Icon._Proc(Weapon.SlamElement).." "..Shared.round(Weapon.SlamAttack, 2, 1)
                else
                    return Shared.round(Weapon.SlamAttack, 2, 1)
                end
            else
                return Weapon.SlamAttack
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "SlamElement") then
        if(Weapon.SlamElement ~= nil) then
            return Weapon.SlamElement
        elseif giveDefault then
            return ""
        else
            return nil
        end
    elseif(ValName == "SlamRadialDmg") then
        if(Weapon.SlamRadialDmg ~= nil) then
            if(asString) then
                if(Weapon.SlamRadialElement ~= nil) then
                    return Icon._Proc(Weapon.SlamRadialElement).." "..Shared.round(Weapon.SlamRadialDmg, 2, 1)
                else
                    return Shared.round(Weapon.SlamRadialDmg, 2, 1)
                end
            else
                return Weapon.SlamRadialDmg
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "SlamRadialElement") then
        if(Weapon.SlamRadialElement ~= nil) then
            return Weapon.SlamRadialElement
        elseif giveDefault then
            return ""
        else
            return nil
        end
    elseif(ValName == "SlamRadialProc") then
        if(Weapon.SlamRadialProc ~= nil) then
            if(type(Weapon.SlamRadialProc) == "string") then
                return Icon._Proc(Weapon.SlamRadialProc).." "..Weapon.SlamRadialProc
            elseif(type(Weapon.SlamRadialProc) == "table") then
                return Icon._Proc(Weapon.SlamRadialProc[1]).." "..Weapon.SlamRadialProc[1].."<br />"..
                    Icon._Proc(Weapon.SlamRadialProc[2]).." "..Weapon.SlamRadialProc[2]
            end
        elseif giveDefault then
            return ""
        else
            return nil
        end
    elseif(ValName == "SlamRadius") then
        if(Weapon.SlamRadius ~= nil) then
            if(asString) then
                return Shared.round(Weapon.SlamRadius, 2, 1).." m"
            else
                return Weapon.SlamRadius
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "SlideAttack") then
        if(Weapon.SlideAttack ~= nil) then
            if(asString) then
                if(Weapon.SlideElement ~= nil) then
                    return Icon._Proc(Weapon.SlideElement).." "..Shared.round(Weapon.SlideAttack, 2, 1)
                else
                    return Shared.round(Weapon.SlideAttack, 2, 1)
                end
            else
                return Weapon.SlideAttack
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "SlideElement") then
        if(Weapon.SlideElement ~= nil) then
            return Weapon.SlideElement
        elseif giveDefault then
            return ""
        else
            return nil
        end
    elseif(ValName == "SniperComboReset") then
        if(Weapon.SniperComboReset ~= nil) then
            if(asString) then
                return Shared.round(Weapon.SniperComboReset, 2, 1).." s"
            else
                return Weapon.SniperComboReset
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "SniperComboMin") then
        if(Weapon.SniperComboMin ~= nil) then
            if(asString) then
                return Weapon.SniperComboMin.." shots"
            else
                return Weapon.SniperComboMin
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "Stagger") then
        if(Weapon.Stagger ~= nil) then
            return Weapon.Stagger
        elseif giveDefault then
            return "No"
        else
            return nil
        end
    elseif(ValName == "StancePolarity") then
        if(Weapon.StancePolarity ~= nil) then
            if(asString) then
                return Icon._Pol(Weapon.StancePolarity)
            else
                return Weapon.StancePolarity
            end
        elseif giveDefault then
            return "None"
        else
            return nil
        end
    elseif(ValName == "SyndicateEffect") then
        if(Weapon.SyndicateEffect ~= nil) then
            if(asString) then
                return "[["..Weapon.SyndicateEffect.."]]"
            else
                return Weapon.SyndicateEffect
            end
        else
            return nil
        end
    elseif(ValName == "Traits") then
        if(Weapon.Traits ~= nil) then
            return Weapon.Traits
        elseif giveDefault then
            return {}
        else
            return nil
        end
    elseif(ValName == "Trigger") then
        -- Note there is a specific version for each attack in getAttackValue
        if(Weapon.Trigger ~= nil) then
            if (forTable) then -- return chargetime and burstcount only in tables
                local trigger = Weapon.Trigger
                if(trigger == "Charge") then
                    local cTime = getAttackValue(Weapon, getAttack(Weapon,"Charge"), "ChargeTime", false)
                    if(cTime ~= nil) then
                        return trigger.." ("..Shared.round(cTime, 2, 1).."s)" 
                    else 
                        return trigger
                    end
                elseif(trigger == "Burst") then
                    local bCount = getAttackValue(Weapon, getAttack(Weapon,"Normal"), "BurstCount", false)
                    if(bCount ~= nil) then
                        return trigger.." ("..bCount..")" 
                    else
                        return trigger
                    end
                else
                    return trigger
                end
            else
                return Weapon.Trigger
            end
            
        elseif giveDefault then
            return "Unknown"
        else
            return nil
        end
    elseif(ValName == "CritChance") then -- Note there is a specific version for each attack in getAttackValue    
    -- search in charge attck, then normal, then secondary if still null
        local returnVal=0
        local Attack={}
        if(hasAttack(Weapon, "Charge")) then
            local chargAtt = getAttack(Weapon, "Charge")
            if(chargAtt.CritChance ~= nil) then
                returnVal=chargAtt.CritChance
                Attack=chargAtt
            end
            if chargAtt.CritChance == null then return end
        end
        if(hasAttack(Weapon, "Normal") and returnVal ==0) then
            local normAtt = getAttack(Weapon, "Normal")
            if(normAtt.CritChance ~= nil) then
                returnVal=normAtt.CritChance
                Attack=normAtt
            end
            if normAtt.CritChance == null then return end
        end
        if(hasAttack(Weapon, "Secondary") and returnVal ==0) then
            local secAtt = getAttack(Weapon, "Secondary")
            if(secAtt.CritChance ~= nil) then
                returnVal=secAtt.CritChance
                Attack=secAtt
            end
            if secAtt.CritChance == null then return end
        end
        if(asString and returnVal ~= 0) then
            return Shared.asPercent(returnVal)
        else
            return returnVal
        end
        if giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "CritMultiplier") then
    -- Note there is a specific version for each attack in getAttackValue
    -- search in charge attck, then normal, then secondary if still null
        local returnVal=0
        local Attack={}
        if(hasAttack(Weapon, "Charge")) then
            local chargAtt = getAttack(Weapon, "Charge")
            if(chargAtt.CritMultiplier ~= nil) then
                returnVal=chargAtt.CritMultiplier
                Attack=chargAtt
            end
            if chargAtt.CritMultiplier == null then return end
        end
        if(hasAttack(Weapon, "Normal") and returnVal ==0) then
            local normAtt = getAttack(Weapon, "Normal")
            if(normAtt.CritMultiplier ~= nil) then
                returnVal=normAtt.CritMultiplier
                Attack=normAtt
            end
            if normAtt.CritMultiplier == null then return end
        end
        if(hasAttack(Weapon, "Secondary") and returnVal ==0) then
            local secAtt = getAttack(Weapon, "Secondary")
            if(secAtt.CritMultiplier ~= nil) then
                returnVal=secAtt.CritMultiplier
                Attack=secAtt
            end
            if secAtt.CritMultiplier == null then return end
        end
        if(asString and returnVal ~= 0) then
            return asMultiplier(returnVal)
        else
            return returnVal
        end
        if giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "FireRate") then
        -- Note there is a specific version for each attack in getAttackValue
        -- search in global weapon then normal attck, then charge, then secondary if still null
        local returnVal=0
        local Attack={}
        if(Weapon.FireRate ~= nil) then
            returnVal = Weapon.FireRate
        end
        if(hasAttack(Weapon, "Normal") and returnVal ==0) then
            local normAtt = getAttack(Weapon, "Normal")
            if(normAtt.FireRate ~= nil) then
                returnVal=normAtt.FireRate
                Attack=normAtt
            end
        end
        if(hasAttack(Weapon, "Charge") and returnVal ==0) then
            local chargAtt = getAttack(Weapon, "Charge")
            if(chargAtt.FireRate ~= nil) then
                returnVal=chargAtt.FireRate
                Attack=chargAtt
            end
        end
        if(hasAttack(Weapon, "Secondary") and returnVal ==0) then
            local secAtt = getAttack(Weapon, "Secondary")
            if(secAtt.FireRate ~= nil) then
                returnVal=secAtt.FireRate
                Attack=secAtt
            end
        end
        if(asString and returnVal ~= 0) then
            if(Weapon.Type ~= nil and Weapon.Type ~= "Melee" and Weapon.Type ~= "Arch-Melee") then
                if(forTable) then
                    return Shared.round(returnVal, {3, 1}) -- .." rps"
                else
                    return Shared.round(returnVal, {3, 1})..p.doPlural(" round<s> per sec", returnVal)
                end
            else
                return Shared.round(returnVal, {3, 1})
            end
        else
            return returnVal
        end
        if giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "StatusChance") then  -- Note there is a specific version for each attack in getAttackValue
        -- search in charge attck, then normal, then secondary if still null
        local returnVal=0
        local Attack={}
        if(hasAttack(Weapon, "Charge")) then
            local chargAtt = getAttack(Weapon, "Charge")
            if(chargAtt.StatusChance ~= nil) then
                returnVal=chargAtt.StatusChance
                Attack=chargAtt
            end
        end
        if(hasAttack(Weapon, "Normal") and returnVal ==0) then
            local normAtt = getAttack(Weapon, "Normal")
            if(normAtt.StatusChance ~= nil) then
                returnVal=normAtt.StatusChance
                Attack=normAtt
            end
        end
        if(hasAttack(Weapon, "Secondary") and returnVal ==0) then
            local secAtt = getAttack(Weapon, "Secondary")
            if(secAtt.StatusChance ~= nil) then
                returnVal=secAtt.StatusChance
                Attack=secAtt
            end
        end
        if(asString and returnVal ~= 0) then
                return Shared.asPercent(returnVal)
            else
                return returnVal
            end
        if giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "Type") then
        if(Weapon.Type ~= nil) then
            return Weapon.Type
        elseif giveDefault then
            return ""
        else
            return nil
        end
    elseif(ValName == "Users") then
        if(Weapon.Users ~= nil) then
            if(asString) then
                local result = ""
                for i, str in pairs(Weapon.Users) do
                    if(i > 1) then result = result.."<br />" end
                    result = result..str
                end
                return result
            else
                return Weapon.Users
            end
        elseif giveDefault then
            return {}
        else
            return nil
        end
    elseif(ValName == "Zoom") then
        if(Weapon.Zoom ~= nil) then
            if(asString) then
                local result = ""
                for i, str in pairs(Weapon.Zoom) do
                    if(i > 1) then result = result.."<br />" end
                    result = result..str
                end
                return result
            else
                return Weapon.Zoom
            end
        else
            return nil
        end
    elseif(ValName == "SpecialFSpeed") then -- to show we can put very special keywords... if wanted
        if(Weapon.Name == "Drakgoon") then 
            if(asString) then 
                return "bounce: 25 m/s"
            else
                return 25
            end
        elseif(getAttackValue(Weapon,getAttack(Weapon,"Area"),"ProjectileSpeed")~=nil) then
            if(asString) then 
                return getAttackValue(Weapon,getAttack(Weapon,"Area"),"ProjectileSpeed",true,true)
            else
                return getAttackValue(Weapon,getAttack(Weapon,"Area"),"ProjectileSpeed")
            end
        elseif(getAttackValue(Weapon,getAttack(Weapon,"Secondary"),"ProjectileSpeed")~=nil) then
            if(asString) then 
                return getAttackValue(Weapon,getAttack(Weapon,"Secondary"),"ProjectileSpeed",true,true)
            else
                return getAttackValue(Weapon,getAttack(Weapon,"Secondary"),"ProjectileSpeed")
            end
        elseif(giveDefault) then
            if(asString) then 
                return "0 m/s"
            else
                return 0
            end            
        else 
            return nil
        end
        
    else
        --if everything failed (and it should NOT) try in the getAttackValue
        return getAttackValue(Weapon, getAttack(Weapon, "Normal"), ValName, giveDefault, asString) 
    end
end
    local function Value(valueName, asString, forTable, giveDefault)
        --note that the three last parameters aren't in the same order in functions "Value" and "getValue"
        if(asString == nil) then asString = false end
        if(forTable == nil) then forTable = false end
        if(giveDefault == nil) then giveDefault = true end
        return 
        (function(t)if t[1] then return t[2] else return [=['''<span class="error scribunto-error" id="mw-scribunto-error-0">]=]..t[2]..[=[</span>''']=] end end)
        {pcall(getValue,  Weapon, valueName, giveDefault, asString, forTable)}
    end

    local function Polarity(pol)
        return '['..'[File:'..(({
            Zenurik  = "Zenurik_Pol_W.png",
            Naramon  = "Naramon_Pol_W.png",
            Vazarin  = "Vazarin_Pol_W.png",
            Penjaga  = "Penjaga_Pol_W.png",
            Exilus   = "Exilus_W.png",
            Madurai  = "Madurai_Pol_W.png",
            Koneksi  = "Koneksi_Pol_W.png",
            Umbra    = "Umbra_Pol_W.png",
            Unairu   = "Unairu_Pol_W.png",
            Aura     = "Aura_Pol_White.png",
            None     = "Spacer.png",
        })[({
            Ability='Zenurik',Bar='Naramon',D='Vazarin',Y='Penjaga',Sila='Penjaga',Sentinel='Penjaga',Precept='Penjaga',
            V='Madurai',O='Koneksi',Core='Koneksi',Fusion='Koneksi',Pengetikan='Koneksi',U='Umbra',Q='Umbra',Ward='Unairu',R='Unairu'
        })[pol]or(pol)] or error(pol))..'|x16px]]'
    end
    local pols = Weapon.Polarities
    if pols and pols[1] then
        local p = {}
        for i, v in ipairs(pols) do
            p[i] = Polarity(v)
        end
        pols = table.concat(p)
    else
        pols = 'None'
    end
    
local function getStrongestAttack(weap)
    --for determining the strongest attack of a weapon based on the raw damage
    --it expects the "weap" to be a table
    if weap.Type == "Melee" then --if melee, return the normal attack
        return weap.NormalAttack
    else
        local tempAtt = nil
        local tempDmg = 0
function p.attackLoop(Weapon)
    if(Weapon == nil) then
        return function() return nil end
    end
    local aType = "Normal"

    local iterator = function()
            if(aType == "Normal") then
                local attack = getAttack(Weapon, aType)
                aType = "Charge"
                if attack ~= nil and attack.Damage ~= nil then return "Normal", attack end
            end
            if(aType == "Charge") then
                local attack = getAttack(Weapon, aType)
                aType = "Area"
                if attack ~= nil and attack.Damage ~= nil then return "Charge", attack end
            end
            if(aType == "Area") then
                local attack = getAttack(Weapon, aType)
                aType = "SecondaryArea"
                if attack ~= nil and attack.Damage ~= nil then return "Area", attack end
            end
            if(aType == "SecondaryArea") then
                local attack = getAttack(Weapon, aType)
                aType = "Secondary"
                if attack ~= nil and attack.Damage ~= nil then return "SecondaryArea", attack end
            end
            if(aType == "Secondary") then
                local attack = getAttack(Weapon, aType)
                aType = "Throw"
                if attack ~= nil and attack.Damage ~= nil then return "Secondary", attack end
            end
            if(aType == "Throw") then
                local attack = getAttack(Weapon, aType)
                aType = "ChargedThrow"
                if attack ~= nil and attack.Damage ~= nil then return "Throw", attack end
            end
            if(aType == "ChargedThrow") then
                local attack = getAttack(Weapon, aType)
                aType = "Slam"
                if attack ~= nil and attack.Damage ~= nil then return "ChargedThrow", attack end
            end
            if(aType == "Slam") then
                local attack = getAttack(Weapon, aType)
                aType = "Heavy"
                if attack ~= nil and attack.Damage ~= nil then return "Slam", attack end
            end
            if(aType == "Heavy") then
                local attack = getAttack(Weapon, aType)
                aType = "end"
                if attack ~= nil and attack.Damage ~= nil then return "Heavy", attack end
            end
 
            return nil
        end
    return iterator
end
        for attName, Attack in p.attackLoop(weap) do --looping through attacks of this weapon
            local dmgCount = 0
            if Attack.Damage ~= nil then --if attack has damage -> Count the total damage -> if higher than earlier highest -> this one becomes the new highest
                for dmgType, dmgNum in pairs(Attack.Damage) do --looping through the attack's damage types and tallying up the total damage
                    dmgCount = dmgCount + dmgNum
                end
                if (dmgCount > tempDmg) then
                    tempAtt = Attack
                    tempDmg = dmgCount
                end
            end
        end
local function fillAttack(weap, Attack)
    --filling an attack's data from either Normal or Charge attacks
    local attributeList={"Accuracy","AttackName","ChargeTime","Damage","CritChance","CritMultiplier","StatusChance","FireRate","ShotType","ShotSpeed"}
    local filledAtt = {}
    local normalAtt = getAttack(weap, "Normal")
    local chargeAtt = getAttack(weap, "Charge")
    local areaAtt = getAttack(weap, "Area")
    local filler = nil
    
    if normalAtt ~= nil then 
        filler = normalAtt
    else 
        filler = chargeAtt
    end
    
    for n,attribute in pairs(attributeList) do
        if Attack[attribute] ~= nil then --if the orig attack's stat exists, copy that to filledAtt
            filledAtt[attribute] = Attack[attribute]
        elseif filler[attribute] ~= nil then --else check if the filler attack has the stat, if so, copy to filled
            filledAtt[attribute] = filler[attribute]
        end
    end
    
    --filling the filled attack with area attack, if it exists, for any attributes that might need filling. Made especially for Staticor
    if areaAtt ~= nil then
        for nn,aattribute in pairs(attributeList) do
            -- if the filled attack's stat doesn't exist but does in area attack, copy that to filledAtt
            if filledAtt[aattribute] == nil and areaAtt[aattribute] ~= nil then
                filledAtt[aattribute] = areaAtt[aattribute]
            end
        end
    end

    --if for some reason Fire rate is missing, try to grab it from the weapon itself
    if filledAtt["FireRate"] == nil then
        if weap.FireRate ~= nil then
            filledAtt["FireRate"] = weap.FireRate
        end
    end

    return filledAtt
end
        tempAtt = fillAttack(weap,tempAtt) --filling the attack as many of the stronger attacks lack many stats
        
        return tempAtt
    end
end
    local attack
    if (Weapon.Class == "Bow" or Weapon.Class == "Crossbow" or Weapon.Class == "Launcher" or Weapon.Trigger == "Charge") then
        attack = getStrongestAttack(Weapon)
    else
        if (Weapon.NormalAttack ~= nil) then
            attack = Weapon.NormalAttack
        else
            attack = Weapon.ChargeAttack
        end
    end

    local t = {}
    local bestDmg = 0
    local bestElement = nil
    local total = 0
    local log = ''
    mw.log(name,'Attacks:')
    for type, dmg in Shared.skpairs(attack.Damage) do
        --log=log..type..':\t'..dmg..'\t(goal: '..bestDmg..')'..'\n'
        table.insert(t,"| style=\"padding-right:4px;\" |"..Icon._Proc(type,"","white","x16",nil,true)..space..dmg..'\n|-')
        if(dmg > bestDmg) then
            bestDmg = dmg
            bestElement = type
        end
        total = total + dmg
    end

    attackText = '\n'..table.concat(t,'|')

    mw.log('attackText:',attackText)

    if bestDmg < total then
        attackBiasText = string.format(
            "\n| colspan=4 |%s (%s %s)\n|-%s",
            Shared.round(total, {2, 1}),
            assert(bestElement,'No best element:\n'..log),
            Icon._Proc(bestElement, "", "white","x16"),
            Shared.asPercent(bestDmg / total, 0)
        )
    end

    if Weapon.Type == "Melee" or Weapon.Type == "Arch-Melee" then
        A2Name  = "Type"
        A2Value = "Class"
        C1Name  = "Atk. Speed"
        C1Value = "FireRate"
        C2Name  = "Slide Atk."
        C2Value = "SlideAttack"
        D1Name  = "Range"
        D1Value = "MeleeRange"
        D2Name  = "Followthru"
        D2Value = "FollowThrough"
    else -- Gun
        A2Name  = "Trigger"
        A2Value = "Trigger"
        if attack == Weapon.ChargeAttack then
            C1Name  = "Charge Time"
            C1Value = "ChargeTime"
        else
            C1Name  = "Fire Rate"
            C1Value = "FireRate"
        end
        C2Name  = "Noise"
        C2Value = "NoiseLevel"
        D1Name  = "Reload"
        D1Value = "Reload"
        D2Name  = "Ammo"
        D2Value = "Ammo"
    end
    E1Name  = "Polarities"
    E1Value = "Polarities"

    local Type = Value("Type"):gsub('Atmosphere','Atmo')

    local function atkStat(stat)
        return attack[stat] and getAttackValue(Weapon,attack,stat,nil,stat ~= "FireRate") or Value(stat) or 'n/a'
    end

--[==[
    local image = "\n| class=\"Image\" style=\"height:120px;\" | <div style=\"position:relative; z-index:2;\">[[File:"..Value("Image").."|160px]]</div>"

    local mRank = Weapon.Mastery
    local mRankIconLoc = #mRank >= 2 and "top:4px; left:5px;" or "top:4px; left:9.5px;"

    local zeroPadding = "\n| style=\"padding:0px;\" |"
    local newRow = "\n|-"
    local spacer = "\n| class=\"Spacer\" |"
    local halfTable = "\n| class=\"TableHalf\" |"
    local dataText = "\n{| class=\"Data\" style=\"font-size:12px;\""
    local dataTextCenter = "\n{| class=\"Data\" style=\"font-size:12px; text-align:center;\""
    local tableEnd = "\n|}"

    --creating the table
    local result = {}
    table.insert(result, "<div style=\"position:relative;\">\n{| class=\"Sub\"")
    table.insert(result, newRow..image..mRankIcon..dispoIcon..newRow..spacer..newRow..zeroPadding)
    table.insert(result, dataText..newRow)
    table.insert(result, halfTable..Link("Slot")..space..Type..halfTable..Link(A2Name)..space..Value(A2Value)..tableEnd)
    table.insert(result, newRow..spacer..titleText..newRow..zeroPadding)
    table.insert(result, dataTextCenter..newRow..attackText)
    if(attackBiasText ~= "") then
        table.insert(result, newRow..attackBiasText)
    end
    table.insert(result, tableEnd)
    table.insert(result, newRow..spacer..newRow..zeroPadding..dataText..newRow..halfTable)
    table.insert(result, Link("Crit")..space..atkStat("CritChance").." | "..atkStat("CritMultiplier")..halfTable..Link("Status")..space..atkStat("StatusChance"))
    table.insert(result, newRow..halfTable..Link(C1Name)..space..atkStat(C1Value)..halfTable..Link(C2Name)..space..Value(C2Value))
    --if not melee and not fishing spear => reload and ammo stats
    if not isMelee and Weapon.Type ~= "Gear" then
        table.insert(result, newRow..halfTable..Link("Reload")..space..Value("Reload", true, true)..halfTable..Link("Ammo")..space..Value("Magazine"))
        --if has max ammo => add max ammo stat
        if Value("MaxAmmo") then
            table.insert(result, "&thinsp;/&thinsp;"..Value("MaxAmmo"))
        end
        table.insert(result, newRow.."\n| style=\"text-align:center;\" colspan=2 |"..Link(E1Name)..space..whitePols(E1Value))
    elseif isMelee then
        table.insert(result, newRow.."\n| style=\"text-align:center;\" colspan=2 |"..Link(E1Name)..space..whitePols(E1Value2 'StancePolarity').." | "..whitePols(E1Value))
    end
    table.insert(result, tableEnd..tableEnd.."\n</div>")

    return '<div style="display:inline-block;">\n{| class="Tooltip Main"\n|-\n|style="padding:0px;"|'..table.concat(result)..'\n|}\n</div>'
--[=[]==]
return string.format([==[
<div style="display:inline-block;">
{| class="Tooltip Main"
|-
|style="padding:0px;"|<div style="position:relative;">
{| class="Sub"
|-
| class="Image" style="height:120px;" | <div style="position:relative; z-index:2;">[[File:%s|160px]]</div><div style="position:absolute;top:6px; left:4px; color:white; font-size:16px; font-weight:bold; text-shadow: 0 0 1px #0D1B1C, 0 0 4px #0D1B1C, 1px 1px 2px #0D1B1C, -1px 1px 2px #0D1B1C, 1px -1px 2px #0D1B1C, -1px -1px 2px #0D1B1C;">[[File:MasteryAffinity64.png|28px]]<div style="position:absolute;top:3.5px;left:%spx">%s</div></div><div style="position:absolute;top:6px; right:4px; color:white; font-size:16px; font-weight:bold; text-shadow: 0 0 1px #0D1B1C, 0 0 4px #0D1B1C, 1px 1px 2px #0D1B1C, -1px 1px 2px #0D1B1C, 1px -1px 2px #0D1B1C, -1px -1px 2px #0D1B1C;">[[File:RivenIcon64.png|28px]]<div style="position:absolute;top:3.5px; right:9.5px;">%s</div></div>
|-
| class="Spacer" |
|-
| style="padding:0px;" |
{| class="Data" style="font-size:12px;"
|-
| class="TableHalf" |<span class="LinkText">%s</span>&nbsp;%s
| class="TableHalf" |<span class="LinkText">%s</span>&nbsp;%s
|}
|-
| class="Spacer" |
|-
| style="padding:0px;" |
{| class="Data" style="font-size:12px; text-align:center;"
|-%s%s
|}
|-
| class="Spacer" |
|-
| style="padding:0px;" |
{| class="Data" style="font-size:12px;"
|-
| class="TableHalf" |<span class="LinkText">%s</span>&nbsp;%s
| class="TableHalf" |<span class="LinkText">%s</span>&nbsp;%s
|-
| class="TableHalf" |<span class="LinkText">%s</span>&nbsp;%s
| class="TableHalf" |<span class="LinkText">%s</span>&nbsp;%s
|-
| class="TableHalf" |<span class="LinkText">%s</span>&nbsp;%s
| class="TableHalf" |<span class="LinkText">%s</span>&nbsp;%s
|-
| style="text-align:center;" colspan=2 |<span class="LinkText">%s</span>&nbsp;%s%s
|}
|}
</div>
|}
</div>]==], 
    Weapon.Image, #((Weapon.Mastery or 0)..'') >= 2 and 5 or 9.5, Weapon.Mastery or 0, math.floor(5*(Weapon.Disposition or 1)-1.5), -- top image
    'Slot', Type, A2Name, atkStat(A2Value), -- Slot/Type; Slot/Trigger
    attackText, attackBiasText, -- class="Data"/%s%s    Damage
    'Crit', atkStat 'CritChance' .. ' | ' .. atkStat 'CritMultiplier', 'Status', atkStat 'StatusChance', -- Crit/Status
    C1Name, atkStat(C1Value), C2Name, atkStat(C2Value), -- Fire Rate/Noise; Atk. Speed/Slide Atk.
    D1Name, atkStat(D1Value), D2Name, atkStat(D2Value), -- Reload/Ammo; Range/Followthru
    E1Name, Weapon.StancePolarity and Polarity(Weapon.StancePolarity).." | " or '', pols -- Polarities
):gsub('%.00%%','%%')--]=]

    --[==[]===]
    local module = {n=[[Module:Weapons]],    l={f='weaponTooltip'},
        f={'<div style="display:inline-block;">\n{| class="Tooltip Main"\n|-\n|style="padding:0px;"|','\n|}\n</div>'},}
    return module.f[1]..require(module.n)[module.l.f]{args={name}}..module.f[2]--]==]
end,--[= [
DamageTypes = function(name)
    local module = {n=[[Module:DamageTypes]],l={f='tooltip'},
            f={'{| class="Tooltip"\n|-\n|style="padding:0;"|\n','\n|}'},}
    return module.f[1]..require(module.n)[module.l.f]{args={name}}..module.f[2]
end,--]=]
Arcane      = function(name)
    local module = {n=[[Module:Arcane]],     l={f='tooltip'},}
    return require(module.n)[module.l.f]{args={name}}
end,
}