Void retrieves drop table data of opening Void Relics. Originally built when the Void rewarded Primed parts and blueprints.

On this Wiki, Void is used in:


Usage

Module

local Void = require('Module:Void')

local function func(input)
    return Void.getRelic('Axi', 'A1')
end

Documentation

Package items

void.isVaulted(relicName) (function)
Checks if a relic is vaulted or not.
Parameter: relicName Relic name (string)
Returns: True if relic is vaulted, false otherwise (boolean)
void.getItemName(itemStr) (function)
Converts item names to their proper Prime names. For example, 'LATRON' becomes 'Latron Prime'.
Parameter: itemStr Item name (string)
Returns: Prime name (string)
void.getPartName(partStr, keepBlueprint) (function)
Converts Prime part names in data to proper casing.
Parameters:
  • partStr Item name (string)
  • keepBlueprint If true, adds 'blueprint' to end of result, false otherwise. Default value is true. (boolean; optional)
Returns: Name of Prime part (string)
void.getRelic(tier, name) (function)
Gets the relic data
Parameters:
  • tier Relic tier (e.g. 'Axi') (string)
  • name Relic name (e.g. 'A1') (string)
Returns: A table containing relic's drops and vaulted info. Returns nil if no data for that relic is found. (table or nil)
void.getRelicDropRarity(relic, item, part) (function)
Returns the rarity if a relic drops a part.
Parameters:
  • relic Relic table entry (table)
  • item Name of item (string)
  • part Name of item part (string)
Returns: The rarity of drop; returns nil if relic does not drop specified item (string or nil)
void.getPartIconForDrop(drop) (function)
Returns the part icon for a drop. For example, "Braton Prime Barrel" returns Primebarrel.png
Parameter: drop Item name (string)
Returns: Icon in the form of a wikitext link (string)
void.getItemIconForDrop(drop) (function)
Returns the item icon for a drop. For example, "Braton Prime Barrel" returns PrimeBraton.png
Parameter: drop Item name (string)
Returns: Icon in the form of a wikitext link (string)
void.item(item_type, item_part, relic_tier) (function)
Returns the relics in which the item is dropped from.
Parameters:
  • item_type (string)
  • item_part (string)
  • relic_tier (string)
Returns: (string)
void._item(item_type, item_part, relic_tier) (function)
Returns the relics in which the item is dropped from.
Parameters:
  • item_type (string)
  • item_part (string)
  • relic_tier (string)
Returns: (string)
void.getRelicDrop(relicName, rarity, number) (function)
Gets the drop table of a relic.
Parameters:
  • relicName (string)
  • rarity (string)
  • number (number)
Returns: (string)
void.getRelicTotal() (function)
Gets the total number of relics in the game.
Parameter: *frame.args Options for what relic types to include are "unvaulted", "vaulted", "baro", or nil (string; optional)
Returns: The total count of all relics (number)
void.getDucatValue(itemName, partName) (function)
Gets the ducat value of a Prime part or blueprint.
Parameters:
  • itemName Prime item name (string)
  • partName Part name (string)
Returns: The ducat value of that Prime part/blueprint (number)
void._getDucatValue(itemName, partName, data) (function)
Gets the ducat value of a Prime part or blueprint.
Parameters:
  • itemName Prime item name (string)
  • partName Part name (string)
  • data Relic data (table)
Returns: The ducat value of that Prime part/blueprint (number)
void.getTotalDucats(tierName) (function)
Gets the total ducat value of all Prime parts and blueprints.
Parameter: tierName Tier name if want to filter by a specific relic tier (string; optional)
Returns: The total ducat value (number)
void.ducatRelicList(tierName, listMode) (function)
Builds a table of all Prime parts, the relics they are in, and their ducat value as seen https://warframe. fandom.com/wiki/Ducats/Prices/Lith
Parameters:
  • tierName Tier name if want to filter by a specific relic tier (string; optional)
  • listMode If nil, displays only unvaulted item; if "All", displays all items, including vaulted ones (string; optional)
Returns: Wikitext of table (string)

Created with Docbuntu


See Also


Code


