Wiki Warframe

Utilisation du Wiki

Pour une meilleure utilisation du Wiki Warframe FR, merci d'activer les scripts Javascript lors de la consultation de certains pages, pour assurer le fonctionnement de certaines fonctionnalités.
Si vous souhaitez contribuer au Wiki, rejoignez-nous sur le Discord Warframe FR (espace wiki)

- Yazu 17:00 01/10/2022

EN SAVOIR PLUS

Wiki Warframe
Advertisement
Erreur Lua dans Module:Docbunto à la ligne 922 : Documentation markup pour Docbunto introuvable dans Module:Weapons.
Documentation automatique créée à l'aide de Docbuntu (-> Modèle automatique)

Voir aussi

Code


--This will eventually contain data for various weapons
--For use in automating assorted wiki functions and to reduce the number of updates needed
-- • 

local p = {}

local WeaponData = mw.loadData( 'Module:Weapons/data' )
local ConclaveData = mw.loadData( 'Module:Weapons/Conclave/data' )
local Icon = require( "Module:Icon" )
local Shared = require( "Module:Shared" )
local Mod = require( "Module:Mods" )

local Elements = {"Impact", "Perforation", "Tranchant", "Feu", "Glace", "Poison", "Électrique", "Explosif", "Corrosif", "Radiation", "Magnétique", "Gaz", "Viral"}
local Physical = {"Impact", "Perforation", "Tranchant"}
local UseDefaultList = {"NOISELEVEL", "AMMOTYPE", "MAXAMMO", "DISPOSITION", "CHANNELMULT", "HEADSHOTMULTIPLIER"}
local VariantList = {"Prime", "Prisma", "Wraith", "Vandal", "Vaykor", "Synoid", "Telos", "Secura", "Sancti", "Rakta", "Mara", "MK1"}

function p.doPlural(Text, Value)
    if(tonumber(Value) == 1) then
        Text = string.gsub(Text, "(<.+>)", "")
    else
        Text = string.gsub(Text, "<(.+)>", "%1")
    end
    return Text
end

function p.isVariant(WeapName)
    for i, var in pairs(VariantList) do
        if(string.find(WeapName, var)) then
            local baseName = string.gsub(WeapName, ' ?'..var..' ?-?', '')
            return true, var, baseName
        end
    end

    return false, 'Base', WeapName
end

function p.buildName(BaseName, Variant)
    if(Variant == nil or Variant == 'Base' or Variant == '') then
        return BaseName
    elseif(Variant == 'Prime' or Variant == 'Wraith' or Variant == 'Vandal') then
        return BaseName..' '..Variant
    elseif(Variant == "MK1") then
        return "MK1-"..BaseName
    else
        return Variant..' '..BaseName
    end
end

--It's a bit of a mess, but this is for compressing a list with variants
--So if a list has Braton, Braton Prime, and MK1-Braton it'll list as
--                  Braton (MK1, Prime)
function p.shortLinkList(Weapons)
    --First grabbing all the pieces and stashing them in a table
    local baseNames = {}
    for key, weap in Shared.skpairs(Weapons) do
        local isVar, varType, baseName = p.isVariant(weap.Name)
        if(baseNames[baseName] == nil) then baseNames[baseName] = {} end
        table.insert(baseNames[baseName], varType)
    end
    
    --Then the fun part: Pulling the table together
    local result = {}
    for baseName, variants in Shared.skpairs(baseNames) do
        --So first, check if 'Base' is in the list
        --Because if it isn't, list all variants separately
        if(Shared.contains(variants, "Base")) then
            table.sort(variants)
            --First, get the basic version
            local thisRow = '[['..baseName.."]]"
            --then, if there are variants...
            if(Shared.tableCount(variants) > 1) then
                --List them in parentheses one at a time
                thisRow = thisRow..' ('
                local count = 0
                for i, varName in pairs(variants) do
                    if(varName ~= 'Base') then
                        if(count > 0) then thisRow = thisRow..', ' end
                        thisRow = thisRow..'[['..p.buildName(baseName, varName)..'|'..varName..']]'
                        count = count + 1
                    end
                end
                thisRow = thisRow..')'
            end
            table.insert(result, thisRow)
        else
            for i, varName in pairs(variants) do
                table.insert(result, '[['..p.buildName(baseName, varName)..']]')
            end
        end
    end
    return result
end

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 function checkWeapon(weap, weapName, conclave)
    if weap == nil or type(weap) ~= 'table' then
        if conclave then
            return p.getConclaveWeapon(weapName)
        else
            return p.getWeapon(weapName)
        end
    elseif type(weap) == 'table' then
        return weap
    end
end

function p.weaponExists(frame)
    local weapName = frame.args ~= nil and frame.args[1] or nil
    
    return p._weaponExists(weapName)
end

function p._weaponExists(weapName, weap)
    local weap = checkWeapon(weap, weapName)
    
    if weapName == 'Épées Versatiles Sombres' then
        return true
    elseif weap then
        return true
    end
    
    if weapName == nil then
        return 'Enter weapon name.'
    elseif weap == nil then
        return 'No weapon '..weapName..' found.'
    end
    
    
end

function p.getLink(frame)
    local weapName = frame.args ~= nil and frame.args[1] or nil
    if weapName == nil then
        return 'Enter weapon name.'
    end
    
    return p._getLink(weapName)
end

function p._getLink(weapName, weap)
    local weap = checkWeapon(weap, weapName)
    local exists = p._weaponExists(weapName, weap)
    if weapName == "Épées Versatiles Sombres" then
        return "Épées Versatiles Sombres"
    elseif exists == true then
        local temp = weap.Link
        if weap.Type == "Arch-Fusil (Atmosphère)" then
            local atmoTemp = Shared.splitString(weap.Name, "%s")
            local atmoCount = Shared.tableCount(atmoTemp)
            if atmoCount == 2 then
                return atmoTemp[1]
            elseif atmoCount >= 2 then
                return table.concat(atmoTemp, ' ', 1, (atmoCount-1))
            end
            return weap.Name
        elseif temp then
            return temp
        else
            return weap.Name
        end
    elseif weapName == nil then
        return false
    else
        return false
    end
end

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

    return nil
end

function p.isMelee(frame)
    if(frame == nil) then
        return nil
    end
    local Weapon = frame.args ~= nil and frame.args[1] or frame
    if(type(Weapon) == "string") then
        Weapon = p.getWeapon(Weapon)
    end
    
    if(Weapon == nil) then
        return nil
    end
    
    if(Weapon.Type ~= nil and (Weapon.Type == "Mêlée" or Weapon.Type == "Arch-Mêlée")) then
        return "yes"
    end
    
    return nil
end

function p.isArchwing(frame)
    if(frame == nil) then
        return nil
    end
    local Weapon = frame.args ~= nil and frame.args[1] or frame
    if(type(Weapon) == "string") then
        Weapon = p.getWeapon(Weapon)
    end
    
    if(Weapon == nil) then
        return nil
    end
    
    if(Weapon.Type ~= nil and (Weapon.Type == "Arch-Fusil" or Weapon.Type == "Arch-Mêlée")) then
        return "yes"
    end
    
    return nil
end

local function getAttack(Weapon, AttackType)
    if(Weapon == nil or AttackType == nil) then
        return nil
    elseif(type(Weapon) == "string") then
        Weapon = p.getWeapon(Weapon)
    end
    AttackType = string.upper(AttackType)
    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 == "MELEESLAM") then
        return Weapon.MeleeSlam
    elseif(AttackType == "MELEEHEAVY") then
        return Weapon.MeleeHeavy
    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 dontHasAttack(Weapon, AttackType)
    if(getAttack(Weapon, AttackType) ~= nil) then 
        return nil 
    else 
        return true 
    end
end


function p.hasAttack(frame)
    local WeapName = frame.args[1]
    local AttackName = frame.args[2]
    
    if(WeapName == nil) then
        return "ERREUR: Il n'y a pas le nom de l'arme"
    elseif(AttackName == nil) then
        AttackName = "Normal"
    end
    
    local Weapon = p.getWeapon(WeapName)
    if(Weapon == nil) then return "ERREUR: L'arme  "..WeapName.." n'a pas été trouvé" end
    
    return hasAttack(Weapon, AttackName)
end

function hasMultipleTypes(Attack)
    local typeCount = 0
    if(Attack ~= nil and Attack.Damage ~= nil) then
        for key, dmg in Shared.skpairs(Attack.Damage) do
            if(dmg > 0) then
                typeCount = typeCount + 1
            end
        end
    end
    if(typeCount > 1) then return "yes" else return nil end
end

function p.hasMultipleTypes(frame)
    local WeapName = frame.args[1]
    local AttackName = frame.args[2]
    if(AttackName == nil) then AttackName = "Normal" end
    local attack = getAttack(WeapName, AttackName)
    return hasMultipleTypes(attack)
end

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 = "end"
                if attack ~= nil and attack.Damage ~= nil then return "ChargedThrow", attack end
            end
 
            return nil
        end
    return iterator
end

function p.getStance(StanceName)
    for i, Stance in pairs(WeaponData["Postures"]) do
        if(Stance.Name == StanceName) then
            return Stance
        end
    end
    return nil
end

local function getAugments(Weapon)
    local name = Weapon.Name ~= nil and Weapon.Name or Weapon
    local augments = {}
    for i, Augment in pairs(WeaponData["Augments"]) do
        for j, WeapName in pairs(Augment.Weapons) do
            if(WeapName == name) then
                table.insert(augments, Augment)
            end
        end
    end
    return augments
end

local function getFamily(FamilyName)
    local familyMembers = {}
    for i, Weapon in Shared.skpairs(WeaponData["Weapons"]) do
        if(Weapon.Family == FamilyName) then
            table.insert(familyMembers, Weapon)
        end
    end
    return familyMembers
end

local function linkMeleeClass(weapClass)
    if(weapClass == nil) then
        return nil
    else
        return "[[:Category:"..weapClass.."|"..weapClass.."]]"
    end
end

--Returns all melee weapons.
--If weapType is not nil, only grab for a specific type
--For example, if weapType is "Nikana", only pull Nikanas
local function getMeleeWeapons(weapClass, PvP)
    local weaps = {}
    local weapClasses = {}
    if(weapClass ~= nil) then
        weapClasses = Shared.splitString(weapClass, ',')
    end
    
    for i, weap in Shared.skpairs(WeaponData["Weapons"]) do
        if((weap.Ignore == nil or not weap.Ignore) and weap.Type ~= nil and weap.Type == "Mêlée") then
            local classMatch = (weapClass == nil or Shared.contains(weapClasses, weap.Class))
            local pvpMatch = (PvP == nil or (PvP and weap.Conclave ~= nil and weap.Conclave))
            if (classMatch and pvpMatch) then
                table.insert(weaps, weap)
            end
        end
    end
    
    return weaps
end

--As above, but for Conclave stats
local function getConclaveMeleeWeapons(weapClass, PvP)
    local weaps = {}
    local weapClasses = {}
    if(weapClass ~= nil) then
        weapClasses = Shared.splitString(weapClass, ',')
    end
    
    for i, weap in Shared.skpairs(ConclaveData["Weapons"]) do
        if((weap.Ignore == nil or not weap.Ignore) and weap.Type ~= nil and weap.Type == "Mêlée") then
            local classMatch = (weapClass == nil or Shared.contains(weapClasses, weap.Class))
            local pvpMatch = (PvP == nil or (PvP and weap.Conclave ~= nil and weap.Conclave))
            if (classMatch and pvpMatch) then
                table.insert(weaps, weap)
            end
        end
    end
    
    return weaps
end

--Learning new things... Trying to allow sending in an arbitrary function
function p.getWeapons(validateFunction)
    local weaps = {}
    for i, weap in Shared.skpairs(WeaponData["Weapons"]) do
        if((weap.Ignore == nil or not weap.Ignore) and validateFunction(weap)) then
            table.insert(weaps, weap)
        end
    end
    return weaps
end

--Same as getWeapons, but for Conclave data
function p.getConclaveWeapons(validateFunction)
    local weaps = {}
    for i, weap in Shared.skpairs(ConclaveData["Weapons"]) do
        if((weap.Ignore == nil or not weap.Ignore) and validateFunction(weap)) then
            table.insert(weaps, weap)
        end
    end
    return weaps
end

local function asMultiplier(val)
    if(val == nil) then
        return "1.0x"
    end
    return Shared.round(val, 2, 1).."x"
end

--Returns all melee weapons.
--If weapType is not nil, only grab for a specific type
--For example, if weapType is "Nikana", only pull Nikanas
local function getStances(weapType, pvpOnly, weapName)
    local stances = {}
    
    --Exception de Serres de Garuda
    if weapName == "Serres de Garuda" then
       weapType = "Griffes" 
    end
    
    if weapType ~= "Arme Exaltée" then
        for i, stance in Shared.skpairs(WeaponData["Postures"]) do
            local classMatch = (weapType == nil or weapType == stance.Class)
            local pvpMatch = (pvpOnly ~= nil and pvpOnly) or (stance.PvP == nil or not stance.PvP)
            if (classMatch and pvpMatch) then
                table.insert(stances, stance)
            end
        end
    else
        for i, stance in Shared.skpairs(WeaponData["Postures"]) do
            local nameMatch = (weapName == nil or weapName == stance.Weapon)
            if nameMatch then
                table.insert(stances, stance)
            end
        end
    end
    return stances
end

local function _getStancesList(weapType)
    
    local ret = nil
    local stanceArray = getStances(weapType, true)
    local first = true
    for _, stance in pairs(stanceArray) do
        if(first) then
            first = false
            ret = Mod._tooltipText(stance.Name)
        else
            ret = ret.." • "..Mod._tooltipText(stance.Name)
        end
        if(stance.PvP) then
            ret = ret.." (PvP)"
        end
    end
    
    return ret
end

function p.getStancesList(frame)
    
    local weapType = frame.args ~= nil and frame.args[1]
    
    return _getStancesList(weapType)
end

local function HasTrait(Weapon, Trait)
    if(Trait == nil or Weapon.Traits == nil) then
        return false
    end
    
    for i, theTrait in pairs(Weapon.Traits) do
        if(theTrait == Trait) then
            return true
        end
    end
    
    return false
end

--If Type is not nil, get damage weapon deals of that type
--If it deals no damage of that type, return 0 instead of nil
--It Type is nil, return total damage
local function GetDamage(Attack, Type, ByPellet)
    if(ByPellet == nil) then ByPellet = false end
    if(Attack == nil or Attack.Damage == nil) then return 0 end
    
    local pCount = 1
    if(ByPellet and Attack.PelletCount ~= nil) then pCount = Attack.PelletCount end
    if(Type == nil) then
        local total = 0
            for i, d in Shared.skpairs(Attack.Damage) do
                total = total + d
            end
        return total / pCount
    else
        if(Type == "Physical") then
            local Impact = Attack.Damage["Impact"] ~= nil and Attack.Damage["Impact"] or 0
            local Puncture = Attack.Damage["Perforation"] ~= nil and Attack.Damage["Perforation"] or 0
            local Slash = Attack.Damage["Tranchant"] ~= nil and Attack.Damage["Tranchant"] or 0
            return (Impact + Puncture + Slash) / pCount
        elseif(Type == "Element") then
            for dType, dmg in Shared.skpairs(Attack.Damage) do
                if(not Shared.contains(Physical, dType) or dmg <= 0) then
                    return dmg / pCount
                end
            end
            return 0
        elseif(Attack.Damage[Type] == nil) then
            return 0
        else
            return Attack.Damage[Type] / pCount
        end
    end
