Module:Attributes

-- Build racial attribute tables local Utils = require("Module:Utils") local mw = mw

local sprintf = Utils.sprintf local upper = Utils.upper local flatten = Utils.flatten

-- --- MODULE DATA -- -- -- -- indexes to race family table local HUMANS = 1 local HUMAN_IDXS = {HUMANS}

local CHADRA = 2 local UDOADRA = 3 local NHEEDRA = 4 local ERWYDRA = 5 local BEASTMEN_IDXS = {CHADRA, UDOADRA, NHEEDRA, ERWYDRA}

local BLOOD = 6 local SHADOW = 7 local HELLFIRE = 8 local DEMON_IDXS = {BLOOD, SHADOW, HELLFIRE}

local race_idxs = flatten({HUMAN_IDXS, BEASTMEN_IDXS, DEMON_IDXS})

local valid_args = { ["HUMANS"] = HUMAN_IDXS, ["HUMAN"] = HUMAN_IDXS, ["BEASTMEN"] = BEASTMEN_IDXS, ["BEASTMAN"] = BEASTMEN_IDXS, ["DEMONS"] = DEMON_IDXS, ["DEMON"] = DEMON_IDXS, ["CHADRA"] = CHADRA, ["UDOADRA"] = UDOADRA, ["NHEEDRA"] = NHEEDRA, ["ERWYDRA"] = ERWYDRA, ["BLOOD"] = BLOOD, ["SHADOW"] = SHADOW, ["HELLFIRE"] = HELLFIRE }

-- indexes to race attribute data local STR = 1 local DEX = 2 local INT = 3 local CON = 4 local PER = 5 local CHA = 6 local CPS = 7 -- creation points local AFF = 8 -- affinity

local attributes = {"STR", "DEX", "INT", "CON", "PER", "CHA", "POINTS"}

local race_attributes = { -- HUMANS {0, 0, 0, 0, 0, 0, 120, nil}, -- all -- BEASTMEN {1, 3, -1, 0, 0, 0, 100, DEX}, -- chadra {-1, 0, -2, 0, 1, 3, 100, CHA}, -- udoadra {2, -2, 0, 3, 0, -2, 100, CON}, -- nheedra {-3, 0, 3, -2, 2, 1, 100, INT}, -- erwydra -- DEMONS {0, -1, 3, -3, 0, 3, 100, CHA}, -- blood {1, 2, 0, -2, 3, 0, 100, PER}, -- shadow {3, 0, -3, 3, -2, -3, 100, STR} -- hellfire }

local MAX_ATTRIBUTE_VALUE = 21 local MIN_ATTRIBUTE_VALUE = 6

-- indexes to attribute table local COST_NORMAL = 1 local COST_AFFINITY = 2

-- regular attribute cost and affinity attribute cost per level local attribute_costs = { nil, nil, nil, nil, nil, {0, 0},   {3, 2}, {3, 2},    {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},    {3, 2}, {3, 2},    {4, 3}, {4, 3}, {4, 3}, {4, 3} }

-- table colors local affinity_color = "lightblue" local penalty_color = "red" local bonus_color = "lightgreen" local fmt_attr_td_style = "background-color:%s;color:black"

local family_tbl_headers = { "HUMANS", "CHADRA", "UDOADRA", "NHEEDRA", "ERWYDRA", "BLOOD", "SHADOW", "HELLFIRE", }

-- ----- MODULE FUNCTIONS --- -- local p = require("Module:BaseModule"):newModule

local main_args = { parentFirst = true, wrappers = { "Template/Attributes" } }

p.main = p:makeInvokeFunc("_main", main_args)

-- ---- INTERNAL FUNCTIONS -- -- -- -- Table with all races and families local function attribute_tbl -- Build table depending on contents of race_idxs and race_attributes. As these are -- declared outside this function, they can be manipulated by the race and family -- functions. It's done this way to create the same table design regardless of what -- content is requested. local have_humans_header = false local have_beastman_header = false local have_demons_header = false

local tbl = mw.html.create("table") :addClass("wikitable") :cssText("text-align: center")

-- Build race header row local race_header = tbl :tag("tr") :cssText("font-size: 115%") :tag("th"):done

for _, idx in ipairs(race_idxs) do       if idx == HUMANS then race_header:tag("th"):done have_humans_header = true

