Module:Resource
Jump to navigation
Jump to search
This module handles displaying resource costs. It can:
- Handle multiple resources at once. The input is a comma separated list of resource names.
- Handle auto-categorisation for actions based on resource consumption via the
categories
function. This is not done implicitly so page generators must call this additional function. - Display in multiple formats suitable for inline usage or for compact table columns.
Parameters
Parameter | Meaning |
---|---|
Unnamed parameter | A comma separated list of resources with an optional count parameter separated by : List → Term | Term, Term |
force plural
|
Boolean flag to force icon names to always use their plural forms. Default is no. |
icons only
|
Boolean flag to show only the icon names. Full resource names are visible in hover-over tooltips. Default is no. |
show links
|
Boolean flag to make resource names into links to the appropriate pages. Default is no. |
icon size
|
Adjust the size of the resource icons. Default is 20 and for inline text, larger icons should not be used. |
Resource types
The available resource types are as follows:
Resource | Name and aliases |
---|---|
![]() | action |
![]() | bonus , ba , bonus action |
![]() | reaction |
![]() | movement , movement m , m |
![]() | half movement , 1/2 movement |
![]() | spell1 , s1 , level1 , l1 |
![]() | spell2 , s2 , level2 , l2 |
![]() | spell3 , s3 , level3 , l3 |
![]() | spell4 , s4 , level4 , l4 |
![]() | spell5 , s5 , level5 , l5 |
![]() | spell6 , s6 , level6 , l6 |
![]() | arcarr , aa , arcane arrow |
![]() | arcrec , ar , arcane recovery |
![]() | bi , bardin , bardic inspiration |
![]() | bladesong , bs , bsp , bladesong power |
![]() | cd , chadiv , channel divinity |
![]() | co , oath , chao , chaoat , channel oath |
![]() | cos , cosmic , omen , cosmic omen |
![]() | es , eyestalk , eyestalk action |
![]() | fi , fnginf , fungal infestation |
![]() | ki |
![]() | loh , lh , layonh , lay on hands |
![]() | luck , lp , lukpnt , luck point |
![]() | natrec , nr , natural recovery |
![]() | rage , rg |
![]() | shadowspell3 , shadow spell , ss3 , shadowlevel3 , sl3 |
![]() | sp , srcpnt , sorcery , sorcery point |
![]() | starmap , sm , star map |
![]() | supdie , sd , superiority die |
![]() | toc , tides , tides of chaos |
![]() | wc , writhing , writhing current |
![]() | ws , wldshp , wildshape , wild shape |
![]() | wp , warpri , war priest |
Examples
Example | Markup | Renders as |
---|---|---|
Basic usage | {{#invoke: Resource | main | action}} | ![]() |
Optional count specified | {{#invoke: Resource | main | ki:3 }} | ![]() |
Multiple resources | {{#invoke: Resource | main | action, bonus, spell1}} | ![]() ![]() ![]() |
Movement speed | {{#invoke: Resource | main | bonus, m:3 }} | ![]() ![]() |
Icons only | {{#invoke: Resource | main | action, bonus, spell1 | format = icons only }} | ![]() ![]() ![]() |
local getArgs = require("Module:Arguments").getArgs
local p = {}
-- Non-breaking thin space character
local nbts = " "
-- Table of reaction resources
-- Required values
-- name: Formatted wikitext to display for this reaction
-- icon: Icon file associated with the resource
-- Optional values:
-- plural: If the plural form of the resource name is not just appending "s" to the end, specify it here
-- aliases: Any additional aliases that can be used to refer to this resource
-- category: Category for actions that consume this resource
-- cropping: Crop this percentage from each side of the icon. This is for icons with excessive whitespace
local resources = {
-- Common resources
{
aliases = {"action"},
name = "Action",
link = "Actions#Resources",
icon = "Action Icon.png",
cropping = 15,
category = "Actions"
},
{
aliases = {"bonus", "ba", "bonus action"},
name = "Bonus Action",
link = "Actions#Resources",
icon = "Bonus Action Icon.png",
cropping = 15,
category = "Bonus actions"
},
{
aliases = {"reaction"},
name = "Reaction",
link = "Actions#Reactions",
icon = "Reaction Icon.png",
cropping = 15,
category = "Reactions"
},
{
aliases = {"movement", "movement m", "m"},
name = "Movement Speed",
plural = "Movement Speed",
link = "Resources#Movement speed",
icon = "Movement Speed Icon.png",
cropping = 15,
category = "Movement-expending actions"
},
{
aliases = {"half movement", "1/2 movement"},
name = "Movement Speed (Half cost)",
plural = "Movement Speed (Half cost)",
link = "Resources#Movement speed",
icon = "Movement Speed Icon.png",
cropping = 15,
category = "Movement-expending actions"
},
{
aliases = {"spell1", "s1", "level1", "l1"},
name = "Level 1 Spell Slot",
link = "Spells#Spell slots",
icon = "Spell Slot Icon.png",
},
{
aliases = {"spell2", "s2", "level2", "l2"},
name = "Level 2 Spell Slot",
link = "Spells#Spell slots",
icon = "Spell Slot Icon.png",
},
{
aliases = {"spell3", "s3", "level3", "l3"},
name = "Level 3 Spell Slot",
link = "Spells#Spell slots",
icon = "Spell Slot Icon.png",
},
{
aliases = {"spell4", "s4", "level4", "l4"},
name = "Level 4 Spell Slot",
link = "Spells#Spell slots",
icon = "Spell Slot Icon.png",
},
{
aliases = {"spell5", "s5", "level5", "l5"},
name = "Level 5 Spell Slot",
link = "Spells#Spell slots",
icon = "Spell Slot Icon.png",
},
{
aliases = {"spell6", "s6", "level6", "l6"},
name = "Level 6 Spell Slot",
link = "Spells#Spell slots",
icon = "Spell Slot Icon.png",
},
-- Class resources
{
aliases = {"arcarr", "aa", "arcane arrow"},
name = "Arcane Arrow",
link = "Arcane Archer#Arcane Arrow",
icon = "Arcane Arrow Resource Icon.png",
},
{
aliases = {"arcrec", "ar", "arcane recovery"},
name = "Arcane Recovery Charge",
link = "Arcane Recovery",
icon = "Arcane Recovery Charges Icons.png",
},
{
aliases = {"bi", "bardin", "bardic inspiration"},
name = "Bardic Inspiration Charge",
link = "Bard#Level 1",
icon = "Bardic Inspiration Resource Icon.png",
category = "Bardic Inspiration actions"
},
{
aliases = {"bladesong", "bs", "bsp", "bladesong power"},
name = "Bladesong Power",
plural = "Bladesong Power",
link = "Bladesinging#Level 2",
icon = "Bladesong Resource Icon.png",
},
{
aliases = {"cd", "chadiv", "channel divinity"},
name = "Channel Divinity Charge",
link = "Channel Divinity",
icon = "Channel Divinity Charges Icons.png",
category = "Channel Divinity actions",
},
{
aliases = {"co", "oath", "chao", "chaoat", "channel oath"},
name = "Channel Oath Charge",
link = "Channel Oath",
icon = "Channel Oath Icon.png",
category = "Channel Oath actions"
},
{
aliases = {"cos", "cosmic", "omen", "cosmic omen"},
name = "Cosmic Omen",
link = "Circle of the Stars#Level 6",
icon = "Cosmic Omen Resource Icon.png",
},
{
aliases = {"es", "eyestalk", "eyestalk action"},
name = "Eyestalk action",
link = "Spectator#Combat",
icon = "Eyestalk Action Icon.png",
},
{
aliases = {"fi", "fnginf", "fungal infestation"},
name = "Fungal Infestation Charge",
link = "Circle of the Spores#Level 6",
icon = "Fungal Infestation Charge Icon.png",
},
{
aliases = {"ki"},
name = "Ki Point",
icon = "Monk Ki Icon.png",
link = "Monk#Level 1",
category = "Ki actions"
},
{
aliases = {"loh", "lh", "layonh", "lay on hands"},
name = "Lay on Hands Charge",
link = "Paladin#Level 1",
icon = "Lay on Hands Resource Icon.png",
},
{
aliases = {"luck", "lp", "lukpnt", "luck point"},
name = "Luck Point",
link = "Lucky",
icon = "Luck Point Resource Icon.png",
},
{
aliases = {"natrec", "nr", "natural recovery"},
name = "Natural Recovery Charge",
link = "Natural Recovery",
icon = "Natural Recovery Charges Icon.png",
},
{
aliases = {"rage", "rg"},
name = "Rage Charge",
link = "Barbarian#Level 1",
icon = "Rage Charges Icons.png",
category = "Rage actions"
},
{
aliases = {"shadowspell3", "shadow spell", "ss3", "shadowlevel3", "sl3"},
name = "Level 3 Shadow Spell Slot",
link = "Permanent bonuses#Consumed Shadow Weave",
icon = "Shadow Spell Slot Icon.png",
},
{
aliases = {"sp", "srcpnt", "sorcery", "sorcery point"},
name = "Sorcery Point",
link = "Sorcerer#Level 2",
icon = "Sorcery Points Icons.png",
category = "Sorcery actions"
},
{
aliases = {"starmap", "sm", "star map"},
name = "Star Map",
link = "Circle of the Stars#Level 2",
icon = "Star Map Resource Icon.png",
},
{
aliases = {"supdie", "sd", "superiority die"},
name = "Superiority Die",
plural = "Superiority Dice",
link = "Battle Master#Level 3",
icon = "Superiority Die d8 Icon.png",
category = "Combat manoeuvres"
},
{
aliases = {"toc", "tides", "tides of chaos"},
name = "Tides of Chaos Charge",
link = "Tides of Chaos",
icon = "Tides of Chaos Resource Icon.png",
},
{
aliases = {"wc", "writhing", "writhing current"},
name = "Writhing Current",
link = "Swarmkeeper#Level 6",
icon = "Writhing Current Resource Icon.png",
},
{
aliases = {"ws", "wldshp", "wildshape", "wild shape"},
name = "Wild Shape Charge",
link = "Druid#Level 2",
icon = "Wild Shape Charges Icon.png",
category = "Wild Shape actions"
},
{
aliases = {"wp", "warpri", "war priest"},
name = "War Priest Charge",
link = "War Domain#Level 1",
icon = "War Priest Charges Icon.png",
},
}
local aliases = {}
local alias_warnings = {}
for idx, resource in ipairs(resources) do
for _, alias in ipairs(resource.aliases or {}) do
if aliases[alias] ~= nil then
table.insert(
alias_warnings,
string.format("Alias \"%s\" defined for \"%s\" and \"%s\".",
alias,
resources[aliases[alias]].name,
resource.name
)
)
end
aliases[alias] = idx
end
end
local function flag_is_set(args, flag)
-- Standardise string by trimming whitespace and converting to lowercase
local value = string.lower(string.match(args[flag] or "", "^%s*(.-)%s*$"))
return value == "y" or value == "yes" or value == "1" or value == "t" or value == "true"
end
local function get_resource(name)
-- Standardise string by trimming whitespace and converting to lowercase
local name = string.lower(string.match(name, "^%s*(.-)%s*$"))
return resources[aliases[name]] or {
name = "Unknown",
plural = "Unknown",
icon = "Alert Icon.png",
category = "Pages with unknown resources"
}
end
local function resource_icon(resource, args)
local size = args["icon size"] or 20
-- Image alt text should be blank unless _only_ the icon is displayed
-- If this not blank, copy-pasting or TextExtract of something like "costs an {{r|action}"
-- will give "costs an Action Icon.png action"
local alt = ""
if flag_is_set(args, "icons only") then
alt = resource.name
end
if resource.cropping then
-- Crop the icon. This is used for some icons which have large amounts of whitespace
return string.format(
"<span style=\"display: inline-block; height: %dpx; width: %dpx; margin-left: %dpx; margin-top: %dpx\">",
size,
size,
-size * (resource.cropping)/100,
-size * (resource.cropping)/100
) .. string.format(
"[[File:%s|link=|x%dpx|alt=%s|class=bg3wiki-icon]]",
resource.icon,
size * (100 + resource.cropping)/100,
alt,
resource.name
) .. "</span>"
else
return string.format(
"[[File:%s|link=|x%dpx|alt=%s|class=bg3wiki-icon]]",
resource.icon,
size,
alt,
resource.name
)
end
end
local function print_resource(resource, count, args)
local name = resource.name
local count = count:match("^%s*(.-)%s*$")
local count_num = tonumber(count)
if ((count ~= "") and (count_num ~= 1)) or flag_is_set(args, "force plural") then
name = resource.plural or resource.name .. "s"
end
if flag_is_set(args, "show links") and resource.link then
name = string.format("[[%s|%s]]", resource.link, name)
end
local amount = ""
-- Movement has a special format when count is specified. It is displayed is both m and ft
if count_num ~= nil and resource.name:find("Movement") ~= nil then
local m = count_num
if m >= 2 then
amount = string.format("%.0f%sm / %.0f%sft ", m, nbts, (m * 10)/3, nbts)
else
amount = string.format("%.1f%sm / %.0f%sft ", m, nbts, (m * 10)/3, nbts)
end
elseif count ~= "" and count_num ~= 1 then
amount = count .. " "
end
local icon = resource_icon(resource, args)
if flag_is_set(args, "icons only") then
local tooltip = string.format([[<span aria-label="%s">%s</span>]], resource.name, icon)
if count ~= "" and count_num ~= 1 and resource.name:find("Movement") == nil then
return count .. " " .. tooltip
else
return tooltip
end
else
return icon .. nbts .. amount .. name
end
end
-- Print the resource list
function p.main(frame)
local args = getArgs(frame)
local terms = args[1] or "Unknown"
local result = ""
-- Parse comma separated list of resource names
for term in terms:gmatch("[^,]+") do
-- Split on ":"" if the optional count is specified
local sep_idx = term:find(":") or 1000
local name = term:sub(0, sep_idx - 1)
local count = term:sub(sep_idx + 1, -1)
result = result .. print_resource(get_resource(name), count, args) .. " + "
end
result = result:sub(0, -9)
return result
end
-- Add a page to the relevant categories for actions that consume these resources
function p.categories(frame)
local args = getArgs(frame)
local terms = args[1]
if terms == nil or terms == "" then
return ""
end
local result = ""
-- Parse comma separated list of resource names
for term in terms:gmatch("[^,]+") do
-- Split on ":"" if the optional count is specified
local sep_idx = term:find(":") or 0
local name = term:sub(0, sep_idx - 1)
local category = get_resource(name).category
if category then
result = result .. string.format("[[Category:%s]]\n", category)
end
end
return result
end
-- Print a formatted list of all the resources for documentation pages
function p.resource_table(frame)
local args = getArgs(frame)
local result = ""
for _, warning in ipairs(alias_warnings) do
result = result .. frame:expandTemplate{
title = "Warning",
args = { warning }
} .. "<br>"
end
result = result .. [[<table class="wikitable">
<caption>List of resources</caption>
<tr>
<th>Resource</th>
<th>Name and aliases</th>
</tr>
]]
for _, resource in ipairs(resources) do
local names = ""
for _, alias in ipairs(resource.aliases or {}) do
names = names .. string.format("<code>%s</code>, ", alias)
end
names = names:sub(0,-3)
result = result .. string.format(
"<tr><td>%s</td><td>%s</td></tr>\n",
print_resource(resource, "", args),
names
)
end
result = result .. "</table>"
return result
end
return p