end

--Returns the damage string as it's formatted in a comparison row
--So instead of '0', returns '-', and appends the icon for an element if necessary
local function GetDamageString(Attack, Type, ByPellet)
    if(ByPellet == nil) then ByPellet = false end
    if(Attack == nil or Attack.Damage == nil) then return "" end
    
    local pCount = 1
    if(ByPellet and Attack.PelletCount ~= nil) then pCount = Attack.PelletCount end
    if(Type == nil) then
        if(not hasMultipleTypes(Attack)) then
            for key, val in pairs(Attack.Damage) do
                if(val > 0) then
                    return Icon._Proc(key).." "..Shared.round(val / pCount, 2)
                end
            end
            return ""
        else
            return Shared.round(GetDamage(Attack, nil, ByPellet), {2, 1})
        end
    else
        local thisVal = GetDamage(Attack, Type, ByPellet)
        if(thisVal == 0) then
            return ""
        else
            return Shared.round(thisVal, {2, 1})
        end
    end
end

local function GetDamageBias(Attack, IncludeSingle)
    if(IncludeSingle == nil) then IncludeSingle = false end
    
    if(Attack.Damage ~= nil and Shared.tableCount(Attack.Damage) > 0) then
        local total = 0
        local bestDmg = 0
        local bestElement = nil
        local count = 0
        for Element, Dmg in pairs(Attack.Damage) do
            if(Dmg > bestDmg) then
                bestDmg = Dmg
                bestElement = Element
            end
            total = total + Dmg
            if(Dmg > 0) then
                count = count + 1
            end
        end
        --Make sure there are two damage instances that are above zero
        --Exception for physical damage types
        if(count > 1 or (IncludeSingle and count > 0)) then
            return (bestDmg / total), bestElement
        else
            return nil
        end
    else
        return nil
    end
end

--If the attack has at least two damage types,
--  Returns something like "58.3% Slash"
--If it doesn't, returns nil
local function GetDamageBiasString(Attack, HideType, ShowText, IncludeSingle, Color)
    if(HideType == nil) then HideType = false end
    if(ShowText == nil) then ShowText = "" end
    if(IncludeSingle == nil) then IncludeSingle = false end
    
    local bestPercent, bestElement = GetDamageBias(Attack, IncludeSingle)
    if(bestPercent ~= nil) then
        local result = Shared.asPercent(bestPercent, 0)
        if(not HideType) then
            result = Icon._Proc(bestElement, ShowText, Color).." "..result
        end
        return result
    else
        return nil
    end
end

function p.GetPolarityString(Weapon)
    if(Weapon.Polarities == nil or type(Weapon.Polarities) ~= "table" or Shared.tableCount(Weapon.Polarities) == 0) then
        return "Aucune"
    else
        local resString = ""
        for i, pol in pairs(Weapon.Polarities) do
            local tempPol = Icon._Pol(pol)
            resString = resString..tempPol
        end
        --Adding Exceptions
        if(Weapon.Name == "Lame Exaltée") then
            resString = resString.."(Vanilla/Prime)<br/>"..Icon._Pol("Umbra")..Icon._Pol("Umbra").."(Umbra)"
        end
        
        
        return resString
    end
end

local function GetStancePolarity(Weapon)
    if(Weapon.StancePolarity == nil or Weapon.StancePolarity == "Aucune") then
        return "Aucune"
    else
        return Icon._Pol(Weapon.StancePolarity)
    end
end

local function getWeaponStanceList(Weapon)
    if(Weapon == nil or Weapon.Type ~= "Mêlée") then return nil end
    
    local stances = getStances(Weapon.Class, Weapon.Conclave, Weapon.Name)
    
    local result = ""
    
    for i, stance in pairs(stances) do
        if (string.len(result) > 0) then
            result = result.."<br/>"
        end
        
        local polarity = ''
        local link = ''
        
        if Weapon.Class ~= "Arme Exaltée" or Weapon.Name == "Serres de Garuda" then
            result = result..Mod._tooltipText(stance.Name)
        end
        
        result = result..polarity
        --If this is a PvP Stance, add the disclaimer
        if(stance.PvP ~= nil and stance.PvP) then
            result = result.." (PvP)"
        end
    end
    
    return result
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
    regularVal = Shared.titleCase(string.sub(ValName, 1, 1), string.sub(ValName, 2))
    ValName = string.upper(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.." mun. par tir"
            else
                return Attack.AmmoCost
            end
        elseif(giveDefault) then
            return 1
        else
            return nil
        end
    elseif(ValName == "BLOCKANGLE") then
        if(Weapon.BlockAngle ~= nil) then
            if(asString) then
                return Weapon.BlockAngle.."°"
            else
                return Weapon.BlockAngle
            end
        else
            return nil
        end
    elseif(ValName == "BURSTCOUNT") then
        if(Attack.BurstCount ~= nil) then
            if(asString) then
                local result = Attack.BurstCount.." balles"
                local dmg = GetDamage(Attack) * Attack.BurstCount
                return result.." ("..Shared.round(dmg, 2, 1).." dégâts totaux)"
            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 == "CRITCHANCE") then -- note there is getValue version
    --search in current attack, then normal, 
        if(Attack.CritChance ~= nil) 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 ~= nil) 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 = "Dégâts max. jusqu'à "..Shared.round(Attack.Falloff.StartRange, 2, 1).." m"
            falloffText = falloffText.."<br/>Dégâts min. à partir de "..Shared.round(Attack.Falloff.EndRange, 2, 1).." m"
            if(Attack.Falloff.Reduction ~= nil) then
                falloffText = falloffText.."<br/>"..Shared.asPercent(Attack.Falloff.Reduction).." réduction max."
            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 ~= "Mêlée" 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(" balle<s>/s", 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(Weapon.FollowThrough ~= nil) then
            if(asString) then
                return Shared.asPercent(Weapon.FollowThrough, 0)
            else
                return Weapon.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 == "Secondaire") then
                    if(Weapon.Class == "Shotgun Sidearm") then
                        return '1.2x'
                    elseif(Weapon.Class == "Arbalète" 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 == "Principale") then
                    if(Weapon.Class == "Fusil à Pompe") then
                        return "1.2x"
                    elseif(Weapon.Class == "Arc") then
                        return "2.0x"
                    elseif(Weapon.Class == "Fusil Sniper") 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 == "MELEECOMBODUR") then
        if(Weapon.MeleeComboDur ~= nil) then
            if(asString) then
                return Weapon.MeleeComboDur.." s"  
            else
                return Weapon.MeleeComboDur
            end
        elseif giveDefault then
            return 5.0
        else
            return nil
        end
    elseif(ValName == "MELEERANGE") then
        if(Weapon.MeleeRange ~= nil) then
            if(asString) then
                return Weapon.MeleeRange.." m"
            else
                return Weapon.MeleeRange
            end
        elseif giveDefault then
            return 1
        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 == "PELLETDAMAGE") then
        if(Attack.PelletCount ~= nil) then
            local result = GetDamageString(Attack, nil, true)
            if(Attack.PelletName ~= nil) then
                return result.." par "..string.lower(Attack.PelletName)
            else
                return result.." par balle"
            end
        else
            return nil
        end
    elseif(ValName == "PELLETNAME") then
        if(Attack.PelletCount ~= nil) then
            if(Attack.PelletName ~= nil) then
                return Attack.PelletName
            else
                return "Balle"
            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.." dégâts par "..string.lower(Attack.PelletName)..")"
            else
                return result.." dégâts par balle)"
            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
        --man screw you too Fusilai
        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.." balles"
            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 == nil) then
            if(Weapon.Trigger ~= nil) then
                return Weapon.Trigger
            end
        else
            return Attack.Trigger
        end
        
        if giveDefault then
            return "Inconnu"
        else
            return nil
        end
    else
        return "ERREUR : No such value "..ValName
    end
end

local function getValue(Weapon, 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(type(ValName) == "table") then
        local VName1 = string.upper(ValName[1])
        local VName2 = string.upper(ValName[2])
        if(VName1 == nil or VName2 == nil) then
            return nil
        end
            
        if(VName1 == "ATTACK" or VName1 == "NORMALATTACK" or VName1 == "NORMAL") 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, "MeleeSlam"), VName2, giveDefault, asString, forTable)
        elseif(VName1 == "HEAVY" or VName1 == "HEAVYATTACK") then
            return getAttackValue(Weapon, getAttack(Weapon, "MeleeHeavy"), VName2, giveDefault, asString, forTable)
        else
            return "ERROR: No such attack '"..VName1.."'"
        end
    end
    
    ValName = string.upper(ValName)
    if(ValName == "NAME") then
        if(Weapon.Name ~= nil) then
            if(forTable) then 
                if (string.find(Weapon.Name,"Atmosphère")~=nil) then
                    return "[["..string.gsub(Weapon.Name,"%s%(Atmosphère%)","").."|"..string.gsub(Weapon.Name,"osphère","").."]]"
                else
                    return "[["..Weapon.Name.."]]"
                end
            else
                return Weapon.Name
            end
        elseif giveDefault then
            return ""
        else
            return nil
        end
    elseif(ValName == "AMMOTYPE") then
        if(Weapon.AmmoType ~= nil) then
            return Weapon.AmmoType
        elseif giveDefault then
            if(Weapon.Type ~= nil) then
                if(Weapon.Type == "Secondaire") then
                    return "Pistolet"
                elseif(Weapon.Type == "Principale") then
                    if(Weapon.Class == nil or Weapon.Class == "Fusil") then
                        return "Fusil"
                    elseif(Weapon.Class == "Fusil à Pompe") then
                        return "Fusil à Pompe"
                    elseif(Weapon.Class == "Fusil de Sniper" or Weapon.Class == "Arc" or Weapon.Class == "Launcher") then
                        return "Sniper/Arc"
                    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..Mod._tooltipText(Aug.Name)
            end
            return AugString
        else
            return nil
        end
    elseif(ValName == "BLOCKRESIST") then
        if(Weapon.Class ~= nil) then
            if(Weapon.Type == "Mêlée") then
                if(Weapon.BlockResist ~= nil) then
                    if(asString) then
                        return Shared.asPercent(Weapon.BlockResist)
                    else
                        return Weapon.BlockResist
                    end
                elseif(Weapon.Class == "Claws" or Weapon.Class == "Dague" or Weapon.Class == "Doubles Dagues" 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%"
                    else
                        return .35
                    end
                elseif(Weapon.Class == "Blade and Whip" or Weapon.Class == "Doubles Épées" or Weapon.Class == "Fist" or Weapon.Class == "Gunblade" or Weapon.Class == "Bâton" or Weapon.Class == "Épée") then
                    if(asString) then
                        return "60%"
                    else
                        return .6
                    end
                elseif(Weapon.Class == "Marteau" or Weapon.Class == "Lame Lourde" or Weapon.Class == "Machette" or Weapon.Class == "Nikana" or Weapon.Class == "Polearm" or Weapon.Class == "Faux" or Weapon.Class == "Épée et Bouclier") then
                    if(asString) then
                        return "85%"
                    else
                        return .85
                    end
                end
            
            else
                return ""
            end
        else
            return ""
        end
    elseif(ValName == "CHANNELMULT") then
        if(Weapon.ChannelMult ~= nil) then
            if(asString) then
                return asMultiplier(Weapon.ChannelMult)
            else
                return Weapon.ChannelMult
            end
        elseif giveDefault and (Weapon.Type ~= nil and Weapon.Type == "Mêlée") then
            if(asString) then
                return "1.5x"
            else
                return 1.5
            end
        else
            return nil
        end
    elseif(ValName == "CLASS") then
        if(Weapon.Class ~= nil) then
            return "[[:Category:"..Weapon.Class.."|"..Weapon.Class.."]]"
        elseif giveDefault then
            return ""
        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-Mêlée" or Weapon.Type == "Emplacement") then return nil end
    
        if(Weapon.Disposition ~= nil) then
            if(asString) then
                return Icon._Dis(Weapon.Disposition)..'<div style="display:inline; position:relative; bottom:2px">('..Weapon.Disposition..')</div>'
            else
                return Weapon.Disposition
            end
        elseif giveDefault then
            if(asString) then
                return "Inconnu"
            else
                return 0
            end
        else
            return nil
        end
    elseif(ValName == "DISPOSITION5") then
        if(Weapon.Type ~= nil and (Weapon.Type == "Arch-Fusil" or Weapon.Type == "Arch-Mêlée") or Weapon.Type == "Emplacement") then return nil end
    
        if(Weapon.Disposition ~= nil) 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 "Inconnu"
            else
                return 0
            end
        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..p._weaponTooltipText(Weap.Name, nil, nil, false)
                        end
                    end
                    return FamilyString
                end
            else
                return Weapon.Family
            end
        elseif giveDefault then
            return ""
        else
            return nil
        end
    elseif(ValName == "FINISHERDAMAGE") then
        if(Weapon.FinisherDamage ~= nil) then
            if(asString) then
                return Shared.round(Weapon.FinisherDamage, 2, 1)
            else
                return Weapon.FinisherDamage
            end
        elseif giveDefault then
            return 0
        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 == "HEAVYATTACK") then
        if(Weapon.MeleeHeavy ~= nil and Weapon.MeleeHeavy.Damage ~= nil) then
            local heavyDamage = Weapon.MeleeHeavy.Damage
            if(asString) then
                if(Weapon.MeleeHeavy.Element ~= nil) then
                    return Icon._Proc(Weapon.MeleeHeavy.Element).." "..Shared.round(heavyDamage, 2, 1)
                else
                    return Shared.round(heavyDamage, 2, 1)
                end
            else
                return heavyDamage
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "HEAVYELEMENT") then
        if(Weapon.MeleeHeavy ~= nil and Weapon.MeleeHeavy.Element ~= nil) then
            return Weapon.MeleeHeavy.Element
        elseif giveDefault then
            return ""
        else
            return nil
        end
    elseif(ValName == "WINDUP") then
        if(Weapon.MeleeHeavy ~= nil and Weapon.MeleeHeavy.WindUp ~= nil) then
            local windUp = Weapon.MeleeHeavy.WindUp
            if(asString) then
                return windUp.." s"
            else
                return windUp
            end
        else
            return nil
        end
    elseif(ValName == "HEAVYSLAMATTACK") then
        if(Weapon.MeleeHeavy ~= nil and Weapon.MeleeHeavy.SlamDamage ~= nil) then
            local heavySlamDamage = Weapon.MeleeHeavy.SlamDamage
            if(asString) then
                if(Weapon.MeleeHeavy.SlamElement ~= nil) then
                    return Icon._Proc(Weapon.MeleeHeavy.SlamElement).." "..Shared.round(heavySlamDamage, 2, 1)
                else
                    return Shared.round(heavySlamDamage, 2, 1)
                end
            else
                return heavySlamDamage
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "HEAVYSLAMELEMENT") then
        if(Weapon.MeleeHeavy ~= nil and Weapon.MeleeHeavy.SlamElement ~= nil) then
            return Weapon.MeleeHeavy.SlamElement
        elseif giveDefault then
            return ""
        else
            return nil
        end
    elseif(ValName == "HEAVYRADIALDMG") then
        if(Weapon.MeleeHeavy ~= nil and Weapon.MeleeHeavy.SlamRadialDamage ~= nil) then
            local damage = Weapon.MeleeHeavy.SlamRadialDamage
            if(asString) then
                if(Weapon.MeleeHeavy.SlamRadialElement ~= nil) then
                    return Icon._Proc(Weapon.MeleeHeavy.SlamRadialElement).." "..Shared.round(damage, 2, 1)
                else
                    return Shared.round(damage, 2, 1)
                end
            else
                return damage
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "HEAVYRADIALELEMENT") then
        if(Weapon.MeleeHeavy ~= nil and Weapon.MeleeHeavy.SlamRadialElement ~= nil) then
            return Weapon.MeleeHeavy.SlamRadialElement
        elseif giveDefault then
            return ""
        else
            return nil
        end
    elseif(ValName == "HEAVYSLAMRADIUS") then
        if(Weapon.MeleeHeavy ~= nil and Weapon.MeleeHeavy.SlamRadius ~= nil) then
            local radius = Weapon.MeleeHeavy.SlamRadius
            if(asString) then
                return Shared.round(radius, 2, 1).." m"
            else
                return radius
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end    
    elseif(ValName == "INTRODUCED") then
        if(Weapon.Introduced ~= nil) then
            return Weapon.Introduced
        elseif giveDefault then
            return ""
        else
            return nil
        end
    elseif(ValName == "JUMPATTACK") then
        if(Weapon.JumpAttack ~= nil) then
            if(asString) then
                if(Weapon.JumpElement ~= nil) then
                    return Icon._Proc(Weapon.JumpElement).." "..Shared.round(Weapon.JumpAttack, 2, 1)
                else
                    return Shared.round(Weapon.JumpAttack, 2, 1)
                end
            else
                return Weapon.JumpAttack
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "JUMPELEMENT") then
        if(Weapon.JumpElement ~= nil) then
            return Weapon.JumpElement
        elseif giveDefault then
            return ""
        else
            return nil
        end
    elseif(ValName == "JUMPRADIUS") then
        if(Weapon.JumpRadius ~= nil) then
            if(asString) then
                return Shared.round(Weapon.JumpRadius, 2, 1).." m"
            else
                return Weapon.JumpRadius
            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(" balle<s> par chargeur", Weapon.Magazine)
                end
            else
                return Weapon.Magazine
            end
        elseif giveDefault then
            if(asString) then
                return "0 balles par chargeur"
            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.Type == "Secondaire") then
                    returnVal = 210
                elseif(Weapon.Type == "Principale") then
                    if(Weapon.Class == nil or Weapon.Class == "Fusil") then
                        returnVal = 540
                    elseif(Weapon.Class == "Fusil à Pompe") then
                        returnVal = 120
                    elseif(Weapon.Class == "Arc" or Weapon.Class == "Fusil Sniper") then
                        returnVal = 72
                    end
                end
            end
        else
            return nil
        end
        if(asString) then
            if(returnVal > 0) then
                return returnVal.." munitions"
            else
                return nil
            end
        else
            if(returnVal > 0) then
                return returnVal
            else
                return nil
            end
        end
    elseif(ValName == "NOISELEVEL") then
        if(Weapon.NoiseLevel ~= nil) then
            return Weapon.NoiseLevel
        elseif giveDefault then
            if(Weapon.Type ~= nil and Weapon.Type ~= "Mêlée" and Weapon.Type ~= "Arch-Melee") then
                if(Weapon.Class ~= nil and (Weapon.Class == "Arc" or Weapon.Class == "Thrown")) then
                    return "Silencieux"
                else
                    return "Bruyant"
                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 "Aucune"
            else
                return {}
            end
        else
            return nil
        end
    elseif(ValName == "RELOAD") then
        if(Weapon.Reload ~= nil) then
            if(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 p. s."
                        if(Weapon.Magazine ~= nil) then
                            result=result.." ("..Shared.round(Weapon.Magazine / Weapon.Reload, 2, 1).."s total)" 
                            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.MeleeSlam ~= nil and Weapon.MeleeSlam.Damage ~= nil) then
            local slamDamage = Weapon.MeleeSlam.Damage
            if(asString) then
                if(Weapon.MeleeSlam.Element ~= nil) then
                    return Icon._Proc(Weapon.MeleeSlam.Element).." "..Shared.round(slamDamage, 2, 1)
                else
                    return Shared.round(slamDamage, 2, 1)
                end
            else
                return Weapon.MeleeSlam
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "SLAMELEMENT") then
        if(Weapon.MeleeSlam ~= nil and Weapon.MeleeSlam.Element ~= nil) then
            return Weapon.MeleeSlam.Element
        elseif giveDefault then
            return ""
        else
            return nil
        end
    elseif(ValName == "SLAMRADIALDMG") then
        if(Weapon.MeleeSlam ~= nil and Weapon.MeleeSlam.RadialDamage ~= nil) then
            local radialDamage = Weapon.MeleeSlam.RadialDamage
            if(asString) then
                local radialElement = Weapon.MeleeSlam.RadialElement
                if(radialElement ~= nil) then
                    return Icon._Proc(radialElement).." "..Shared.round(radialDamage, 2, 1)
                else
                    return Shared.round(radialDamage, 2, 1)
                end
            else
                return radialDamage
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "SLAMRADIALELEMENT") then
        if(Weapon.MeleeSlam ~= nil and Weapon.MeleeSlam.Element ~= nil) then
            return Weapon.MeleeSlam.Element
        elseif giveDefault then
            return ""
        else
            return nil
        end
    elseif(ValName == "SLAMRADIUS") then
        if(Weapon.MeleeSlam ~= nil and Weapon.MeleeSlam.Radius ~= nil) then
            local radius = Weapon.MeleeSlam.Radius
            if(asString) then
                return Shared.round(radius, 2, 1).." m"
            else
                return radius
            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.." tirs"
            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 "Aucune"
        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 == "Rafale") 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
        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
        end
        if(hasAttack(Weapon, "Secondaire") and returnVal ==0) then
            local secAtt = getAttack(Weapon, "Secondaire")
            if(secAtt.CritChance ~= nil) then
                returnVal=secAtt.CritChance
                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 == "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
        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
        end
        if(hasAttack(Weapon, "Secondaire") and returnVal ==0) then
            local secAtt = getAttack(Weapon, "Secondaire")
            if(secAtt.CritMultiplier ~= nil) then
                returnVal=secAtt.CritMultiplier
                Attack=secAtt
            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 ~= "Mêlée" 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(" balle<s>/s", 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, "Secondaire") and returnVal ==0) then
            local secAtt = getAttack(Weapon, "Secondaire")
            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 == "WALLATTACK") then
        if(Weapon.WallAttack ~= nil) then
            if(asString) then
                if(Weapon.WallElement ~= nil) then
                    return Icon._Proc(Weapon.WallElement).." "..Shared.round(Weapon.WallAttack, 2, 1)
                else
                    return Shared.round(Weapon.WallAttack, 2, 1)
                end
            else
                return Weapon.WallAttack
            end
        elseif giveDefault then
            return 0
        else
            return nil
        end
    elseif(ValName == "WALLELEMENT") then
        if(Weapon.WallElement ~= nil) then
            return Weapon.WallElement
        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

