Module:Items

From The Walkscape Walkthrough

Get All Materials

{{#invoke:Items|outputItemTable|Materials}}

Creates the table on Materials

Get All Consumables

{{#invoke:Items|outputItemTable|Consumables}}
Name Type Skill(s) Attribute(s) Duration Note
Beer Alcohol, Beverage 1000 Steps
Saltrum Alcohol, Beverage 1000 Steps
Wine Alcohol, Beverage 1000 Steps
Chocolate Milk Beverage 1000 Steps
Spicy Pumpkin Juice Beverage 2000 Steps
Nettle Tea Beverage 1000 Steps
Cooked Shrimp Cooked Fish, Food 500 Steps
Cooked Jellyfish Cooked Fish, Food 500 Steps
Cooked Trout Cooked Fish, Food 500 Steps
Cooked Lobster Cooked Fish, Food 500 Steps
Cooked Perch Cooked Fish, Food 500 Steps
Cooked Stingray Cooked Fish, Food 500 Steps
Cooked Anglerfish Cooked Fish, Food 500 Steps
Cooked Pike Cooked Fish, Food 500 Steps
Cooked Salmon Cooked Fish, Food 500 Steps
Cooked Squid Cooked Fish, Food 500 Steps
Cooked Carp Cooked Fish, Food 500 Steps
Cooked Shark Cooked Fish, Food 500 Steps
Cooked Swordfish Cooked Fish, Food 500 Steps
Fried Noodles Food 2000 Steps
Sweet Carrot Pie Food 1000 Steps
Underwater Salad Food 1000 Steps
Pickles Food 1000 Steps
Trout Soup Food 1000 Steps
Kelp Rolls Food 1000 Steps
Mushroom Curry Food 1000 Steps
Porridge Food 1000 Steps
Veggie Soup Food 2000 Steps
Jarvonian Pastry Food 2000 Steps
Pancake Food 1000 Steps
Bread Food 1000 Steps
Salmon Pie Food 1000 Steps
Schnitzel Food 2000 Steps
Agility Memosphere Memosphere 2000 Steps Cannot Be Banked, Traded, Sold, or Dropped.
Carpentry Memosphere Memosphere 2000 Steps Cannot Be Banked, Traded, Sold, or Dropped.
Cooking Memosphere Memosphere 2000 Steps Cannot Be Banked, Traded, Sold, or Dropped.
Crafting Memosphere Memosphere 2000 Steps Cannot Be Banked, Traded, Sold, or Dropped.
Fishing Memosphere Memosphere 2000 Steps Cannot Be Banked, Traded, Sold, or Dropped.
Foraging Memosphere Memosphere 2000 Steps Cannot Be Banked, Traded, Sold, or Dropped.
Mining Memosphere Memosphere 2000 Steps Cannot Be Banked, Traded, Sold, or Dropped.
Smithing Memosphere Memosphere 2000 Steps Cannot Be Banked, Traded, Sold, or Dropped.
Woodcutting Memosphere Memosphere 2000 Steps Cannot Be Banked, Traded, Sold, or Dropped.
Bagel Sandwich, Food 1000 Steps
Jelly Sandwich Sandwich, Food 1000 Steps
Fried Fish Sandwich Sandwich, Food 1000 Steps
Bug Bait 2000 Steps
Frozen Bait 2000 Steps
Dynamite 1000 Steps

local p = {}

-- Helper function to load data by item type
local function loadDataByType(itemType)
    local pathMap = {
        Collectibles = 'Module:Items/Data/Collectibles',
        Consumables = 'Module:Items/Data/Consumables',
        Containers = 'Module:Items/Data/Containers',
        Crafted = 'Module:Items/Data/Crafted',
        Loot = 'Module:Items/Data/Loot',
        Materials = 'Module:Items/Data/Materials'
    }

    -- Load the correct data file based on the itemType
    local path = pathMap[itemType]
    if not path then
        return nil, "Invalid item type: " .. tostring(itemType)
    end

    local data = mw.loadJsonData(path)
    return data
end

-- Helper function to load the YAML data
local function loadYAMLData()
    local yamlData = mw.loadJsonData('Module:Items/YAML')
    return yamlData
end

-- Helper function to format strings in Proper Case, replace underscores with spaces, and add "Keyword" as a link
local function formatType(str)
    -- Skip keywords that start with "search"
    if mw.ustring.find(str:lower(), "^search") then
        return nil
    end

    -- Replace underscores with spaces
    str = mw.ustring.gsub(str, "_", " ")
    
    -- Insert space between lowercase and uppercase letters (for camelCase words)
    str = mw.ustring.gsub(str, "([a-z])([A-Z])", "%1 %2")
    
    -- Remove "Weight" from the start if it exists
    str = mw.ustring.gsub(str, "^weight ", "")

    -- Capitalize each word
    str = mw.ustring.gsub(str, "(%a)([%w_']*)", function(first, rest)
        return mw.ustring.upper(first) .. mw.ustring.lower(rest)
    end)

    -- Add "Keyword" as a link at the end
    return string.format("[[%s Keyword | %s]]", str, str)
end

-- Helper function to retrieve and format names from YAML
local function getNameFromYAML(namePath)
    local yamlData = loadYAMLData()

    -- Remove "items." prefix
    local path = mw.text.split(namePath, "%.")
    table.remove(path, 1)  -- Remove "items"

    -- Traverse the YAML hierarchy
    local result = yamlData
    for _, segment in ipairs(path) do
        result = result[segment]
        if not result then
            return namePath  -- Return the original path if name not found
        end
    end

    -- Return formatted result
    return mw.ustring.gsub(result, "(%a)([%w_']*)", function(first, rest)
        return mw.ustring.upper(first) .. mw.ustring.lower(rest)
    end)
end

-- Helper function to format the notes
local function formatNotes(item)
    local cannotBe = {}

    if item.canBeBanked == false then
        table.insert(cannotBe, "Banked")
    end
    if item.canBeTraded == false then
        table.insert(cannotBe, "Traded")
    end
    if item.canBeSold == false then
        table.insert(cannotBe, "Sold")
    end
    if item.canBeDropped == false then
        table.insert(cannotBe, "Dropped")
    end
    if item.canBeFine == false then
        table.insert(cannotBe, "Fine")
    end

    -- Combine the list into a single string
    local noteText = ""
    if #cannotBe > 0 then
        noteText = "Cannot Be " .. table.concat(cannotBe, ", ", 1, #cannotBe - 1) -- Insert commas between entries
        if #cannotBe > 1 then
            noteText = noteText .. ", or " .. cannotBe[#cannotBe] .. "." -- Add "or" before the last item and a period
        else
            noteText = noteText .. cannotBe[1] .. "." -- If only one item, just add it with a period
        end
    end

    return noteText
end

-- Function to extract data from metatables if necessary
local function extractData(tbl)
    local realTable = {}
    for k, v in pairs(tbl) do
        if type(v) == "table" then
            realTable[k] = extractData(v)
        else
            realTable[k] = v
        end
    end
    return realTable
end

-- Function to generate a MediaWiki sortable table for "Materials"
local function generateMaterialsTable(items)
    local tableData = {}

    for _, item in ipairs(items) do
        local namePath = item.name
        local name = getNameFromYAML(namePath)
        local image = string.format("[[File:%s.svg|frameless|32px]]", name)
        
        -- Keep the raw keywords for sorting
        local rawKeywords = item.keywords or {}
        local typeText = table.concat(rawKeywords, ", ")
        
        -- Format the notes using the helper function
        local noteText = formatNotes(item)
        
        -- Insert raw data for sorting, formatted data later
        table.insert(tableData, {
            image = image,
            name = "[[" .. name .. "]]",
            rawType = typeText,
            keywords = rawKeywords,
            note = noteText or "" -- Store the note for each item
        })
    end

    -- Sort table data: first by raw keyword (before formatting), then by name
    table.sort(tableData, function(a, b)
        if a.rawType == b.rawType then
            return a.name < b.name
        else
            return a.rawType < b.rawType
        end
    end)

    -- After sorting, apply formatting to keywords
    for _, row in ipairs(tableData) do
        if #row.keywords > 0 then
            local formattedKeywords = {}
            for _, keyword in ipairs(row.keywords) do
                table.insert(formattedKeywords, formatType(keyword))
            end
            row.type = table.concat(formattedKeywords, ", ")
        else
            row.type = ""
        end
    end

    -- Start the table
    local tableText = '{| class="wikitable sortable"\n'
    tableText = tableText .. '! colspan="2" | Name !! Type !! Note\n'

    -- Add rows
    for _, row in ipairs(tableData) do
        tableText = tableText .. '|-\n'
        tableText = tableText .. '| ' .. row.image .. ' || ' .. row.name .. ' || ' .. row.type .. ' || ' .. row.note .. '\n'
    end

    tableText = tableText .. '|}\n'
    return tableText
end

-- Function to generate a MediaWiki sortable table for "Consumables"
local function generateConsumablesTable(items)
    local tableData = {}

    for _, item in ipairs(items) do
        local namePath = item.name
        local name = getNameFromYAML(namePath)
        local image = string.format("[[File:%s.svg|frameless|32px]]", name)

        -- Keep the raw keywords for sorting
        local rawKeywords = item.keywords or {}
        local typeText = table.concat(rawKeywords, ", ")
        
        -- Format the notes using the helper function
        local noteText = formatNotes(item)

        -- Check for "buffs" array and "cooldown" object
        if item.buffs and #item.buffs > 0 then
            for _, buff in ipairs(item.buffs) do
                if buff.cooldown and buff.cooldown.steps then
                    -- Format the duration as " %d [File:Steps_icon.png|frameless] Steps"
                    duration = string.format("%d [[File:Steps_icon.png|frameless]] Steps", buff.cooldown.steps)
                    break  -- Use the first found cooldown steps and stop searching
                end
            end
        end

        -- Insert raw data for sorting, formatted data later
        table.insert(tableData, {
            image = image,
            name = "[[" .. name .. "]]",
            rawType = typeText,
            keywords = rawKeywords,
            skill = "", -- Placeholder for future Skill(s)
            attribute = "", -- Placeholder for future Attribute(s)
            duration = duration, -- Duration value
            note = noteText or "" -- Store the note for each item
        })
    end

    -- Sort table data: first by raw keyword (before formatting), then by name
    table.sort(tableData, function(a, b)
        if a.rawType == b.rawType then
            return a.name < b.name
        else
            return a.rawType < b.rawType
        end
    end)
    
    -- After sorting, apply formatting to keywords
    for _, row in ipairs(tableData) do
        if #row.keywords > 0 then
            local formattedKeywords = {}
            for _, keyword in ipairs(row.keywords) do
                table.insert(formattedKeywords, formatType(keyword))
            end
            row.type = table.concat(formattedKeywords, ", ")
        else
            row.type = ""
        end
    end
	
    -- Start the table with the new columns for Skill(s), Attribute(s), and Duration
    local tableText = '{| class="wikitable sortable"\n'
    tableText = tableText .. '! colspan="2" | Name !! Type !! Skill(s) !! Attribute(s) !! Duration !! Note\n'

    -- Add rows
    for _, row in ipairs(tableData) do
        tableText = tableText .. '|-\n'
        tableText = tableText .. '| ' .. row.image .. ' || ' .. row.name .. ' || ' .. row.type .. ' || ' .. row.skill .. ' || ' .. row.attribute .. ' || ' .. row.duration .. ' || ' .. row.note .. '\n'
    end

    tableText = tableText .. '|}\n'
    return tableText
end

-- Main function to handle different item types and output MediaWiki tables
function p.outputItemTable(frameOrType)
    -- Check if the first argument is a frame object
    local isFrame = type(frameOrType) == "table" and frameOrType.args ~= nil

    local itemType

    if isFrame then
        -- If it's a frame, get the type from the frame arguments
        itemType = frameOrType.args[1]
    else
        -- Otherwise, use the argument passed directly
        itemType = frameOrType
    end

    -- Load the data for the given item type
    local data, err = loadDataByType(itemType)
    if not data then
        return err
    end

    -- Extract actual data from metatables, if present
    data = extractData(data)

    -- Generate a table based on the item type
    if itemType == "Materials" then
        return generateMaterialsTable(data)
    elseif itemType == "Consumables" then
        return generateConsumablesTable(data)
    else
        return "Table structure for item type '" .. itemType .. "' not implemented yet."
    end
end

return p