--- '''Void''' retrieves drop table data of opening [[Void Relic]]s. Originally
--  built when the [[Void]] rewarded [[Prime]]d parts and blueprints.
--  
--  On this Wiki, Void is used in:
--  * [[Module:Acquisition]]
--  
--  
--  @module     void
--  @alias      p
--  @author     [[User:ChickenBar|ChickenBar]]
--  @attribution    [[User:Flaicher|Flaicher]]
--  @attribution    [[User:FINNER|FINNER]]
--  @attribution    [[User:Falterfire|Falterfire]]
--  @attribution    [[User:Gigamicro|Gigamicro]]
--  @attribution    [[User:Synthtech|Synthtech]]
--  @image      VoidProjectionsIronD.png
--  @require    [[Module:Void/data]]
--  @require    [[Module:Icon]]
--  @require    [[Module:Shared]]
--  @require    [[Module:String]]
--  @require    [[Module:Math]]
--  @release    stable
--  <nowiki>

-- TODO: Replace any mentions of string functions from Shared to those from String

local p = {}

local VoidData = mw.loadData [[Module:Void/data]]
local Icon = require [[Module:Icon]]
local Shared = require [[Module:Shared]]
local String = require [[Module:String]]
local Math = require [[Module:Math]]

local TxtColors = {Common = '#9C7344', Uncommon = '#D3D3D3', Rare = '#D1B962'}

local tooltipStart = '<span class="relic-tooltip" data-param="'
local tooltipCenter = '">'
local tooltipEnd = '</span>'

--- Checks if a relic is vaulted or not.
--  @function       p.isVaulted
--  @param          {string} relicName Relic name
--  @return         {boolean} True if relic is vaulted, false otherwise
function p.isVaulted(relicName)
	local itr = string.gmatch(relicName, '([^ ]+)')
	local tier = itr[1]
	local name = itr[2]
	return p.getRelic(tier, name)['IsVaulted'] == 1
end

--- Converts item names to their proper Prime names. 
--  For example, 'LATRON' becomes 'Latron Prime'.
--  @function       p.getItemName
--  @param          {string} itemStr Item name
--  @return         {string} Prime name
function p.getItemName(itemStr)
    local caseItem = String.titleCase(itemStr)
    if (itemStr ~= "FORMA") then
        caseItem = caseItem.." Prime"
    end
    return caseItem
end

--- Converts Prime part names in data to proper casing.
--  @function       p.getPartName
--  @param          {string} partStr Item name
--  @param[opt]     {boolean} keepBlueprint If true, adds 'blueprint' to end of result, false otherwise. 
--                                          Default value is true.
--  @return         {string} Name of Prime part 
function p.getPartName(partStr, keepBlueprint)
    --User:Falterfire 6/19/2018:
    --      New parameter to remove ' Blueprint' if wanted
    --      IE returns 'Neuroptics' instead of 'Neuroptics Blueprint'
    if keepBlueprint == nil then keepBlueprint = true end
    local result = String.titleCase(partStr)
    if not keepBlueprint and Shared.contains(result, ' Blueprint') then
        result = string.gsub(result, ' Blueprint', '')
    end
    return result
end

--- Gets the relic data
--  @function       p.getRelic
--  @param          {string} tier Relic tier (e.g. 'Axi')
--  @param          {string} name Relic name (e.g. 'A1')
--  @return         {table or nil} A table containing relic's drops and vaulted info. Returns nil if no data for that relic is found.
function p.getRelic(tier, name)
    return VoidData['RelicNames'][('%s %s'):format(tier, name)]
end

--- Returns the rarity if a relic drops a part.
--  @function       p.getRelicDropRarity
--  @param          {table} relic Relic table entry
--  @param          {string} item Name of item
--  @param          {string} part Name of item part
--  @return         {string or nil} The rarity of drop; returns nil if relic does not drop specified item
function p.getRelicDropRarity(relic, item, part)
    for i, drop in pairs(relic['Drops']) do
        if (drop['Item'] == item and drop['Part'] == part) then
            return drop.Rarity
        end
    end
    return nil
end