function p.getValue(frame)
    local WeapName = frame.args[1]
    local ValName1 = frame.args[2]
    local ValName2 = frame.args[3]
    local AsString = frame.args["Raw"] == nil
    if(WeapName == nil) then
        return ""
    elseif(ValName1 == nil) then
        return "ERREUR : Pas de valeur spécifiée"
    end
    
    local theWeap = p.getWeapon(WeapName)
    if(theWeap == nil) then
        return ""
    end
    
    local vName
    local useDefault
    if(ValName2 == nil or ValName2 == "") then
        vName = ValName1
        useDefault = Shared.contains(UseDefaultList, string.upper(ValName1))
    else
        vName = {ValName1, ValName2}
        useDefault = Shared.contains(UseDefaultList, string.upper(ValName2))
    end
    
    return getValue(theWeap, vName, useDefault, AsString)
end

function p.getConclaveValue(frame)
    local WeapName = frame.args[1]
    local ValName1 = frame.args[2]
    local ValName2 = frame.args[3]
    if(WeapName == nil) then
        return ""
    elseif(ValName1 == nil) then
        return "ERROR: No value selected"
    end
    
    local theWeap = p.getConclaveWeapon(WeapName)
    if(theWeap == nil) then
        return ""
    end
    
    local vName
    local useDefault
    if(ValName2 == nil or ValName2 == "") then
        vName = ValName1
        useDefault = Shared.contains(UseDefaultList, string.upper(ValName1))
    else
        vName = {ValName1, ValName2}
        useDefault = Shared.contains(UseDefaultList, string.upper(ValName2))
    end
    
    return getValue(theWeap, vName, useDefault, true)
end

local function buildInfoboxRow(Label, Text, Collapse, Digits, Addon)
    local result = ""
    
    if(Collapse == nil) then
        Collapse = false
    elseif(Collapse == 1) then
        Collapse = true
    end
    if(Text ~= nil) then
        result = '<div style="margin-left:-3px;" '
        if(Collapse) then
            result = result..'class="Infobox_Collapsible"'
        end
        result = result..'>'
        result = result..'\n{| style="width:100%;"'
        result = result..'\n|-'
        result = result..'\n| class="left" | <span style="white-space:nowrap;">'
            result = result.."'''"..Label.."'''"
        result = result..'</span>'
        result = result..'\n| class="right" | '
        if(Digits == nil) then
            result = result..Text
        else
            result = result..Shared.round(Text, Digits)
        end
        if(Addon ~= nil) then
            result = result..p.doPlural(Addon, Text)
        end
        result = result..'\n|}'
        result = result..'\n</div>'
    end
    return result
end

--Returns a list of weapons for a stance
--Adds a ✓ if the weapon matches the polarity
function p.getStanceWeaponList(frame)
    local StanceName = frame.args ~= nil and frame.args[1] or frame
    local Stance = p.getStance(StanceName)
    
    if(Stance == nil) then
        return "ERREUR : "..StanceName.." introuvable"
    end
    
    local weaps = getMeleeWeapons(Stance.Class, Stance.PvP)
    local result = ""
    
    for i, weap in Shared.skpairs(weaps) do
        if (string.len(result) > 0) then
            result = result.."\n"
        end
        
        if(Stance.PvP) then
            result = result.."*[[Conclave:"..weap.Name.."|"..weap.Name.."]]"
        else
            result = result.."*[["..weap.Name.."]]"
        end
        
        if(weap.StancePolarity == Stance.Polarity) then
            result = result.." ✓"
        end
    end
    
    return result
end

--Returns a list of stances for a weapon
--Adds the polarity for each stance
function p.getWeaponStanceList(frame)
    local WeaponName = frame.args ~= nil and frame.args[1] or frame
    local Weapon = getWeapon(WeaponName)
    
    if(Weapon == nil) then
        return "ERROR: "..WeaponName.." not found"
    end
    
    return getWeaponStanceList(Weapon)
end

function p.getStanceGallery(frame)
    local StanceType = frame.args ~= nil and frame.args[1] or frame
    local Stances = getStances(StanceType, true)
    local result = "==[[Posture|Mods de Posture]] pour "..StanceType.."=="
    result = result..'\n{| style="margin:auto;text-align:center;"'
    local nameRow = ''
    for i, Stance in pairs(Stances) do
        if((i - 1) % 4 == 0) then 
            result = result..nameRow..'\n|-' 
            nameRow = '\n|-'
        end
        local stanceImage = Mod._getValue(Stance.Name, "IMAGE")
        result = result..'\n| style="width:165px" |[[File:'..stanceImage..'|150px|link='..Stance.Name..']]'
        nameRow = nameRow..'\n| style="vertical-align: text-top;" |'..Mod._tooltipText(Stance.Name)
        if(Stance.PvP ~= nil and Stance.PvP) then
            nameRow = nameRow..'<br/>([[Conclave]] uniquement)'
        end
    end
    result = result..nameRow
    result = result..'\n|}'
    return result
end

local function getWeaponGallery(Weapons)
    local result = '{| style="margin:auto;text-align:center;"'
    local nameRow = ''
    for i, Weapon in pairs(Weapons) do
        local theImage = Weapon.Image ~= nil and Weapon.Image or "Panel.png"
        local weapLink = p._getLink(Weapon.Name)
        if((i - 1) % 4 == 0) then 
            result = result..nameRow..'\n|-' 
            nameRow = '\n|-'
        end
        result = result..'\n| style="width:165px" |[[File:'..theImage..'|150px|link='..Weapon.Name..']]'
        nameRow = nameRow..'\n| style="vertical-align: text-top;" |[['..weapLink..'|'..Weapon.Name..']]'
    end
    result = result..nameRow
    result = result..'\n|}'
    return result
end

function p.getMeleeWeaponGallery(frame)
    local Type = frame.args ~= nil and frame.args[1] or frame
    if(Type == nil) then
        return ""
    end
    local WeapArray = getMeleeWeapons(Type)
    local result = "==Armes de type "..Type.."==\n"
    result = result..getWeaponGallery(WeapArray)
    return result
end

function p.getWeaponCount(frame)
    local Type = frame.args ~= nil and frame.args[1] or frame
    local getFullList = frame.args ~= nil and frame.args[2]
    if getFullList == "nil" then --bleh, this lovely parsing of invokes..
        getFullList = nil
    end
    local getAll = frame.args ~= nil and frame.args[3]
    local count = 0
    local fullList = ""
    for i, val in Shared.skpairs(WeaponData["Weapons"]) do
        if(not Shared.contains(WeaponData["IgnoreInCount"], i) and getAll ~= "true") or getAll == "true" then
            if(Type == nil or Type == "") then
                count = count + 1
                if(getFullList ~= nil) then fullList = fullList..'\n# '..val.Name end
            elseif(Type == "Warframe") then
                if(val.Type == "Principale" or val.Type == "Secondaire" or val.Type == "Mêlée") then
                    count = count + 1
                    if(getFullList ~= nil) then fullList = fullList..'\n# '..val.Name end
                end
            elseif(Type == "Archwing") then
                if(val.Type == "Arch-Gun" or val.Type == "Arch-Melee") then
                    count = count + 1
                    if(getFullList ~= nil) then fullList = fullList..'\n# '..val.Name end
                end
            elseif(Type == "Rest") then
                if(val.Type ~= "Arch-Gun" and val.Type ~= "Arch-Melee" and val.Type ~= "Principale" and val.Type ~= "Secondaire" and val.Type ~= "Mêlée") then
                    count = count + 1
                    if(getFullList ~= nil) then fullList = fullList..'\n# '..val.Name end
                end
            else
                if(val.Type == Type) then
                    count = count + 1
                    if(getFullList ~= nil) then fullList = fullList..'\n# '..val.Name end
                end
            end
        end
    end
    if(getFullList ~= nil) then return fullList end
    return count
end

