Warframe日本語 Wiki
Advertisement

このモジュールについての説明文ページを モジュール:Void/doc に作成できます

--- '''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 M:Shared to those from M: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 Version = require [[Module:Version]]

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

local tooltipStart = '<span class="tooltip" data-param="'
local tooltipCenter = '" data-param2="Void">'
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)['Vaulted'] ~= nil
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 String.contains(result, 'の設計図') then
        result = string.gsub(result, 'の設計図', '')
    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.Vaulted ~= nil) 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
        error("ERROR: Missing argument 'Relic Name'")
    elseif rarity == nil or rarity == '' then
        error("ERROR: Missing argument 'Rarity'")
    end
    
    local bits = String.split(relicName, '%s')

    local theRelic = p.getRelic(bits[1], bits[2])
    
    -- Return an error if the relic wasn't found
    assert(theRelic ~= nil, "ERROR: Invalid relic "..relicName)
    
    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.
    error("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.Vaulted == nil) then
                total = total + 1
            end
        end
    end
    if (Shared.contains(frame.args, "vaulted")) then
        for _, relic in pairs(VoidData["Relics"]) do
            if (relic.Vaulted ~= nil) 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.Vaulted ~= nil, 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.Vaulted 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.Vaulted 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.Vaulted 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 = String.titleCase(item..'<> '..part)
                        else
                            tempName = String.titleCase(item..'<>'..part)
                        end
                        if not Shared.contains(itemList, tempName) then
                            if listMode == 'VAULTED' then
                                if drop.isBaro or drop.Vaulted then
                                    table.insert(itemList, tempName)
                                end
                            elseif listMode == 'UNVAULTED' then
                                if not drop.IsBaro and not drop.Vaulted 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 = String.split(itm, '<>')
        item[1] = String.trim(item[1])
        item[2] = String.trim(item[2])
        table.insert(result, (ducatPriceRow(item[1], item[2], tierName, data)))
    end
    return table.concat(result)
end

--- Builds relic infobox.
--	TODO: Figure out errors with _getVersionLink() and String.trim()
--	@function		p.buildRelicInfobox
--	@param			{table} frame
--	@return			{string} Wikitext of infobox
function p.buildRelicInfobox(frame)
	assert(frame and frame.args ~= nil, 'p.buildRelicInfobox(frame): empty frame arguments')
	local relicName = frame.args[1]
	
	local Relic = VoidData['RelicNames'][relicName]
	assert(Relic ~= nil, 'p.buildRelicInfobox(frame): "'..relicName..'" does not exist in [[Module:Void/data]]')
	
	local imageMap = {
		Lith = 'VoidProjectionsIronD.png',
		Meso = 'VoidProjectionsBronzeD.png',
		Neo  = 'VoidProjectionsSilverD.png',
		Axi  = 'VoidProjectionsGoldD.png',
		Requiem = 'RequiemR0.png'
	}
	
	local getRelicStatus = function(Relic) 
		if (Relic.isBaro == nil) then
			if (Relic.Vaulted == nil) then
				return '<div style="text-align:center;">{{text|green|Available}}</div>'
			else
				return '<div style="text-align:center;">{{text|red|Vaulted}}</div>[[Category:Vaulted]]'
			end
		else
			return '<div style="text-align:center;">[[Baro Ki\'Teer|{{text|blue|Baro Ki\'Teer Exclusive}}]]</div>[[Category:Removed]]'
		end
	end
			
	local infobox = [=[
<infobox>
    <title source="name"><default><span><b>%s</b></span></default></title>
    <image source="image"><default>%s</default></image>
	<group>
	    <header>General</header>
	    <data source="release-date">
	    	<label>Release date</label><default>%s</default>
    	</data>
	    <data source="vault-date">
	    	<label>Vault date</label><default>%s</default>
	    </data>
	    <data source="baro"><default>%s</default></data>
	</group>
</infobox>
]=]

	infobox = infobox:format(
		relicName,
		imageMap[Relic.Tier],
		Version._getVersionLink(Relic.Introduced),
		Version._getVersionLink(Relic.Vaulted),
		getRelicStatus(Relic)
	)
	
	mw.log(infobox)
	return frame:preprocess(infobox)
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
Advertisement