--- Returns the part icon for a drop.
--  For example, "Braton Prime Barrel" returns [[File:Primebarrel.png|38px]]
--  @function       p.getPartIconForDrop
--  @param          {string} drop Item name
--  @return         {string} Icon in the form of a wikitext link
function p.getPartIconForDrop(drop)
    local iName = p.getItemName(drop.Item)
    local pName = p.getPartName(drop.Part)
    local iconSize =''
    local primeToggle = 'Prime '
    if iName == 'Forma' then
        iconSize = '43'
    else
        iconSize = '54'
    end
    
    if iName == 'Odonata Prime' then
        if pName == 'Harness Blueprint' or pName == 'Systems Blueprint' or pName == 'Wings Blueprint' then
            primeToggle = 'Archwing '
        end
    elseif pName == 'Carapace' or pName == 'Cerebrum' or pName == 'Systems' then
        primeToggle = ''
    end
    
    local icon =''
    if(pName == 'Blueprint') then
        icon = Icon._Prime(String.titleCase(drop.Item), nil, iconSize)
    elseif iName == 'Kavasa Prime' then
        icon = Icon._Prime('Kavasa', nil,iconSize)
    else
        icon = Icon._Item(primeToggle..pName, "", iconSize)
    end
    
    return icon
end

--- Returns the item icon for a drop.
--  For example, "Braton Prime Barrel" returns [[File:PrimeBraton.png|38px]]
--  @function       p.getItemIconForDrop
--  @param          {string} drop Item name
--  @return         {string} Icon in the form of a wikitext link
function p.getItemIconForDrop(drop)
    local iName = p.getItemName(drop.Item)
    local pName = p.getPartName(drop.Part)
    local iconSize = '38'
    
    return Icon._Prime(String.titleCase(drop.Item), nil, iconSize)
end

--- Returns the relics in which the item is dropped from.
--  @function       p.item
--  @param          {string} item_type
--  @param          {string} item_part
--  @param          {string} relic_tier
--  @return         {string}
function p.item(frame)
    local item_type = frame.args[1]
    local item_part = frame.args[2]
    local relic_tier = frame.args[3]
    
    return p._item(item_type, item_part, relic_tier)
end

--- Returns the relics in which the item is dropped from.
--  @function       p._item
--  @param          {string} item_type
--  @param          {string} item_part
--  @param          {string} relic_tier
--  @return         {string}
function p._item(item_type, item_part, relic_tier)
    item_type = string.upper(item_type)
    item_part = string.upper(item_part)
    if (item_part == "HELMET BLUEPRINT") then
        item_part = "NEUROPTICS BLUEPRINT"
    end
    local locations = {}
    local vaultLocations = {}
    local i
    for i, relic in pairs(VoidData["Relics"]) do
        if (relic_tier == nil or relic.Tier == relic_tier) then
            local dropRarity = p.getRelicDropRarity(relic, item_type, item_part)
            if(dropRarity ~= nil) then
                local relicText = relic.Tier.." "..relic.Name
                local relicString = tooltipStart..relicText..tooltipCenter.."[["..relicText.."]]"..tooltipEnd.." "..dropRarity
                if(relic.IsVaulted == 1) then
                    relicString = relicString.." ([[Prime Vault|V]])"
                    table.insert(vaultLocations, relicString)
                else
                    if(relic.IsBaro == 1) then
                        relicString = relicString.." ([[Baro Ki%27Teer|B]])"
                    end
                    table.insert(locations, relicString)
                end
            end
        end
    end
    
    for _, i in pairs(vaultLocations) do
        table.insert(locations, i)
    end
    return table.concat(locations, "<br/>")
end