function getSecondaryCategory(weapon)
    local class = getValue(weapon, "Class", true)
    if(class == "Jet") then
        return "Jet"
    elseif(class == "Doubles Fusils à Pompe" or class == "Fusil à Pompe de poing") then
        return "Fusil à Pompe"
    else
        local trigger = getValue(weapon, "Trigger", true)
        if(trigger == "Semi-Auto" or trigger == "Rafale") then
            return "Semi-Auto"
        elseif(trigger == "Auto" or trigger == "Auto à Cadence Croissante") then
            return "Auto"
        end
    end
    return "Other"
end

function getPrimaryCategory(weapon)
    local class = getValue(weapon, "Class", true)
    if(class == "Fusil à Pompe") then
        return "Fusil à Pompe"
    elseif(class == "Arc") then
        return "Arc"
    elseif(class == "Fusil de Sniper") then
        return "Fusil de Sniper"
    elseif(class == "Fusil") then
        local trigger = getValue(weapon, "Trigger", true)
        if(trigger == "Semi-Auto" or trigger == "Rafale") then
            return "Semi-Auto"
        elseif(trigger == "Auto" or trigger == "Auto à Cadence Croissante") then
            return "Auto"
        end
    end
    return "Other"
end

function p.getPolarityTable()
    local tHeader = ""
    tHeader = tHeader..'\n{| style="width: 100%; border-collapse: collapse; cellpadding: 2" border="1"'
    tHeader = tHeader..'\n! colspan="2" |Armes Principale'
    tHeader = tHeader..'\n! colspan="2" |Armes Secondaire'
    tHeader = tHeader..'\n! colspan="2" |Armes Mêlée'
    local tRows = ""
    
    local Melees = p.getWeapons(function(x) return p.isMelee(x) and Shared.tableCount(getValue(x, "Polarities", true)) > 0 end)
    local Pistols = p.getWeapons(function(x) return x.Type == "Secondaire" and  Shared.tableCount(getValue(x, "Polarities", true)) > 0 end)
    local Primaries = p.getWeapons(function(x) return (x.Type == "Principale") and Shared.tableCount(getValue(x, "Polarities", true)) > 0 end)
    
    local ACount = Shared.tableCount(Melees)
    local maxLen = ACount
    local BCount = Shared.tableCount(Pistols)
    if(BCount > maxLen) then
        maxLen = BCount
    end
    local CCount = Shared.tableCount(Primaries)
    if(CCount > maxLen) then
        maxLen = CCount
    end
    
    for i=1, maxLen, 1 do
        tRows = tRows.."\n|-"
        if(i <= CCount) then
            tRows = tRows.."\n|[["..Primaries[i].Name.."]]||"..p.GetPolarityString(Primaries[i])
        else
            tRows = tRows.."\n| ||"
        end
        if(i <= BCount) then
            tRows = tRows.."\n|[["..Pistols[i].Name.."]]||"..p.GetPolarityString(Pistols[i])
        else
            tRows = tRows.."\n| ||"
        end
        if(i <= ACount) then
            tRows = tRows.."\n|[["..Melees[i].Name.."]]||"..p.GetPolarityString(Melees[i])
        else
            tRows = tRows.."\n| ||"
        end
    end
    
    return tHeader..tRows.."\n|}"
end

function buildCompareString(Val1, Val2, ValName, Digits, Addon, Words, Start, Middle)
    if(Val1 == nil or Val2 == nil) then
        return ""
    end
    local V1Str = Val1
    local V2Str = Val2
    if(Digits ~= nil) then
        local didWork, rowStr = pcall(Shared.round, Val1, Digits)
        if(didWork) then
            V1Str = rowStr
            local didWork, rowStr = pcall(Shared.round, Val2, Digits)
            if(didWork) then
                V2Str = rowStr
            else
                mw.log("Failed to round "..Val2)
            end
        else
            mw.log("Failed to round "..Val1)
        end
    end
    if(Addon ~= nil) then
        V1Str = V1Str..p.doPlural(Addon, Val1)
        V2Str = V2Str..p.doPlural(Addon, Val2)
    end
    local bigWord = Words ~= nil and Words[1] or "Plus de"
    local smallWord = Words ~= nil and Words[2] or "Moins de"
    local start = Start ~= nil and Start or "\n**"
    local bigMiddle = Middle ~= nil and Middle[1] or ""
    local smallMiddle = Middle ~= nil and Middle[2] or ""
    
    if(Val1 > Val2) then
        return start.." "..bigWord.." "..ValName.." "..bigMiddle.." ("..V1Str.." vs. "..V2Str..")"
    elseif(Val2 > Val1) then
        return start.." "..smallWord.." "..ValName.." "..smallMiddle.." ("..V1Str.." vs. "..V2Str..")"
    else
        return ""
    end
end

function buildGunComparisonString(Weapon1, Weapon2, Conclave)
    local result = ""
    if(Conclave) then
        result = "* "..Weapon1.Name..", comparé au [[Conclave:"..Weapon2.Name.."|"..Weapon2.Name.."]]:"
    else
        result = "* "..Weapon1.Name..", comparé au [["..Weapon2.Name.."]]:"
    end
    
    if(hasAttack(Weapon1, "Normal") and hasAttack(Weapon2, "Normal")) then
        local Att1 = getAttack(Weapon1, "Normal")
        local Att2 = getAttack(Weapon2, "Normal")
        local dmgString = ""
        dmgString = dmgString..buildCompareString(GetDamage(Att1), GetDamage(Att2), "dégâts de base", {2, 1})
        dmgString = dmgString..buildCompareString(Att1.Damage["Impact"], Att2.Damage["Impact"], " dégâts "..Icon._Proc("Impact", "text"), {2, 1}, nil, {"Plus de", "Moins de"}, "\n***")
        dmgString = dmgString..buildCompareString(Att1.Damage["Perforation"], Att2.Damage["Perforation"], " dégâts "..Icon._Proc("Perforation", "text"), {2, 1}, nil, {"Plus de", "Moins de"}, "\n***")
        dmgString = dmgString..buildCompareString(Att1.Damage["Tranchant"], Att2.Damage["Tranchant"], " dégâts "..Icon._Proc("Tranchant", "text"), {2, 1}, nil, {"Plus de", "Moins de"}, "\n***")
        if(string.len(dmgString) > 0 and GetDamage(Att1) == GetDamage(Att2)) then
            dmgString = "\n**Dégâts de base équivalent, mais composition différente:"..dmgString    
        end
        result = result..dmgString
    end
    if(hasAttack(Weapon1, "Charge")and hasAttack(Weapon2, "Charge")) then
        local Att1 = getAttack(Weapon1, "Charge")
        local Att2 = getAttack(Weapon2, "Charge")
--        local addedString = ""
--        if(dontHasAttack(Weapon1, "Normal")and dontHasAttack(Weapon2, "Normal")) then        
--            addedString = "charged test"
--        end
        if(Att1.CritChance ~= nil and Att2.CritChance ~= nil) then
            if(dontHasAttack(Weapon1, "Normal")and dontHasAttack(Weapon2, "Normal")) then        
                result = result..buildCompareString((Att1.CritChance * 100), (Att2.CritChance * 100), "[[Chance de Coup Critique]]", 2, "%")
            end
            if(hasAttack(Weapon1, "Normal")and hasAttack(Weapon2, "Normal")) then        
                result = result..buildCompareString((Att1.CritChance * 100), (Att2.CritChance * 100), "[[Chance de Coup Critique]] avec un tir chargé", 2, "%")
            end
        end
        if(dontHasAttack(Weapon1, "Normal")and dontHasAttack(Weapon2, "Normal")) then        
            result = result..buildCompareString(Att1.CritMultiplier, Att2.CritMultiplier, "[[Multiplicateur de Critique]]", 2, "x")
        end
        if(hasAttack(Weapon1, "Normal")and hasAttack(Weapon2, "Normal")) then    
            result = result..buildCompareString(Att1.CritMultiplier, Att2.CritMultiplier, "[[Multiplicateur de Critique]] avec un tir chargé", 2, "x")
        end
        if(Att1.StatusChance ~= nil and Att2.StatusChance ~= nil) then
            if(dontHasAttack(Weapon1, "Normal")and dontHasAttack(Weapon2, "Normal")) then        
                result = result..buildCompareString((Att1.StatusChance * 100), (Att2.StatusChance * 
                100), "[[Chance de Statut]]", 2, "%")
            end
            if(hasAttack(Weapon1, "Normal")and hasAttack(Weapon2, "Normal")) then        
                result = result..buildCompareString((Att1.StatusChance * 100), (Att2.StatusChance * 
                100), "[[Chance de Statut]] avec un tir chargé", 2, "%")
            end
        end
        if(dontHasAttack(Weapon1, "Normal")and dontHasAttack(Weapon2, "Normal")) then        
            result = result..buildCompareString(GetDamage(Weapon1.ChargeAttack), GetDamage(Weapon2.ChargeAttack), "dégâts", {2, 1})
        end
        if(hasAttack(Weapon1, "Normal")and hasAttack(Weapon2, "Normal")) then        
            result = result..buildCompareString(GetDamage(Weapon1.ChargeAttack), GetDamage(Weapon2.ChargeAttack), "dégâts avec un tir chargé", {2, 1})
        end
        result = result..buildCompareString(getValue(Weapon1, {"Charge", "ChargeTime"}), getValue(Weapon2, {"Charge", "ChargeTime"}), "Temps de charge", {2, 1}, " s", {"",""}, nil, {"plus lent", "plus rapide"})
    end
    if(hasAttack(Weapon1, "Area") and hasAttack(Weapon2, "Area")) then
        result = result..buildCompareString(GetDamage(Weapon1.AreaAttack), GetDamage(Weapon2.AreaAttack), "dégâts de zone", {2, 1})
    end
    if(hasAttack(Weapon1, "Secondary") and hasAttack(Weapon2, "Secondary")) then
        result = result..buildCompareString(GetDamage(Weapon1.SecondaryAttack), GetDamage(Weapon2.SecondaryAttack), "secondary attack damage", {2, 1})
    --test code to fix stradavar wrong comparison
        local Att1 = getAttack(Weapon1, "Secondary")
        local Att2 = getAttack(Weapon2, "Secondary")
        if(Att1.CritChance ~= nil and Att2.CritChance ~= nil) then
            result = result..buildCompareString((Att1.CritChance * 100), (Att2.CritChance * 100), "secondary mode [[Chance de Coup Critique]]", 2, "%")
        end
            result = result..buildCompareString(Att1.CritMultiplier, Att2.CritMultiplier, "secondary mode [[Multiplicateur de Critique]]", 2, "x")
        if(Att1.StatusChance ~= nil and Att2.StatusChance ~= nil) then
            result = result..buildCompareString((Att1.StatusChance * 100), (Att2.StatusChance * 100), "secondary mode [[Chance de Statut]]", 2, "%")
        end
        result = result..buildCompareString(Att1.FireRate, Att2.FireRate, "secondary mode [[Cadence de Tir]]", 2, " balle<s>/s")
    --end of test code
    end

--test code to fix tiberon prime comparison

    if((hasAttack(Weapon1, "Normal") and hasAttack(Weapon2, "Secondary") and dontHasAttack(Weapon1, "Secondary")) or (hasAttack(Weapon1, "Secondary") and hasAttack(Weapon2, "Normal") and dontHasAttack(Weapon2, "Secondary")))then
        local Att1 = getAttack(Weapon1, "Normal")
        local Att2 = getAttack(Weapon2, "Normal")
        if(Att1.CritChance ~= nil and Att2.CritChance ~= nil) then
            result = result..buildCompareString((Att1.CritChance * 100), (Att2.CritChance * 100), "[[Chance de Coup Critique]]", 2, "%")
        end   
        result = result..buildCompareString(Att1.CritMultiplier, Att2.CritMultiplier, "[[Multiplicateur de Critique]]", 2, "x")

        if(Att1.StatusChance ~= nil and Att2.StatusChance ~= nil) then
            result = result..buildCompareString((Att1.StatusChance * 100), (Att2.StatusChance * 100), "[[Chance de Statut]]", 2, "%")
        end
    end
  

    
