Module:ItemEffects
From Fallen London Wiki
Documentation for this module may be created at Module:ItemEffects/doc
local p = {}
--[[
Table of contents
- 10-25 Universal stuff for both
- 27-278 Item page effect display and BiS message calculations
- 280- Item Effects template functions
--]]
-- Menaces only need to be added here if they appear as an equipment's effect in an increases/reduces way.
menaces = {
["Nightmares"] = true,
["Scandal"] = true,
["Suspicion"] = true,
["Wounds"] = true,
["Plagued by a Popular Song"] = true,
["Troubled Waters"] = true,
["Hearts' Game: Counterplay"] = true,
["Poison Tolerance of Your Target"] = true
}
menace_msg = {
[-4] = "Massively reduces",
[-2] = "Greatly reduces",
[-1] = "Reduces",
[1] = "Increases",
[2] = "Greatly increases"
}
function ask_minmax(quality, slot, pageID, minmax, extra)
local limit = 0
if pageID == nil then
pageID = 0
end
local ask = mw.smw.ask{
'[[Modifies quality::' .. quality .. ']][[-Has effect::<q>[[Has effect::' .. quality .. ']][[Equips in slot::Category:' .. slot .. ']]' .. extra .. '[[Page ID::!' .. pageID .. ']]</q>]]',
'?Modifies by=',
sort = 'Modifies by',order = minmax,limit = 1,searchlabel = '',mainlabel = '-'}
if ask ~= nil then limit = ask[1][1] end
return limit
end
function ask_minmax_bdr(slot, mimax, extra)
local limit = 0
local ask = mw.smw.ask{
'[[Equips in slot::Category:' .. slot .. ']]' .. extra .. '[[Page ID::!' .. pageID .. ']]',
'?Total BDR=',
sort = 'Total BDR',order = minmax,limit = 1,searchlabel = '',mainlabel = '-'}
if ask ~= nil then limit = ask[1][1] end
return limit
end
function msg_logic(value, limit_f, limit_nf, is_fate)
local out = ''
if value > 0 then -- BiS
if value > limit_nf and value ~= limit_f then
out = out .. 'Strict'
elseif value == limit_nf or (value == limit_f and limit_nf <= limit_f) then
out = out .. 'Shared'
end
if out ~= '' then
out = out .. ' Best-in-Slot'
if value < limit_f and not is_fate then
out = out .. ' non-Fate'
end
end
elseif value < 0 then -- WiS
if value < limit_nf and value ~= limit_f then
out = out .. 'Strict'
elseif value == limit_nf or (value == limit_f and limit_nf >= limit_f) then
out = out .. 'Shared'
end
if out ~= '' then
out = out .. ' Worst-in-Slot'
if value > limit_f and not is_fate then
out = out .. ' non-Fate'
end
end
end
return out
end
function bis_msg(value, quality, slot, pageID, minmax, is_fate, state)
if state ~= "Normal" then
return ''
end
local attributes = {
["Watchful"] = true,
["Shadowy"] = true,
["Persuasive"] = true,
["Dangerous"] = true,
["Bizarre"] = true,
["Dreaded"] = true,
["Respectable"] = true,
["A Player of Chess"] = true,
["Artisan of the Red Science"] = true,
["Chthonosophy"] = true,
["Glasswork"] = true,
["Kataleptic Toxicology"] = true,
["Inerrant"] = true,
["Insubstantial"] = true,
["Mithridacy"] = true,
["Monstrous Anatomy"] = true,
["Shapeling Arts"] = true,
["Neathproofed"] = true,
["Zeefaring"] = true,
["Steward of the Discordance"] = true,
}
local item_slot = {
["Burden"] = true,
["Hat"] = true,
["Clothing"] = true,
["Gloves"] = true,
["Weapon"] = true,
["Boots"] = true,
["Companion"] = true,
["Treasure"] = true,
["Destiny"] = true,
["Affiliation"] = true,
["Transport"] = true,
["Home Comfort"] = true,
["Ship"] = true,
["Spouse"] = true,
["Club"] = true,
["Tools of the Trade"] = true,
["Adornment"] = true,
["Luggage"] = true,
["Crew"] = true,
["Airship"] = true,
["Accoutrement"] = true
}
if (quality == nil) or (not item_slot[slot]) then
return '[[Category:Items with Malformed Effects Field]]'
end
if not attributes[quality] then
return ''
end
local out_bis = ''
local limit_f = 0
local limit_nf = 0
if not is_fate then
limit_f = ask_minmax(quality, slot, pageID, minmax, '[[Equipment status::Normal]][[Is Fate::true]]')
limit_nf = ask_minmax(quality, slot, pageID, minmax, '[[Equipment status::Normal]][[Is Fate::false]]')
else
limit_nf = ask_minmax(quality, slot, pageID, minmax, '[[Equipment status::Normal]]')
end
out_bis = msg_logic(value, limit_f, limit_nf, is_fate)
if out_bis ~= '' then
out_bis = out_bis .. ' item'
end
return out_bis
end
function bis_msg_bdr(total_bdr, slot, pageID, is_fate, state)
if state ~= "Normal" then
return ''
end
local out_bdr = ''
if total_bdr > 0 then minmax = 'desc'
elseif total_bdr < 0 then minmax = 'asc'
else return '' end
local limit_f = 0
local limit_nf = 0
if is_fate then
limit_nf = ask_minmax_bdr(slot, minmax, '')
else
limit_f = ask_minmax_bdr(slot, minmax, '[[Is Fate::true]]')
limit_nf = ask_minmax_bdr(slot, minmax, '[[Is Fate::false]]')
end
out_bdr = msg_logic(total_bdr, limit_f, limit_nf, is_fate, 0)
if out_bdr ~= '' then
out_bdr = out_bdr .. ' [[BDR]] item'
end
return out_bdr
end
-- Original 'smw_set' function by [[User:Asarta]]
function smw_set(quality, value, bis)
if quality and value then
local propertyname = "Has effect"
mw.smw.set({[propertyname] = quality .. ";" .. value})
if bis ~= '' then
mw.smw.set({["Is Best in Slot"] = quality .. ";" .. bis})
end
end
end
-- Original 'quality_from_effect' function and multiple effect sorting by [[User:Adnoam]]
function quality_from_effect(effect)
local quality, sign, value = string.match(effect, "%[%[File:.*link=([^%|]*)%|alt=%]%] %[%[%1%]%]%<%/span%>%s+([%+-]?)%D*(%d+)")
value = tonumber(value)
if sign == '-' then
value = value * -1
end
return quality, value
end
function p.effects(frame)
targs = frame:getParent().args
list = {}
slot = frame.args.slot
out = ''
ask = nil
total_bdr = 0
has_bis = false
is_fate = false
if frame.args.fate ~= 'no' then is_fate = true end
pageID = 0
title = mw.title.getCurrentTitle()
ask = mw.smw.ask{'[[' .. title.prefixedText .. ']]','?Page ID=',mainlabel = '-'}
if ask ~= nil then pageID = ask[1][1] end
for k, v in pairs(targs) do
num = string.match(k, "^Effects(%d+)$")
if (num) then
table.insert(list, tonumber(num))
end
end
table.sort(list)
local bdr = {
["Bizarre"] = true,
["Dreaded"] = true,
["Respectable"] = true
}
for _, num in ipairs(list) do
local effect = targs["Effects" .. num]
local quality, value = quality_from_effect(effect)
if (bdr[quality]) then
total_bdr = total_bdr + value
end
minmax = ''
if value > 0 then minmax = 'desc'
elseif value < 0 then minmax = 'asc'
else return '' end
if menaces[quality] then
out = out .. '*'
if menace_msg[value] then
out = out .. menace_msg[value] .. ' ' .. string.gsub(effect, '[+-]%d', 'build up.<sup>[[Menaces (Guide)#Menace Equipment|What does this mean?]]</sup>')
else
out = out .. '<span class="error">Invalid menace input!</span>'
end
else
out = out .. '*' .. effect
end
out_bis = ''
out_bis = bis_msg(value, quality, slot, pageID, minmax, is_fate, frame.args.state)
if out_bis ~= '' then
has_bis = true
out = out .. ' (' .. out_bis .. ')'
end
smw_set(quality, value, out_bis)
out = out .. '[[Category:' .. quality .. ' Items]]\n'
end
if total_bdr ~= 0 then
out_bdr = bis_msg_bdr(total_bdr, slot, pageID, is_fate, frame.args.state)
if out_bdr ~= '' then
out = out .. ':* '
if has_bis then out = out .. 'Also: ' end
out = out .. out_bdr
out = out .. '\n'
end
end
return out
end
local wrap_bis_pre = {
['none'] = '',
['italic'] = '<i>',
['bold'] = '<b>',
['underline'] = '<u>',
['text'] = ''
}
local wrap_bis_post = {
['none'] = '',
['italic'] = '</i>',
['bold'] = '</b>',
['underline'] = '</u>',
['text'] = ''
}
local wrap_full_pre = {
['tablelist'] = '<ul style="list-style-type: none; margin-left: 0;">',
['ul'] = '<ul>',
['tight'] = ''
}
local wrap_full_post = {
['tablelist'] = '</ul>',
['ul'] = '</ul>',
['tight'] = ''
}
local wrap_effects_pre = {
['tablelist'] = '<li>',
['ul'] = '<li>',
['tight'] = ''
}
local wrap_effects_post = {
['tablelist'] = '</li>',
['ul'] = '</li>',
['tight'] = '<br>'
}
local function handle_effect(frame, full, out, style)
local ret = out
local quality, value = string.match(full, '%[%[:(.-)%|.-%]%]% %((.-)%)')
local icon = '[[File:Question.png]]'
local icon_q = mw.smw.ask{
'[[' .. quality .. ']]', '?Has icon=icon',
mainlabel = '-'
}
if icon_q ~= nil then
icon = icon_q[1]['icon']
end
icon = string.gsub(icon, '%|frameless%|border%|text%-top%|', '|20px|link=' .. quality .. '|alt=')
if menaces[quality] then
ret = ret .. wrap_effects_pre[style] .. menace_msg[tonumber(value)] .. ' ' .. icon .. ' [[' .. quality .. ']]' .. ' build up.<sup>[[Menaces (Guide)#Menace Equipment|?]]</sup>' .. wrap_effects_post[style]
else
if tonumber(value) > 0 then value = '+' .. value end
ret = ret .. wrap_effects_pre[style] .. icon .. ' [[' .. quality .. ']] ' .. value .. wrap_effects_post[style]
end
return ret
end
local function handle_bis(full, out, strict, shared)
local ret = out
local quality, bis = string.match(full, '(.-)% %((.-)%)')
if string.sub(bis, 1, 6) == 'Strict' then
if strict == 'text' then
bis = string.gsub(bis, '(%u)[eo][sr].-%-in%-Slot', '%1iS')
ret = string.gsub(ret, '%[%[' .. quality .. '%]%]% ([+-]%d+)', '[[' .. quality .. ']]</span> %1 (' .. bis .. ')')
else
ret = string.gsub(ret, '%[%[' .. quality .. '%]%]', wrap_bis_pre[strict] .. '[[' .. quality .. ']]' .. wrap_bis_post[strict])
end
elseif string.sub(bis, 1, 6) == 'Shared' then
if shared == 'text' then
bis = string.gsub(bis, '(%u)[eo][sr].-%-in%-Slot', '%1iS')
ret = string.gsub(ret, '%[%[' .. quality .. '%]%]% ([+-]%d+)', '[[' .. quality .. ']]</span> %1 (' .. bis .. ')')
else
ret = string.gsub(ret, '%[%[' .. quality .. '%]%]', wrap_bis_pre[shared] .. '[[' .. quality .. ']]' .. wrap_bis_post[shared])
end
end
return ret
end
function p.effects_template(frame)
local args = frame.args
if args[1] == nil then
return '<span class="error">Item Effects error, no parameter was given.</span>'
end
local item = args[1]
local style = args.style or 'tablelist'
local style_strict = args.bis_strict or 'none'
local style_shared = args.bis_shared or 'none'
local query = mw.smw.ask{
'[[' .. item .. ']]', '?Has Game Type=gt', '?Has effect=effects', '?Is Best in Slot=bis',
mainlabel = '-'
}
if query == nil then
return '<span class="error">Item Effects error, query returned no results.</span>'
end
if query[1]['gt'] ~= 'Item' then
return '<span class="error">Item Effects error, given page is not an item.</span>'
end
local ret = ''
ret = ret .. wrap_full_pre[style]
if query[1]['effects'] then
if type(query[1]['effects']) == 'string' then
ret = handle_effect(frame, query[1]['effects'], ret, style)
else
for _,r in ipairs(query[1]['effects']) do
ret = handle_effect(frame, r, ret, style)
end
end
end
if query[1]['bis'] then
if type(query[1]['bis']) == 'string' then
ret = handle_bis(query[1]['bis'], ret, style_strict, style_shared)
else
for _,r in ipairs(query[1]['bis']) do
ret = handle_bis(r, ret, style_strict, style_shared)
end
end
end
ret = ret .. wrap_full_post[style]
return ret
end
return p