--- Gets the drop table of a relic.
--  @function       p.getRelicDrop
--  @param          {string} relicName
--  @param          {string} rarity
--  @param          {number} number
--  @return         {string}
function p.getRelicDrop(frame)
    local relicName = frame.args ~= nil and frame.args[1] or nil
    local rarity = frame.args ~= nil and frame.args[2] or nil
    local number = frame.args ~= nil and frame.args[3] or nil
    -- The number of the drop defaults to 1 if not set
    if number == nil then 
        number = 1
    elseif type(number) == 'string' then
        -- If the argument is a string, force it into being a number
        number = tonumber(number)
    end
    
    -- Return an error if any arguments are missing
    if relicName == nil or relicName == '' then
        return "ERROR: Missing argument 'Relic Name'"
    elseif rarity == nil or rarity == '' then
        return "ERROR: Missing argument 'Rarity'"
    end
    
    local bits = Shared.splitString(relicName, ' ')

    local theRelic = p.getRelic(bits[1], bits[2])
    
    -- Return an error if the relic wasn't found
    if theRelic == nil then
        return "<strong style='color:red;'>ERROR: Invalid relic '"..relicName.."'</strong>"
    end
    
    local count = 0
    for i, drop in pairs(theRelic.Drops) do
        -- Loop through the drops to find drops of the chosen rarity
        if drop.Rarity == rarity then
            count = count + 1
            -- Once enough drops of the right kind have been found, return the icon + the item name
            if count == number then
                local iName = p.getItemName(drop.Item)
                local pName = p.getPartName(drop.Part, false)
                local icon = p.getItemIconForDrop(drop)
                
                return icon..' [['..iName..'|'..iName..' '..pName..']]'
            end
        end
    end

    -- If we got to here, there weren't enough drops of that rarity for this relic.
    return "ERROR: Only found "..count.." drops of "..rarity.." rarity for "..relicName
end

--- Gets the total number of relics in the game.
--  @function       p.getRelicTotal
--  @param[opt]     {string} frame.args Options for what relic types to include are
--                           "unvaulted", "vaulted", "baro", or nil
--  @return         {number} The total count of all relics
function p.getRelicTotal(frame)
    local total = 0
 
    if (Shared.contains(frame.args, "unvaulted")) then
        for _, relic in pairs(VoidData["Relics"]) do
            if (relic.IsVaulted == 0) then
                total = total + 1
            end
        end
    end
    if (Shared.contains(frame.args, "vaulted")) then
        for _, relic in pairs(VoidData["Relics"]) do
            if (relic.IsVaulted == 1) then
                total = total + 1
            end
        end
    end
    if (Shared.contains(frame.args, "baro")) then
        for _, relic in pairs(VoidData["Relics"]) do
            if (relic.IsBaro == 1) then
                total = total + 1
            end
        end
    end
    if (frame.args[1] == nil) then
        total = Shared.tableCount(VoidData["Relics"])
    end
 
    return total
end

local function relicData()
    --This is snatched from m:VoidByReward p.byReward
    local data = {}
 
    for _, relic in pairs(VoidData["Relics"]) do
        for i, drop in pairs(relic.Drops) do
            local newObj = {Tier = relic.Tier, Name = relic.Name, Rarity = drop.Rarity, IsVaulted = relic.IsVaulted == 1, IsBaro = relic.IsBaro == 1}
            if (data[drop.Item] == nil) then
                data[drop.Item] = {}
            end
            if(data[drop.Item][drop.Part] == nil) then
                data[drop.Item][drop.Part] = {}
            end
            table.insert(data[drop.Item][drop.Part], newObj)
        end
    end
 
    return data
end

local function checkData(data)
    if data == nil or type(data) ~= 'table' then
        local data = relicData()
        return data
    elseif type(data) == 'table' then
        return data
    end
end

local function getItemRarities(itemName, partName, data)
    local data = checkData(data)
    
    local rarities = {}
    itemName = string.upper(itemName)
    partName = string.upper(partName)
    
    for n, drop in Shared.skpairs(data[itemName][partName]) do
        rarities[drop.Rarity] = true
    end
    local brarities = {}
    for r in pairs(rarities) do table.insert(brarities,r) end
    
    --[[for rar, n in pairs(rarities) do
        mw.log(rar)
    end--]]
    
    return brarities
end

--- Gets the ducat value of a Prime part or blueprint.
--  @function       p.getDucatValue
--  @param          {string} itemName Prime item name
--  @param          {string} partName Part name
--  @return         {number} The ducat value of that Prime part/blueprint
function p.getDucatValue(frame)
    --T his is just for invoking p._getDucatValue on article pages.
    local itemName = frame.args ~= nil and frame.args[1] or nil
    local partName = frame.args ~= nil and frame.args[2] or nil
    
    if itemName == nil or itemName == '' then
        return 'Item name missing'
    elseif partName == nil or partName == '' then
        return 'Part name missing'
    end
    return p._getDucatValue(itemName, partName)
end