--end of test code to fix tiberon prime comparison
    
    if(hasAttack(Weapon1, "Normal") and hasAttack(Weapon2, "Normal") ) then
        local Att1 = getAttack(Weapon1, "Normal")
        local Att2 = getAttack(Weapon2, "Normal")
        if(Att1.CritChance ~= nil and Att2.CritChance ~= nil) then
            if(dontHasAttack(Weapon1, "Charge")and dontHasAttack(Weapon2, "Charge") and dontHasAttack(Weapon1, "Secondary")and dontHasAttack(Weapon2, "Secondary")) then        
                result = result..buildCompareString((Att1.CritChance * 100), (Att2.CritChance * 100), "[[Chance de Coup Critique]]", 2, "%")
            end
            if(hasAttack(Weapon1, "Charge")and hasAttack(Weapon2, "Charge")) then        
                result = result..buildCompareString((Att1.CritChance * 100), (Att2.CritChance * 100), "base [[Chance de Coup Critique]]", 2, "%")
            end
            if(hasAttack(Weapon1, "Secondary")and hasAttack(Weapon2, "Secondary")) then        
                result = result..buildCompareString((Att1.CritChance * 100), (Att2.CritChance * 100), "primary [[Chance de Coup Critique]]", 2, "%")
            end
        end
        if(dontHasAttack(Weapon1, "Charge")and dontHasAttack(Weapon2, "Charge") and dontHasAttack(Weapon1, "Secondary")and dontHasAttack(Weapon2, "Secondary")) then        
            result = result..buildCompareString(Att1.CritMultiplier, Att2.CritMultiplier, "[[Multiplicateur de Critique]]", 2, "x")
        end
        if(hasAttack(Weapon1, "Charge")and hasAttack(Weapon2, "Charge")) then        
            result = result..buildCompareString(Att1.CritMultiplier, Att2.CritMultiplier, "base [[Multiplicateur de Critique]]", 2, "x")
        end
        if(hasAttack(Weapon1, "Secondary")and hasAttack(Weapon2, "Secondary")) then        
            result = result..buildCompareString(Att1.CritMultiplier, Att2.CritMultiplier, "primary [[Multiplicateur de Critique]]", 2, "x")
        end
        if(Att1.StatusChance ~= nil and Att2.StatusChance ~= nil) then
           if(dontHasAttack(Weapon1, "Charge")and dontHasAttack(Weapon2, "Charge") and dontHasAttack(Weapon1, "Secondary")and dontHasAttack(Weapon2, "Secondary")) then        
                result = result..buildCompareString((Att1.StatusChance * 100), (Att2.StatusChance * 100), "[[Chance de Statut]]", 2, "%")
            end
            if(hasAttack(Weapon1, "Charge")and hasAttack(Weapon2, "Charge")) then        
                result = result..buildCompareString((Att1.StatusChance * 100), (Att2.StatusChance * 100), "base [[Chance de Statut]]", 2, "%")
            end
            if(hasAttack(Weapon1, "Secondary")and hasAttack(Weapon2, "Secondary")) then        
                result = result..buildCompareString((Att1.StatusChance * 100), (Att2.StatusChance * 100), "primary [[Chance de Statut]]", 2, "%")
            end
        end
        result = result..buildCompareString(Att1.FireRate, Att2.FireRate, "[[Cadence de Tir]]", 2, " balle<s>/s")
        
        --Handling Damage Falloff        
        if(Att1.Falloff ~= nil and Att2.Falloff == nil) then
            result = result.."\n** "..Att1.Falloff.StartRange.."m - "..Att1.Falloff.EndRange.."m dégradation dégâts"
            if(Att1.Falloff.Reduction ~= nil) then
               result = result.." avec jusqu'à "..(Att1.Falloff.Reduction * 100).."% réduction dégâts"
            end
        elseif(Att2.Falloff ~= nil and Att1.Falloff == nil) then
            result = result.."\n** No "..Att2.Falloff.StartRange.."m - "..Att2.Falloff.EndRange.."m damage falloff"
            if(Att2.Falloff.Reduction ~= nil) then
                result = result.." with up to "..(Att2.Falloff.Reduction * 100).."% réduction dégâts"
            end
        elseif(Att1.Falloff ~= nil and Att2.Falloff ~= nil) then
            result = result..buildCompareString(Att1.Falloff.StartRange, Att2.Falloff.StartRange, "range before damage falloff starts", 2, "m", {"Longer", "Shorter"})
            result = result..buildCompareString(Att1.Falloff.EndRange, Att2.Falloff.EndRange, "range before damage falloff ends", 2, "m", {"Longer", "Shorter"})
            if(Att1.Falloff.Reduction ~= nil and Att2.Falloff.Reduction ~= nil) then
                result = result..buildCompareString(Att1.Falloff.Reduction * 100, Att2.Falloff.Reduction * 100, "max damage reduction due to falloff", 2, "%", {"Plus grand", "Plus petit"})
            end
        end
    end
    
    result = result..buildCompareString(Weapon1.Magazine, Weapon2.Magazine, "chargeur", 0, " balle<s>", {"Plus gros", "Plus petit"})
    result = result..buildCompareString(Weapon1.MaxAmmo, Weapon2.MaxAmmo, "Réserve de munition", 0, " balle<s>", {"", ""}, nil, {"plus grande", "plus petite"})
    --If this is a weapon that regenerates ammo, flip the comparison
    if (Weapon1.ReloadStyle ~= nil and Weapon1.ReloadStyle == "Regenerate") then
        result = result..buildCompareString(Weapon1.Reload, Weapon2.Reload, "[[Rechargement]]", 2, " balle<s>/s", {"", ""}, nil, {"plus lent", "plus rapide"})
    else
        result = result..buildCompareString(Weapon1.Reload, Weapon2.Reload, "[[Rechargement]]", 2, " s", {"", ""}, nil, {"plus lent", "plus rapide"})
    end
    result = result..buildCompareString(Weapon1.Spool, Weapon2.Spool, "spool-up", 0, " balle<s>", {"Slower", "Faster"})
    local Acc1 = getValue(Weapon1, "Accuracy")
    local Acc2 = getValue(Weapon2, "Accuracy")
    if(type(Acc1) == "number" and type(Acc2) == "number") then
        result = result..buildCompareString(Acc1, Acc2, "[[Précision]]", 0, nil, {"Meilleure", "Moins bonne"})
    end
        
    --Handling Syndicate radial effects
    if(Weapon1.SyndicateEffect ~= nil and Weapon2.SyndicateEffect == nil) then
        result = result.."\n** Innate [["..Weapon1.SyndicateEffect.."]] effect"
    elseif(Weapon2.SyndicateEffect ~= nil and Weapon1.SyndicateEffect == nil) then
        result = result.."\n** Lack of an innate [["..Weapon2.SyndicateEffect.."]] effect"
    elseif(Weapon1.SyndicateEffect ~= nil and Weapon2.SyndicateEffect ~= nil and Weapon1.SyndicateEffect ~= Weapon2.SyndicateEffect2) then
        result = result.."\n** Different innate [[Syndicate Radial Effects|Syndicate Effect]]: [["..Weapon1.SyndicateEffect.."]] vs. [["..Weapon2.SyndicateEffect.."]]"
    end
    
    --Handling Polarities
    local Pol1 = Weapon1.Polarities ~= nil and Weapon1.Polarities or {}
    local Pol2 = Weapon2.Polarities ~= nil and Weapon2.Polarities or {}
    local count1 = Shared.tableCount(Pol1)
    local count2 = Shared.tableCount(Pol2)
    local isDifferent = count1 ~= count2
    if(not isDifferent and count1 > 0) then
        table.sort(Pol1, function(x, y) return x < y end)
        table.sort(Pol2, function(x, y) return x < y end)
        for i, pol in pairs(Pol1) do
            if(pol ~= Pol2[i]) then
                isDifferent = true
            end
        end
    end
    
    if(isDifferent) then
        result = result.."\n** Différentes polarités ("..p.GetPolarityString(Weapon1).." vs. "..p.GetPolarityString(Weapon2)..")"
    end
    
    result = result..buildCompareString(Weapon1.Mastery, Weapon2.Mastery, "[[Rang de Maîtrise]] requis", 0, nil, {"", ""}, nil, {"supérieur", "inférieur"})
    return result
end

function buildMeleeComparisonString(Weapon1, Weapon2, Conclave)
    local result = ""
    if(Conclave) then
        result = "* "..Weapon1.Name..", comparé au [[Conclave:"..Weapon2.Name.."|"..Weapon2.Name.."]]:"
    else
        result = "* "..Weapon1.Name..", comparé au [["..Weapon2.Name.."]]:"
    end
    
    local dmgString = ""
    local Att1 = getAttack(Weapon1, "Normal")
    local Att2 = getAttack(Weapon2, "Normal")
    dmgString = dmgString..buildCompareString(GetDamage(Att1), GetDamage(Att2), "dégâts de base", {2, 1})
    dmgString = dmgString..buildCompareString(Att1.Damage["Impact"], Att2.Damage["Impact"], " dégâts "..Icon._Proc("Impact", "text"), {2, 1}, nil, {"Plus de", "Moins de"}, "\n***")
    dmgString = dmgString..buildCompareString(Att1.Damage["Perforation"], Att2.Damage["Perforation"], " dégâts "..Icon._Proc("Perforation", "text"), {2, 1}, nil, {"Plus de", "Moins de"}, "\n***")
    dmgString = dmgString..buildCompareString(Att1.Damage["Tranchant"], Att2.Damage["Tranchant"], " dégâts "..Icon._Proc("Tranchant", "text"), {2, 1}, nil, {"Plus de", "Moins de"}, "\n***")
    if(string.len(dmgString) > 0 and GetDamage(Att1) == GetDamage(Att2)) then
        dmgString = "\n**Dégâts de base équivalent, mais composition différente:"..dmgString    
    end
    result = result..dmgString
    
    
    if(Att1.CritChance ~= nil and Att2.CritChance ~= nil) then
        result = result..buildCompareString((Att1.CritChance * 100), (Att2.CritChance * 100), "[[Chance de Coup Critique]]", 2, "%")
    end
    result = result..buildCompareString(Att1.CritMultiplier, Att2.CritMultiplier, "[[Multiplicateur de Critique]]", {2, 1}, "x")
    
    if(Att1.StatusChance ~= nil and Att2.StatusChance ~= nil) then
        result = result..buildCompareString((Att1.StatusChance * 100), (Att2.StatusChance * 100), "[[Chance de Statut]]", 2, "%")
    end
    result = result..buildCompareString(Att1.FireRate, Att2.FireRate, "[[Vitesse d'Attaque]]", 2)
    result = result..buildCompareString(Icon._Pol(Weapon1.StancePolarity), Icon._Pol(Weapon2.StancePolarity), "polarité de [[Posture]]", nil, nil, {"Différente", "Différente"})
    result = result..buildCompareString(getValue(Weapon1, "ChannelMult", true), getValue(Weapon2, "ChannelMult", true), "Multiplicateur de Canalisation", 1, "x")
    
    --Handling Polarities
    local Pol1 = Weapon1.Polarities ~= nil and Weapon1.Polarities or {}
    local Pol2 = Weapon2.Polarities ~= nil and Weapon2.Polarities or {}
    local count1 = Shared.tableCount(Pol1)
    local count2 = Shared.tableCount(Pol2)
    local isDifferent = count1 ~= count2
    if(not isDifferent and count1 > 0) then
        table.sort(Pol1, function(x, y) return x < y end)
        table.sort(Pol2, function(x, y) return x < y end)
        for i, pol in pairs(Pol1) do
            if(pol ~= Pol2[i]) then
                isDifferent = true
            end
        end
    end
    
    if(isDifferent) then
        result = result.."\n** Polarités différentes ("..p.GetPolarityString(Weapon1).." vs. "..p.GetPolarityString(Weapon2)..")"
    end
    
    result = result..buildCompareString(Weapon1.Mastery, Weapon2.Mastery, "[[Rang de Maîtrise]] requis", 0)
    return result
end

function p.buildComparison(frame)
    local WeapName1 = frame.args[1]
    local WeapName2 = frame.args[2]
    
    if(WeapName1 == nil or WeapName2 == nil) then
        return '<span style="color:red">ERROR: Must compare two weapons</span>'
    end
    
    local Weapon1 = p.getWeapon(WeapName1)
    if(Weapon1 == nil) then
        return '<span style="color:red">ERROR: Could not find '..WeapName1..'</span>'
    end
    local Weapon2 = p.getWeapon(WeapName2)
    if(Weapon2 == nil) then
        return '<span style="color:red">ERROR: Could not find '..WeapName2..'</span>'
    end
    
    if(p.isMelee(Weapon1)) then
        return buildMeleeComparisonString(Weapon1, Weapon2)--.."[[Category:Automatic Comparison]]"
    else
        return buildGunComparisonString(Weapon1, Weapon2)--.."[[Category:Automatic Comparison]]"
    end
end

function p.buildConclaveComparison(frame)
    local WeapName1 = frame.args[1]
    local WeapName2 = frame.args[2]
    
    if(WeapName1 == nil or WeapName2 == nil) then
        return '<span style="color:red">ERROR: Must compare two weapons</span>'
    end
    
    local Weapon1 = p.getConclaveWeapon(WeapName1)
    if(Weapon1 == nil) then
        return '<span style="color:red">ERROR: Could not find '..WeapName1..'</span>'
    end
    local Weapon2 = p.getConclaveWeapon(WeapName2)
    if(Weapon2 == nil) then
        return '<span style="color:red">ERROR: Could not find '..WeapName2..'</span>'
    end
    
    if(p.isMelee(Weapon1)) then
        return buildMeleeComparisonString(Weapon1, Weapon2, true)--.."[[Category:Automatic Comparison]]"
    else
        return buildGunComparisonString(Weapon1, Weapon2, true)--.."[[Category:Automatic Comparison]]"
    end
end

function p.buildFamilyComparison(frame)
    local WeapName = frame.args ~= nil and frame.args[1] or frame
    if(WeapName == nil) then
        return '<span style="color:red">ERROR: Must provide a Weapon name</span>'
    end
    
    local Weapon = p.getWeapon(WeapName)
    if(Weapon == nil) then
        return '<span style="color:red">ERROR: Could not find '..WeapName1..'</span>'
    end
    if(Weapon.Family == nil) then
        return '<span style="color:red">ERROR: '..WeapName..' doesn\'t have a family</span>'
    end
    
    local relatives = getFamily(Weapon.Family)
    local result = {}
    for i, NewWeapon in pairs(relatives) do
        if(WeapName ~= NewWeapon.Name) then
            if(p.isMelee(NewWeapon)) then
                table.insert(result, buildMeleeComparisonString(Weapon, NewWeapon))
            else
                table.insert(result, buildGunComparisonString(Weapon, NewWeapon))
            end
        end
    end
    return table.concat(result, "\n")
end

function p.buildAutoboxCategories(frame)
    local WeapName = frame.args ~= nil and frame.args[1] or frame
    local Weapon = p.getWeapon(WeapName)
    local result = "[[Category:Armes]]"
    if(Weapon == nil) then
        return ""
    elseif(Weapon.IgnoreCategories ~= nil and Weapon.IgnoreCategories) then
        return ""
    end
    if(Weapon.Type ~= nil) then
        if(Weapon.Type == "Arch-Mêlée") then
            result = result.."[[Category:Arch-Mêlée]]"
        elseif(Weapon.Type == "Arch-Fusil" or Weapon.Type == "Arch-Fusil (Atmosphère)") then
            result = result.."[[Category:Arch-Fusil]]"
        elseif(Weapon.Type == "Arch-Fusil (Atmosphere)") then
            result = result
        elseif(Weapon.Type == "Mêlée") then
            result = result.."[[Category:Arme de Mêlée]]"
        elseif(Weapon.Type == "Amplificateur") then
            result = result
        else
            result = result.."[[Category: Arme "..Weapon.Type.."]]"
        end
    end
    if(Weapon.Class ~= nil) then
        result = result.."[[Category:"..Weapon.Class.."]]"
    end
    
    local augments = getAugments(Weapon)
    if(Shared.tableCount(augments) > 0) then
        result = result.."[[Category:Arme d'Augment]]"
    end
    
    if(HasTrait(Weapon, "Prime")) then
        result = result.."[[Category:Prime]]"
        if(HasTrait(Weapon, "Never Vaulted")) then
            result = result.."[[Category:Never Vaulted]]"
        elseif(HasTrait(Weapon, "Vaulted")) then
            result = result.."[[Category:Vaulted]]"
        end
    end

    if(HasTrait(Weapon, "Grineer")) then
        result = result.."[[Category:Armes Grineer]]"
    elseif(HasTrait(Weapon, "Corpus")) then
        result = result.."[[Category:Armes Corpus]]"
    elseif(HasTrait(Weapon, "Infesté")) then
        result = result.."[[Category:Armes Infesté]]"
    elseif(HasTrait(Weapon, "Tenno")) then
        result = result.."[[Category:Armes Tenno]]"
    end

    local attack = nil
    if(hasAttack(Weapon, "Normal")) then
        attack = getAttack(Weapon, "Normal")
    elseif(hasAttack(Weapon, "Charge")) then
        attack = getAttack(Weapon, "Charge")
    end
    if(attack ~= nil) then
        local bestPercent, bestElement = GetDamageBias(attack)
        if(bestElement == "Impact" or bestElement == "Perforation" or bestElement == "Tranchant") then
            if(bestPercent > .38) then
                result = result.."[[Category:Arme de Type "..bestElement.."]]"
            else
                result = result.."[[Category:Arme de Type Equilibré]]"
            end
        end
        
        for key, value in Shared.skpairs(attack.Damage) do
            if(key ~= "Impact" and key ~= "Perforation" and key ~= "Tranchant") then
                result = result.."[[Category:Arme de Type "..key.."]]"
            end
        end
    end
    
    if(hasAttack(Weapon, "Secondaire")) then
        result = result.."[[Category:Weapons with Alt Fire]]"
    end
    
    return result
end

function p.buildAugmentTable(frame)
    local result = ""
    result = result..'\n{|class="listtable sortable" style="width:100%;"'
    result = result..'\n|-'
    result = result..'\n! Nom'
    result = result..'\n! Catégorie'
    result = result..'\n! Source'
    result = result..'\n! Arme'
    
    for i, Augment in pairs(WeaponData["Augments"]) do
        local thisStr = "\n|-"
        thisStr = thisStr.."\n| <span class=\"mod-tooltip\" data-param=\""..Augment.Name.."\" style=\"white-space:pre\">[["..Augment.Name.."]]</span>" --span class = displays the mod tooltip in the table on hover.
        thisStr = thisStr.."\n| "..Augment.Category
        thisStr = thisStr.."\n| [["..Augment.Source.."]]"
        thisStr = thisStr.."\n| "
        for i, weap in pairs(Augment.Weapons) do
            if(i>1) then thisStr = thisStr.."<br/>" end
            thisStr = thisStr.."[["..weap.."]]"
        end
        result = result..thisStr
    end
    
    result = result..'\n|}'
    return result 
