Editing Module:ItemData/navGive feedback
Jump to navigation
Jump to search
The edit can be undone.
Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
| Latest revision | Your text | ||
| Line 1: | Line 1: | ||
local p = {} | local p = {} | ||
local items_data = mw.loadJsonData("Data:ItemData.json") | local items_data = mw.loadJsonData("Data:ItemData.json") | ||
| Line 7: | Line 5: | ||
local util_module = require('Module:Utilities') | local util_module = require('Module:Utilities') | ||
-- | --exceptions if the link is different from the item name | ||
local linkOverrides = { | local linkOverrides = { | ||
["Bullet Lifesteal"] = "Bullet Lifesteal (item)", | ["Bullet Lifesteal"] = "Bullet Lifesteal (item)", | ||
| Line 13: | Line 11: | ||
} | } | ||
-- | --With debug_mode on, it outputs unprocessed wikitext | ||
--With debug_mode off/unspecified, it processes the wikitext | |||
-- With debug_mode | |||
local function process_debug_mode(wikitext, debug_mode) | local function process_debug_mode(wikitext, debug_mode) | ||
if debug_mode == 'true' then | |||
return wikitext | |||
elseif debug_mode == 'false' or debug_mode == nil then | |||
return mw.getCurrentFrame():preprocess(wikitext) | |||
else | |||
return "debug_mode must be 'true' or 'false'" | |||
end | |||
end | end | ||
-- Writes list of items of a certain slot within the min and max soul bounds | --Writes list of items of a certain slot within the min and max soul bounds | ||
-- Each item is wrapped and separated. For example of wrapping/separator, see | |||
-- get_item_nav_bulletpoints. 'sep' should not be combined with 'right_wrap', | |||
-- as the trailing separator should also be removed from the string | |||
-- filter_mode parameter: nil/"all", "exclude_street_brawl", or "street_brawl_only" | |||
local function write_wrapped_item_list(slot, min_souls, max_souls, template, sep, filter_mode) | local function write_wrapped_item_list(slot, min_souls, max_souls, template, sep, filter_mode) | ||
if slot ~= 'Weapon' and slot ~= 'Armor' and slot ~= 'Tech' then | if slot ~= 'Weapon' and slot ~= 'Armor' and slot ~= 'Tech' then | ||
| Line 59: | Line 37: | ||
if min_souls == nil or max_souls == nil then return 'Min/Max souls must be numerical' end | if min_souls == nil or max_souls == nil then return 'Min/Max souls must be numerical' end | ||
-- Normalize filter_mode to handle unset parameter | |||
filter_mode = filter_mode or "all" | filter_mode = filter_mode or "all" | ||
-- | -- Retrieve all items that fit the bounds and filter criteria | ||
local items = {} | local items = {} | ||
for item_key, item_data in pairs(items_data) do | |||
-- future proofing; Disabled will be renamed to IsDisabled soon | |||
for | local this_cost = tonumber(item_data["Cost"]) | ||
local | local this_slot = item_data["Slot"] | ||
local item_data | |||
-- Filter logic for Street Brawl items | |||
local is_street_brawl = item_data["StreetBrawl"] == true | local is_street_brawl = item_data["StreetBrawl"] == true | ||
local should_include = true | local should_include = true | ||
if filter_mode == "street_brawl_only" and not is_street_brawl then | if filter_mode == "street_brawl_only" and not is_street_brawl then | ||
should_include = false | should_include = false | ||
| Line 82: | Line 57: | ||
end | end | ||
if should_include and item_data["Name"] ~= nil and item_data["IsDisabled"] == false and this_cost ~= nil then | if should_include and item_data["Name"] ~= nil and item_data["IsDisabled"] == false and this_cost ~= nil and this_slot ~= nil then | ||
if this_cost >= min_souls and this_cost < max_souls then | if slot == this_slot and this_cost >= min_souls and this_cost < max_souls then | ||
local item_name_english = lang_module.get_string(item_key, "en") | local item_name_english = lang_module.get_string(item_key, "en") -- Get the English name | ||
local item_link = linkOverrides[item_name_english] or item_name_english | local item_link = linkOverrides[item_name_english] or item_name_english -- Use override link if available | ||
local item_name_local = lang_module.get_string(item_key, lang_code) | local lang_code = lang_module.get_lang_code() -- Get the language code from the subpage | ||
local item_name_local = lang_module.get_string(item_key, lang_code) -- Get the localized name | |||
-- Construct the template based on the type | |||
local item_template | local item_template | ||
if template == "ItemIcon" then | if template == "ItemIcon" then | ||
if lang_code == "en" then | if lang_code == "en" then | ||
item_template = "{{ItemIcon|" .. item_name_english .. " | -- For English pages, do not include lang or localized name | ||
item_template = "{{ItemIcon|" .. item_name_english .. "}}" | |||
else | else | ||
item_template = "{{ItemIcon|" .. item_name_english .. "|lang=" .. lang_code .. "|l1=" .. item_name_local .. " | -- For non-English pages, include lang and localized name | ||
item_template = "{{ItemIcon|" .. item_name_english .. "|lang=" .. lang_code .. "|l1=" .. item_name_local .. "}}" | |||
end | end | ||
elseif template == "ItemBox" then | elseif template == "ItemBox" then | ||
if lang_code == "en" then | if lang_code == "en" then | ||
if is_street_brawl then | -- For English pages, do not include item_loc or link | ||
item_template = "{{ItemBox|itemName=" .. item_name_english .. "|overrideLinkClick=" .. item_link .. "| | -- Display cost as "Legendary" for street brawl items | ||
if is_street_brawl == true then | |||
item_template = "{{ItemBox|itemName=" .. item_name_english .. "|overrideLinkClick=" .. item_link .. "|item_price=Legendary" .. "}}" | |||
else | else | ||
item_template = "{{ItemBox|itemName=" .. item_name_english .. "|overrideLinkClick=" .. item_link | item_template = "{{ItemBox|itemName=" .. item_name_english .. "|overrideLinkClick=" .. item_link .. "}}" | ||
end | end | ||
else | else | ||
local link_local = item_link .. "/" .. lang_code | -- For non-English pages, include item_loc and link | ||
if is_street_brawl then | local link_local = item_link .. "/" .. lang_code -- Add subpage for non-English languages | ||
item_template = "{{ItemBox|itemName=" .. item_name_english .. "|overrideLinkClick=" .. link_local .. "|item_price={{#invoke:Lang|get_string|Citadel_ItemDraft_Legendary}}" | if is_street_brawl == true then | ||
item_template = "{{ItemBox|itemName=" .. item_name_english .. "|overrideDisplayName=" .. item_name_local .. "|overrideLinkClick=" .. link_local .. | |||
"|item_price={{#invoke:Lang|get_string|Citadel_ItemDraft_Legendary}}" .. "}}" | |||
else | else | ||
item_template = "{{ItemBox|itemName=" .. item_name_english .. "|overrideDisplayName=" .. item_name_local .. "|overrideLinkClick=" .. link_local .. "}}" | |||
end | end | ||
end | end | ||
| Line 126: | Line 102: | ||
-- Order list alphabetically | -- Order list alphabetically | ||
table.sort(items) | table.sort(items) -- O(nlogn) | ||
-- | -- Add each item to output | ||
-- Each item is already wrapped in the template, so no need for additional wrapping | |||
local ret = table.concat(items, sep) | |||
return | return ret | ||
end | end | ||
-- for [[Template:Item Navbox]] | -- for [[Template:Item Navbox]] | ||
-- Supports filter parameter via frame.args["filter"] | |||
function p.get_item_nav_bulletpoints(slot, min_souls, max_souls, debug_mode, filter_mode) | function p.get_item_nav_bulletpoints(slot, min_souls, max_souls, debug_mode, filter_mode) | ||
-- Handle the case where it's called via #invoke (i.e., from wikitext) | |||
if type(slot) == "table" and slot.args then | if type(slot) == "table" and slot.args then | ||
local frame = slot | local frame = slot | ||
| Line 153: | Line 123: | ||
filter_mode = frame.args["filter"] | filter_mode = frame.args["filter"] | ||
end | end | ||
local item_list = write_wrapped_item_list(slot, min_souls, max_souls, "ItemIcon", | local sep = ' • ' | ||
local item_list = write_wrapped_item_list(slot, min_souls, max_souls, "ItemIcon", sep, filter_mode) | |||
return process_debug_mode(item_list, debug_mode) | return process_debug_mode(item_list, debug_mode) | ||
end | end | ||
-- for [[Template:Infobox ShopItems]] | -- for [[Template:Infobox ShopItems]] | ||
-- Supports filter parameter via frame.args["filter"] | |||
function p.get_item_nav_cards(slot, min_souls, max_souls, debug_mode, filter_mode) | function p.get_item_nav_cards(slot, min_souls, max_souls, debug_mode, filter_mode) | ||
-- Handle the case where it's called via #invoke (i.e., from wikitext) | |||
if type(slot) == "table" and slot.args then | if type(slot) == "table" and slot.args then | ||
local frame = slot | local frame = slot | ||
| Line 168: | Line 143: | ||
filter_mode = frame.args["filter"] | filter_mode = frame.args["filter"] | ||
end | end | ||
local item_list = write_wrapped_item_list(slot, min_souls, max_souls, "ItemBox", | local sep = ' ' | ||
local item_list = write_wrapped_item_list(slot, min_souls, max_souls, "ItemBox", sep, filter_mode) | |||
return process_debug_mode(item_list, debug_mode) | return process_debug_mode(item_list, debug_mode) | ||
end | end | ||
-- for [[Template:Item Navbox]] subgroup rows | -- for [[Template:Item Navbox]] subgroup rows | ||
-- Writes price tiers and appends Street Brawl section if items exist | |||
function p.write_item_slot_subgroup(frame) | function p.write_item_slot_subgroup(frame) | ||
local slot = frame.args[1] | |||
local type = frame.args[2] | |||
local debug_mode = frame.args['debug_mode'] | |||
local street_brawl_label = frame.args['street_brawl_label'] or '{{Legendary|{{#invoke:Lang|get_string|Citadel_ItemDraft_Legendary}}}}' | |||
if slot == nil then return "'slot' parameter is required" end | |||
-- Define base args | |||
local template_title = "Navbox subgroup" | |||
local template_args = { | |||
["groupstyle"] = "background-color:" .. util_module.get_slot_color(slot) .. ";width:10%;min-width:70px;border-radius: 8px 0 0 8px", | |||
["grouppadding"] = "5px", | |||
["listpadding"] = "0 0.25rem", | |||
} | |||
local soul_style = "font-size: 12px; text-shadow: 1px 1px rgba(0, 0, 0, 0.3);" | |||
local prices = generic_module.get_item_price_per_tier() | |||
local group_index = 1 | |||
for i, souls in ipairs(prices) do | |||
min_souls = souls | |||
--Skip 0 to i1 as no items cost less than 500 | |||
if min_souls ~= 0 then | |||
-- Determine upper bound for soul tier | |||
max_souls = prices[i+1] | |||
if max_souls == nil then | |||
max_souls = min_souls * 10 | |||
end | |||
-- Generate list for this price tier, excluding Street Brawl items | |||
local list | |||
if type=='get_item_nav_cards' then | |||
list = p.get_item_nav_cards(slot, min_souls, max_souls, debug_mode, "exclude_street_brawl") | |||
elseif type=='get_item_nav_bulletpoints' then | |||
list = p.get_item_nav_bulletpoints(slot, min_souls, max_souls, debug_mode, "exclude_street_brawl") | |||
else | |||
return "'type' should be get_item_nav_cards or get_item_nav_bulletpoints" | |||
end | |||
-- Only add the group if there are items in this tier | |||
if list and list ~= "" then | |||
template_args["group" .. group_index] = frame:expandTemplate{title="Souls", args={[1] = min_souls, ["Shadow"] = soul_style}} | |||
template_args["list" .. group_index] = list | |||
group_index = group_index + 1 | |||
end | |||
end | |||
end | |||
-- Add Street Brawl section at the bottom of the slot | |||
local sb_min = 0 | |||
local sb_max = 999999 | |||
local sb_list | |||
if type=='get_item_nav_cards' then | |||
sb_list = p.get_item_nav_cards(slot, sb_min, sb_max, debug_mode, "street_brawl_only") | |||
elseif type=='get_item_nav_bulletpoints' then | |||
sb_list = p.get_item_nav_bulletpoints(slot, sb_min, sb_max, debug_mode, "street_brawl_only") | |||
end | |||
-- Only add Street Brawl group if there are items for this slot | |||
if sb_list and sb_list ~= "" then | |||
-- Style the link to match other tier headers with white text inside the link to prevent visited link color | |||
local sb_style = "color:#98ffde; font-family:'Retail Demo', sans-serif; text-wrap: nowrap; text-shadow: 0px 0px 2px #2c312e, 1.3px 1.3px rgba(0, 0, 0, 0.2);padding:5px;" | |||
local sb_link_text = "[[Street Brawl{{if_lang}}|<span style=\"" .. sb_style .. "\"><b>" .. street_brawl_label .. "</b></span>]]" | |||
template_args["group" .. group_index] = frame:preprocess(sb_link_text) | |||
template_args["list" .. group_index] = sb_list | |||
end | |||
return frame:expandTemplate{title=template_title, args=template_args} | |||
end | end | ||
-- for [[Template:Active Items]] | -- for [[Template:Active Items]] | ||
function p.generate_active_items_table(frame) | function p.generate_active_items_table(frame) | ||
local active_items = {} | local active_items = {} | ||
-- 1. Collect active items and their cost | |||
for item_key, item_data in pairs(items_data) do | for item_key, item_data in pairs(items_data) do | ||
-- Convert cost to a number; will be nil if the JSON value is null or missing | |||
local cost = tonumber(item_data["Cost"]) | local cost = tonumber(item_data["Cost"]) | ||
if item_data["Name"] and | if item_data["Name"] and | ||
item_data["IsDisabled"] == false and | item_data["IsDisabled"] == false and | ||
cost ~= nil and cost > 0 and | cost ~= nil and cost > 0 and -- FILTER: Must have a cost greater than 0 | ||
item_data["Activation"] and | item_data["Activation"] and | ||
item_data["Activation"] ~= "Passive" then | item_data["Activation"] ~= "Passive" then | ||
table.insert(active_items, { | table.insert(active_items, { | ||
| Line 303: | Line 246: | ||
cost = cost, | cost = cost, | ||
slot = item_data["Slot"] or "Weapon", | slot = item_data["Slot"] or "Weapon", | ||
has_active_desc = item_data["ActiveDescription"] ~= nil | has_active_desc = item_data["ActiveDescription"] ~= nil | ||
}) | }) | ||
end | end | ||
end | end | ||
-- 2. Sort by name | |||
table.sort(active_items, function(a, b) return a.name < b.name end) | table.sort(active_items, function(a, b) return a.name < b.name end) | ||
-- | -- 3. Generate wiki markup | ||
local | local wikitext = [=[ | ||
{| class="wikitable sortable" style="width:100%" | |||
|+{{#invoke:Dictionary|translate|Active Items}} | |+{{#invoke:Dictionary|translate|Active Items}} | ||
! colspan="2" | {{#invoke:Lang|get_string|Citadel_HeroBuilds_CategoryNameLabel}} | ! colspan="2" | {{#invoke:Lang|get_string|Citadel_HeroBuilds_CategoryNameLabel}} | ||
| Line 323: | Line 263: | ||
! {{#invoke:Lang|get_string|Citadel_Mod_Tooltip_Active}} | ! {{#invoke:Lang|get_string|Citadel_Mod_Tooltip_Active}} | ||
! {{#invoke:Lang|get_string|AbilityCooldown_label}} | ! {{#invoke:Lang|get_string|AbilityCooldown_label}} | ||
]=] | |||
-- 4. Add rows for each item | |||
for _, item in ipairs(active_items) do | for _, item in ipairs(active_items) do | ||
-- Determine background color and item type | |||
local bg_color, item_type | |||
if item.slot == "Armor" then | |||
bg_color = "#86C921" | |||
item_type = "Armor" | |||
elseif item.slot == "Tech" then | |||
bg_color = "#DE9CFF" | |||
item_type = "Tech" | |||
else | |||
bg_color = "#FCAC4D" | |||
item_type = "Weapon" | |||
end | |||
-- The cost cell uses 'data-sort-value' to provide a clean number for the client-side sorter, | |||
-- while the cell's visible content is formatted by the {{Souls}} template. | |||
wikitext = wikitext .. "\n" .. string.format([=[ | |||
|- | |- | ||
! style="background-color:%s" | [[File:%s.png|64x64px]] | ! style="background-color:%s" | [[File:%s.png|64x64px]] | ||
| Line 345: | Line 289: | ||
| data-sort-value="%d" style="text-align:center;font-size:15px" | {{Souls|%d}} | | data-sort-value="%d" style="text-align:center;font-size:15px" | {{Souls|%d}} | ||
| {{#invoke:Utilities|process_variables|%s_active_desc|%s}}{{#invoke:Utilities|process_variables|%s_desc|%s}}{{#invoke:Utilities|process_variables|%s_active|%s}} | | {{#invoke:Utilities|process_variables|%s_active_desc|%s}}{{#invoke:Utilities|process_variables|%s_desc|%s}}{{#invoke:Utilities|process_variables|%s_active|%s}} | ||
%s | | style="text-align:center;font-size:16px" | {{#invoke:ItemData|get_prop|%s|AbilityCooldown}}s | ||
]=], | |||
bg_color, | bg_color, | ||
item.name, | item.name, | ||
| Line 354: | Line 297: | ||
item.cost, item.cost, | item.cost, item.cost, | ||
item.key, item.name, item.key, item.name, item.key, item.name, | item.key, item.name, item.key, item.name, item.key, item.name, | ||
item.name) | |||
end | end | ||
wikitext = wikitext .. "\n|}" | |||
return | |||
return frame:preprocess(wikitext) | |||
end | end | ||
return p | return p | ||