Documentation for this module may be created at Module:Tooltip/Types/doc
This module holds the main functions of Module:Building, Module:Law, Module:Production method, and Module:Technology. This is done to avoid loops.
------------------------------------------------------------------------------
--
-- Module:Tooltip/Types
--
-- Due to interconnected nature of tooltips, they must be held in the same module to avoid circular loops
------------------------------------------------------------------------------
local iconify = require('Module:Iconify').iconify
local getArgs = require('Module:Arguments').getArgs
local ttUtils = require('Module:Tooltip')
local size = require('Module:TableTools').size
local uString = mw.ustring
local uFormat = uString.format
local htmlCreate = mw.html.create
-- set tooltip style, imitates in-game tooltips
local gameTT = 'color: #c2bdb8; background: linear-gradient(to bottom,#47373a,#211b1c); border: solid #b19656; border-radius: 10px; width: max-content; padding: 5px;'
local p = {};
function p.main(frame)
local args = getArgs(frame)
local func = args.func or nil
if type(p[func]) == 'function' then
return p[func](args)
else
return '<span style="color:red; font-size:11px;">(unrecognized function "' .. func .. '" for [[Module:Tooltip/Types]])</span>[[Category:Pages with unrecognized module functions]]'
end
end
function p.building(args)
local index = tonumber(args.index)
local buildID = uString.lower(args[1])
local buildData = mw.loadData('Module:Building/List')[buildID] --load building data
-- catch unknown/error
if not buildData then
return '<span style="color:red; font-size:11px;">(unrecognized building "' .. args[1] .. '" for [[Module:Building]])</span>[[Category:Pages with unrecognized buildings]]'
end
local loc = buildData.canLoc
if (args[1] ~= loc) and (args[1] ~= buildData.altLoc) then
args[1] = loc -- Don't use 'building_X' in display
end
local fromText = (args.from == 'pm') and 'Used by ' or ''
local icon = buildData.icon or "Building "..uString.lower(args[1])..".png"
-- set tooltip display as icon and text, short-circuit tooltip if out of index
local displayText = uFormat("%s[[File:%s|%s|link=List of buildings#%s|%s]] %s", fromText, icon, args.width or '24px', loc, args[1], args[1])
--local displayText = iconify{icon=args[1], group="building", image=icon, link="List of buildings#"..loc, mod=fromText, extra=args[1]}
if args.fromfrom == 'building' then index = 4 end
if type(index) ~= 'number' or index > 3 then -- any non number or index over 3 returns basic display
return args.from and ttUtils.tooltip(displayText) or displayText
end
-- set up header subtitle, with building basic info
local constr = uFormat([[%s <span title="Construction">Constr. '''%s'''</span>]], "[[File:State status construction.png|16px|link=Construction]]", buildData.cost)
local infra = uFormat([[%s <span title="Infrastructure">Infra. '''%s'''</span>]], "[[File:State status infrastructure.png|16px|link=Infrastructure]]", buildData.infra)
local urban = uFormat([[<span title="Urbanization">Urban. '''%s'''</span>]], buildData.urb)
local subtitle = uFormat("<span>%s | %s | %s</span>", constr, infra, urban)
-- start header with float left icon
local header = ttUtils.headerStyle('2LR', {
leftText=uFormat("[[File:%s|48px|link=List of buildings#%s|%s]]", icon, loc, loc),
--leftText=iconify{icon=loc, group="building", image=icon, width="48px", text=0, link="List of buildings#"..loc, extra=loc},
rightText=buildData.category,
mainText=loc,
subText=subtitle
})
-- start body with reqs and blockers
local body = '<hr>'
local reqs, notes
if buildData.reqs and size(buildData.reqs) > 0 then
reqs = '<div>Requires:' .. ttUtils.ttList(buildData.reqs, {index=(index + 1), from="building", fromfrom=args.from})..'</div>'
end
if buildData.notes and buildData.notes[1] then
notes = ''
for _, v in ipairs(buildData.notes) do
notes = uFormat("%s<div>%s</div>", notes, v)
end
notes = '<div>Additional info:<div style="display:grid; margin-left:1em;">' .. notes .. '</div></div>'
end
if reqs or notes then
reqs, notes = reqs or '', notes or ''
body = body .. '<div style="display:grid; grid-template-columns: auto auto; gap:5px;">' .. reqs .. notes .. '</div><hr>'
end
-- no recursive tooltips please
local pmIndex = index + 1
if args.from == "pm" then pmIndex = 4 end
-- continue tooltip for PMs, grid and flexbox to align them neatly
if buildData.pm and buildData.pm[1] then
body = body .. '<div style="display:grid; grid-template-columns: auto auto; gap:5px 10px;">'
for _,pmg in ipairs(buildData.pm) do
body = body .. '<div style="display:flex; flex-direction: column; align-items: flex-start">'
if pmg.group then
body = body .. tostring(htmlCreate('div'):cssText("color:white; font-weight:bold;"):wikitext(pmg.group))
end
for _,u in ipairs(pmg) do
body = body..p.productionMethod{u, index=pmIndex, from="building", fromfrom=args.from}
end
body = body .. '</div>'
end
body = body .. '</div>'
end
return ttUtils.tooltip(displayText, header, body, {style=gameTT, index=index})
end
function p.productionMethod(args)
local index = tonumber(args.index)
local pmID = uString.lower(args[1])
local pmData = mw.loadData('Module:Production method/List')[pmID] --load pm data
-- catch unknown/error
if not pmData then
return '<span style="color:red; font-size:11px;">(unrecognized production method "' .. args[1] .. '" for [[Module:Production method]])</span>[[Category:Pages with unrecognized production methods]]'
end
-- translate from game icon list to wiki icon list, could offload to data page
local icon = "Method "..pmData.icon..".png"
local loc = pmData.loc
-- set tooltip display as icon and text, short-circuit tooltip if out of index
local displayText = uFormat("[[File:%s|%s|link=List of production methods#%s|%s]] %s", icon, args.width or '24px', loc, loc, loc)
--local displayText = iconify{icon=loc, image=icon, link="List of production methods#"..loc, extra=loc}
if args.fromfrom == 'pm' then index = 4 end
if type(index) ~= 'number' or index > 3 then -- any non number or index over 3 returns basic display
if not args.from then
return displayText
else
return ttUtils.tooltip(displayText)
end
end
-- set up header subtitle, with building for pm, tooltip building if pm called directly
local subtitle = ''
if pmData.building == "Multiple" then
subtitle = "Used by multiple buildings"
elseif args.from ~= "building" then
subtitle = p.building{pmData.building, index=(index+1), from="pm", fromfrom=args.from}
else
subtitle = uFormat("Used by [[File:Building %s.png|24px|link=List of buildings#%s|%s]] %s", uString.lower(pmData.building), pmData.building, pmData.building, pmData.building)
--subtitle = iconify{icon=pmData.building, group="building", mod="Used by", link="List of buildings#"..pmData.building}
end
subtitle = '<span>' .. subtitle .. '</span>'
local header = ttUtils.headerStyle('2LR', {
leftText=uFormat("[[File:%s|48px|link=List of production methods#%s|%s]]", icon, loc, loc),
--leftText=iconify{icon=loc, image=icon, width="48px", text=0, link="List of production methods#"..loc, extra=loc},
rightText=pmData.group,
mainText=loc,
subText=subtitle
})
-- start body with reqs and blockers
local body = '<hr>'
local reqs, blockers
if pmData.reqs and size(pmData.reqs) > 0 then
reqs = '<div>Requires:' .. ttUtils.ttList(pmData.reqs, {index=(index + 1), from="pm", fromfrom=args.from})..'</div>'
end
if pmData.blockers and size(pmData.blockers) > 0 then
blockers = '<div>Blocked by:' .. ttUtils.ttList(pmData.blockers, {index=(index+1), from="pm", fromfrom=args.from}) .. '</div>'
end
if reqs or blockers then
reqs, blockers = reqs or '', blockers or ''
body = body .. '<div style="display:grid; grid-template-columns: auto auto; gap:5px;">' .. reqs .. blockers .. '</div><hr>'
end
local effects = ''
-- iterate effects
if pmData.input and pmData.input[1] then
effects = effects .. '<div>Input:<div style="margin-left:1em;">' .. ttUtils.effectList(pmData.input,{icon="Goods"}) .. '</div></div>'
end
if pmData.output and pmData.output[1] then
effects = effects .. '<div>Output:<div style="margin-left:1em;">' .. ttUtils.effectList(pmData.output,{icon="Goods"}) .. '</div></div>'
end
if pmData.workforce and pmData.workforce[1] then
effects = effects .. '<div>Workforce:<div style="margin-left:1em;">' .. ttUtils.effectList(pmData.workforce,{icon="pop",page="Profession"}) .. '</div></div>'
end
local modifiers = { ws = { }, ls = { }, us = { } }
local modList = ''
local function modConcat(t)
for k, _ in pairs(t) do
for _, v in ipairs(t[k]) do
table.insert(modifiers[k], v)
end
end
end
if pmData.bm then modConcat(pmData.bm) end
if pmData.sm then modConcat(pmData.sm) end
if pmData.cm then modConcat(pmData.cm) end
if modifiers.ws[1] then modList = modList..ttUtils.effectList(modifiers.ws) end
if modifiers.ls[1] then modList = modList..'<br>Level scaled<br>'..ttUtils.effectList(modifiers.ls) end
if modifiers.us[1] then modList = modList..'<br>Unscaled<br>'..ttUtils.effectList(modifiers.us) end
if modList ~= '' then
effects = effects .. '<div>Modifiers:<div style="margin-left:1em;">' .. modList .. '</div></div>'
end
if effects ~= '' then
body = body .. tostring(htmlCreate('div'):cssText("display:grid; grid-template-columns: auto auto; gap:5px 10px;"):wikitext(effects))
else
body = body .. "No effects"
end
return ttUtils.tooltip(displayText, header, body, {style=gameTT, index=index})
end
function p.tech(args)
local index = tonumber(args.index)
local techID = uString.lower(args[1])
local techData = mw.loadData('Module:Technology/List')[techID] --load pm data
-- catch unknown/error
if not techData then
return '<span style="color:red; font-size:11px;">(unrecognized technology "' .. args[1] .. '" for [[Module:Technology]])</span>[[Category:Pages with unrecognized technologies]]'
end
local loc = techData.loc
-- set tooltip display as icon and text, short-circuit tooltip if out of index
--local displayText = uFormat("[[File:Invention %s.png|%s|link=%s technology#%s|%s]] %s", uString.lower(loc), args.width or '24px', techData.category, loc, loc, loc)
local displayText = iconify{icon=loc, group="Invention", width=args.width or '24px', link=techData.category.." technology#"..loc, extra=loc} --[[File:Invention loc.png|24px|loc|link=cat tech#loc]]
if args.fromfrom == 'tech' then index = 4 end
if type(index) ~= 'number' or index > 3 then -- any non number or index over 3 returns basic display
if not args.from then
return displayText
else
return ttUtils.tooltip(displayText)
end
end
-- set up header subtitle, with building for pm, tooltip building if pm called directly
local cost = { "7,000", "10,000", "12,500", "15,000", "17,500" }
cost = uFormat("Base cost: [[File:Innovation.png|16px|link=Innovation]] '''%s'''", cost[techData.era])
local subtitle = uFormat("<span>Era: %s</span> | %s", techData.era, cost)
local header = ttUtils.headerStyle('2LR', {
--leftText=uFormat("[[File:Invention %s.png|48px|link=%s technology#%s|%s]]", uString.lower(loc), techData.category, loc, loc),
leftText=iconify{icon=loc, group="Invention", width="48px", text=0, link=techData.category.." technology#"..loc, extra=loc},
rightText=techData.category.." technology",
mainText=loc,
subText=subtitle
})
-- start body with reqs
local body = '<hr>'
if techData.reqs and techData.reqs[1] then
local reqText = "Requires:"
local reqList = {}
if techData.reqs[2] then reqText = "Requires all of:" end
for i, v in ipairs(techData.reqs) do
reqList[i] = p.tech{v, index=index+1, from="tech", fromfrom=args.from}
end
body = body .. tostring(htmlCreate('div'):wikitext(reqText)
:tag('div'):cssText('display:grid; justify-items: start; margin-left:1em;'):wikitext(table.concat(reqList)):done())..'<hr>'
--body = body .. reqText .. ttUtils.ttList(techData.reqs, {index=(index+1), from="tech", fromfrom=args.from, multiKey="All of"})
end
local effects = ''
if techData.unlocks and size(techData.unlocks) > 0 then
effects = effects .. '<div>Unlocks:' .. ttUtils.ttList(techData.unlocks,{index=(index+1), from="tech", fromfrom=args.from, multiKey=""}) .. '</div>'
end
if techData.modifiers and techData.modifiers[1] then
effects = effects .. '<div>Modifiers:<div style="margin-left:1em;">' .. ttUtils.effectList(techData.modifiers) .. '</div></div>'
end
if effects ~= '' then
body = body .. tostring(htmlCreate('div'):cssText("display:grid; grid-template-columns: auto auto; gap:5px 10px;"):wikitext(effects))
else
body = body .. "No effects"
end
if techData.desc then
body = body .. '<hr><div style="font-size:smaller; font-style:italic; line-height:1.2em; max-width:350px">' .. techData.desc .. '</div>'
end
return ttUtils.tooltip(displayText, header, body, {style=gameTT, index=index})
end
function p.law(args)
local index = tonumber(args.index)
local lawID = uString.lower(args[1])
local lawData = mw.loadData('Module:Law/List')[lawID] --load pm data
-- catch unknown/error
if not lawData then
return '<span style="color:red; font-size:11px;">(unrecognized law "' .. args[1] .. '" for [[Module:Law]])</span>[[Category:Pages with unrecognized laws]]'
end
local loc = lawData.loc
-- set tooltip display as icon and text, short-circuit tooltip if out of index
--local displayText = uFormat("[[File:Law %s.png|%s|link=%s#%s|%s]] %s", uString.lower(loc), args.width or '24px', lawData.category, loc, loc, loc)
local displayText = iconify{icon=loc, group="Law", width=args.width or '24px', link=uString.lower(lawData.category).."#"..loc, extra=loc}
if args.fromfrom == 'law' then index = 4 end
if type(index) ~= 'number' or index > 3 then -- any non number or index over 3 returns basic display
if not args.from then
return displayText
else
return ttUtils.tooltip(displayText)
end
end
-- set up header subtitle, with building for pm, tooltip building if pm called directly
subtitle = '<span>Law group: ' .. lawData.group .. '</span>'
local header = ttUtils.headerStyle('2LR', {
--leftText=uFormat("[[File:Law %s.png|48px|link=%s#%s|%s]]", uString.lower(loc), lawData.category, loc, loc),
leftText=iconify{icon=loc, group="Law", width="48px", text=0, link=uString.lower(lawData.category).."#"..loc, extra=loc},
rightText=lawData.category,
mainText=loc,
subText=subtitle
})
-- start body with reqs and blockers
local body = '<hr>'
local reqs, blockers
if lawData.reqs and size(lawData.reqs) > 0 then
reqs = '<div>Requires:' .. ttUtils.ttList(lawData.reqs, {index=(index + 1), from="law", fromfrom=args.from})..'</div>'
end
if lawData.blockers and size(lawData.blockers) > 0 then
blockers = '<div>Blocked by:' .. ttUtils.ttList(lawData.blockers, {index=(index+1), from="law", fromfrom=args.from}) .. '</div>'
end
if reqs or blockers then
reqs, blockers = reqs or '', blockers or ''
body = body .. '<div style="display:grid; grid-template-columns: auto auto; gap:5px;">' .. reqs .. blockers .. '</div><hr>'
end
local effects = ''
-- iterate effects
if lawData.effects and lawData.effects[1] then
effects = effects .. '<div>Effects:<div style="margin-left:1em;">' .. ttUtils.effectList(lawData.effects) .. '</div></div>'
end
if lawData.enact and lawData.enact[1] then
effects = effects .. '<hr><div>When enacted:<div style="margin-left:1em;">' .. ttUtils.effectList(lawData.enact) .. '</div></div>'
end
if effects ~= '' then
body = body .. tostring(htmlCreate('div'):wikitext(effects))
else
body = body .. "No effects"
end
if lawData.desc then
body = body .. '<hr><div style="font-size:smaller; font-style:italic; line-height:1.2em; max-width:350px">' .. lawData.desc .. '</div>'
end
return ttUtils.tooltip(displayText, header, body, {style=gameTT, index=index})
end
return p