end

function noNil(val, default)
    if(val ~= nil) then
        return val
    else
        if(default ~= nil) then
            return default
        else
            return ""
        end
    end
end

function p.buildDamageTypeTable(frame)
    local DamageType = frame.args ~= nil and frame.args[1] or frame
    local Weapons = {}
    local WeapArray = p.getWeapons(function(x) 
                                    local Dmg, Element 
                                    if (hasAttack(x, "Normal")) then
                                        Dmg, Element = GetDamageBias(getAttack(x, "Normal"), true)
                                    elseif(hasAttack(x, "Charge")) then
                                        Dmg, Element = GetDamageBias(getAttack(x, "Charge"), true)
                                    else
                                        return false
                                    end
                                    return Element == DamageType end)
                              
    local procString = Icon._Proc(DamageType,'text')
    local procShort = Icon._Proc(DamageType)
    local result = ""
    local tHeader = '{|class = "listtable sortable" style="margin:auto;"'
    tHeader = tHeader..'\n|-'
    tHeader = tHeader..'\n!Name'
    tHeader = tHeader..'\n!Type'
    tHeader = tHeader..'\n!Class'
    tHeader = tHeader..'\n!'..procString
    tHeader = tHeader..'\n!'..procShort..'%'
    local tRows = ""
    for i, Weapon in pairs(WeapArray) do
        local thisRow = '\n|-\n|'
        thisRow = thisRow.."|[["..Weapon.Name.."]]||"..Weapon.Type.."|| "..getValue(Weapon, "Class", true, true)
        if(hasAttack(Weapon, "Normal")) then
            local tempBias = getValue(Weapon, {"Normal", "DamageBias"}, true)
            local tempBiasStripped = string.match(tempBias,"(%d*)%%")
            thisRow = thisRow.."||"..getValue(Weapon, {"Normal", DamageType}).."||".."data-sort-value="..tempBiasStripped.."|"..tempBias
        elseif(hasAttack(Weapon, "Charge")) then
            local tempBias = getValue(Weapon, {"Charge", "DamageBias"}, true)
            local tempBiasStripped = string.match(tempBias,"(%d*)%%")
            thisRow = thisRow.."||"..getValue(Weapon, {"Charge", DamageType}).."||".."data-sort-value="..tempBiasStripped.."|"..tempBias
        end
        
        tRows = tRows..thisRow
    end
    result = tHeader..tRows.."\n|}"
    return result
end

function p.buildWeaponByMasteryRank(frame)
    local MasteryRank
    local MRTable = {}
    for i, Weapon in Shared.skpairs(WeaponData["Weapons"]) do
        if(Weapon.Mastery ~= nil) then
            if(MRTable[Weapon.Mastery] == nil) then
                MRTable[Weapon.Mastery] = {}
            end
            if(MRTable[Weapon.Mastery][Weapon.Type] == nil) then
                MRTable[Weapon.Mastery][Weapon.Type] = {}
            end
            table.insert(MRTable[Weapon.Mastery][Weapon.Type], Weapon)
        end
    end
    local result = ""
    for i, TypeTable in Shared.skpairs(MRTable) do
        local thisTable = "\n==Mastery Rank "..i.." Required=="
        if(i == 0) then
            thisTable = "==No Mastery Rank Required=="
        end
        thisTable = thisTable..'\n{| style="width:80%;margin:auto"'
        thisTable = thisTable..'\n|-\n| style="vertical-align:top;width:33%;" |'
        if(TypeTable["Primary"] ~= nil and Shared.tableCount(TypeTable["Primary"]) > 0) then
            thisTable = thisTable.."\n===Primary==="
            local tempList = p.shortLinkList(TypeTable["Primary"])
            for i, text in pairs(tempList) do
                thisTable = thisTable.."\n* "..text
            end
        end
        
        thisTable = thisTable..'\n| style="vertical-align:top;width:33%;" |'
        if(TypeTable["Secondary"] ~= nil and Shared.tableCount(TypeTable["Secondary"]) > 0) then
            thisTable = thisTable.."\n===Secondary==="
            local tempList = p.shortLinkList(TypeTable["Secondary"])
            for i, text in pairs(tempList) do
                thisTable = thisTable.."\n* "..text
            end
        end
        
        thisTable = thisTable..'\n| style="vertical-align:top;width:33%;" |'
        if(TypeTable["Mêlée"] ~= nil and Shared.tableCount(TypeTable["Mêlée"]) > 0) then
            thisTable = thisTable.."\n===Melee==="
            local tempList = p.shortLinkList(TypeTable["Mêlée"])
            for i, text in pairs(tempList) do
                thisTable = thisTable.."\n* "..text
            end
        end
        thisTable = thisTable.."\n|}"
        result = result..thisTable
    end
    return result
end

function p.getMasteryShortList(frame)
    local WeaponType = frame.args[1]
    local MasteryRank = tonumber(frame.args[2])
        
    local weapArray = p.getWeapons(function(x) 
                                    if(x.Type ~= nil and x.Mastery ~= nil) then
                                        return x.Type == WeaponType and x.Mastery == MasteryRank
                                    else
                                        return false
                                    end
                                end)
    
    local result = ""
    local shortList = p.shortLinkList(weapArray)
    for i, pair in Shared.skpairs(shortList) do
        if(string.len(result) > 0) then result = result.." • " end
        result = result..pair
    end
    return result
end

function p.getRivenDispositionList(frame)
    local WeaponType = frame.args[1]
    local Disposition = tonumber(frame.args[2])
        
    local weapArray = p.getWeapons(function(x) 
        if(x.Type ~= nil and x.Disposition ~= nil) then
            return (string.upper(WeaponType) == "ALL" or x.Type == WeaponType) and x.Disposition == Disposition
        else
            return false
        end
    end)
    
    local result = ""
    local shortList = p.shortLinkList(weapArray)
    for i, pair in Shared.skpairs(shortList) do
        result = result..'\n* '..pair
    end
    return result
end

function p.getRivenDispositionTable(frame)
    local WeaponType = frame.args[1]
        
    local result = '{| class="article-table" border="0" cellpadding="1" cellspacing="1" style="width: 100%"'
    result = result..'\n|-'
    for i = 5, 1, -1 do
        if      (i == 5) then j = 1.5
        elseif  (i == 4) then j = 1.3
        elseif  (i == 3) then j = 1.1
        elseif  (i == 2) then j = 0.89
        else                  j = 0.69 end
        result = result..'\n! scope="col" style="text-align:center;"|'..Icon._Dis(j)
    end
    result = result..'\n|-'
    for i = 5, 1, -1 do
        result = result..'\n| style="vertical-align:top" |'
        if      (i == 5) then
            for j = 1550, 1301, -1 do
                result = result..p.getRivenDispositionList({args = {WeaponType, j/1000}}) end
        elseif  (i == 4) then
            for j = 1300, 1101, -1 do
                result = result..p.getRivenDispositionList({args = {WeaponType, j/1000}}) end
        elseif  (i == 3) then
            for j = 1100, 900, -1 do
                result = result..p.getRivenDispositionList({args = {WeaponType, j/1000}}) end
        elseif  (i == 2) then
            for j = 899, 700, -1 do
                result = result..p.getRivenDispositionList({args = {WeaponType, j/1000}}) end
        else
            for j = 699, 500, -1 do
                result = result..p.getRivenDispositionList({args = {WeaponType, j/1000}}) end
        end
    end
    result = result..'\n|}'
    
    return result
end

function p.getConclaveList(frame)
    local WeaponType = frame.args[1]
        
    local weapArray = p.getWeapons(function(x) 
                                    if(x.Type ~= nil and x.Conclave ~= nil) then
                                        return x.Type == WeaponType and x.Conclave
                                    else
                                        return false
                                    end
                                end)
    
    local result = ""
    local shortList = p.shortLinkList(weapArray)
    for i, pair in Shared.skpairs(shortList) do
        result = result..'\n* '..pair
    end
    return result
end

--Runs a bunch of things to quickly check if anything broke
function p.checkForBugs(frame)
    return p.buildComparison({args = {"Lato", "Lato Prime"}})..p.buildComparison({args = {"Glaive", "Glaive Prime"}})..p.getMeleeComparisonTable({})..p.getSecondaryComparisonTable({})
end

function p.checkElements(frame)
    local result = "wyrd"
    for key, theWeap in Shared.skpairs(WeaponData["Weapons"]) do
        for attName, Attack in p.attackLoop(theWeap) do
            local elementCount = 0
            if(Attack.Damage ~= nil) then
                for element, dmg in Shared.skpairs(Attack.Damage) do
                    if(not Shared.contains(Physical, element)) then
                        elementCount = elementCount + 1
                    end
                end
            else
                result = result.."\n"..key.." attempted to loop the "..attName.." attack"
            end
            if(elementCount > 1) then
                result = result.."\n"..key.." has "..elementCount.." elements in its "..attName.." attack"
            end
        end
    end
    return result
end

function p.checkForMissingData(frame)
    local result = ""
    for key, weapon in Shared.skpairs(WeaponData["Weapons"]) do
        if(weapon.Name == nil) then
            result = result.."\n"..key.." does not have a Name"
        end
        if(weapon.Image == nil) then
            result = result.."\n"..key.." does not have an Image"
        end
        if(weapon.Mastery == nil) then
            result = result.."\n"..key.." does not have Mastery"
        end
        if(weapon.Disposition == nil and p.isArchwing(weapon) == nil) then
            result = result.."\n"..key.." does not have Disposition"
        end
        if(weapon.Type == nil) then
            result = result.."\n"..key.." does not have a Type"
        end
        if(weapon.Class == nil and p.isArchwing(weapon) == nil) then
            result = result.."\n"..key.." does not have a Class"
        end
        if(weapon.NormalAttack ~= nil and weapon.NormalAttack.Damage == nil) then
            result = result.."\n"..key.." does not do Normal Attacks"
        end
    end
    if (result == "") then
        result = "All weapons complete based on this test"
    end
    return result
end


function p.buildTunaWeaponTable(frame)
    local Category = frame.args ~= nil and frame.args[1] or frame
    local Weapons = p.getWeapons( function(x)
                                    return getValue(x, "Type", true) == Category
                                end)
                                    
    
    local result = '{| style="margin:auto;text-align:center;"'
    local i = 0
    for key, Weapon in Shared.skpairs(Weapons) do
        i = i + 1
        local theImage = Weapon.Image ~= nil and Weapon.Image or "Panel.png"
        if((i - 1) % 7 == 0) then 
            result = result..'\n|-'
        end
        result = result..'\n| style="width:85px" |[[File:'..Weapon.Name..'.png|70px]]'
    end
    result = result..'\n|}'
    return result
end

-- and we are back... new table building functions !

local function BuildCompRow(Head, Weapon, UseCompDisplay)
    --User:Falterfire 6/12/18 - Adding new Comparison Display functionality
    --                          Toggled with a variable, which is false if not specified
    if UseCompDisplay == nil then UseCompDisplay = false end
    local styleString = ""--"border: 1px solid lightgray;"
    local td = ''
    local result = ''
    local ValNameZ = nil
    local ValName = nil
    
    --User:Faltefire 6/12/18 - By default, use old version of code
    if not UseCompDisplay or Weapon.ComparisonDisplay == nil then
        local attName = ""
        if(hasAttack(Weapon, "Charge")) then
            attName = "Charge"
        elseif(hasAttack(Weapon, "Normal")) then
            attName = "Normal"
        else
            return ""
        end
        
    	result = '\n|-\n|'
    	
        for i, Hline in ipairs(Head) do
            ValName = Hline[1]
            local isName = false
            
            if(type(ValName) == "table" and ValName[1]=="default") then
                ValName = {attName, ValName[2]}
            elseif(type(ValName) == "table") then 
                ValName = {ValName[1], ValName[2]}
            else
                isName = string.upper(ValName) == "NAME"
            end
            
            if(i == 1) then td = '' else td='||' end
            --Override pour le nom et link correctement 
            if(getValue(Weapon, ValName)~=nil) then
                --Replace the default name with the name from ComparisonDisplay
                if isName then
                    local weapName = getValue(Weapon, ValName)
                    local weapLink = p._getLink(weapName, Weapon)
                    result = result..td..'style="'..styleString..'"|[['..weapLink..'|'..weapName..']]'
                elseif(Hline[2]) then 
                --Add a data sort value if requested
                    result = result..td..'data-sort-value="'..getValue(Weapon, ValName)..'" style="'..styleString..'"|'..getValue(Weapon, ValName, true, true, true)
                else
                    result = result..td..'style="'..styleString..'"|'..getValue(Weapon, ValName, true, true, true)
                end
            else 
                result = result..td..'style = "'..styleString..'"|'.."N/A" 
            end
        end
    else
        --User:Faltefire 6/12/18 - Swap to new version if ComparisonDisplay is set for this weapon and UseCompDisplay is true
        for i, row in pairs(Weapon.ComparisonDisplay) do
            local attCount = Shared.tableCount(row.Attacks)
            if attCount > 0 then
                local rowText = '\n|-\n|'
                local attName = row.Attacks[1]
                for j, Hline in ipairs(Head) do
                    ValName = Hline[1]
                    local KeyName = ''
                    
                    --If we're using the ComparisonDisplay, we're overriding the attempt to shunt to a different attack
                    --So always use attName + ValName, with one two exceptions: Damage and Name are overridden
                    if(type(ValName) == "table") then
                        ValName = {attName, ValName[2]}
                        KeyName = string.upper(ValName[2])
                    else
                        KeyName = string.upper(ValName)
                    end
                    
                    if(j == 1) then td = '' else td='||' end
                    if KeyName == 'NAME' then
                        local rowName = string.gsub(row.Name, "%[NAME%]", Weapon.Name)
                        --Replace the default name with the name from ComparisonDisplay
                        rowText = rowText..td..'style="'..styleString..'"|[['..rowName..'|'..rowName..']]'
                    elseif KeyName == 'DAMAGE' then
                        --For damage, go with the listed attack
                        if attCount == 1 then
                           rowText = rowText..td..'data-sort-value="'..getValue(Weapon, {attName, "Damage"})..'" style="'..styleString..'"|'..getValue(Weapon, {attName, "Damage"}, true, true, true)
                        else
                            --If multiple attacks are listed, show the combined damage
                            local attDmg = 0
                            for k, att in pairs(row.Attacks) do
                                mw.log(att)
                                attDmg = attDmg + getValue(Weapon, {att, "Damage"})
                            end
                            rowText = rowText..td..'data-sort-value="'..attDmg..'" style="'..styleString..'"|'..attDmg
                        end
                    else
                        if(getValue(Weapon, ValName) ~= nil) then
                            --Add a data sort value if requested
                            if(Hline[2]) then 
                                rowText = rowText..td..'data-sort-value="'..getValue(Weapon, ValName)..'" style="'..styleString..'"|'..getValue(Weapon, ValName, true, true, true)
                            else
                                rowText = rowText..td..'style="'..styleString..'"|'..getValue(Weapon, ValName, true, true, true)
                            end
                        else 
                            rowText = rowText..td..'style = "'..styleString..'"|'.."N/A" 
                        end
                    end
                end
                
                result = result..rowText
            end
        end
    end
		
    return result