elseif have_beastman_header == false and idx >= CHADRA and idx <= ERWYDRA then race_header :tag("th") :attr("colspan", #BEASTMEN_IDXS) :wikitext("Beastmen") :done

have_beastman_header = true

elseif have_demons_header == false and idx >= BLOOD and idx <= HELLFIRE then race_header :tag("th") :attr("colspan", #DEMON_IDXS) :wikitext("Demons") :done

have_demons_header = true end end race_header:done

-- Build family header row local family_header = tbl :tag("tr") :cssText("font-size: 90%") :tag("th"):done

for _, idx in ipairs(race_idxs) do       family_header:tag("th") :cssText("padding: 2px 8px") :wikitext(family_tbl_headers[idx]) :done end family_header:done

-- Build attributes for table body local tr   for idx, attr in ipairs(attributes) do        tr = tbl :tag("tr") :tag("td") :wikitext(sprintf("%s", attr)) :done

for ra_idx, race_attrs in ipairs(race_attributes) do           local td = tr:tag("td")

if race_attrs[idx] == 0 then td:wikitext("-") else if race_attrs[idx] < 0 then td                       :cssText(sprintf(fmt_attr_td_style, penalty_color)) :wikitext(race_attrs[idx]) else if race_attrs[AFF] == idx then td                           :cssText(sprintf(fmt_attr_td_style, affinity_color)) :wikitext("+" .. race_attrs[idx]) else if CPS == idx then -- only highlight first points if the table has humans in it as                           -- they're the only ones who get the bonus if have_humans_header == true and ra_idx == 1 then td                               :cssText(sprintf(fmt_attr_td_style, bonus_color)) :wikitext(race_attrs[idx]) else td:wikitext(race_attrs[idx]) end else td                               :cssText(sprintf(fmt_attr_td_style, bonus_color)) :wikitext("+" .. race_attrs[idx]) end end end end

td:done end

tr:done end

return tbl:allDone end

-- Table with race and all race families -- Called as local function race_tbl(race) --luacheck: ignore local attr_tbl = {} race_idxs = race

for idx, ra_idx in ipairs(race_idxs) do       attr_tbl[idx] = race_attributes[ra_idx] end

race_attributes = attr_tbl

return attribute_tbl end

-- Table with specific race family -- Called as local function family_tbl(race, family) --luacheck: ignore local attr_tbl = {}

if race == HUMAN_IDXS then race_idxs = race else race_idxs = {family} end

for idx, ra_idx in ipairs(race_idxs) do       attr_tbl[idx] = race_attributes[ra_idx] end

race_attributes = attr_tbl

return attribute_tbl

end

-- -- PAGE FUNCTIONS -- function p._main(args, frame) --luacheck: ignore local race local family local tbl

if args ~= nil then race = valid_args[upper(args[1])] family = valid_args[upper(args[2])] end

if race == nil then tbl = attribute_tbl else if family == nil then tbl = race_tbl(race) else tbl = family_tbl(race, family) end end

return tostring(tbl) end

-- Build table depicting attribute points cost when creating characters function p.cost_table(frame) -- luacheck: ignore local normal_cumulative_cost = 0 local affinity_cumulative_cost = 0

local tbl = mw.html.create("table") :addClass("wikitable") :cssText("text-align: center") :tag("tr") :tag("th") :wikitext("ATTRIBUTE SCORE") :done :tag("th") :wikitext("ATTRIBUTE COST") :done :tag("th") :wikitext("CUMULATIVE COST") :done :tag("th") :wikitext("AFFINITY COST") :done :tag("th") :wikitext("CUMULATIVE COST WITH AFFINITY") :done :tag("th") :wikitext("POINTS SAVED WITH AFFINITY") :done :done local trs = {nil, nil, nil, nil, nil} local attr_cost, aff_cost, affinity_saved

for score = MIN_ATTRIBUTE_VALUE, MAX_ATTRIBUTE_VALUE do       attr_cost = attribute_costs[score][COST_NORMAL] aff_cost = attribute_costs[score][COST_AFFINITY]

normal_cumulative_cost = normal_cumulative_cost + attr_cost affinity_cumulative_cost = affinity_cumulative_cost + aff_cost affinity_saved = normal_cumulative_cost - affinity_cumulative_cost

local tr = mw.html.create("tr")

if score == 10 or score == 18 then tr:cssText("background-color:orange; font-weight:bold") end

tr           :tag("td") :wikitext(score) :done :tag("td") :wikitext(attr_cost) :done :tag("td") :wikitext(normal_cumulative_cost) :done :tag("td") :wikitext(aff_cost) :done :tag("td") :wikitext(affinity_cumulative_cost) :done :tag("td") :wikitext(affinity_saved) :done :done

trs[score] = tr   end

for i = MAX_ATTRIBUTE_VALUE, MIN_ATTRIBUTE_VALUE, -1 do       tbl:node(trs[i]) end

return tostring(tbl:allDone) end

return p