3,124
edits
(Add biome icons to p.GetBuildingBiomeTable(), p.GetBuildingTable() p._GetBiomeModifiers()) |
(Fixed currencies not showing up in task list) |
||
(44 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
local Shared = require('Module:Shared') | local Shared = require('Module:Shared') | ||
local Icons = require('Module:Icons') | local Icons = require('Module:Icons') | ||
local Items = require('Module:Items') | |||
local Monsters = require('Module:Monsters') | |||
local Shop = require('Module:Shop') | |||
local GameData = require('Module:GameData') | local GameData = require('Module:GameData') | ||
local | local Modifiers = require('Module:Modifiers') | ||
local Num = require('Module:Number') | |||
local p = {} | local p = {} | ||
Line 10: | Line 13: | ||
p.Township = Township | p.Township = Township | ||
-- Gets a Township building by ID, e.g. melvorF:Hunters_Cabin | |||
function p._getBuildingByID(id) | |||
-- Check for the special statue case | |||
if id == 'melvorF:Statues' then | |||
local building = Shared.clone(GameData.getEntityByID(Township.buildings, id)) | |||
building.name = 'Statue of Worship' | |||
return building | |||
else | |||
return GameData.getEntityByID(Township.buildings, id) | |||
end | |||
end | |||
-- Gets a Township building by name, e.g. Hunters Cabin | |||
function p._getBuildingByName(name) | |||
-- Check for the special statue case | |||
if name == 'Statues' then | |||
name = 'Statue of Worship' | |||
end | |||
local STATUE_OF = 'Statue of ' | |||
if string.sub(name, 1, string.len(STATUE_OF)) == STATUE_OF then | |||
local building = Shared.clone(GameData.getEntityByID(Township.buildings, 'melvorF:Statues')) | |||
building.name = name | |||
return building | |||
else | |||
return GameData.getEntityByName(Township.buildings, name) | |||
end | |||
end | |||
-- Gets a resource from id | |||
function p._getResourceByID(id) | |||
return GameData.getEntityByID(Township.resources, id) | |||
end | |||
-- Given a building, find the next building upgrade | |||
function p._getBuildingUpgrade(building) | |||
local function checkFunc(entity) | |||
return entity.upgradesFrom ~= nil and entity.upgradesFrom == building.id | |||
end | |||
local upgradesTo = GameData.getEntities(Township.buildings, checkFunc) | |||
if #upgradesTo > 0 then | |||
return upgradesTo[1] | |||
end | |||
return nil | |||
end | |||
-- | -- Given a building, find the building's downgrade | ||
function p._getBuildingDowngrade(building) | |||
function p. | if building.upgradesFrom ~= nil then | ||
return p._getBuildingByID(building.upgradesFrom) | |||
if | |||
return | |||
end | end | ||
return nil | |||
end | |||
-- Given a building and biome ID, returns the cost of constructing the building | |||
-- within that biome as a human readable text string. Returns nil if the building | |||
-- cannot be built within that biome. | |||
function p._getBuildingCostText(building, biomeID, delimiter) | |||
-- Basic validation of inputs | |||
if type(building) == 'table' and building.cost ~= nil and biomeID ~= nil then | |||
local delim = delimiter | |||
for | if delim == nil then | ||
delim = ', ' | |||
if | end | ||
for i, costDef in ipairs(building.cost) do | |||
for | if costDef.biomeID == biomeID then | ||
if | local resultPart = {} | ||
table.insert( | for j, cost in ipairs(costDef.cost) do | ||
local resData = p._getResourceByID(cost.id) | |||
if resData ~= nil then | |||
table.insert(resultPart, Icons.Icon({resData.name, type='resource', notext=true, nolink=true, qty=cost.quantity})) | |||
end | end | ||
end | end | ||
return table.concat(resultPart, delim) | |||
end | end | ||
end | end | ||
end | end | ||
end | end | ||
-- | -- Given a building, groups biomes for which that building has a common cost | ||
function p. | function p._getBuildingGroupedCosts(building) | ||
local biomeGroups = {} | |||
-- | for i, biomeID in ipairs(building.biomes) do | ||
local currentBiomeCost = p._getBuildingCostText(building, biomeID) | |||
local found = false | |||
for j, biomeGroup in ipairs(biomeGroups) do | |||
return | if biomeGroup.cost == currentBiomeCost then | ||
-- Another biome exists with this cost | |||
table.insert(biomeGroup.biomeIDs, biomeID) | |||
found = true | |||
break | |||
end | |||
end | |||
if not found then | |||
table.insert(biomeGroups, { biomeIDs = { biomeID }, cost = currentBiomeCost}) | |||
end | |||
end | |||
return biomeGroups | |||
end | end | ||
-- | -- Given a building, returns a text string repesenting the building costs for all biomes | ||
function p. | function p._getBuildingGroupedCostText(building) | ||
local resultPart = {} | |||
local biomeGroups = p._getBuildingGroupedCosts(building) | |||
if Shared.tableCount(biomeGroups) == 1 then | |||
-- If only one entry then simply output the cost | |||
table.insert(resultPart, biomeGroups[1].cost) | |||
else | |||
-- Otherwise, split by biome group | |||
for i, biomeGroup in ipairs(biomeGroups) do | |||
local biomeText = {} | |||
for j, biomeID in ipairs(biomeGroup.biomeIDs) do | |||
local biome = GameData.getEntityByID(Township.biomes, biomeID) | |||
table.insert(biomeText, Icons.Icon({biome.name, type='biome', notext=true, nolink=true, alt=biome.name})) | |||
end | |||
table.insert(resultPart, table.concat(biomeText, ', ') .. ': ' .. biomeGroup.cost) | |||
end | |||
end | |||
return table.concat(resultPart, '<br/>') | |||
end | end | ||
-- | -- Given a building and biome ID, returns a string displaying the building's benefits, | ||
-- or nil if no benefits | |||
function p._getBuildingBenefitText(building, biomeID, includeModifiers, delimiter) | |||
-- Basic validation of inputs | |||
if type(building) == 'table' and building.provides ~= nil and biomeID ~= nil then | |||
-- | local delim = delimiter | ||
if delim == nil then | |||
delim = ', ' | |||
end | |||
local includeMods = includeModifiers | |||
if includeMods == nil then | |||
includeMods = false | |||
end | |||
local providesData = nil | |||
for i, provides in ipairs(building.provides) do | |||
if provides.biomeID == biomeID then | |||
providesData = provides | |||
break | |||
end | |||
end | |||
if providesData ~= nil then | |||
local resultPart = {} | |||
local stats = { | |||
population = 'Population', | |||
happiness = 'Happiness', | |||
education = 'Education', | |||
storage = 'Storage', | |||
worship = 'Worship', | |||
fortification = 'Fortification' | |||
} | |||
local resourceText = function(resName, resType, quantity) | |||
local elemClass = (quantity < 0 and 'text-negative') or 'text-positive' | |||
local resIcon = Icons.Icon({resName, type=resType, notext=true}) | |||
return resIcon .. ' <span class="' .. elemClass .. '">' .. Num.numStrWithSign(quantity) .. '</span>' | |||
end | end | ||
-- Resources | |||
if providesData.resources ~= nil then | |||
for i, resource in ipairs(providesData.resources) do | |||
local resData = p._getResourceByID(resource.id) | |||
if resData ~= nil and resource.quantity ~= 0 then | |||
table.insert(resultPart, resourceText(resData.name, 'resource', resource.quantity)) | |||
end | |||
end | |||
end | end | ||
for | -- Other stats | ||
for key, stat in pairs(stats) do | |||
local quantity = providesData[key] | |||
if quantity ~= nil and quantity ~= 0 then | |||
table.insert(resultPart, resourceText(stat, 'township', quantity)) | |||
end | |||
end | end | ||
-- Modifiers | |||
if includeMods and building.modifiers ~= nil then | |||
table.insert(resultPart, Modifiers.getModifiersText(building.modifiers)) | |||
end | end | ||
if not Shared.tableIsEmpty(resultPart) then | |||
return table.concat(resultPart, delim) | |||
end | end | ||
end | end | ||
end | end | ||
end | end | ||
-- | -- Given a building, groups biomes for which that building has a common benefit/provides | ||
function p. | function p._getBuildingGroupedBenefits(building, includeModifiers) | ||
if includeModifiers == nil then | |||
includeModifiers = true | |||
end | |||
local | local biomeGroups = {} | ||
for | for i, biomeID in ipairs(building.biomes) do | ||
local currentBiomeBenefit = p._getBuildingBenefitText(building, biomeID, includeModifiers) | |||
local found = false | |||
for j, biomeGroup in ipairs(biomeGroups) do | |||
if biomeGroup.benefit == currentBiomeBenefit then | |||
-- Another biome exists with this cost | |||
table.insert(biomeGroup.biomeIDs, biomeID) | |||
found = true | |||
break | |||
if | |||
table.insert( | |||
end | end | ||
end | |||
if not found then | |||
table.insert(biomeGroups, { biomeIDs = { biomeID }, cost = currentBiomeBenefit}) | |||
end | |||
end | |||
return biomeGroups | |||
end | |||
-- Given a building, returns a text string repesenting the building benefits for all biomes | |||
function p._getBuildingGroupedBenefitText(building, includeModifiers) | |||
if includeModifiers == nil then | |||
includeModifiers = true | |||
end | |||
local resultPart = {} | |||
local biomeGroups = p._getBuildingGroupedBenefits(building, includeModifiers) | |||
if Shared.tableCount(biomeGroups) == 1 then | |||
-- If only one entry then simply output the cost | |||
table.insert(resultPart, biomeGroups[1].cost) | |||
else | |||
-- Otherwise, split by biome group | |||
for i, biomeGroup in ipairs(biomeGroups) do | |||
local biomeText = {} | |||
for j, biomeID in ipairs(biomeGroup.biomeIDs) do | |||
local biome = GameData.getEntityByID(Township.biomes, biomeID) | |||
table.insert(biomeText, Icons.Icon({biome.name, type='biome', notext=true, nolink=true, alt=biome.name})) | |||
end | end | ||
table.insert(resultPart, table.concat(biomeText, ', ') .. ': ' .. biomeGroup.cost) | |||
table.insert( | |||
end | end | ||
end | end | ||
return table.concat( | return table.concat(resultPart, '<br/>') | ||
end | end | ||
-- | -- Returns a sorted list of all Township buildings | ||
function p._sortedBuildings(keepUnsorted) | |||
local ku = true | |||
if keepUnsorted ~= nil then | |||
ku = keepUnsorted | |||
end | |||
return GameData.sortByOrderTable(Township.buildings, Township.buildingDisplayOrder, ku) | |||
end | end | ||
-- Gets a | -- Gets the Township level or abyssalLevel, population and fortification requirements for a tier | ||
function p. | -- Returns {population=X, level=X} for non-abyssal tiers | ||
-- Returns {population=X, abyssalLevel=X, fortification=X} for abyssal tiers | |||
if | function p._getTierRequirements(tier, abyssalTier) | ||
local | local tierData = Township.populationForTier[tier] | ||
if abyssalTier ~= nil then | |||
return | local abyssalTierData = Shared.clone(Township.abyssalTierRequirements[abyssalTier + 1]) | ||
abyssalTierData.population = tierData.population | |||
return abyssalTierData | |||
else | else | ||
return | return tierData | ||
end | end | ||
end | end | ||
-- | -- Returns a string containing the Township level and population requirements for a tier | ||
function p. | function p._getTierText(tier, abyssalTier) | ||
local realmID = (abyssalTier ~= nil and 'melvorItA:Abyssal' or 'melvorD:Melvor') | |||
if | local tierData = p._getTierRequirements(tier, abyssalTier) | ||
if tierData ~= nil then | |||
local tierText = Icons._SkillReq('Township', tierData.abyssalLevel or tierData.level, false, realmID) | |||
if tierData.population ~= nil and tierData.population > 0 then | |||
tierText = tierText .. '<br/>' .. Icons.Icon({'Population', type='township', notext=true}) .. ' ' .. Num.formatnum(tierData.population) | |||
end | |||
if tierData.fortification ~= nil and tierData.fortification > 0 then | |||
tierText = tierText .. '<br/>' .. Icons.Icon({'Fortification', type='township', notext=true}) .. ' ' .. Num.formatnum(tierData.fortification) .. '%' | |||
end | |||
return tierText | |||
end | end | ||
local | end | ||
local | -- Generates a table of all seasons, their type/requirements, and modifiers | ||
function p.getSeasonTable(frame) | |||
-- Manual data specifying the worship requirement for those rare seasons | |||
local seasonReqs = { | |||
["Nightfall"] = Icons.Icon({'Township%23Worship', 'Bane Worship', img='Statue of Bane', type='building'}), | |||
["SolarEclipse"] = Icons.Icon({'Township%23Worship', 'The Herald Worship', img='Statue of The Herald', type='building'}), | |||
["Lemon"] = Icons.Icon({'Ancient_Relics', 'Ancient Relics', img='Ancient Relics'}), | |||
["EternalDarkness"] = Icons.Icon({'Township%23Worship', 'Xon Worship', img='Statue of Xon', type='building'}), | |||
} | |||
local seasons = Shared.shallowClone(Township.seasons) | |||
table.sort(seasons, function(a, b) return a.order < b.order end) | |||
local resultPart = {} | |||
table.insert(resultPart, '{| class="wikitable sortable stickyHeader"') | |||
table.insert(resultPart, '\n|- class="headerRow-0"') | |||
table.insert(resultPart, '\n!colspan="2" | Season\n!Type\n!Modifiers') | |||
for i, season in ipairs(seasons) do | |||
local ns, localSeasonID = Shared.getLocalID(season.id) | |||
local reqs = seasonReqs[localSeasonID] | |||
table.insert(resultPart, '\n|-') | |||
table.insert(resultPart, '\n|class="table-img"| ' .. Icons.Icon({season.name, type='township', size=50, nolink=true, notext=true})) | |||
table.insert(resultPart, '\n| ' .. Icons.Icon({season.name, type='township', nolink=true, noicon=true})) | |||
table.insert(resultPart, '\n| ' .. (season.order <= 3 and 'Regular' or 'Rare')) | |||
if reqs ~= nil then | |||
table.insert(resultPart, '<br/>Requires ' .. reqs) | |||
end | |||
table.insert(resultPart, '\n| ' .. Modifiers.getModifiersText(season.modifiers)) | |||
end | end | ||
table.insert(resultPart, '\n|}') | |||
return table.concat(resultPart) | |||
end | end | ||
-- | -- Generates a table listing all biomes and their associated requirements | ||
-- | function p.getBiomeTable(frame) | ||
local resultPart = {} | |||
table.insert(resultPart, '{| class="wikitable sortable stickyHeader"') | |||
end | table.insert(resultPart, '\n|- class="headerRow-0"') | ||
table.insert(resultPart, '\n!rowspan="2" colspan="2"| Biome\n!colspan="3"| Requirements') | |||
table.insert(resultPart, '\n|- class="headerRow-1"') | |||
table.insert(resultPart, '\n! ' .. Icons.Icon({'Township', 'Level', type='skill', nolink=true})) | |||
table.insert(resultPart, '\n! ' .. Icons.Icon({'Township', 'Population', img='Population', type='township', section='Population' })) | |||
table.insert(resultPart, '\n! ' .. Icons.Icon({'Township', 'Forification', img='Fortification', type='township', section='Fortification' })) | |||
for i, biome in ipairs(Township.biomes) do | |||
local reqs = p._getTierRequirements(biome.tier, biome.abyssalTier) | |||
local fortification = reqs.fortification or 0 | |||
table.insert(resultPart, '\n|-\n|class="table-img"| ' .. Icons.Icon({biome.name, type='biome', size=50, nolink=true, notext=true})) | |||
table.insert(resultPart, '\n| ' .. biome.name) | |||
table.insert(resultPart, '\n|style="text-align:right"| ' .. (reqs.abyssalLevel or reqs.level)) | |||
table.insert(resultPart, '\n|style="text-align:right" data-sort-value="' .. reqs.population .. '"| ' .. Num.formatnum(reqs.population)) | |||
table.insert(resultPart, '\n|style="text-align:right" data-sort-value="' .. fortification .. '"| ' .. Num.formatnum(fortification)) | |||
end | |||
table.insert(resultPart, '\n|}') | |||
return table.concat(resultPart) | |||
return | |||
end | end | ||
-- | -- Generates a table showing which buildings can be built in which biomes | ||
function p. | -- Skips upgraded buildings | ||
local | function p.getBuildingBiomeTable(frame) | ||
local tbl = mw.html.create('table') | |||
:addClass('wikitable sortable stickyHeader') | |||
:css('text-align', 'center') | |||
local header = mw.html.create('tr'):addClass('headerRow-0') | |||
local level = mw.html.create('tr'):addClass('sorttop') | |||
local pop = mw.html.create('tr'):addClass('sorttop') | |||
local fort = mw.html.create('tr'):addClass('sorttop') | |||
local | |||
- | header:tag('th') | ||
:css('z-index', '2') | |||
:wikitext('Building') | |||
level:tag('th') | |||
:wikitext(Icons.Icon({'Township', 'Level', type='skill', nolink=true})) | |||
pop:tag('th') | |||
:wikitext(Icons.Icon({'Township', 'Population', img='Population', type='township', section='Population' })) | |||
fort:tag('th') | |||
:wikitext(Icons.Icon({'Township', 'Fortification', img='Fortification', type='township', section='Fortification' })) | |||
for _, biome in ipairs(Township.biomes) do | |||
local reqs = p._getTierRequirements(biome.tier, biome.abyssalTier) | |||
header:tag('th') | |||
:wikitext(Icons.Icon({biome.name, type='biome', notext=true, nolink=true}).. '<br/>' .. biome.name) | |||
level:tag('td') | |||
:wikitext(Num.formatnum((reqs.abyssalLevel or reqs.level))) | |||
pop:tag('td') | |||
:wikitext(Num.formatnum(reqs.population)) | |||
fort:tag('td') | |||
:wikitext(Num.formatnum((reqs.fortification or 0))) | |||
end | end | ||
-- | tbl:node(header) | ||
tbl:node(level) | |||
tbl:node(pop) | |||
tbl:node(fort) | |||
for _, _building in ipairs(p._sortedBuildings(false)) do | |||
-- Fix melvorF:Statues | |||
local building = p._getBuildingByID(_building.id) | |||
-- Skip upgraded buildings | |||
if p._getBuildingDowngrade(building) == nil then | |||
-- Populate the biome habitability data | |||
local buildingBiomes = {} | |||
-- Set all valid biomes to true | |||
for _, biomeid in ipairs(building.biomes) do | |||
buildingBiomes[biomeid] = true | |||
end | |||
local trow = tbl:tag('tr') | |||
trow:tag('th') | |||
:css('text-align', 'left') | |||
:attr('data-sort-value', building.name) | |||
:wikitext(Icons.Icon({building.name, type='building'})) | |||
for _, biome in ipairs(Township.biomes) do | |||
if buildingBiomes[biome.id] then | |||
trow:tag('td') | |||
:addClass('table-positive') | |||
:wikitext('✓') | |||
else | |||
trow:tag('td') | |||
end | |||
end | |||
end | |||
end | end | ||
-- | return tostring(tbl) | ||
end | |||
-- Generates a table contaning each building plus their relevant information | |||
function p.getBuildingTable(frame) | |||
local resultPart = {} | |||
-- Change structure of biomes data for ease of use later | |||
local biomesByID = {} | |||
for i, biome in ipairs(Township.biomes) do | |||
biomesByID[biome.id] = biome | |||
end | end | ||
-- | -- Generate table header | ||
table.insert(resultPart, '{| class="wikitable sortable stickyHeader"') | |||
table.insert(resultPart, '\n|- class="headerRow-0"') | |||
table.insert(resultPart, '\n!colspan="2"|Building\n!Requirements\n!Max Built') | |||
table.insert(resultPart, '\n!Biomes\n!Cost\n!Provides') | |||
local buildings = p._sortedBuildings(false) | |||
-- | for i, building in ipairs(buildings) do | ||
-- Number of rows per building is dictated by number of biomes | |||
local buildingName = (building.id == 'melvorF:Statues' and 'Statue of Worship') or building.name | |||
local firstRow = true | |||
local rowCount = Shared.tableCount(building.biomes) | |||
local rowSpan = (rowCount > 1 and ' rowspan="' .. rowCount .. '"') or '' | |||
local rowSpanOnly = (rowCount > 1 and '|' .. rowSpan) or '' | |||
for j, biomeID in ipairs(building.biomes) do | |||
local biome = biomesByID[biomeID] | |||
if firstRow then | |||
table.insert(resultPart, '\n|-') | |||
table.insert(resultPart, '\n|class="table-img"' .. rowSpan .. '| ' .. Icons.Icon({buildingName, type='building', notext=true, size=50})) | |||
table.insert(resultPart, '\n' .. rowSpanOnly .. '| ' .. Icons.getExpansionIcon(building.id) .. Icons.Icon({buildingName, type='building', noicon=true})) | |||
table.insert(resultPart, '\n|' .. 'data-sort-value="' .. building.tier .. '"' .. rowSpan .. '| ' .. (p._getTierText(building.tier, building.abyssalTier) or '')) | |||
table.insert(resultPart, '\n|style="text-align:right"' .. rowSpan .. '| ' .. building.maxUpgrades) | |||
firstRow = false | |||
else | |||
table.insert(resultPart, '\n|-') | |||
end | |||
table.insert( | -- This section generates by biome rows | ||
table.insert(resultPart, '\n| ' .. Icons.Icon({biome.name, type='biome', nolink=true})) | |||
table.insert(resultPart, '\n| ' .. p._getBuildingCostText(building, biomeID)) | |||
local providesText = p._getBuildingBenefitText(building, biomeID) | |||
if building.modifiers ~= nil then | |||
local modText = Modifiers.getModifiersText(building.modifiers) | |||
if providesText == nil then | |||
providesText = modText | |||
else | |||
providesText = providesText .. '<br/>' .. modText | |||
end | |||
end | |||
table.insert(resultPart, '\n| ' .. (providesText or '')) | |||
end | end | ||
end | end | ||
table.insert(resultPart, '\n|}') | |||
table.insert( | return table.concat(resultPart) | ||
return table.concat( | |||
end | end | ||
-- | -- Builds the table of trader items | ||
function p.getTraderTable(frame) | |||
function p. | local resultPart = {} | ||
local | |||
-- Build table header | |||
table.insert(resultPart, '{| class="wikitable sortable stickyHeader"') | |||
table.insert(resultPart, '\n|- class="headerRow-0"') | |||
table.insert(resultPart, '\n!colspan="2"| Item\n!Description\n!style="min-width:60px"| Cost\n!Requirements') | |||
for i, tsResource in ipairs(Township.itemConversions.fromTownship) do | |||
local res = GameData.getEntityByID(Township.resources, tsResource.resourceID) | |||
for j, tradeDef in ipairs(tsResource.items) do | |||
local item = Items.getItemByID(tradeDef.itemID) | |||
local itemDesc = item.customDescription | |||
if itemDesc == nil then | |||
if item.modifiers ~= nil then | |||
itemDesc = Modifiers.getModifiersText(item.modifiers, false, true) | |||
else | |||
for | itemDesc = '' | ||
end | |||
local | |||
end | end | ||
local resQty = math.max(item.sellsFor, 2) | |||
local costSort = i * 10000 + resQty | |||
table.insert(resultPart, '\n|-\n| ' .. Icons.Icon({item.name, type='item', size=50, notext=true})) | |||
table.insert(resultPart, '\n| ' .. Icons.getExpansionIcon(item.id) .. Icons.Icon({item.name, type='item', noicon=true})) | |||
table.insert(resultPart, '\n| ' .. itemDesc) | |||
table.insert(resultPart, '\n|data-sort-value="' .. costSort ..'" style="text-align:right"| ' .. Icons.Icon({res.name, type='resource', qty=resQty, notext=true})) | |||
table.insert(resultPart, '\n| ' .. Shop.getRequirementString(tradeDef.unlockRequirements)) | |||
end | end | ||
end | end | ||
table.insert(resultPart, '\n|}') | |||
return table.concat(resultPart) | |||
end | end | ||
-- | -- Generates a table showing all the worship options | ||
function p. | function p.getWorshipTable() | ||
local | local function getCheckpointCell(checkpoint) | ||
return '\n|-\n!' .. checkpoint .. '%<br/>' .. Num.formatnum(checkpoint * Township.maxWorship / 100) .. '/' .. Num.formatnum(Township.maxWorship) | |||
end | |||
local worships = GameData.getEntities(Township.worships, function(w) return not w.isHidden end) | |||
local ret = {} | |||
worship = ' | table.insert(ret, '{| class="wikitable stickyHeader"') | ||
table.insert(ret, '\n!' .. Icons.Icon({'Worship', type='township', nolink=true})) | |||
for | -- Names | ||
if | for _, worship in ipairs(worships) do | ||
local | table.insert(ret, '\n!' .. Icons.Icon({worship.name, type='monster', size=50}) .. Icons.Icon({'Statue of ' .. worship.name, type='building', size=50, notext=true})) | ||
if | end | ||
-- Requirements | |||
table.insert(ret, '\n|-\n!Requirements') | |||
for _, worship in ipairs(worships) do | |||
local cellStyle = (Shared.tableIsEmpty(worship.unlockRequirements) and 'class="table-na"') or 'style="text-align:center"' | |||
table.insert(ret, '\n|' .. cellStyle ..'| ' .. Shop.getRequirementString(worship.unlockRequirements)) | |||
end | |||
-- Season multipliers | |||
table.insert(ret, '\n|-\n!Bonus Seasons') | |||
for _, worship in ipairs(worships) do | |||
local bonusPart = {} | |||
local cellStyle = 'style="text-align:center"' | |||
if Shared.tableIsEmpty(worship.seasonMultiplier) then | |||
bonusPart, cellStyle = {'None'}, 'class="table-na"' | |||
end | |||
for i, seasonMult in ipairs(worship.seasonMultiplier) do | |||
local season = GameData.getEntityByID(Township.seasons, seasonMult.seasonID) | |||
if season ~= nil then | |||
table.insert(bonusPart, Icons.Icon({season.name, type='township', nolink=true}) .. ' (' .. seasonMult.multiplier .. 'x)') | |||
end | end | ||
end | end | ||
table.insert(ret, '\n|' .. cellStyle .. '| ' .. table.concat(bonusPart, '<br/>')) | |||
end | end | ||
-- Base modifiers | |||
table.insert(ret, getCheckpointCell(0)) | |||
for _, worship in ipairs(worships) do | |||
table.insert(ret, '\n| ' .. Modifiers.getModifiersText(worship.modifiers)) | |||
end | end | ||
-- | -- Checkpoint modifiers | ||
for i, checkpoint in ipairs(Township.worshipCheckpoints) do | |||
table.insert(ret, getCheckpointCell(checkpoint)) | |||
for _, worship in ipairs(worships) do | |||
table.insert(ret, '\n| ' .. Modifiers.getModifiersText(worship.checkpoints[i])) | |||
end | |||
end | end | ||
local | |||
-- Total sum | |||
-- TODO Needs fixing, no function currently for aggregating modifiers | |||
--[==[ | |||
table.insert(ret, '\n|-\n!Total') | |||
for _, worship in ipairs(worships) do | |||
local modifiers = Shared.clone(worship.modifiers) | |||
for _, checkpoint in ipairs(worship.checkpoints) do | |||
for modifier, magnitude in pairs(checkpoint) do | |||
local swappedModifier = string.sub(modifier, 1, string.len('increased')) == 'increased' and string.gsub(modifier, 'increased', 'decreased') or string.gsub(modifier, 'decreased', 'increased') | |||
-- The modifier already exists, so we add the two modifiers together | |||
if modifiers[modifier] ~= nil then | |||
modifiers[modifier] = modifiers[modifier] + magnitude | |||
-- The inverse modifier already exists, so we subtract the negative value of the new modifier | |||
elseif modifiers[swappedModifier] ~= nil then | |||
modifiers[swappedModifier] = modifiers[swappedModifier] - magnitude | |||
-- The modifier does not exist, so create the modifier | |||
else | |||
modifiers[modifier] = magnitude | |||
end | |||
end | |||
end | |||
table.insert(ret, '\n|' .. Modifiers.getModifiersText(modifiers)) | |||
end | end | ||
return | --]==] | ||
table.insert(ret, '\n|}') | |||
return table.concat(ret) | |||
end | end | ||
-- | -- Gets a building and prepares all the relevant stats for the building, presented as an infobox | ||
function p. | function p.getBuildingInfoBox(frame) | ||
if building | local name = frame.args ~= nil and frame.args[1] or frame | ||
return | local building = p._getBuildingByName(name) | ||
if building == nil then | |||
return Shared.printError('No building named "' .. name .. '" exists in the data module') | |||
end | end | ||
-- | local ret = {} | ||
-- Header | |||
table.insert(ret, '{| class="wikitable infobox"') | |||
local | -- Name | ||
table.insert(ret, '\n|-\n! ' .. Icons.getExpansionIcon(building.id) .. building.name) | |||
-- Icon | |||
table.insert( | table.insert(ret, '\n|-\n|style="text-align:center"| ' .. Icons.Icon({building.name, type='building', size='250', notext=true})) | ||
-- ID | |||
table.insert(ret, '\n|-\n| <b>Building ID:</b> ' .. building.id) | |||
-- Tier | |||
local tier = p._getTierText(building.tier, building.abyssalTier) | |||
table.insert(ret, '\n|-\n| <b>Requirements:</b><br/>' .. tier) | |||
-- Upgrades From | |||
table.insert(ret, '\n|-\n| <b>Base Cost:</b>') | |||
local upgradesFrom = p._getBuildingDowngrade(building) | |||
if upgradesFrom ~= nil then | |||
table.insert(ret, '<br/>' .. Icons.Icon({upgradesFrom.name, type='building'})) | |||
end | end | ||
return table.concat(cost, | -- Cost | ||
end | --table.insert(ret, '<br/>' .. p._getBuildingGroupedCostText(building)) | ||
local function getGroupedText(building, groupFunc) | |||
local biomeGroups = groupFunc(building) | |||
if Shared.tableCount(biomeGroups) == 1 then | |||
-- If only one entry then simply output the cost | |||
return biomeGroups[1].cost | |||
else | |||
-- Otherwise, split by biome group | |||
local resultPart = {} | |||
table.insert(resultPart, '{| class="wikitable" style="text-align:center; margin: 0.25em 0 0 0"') | |||
for i, biomeGroup in ipairs(biomeGroups) do | |||
local biomeText = {} | |||
for j, biomeID in ipairs(biomeGroup.biomeIDs) do | |||
local biome = GameData.getEntityByID(Township.biomes, biomeID) | |||
table.insert(biomeText, Icons.Icon({biome.name, type='biome', notext=true, nolink=true, alt=biome.name})) | |||
end | |||
table.insert(resultPart, '\n|-\n| ' .. table.concat(biomeText, '<br/>')) | |||
table.insert(resultPart, '\n| ' .. biomeGroup.cost) | |||
end | |||
table.insert(resultPart, '\n|}') | |||
return table.concat(resultPart) | |||
end | |||
end | |||
table.insert(ret, '\n' .. getGroupedText(building, p._getBuildingGroupedCosts)) | |||
-- | -- Upgrades To | ||
local upgradesTo = p._getBuildingUpgrade(building) | |||
if upgradesTo ~= nil then | |||
end | table.insert(ret, '\n|-\n| <b>Upgrades To:</b>') | ||
table.insert(ret, '<br/>' .. Icons.Icon({upgradesTo.name, type='building'})) | |||
table.insert(ret, '\n' .. getGroupedText(upgradesTo, p._getBuildingGroupedCosts)) | |||
end | |||
-- | -- Maximum built | ||
local biomeCount = Shared.tableCount(building.biomes) | |||
local | local maxText = Num.formatnum(building.maxUpgrades) | ||
if biomeCount > 1 then | |||
maxText = maxText .. ' per biome, ' .. Num.formatnum(biomeCount * building.maxUpgrades) .. ' total' | |||
end | end | ||
if | table.insert(ret, '\n|-\n| <b>Maximum Built:</b><br/>' .. maxText) | ||
-- Benefits | |||
local benefits = p._getBuildingGroupedBenefitText(building) | |||
if benefits ~= nil and benefits ~= '' then | |||
table.insert(ret, '\n|-\n| <b>Provides:</b><br/>' .. benefits) | |||
end | end | ||
-- Biomes | |||
table.insert(ret, '\n|-\n| <b>Biomes:</b>') | |||
for _, biomeid in ipairs(building.biomes) do | |||
local biome = GameData.getEntityByID(Township.biomes, biomeid) | |||
table.insert(ret, '<br/>' .. Icons.Icon({biome.name, type='biome', nolink=true})) | |||
end | |||
-- End | |||
table.insert(ret, '\n|}') | |||
return table.concat(ret) | |||
end | end | ||
-- Returns an upgrade table of a building | -- Returns an upgrade table of a building | ||
function p. | function p.getBuildingUpgradeTable(frame) | ||
local buildingname = frame.args ~= nil and frame.args[1] or frame | local buildingname = frame.args ~= nil and frame.args[1] or frame | ||
local building = p. | local building = p._getBuildingByName(buildingname) | ||
if building == nil then | |||
return Shared.printError('No building named "' .. buildingname .. '" exists in the data module') | |||
end | |||
-- Let's find the base building | -- Let's find the base building | ||
local baseBuilding = building | local baseBuilding = building | ||
while true do | while true do | ||
local previousBuilding = p. | local previousBuilding = p._getBuildingDowngrade(baseBuilding) | ||
if previousBuilding ~= nil then | if previousBuilding ~= nil then | ||
baseBuilding = previousBuilding | baseBuilding = previousBuilding | ||
Line 540: | Line 702: | ||
end | end | ||
end | end | ||
-- Let's make a list of all the buildings | -- Let's make a list of all the buildings | ||
-- Return empty string if there is only 1 building in the upgrade chain (i.e. no upgrades/downgrades) | -- Return empty string if there is only 1 building in the upgrade chain (i.e. no upgrades/downgrades) | ||
Line 547: | Line 709: | ||
while true do | while true do | ||
table.insert(buildingList, _curBuilding) | table.insert(buildingList, _curBuilding) | ||
_curBuilding = p. | _curBuilding = p._getBuildingUpgrade(_curBuilding) | ||
if _curBuilding == nil then | if _curBuilding == nil then | ||
break | break | ||
Line 555: | Line 717: | ||
return '' | return '' | ||
end | end | ||
local ret = {} | local ret = {} | ||
table.insert(ret, ' | table.insert(ret, '\n== Upgrade Chart ==') | ||
table.insert(ret, ' | table.insert(ret, '\n{| class="wikitable" style="text-align:center"') | ||
-- Name | -- Name | ||
table.insert(ret, ' | table.insert(ret, '\n|-\n!colspan="2"| Name') | ||
for _, building in ipairs(buildingList) do | for _, building in ipairs(buildingList) do | ||
table.insert(ret, ' | table.insert(ret, '\n!' .. Icons.getExpansionIcon(building.id) .. Icons.Icon({building.name, type='building'})) | ||
end | end | ||
-- Tier | -- Tier | ||
table.insert(ret, ' | table.insert(ret, '\n|-\n!colspan="2"| Requirements') | ||
for _, building in ipairs(buildingList) do | for _, building in ipairs(buildingList) do | ||
table.insert(ret, '\n|' .. p._getTierText(building.tier, building.abyssalTier)) | |||
table.insert(ret, ' | |||
end | end | ||
-- Cost | -- Cost | ||
table.insert(ret, ' | local biomeCount = Shared.tableCount(baseBuilding.biomes) | ||
for _, building in ipairs(buildingList) do | table.insert(ret, '\n|-\n!rowspan="' .. biomeCount .. '"| Cost') | ||
local firstBiome = true | |||
for _, biomeID in ipairs(baseBuilding.biomes) do | |||
local biome = GameData.getEntityByID(Township.biomes, biomeID) | |||
table.insert(ret, (firstBiome and '' or '\n|-') .. '\n! ' .. Icons.Icon({biome.name, type='biome', nolink=true})) | |||
for _, building in ipairs(buildingList) do | |||
local cost = p._getBuildingCostText(building, biomeID) | |||
table.insert(ret, '\n| ' .. cost) | |||
end | |||
firstBiome = false | |||
end | end | ||
-- | -- Benefits | ||
local benefitText = {} | |||
- | table.insert(benefitText, '\n|-\n!rowspan="' .. biomeCount .. '"| Benefits') | ||
firstBiome = true | |||
local | local hasText = false | ||
local | for _, biomeID in ipairs(baseBuilding.biomes) do | ||
local biome = GameData.getEntityByID(Township.biomes, biomeID) | |||
table.insert(benefitText, (firstBiome and '' or '\n|-') .. '\n! ' .. Icons.Icon({biome.name, type='biome', nolink=true})) | |||
for _, building in ipairs(buildingList) do | for _, building in ipairs(buildingList) do | ||
local | local benefit = p._getBuildingBenefitText(building, biomeID, true) or '' | ||
if not hasText and benefit ~= '' then | |||
hasText = true | |||
end | |||
table.insert(benefitText, '\n| ' .. benefit) | |||
end | end | ||
firstBiome = false | |||
end | |||
if hasText then | |||
-- Only add benefits rows if the building has benefits to display | |||
table.insert(ret, table.concat(benefitText)) | |||
end | end | ||
-- End | -- End | ||
table.insert(ret, ' | table.insert(ret, '\n|}') | ||
return table.concat(ret) | return table.concat(ret) | ||
end | end | ||
-- Returns a row containing a task given a title and a task table | |||
-- | function p._getTaskRow(title, task, isDailyTask) | ||
local ret = {} | |||
function p. | |||
local | -- If has description, we will need to rowspan the title by 2, and insert a description with colspan 2 | ||
local hasDescription = false | |||
if task.description ~= nil then | |||
hasDescription = true | |||
end | |||
local titlespan = hasDescription == true and 'rowspan="2"|' or '' | |||
-- Title | |||
-- | table.insert(ret, '\n|-') | ||
if | table.insert(ret, '\n!' .. titlespan .. title) | ||
-- Description | |||
if hasDescription then | |||
table.insert(ret, '\n|colspan="2"|' .. task.description) | |||
table.insert(ret, '\n|-') | |||
end | end | ||
-- Requirements | |||
table.insert(ret, '\n|') | |||
-- Determines order of requirements output | |||
local reqOrder = { | |||
["items"] = 10, | |||
["monsters"] = 20, | |||
["monsterWithItems"] = 30, | |||
["skillXP"] = 40, | |||
["buildings"] = 50, | |||
["numPOIs"] = 60, | |||
["numRefinements"] = 70 | |||
} | |||
local reqTextPart = {} | |||
local function getItemText(itemID) | |||
local item = Items.getItemByID(itemID) | |||
if item == nil then | |||
local | return Shared.printError('Unknown item: ' .. (itemID or 'nil')) | ||
else | |||
end | return Icons.Icon({item.name, type='item'}) | ||
end | |||
end | |||
local function getMonsterText(monsterID) | |||
local monster = Monsters.getMonsterByID(monsterID) | |||
if monster == nil then | |||
return Shared.printError('Unknown monster: ' .. (monsterID or 'nil')) | |||
else | |||
return Icons.Icon({Monsters.getMonsterName(monster), type='monster'}) | |||
end | |||
end | |||
for goalType, goalData in pairs(task.goals) do | |||
local typeOrder = reqOrder[goalType] or 0 | |||
local goalText = nil | |||
if type(goalData) == 'table' then | |||
-- Goal data is a table | |||
for goalIdx, goalObj in ipairs(goalData) do | |||
if goalType == 'items' then | |||
goalText = Num.formatnum(goalObj.quantity) .. ' ' .. getItemText(goalObj.id) | |||
elseif goalType == 'monsters' then | |||
goalText = Num.formatnum(goalObj.quantity) .. ' ' .. getMonsterText(goalObj.id) | |||
elseif goalType == 'monsterWithItems' then | |||
local itemsText = {} | |||
for i, itemID in ipairs(goalObj.itemIDs) do | |||
table.insert(itemsText, getItemText(itemID)) | |||
end | |||
goalText = Num.formatnum(goalObj.quantity) .. ' ' .. getMonsterText(goalObj.monsterID) .. ' with ' .. table.concat(itemsText, ', ') .. ' equipped' | |||
elseif goalType == 'skillXP' then | |||
local skillName = GameData.getSkillData(goalObj.id).name | |||
goalText = Num.formatnum(goalObj.quantity) .. ' ' .. Icons.Icon({skillName, type='skill'}) .. ' XP' | |||
elseif goalType == 'buildings' then | |||
local buildingName = p._GetBuildingByID(goalObj.id).name | |||
goalText = Num.formatnum(goalObj.quantity) .. ' ' .. Icons.Icon({buildingName, type='building'}) | |||
elseif goalType == 'numPOIs' then | |||
local mapName = GameData.getEntityByID(GameData.skillData.Cartography.worldMaps, goalObj.worldMapID).name | |||
goalText = 'Discover ' .. Num.formatnum(goalObj.quantity) .. ' Points of Interest in ' .. Icons.Icon({'Cartography', type='skill'}) .. ' world map of ' .. mapName | |||
else | |||
goalText = Shared.printError('Unknown goal type: ' .. (goalType or 'nil')) | |||
end | |||
table.insert(reqTextPart, { | |||
["goalOrder"] = typeOrder, | |||
["subOrder"] = goalIdx, | |||
["text"] = goalText | |||
}) | |||
end | |||
else | |||
-- Goal data is another value of some type | |||
if goalType == 'numRefinements' then | |||
goalText = 'Refine dig site maps in ' .. Icons.Icon({'Cartography', type='skill'}) .. ' ' .. Num.formatnum(goalData) .. ' times' | |||
else | |||
goalText = Shared.printError('Unknown goal type: ' .. (goalType or 'nil')) | |||
end | |||
table.insert(reqTextPart, { | |||
["goalOrder"] = typeOrder, | |||
["subOrder"] = 0, | |||
["text"] = goalText | |||
}) | |||
end | |||
end | end | ||
table.sort(reqTextPart, | |||
function(a, b) | |||
if a.goalOrder == b.goalOrder then | |||
return a.subOrder < b.subOrder | |||
else | |||
return a.goalOrder < b.goalOrder | |||
end | |||
end | |||
) | |||
-- | local requirements = {} | ||
for i, req in ipairs(reqTextPart) do | |||
local | table.insert(requirements, req.text) | ||
table.insert( | end | ||
table.insert( | -- We don't check tasks.requirements (so far it's only used to enumerate the Tutorial tasks so you only see 1 at a time) | ||
for | table.insert(ret, table.concat(requirements, '<br/>')) | ||
table.insert(ret, ' | -- Rewards | ||
table.insert(ret, '\n|') | |||
local rewards = {} | |||
local rewardsVariableQty = {} | |||
if task.rewards.currencies ~= nil then | |||
for _, currReward in ipairs(task.rewards.currencies) do | |||
if isDailyTask and currReward.id ~= 'melvorD:GP' then | |||
table.insert(rewardsVariableQty, Icons._Currency(currReward.id)) | |||
elseif not isDailyTask then | |||
table.insert(rewards, Icons._Currency(currReward.id, currReward.quantity)) | |||
end | |||
end | |||
end | |||
for _, item in ipairs(task.rewards.items) do | |||
local itemname = GameData.getEntityByID('items', item.id).name | |||
table.insert(rewards, Num.formatnum(item.quantity)..' '..Icons.Icon({itemname, type='item'})) | |||
end | |||
for _, skill in ipairs(task.rewards.skillXP) do | |||
if not (isDailyTask and skill.id == 'melvorD:Township') then | |||
local skillname = GameData.getSkillData(skill.id).name | |||
table.insert(rewards, Num.formatnum(skill.quantity)..' '..Icons.Icon({skillname, type='skill'})..' XP') | |||
end | |||
end | |||
for _, townshipResource in ipairs(task.rewards.townshipResources) do | |||
local resourcename = p._getResourceByID(townshipResource.id).name | |||
table.insert(rewards, Num.formatnum(townshipResource.quantity)..' '..Icons.Icon({resourcename, type='resource'})) | |||
end | |||
if not Shared.tableIsEmpty(rewardsVariableQty) then | |||
table.insert(ret, '[[Township#Casual Tasks|Variable]] ' .. table.concat(rewardsVariableQty, ', ') .. '<br/>') | |||
end | |||
table.insert(ret, table.concat(rewards, '<br/>')) | |||
-- Unlock requirements, daily task specific | |||
if isDailyTask then | |||
table.insert(ret, '\n|' .. Shop.getRequirementString(task.requirements)) | |||
end | end | ||
return table.concat(ret) | return table.concat(ret) | ||
end | end | ||
-- | -- Returns all the tasks of a given category | ||
-- | -- TODO: Support casual tasks | ||
function p. | function p.getTaskTable(frame) | ||
local category = frame.args ~= nil and frame.args[1] or frame | |||
local categoryData = GameData.getEntityByName(Township.taskCategories, category) | |||
local taskData, categoryName, isDailyTask = nil, nil, false | |||
if category == 'Daily' then | |||
isDailyTask = true | |||
taskData = Township.casualTasks | |||
categoryName = 'Casual' | |||
elseif categoryData ~= nil then | |||
taskData = Township.tasks | |||
categoryName = categoryData.name | |||
else | |||
return Shared.printError('Invalid task category specified: ' .. (tostring(category) or 'nil')) | |||
end | |||
local taskcount = 0 | |||
local ret = {} | local ret = {} | ||
table.insert(ret, ' | table.insert(ret, '{| class="wikitable lighttable stickyHeader" style="text-align:left"') | ||
table.insert(ret, '\ | table.insert(ret, '\n|- class="headerRow-0"') | ||
table.insert(ret, '\n!Task') | |||
table.insert(ret, '\n!Requirements') | |||
table.insert(ret, '\n!Rewards') | |||
if isDailyTask then | |||
table.insert(ret, '<br/>(In addition to [[Township#Casual Tasks|Variable]] ' .. Icons._Currency('melvorD:GP') .. ' & ' .. Icons.Icon({'Township', type='skill', notext=true}) .. ' XP)') | |||
table.insert(ret, ' | |||
end | end | ||
if isDailyTask then | |||
table.insert(ret, '\n!Unlock Requirements') | |||
table.insert(ret, ' | |||
end | end | ||
for _, | for _, task in ipairs(taskData) do | ||
-- | -- Filter out other categories | ||
local | local categoryID, categoryNS, categoryLocalID = '', '', '' | ||
if categoryData ~= nil then | |||
categoryID = categoryData.id | |||
if | categoryNS, categoryLocalID = Shared.getLocalID(categoryID) | ||
-- | end | ||
local | if isDailyTask or task.category == categoryID or task.category == categoryLocalID then | ||
taskcount = taskcount + 1 | |||
for _, | local title = categoryName .. ' ' .. taskcount | ||
table.insert(ret, p._getTaskRow(title, task, isDailyTask)) | |||
end | |||
end | |||
table.insert(ret, '\n|}') | |||
return table.concat(ret) | |||
end | |||
-- Returns a table containing all the tasks that reference an item or monster | |||
-- e.g. p.getTaskReferenceTable({'Chicken Coop', 'dungeon'}) | |||
-- name = item or monster name | |||
-- type = 'item' or 'monster' or 'dungeon' | |||
function p.getTaskReferenceTable(frame) | |||
-- Returns a set containing all the desired IDs | |||
local function GetReferenceIDs(referenceName, referenceType) | |||
local IDs = {} | |||
if referenceType == 'dungeon' then | |||
-- We get the tasks associated with all monsters in the dungeon | |||
local area = nil | |||
local areaTypes = {'dungeons', 'abyssDepths'} | |||
for _, areaType in ipairs(areaTypes) do | |||
area = GameData.getEntityByName(areaType, referenceName) | |||
if area ~= nil then | |||
break | |||
end | |||
end | end | ||
local monsters = area.monsterIDs | |||
for _, | for _, monster in ipairs(monsters) do | ||
IDs[monster] = true | |||
end | end | ||
end | |||
if referenceType == 'item' then | |||
IDs[GameData.getEntityByName('items', referenceName).id] = true | |||
end | |||
if referenceType == 'monster' then | |||
IDs[Monsters.getMonster(referenceName).id] = true | |||
end | |||
return IDs | |||
end | |||
-- For a task, returns where to search for the desired IDs, given the type | |||
local function GetGetSearchTables(referenceType) | |||
local function searchItems(task) | |||
return {task.goals.items, task.rewards.items} | |||
end | |||
local function searchMonsters(task) | |||
return {task.goals.monsters} | |||
end | |||
-- item -> searchItems; monster or dungeon -> searchMonsters | |||
return referenceType == 'item' and searchItems or searchMonsters | |||
end | |||
local args = frame.args ~= nil and frame.args or frame | |||
local referenceName = Shared.fixPagename(args[1]) | |||
local referenceType = args[2] | |||
local referenceIDs = GetReferenceIDs(referenceName, referenceType) | |||
-- GetSearchTables = function searchItems/Monsters(task) | |||
local GetSearchTables = GetGetSearchTables(referenceType) | |||
local function checkTask(task) | |||
local function checkID(entry) | |||
return referenceIDs[entry.id] ~= nil | |||
end | |||
for _, searchTable in pairs(GetSearchTables(task)) do -- ipairs won't work if first table is nil | |||
-- Check to see if the table contains any of the IDs in referenceIDs | |||
if searchTable[1] ~= nil then -- Make sure table is not empty | |||
if #GameData.getEntities(searchTable, checkID) ~= 0 then -- Make sure we have at least 1 match | |||
return true | |||
end | end | ||
end | end | ||
end | end | ||
return false | |||
end | |||
-- Find all tasks that contain the desired ids | |||
local tasks = GameData.getEntities(Township.tasks, checkTask) | |||
if #tasks == 0 then | |||
return '' | |||
end | |||
-- Build the table | |||
local ret = {} | |||
table.insert(ret, '==Tasks==') | |||
table.insert(ret, '\n{| class="wikitable" style="text-align:left"') | |||
table.insert(ret, '\n!Task') | |||
table.insert(ret, '\n!Requirements') | |||
table.insert(ret, '\n!Rewards') | |||
for _, task in ipairs(tasks) do | |||
-- Some categories have a local ID, resolve this before looking up the task category | |||
local taskNS, taskLocalID = Shared.getLocalID(task.id) | |||
local catID = Shared.getNamespacedID(taskNS, task.category) | |||
local categoryname = GameData.getEntityByID(Township.taskCategories, catID).name | |||
local title = '[[Township/Tasks#'..categoryname..'|'..categoryname..']]' | |||
table.insert(ret, p._getTaskRow(title, task, false)) | |||
end | end | ||
table.insert(ret, ' | table.insert(ret, '\n|}') | ||
return table.concat(ret) | return table.concat(ret) | ||
end | end | ||
return p | return p |