end

local function BuildCompTable(Head, Weapons, UseCompDisplay)
    local styleString = "border: 1px solid black;border-collapse: collapse;"
    local tHeader = ""
    tHeader = tHeader..'\n{| cellpadding="1" cellspacing="0" class="listtable sortable" style="font-size:11px;"'
	for i, Hline in ipairs(Head) do
		if(Hline[2] == true) then
			tHeader = tHeader..'\n! data-sort-type="number" style="'..styleString..'"|'..Hline[3]..''
		else
			tHeader = tHeader..'\n! style="'..styleString..'"|'..Hline[3]..'' 
		end
	end
--	mw.log(tHeader)


    local tRows = ""
    for i, Weap in pairs(Weapons) do
        rowStr = BuildCompRow(Head, Weap, UseCompDisplay)
        tRows = tRows..rowStr
    end
--    mw.log(tRows)
    return  tHeader..tRows.."\n|}"--[[Category:Automatic Comparison Table]]
end

function p.getCompTableGuns(frame)
    local Catt = frame.args ~= nil and frame.args[1]
    local Type = frame.args ~= nil and frame.args[2] or nil
        if(Type == "All") then Type = nil end
    local WeapArray = {}
    if(Catt == "Principale") then WeapArray = p.getWeapons(function(x) 
                                if(getValue(x, "Type", true) == "Principale") then
                                    if(Type ~= nil) then return getPrimaryCategory(x) == Type else return true end
                                end
                                    return false
                                end)
    elseif(Catt == "Secondaire") then WeapArray = p.getWeapons(function(x) 
                                if(getValue(x, "Type", true) == "Secondaire") then
                                    if(Type ~= nil) then return getSecondaryCategory(x) == Type else return true end
                                end
                                    return false
                                end)
	elseif(Catt == "Robotique") then WeapArray = p.getWeapons(function(x) 
                                    return getValue(x, "Type", true) == "Robotique"
                                    end)
    else return "\n Error : Wrong Class (use Principale, Secondaire, or Robotique) [[Category:Invalid Comp Table]]"
    end
    

	local Head={{"Name",false,"Name"}}
	 -- better if Name is always the first column !!!
	table.insert(Head,{"Trigger",false,"Mode de Tir"})
	table.insert(Head,{{"default","Damage"},true,"[[Dégâts]]"})
	table.insert(Head,{{"default", "CritChance"},true,"[[Chance de Coup Critique|Chance Crit.]]"})
	table.insert(Head,{{"default", "CritMultiplier"},true,"[[Multiplicateur de Critique|Multiplicateur de Crit.]]"})
	table.insert(Head,{{"default", "StatusChance"},true,"[[Chance de Statut]]"})
	table.insert(Head,{{"default","BulletType"},false,"Type de Projectile"})
	table.insert(Head,{{"default", "FireRate"},true,"[[Cadence de Tir]]"})
	table.insert(Head,{"Magazine",true,"[[Munitions#Capacité du Chargeur|Taille Chargeur]]"})
	table.insert(Head,{"Reload",true,"[[Rechargement|Tmps. Rechargement]]"})
	table.insert(Head,{"Mastery",true,"[[Rang de Maîtrise]]"})
	table.insert(Head,{"Disposition",true,"[[Mod Riven#Disposition|Disposition]]"})
	    
    return BuildCompTable(Head, WeapArray, true)
end

function p.getCompTableConclaveGuns(frame)
    local Catt = frame.args ~= nil and frame.args[1]
    local Type = frame.args ~= nil and frame.args[2] or nil
        if(Type == "All") then Type = nil end
    local WeapArray = {}
    if(Catt == "Principale") then WeapArray = p.getConclaveWeapons(function(x) 
                                if((getValue(x, "Type", true) == "Principale") and (getValue(x, "Conclave", true) == true)) then
                                    if(Type ~= nil) then return getPrimaryCategory(x) == Type else return true end
                                end
                                    return false
                                end)
    elseif(Catt == "Secondaire") then WeapArray = p.getConclaveWeapons(function(x) 
                                if((getValue(x, "Type", true) == "Secondaire") and (getValue(x, "Conclave", true) == true)) then
                                    if(Type ~= nil) then return getSecondaryCategory(x) == Type else return true end
                                end
                                    return false
                                end)
    else return "\n Error : Wrong Class (use Principale or Secondaire) [[Category:Invalid Comp Table]]"
    end
    

	local Head={{"Name",false,"Name"}}
	 -- better if Name is always the first column !!!
	table.insert(Head,{"Trigger",false,"[[Fire Rate|Trigger Type]]"})
	table.insert(Head,{{"default","Damage"},true,"[[Dégâts]]"})
	table.insert(Head,{"HeadshotMultiplier",true,"HS Multiplier"})
	table.insert(Head,{{"default","BulletType"},false,"Projectile Type"})
	table.insert(Head,{"FireRate",true,"[[Fire Rate]]"})
	table.insert(Head,{"Magazine",true,"[[Munitions#Magazine Capacity|Magazine Size]]"})
	table.insert(Head,{"Reload",true,"[[Reload Speed|Reload Time]]"})
	table.insert(Head,{"Mastery",true,"[[Rang de Maîtrise]]"})
	    
    return BuildCompTable(Head,WeapArray)
end

function p.getCompTableArchGuns(frame)
    local ArchType="Arch-Fusil"
    if (frame.args ~= nil) then 
        if (frame.args[1] == "Arch-Fusil (Atmosphère)") then
            ArchType="Arch-Fusil (Atmosphère)"
        end
    end
    
    local WeapArray = {}
    WeapArray = p.getWeapons(function(x) 
                                    return getValue(x, "Type", true) == ArchType
                                    end)
    
	local Head={{"Name",false,"Name"}}
	 -- better if Name is always the first column !!!
	table.insert(Head,{"Trigger",false,"Mode de Tir"})
	table.insert(Head,{{"default","Damage"},true,"[[Dégâts]]"})
	table.insert(Head,{"CritChance",true,"[[Chance de Coup Critique]]"})
	table.insert(Head,{"CritMultiplier",true,"[[Multiplicateur de Critique|Multiplicateur de Crit.]]"})
	table.insert(Head,{"StatusChance",true,"[[Chance de Statut]]"})
	table.insert(Head,{{"default","BulletType"},false,"Type de Projectile"})
	table.insert(Head,{"FireRate",true,"[[Cadence de Tir]]"})
	table.insert(Head,{"Magazine",true,"[[Ammo#Magazine Capacity|Taille Chargeur]]"})
	table.insert(Head,{"Reload",true,"[[Vitesse de Rechargement]]"})
	table.insert(Head,{"Mastery",true,"[[Rang de Maîtrise]]"})
    return BuildCompTable(Head,WeapArray)
end


function p.getCompTableMelees(frame)
    --Changed formatting, now only takes type since only class handled is Melee
    --Keeping old formatting to avoid breaking pages
    local Type = frame.args ~= nil and frame.args[2] or nil
    if(Type == nil) then Type = frame.args ~= nil and frame.args[1] or nil end 
    if(Type == "All") then Type = nil end
    local WeapArray = {}
    WeapArray = getMeleeWeapons(Type)
    local addClass = Type == nil or Shared.contains(Type, ",")
								
	local Head={{"Name",false,"Nom"}}
	 -- better if Name is always the first column !!!
	table.insert(Head,{"Class",false,"Type"})
	table.insert(Head,{{"Normal","Damage"},true,"[[Dégâts|Normal]]"})
	table.insert(Head,{"SlideAttack",true,"[[Mêlée#Attaque Glissée|Glissée]]"})
	table.insert(Head,{{"default","FireRate"},true,"[[Vitesse d'Attaque]]"})
	table.insert(Head,{"CritChance",true,"[[Chance de Coup Critique|Chance Crit.]]"})
	table.insert(Head,{"CritMultiplier",true,"[[Multiplicateur de Critique|Multiplicateur Crit.]]"})
	table.insert(Head,{"StatusChance",true,"[[Chance de Statut]]"})
	table.insert(Head,{"Mastery",true,"[[Rang de Maîtrise]]"})
	table.insert(Head,{"STANCEPOLARITY",false,"[[Posture]]"})
	table.insert(Head,{"Disposition",true,"[[Mod Riven#Disposition|Disposition]]"})
	for k, v in pairs(Head[1]) do mw.log(k, v) end
    
    return BuildCompTable(Head,WeapArray)
end

--As above, but for conclave
function p.getCompTableConclaveMelees(frame)
    local Type = frame.args ~= nil and frame.args[1] or nil
    if(Type == "All") then Type = nil end
    local WeapArray = {}
    WeapArray = getConclaveMeleeWeapons(Type)
    local addClass = Type == nil or Shared.contains(Type, ",")
								
	local Head={{"Name",false,"Name"}}
	 -- better if Name is always the first column !!!
	table.insert(Head,{"Class",false,"Type"})
	table.insert(Head,{{"Normal","Damage"},true,"[[Dégâts|Normal]]"})
	table.insert(Head,{"SlideAttack",true,"[[Mêlée#Attaque Glissée|Glissée]]"})
	table.insert(Head,{{"default","FireRate"},true,"[[Vitesse d'Attaque]]"})
	table.insert(Head,{"Mastery",true,"[[Rang de Maîtrise]]"})
	table.insert(Head,{"STANCEPOLARITY",false,"[[Posture]]"})
	for k, v in pairs(Head[1]) do mw.log(k, v) end
    
    return BuildCompTable(Head,WeapArray)
end

function p.getCompTableArchMelees(frame)
    local WeapArray = {}
    WeapArray = p.getWeapons(function(x) 
                                    return getValue(x, "Type", true) == "Arch-Mêlée"
                                end)
								
	local Head={{"Name",false,"Name"}}
	 -- better if Name is always the first column !!!
	table.insert(Head,{{"Normal","Damage"},true,"[[Dégâts|Normal]]"})
	table.insert(Head,{"SlideAttack",true,"[[Mêlée#Attaque Glissée|Glissée]]"})
	table.insert(Head,{{"default","FireRate"},true,"[[Vitesse d'Attaque]]"})
	table.insert(Head,{"CritChance",true,"[[Chance de Coup Critique|Chance de Crit.]]"})
	table.insert(Head,{"CritMultiplier",true,"[[Multiplicateur de Critique|Multiplicateur de Crit.]]"})
	table.insert(Head,{"StatusChance",true,"[[Chance de Statut]]"})
	table.insert(Head,{"Mastery",true,"[[Rang de Maîtrise]]"})
	for k, v in pairs(Head[1]) do mw.log(k, v) end
    
    return BuildCompTable(Head,WeapArray)
end

function p.getCompTableSpeedGuns(frame)
    local Catt = frame.args ~= nil and frame.args[1]
    local Type = frame.args ~= nil and frame.args[2] or nil
        if(Type == "All") then Type = nil end
    local WeapArray = {}
    if(Catt == "Principale") then WeapArray = p.getWeapons(function(x) 
                                if(getValue(x, "Type", true) == "Principale") then
                                    if(Type ~= nil) then return getPrimaryCategory(x) == Type else return true end
                                end
                                    return false
                                end)
    elseif(Catt == "Secondaire") then WeapArray = p.getWeapons(function(x) 
                                if(getValue(x, "Type", true) == "Secondaire") then
                                    if(Type ~= nil) then return getSecondaryCategory(x) == Type else return true end
                                end
                                    return false
                                end)
	elseif(Catt == "Robotique") then WeapArray = p.getWeapons(function(x) 
                                    return getValue(x, "Type", true) == "Robotique"
                                    end)
	elseif(Catt == "Arch-Fusil") then WeapArray = p.getWeapons(function(x) 
                                    return getValue(x, "Type", true) == "Arch-Fusil"
                                    end)
    else return "\n Erreur : Mauvaise Class (utilisez Principale, Secondaire, Robotique, ou Arch-Fusil) [[Category:Invalid Comp Table]]"
    end
    -- special sorting for projectile weapons
    local WeapArray2 = {}
    for k, Weapon in ipairs(WeapArray) do
        local attName = ""
        if(hasAttack(Weapon, "Charge")) then
            attName = "Charge"
        elseif(hasAttack(Weapon, "Normal")) then
            attName = "Normal"
        else
            return ""
        end
        if(getValue(Weapon,{attName, "BulletType"}, false) == "Projectile") then
            table.insert(WeapArray2, Weapon)
        elseif(getValue(Weapon,{"Area", "BulletType"}, false) == "Projectile") then
            table.insert(WeapArray2, Weapon)
        elseif(getValue(Weapon,{"Secondaire", "BulletType"}, false) == "Projectile") then
            table.insert(WeapArray2, Weapon)
        elseif (getValue(Weapon,{attName, "BulletType"}, false) == "Thrown") then
            table.insert(WeapArray2, Weapon)
        end
    end

	local Head={{"Name",false,"Name"}}
	 -- better if Name is always the first column !!!
	table.insert(Head,{"Class",false,"Type"})
	table.insert(Head,{{"Normal","PROJECTILESPEED"},true,"Flight Speed"})
	table.insert(Head,{{"Charge","PROJECTILESPEED"},true,"Charge Flight Speed"})
	table.insert(Head,{"SPECIALFSPEED",true,"Alt-Fire / Special"})
    
    return BuildCompTable(Head,WeapArray2)
end

function p.getCompTableSpeedMelees(frame)
    local Catt = frame.args ~= nil and frame.args[1]
    local Type = frame.args ~= nil and frame.args[2] or nil
    if(Type == "Tous") then Type = nil end
    local WeapArray = {}
    if(Catt == "Mêlée") then WeapArray = getMeleeWeapons(Type)
	                                local addClass = Type == nil or Shared.contains(Type, ",")
	elseif(Catt == "Arch-Mêlée") then WeapArray = p.getWeapons(function(x) 
                                    return getValue(x, "Type", true) == "Arch-Mêlée"
                                end)
    else return "\n Error : Wrong Class (use Melee or Arch-Melee) [[Category:Invalid Comp Table]]"
    end
    -- special sorting for projectile weapons ONLY WORKS FOR GLAIVE TYPE MELEE WEAPONS !!!
    local WeapArray2 = {}
    for k, Weapon in ipairs(WeapArray) do
        if (getValue(Weapon,{"Normal", "BulletType"}, false) == "Thrown") then
            table.insert(WeapArray2, Weapon)
        end
    end

	local Head={{"Name",false,"Name"}}
	 -- better if Name is always the first column !!!
	table.insert(Head,{{"Normal","PROJECTILESPEED"},true,"Flight Speed"})
	table.insert(Head,{"SPECIALFSPEED",true,"Special"})
    
    return BuildCompTable(Head,WeapArray2)
end

function p.weaponTooltipText(frame)

    local weapName = frame.args ~= nil and frame.args[1]
    local newName = frame.args[2]
    local conclave = frame.args["Conclave"] == "true" and true
    local iconless = frame.args["Iconless"] == "true" and true
    
    return p._weaponTooltipText(weapName, newName, conclave, iconless)
end