--- Gets the ducat value of a Prime part or blueprint.
--  @function       p._getDucatValue
--  @param          {string} itemName Prime item name
--  @param          {string} partName Part name
--  @param          {table} data Relic data
--  @return         {number} The ducat value of that Prime part/blueprint
function p._getDucatValue(itemName, partName, data)
    local rarities = getItemRarities(itemName, partName, data)
    
    local exceptions = {
            akstiletto={receiver=45},
            braton={stock=15,receiver=45},
            rubico={stock=45},
            saryn={['neuroptics blueprint']=45},
            soma={blueprint=15},
            --valkyr={['systems blueprint']=100},
        };
    
    if exceptions[string.lower(itemName)] ~= nil and exceptions[string.lower(itemName)][string.lower(partName)] ~= nil then
        return exceptions[string.lower(itemName)][string.lower(partName)]
    end
    
    return not rarities and -1
        or rarities[2] and (Shared.contains(rarities, 'Common') and 25 or Shared.contains(rarities, 'Rare') and 65 or rarities[3] and 25 )
        or ({Common=15,Uncommon=45,Rare=100})[rarities[1]]
end

--- Gets the total ducat value of all Prime parts and blueprints.
--  @function       p.getTotalDucats
--  @param[opt]     {string} tierName Tier name if want to filter by a specific relic tier
--  @return         {number} The total ducat value
function p.getTotalDucats(frame)
    local tierName = frame.args ~= nil and frame.args[1]
    local data = relicData()
    local totalItemCount = 0 --counting all items
    local withoutFormaCount = 0 --counting all items excluding forma
    local totalDucats = 0 --all, including duplicates, itemDucats
    local availableDucats = 0 --total ducats for items from available relics
    local availableItems = 0 --available items
    local availableItemsEF = 0 --available items excluding forma
    local vaultedDucats = 0 --total ducats for items from vaulted relics
    local vaultedItems = 0 --vaulted items
    local vaultedItemsEF = 0 --vaulted items excluding forma
    local result = ''
    
    for item, parts in Shared.skpairs(data) do
        for part, drops in Shared.skpairs(parts) do
            for n, drop in Shared.skpairs(drops) do
                if tierName == drop.Tier or tierName == nil then
                    if drop.IsVaulted then
                        vaultedItems = vaultedItems + 1
                    else
                        availableItems = availableItems + 1
                    end
                    
                    totalItemCount = totalItemCount + 1
                    if item ~= 'FORMA' then
                        local tempDucat =p._getDucatValue(item, part, data)
                        totalDucats = totalDucats + tempDucat
                        withoutFormaCount = withoutFormaCount + 1
                        if drop.IsVaulted then
                            vaultedDucats = vaultedDucats + tempDucat
                            vaultedItemsEF = vaultedItemsEF + 1
                        else
                            availableDucats = availableDucats + tempDucat
                            availableItemsEF = availableItemsEF + 1
                        end
                    end
                end
            end
        end
    end
    
    if tierName then
        result = "'''Average Ducats Value'''&#58; "..Icon._Item('Ducats').."'''"..Math.round((totalDucats / totalItemCount), 0.01).."''' ("..totalItemCount..' rewards with '..withoutFormaCount..' parts)'
        result = result.."<br>'''Available'''&#58; "..Icon._Item('Ducats').."'''"..Math.round((availableDucats/availableItems), 0.01).."''' ("..availableItems..' rewards with '..availableItemsEF..' parts)'
        result = result.." | '''Vaulted'''&#58; "..Icon._Item('Ducats').."'''"..Math.round((vaultedDucats/vaultedItems), 0.01).."''' ("..vaultedItems..' rewards with '..vaultedItemsEF..' parts)'
    else
        result = "'''Total Ducats Value'''&#58; "..Icon._Item('Ducats').."'''"..Math.formatnum(totalDucats).."''' ("..totalItemCount..' rewards with '..withoutFormaCount..' parts)'
        result = result.."<br>'''Available'''&#58; "..Icon._Item('Ducats').."'''"..Math.formatnum(availableDucats).."''' ("..availableItems..' rewards with '..availableItemsEF..' parts)'
        result = result.." | '''Vaulted'''&#58; "..Icon._Item('Ducats').."'''"..Math.formatnum(vaultedDucats).."''' ("..vaultedItems..' rewards with '..vaultedItemsEF..' parts)'
    end
    
    return result
