Module:DropsLineMulti
Jump to navigation
Jump to search
Documentation for this module may be created at Module:DropsLineMulti/doc
-- <nowiki>
local p = {}
local VariablesLua = mw.ext.VariablesLua
local dropsline = require('Module:DropsLine')
local params = require('Module:Paramtest')
local yesno = require('Module:Yesno')
local geprices_data = mw.loadData('Module:GEPrices/data')
local highalch_data = mw.loadData('Module:GEHighAlchs/data')
local multidata = mw.loadData('Module:DropsLineMulti/data')
local multidrops = multidata.all
local ptitle = mw.title.getCurrentTitle()
local ns = ptitle.nsText
local title = ptitle.fullText
local _membs = ' <sub title="Members only" style="cursor:help; margin-left:3px;">(m)</sub>'
local _nmnote = 'One of the following items is dropped: '
local _defrarnote = 'The chance of rolling a %s drop is %s, and the chance of getting a particular item is %s.'
local rarities = {
always = { 'table-bg-blue', 1 },
common = { 'table-bg-green', 16 },
uncommon = { 'table-bg-yellow', 64 },
rare = { 'table-bg-orange', 256 },
['very rare'] = { 'table-bg-red', 1024 },
random = { 'table-bg-pink', 4096 },
varies = { 'table-bg-pink', 4096 },
_default = { 'table-bg-grey', 65536 }
}
function p.main(frame)
local args = frame:getParent().args
local tempArgs = frame.args
if not params.has_content(tempArgs.dtype) then
tempArgs.dtype = 'drop'
end
local dropnm = string.lower(args.Name or args[1] or '')
local drop = multidrops[dropnm]
if not drop then
return error('Drop type not found. See [[Template:DropsLineMulti]] for valid types, and instructions on adding one.')
end
-- Params and defaults
local namenotes,
quantity,quantitynotes,
rarity,raritynotes,memsover,
altcur,monVers,altSource = params.defaults{
{args.Namenotes,''},
{args.Quantity,'Unknown'},
{args.Quantitynotes,''},
{args.Rarity,'Unknown'},
{args.Raritynotes,''},
{args.members,''},
{args.AltCurrency,''},
{args.Version,''},
{args.Altsource,'GazBot'},
}
if altSource ~= "GazBot" then
pgTitle = altSource
end
local name = drop.name
local altname = drop.alt or name
altname = params.default_to(args.Alt,altname)
local gemwname = name
local _smwname = params.default_to(args.smwname,gemwname)
local isCoins = false
--local raritynotes = args.Raritynotes or ''
-- Remove version number from potions, enchanted jewellery, waterskins etc for smw
local cleanedName
local dropVers = ''
if _smwname:match(' %(%d%)$') then
cleanedName, dropVers = mw.ustring.match(_smwname, '^(.-) (%(%d%))$')
elseif _smwname:match('%#') then
cleanedName, dropVers = mw.ustring.match(_smwname, '^(.-)%#([%w%s%(%)_]+)$')
else
cleanedName = mw.ustring.gsub(_smwname, ' %(%d%)$', '')
end
cleanedName = mw.text.trim(cleanedName)
dropVers = mw.text.trim(dropVers)
local smwname = cleanedName
if dropVers ~= '' then
-- get subobject instead
smwname = cleanedName..'#'..dropVers
end
if args.dtype and params.has_content(args.dtype) then
tempArgs.dtype = args.dtype
end
local rarity_value
if rarities[rarity:lower()] then
rarity = params.ucflc(rarity)
else
rarity_value = expr(rarity)
end
-- Generate rarity note
local ad_raritynote
local note_rare = rarity
local note_item_rare = rarity_value or rarity
if rarity_value and tonumber(rarity_value) then
local fract = mw.text.split(rarity,'%s*/%s*')
local denom
local itemcnt = 0
for i,v in ipairs(drop.items) do
itemcnt = itemcnt + 1
end
if fract[2] then
denom = fract[2] * itemcnt
else
denom = itemcnt
end
local def_rarity = fract[1]..'/'..denom
local calced_rarity = tonumber(rarity_value) / itemcnt
local oneover_rarity = sigfigalt(1/calced_rarity)
local perc_rarity = sigfig(100 * calced_rarity, 3)
note_item_rare = string.format('%s (1/%s, %s%%)', def_rarity, oneover_rarity, perc_rarity)
end
if drop.note then
ad_raritynote = string.format(drop.note, note_rare, note_item_rare)
else
ad_raritynote = string.format(_defrarnote, name, note_rare, note_item_rare)
end
if ad_raritynote ~= '' then
ad_raritynote = frame:callParserFunction{ name = '#tag:ref', args = {
ad_raritynote, name = 'dlm-r '..drop.name, group = 'd'
} }
VariablesLua.vardefine( '_refs_used_', 'true' )
end
raritynotes = raritynotes .. ad_raritynote
-- Generate items note
local itlinks = {}
for i,v in ipairs(drop.items) do
local valt = params.default_to(v.alt,v.name)
table.insert(itlinks, string.format('[[%s|%s]]', v.name, string.lower(valt)))
end
local ad_namenote = _nmnote .. table.concat(itlinks, ', ') .. '.'
if ad_namenote ~= _nmnote then
ad_namenote = frame:callParserFunction{ name = '#tag:ref', args = {
ad_namenote, name = 'dlm-n '..drop.name, group = 'd'
} }
namenotes = namenotes .. ad_namenote
VariablesLua.vardefine( '_refs_used_', 'true' )
end
quantity = mw.ustring.lower(quantity)
local alch = false
local gemw = false
local valueInfo = {
alch = {
has = false,
value = 0,
from = nil
},
ge = {
has = false,
value = 0,
from = nil
}
}
if drop.value then
valueInfo = {
alch = {
has = true,
value = drop.value,
from = 'alt'
},
ge = {
has = true,
value = drop.value,
from = 'alt'
}
}
alch = true
gemw = true
end
-- Check members or F2P
local members = false
if params.has_content(memsover) then
-- overridden
members = yesno(memsover)
elseif drop.members ~= nil then
members = drop.members
end
-- Add to name of item if members item
if members == true then
imgmembs = _membs
else
imgmembs = ''
end
-- Image
local image_n = mw.ustring.gsub(drop.icon, '#.+$', '.png')
local image
if image_n:lower() == 'no' or params.is_empty(drop.icon) then
image = ''
else
image = mw.ustring.format('[[File:%s|link=%s|alt=%s: RS3 %s drops %s with rarity %s in quantity %s]]', image_n, name, image_n, title, name, rarity, quantity)
end
-- this only affects the JSON for the constituent items
local smwjson = string.lower(args.smwjson or '')
if params.has_content(args.nosmw) then
smwjson = false
elseif smwjson == 'no' then
smwjson = false
elseif smwjson == 'rdt' then
smwjson = 'rdt'
else
smwjson = true
end
-- Level for Fishing, Archaeology, Mining, Woodcutting and Divination
local level = 0
if drop.level then
level = drop.level
end
-- SMW Drops so they display on pages etc, values
local totge, totalch, totvals = 0,0,0
local subrows = {}
for _,v in ipairs(drop.items) do
local tmpdrop = smwdrop(v, drop, tempArgs, {
['monVers'] = monVers,
['altSource'] = altSource,
rarity=rarity,
raritynotes=raritynotes,
['rarity_value']=rarity_value,
quantity=quantity,
memsover=memsover,
smwjson = smwjson
})
if tmpdrop.alch and tmpdrop.alch > 0 then
totalch = totalch + tmpdrop.alch
if tmpdrop.ge and tmpdrop.ge > 0 then
totge = totge + tmpdrop.ge
else
totge = totge + tmpdrop.alch
end
totvals = totvals + 1
end
local tmpline = tostring(tmpdrop.line)
table.insert(subrows, tmpline)
end
if totalch > 0 then
local alchval = math.floor(totalch / totvals)
local geval = math.floor(totge / totvals)
valueInfo = {
alch = {
has = true,
value = alchval,
from = 'alt'
},
ge = {
has = true,
value = geval,
from = 'alt'
}
}
alch = true
gemw = true
end
-- Rarity pref
local rarePref = ''
if args.approx and yesno(args.approx) then
rarePref = '<span title="Approximate">~</span> '
end
-- Class for row
local rowClass = 'dlm-drop dlm-'..string.gsub(drop.name, '%A', '_')
-- Table display row, no smw
local dlsmwjson = false
local ret = ''
local ret = dropsline._main{ name,
altname,namenotes,
quantity,quantitynotes,rarePref,
rarity,rarity_value,raritynotes,
image,members,
valueInfo,gemw,alch,alt,
isCoins,
tempArgs,monVers,
cleanedName,dropVers,level,rowClass,
smwname,dlsmwjson }
-- categories for mainspace
local cats = ''
if ns == '' then
if drop.cats then
cats = cats .. drop.cats
end
if quantity:find('Unknown') then
ret = ret .. '[[Category:Needs drop quantity added]]'
end
end
subrows = table.concat(subrows, '\n')
return ret..subrows..cats
end
function p.list(frame)
local args = frame:getParent().args
local dlines = {'{{DropsTableHead}}'}
local grouptbl = mw.html.create( 'table' )
grouptbl:addClass('wikitable')
:tag('tr')
:tag('th'):wikitext('Name'):done()
:tag('th'):wikitext('Aliases'):done()
:done()
for i,v in pairs(multidata.noaliases) do
local v_alias = ''
for j,k in ipairs(v.alias) do
v_alias = v_alias .. '<code>'..k..'</code> '
end
grouptbl:tag('tr')
:tag('td')
:tag('code'):wikitext(i):done()
:done()
:tag('td')
:wikitext(v_alias)
:done()
local dline = string.format('{{DropsLineMulti|Name=%s|Rarity=1/100|Quantity=1}}', i)
table.insert(dlines, dline)
end
table.insert(dlines, '{{DropsTableBottom}}')
local dlinestr = frame:preprocess( table.concat(dlines, '') )
local ret = mw.html.create( 'div' )
ret:wikitext('The following is a list of available drop groups:')
:newline()
:node( grouptbl )
:newline()
:wikitext('Resulting dropslines:')
:newline()
:wikitext( dlinestr )
return ret
end
-- Function to generate smw data per dropped item
function smwdrop(ditem, group, tempArgs, parsed)
-- Params and defaults
local name,namenotes,
quantity,quantitynotes,
raritynotes,memsover = params.defaults{
{ditem.name,'Item'},
{ditem.namenotes,''},
{ditem.quantity, '1'},
{ditem.quantitynotes,''},
{ditem.raritynotes,''},
{ditem.members,''},
}
local altname = params.default_to(ditem.alt,name)
local rarity = ditem.rarity or group.rarity or 'auto'
local gemwname = params.default_to(ditem.gemwname,name)
local _smwname = params.default_to(ditem.smwname,gemwname)
local isCoins = false
-- Inherited
local altSource = parsed.altSource
local monVers = parsed.monVers
-- Remove version number from potions, enchanted jewellery, waterskins etc for smw
local cleanedName
local dropVers = ''
if _smwname:match(' %(%d%)$') then
cleanedName, dropVers = mw.ustring.match(_smwname, '^(.-) (%(%d%))$')
elseif _smwname:match('%#') then
cleanedName, dropVers = mw.ustring.match(_smwname, '^(.-)%#([%w%s%(%)_]+)$')
else
cleanedName = mw.ustring.gsub(_smwname, ' %(%d%)$', '')
end
cleanedName = mw.text.trim(cleanedName)
dropVers = mw.text.trim(dropVers)
local smwname = cleanedName
if dropVers ~= '' then
-- get subobject instead
smwname = cleanedName..'#'..dropVers
end
local rarity_value
local numitems = 0
for i,v in ipairs(group.items) do
numitems = numitems + 1
end
local baserarity = false
if string.lower(rarity) == 'base' then
baserarity = true
end
if rarities[rarity:lower()] then
rarity = params.ucflc(rarity)
elseif string.lower(rarity) == 'auto' then
if rarities[parsed.rarity:lower()] then
rarity = params.ucflc(parsed.rarity)
else
rarity_value = 1 / numitems
rarity = '1/'..numitems
end
elseif baserarity then
rarity = parsed.rarity
rarity_value = parsed.rarity_value
else
rarity_value = expr(rarity)
end
if parsed.rarity_value and rarity_value and baserarity == false then
local parent = tonumber(parsed.rarity_value)
if parent then
rarity_value = rarity_value * parent
local fract = mw.text.split(rarity,'%s*/%s*')
local denom
if fract[2] then
denom = fract[2] * (1 / parent)
else
denom = (1 / parent)
end
rarity = fract[1]..'/'..denom
end
end
raritynotes = raritynotes..parsed.raritynotes
-- Calculate quantities
quantity = mw.ustring.lower(quantity)
if parsed.quantity == 'unknown' then
quantity = 'unknown'
elseif parsed.quantity == 'varies' then
quantity = 'varies'
elseif parsed.quantity ~= '1' then
quantity = calcqty(quantity, parsed.quantity)
end
local gemw = yesno(ditem.gemw or group.gemw or 'yes', false)
local alch = yesno(ditem.alch or group.alch or 'yes', false)
-- Test for existance of alch value
local valueInfo = {
alch = {
has = false,
value = 0,
from = nil
},
ge = {
has = false,
value = 0,
from = nil
}
}
-- Bulk sources
local geprice_frombulk = geprices_data[gemwname]
if not (type(geprice_frombulk) == 'number' and geprice_frombulk > 0) then
geprice_frombulk = nil
end
if alch then
local alch_frombulk = highalch_data[gemwname]
if not (type(alch_frombulk) == 'number' and alch_frombulk > -1) then
alch_frombulk = nil
end
if alch_frombulk ~= nil then
valueInfo.alch = {
has = true,
value = alch_frombulk,
from = 'cache'
}
elseif gemw then
-- is not on the no-ge list/override
-- lookup in GEMW
local hasgealch, gealchval = pcall(f_gealch,gemwname)
-- is not on the no-alch list or has alch disabled (and is not coins)
if hasgealch then
if gealchval > -1 then
-- has a alch value from GEMW
valueInfo.alch = {
has = true,
value = tonumber(gealchval),
from = 'ge'
}
end
end
end
if not valueInfo.alch.has then
-- failed to find alch in GEMW or is on the no-ge list/override
-- lookup in SMW
local smwret = getSMWInfo(smwname)
if smwret and smwret.alch ~= nil then
-- alch is defined, use it
valueInfo.alch = {
has = true,
value = smwret.alch,
from = 'smw'
}
elseif ditem.AltValue then
--AltValue set, no alch from GE or SMW, use alt as regular alch
valueInfo.alch = {
has = true,
value = tonumber(ditem.AltValue),
from = 'alt'
}
if hasCur then
valueInfo.alch.curr = altcur
end
else
alch = false
end
end
else
-- is on the no-alch list (and is not coins)
if ditem.AltValue then
--Altvalue set, no alch value
valueInfo.alch = {
has = true,
value = tonumber(ditem.AltValue),
from = 'alt'
}
end
end
if gemw then
if geprice_frombulk ~= nil then
valueInfo.ge = {
has = true,
value = geprice_frombulk,
from = 'cache'
}
else
local hasgemw, gepric = pcall(geprice,gemwname)
if hasgemw then
valueInfo.ge = {
has = true,
value = gepric,
from = 'ge'
}
else
valueInfo.ge = {
has = true,
value = valueInfo.alch.value,
from = 'alch'
}
end
end
elseif ditem.AltValue then
valueInfo.ge = {
has = true,
value = tonumber(ditem.AltValue),
from = 'alt'
}
elseif alch then
valueInfo.ge = {
has = true,
value = valueInfo.alch.value,
from = 'alch'
}
end
-- Check members or F2P
local members = false
if params.has_content(memsover) then
-- overridden
members = yesno(memsover)
elseif params.has_content(parsed.memsover) then
-- overridden by parent
members = yesno(parsed.memsover)
elseif group.members ~= nil then
members = group.members
else
local smwret = getSMWInfo(smwname)
if smwret and smwret.members ~= nil then
members = smwret.members
end
end
-- Add to name of item if members item
if members == true then
imgmembs = _membs
else
imgmembs = ''
end
local image,image_n
if ditem.image then
image_n = ditem.image
else
image_n = name .. '.png'
image_n = mw.ustring.gsub(image_n, '#.+$', '.png')
end
if image_n:lower() == 'no' or params.is_empty(image_n) then
image = ''
else
image = mw.ustring.format('[[File:%s|link=%s|alt=%s: RS3 %s drops %s with rarity %s in quantity %s]]', image_n, name, image_n, title, name, rarity, quantity)
end
-- Level for Fishing, Archaeology, Mining, Woodcutting and Divination
local level = 0
if ditem.Level and tonumber(ditem.Level, 10) then
level = tonumber(ditem.Level, 10)
elseif group.Level and tonumber(group.Level, 10) then
level = tonumber(group.Level, 10)
end
-- Class for row
local rowClass = 'dlm-sub-drop table-na expand-child dlm-'..string.gsub(group.name, '%A', '_')
local tmpline = dropsline._main{ name,
altname,namenotes,
quantity,quantitynotes,rarePref,
rarity,rarity_value,raritynotes,
image,members,
valueInfo,gemw,alch,alt,
isCoins,
tempArgs,monVers,
cleanedName,dropVers,level,rowClass,
smwname,parsed.smwjson }
-- mw.log(tmpline)
return { alch = valueInfo.alch.value, ge = valueInfo.ge.value, line = tmpline }
end
function expr(t)
local noerr, val = pcall(mw.ext.ParserFunctions.expr, t)
if noerr then
return tonumber(val)
else
return false
end
end
function sigfig(n, f)
f = math.floor(f-1)
if n == 0 then return 0 end
local m = math.floor(math.log10(n))
local v = n / (10^(m-f))
-- floor(x + 0.5) is standard rounding to one decimal place
v = math.floor(v+0.5) * 10^(m-f)
return v
end
p.sigfig = sigfig
function sigfigalt(n)
if n >= 100 then
return math.floor(n+0.5)
else
return sigfig(n, 3)
end
end
function getSMWInfo(item)
if smwData ~= nil then
return smwData
end
local smw = mw.smw.ask({
'[['..item..']]',
'?High Alchemy value',
'?Is members only'
})
if smw and smw[1] then
smwData = {
alch = smw[1]['High Alchemy value'],
members = smw[1]['Is members only']
}
else
smwData = false
end
return smwData
end
function calcqty(quantity, parent)
-- if no quantity is given, return unknown
if string.lower(quantity) == 'varies' then
return 'Varies'
end
if not quantity or string.lower(quantity) == 'unknown' then
return 'Unknown'
end
-- Get parent value
-- en dashes are the proper dash for number ranges
-- replace all hyphens and em dashes with en
-- strip *all* whitespace
parent = mw.ustring.gsub(parent,'[-—]','–')
:gsub('%s','')
-- check if noted then remove text
local noted = false
if mw.ustring.find(parent,'%(noted%)') then
noted = true
parent = mw.ustring.gsub(parent,'%(noted%)','$n')
end
-- get parent amounts
local par_vals = mw.text.split(quantity,'[,;]')
local par_low = 2147483648
local par_high = 0
local multipliers = {}
for _, v in ipairs(par_vals) do
if mw.ustring.find(v,'–') then
local splitvals = mw.text.split(v,'–')
-- assume a is smaller, b is larger
local a = tonumber(splitvals[1])
local b = tonumber(splitvals[2])
-- Just in case
if a > b then
a,b = b,a
end
if a < par_low then
low = a
end
if b > par_high then
high = b
end
else
local num = tonumber(v)
if num then
table.insert(multipliers, num)
end
end
end
local range = false
if par_low < 2147483648 and par_high > 0 then
range = true
end
-- en dashes are the proper dash for number ranges
-- replace all hyphens and em dashes with en
-- strip *all* whitespace
quantity = mw.ustring.gsub(quantity,'[-—]','–')
:gsub('%s','')
-- split list into table
local vals = mw.text.split(quantity,'[,;]')
local rettbl = {}
for i, v in ipairs(vals) do
local inote = mw.ustring.find(v,'%(noted%)')
local clean = mw.ustring.gsub(v,'%(noted%)','')
if mw.ustring.find(v,'–') then
local splitvals = mw.text.split(clean,'–')
-- assume a is smaller, b is larger
local a = tonumber(splitvals[1])
local b = tonumber(splitvals[2])
-- Just in case
if a > b then
a,b = b,a
end
if range then
local reta = par_low * a
local retb = par_high * b
table.insert(rettbl, reta..'-'..retb)
end
for j,k in ipairs(multipliers) do
local reta = a * k
local retb = b * k
table.insert(rettbl, reta..'-'..retb)
end
else
local a = tonumber(clean)
if range then
local reta = par_low * a
local retb = par_high * a
table.insert(rettbl, reta..'-'..retb)
end
for j,k in ipairs(multipliers) do
local reta = a * k
table.insert(rettbl, reta)
end
end
end
-- Make string again
ret = table.concat(rettbl,'; ')
-- If no numbers are found in the string, return unknown
if not ret:find('%d') then
return 'Unknown'
end
return ret
end
return p