function p._weaponTooltipText(weapName, newName, conclave, iconless)

    if(conclave == nil) then
        conlave = false 
    end
    if(iconless == nil) then
        iconless = false 
    end
    local conclaveParam = ''
    local linkText = ''
    local namespace = ''
    
    if newName == '' then
        newName = nil
    end

    local weap = checkWeapon(weap, weapName, conclave)
    if weap == nil and conclave == true then
        weap = checkWeapon(weap, weapName)
    end
    
    if weap ~= nil or weapName == "Épées Versatiles Sombres" then
        local link = p._getLink(weapName, weap)
        
        if conclave == true then
            conclaveParam = ' data-param2="true"'
            if weapName == "Épées Versatiles Sombres" then
                namespace = 'Conclave:'
            elseif weap.Conclave == true then
                namespace = 'Conclave:'
            end
        end
        
        if link and newName ~= nil then
            linkText = '[['..namespace..link..'|'..newName..']]'
        elseif newName ~= nil then
            linkText = '[['..namespace..weapName..'|'..newName..']]'
        elseif link == weapName then
            linkText = '[['..namespace..link..'|'..link..']]'
        elseif link then
            linkText = '[['..namespace..link..'|'..weapName..']]'
        else
            linkText = '[['..namespace..weapName..'|'..weapName..']]'
        end

        if link ~= false and iconless ~= true then
            local image = getValue(weap,"Image",true)
            return '<span class="weapon-tooltip" data-param="'..weapName..'"'..conclaveParam..' style="white-space:pre">'..linkText..' [[File:'..image..'|x19px|link='..namespace..link..']]</span>'
        elseif link ~= false then
            return '<span class="weapon-tooltip" data-param="'..weapName..'"'..conclaveParam..' style="white-space:pre">'..linkText..'</span>'
        else
            return '<span style="color:red;">{{[[Template:Weapon|Weapon]]}}</span> "'..weapName..'" not found[[Category:Tooltip Error]]'
        end
    else
        return '<span style="color:red;">{{[[Template:Weapon|Weapon]]}}</span> "'..weapName..'" not found[[Category:Tooltip Error]]'
    end
end

function p.weaponTooltip(frame)
    local weapName = frame.args ~= nil and frame.args[1]
    local conclave = frame.args[2] == "true" and true
    --there's no "Dark Split-Sword" in m:weapons/data -> setting name to dual sword variant
    if weapName == 'Épées Versatiles Sombres' then
        weapName = 'Épées Versatiles Sombres (Doubles Épées)'
    end
    
    local A2Name = nil
    local A2Value = nil
    local C1Name = nil
    local C1Value = nil
    local C1Toggle = nil
    local C2Name = nil
    local C2Value = nil
    local D1Name = nil
    local D1Value = nil
    local D1Value2 = nil
    local titleText = ''
    local hasCharged = false
    local attackType = 'Normal'
    local attack = nil
    local attackText = ''
    local space = '&nbsp;'
    local attackBiasText = ''
    
    if weapName == nil then
        return nil
    end
    
    local Weapon = nil
    local cAvailability = false
    if conclave then
        Weapon = p.getConclaveWeapon(weapName)
        if Weapon ~= nil then
            cAvailability = getValue(Weapon, "Conclave", true, false, false)
        end
        if not cAvailability then
            Weapon = p.getWeapon(weapName)
        end
    else
        Weapon = p.getWeapon(weapName)
    end
    
    local conclaveNotice = ''
    if conclave and cAvailability == false then
        conclaveNotice = '\n{| class="Data" style="font-size:10px; white-space:normal;"\n|-\n|Note: Non disponible en Conclave, displaying Cooperative stats and Cooperative Link.\n|}'
    end

    if Weapon == nil then
        return 'L\'arme '..weapName..' n\'a pas été trouvée.'
    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 getValue(Weapon, valueName, giveDefault, asString, forTable)
    end
    
    local function whitePols(valueName)
        local pols = Value(valueName)
        local polIcon = ''
        
        if type(pols) == "table" then
            local i = 0
            if pols[1] == nil then
                polIcon = 'Aucune'
                return polIcon
            else
                while pols[i+1] ~= nil do
                    i = i + 1
                end
                for j = 1, i do
                    polIcon = polIcon..Icon._Pol(pols[j],'white','x16')
                end
                return polIcon
            end
        elseif pols ~= nil and type(pols) == "string" and pols ~= "Aucune" then
            return Icon._Pol(pols,'white','x16')
        end
        return 'Aucune'
    end
    
    --for weapons which have no max ammo
    local ammoException = nil
    if Value("MaxAmmo") == nil then
        ammoException = true
    end

    local isMelee = p.isMelee(Weapon) == "yes"
    
    local chargedExceptions = {"Tiberon Prime", "Kohm", "Kohmak", "Twin Kohmak", "Stug"} -- weapons which have a charged attack but normal attack values are used for the tooltip
    local secondaryExceptions = {"Penta", "Carmine Penta", "Secura Penta"}
    local areaExceptions = {"Ogris", "Zarr", "Tonkor", "Kulstar", "Angstrum", "Prisma Angstrum"}
    local secondaryAreaExceptions ={"Lenz"}
    
    if isMelee ~= true then
        if Shared.contains(chargedExceptions, weapName) ~= true and Value({"Charge","AttackName"}) ~= nil then
            hasCharged = true
            attackType = 'Charge'
        end
        if Shared.contains(secondaryExceptions, weapName) then
            attackType = 'Secondary'
        elseif Shared.contains(areaExceptions, weapName) then
            attackType = 'Area'
        elseif Shared.contains(secondaryAreaExceptions, weapName) then
            attackType = 'SecondaryArea'
        end
    end
    
    attack = getAttack(Weapon, attackType)
    local count = 0
    for type, dmg in Shared.skpairs(attack.Damage) do
        if count == 0 then
            attackText = '\n| style=\"padding-right:2px;\" |'..Icon._Proc(type,'','white','x16')..space..dmg
            count = count + 1
        else
            attackText = attackText..'|| style=\"padding-right:4px;\" |'..Icon._Proc(type,'','white','x16')..space..dmg
        end
    end

    if(hasMultipleTypes(attack)) then
        attackBiasText = '\n| colspan=4 |'..GetDamageString(attack, nil).." ("..GetDamageBiasString(attack,nil,'',nil,'white','x16')..")"
    end
    
    local mRankIcon = ''
    local mRank = Value("Mastery",false,false,false)
    local mRankIconLoc = 'top:4px; left:9.5px;'
    if mRank then
        if string.len(mRank) >= 2 then
            mRankIconLoc = 'top:4px; left:5px;'
        end
        mRankIcon = '<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;'..mRankIconLoc..'">'..mRank..'</div></div>'
    end
    
    local dispoIcon = ''
    local dispoVal = Value("Disposition5",false,false,false)
    if dispoVal then
        dispoIcon = '<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;">'..dispoVal..'</div></div>'
    end
    
    if isMelee == true then
        A2Name = 'Type'
        A2Value = 'Class'
        C1Name = 'Vitesse Atq.'
        C1Value = 'FireRate'
        C1Toggle = true
        C2Name = 'Atq. Glissade'
        C2Value = 'SlideAttack'
        D1Name = 'Polarités'
        D1Value = 'Polarities'
        D1Value2 = 'StancePolarity'
    else
        A2Name = 'Tir'
        A2Value = 'Trigger'
        if hasCharged == true then
            C1Name = 'Charge Time'
            if weapName == "Staticor" then
                C1Value = {'Area','ChargeTime'}
            else
                C1Value = {'Charge','ChargeTime'}
            end
            C1Toggle = true
        else
            C1Name = 'Cad. de Tir'
            C1Value = 'FireRate'
        end
        C2Name = 'Sonorité'
        C2Value = 'NoiseLevel'
        D1Name = 'Polarités'
        D1Value = 'Polarities'
    end
        
    local function Link(linkName)
        local spanStart = '<span class=\"LinkText\">'
        local spanEnd = '</span>'
        return spanStart..linkName..spanEnd
    end
    
    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|}'
    
    local Type = ''
    local tType = Value("Type")
    if tType == "Arch-Gun (Atmosphere)" then
        Type = "Arch-Gun (Atmo)"
    else
        Type = tType
    end
    
    local image = '\n| class=\"Image\" style=\"height:120px;\" | <div style="position:relative; z-index:2;">[[File:'..Value("Image")..'|160px]]</div>'
    
    --creating the table
    local result = '<div style="position:relative;">\n{| class=\"Sub\"'..newRow..image..mRankIcon..dispoIcon..newRow..spacer..newRow..zeroPadding
    result = result..dataText..newRow
    result = result..halfTable..Link("Slot")..space..Type..halfTable..Link(A2Name)..space..Value(A2Value)..tableEnd
    result = result..newRow..spacer..titleText..newRow..zeroPadding
    result = result..dataTextCenter..newRow..attackText
    if(attackBiasText ~= '') then
        result = result..newRow..attackBiasText
    end
    result = result..tableEnd
    result = result..newRow..spacer..newRow..zeroPadding..dataText..newRow..halfTable..Link("Critique")..space..Value("CritChance",true)..' | '..Value("CritMultiplier",true)..halfTable..Link("Statut")..space..Value("StatusChance",true)
    result = result..newRow..halfTable..Link(C1Name)..space..Value(C1Value,C1Toggle)..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
        result = result..newRow..halfTable..Link("Recharge")..space..Value("Reload", true, true)..halfTable..Link("Munitions")..space..Value("Magazine")
        --if has max ammo => add max ammo stat
        if ammoException == nil then
            result = result..'&thinsp;/&thinsp;'..Value("MaxAmmo")
        end
        result = result..newRow..'\n| style=\"text-align:center;\" colspan=2 |'..Link(D1Name)..space..whitePols(D1Value)
    elseif isMelee then
        result = result..newRow..'\n| style=\"text-align:center;\" colspan=2 |'..Link(D1Name)..space..whitePols(D1Value2)..' | '..whitePols(D1Value)
    end
    result = result..tableEnd..conclaveNotice..tableEnd..'\n</div>'
    
    return result
end

function p.getWeaponReplaceList(frame)
    --local Type = frame.args ~= nil and frame.args[1] or frame
    local fullList = {}
    local primaries = {}
    local secondaries = {}
    local melees = {}
    local archGuns = {}
    local archMelees = {}
    local theRest ={}
    
    local avoidNames ={'Lame Exaltée (Umbra)','Corvas (Atmosphere)','Cyngas (Atmosphere)','Dargyn','Doubles Decurion (Atmosphere)','Fluctus (Atmosphere)','Grattler (Atmosphere)','Imperator (Atmosphere)','Imperator Vandal (Atmosphere)','Phaedra (Atmosphere)','Rampart','Velocitus (Atmosphere)'}
    
    local function addToList(name,link,list)
        if link == nil then
            link = name
        end
        --local 6s = '      '
        --local 8s = '        '
        local temp = '      <Replacement>\n        <Find>\[\['..link..']]</Find>\n        <Replace>{{Weapon|'..name..'}}</Replace>\n        <Comment />\n        <IsRegex>false</IsRegex>\n        <Enabled>true</Enabled>\n         <Minor>false</Minor>\n        <BeforeOrAfter>false</BeforeOrAfter>\n        <RegularExpressionOptions>IgnoreCase</RegularExpressionOptions>\n      </Replacement>'
        return table.insert(list,temp)
    end
    
    for i, val in Shared.skpairs(WeaponData["Weapons"]) do
        if not Shared.contains(avoidNames,val.Name) then
            
            if val.Type == "Principale" then
                addToList(val.Name,val.Link,primaries)
            elseif val.Type == "Secondaire" then
                addToList(val.Name,val.Link,secondaries)
            elseif val.Type == "Mêlée" then
                addToList(val.Name,val.Link,melees)
            elseif val.Type == "Arch-Fusil" then
                addToList(val.Name,val.Link,archGuns)
            elseif val.Type == "Arch-Mêlée" then
                addToList(val.Name,val.Link,archMelees)
            else
                addToList(val.Name,val.Link,theRest)
            end
        end
    end
    
    table.insert(fullList,table.concat(primaries,'\n'))
    table.insert(fullList,table.concat(secondaries,'\n'))
    table.insert(fullList,table.concat(melees,'\n'))
    table.insert(fullList,table.concat(archGuns,'\n'))
    table.insert(fullList,table.concat(archMelees,'\n'))
    table.insert(fullList,table.concat(theRest,'\n'))

    return table.concat(fullList, "\n")
end

local function buildHTMLTable(table)
    resultTable = '\n{| class="wikitable"'
    for i, val in Shared.skpairs(table) do
        resultTable = resultTable..'\n|'..i..'||'
        if(val ~= nil and type(val) == "table") then
            resultTable = resultTable..buildHTMLTable(val)
        else
            resultTable = resultTable..tostring(val)
        end
        resultTable = resultTable..'\n|-'
    end
    resultTable = resultTable..'\n|}'
    return resultTable
end

function p.buildHTMLDB()
    
    return buildHTMLTable(WeaponData["Weapons"])
end

local function filterWeaponsArray_Melee(subCat, weapArray)
    
    local ret = {}
    for _, weapon in ipairs(weapArray) do
        if(weapon.Class == subCat) then
            local key = nil
            if(weapon.Family ~= nil) then
                key = weapon.Family
            else
                key = weapon.Name
            end
            if(ret[key] == nil) then
                ret[key] = {weapon.Name} 
            else
                table.insert(ret[key], weapon.Name)
            end
        end
    end
    return ret
end

local function printFamily(familyName, familyValues, conclave)

    local ret = p._weaponTooltipText(familyName, nil, conclave, nil)
    local first = true
    for _, wpName in ipairs(familyValues) do
        if(wpName ~= familyName) then
            local newName = Shared.trim(wpName:gsub(familyName, ""))
            --Special case
            if(newName == "MK1-") then
                newName = "MK1" 
            end
            if(first) then
                first = false
                ret = ret.." ("..p._weaponTooltipText(wpName, newName, conclave, nil)
            else
                ret = ret.." • "..p._weaponTooltipText(wpName, newName, conclave, nil)
            end
        end
    end
    if(not first) then
        ret = ret..")"
    end
    return ret
end

function p.getWeaponsList(frame)
    
    local mainCat = frame.args ~= nil and frame.args[1]
    local subCat = frame.args ~= nil and frame.args[2]
    local conclave = frame.args ~= nil and frame.args[3]
    conclave = conclave ~= nil and conclave ~= "false"
    
    return p._getWeaponsList(mainCat, subCat, conclave)
end

function p._getWeaponsList(mainCat, subCat, conclave)

    local weapArray = nil
    --Get array of mainCat weapons
    if(conclave) then
        weapArray = p.getConclaveWeapons(function(x) return x.Type == mainCat end)
    else
        weapArray = p.getWeapons(function(x) return x.Type == mainCat end)
    end
    --Filter for second cat
    local weapMap = {}
    if(mainCat == "Mêlée") then
        weapMap = filterWeaponsArray_Melee(subCat, weapArray)
    end
    --Build String for result array
    local first = true
    local ret = nil
    for family, wpList in Shared.skpairs(weapMap) do
        if(first) then
            ret = printFamily(family, wpList, conclave)
            first = false
        else
            ret = ret.." • "..printFamily(family, wpList, conclave)
        end
    end
    
    return ret
end

return p
Advertisement