end

local function ducatPriceRow(itemName, partName, tierName, data)
    local ducatValue = p._getDucatValue(itemName, partName, data)
    local sortValue = ''
    
    local function createRelicText(itemName, partName, tierName, data)
        itemName = string.upper(itemName)
        partName = string.upper(partName)
        
        local locations = {}
        local vaultLocations = {}
        for n, drop in Shared.skpairs(data[itemName][partName]) do
            if drop.Tier == tierName or tierName == nil then
                local dropRarity = drop.Rarity
                if dropRarity ~= nil then
                    local relicText = drop.Tier.." "..drop.Name
                    local relicString = tooltipStart..relicText..tooltipCenter.."[["..relicText.."]]"..tooltipEnd.." "..dropRarity
                    if drop.IsVaulted then
                        relicString = relicString.." ([[Prime Vault|V]])"
                        table.insert(vaultLocations, relicString)
                    else
                        if drop.IsBaro then
                            relicString = relicString.." ([[Baro Ki%27Teer|B]])"
                        end
                        table.insert(locations, relicString)
                    end
                end
            end
        end
        
        for _, i in pairs(vaultLocations) do
            table.insert(locations, i)
        end
        
        return table.concat(locations, "<br/>")
    end
        

    if itemName == nil or itemName == '' or partName == nil or partName == '' then
        return 'Please enter item and part names'
    end
    
    --first cell
    if partName == 'Blueprint' then
        sortValue = itemName..' _'..partName
    else
        sortValue = itemName..' '..partName
    end
    local cell1 = '\n|data-sort-value="'..sortValue..'"|'..Icon._Prime(itemName,partName)
    local cell2 = '\n|'..createRelicText(itemName, partName, tierName, data)
    local cell3 = '\n|data-sort-value="'..ducatValue..'"|'..Icon._Item('Ducats').."'''"..ducatValue.."'''\n|-"
    
    return cell1..cell2..cell3
end

--- Builds a table of all Prime parts, the relics they are in, and their ducat value
--  as seen https://warframe.fandom.com/wiki/Ducats/Prices/Lith
--  @function       p.ducatRelicList
--  @param[opt]     {string} tierName Tier name if want to filter by a specific relic tier
--  @param[opt]     {string} listMode If nil, displays only unvaulted item; if "All", displays all items, including vaulted ones
--  @return         {string} Wikitext of table
function p.ducatRelicList(frame)
    local data = relicData()
    local tierName = frame.args ~= nil and frame.args[1] or nil
    -- Adding switch to choose only vaulted or unvaulted items to show
    local listMode = frame.args ~= nil and frame.args[2] or 'ALL'
    listMode = string.upper(listMode)
    local itemList = {}
    local result = {}
    
    for item, parts in Shared.skpairs(data) do
        if item ~= 'FORMA' then
            for part, drops in Shared.skpairs(parts) do
                for i, drop in pairs(drops) do
                    if drop.Tier == tierName or tierName == nil then
                        local tempName = ''
                        if part == 'BLUEPRINT' then
                            tempName = Shared.titleCase(item..'<> '..part)
                        else
                            tempName = Shared.titleCase(item..'<>'..part)
                        end
                        if not Shared.contains(itemList, tempName) then
                            if listMode == 'VAULTED' then
                                if drop.isBaro or drop.IsVaulted then
                                    table.insert(itemList, tempName)
                                end
                            elseif listMode == 'UNVAULTED' then
                                if not drop.IsBaro and not drop.IsVaulted then
                                    table.insert(itemList, tempName)
                                end
                            else
                                table.insert(itemList, tempName)
                            end
                        end
                    end
                end
            end
        end
    end
    table.sort(itemList)
    
    for num, itm in pairs(itemList) do
        local item = Shared.splitString(itm, '<>')
        item[1] = Shared.trim(item[1])
        item[2] = Shared.trim(item[2])
        table.insert(result, (ducatPriceRow(item[1], item[2], tierName, data)))
    end
    return table.concat(result)
end

p.relicTooltip = function(frame) mw.log'Remove Void.relicTooltip call' return require [[Module:Tooltips/tip]] .Void (frame.args and frame.args[1] or frame) end

return p
Community content is available under CC-BY-SA unless otherwise noted.