A documentação para este módulo pode ser criada na página Módulo:Cosmetics/doc
local p = {}
local utils = require("Module:Utils")
local data = require("Module:Datatable" .. utils.lang())
local cosData = require("Module:Datatable/Cosmetics/Arbiter" .. utils.lang())
local str = require("Module:Strings")
local killersM = require("Module:Killers")
local survM = require("Module:Survivors")
local frame = mw.getCurrentFrame()
p.strings = {
notFound = "Não Encontrado!",
noCosmetics = "No cosmetics found. Cosmetics data probably weren't updated yet." .. cstr.contact,
cosmetics = "Cosméticos",
character = "Personagem",
gender = "Gênero",
name = "Nome",
origin = "Origem",
actor = "Dublador(a)",
prestigeReward = "Recompensa de Nível de Prestígio #plv", --#plv = prestige level
pCharmDesc = "Uma lembrança recebida ao dominar uma habilidade específica.",
expand = "Expandir",
collapse = "Colapsar",
thumbnail = "Miniatura",
contains = "Contém",
collectionName = "Nome da Coleção",
releaseDate = "Data de Lançamento",
modifier = "Modificador",
tome = "Livro",
price = "Preço",
desc = "Descrição",
riftTier = "Nível da Fenda",
piece = "Peça",
collection = "Coleção",
heads = "Heads",
masks = "Masks",
hairs = "Hairs",
torsos = "Torsos",
legs = "Legs",
bodies = "Bodies",
weapons = "Weapons",
arms = "Arms",
hands = "Hands",
upperBodies = "Upper Bodies",
--Collections indicating survivors'/killers' collections (these collections are sorted special way)
essentials = "Essentials",
aberrations = "Aberrations"
}
local strings = p.strings
----------------------------------------------
if utils.lang() ~= cstr.empty and (counter or 0) < 1 then
counter = (counter or 0) + 1
strings = require("Module:Cosmetics" .. utils.lang()).strings
end
p.bodyPositions_killer = {
[1] = {heads = "heads", masks = "masks", hairs = "heads", upperBodies = "upperBodies", arms = "arms", hands = "hands"},
[2] = {legs = "legs", bodies = "bodies", torsos = "torsos"},
[3] = {weapons = "weapons"}
}
p.bodyPositions_survivor = {
[1] = {heads = "heads", masks = "masks", hairs = "heads", arms = "arms", hands = "hands"},
[2] = {torsos = "torsos", bodies = "bodies", upperBodies = "upperBodies"},
[3] = {legs = "legs", weapons = "weapons"}
}
local cosCategories = {
store = "store",
rift = "rift"
}
function p.getAllOutfitsForChar(character)
character = utils.getCharacterByName(utils.resolveParameter(character, "character", true) or utils.resolveParameter(character))
if not character then return false end
local outfitList = {}
local fakeOutfits = {}
character.charTypeName = (utils.isKiller(character) and "killer") or "survivor"
for _, cosmetic in ipairs(cosData.outfits) do
if character.id == cosmetic[character.charTypeName] then
if cosmetic.fakeOutfit then
table.insert(fakeOutfits, table.copy(cosmetic)) --we must create a COPY of the cosmetic as the data are loaded via mw.loadData which is ReadOnly
else
table.insert(outfitList, table.copy(cosmetic))
end
end
end
for i, cosmetic in ipairs(outfitList) do
cosmetic.pieces = getUnderlyingPieces(cosmetic)
end
for i, cosmetic in ipairs(fakeOutfits) do
cosmetic.pieces = getUnderlyingPieces(cosmetic)
end
--mw.log(mw.dumpObject(outfitList))
--mw.log(mw.dumpObject(fakeOutfits))
return outfitList, fakeOutfits
end
function p.getCosmeticsByName(outfitNames,multiName)
multiName = multiName or utils.resolveParameter(outfitNames, "multiName", true) or utils.resolveParameter(outfitNames, 2)
outfitNames = utils.resolveParameter(outfitNames, 1)
outfitNames = string.replace(outfitNames, '[\n]', cstr.empty)
outfitNames = (outfitNames and string.split(outfitNames, ',')) or false
if not outfitNames then return strings.notFound end
dmp(outfitNames)
local outfits = {}
local fakeOutfits = {}
for _, cosmetic in ipairs(cosData.outfits) do
if cosmetic.fakeOutfit then
for piece, cosId in pairs(cosmetic.pieces) do
if table.contains(outfitNames, cosData[piece][cosId].name) then
table.insert(fakeOutfits, table.copy(cosmetic)) --we must create a COPY of the cosmetic as the data are loaded via mw.loadData which is ReadOnly
end
end
else
if table.contains(outfitNames, cosmetic.name) then
table.insert(outfits, table.copy(cosmetic))
end
end
--When this is enabled it will supress any multiName pieces. If we wan to optimise the loop anyway we should used a parameter multiName to know whether we expect multiple cosmetics with same name
--if #outfitNames == (#outfits + #fakeOutfits) then
-- break
--end
end
for i, cosmetic in ipairs(outfits) do cosmetic.pieces = getUnderlyingPieces(cosmetic) end
for i, cosmetic in ipairs(fakeOutfits) do cosmetic.pieces = getUnderlyingPieces(cosmetic) end
outfits = populateTomes(outfits)
fakeOutfits = populateTomes(fakeOutfits)
return renderCosmeticTable(outfits, fakeOutfits, true, true)
end
function p.getCosmeticsByCollection(collectionNames)
local collectionList = utils.resolveParameter(collectionNames, "collectionList", true)
collectionNames = utils.resolveParameter(collectionNames, 1)
collectionNames = (collectionNames and string.split(collectionNames, ',')) or false
if not collectionNames then return strings.notFound end
local outfits = {}
local fakeOutfits = {}
collectionList = (collectionList and {collectionList}) or getCollections(collectionNames)
local collectionIdList = table.get(collectionList, "id")
--dmp(collectionIdList)
for _, cosmetic in ipairs(cosData.outfits) do
if cosmetic.fakeOutfit then
for piece, cosId in pairs(cosmetic.pieces) do
if table.contains(collectionIdList, cosmetic.collectionId) then
table.insert(fakeOutfits, table.copy(cosmetic)) --we must create a COPY of the cosmetic as the data are loaded via mw.loadData which is ReadOnly
fakeOutfits[#fakeOutfits].collection = assignCollection(collectionList, cosmetic.collectionId)
end
end
else
if table.contains(collectionIdList, cosmetic.collectionId) then
table.insert(outfits, table.copy(cosmetic))
outfits[#outfits].collection = assignCollection(collectionList, cosmetic.collectionId)
end
end
end
for i, cosmetic in ipairs(outfits) do cosmetic.pieces = getUnderlyingPieces(cosmetic) end
for i, cosmetic in ipairs(fakeOutfits) do cosmetic.pieces = getUnderlyingPieces(cosmetic) end
outfits = populateTomes(outfits)
fakeOutfits = populateTomes(fakeOutfits)
return renderCosmeticTable(outfits, fakeOutfits, true, true)
end
--sorting list by characters stored in the main datatable - their order stored in the corresponding table is the same as we need
local function sortCosmeticsByCharacters(collectionList, charTable)
for _, character in ipairs(charTable) do
for _, collection in ipairs(collectionList) do
--string.find(collection.name, string.replace(character.name, "%-", "%%-")), in order to SEARCH a "-" sign we have to escape it "%-", and add another percent sign "%%-"
--so when we call strin.find() it will look at "%-" and interpret it as literally "-" instead of taking a "-" as a quantifier/magic character
if string.find(collection.name, utils.getCharacterFirstName(character)) or string.find(collection.name, string.replace(character.name, "%-", "%%-")) then
collection.rate = character.id
break
end
end
end
utils.sortByRate(collectionList)
end
function p.getCollectionsContainingString(containStrings)
containStrings = utils.resolveParameter(containStrings, 1)
containStrings = string.replace(containStrings, '[\n]', cstr.empty)
containStrings = (containStrings and string.split(containStrings, ',')) or false
if not containStrings then return strings.notFound end
local collectionList = {}
for _, collection in ipairs(cosData.collections) do
for _, containString in ipairs(containStrings) do
if string.find(collection.name, containString) then
table.add(collectionList, table.copy(collection)) --We don't do the table list for tabber here because we want to use generic sort function on names eventually
end
end
end
--sorting special collections
--lg("************************************ BEFORE ************************************")
--dmp(collectionList)
if containStrings[1] == strings.essentials then
sortCosmeticsByCharacters(collectionList, data.survivors)
elseif containStrings[1] == strings.aberrations then
sortCosmeticsByCharacters(collectionList, data.killers)
else
utils.sortByName(collectionList, true)
end
--lg("************************************ AFTER ************************************")
--dmp(collectionList)
--{{header = 2022, content = "..."}, {}, ...}
local tabberTable = {}
for _, collection in ipairs(collectionList) do
table.add(tabberTable,
{
header = collection.name,
content = p.getCosmeticsByCollection({args={collectionList = collection}})
}
)
end
return
'<div class = "tableTabber">' .. nl ..
utils.getTabberFromTable(tabberTable) .. nl ..
'</div>'
end
function assignCollection(collectionList, collectionId)
for _, collection in ipairs(collectionList) do
if collection.id == collectionId then
return collection
end
end
end
function getCollections(collectionNames)
result = {}
for _, collection in ipairs(cosData.collections) do
if table.contains(collectionNames, collection.name, true) then
table.add(result, collection)
end
if #collectionNames == #result then break end
end
return result
end
function getUnderlyingPieces(cosmetic)
local pieceObjects = {}
for key, pieceId in pairs(cosmetic.pieces) do
--mw.log("cosData[key][pieceId].id == pieceId :: " .. cosData[key][pieceId].id .. " == " .. pieceId)
if cosData[key][pieceId].id == pieceId then --optimization => before we search for the piece in according body type list we try to find it by index (presuming that index == ID, e.g. we use piece ID as an Index in table and look whether ID of searched piece matches)
pieceObjects[key] = cosData[key][pieceId]
else
for _, categoryPiece in ipairs(cosData[key]) do --go through piece category list (e.g. heads, masks, torsos, etc...)
if categoryPiece.id == pieceId then
pieceObjects[key] = categoryPiece
break --once we find a piece, we can go on the next one since there are no more than one of the same piece type
end
end
end
end
return pieceObjects
end
function p.resolveCosCharBox(args)
name = utils.resolveParameter(args)
cosChar = getCosCharByName(name)
local portrait--,character
if not cosChar then return strings.cosmetics .. space .. strings.notFound .. colon .. space .. name end
--[[if cosChar.killer then
character = killersM.getKillerById(cosChar.killer)
else
character = survM.getSurvivorById(cosChar.survivor)
end]]
portrait = "CC" .. string.format("%03d", cosChar.id) .. "_charSelect_portrait"
result = '{| class = "infoboxtable"' .. nl ..
ntl ..' class = "infoboxTitle" | ' .. nl ..
'! class = "center bold" colspan = 2 | ' .. ((cosChar.killer and the(cosChar)) or cstr.empty) .. cosChar.name .. nl .. ntl .. nl ..
'! class = "center" colspan = 2 | ' .. file(portrait .. '.png', '150px') .. nl .. ntl .. nl
if cosChar.realName ~= nil then
result = result .. '| class = "titleColumn" | ' .. strings.name .. ' || class = "valueColumn" | ' .. cosChar.realName .. nl .. ntl .. nl
end
result = result .. '| class = "titleColumn" | ' .. strings.gender .. ' || class = "valueColumn" | ' .. cosChar.gender .. nl
if cosChar.origin ~= nil then
result = result .. ntl .. nl .. '| class = "titleColumn" | ' .. strings.origin .. ' || class = "valueColumn" | ' .. cosChar.origin .. nl
end
if cosChar.actor ~= nil then
result = result .. ntl .. nl .. '| class = "titleColumn" | ' .. strings.actor .. ' || class = "valueColumn" | ' .. cosChar.actor .. nl
end
result = result .. '|}'
mw.log(result)
return result
end
function getCosCharByName(name)
for _, outfit in ipairs(cosData.cosChars) do
if cstr.the .. space .. outfit.name == name then
return outfit
end
end
for _, outfit in ipairs(cosData.cosChars) do
if outfit.name == name then
return outfit
end
end
end
function getCharactersBodyParts(outfits)
result = {}
for _, outfit in ipairs(outfits) do
for piece, pieceId in pairs(outfit.pieces) do
local pieceFound = false
for _, foundPiece in ipairs(result) do
if foundPiece == piece then
pieceFound = true
break
end
end
if not pieceFound then
table.insert(result, piece)
end
end
if #result == 3 then break end
end
return result
end
--doesn't have to return all parts
function getOutfitBodyParts(outfit)
result = {}
for piece, pieceId in pairs(outfit.pieces) do
local pieceFound = false
for _, foundPiece in ipairs(result) do
if foundPiece == piece then
pieceFound = true
break
end
end
if not pieceFound then
table.insert(result, piece)
end
end
return result
end
function getCosCharType(outfit)
return (outfit.killer and 'K') or (outfit.survivor and 'S')
end
function getSortedBodyPartsWithIcons(bodyParts, charType)
local result = {}
for _, bp in ipairs(bodyParts) do
for i, category in ipairs((charType == 'K' and p.bodyPositions_killer) or p.bodyPositions_survivor) do --ipairs(p[bodyPositions_ .. ((charType == 'killer' and 'killer') or 'survivor')] ) do
local foundCategory = false
for catName, catIcon in pairs(category) do
if catName == bp then
result[i] = {[catName] = catIcon}
--result['"' .. i .. '"'] = {[catName] = catIcon}
foundCategory = true
break
end
end
if foundCategory then break end
end
end
return result
end
function sortBodyParts(bodyParts, charType, debugMode)
local result = {}
for bpKey, bp in pairs(bodyParts) do
for i, category in ipairs((charType == 'K' and p.bodyPositions_killer) or p.bodyPositions_survivor) do --ipairs(p[bodyPositions_ .. ((charType == 'killer' and 'killer') or 'survivor')] ) do
local foundCategory = false
for catName, _ in pairs(category) do
if catName == bpKey then
result[i] = {[bpKey] = bp}
foundCategory = true
break
end
end
if foundCategory then break end
end
end
return result
end
function filterOutfits(outfits, category, bodypart)
local itemsToRemove = {}
if category == cosCategories.store then
for i, outfit in pairs(outfits) do
if outfit.fakeOutfit then
for pieceKey, piece in pairs(outfit.pieces) do
if (not piece.ac and not piece.is) or piece.tier or not piece.purchasable then --Condition to be REMOVED
table.insert(itemsToRemove, i)
end
end
elseif not outfit.ac and not outfit.is or not outfit.purchasable then --Condition to be REMOVED
table.insert(itemsToRemove, i)
end
end
utils.sortTableDesc(itemsToRemove)
for _, i in ipairs(itemsToRemove) do
table.remove(outfits, i)
end
end
if category == cosCategories.rift then
for i, outfit in pairs(outfits) do
for _, piece in pairs(outfit.pieces) do
if not piece.tier then
table.insert(itemsToRemove, i)
break
end
end
end
utils.sortTableDesc(itemsToRemove)
for _, i in ipairs(itemsToRemove) do
table.remove(outfits, i)
end
end
--dmp(table.get(outfits, "name"))
return outfits --perhaps redesign to not remove it from original. Better way would probably be making a copy and render all categories from one run at once
end
function populateTomes(outfits)
for _, outfit in pairs(outfits) do
for _, piece in pairs(outfit.pieces) do
if piece.tome then
for _, tome in ipairs(tomes) do
if piece.tome == tome.tome and not (tome.event or tome.modifier) then
outfit.tome = tome --let's move the TOME info to outfit object (instead of underlying piece)
break
end
end
break --first run should suffice to find a Tome
end
end
end
--dmp(outfits)
return outfits
end
function p.getPerkCharmsForCharacter(character)
character = utils.getCharacterByName(utils.resolveParameter(character, "character", true) or utils.resolveParameter(character))
if not character then return false end
local isKiller = utils.isKiller(character)
local charms = {}
local result = cstr.empty
for _, charm in ipairs(cosData.charms) do
if string.find(charm.filename, (isKiller and 'K' or 'S') .. string.format("%02d", character.id)) then
table.insert(charms, charm)
if(#charms == 3) then break end
end
end
for i = 7, 9 do
result = result .. hl .. string.replace(strings.prestigeReward, '#plv', i) .. nl
end
result = result .. ntl .. nl
utils.sortItemsBycompFilename(charms) --sort it by filename
for _, charm in ipairs(charms) do
result = result .. tl .. class("BG-All CosmeticsBG-All SquareBG-2-enh") .. tl .. file(charm.filename, "256px") .. nl
end
result = result ..
tLine("colspan = 3 " .. class("center"), strings.pCharmDesc)
result = utils.wrapBasicTable(result)
--lg(result)
return result
end
function p.getOutfitsForCharacter(character, category, bodypart)
bodypart = bodypart or utils.resolveParameter(character, "bodypart", true)
category = category or utils.resolveParameter(character, "category", true)
local outfits, fakeOutfits = p.getAllOutfitsForChar(character)
if not outfits or table.empty(outfits) then return strings.noCosmetics end
character = utils.getCharacterByName(utils.resolveParameter(character, "character", true) or utils.resolveParameter(character)) --can be optimized as the getAllOutfitsForChar calls the function too
outfits = filterOutfits(outfits, category, bodypart)
fakeOutfits = filterOutfits(fakeOutfits, category, bodypart)
if category == cosCategories.rift then
outfits = populateTomes(outfits)
fakeOutfits = populateTomes(fakeOutfits)
--TODO
--p.getOutfitsForCharacter("Dwight Fairfield", "rift")
--create a deisgn for fakeOutfits - this will need whole new logic instead of merging it into already existing outfits
end
return renderCosmeticTable(outfits, fakeOutfits, false, false)
end
function renderCosmeticTable(outfits, fakeOutfits, displayIconForActivePiecesOnly, displayName)
utils.sortCosmeticsByRarityAndName(outfits)
utils.sortCosmeticsByRarityAndName(fakeOutfits)
local result =
'<div id = "collapseString" style = "display:none;">' .. strings.collapse .. '</div>' .. nl ..
'<div id = "expandString" style = "display:none;">' .. strings.expand .. '</div>' .. nl
for _, outfit in ipairs(outfits) do
if not (outfit.collection and type(outfit.collection) == types.table) then
outfit.collection = getCollection(outfit)
end
local charType = getCosCharType(outfit)
local characterBodyParts = getSortedBodyPartsWithIcons((displayIconForActivePiecesOnly and getOutfitBodyParts(outfit)) or getCharactersBodyParts(outfits), charType)
result = result ..
'<div class = "cosmeticTable divTable displayFlex flexColumn cosmetic' .. outfit.id .. '">' .. nl ..
'<div class = "outfitView">' .. nl ..
'<div class = "cosmeticHeader displayFlex">' .. nl .. --HEADERS
'<div class = "cosmeticThumbnail divTableHeader">' .. strings.thumbnail .. '</div>' .. nl ..
'<div class = "cosmeticPieces divTableHeader">' .. strings.contains .. '</div>' .. nl .. -- <!--Variable => "Contains" for outfits, "Piece" for individual piece-->
'<div class = "cosmeticName divTableHeader">' .. strings.name .. '</div>' .. nl ..
((displayName and '<div class = "cosmeticCharacter divTableHeader">' .. strings.character .. '</div>' .. nl) or cstr.empty) ..
'<div class = "cosmeticCollection divTableHeader">' .. strings.collectionName .. '</div>' .. nl .. --<!--optional-->
((outfit.tome and '<div class = "cosmeticTome divTableHeader">' .. strings.tome .. '</div>' .. nl) or cstr.empty) ..
'<div class = "cosmeticReleaseDate divTableHeader">' .. strings.releaseDate .. '</div>' .. nl .. --<!--optional?-->
'<div class = "cosmeticPrice divTableHeader">' .. strings.price .. '</div>' .. nl ..
'</div>' ..
generateOutfitTableRow(outfit, characterBodyParts, displayName) ..
'<div class = "expansionButton">' .. nl ..
'<div class = "divTableHeader displayFlex flexCenter bold"><span id = "outfit-' .. outfit.id .. '" class = "divButton fakeLink">⇓ ' .. strings.expand .. ' ⇓</span></div>' .. nl .. -- <!-- outfit# => variable unique to outfit --> <!-- Secondary text: ⇑ Collapse ⇑ -->
'</div>' .. nl ..
'</div>' .. nl ..
'<div class = "expandablePart displayFlex flexColumn outfit-' .. outfit.id .. '">' .. nl -- <!-- outfit# => variable unique to outfit -->
local pieceIndex = 1
local sortedPieces = sortBodyParts(outfit.pieces, charType, outfit.id)
--if outfit.id == 172 then mw.log(mw.dumpObject(sortedPieces)) end
for i, keyValuePair in pairs(sortedPieces) do
for pieceType, piece in pairs(keyValuePair) do --data are stored like this: { [1] = {heads = {}}, [2] = {torsos = {}}, [3] = {legs = {}} } - in order to keep order of bodyparts
local iconLinkPieceName = ((charType == 'K' and p.bodyPositions_killer) or p.bodyPositions_survivor)[i][pieceType] or cstr.empty
result = result .. generateOutfitPieceRow(iconLinkPieceName, outfit, piece, pieceIndex)
end
pieceIndex = pieceIndex + 1
end
result = result ..
'</div>' .. nl ..
'</div>' .. nl
end
for i, outfit in ipairs(fakeOutfits) do
for pieceType, piece in pairs(outfit.pieces) do
result = result .. generateOutfitPieceRow(pieceType, outfit, piece, nil, displayName)
end
end
result =
'<div class = "cosmeticWrapper">' .. nl ..
result .. nl ..
'</div>'
--mw.log(result)
return result
end
function getDisabledPieces(outfit, characterBodyParts)
local result = {}
--if outfit.id == 179 --[[354]] --[[437]] then dmp(outfit) lg("*************************") dmp(characterBodyParts) end
for _, keyValuePair in ipairs(characterBodyParts) do
for bp, _ in pairs(keyValuePair) do
local pieceFound = false
for pieceType, _ in pairs(outfit.pieces) do
if pieceType == bp then
pieceFound = true
break
end
end
if not pieceFound then
table.insert(result, bp)
end
end
end
--if outfit.id == 179 then dmp(result) end
return result
end
function isPieceDisabled(disabledPieces, piece)
for _, disabledPiece in pairs(disabledPieces) do
if disabledPiece == piece then
return true
end
end
return false
end
--bodypart value
function bpValue(bodypart)
for key, value in pairs(bodypart) do
return value
end
end
--bodypart key
function bpKey(bodypart)
for key, value in pairs(bodypart) do
return key
end
end
function getCollection(outfit)
if outfit.collectionId then
for _, collection in ipairs(cosData.collections) do
if collection.id == outfit.collectionId then
return collection
end
end
end
end
--example characterBodyParts: { [1] = {hairs = "heads"}, [2] = {bodies = "bodies"}, [3] = {weapons = "weapon"} } => { [pieceCategory] = { bodypartName = "iconToShow"} , ..., ...}
function generateOutfitTableRow(outfit, characterBodyParts, displayName)
local various = require("Module:Various")
local result = cstr.empty
local disabledPieces = getDisabledPieces(outfit, characterBodyParts)
--utils.getIcon(FirstLetterUpper(next(characterBodyParts[1])))
local collectionNameString = cstr.empty
if type(outfit.collection) == types.table and outfit.collection.name then
collectionNameString = outfit.collection.name
if string.find(outfit.collection.name, strings.collection) then
collectionNameString = link(collectionNameString)
else
collectionNameString = link(collectionNameString .. space .. strings.collection, collectionNameString)
end
end
result = result ..
'<div class = "cosmeticPiece displayFlex">' .. nl ..
'<div class = "pieceThumbnail displayFlex flexCenter BG-All CosmeticsBG-All SquareBG-' .. outfit.rarity .. '-enh ' .. ((outfit.visceral and "CosmeticsBG-Visceral") or cstr.empty) .. '">' .. file(outfit.filename, "230px", "link=") ..
((outfit.linked and nl .. '<div class = "linkedIcon">' .. file("IconHelp cosmetic sets.png", "56px", "link=") .. '</div>') or cstr.empty) ..
'</div>' .. nl ..
'<div class = "pieceDetails displayFlex flexColumn">' .. nl ..
'<div class = "outfitDetailsValues displayFlex flexCenter flexStretch center">' .. nl ..
'<div class = "outfitPieces divTableCell displayFlex">' .. nl
for key, value in pairs(characterBodyParts) do
local kValue = value[next(value)] --next() workarounds when key is associative string (like "hairs": hairs = "heads"). Value[next()] picks value then
iconName = utils.getIcon(utils.FirstLetterUpper(kValue))
result = result ..
'<div class = "outfitSlot' .. key .. ((isPieceDisabled(disabledPieces, kValue) and space .. 'disabledPiece') or cstr.empty) .. '">' .. file(iconName, "56px", "link=") .. '</div>' .. nl
end
result = result ..
'</div>' .. nl ..
'<div class = "pieceName cellHeader displayFlex flexCenter">' .. outfit.name .. '</div>' .. nl ..
((displayName and
'<div class = "pieceCharacter divTableCell displayFlex flexCenter">' .. nl ..
'<div class = "iconLinkWrapper">'.. utils.IconLink({args={utils.resolveCharacterIconLinkName(various.getCharacter(outfit)), noTooltip = true}}) .. '</div>' .. nl ..
'</div>') or cstr.empty) ..
'<div class = "collectionValue divTableCell displayFlex flexCenter">' .. nl ..
'<div class = "collectionNameWrapper">' .. collectionNameString .. '</div>' .. nl ..
'</div>' .. nl ..
((outfit.tome and '<div class = "tomeValue divTableCell displayFlex flexCenter">' .. link((outfit.tome.modifier and strings.modifier .. space or cstr.empty) .. strings.tome .. space .. outfit.tome.tome .. ' - ' .. outfit.tome.name) .. '</div>' .. nl) or cstr.empty) ..
'<div class = "releaseDateValue divTableCell displayFlex flexCenter">' .. utils.resolveDateTime(outfit.rDate) .. '</div>' .. nl ..
'</div>' .. nl ..
'<div class = "pieceDescriptionHeader divTableHeader">' .. strings.desc .. '</div>' .. nl ..
'<div class = "pieceDescValue divTableCell displayFlex flexCenter center">' .. outfit.desc .. '</div>' .. nl ..
'</div>' .. nl ..
'<div class = "priceContainer displayFlex flexColumn">' .. nl ..
((outfit.ac and '<div class = "ccyPrice displayFlex flexCenter flexColumn BG-All ISACBG-All ACBG">' .. outfit.ac .. file("IconHelp auricCells.png", "48px","link=Auric Cells") .. '</div>' .. nl) or cstr.empty) ..
((outfit.is and '<div class = "ccyPrice displayFlex flexCenter flexColumn BG-All ISACBG-All ISBG">' .. outfit.is .. file("IconHelp iridescentShards.png", "48px","link=Iridescent Shards") .. '</div>' .. nl) or cstr.empty) ..
'</div>' .. nl ..
'</div>' .. nl
return result
end
function generateOutfitPieceRow(pieceKey, outfit, piece, pieceIndex, displayName) --need to pass the key itself: heads = {...}
local various = require("Module:Various")
local result = cstr.empty
local iconName = utils.getIcon(utils.FirstLetterUpper(pieceKey))
local expandedPartCSS = 'expandedPiece piece' .. (pieceIndex or "error")
local fakeOutfitCSS = 'cosmeticTable divTable fakeOutfit flexStretch'
if not (outfit.collection and type(outfit.collection) == types.table) then
outfit.collection = getCollection(outfit)
end
local collectionNameString = false
if outfit.collectionId and outfit.collection then
if string.find(outfit.collection.name, strings.collection) then
collectionNameString = link(outfit.collection.name)
else
collectionNameString = link(outfit.collection.name .. space .. strings.collection, outfit.collection.name)
end
end
result = result ..
'<div class = "' .. ((outfit.fakeOutfit and fakeOutfitCSS) or expandedPartCSS) .. space .. 'displayFlex center">' .. nl ..
'<div class = "pieceThumbnail displayFlex flexCenter BG-All CosmeticsBG-All SquareBG-' .. outfit.rarity .. '-enh ' .. ((outfit.visceral and "CosmeticsBG-Visceral") or cstr.empty) .. '">' .. file(piece.filename, "230px", "link=") .. '</div>' .. nl ..
'<div class = "pieceDetailsValues displayFlex flexCenter flexStretch">' .. nl ..
'<div class = "pieceHeaders displayFlex flexColumn">' .. nl ..
'<div class = "pieceDetail bodyPartHeader divTableHeader displayFlex flexCenter">' .. strings.piece .. '</div>' .. nl ..
'<div class = "pieceDetail pieceName divTableHeader displayFlex flexCenter">' .. strings.name .. '</div>' .. nl ..
((displayName and '<div class = "pieceDetail pieceCharacter divTableHeader displayFlex flexCenter">' .. strings.character .. '</div>' .. nl) or cstr.empty) ..
((outfit.collectionId and '<div class = "pieceDetail collectionHeader divTableHeader displayFlex flexCenter">' .. strings.collection .. '</div>' .. nl) or cstr.empty) ..
((outfit.fakeOutfit and outfit.tome and '<div class = "pieceDetail pieceTome divTableHeader displayFlex flexCenter">' .. strings.tome .. '</div>' .. nl) or cstr.empty) ..
((piece.tier and '<div class = "pieceDetail pieceTier divTableHeader displayFlex flexCenter">' .. strings.riftTier .. '</div>' .. nl) or cstr.empty) .. --<!--optional-->
'</div>' .. nl
result = result ..
'<div class = "pieceHeaders displayFlex flexColumn">' .. nl ..
'<div class = "pieceDetail bodyPartHeader divTableCell displayFlex flexCenter">' .. file(iconName, "56px", "link=") .. '</div>' .. nl ..
'<div class = "pieceDetail pieceName divTableCell displayFlex flexCenter">' .. piece.name .. '</div>' .. nl ..
((displayName and
'<div class = "pieceDetail pieceCharacter divTableCell displayFlex flexCenter">' .. nl ..
'<div class = iconLinkWrapper>'.. utils.IconLink({args={utils.resolveCharacterIconLinkName(various.getCharacter(outfit)), noTooltip = true}}) .. '</div>' .. nl ..
'</div>') or cstr.empty) ..
((outfit.collectionId and collectionNameString and
'<div class = "collectionNameWrapper">' .. nl ..
'<div class = "pieceDetail collectionHeader divTableCell displayFlex flexCenter">' .. collectionNameString .. '</div>' .. nl ..
'</div>' .. nl) or cstr.empty) .. --todo revisit optimization
((outfit.fakeOutfit and outfit.tome and '<div class = "pieceDetail pieceTome divTableCell displayFlex flexCenter">' .. link(strings.tome .. space .. outfit.tome.tome .. ' - ' .. outfit.tome.name) .. '</div>' .. nl) or cstr.empty) ..
((piece.tier and '<div class = "pieceDetail pieceTier divTableCell displayFlex flexCenter">' .. piece.tier .. '</div>' .. nl) or cstr.empty) ..
'</div>' .. nl
result = result ..
'<div class = "pieceDesc divTableCell displayFlex flexColumn flexCenter">' .. (piece.desc or cstr.empty) .. '</div>' .. nl ..
'<div class = "priceContainer displayFlex flexColumn">' .. nl ..
((not outfit.linked and piece.ac and '<div class = "ccyPrice displayFlex flexColumn flexCenter BG-All ISACBG-All ACBG">' .. piece.ac .. file("IconHelp auricCells.png", "48px","link=Auric Cells") .. '</div>' .. nl) or cstr.empty) ..
((not outfit.linked and piece.is and '<div class = "ccyPrice displayFlex flexColumn flexCenter BG-All ISACBG-All ISBG">' .. piece.is .. file("IconHelp iridescentShards.png", "48px","link=Iridescent Shards") .. '</div>' .. nl) or cstr.empty) ..
'</div>' .. nl ..
'</div>' .. nl ..
'</div>' .. nl
return result
end
-- <div class = "cosmeticTable displayFlex flexColumn cosmetic1"> <!-- cosmetic# => variable unique to outfit -->
-- <div class = "outfitView">
-- <div class = "cosmeticHeader displayFlex">
-- <div class = "cosmeticThumbnail divTableHeader">Thumbnail</div>
-- <div class = "cosmeticPieces divTableHeader">Contains</div> <!--Variable => "Contains" for outfits, "Piece" for individual piece-->
-- <div class = "cosmeticName divTableHeader">Name</div>
-- <div class = "cosmeticCollection divTableHeader">Collection Name</div> <!--optional-->
-- <div class = "cosmeticReleaseDate divTableHeader">Release Date</div> <!--optional?-->
-- <div class = "cosmeticPrice divTableHeader">Price</div>
-- </div>
-- <div class = "cosmeticPiece displayFlex">
-- <div class = "pieceThumbnail displayFlex flexCenter BG-All CosmeticsBG-All SquareBG-1-enh">[[File:Dwight outfit 014.png|230px|link=]]</div>
-- <div class = "pieceDetails displayFlex flexColumn">
-- <div class = "pieceDetailsValues displayFlex flexCenter flexStretch">
-- <div class = "outfitPieces divTableCell displayFlex">
-- <div class = "outfitSlot1 disabledPiece">[[File:CategoryIcon head.png|56px|link=]]</div>
-- <div class = "outfitSlot2">[[File:CategoryIcon torso.png|56px|link=]]</div>
-- <div class = "outfitSlot3">[[File:CategoryIcon legs.png|56px|link=]]</div>
-- </div>
-- <div class = "pieceName cellHeader displayFlex flexCenter">name</div>
-- <div class = "collectionValue divTableCell displayFlex flexCenter">Collection Name</div>
-- <div class = "releaseDateValue divTableCell displayFlex flexCenter">23 September 2022</div>
-- </div>
-- <div class = "pieceDescriptionHeader divTableHeader">Description</div>
-- <div class = "pieceDescValue divTableCell displayFlex flexCenter">desc</div>
-- </div>
-- <div class = "priceContainer displayFlex flexColumn">
-- <div class = "ccyPrice displayFlex flexCenter flexColumn BG-All ISACBG-All ACBG">135[[File:IconHelp auricCells.png|48px|link=Auric Cells]]</div>
-- <div class = "ccyPrice displayFlex flexCenter flexColumn BG-All ISACBG-All ISBG">2700[[File:IconHelp iridescentShards.png|48px|link=Iridescent Shards]]</div>
-- </div>
-- </div>
-- <div class = "expansionButton">
-- <div class = "divTableHeader displayFlex flexCenter bold"><span id = "outfit1" class = "divButton fakeLink">⇓ Expand ⇓</span></div> <!-- outfit# => variable unique to outfit --> <!-- Secondary text: ⇑ Collapse ⇑ -->
-- </div>
-- </div>
-- <div class = "expandablePart displayFlex flexColumn outfit1"> <!-- outfit# => variable unique to outfit -->
-- <div class = "expandedPiece displayFlex piece1">
-- <div class = "pieceThumbnail displayFlex flexCenter BG-All CosmeticsBG-All SquareBG-1-enh">[[File:DF Head01 CV04.png|230px|link=]]</div>
-- <div class = "pieceDetailsValues displayFlex flexCenter flexStretch">
-- <div class = "pieceHeaders displayFlex flexColumn">
-- <div class = "pieceDetail bodyPartHeader divTableHeader displayFlex flexCenter">Piece</div>
-- <div class = "pieceDetail nameHeader divTableHeader displayFlex flexCenter">Name</div>
-- <div class = "pieceDetail collectionHeader divTableHeader displayFlex flexCenter">Collection</div>
-- </div>
-- <div class = "pieceHeaders displayFlex flexColumn">
-- <div class = "pieceDetail bodyPartHeader divTableCell displayFlex flexCenter">[[File:CategoryIcon head.png|56px|link=]]</div>
-- <div class = "pieceDetail nameHeader divTableCell displayFlex flexCenter">Basic Fitted Cap (Gray)</div>
-- <div class = "pieceDetail collectionHeader divTableCell displayFlex flexCenter">Dwight Essentials</div>
-- </div>
-- <div class = "pieceDesc divTableCell displayFlex flexCenter">piece desc</div>
-- <div class = "priceContainer displayFlex flexColumn">
-- <div class = "ccyPrice displayFlex flexCenter flexColumn BG-All ISACBG-All ACBG">50[[File:IconHelp auricCells.png|48px|link=Auric Cells]]</div>
-- <div class = "ccyPrice displayFlex flexCenter flexColumn BG-All ISACBG-All ISBG">900[[File:IconHelp iridescentShards.png|48px|link=Iridescent Shards]]</div>
-- </div>
-- </div>
-- </div>
-- <div class = "expandedPiece displayFlex piece2">
-- <div class = "pieceThumbnail displayFlex flexCenter BG-All CosmeticsBG-All SquareBG-1-enh">[[File:DF Torso01 CV04.png|230px|link=]]</div>
-- <div class = "pieceDetailsValues displayFlex flexCenter flexStretch">
-- <div class = "pieceHeaders displayFlex flexColumn">
-- <div class = "pieceDetail bodyPartHeader divTableHeader displayFlex flexCenter">Piece</div>
-- <div class = "pieceDetail nameHeader divTableHeader displayFlex flexCenter">Name</div>
-- <div class = "pieceDetail collectionHeader divTableHeader displayFlex flexCenter">Collection</div>
-- </div>
-- <div class = "pieceHeaders displayFlex flexColumn">
-- <div class = "pieceDetail bodyPartHeader divTableCell displayFlex flexCenter">[[File:CategoryIcon torso.png|56px|link=]]</div>
-- <div class = "pieceDetail nameHeader divTableCell displayFlex flexCenter">Basic Fitted Cap (Gray)</div>
-- <div class = "pieceDetail collectionHeader divTableCell displayFlex flexCenter">Dwight Essentials</div>
-- </div>
-- <div class = "pieceDesc divTableCell displayFlex flexCenter">piece desc</div>
-- <div class = "priceContainer displayFlex flexColumn">
-- <div class = "ccyPrice displayFlex flexCenter flexColumn BG-All ISACBG-All ACBG">50[[File:IconHelp auricCells.png|48px|link=Auric Cells]]</div>
-- <div class = "ccyPrice displayFlex flexCenter flexColumn BG-All ISACBG-All ISBG">900[[File:IconHelp iridescentShards.png|48px|link=Iridescent Shards]]</div>
-- </div>
-- </div>
-- </div>
-- <div class = "expandedPiece displayFlex piece3">
-- <div class = "pieceThumbnail displayFlex flexCenter BG-All CosmeticsBG-All SquareBG-1-enh">[[File:DF Legs01 CV07.png|230px|link=]]</div>
-- <div class = "pieceDetailsValues displayFlex flexCenter flexStretch">
-- <div class = "pieceHeaders displayFlex flexColumn">
-- <div class = "pieceDetail bodyPartHeader divTableHeader displayFlex flexCenter">Piece</div>
-- <div class = "pieceDetail nameHeader divTableHeader displayFlex flexCenter">Name</div>
-- <div class = "pieceDetail collectionHeader divTableHeader displayFlex flexCenter">Collection</div>
-- </div>
-- <div class = "pieceHeaders displayFlex flexColumn">
-- <div class = "pieceDetail bodyPartHeader divTableCell displayFlex flexCenter">[[File:CategoryIcon legs.png|56px|link=]]</div>
-- <div class = "pieceDetail nameHeader divTableCell displayFlex flexCenter">Basic Fitted Cap (Gray)</div>
-- <div class = "pieceDetail collectionHeader divTableCell displayFlex flexCenter">Dwight Essentials</div>
-- </div>
-- <div class = "pieceDesc divTableCell displayFlex flexCenter">piece desc</div>
-- <div class = "priceContainer displayFlex flexColumn">
-- <div class = "ccyPrice displayFlex flexCenter flexColumn BG-All ISACBG-All ACBG">50[[File:IconHelp auricCells.png|48px|link=Auric Cells]]</div>
-- <div class = "ccyPrice displayFlex flexCenter flexColumn BG-All ISACBG-All ISBG">900[[File:IconHelp iridescentShards.png|48px|link=Iridescent Shards]]</div>
-- </div>
-- </div>
-- </div>
-- </div>
-- </div>
return p