Module:Moons/AutoTables
Documentation for this module may be created at Module:Moons/AutoTables/doc
local p = {}
local WikiAutomated = require('Module:WikiAutomated')
local GameVersion = require('Module:GameVersion')
local Scraps = require('Module:Scraps')
local Entities = require('Module:Entities')
local Moons = require('Module:Moons')
local Rarities = require('Module:Rarities')
local I18n = require('Module:I18n')
--------------------
--#region lootTable
--------------------
function p._lootTableData(moon, version)
local errors = {}
local data = {
version = GameVersion.parseVersion(version, Scraps.versions),
extras = {},
rows = {},
}
if Moons.isMoonExistInVersion(moon, version) then
local totalRarity = Rarities.getItemsTotalRarity(moon, version)
data.extras.totalRarity = totalRarity
local rarities = Rarities.getItemsRarities(moon, version)
for scrap_mName, rarity in pairs(rarities) do
local row = {}
local scrap = Scraps.getScrap(scrap_mName, version)
row.scrap_mName = scrap_mName
row.name = scrap.name
row.rarity = rarity
row.spawnChance = rarity / totalRarity * 100
row.minValue = scrap.minValue
row.maxValue = scrap.maxValue
row.weight = scrap.weight
row.conductive = scrap.conductive
row.twoHanded = scrap.twoHanded
table.insert(data.rows, row)
table.sort(data.rows, function(a, b) return a.rarity > b.rarity end)
end
else
table.insert(errors, 'moonNotAddedInVersion')
end
if #errors > 0 then
data.errors = table.concat(errors, ',')
end
return data
end
function p._lootTableRender(tblDataRows, lang)
local tableHeader = ([[
! rowspan=2 | %s
! rowspan=2 | %s
! colspan=3 | %s
! rowspan=2 | %s
! rowspan=2 | %s
! rowspan=2 | %s
|-
! %s !! %s !! %s
]]):format(
I18n.getTranslation(lang, 'Scrap', 'ScrapTableHeaders'),
I18n.getTranslation(lang, 'Spawn chance', 'ScrapTableHeaders'),
I18n.getTranslation(lang, 'Values (c)', 'ScrapTableHeaders'),
I18n.getTranslation(lang, 'Weight (lb)', 'ScrapTableHeaders'),
I18n.getTranslation(lang, 'Is conductive', 'ScrapTableHeaders'),
I18n.getTranslation(lang, 'Is two-handed', 'ScrapTableHeaders'),
-- |-
I18n.getTranslation(lang, 'Min', 'ScrapTableHeaders'),
I18n.getTranslation(lang, 'Average', 'ScrapTableHeaders'),
I18n.getTranslation(lang, 'Max', 'ScrapTableHeaders')
)
local tblContents = {}
local tblContentTmpl = '| %s || %.2f%% || %s || %s || %s || %s || %s || %s'
local contents = {
'{| class="wikitable sortable"',
tableHeader,
'|-'
}
for _, rowData in ipairs(tblDataRows) do
local minValue = Scraps.utils.scrapValue(rowData.minValue)
local maxValue = Scraps.utils.scrapValue(rowData.maxValue)
local weight = Scraps.utils.scrapWeight(rowData.weight)
table.insert(tblContents, tblContentTmpl:format(
I18n.getTranslationLink(lang, rowData.name, 'Scraps'),
rowData.spawnChance,
minValue,
WikiAutomated.round((minValue + maxValue) / 2, 0),
maxValue,
weight,
WikiAutomated.expandYesNoT(rowData.conductive),
WikiAutomated.expandYesNoT(rowData.twoHanded)
))
end
local tbl_contents_concat = table.concat(tblContents, '\n|-\n')
table.insert(contents, tbl_contents_concat)
table.insert(contents, '|}')
return table.concat(contents, '\n')
end
---return `moon`'s loot table
---@param moon string
---@param version version? see [[Module:GameVersion]] for default value
---@param lang string which language to use
function p._lootTable(moon, version, lang)
local tblData = p._lootTableData(moon, version)
return p._lootTableRender(tblData, lang)
end
function p.lootTable(frame)
return p._lootTable(
frame.args['moon'] or frame.args[1],
frame.args['version'],
frame.args['lang'] or mw.message.getDefaultLanguage().code
)
end
function p._lootTableGrouped(moon)
local moonVersions = Moons.versions
local tblDatas = {}
for _, version in ipairs(moonVersions) do
local tblData = p._lootTableData(moon, version)
if tblData.errors == nil then
table.insert(tblDatas, tblData)
else
mw.log('version ' .. version .. ' skipped because errors: ' .. tblData.errors)
end
end
return WikiAutomated.contentTables.group(tblDatas)
end
function p.lootTables(frame)
return WikiAutomated.contentTables.groupRender(
p._lootTableGrouped(frame.args['moon'] or frame.args[1]),
p._lootTableRender,
frame.args['lang'] or mw.message.getDefaultLanguage().code
)
end
function p.lootTables_Auto()
local frame = mw.getCurrentFrame()
---@type string
local rootPagename = I18n.getLocalizedPageRootPageName(frame:preprocess('{{PAGENAME}}'))
mw.log('LootTablesAuto: Generating tables on ' .. rootPagename)
return WikiAutomated.contentTables.groupRender(
p._lootTableGrouped(rootPagename),
p._lootTableRender,
mw.message.getDefaultLanguage().code
)
end
--------------------
--#endregion lootTable
--------------------
--------------------
--#region entitiesSpawnChancesTable
--------------------
---@param entityType string one of the `Entities.getEntityType()` output
function p._entitiesSpawnChancesTableData(moon, entityType, version)
local errors = {}
local data = {
version = GameVersion.parseVersion(version, Entities.versions),
extras = {},
rows = {},
}
if Moons.isMoonExistInVersion(moon, version) then
data.extras.totalRarity = Rarities.getEntitiesTotalRarity(moon, entityType, version)
local rarities = Rarities.getEntitiesRarities(moon, version)
for entity_mName, rarity in pairs(rarities) do
local row = {}
local entity = Entities.getEntity(entity_mName, version)
if entity.type == entityType and rarity ~= nil and rarity > 0 then
row.entity_mName = entity_mName
row.name = entity.name
row.rarity = rarity
row.spawnChance = rarity / data.extras.totalRarity * 100
row.powerLevel = entity.powerLevel
row.maxCount = entity.maxCount
row.stunnable = entity.stunnable
row.stunTimeMultiplier = entity.stunTimeMultiplier
row.canDie = entity.canDie
row.enemyHP = entity.enemyHP
row.stunTimeSeconds = Entities.utils.stunTimeMultiplierToSeconds(
entity.stunTimeMultiplier, version
)
table.insert(data.rows, row)
end
table.sort(data.rows, function(a, b) return a.rarity > b.rarity end)
end
else
table.insert(errors, 'moonNotAddedInVersion')
end
if #errors > 0 then
data.errors = table.concat(errors, ',')
end
return data
end
function p._entitiesSpawnChancesTableRender(tblDataRows, lang)
local frame = mw.getCurrentFrame()
local tableHeadersTranslated = {
I18n.getTranslation(lang, 'Entity', 'TableHeaders'),
I18n.getTranslation(lang, 'Spawn chance', 'TableHeaders'),
I18n.getTranslation(lang, 'Power level', 'TableHeaders'),
I18n.getTranslation(lang, 'Max spawned', 'TableHeaders'),
I18n.getTranslation(lang, 'Stunning', 'TableHeaders'),
I18n.getTranslation(lang, 'HP', 'TableHeaders'),
}
local contents = {
'{| class="wikitable sortable"',
'! ' .. table.concat(tableHeadersTranslated, ' !! '),
'|-'
}
local tblContents = {}
-- | name || spawn chance || power level || max count || stun multiplier || HP
local tblContentTmpl = '| %s || %.2f%% || %s || %s || %s || %s'
---[[formatting stun multiplier to a more human readable expression]]
---@param stunTimes { stunGrenade: number, homemadeFlashbang: number?, radarBooster: number? }|nil
---@param stunMultiplier number
local function stunTimeMultiplierToReadable(stunTimes, stunMultiplier)
if stunTimes == nil then
return frame:expandTemplate { title = 'No_T', args = { 'Not stunnable' } }
end
local stunTimeContentTmpl = '<span style="white-space: nowrap; margin-inline-end: 0.5em;"><span>%s</span> <span>%.1fs</span></span>'
local stunTimeReadableContents = {}
local grenade = stunTimes.stunGrenade
local flashbang = stunTimes.homemadeFlashbang
local radar = stunTimes.radarBooster
local grenadeIcon = ('[[File:Stun Grenade Icon.png|link=%s|20px]]'):format(
I18n.getLocalizedPageLink('Stun Grenade', lang)
)
local flashbangIcon = ('[[File:DIYFlashbangRender.png|link=%s|20px]]'):format(
I18n.getLocalizedPageLink('Homemade Flashbang', lang)
)
local radarIcon = ('[[File:Radar Booster Icon.png|link=%s|20px]]'):format(
I18n.getLocalizedPageLink('Radar Booster', lang)
)
if grenade ~= nil and grenade == flashbang then
local _content = stunTimeContentTmpl:format(grenadeIcon .. flashbangIcon, grenade)
table.insert(stunTimeReadableContents, _content)
else
if grenade ~= nil then
local _content = stunTimeContentTmpl:format(grenadeIcon, grenade)
table.insert(stunTimeReadableContents, _content)
end
if flashbang ~= nil then
local _content = stunTimeContentTmpl:format(flashbangIcon, flashbang)
table.insert(stunTimeReadableContents, _content)
end
end
if radar ~= nil then
local _content = stunTimeContentTmpl:format(radarIcon, radar)
table.insert(stunTimeReadableContents, _content)
end
local mainContents = ''
for i, content in ipairs(stunTimeReadableContents) do
mainContents = mainContents .. content
if i % 2 == 0 and i ~= #stunTimeReadableContents then
mainContents = mainContents .. '<br/>'
end
end
mainContents = mainContents .. ('<br/><small>%s: %s</small>'):format(
I18n.getTranslation(lang, 'Stun multiplier'), stunMultiplier
)
return '<div>' .. mainContents .. '</div>'
end
for _, row in ipairs(tblDataRows) do
local stunRowContent
if row.stunnable then
stunRowContent = stunTimeMultiplierToReadable(row.stunTimeSeconds, row.stunTimeMultiplier)
else
stunRowContent = stunTimeMultiplierToReadable(nil)
end
local enemyHPRowContent
if row.canDie and row.enemyHP ~= "-1" then
enemyHPRowContent = ('[[File:Shovel Icon.png|link=%s|20px]] %s'):format(
I18n.getLocalizedPageLink('Shovel', lang), row.enemyHP
)
else
enemyHPRowContent = frame:expandTemplate { title = 'No_T', args = { 'Not killable' } }
end
table.insert(tblContents, tblContentTmpl:format(
I18n.getLocalizedPageLink(row.name, lang),
row.spawnChance,
row.powerLevel,
row.maxCount,
stunRowContent,
enemyHPRowContent
))
end
local tbl_contents_concat = table.concat(tblContents, '\n|-\n')
table.insert(contents, tbl_contents_concat)
table.insert(contents, '|}')
return table.concat(contents, '\n')
end
---@param moon string
---@param version version? see [[Module:GameVersion]] for default value
---@param lang string which language to use
function p._entitiesSpawnChancesTable(moon, entityType, version, lang)
local tblData = p._entitiesSpawnChancesTableData(moon, entityType, version)
return p._entitiesSpawnChancesTableRender(tblData.rows, lang)
end
function p.entitiesSpawnChancesTable(frame)
return p._entitiesSpawnChancesTable(
frame.args['moon'] or frame.args[1],
frame.args['entityType'] or frame.args[2],
frame.args['version'],
frame.args['lang'] or mw.message.getDefaultLanguage().code
)
end
function p._entitiesSpawnChancesTableGrouped(moon, entityType)
local versions = Entities.versions
local tblDatas = {}
for _, version in ipairs(versions) do
local tblData = p._entitiesSpawnChancesTableData(moon, entityType, version)
if tblData.errors == nil then
table.insert(tblDatas, tblData)
else
mw.log('version ' .. version .. ' skipped because errors: ' .. tblData.errors)
end
end
return WikiAutomated.contentTables.group(tblDatas)
end
function p.entitiesSpawnChancesTables(frame)
return WikiAutomated.contentTables.groupRender(
p._entitiesSpawnChancesTableGrouped(
frame.args['moon'] or frame.args[1],
frame.args['entityType'] or frame.args[2]
),
p._entitiesSpawnChancesTableRender,
frame.args['lang'] or mw.message.getDefaultLanguage().code
)
end
--[[wrapper for the auto tables below]]
function p._entitiesSpawnChancesTables_AutoWrapper(entityType)
local frame = mw.getCurrentFrame()
---@type string
local rootPagename = I18n.getLocalizedPageRootPageName(
frame:preprocess('{{PAGENAME}}')
)
mw.log('EntitiesSpawnChancesTablesAuto: Generating tables on ' .. rootPagename)
return WikiAutomated.contentTables.groupRender(
p._entitiesSpawnChancesTableGrouped(rootPagename, entityType),
p._entitiesSpawnChancesTableRender,
mw.message.getDefaultLanguage().code
)
end
function p.entitiesSpawnChancesTables_AutoIndoor()
return p._entitiesSpawnChancesTables_AutoWrapper('indoor')
end
function p.entitiesSpawnChancesTables_AutoNighttime()
return p._entitiesSpawnChancesTables_AutoWrapper('nighttime')
end
function p.entitiesSpawnChancesTables_AutoDaytime()
return p._entitiesSpawnChancesTables_AutoWrapper('daytime')
end
--------------------
--#endregion entitiesSpawnChancesTable
--------------------
return p