Dead by Daylight Wiki
Iscriviti
Advertisement

local p = {}
local utils = require("Module:Utils")
local data = require("Module:Datatable" .. utils.lang())
local perksData = require("Module:Datatable/Perks" .. utils.lang()) --mw.loadData
local str = require("Module:Strings")
local frame = mw.getCurrentFrame()


local perks = perksData.perks
local perkDescription = perksData.perkDescription
local perkStrings = perksData.perkStrings
local units = perksData.units
local unitMapper = perksData.unitMapper

p.strings = {
	-- #patch# => perk's patch value
	-- "#lpatch#" => latest patch
	ptbHeader = "Questa descrizione si basa sulle modifiche presenti nella prossima patch: #patch#",
	
	descNotFound = "Impossibile recuperare la descrizione della Competenza o non è possibile visualizzarla.",
	perkValuesNotFound = "Impossibile recuperare i valori dei livelli della Competenza.",
	unitNotFound = "Impossibile recuperare l'unità di misura per i valori dei livelli della Competenza.",
	notUniquePerk = "Non è possibile fornire il nome del personaggio, poiché si tratta di una competenza generale, non assegnata a un personaggio specifico.",
	dlcNotFound = i(bclr(6, "Impossibile recuperare il DLC collegato, quindi non è possibile visualizzare le Competenze associate." .. cstr.contact)),
	charNotFound = i(bclr(6, "Impossibile recuperare il personaggio collegato, quindi non è possibile visualizzare le Competenze associate." .. cstr.contact)),
	perkNotFound = i(bclr(6, "Impossibile recuperare la Competenza, quindi non è possibile visualizzarne i dettagli." .. cstr.contact)),
	all = 'Tutti', --used in Perk Table for common perks of Survivrros and Killers
	icon = "Icona",
	cost = "Costo",
	bpLink = "Punti Sangue",
	shardsLink = "Frammenti Iridescenti",
	name = "Nome",
	desc = "Descrizione",
	character = "Personaggio",
	killers = "Killer",
	survivors = "Sopravvissuti",
	belongs = "Questa Competenza appartiene a",
	noChar = "Nessun personaggio collegato disponibile, impossibile visualizzare le sue Competenze.",
	noLevel = "Livello mancante per recupare il nome di una Competenza.",
	perkByLvlNotFound = "Non esiste una Competenza di questo livello.",
	noPerk = "La competenza non è stata trovata.",
}
local strings = p.strings
if utils.lang() ~= cstr.empty and (counter or 0) < 1 then
	counter = (counter or 0) + 1
	strings = require("Module:Perks" .. utils.lang()).strings
end

local perkBPCosts = {
	[2] = 2500, --1st level
	[3] = 3250, --2nd level
	[4] = 4000  --3rd level
}
p.perkBPCosts = perkBPCosts

local function getMaxPerkId()
	result = 0
	for _, perk in ipairs(perks) do
		if result < perk.id then result = perk.id end
	end
	return result
end

function p.getNextFreePerkId()
	return getMaxPerkId() + 1
end

function p.isGeneralPerk(perk)
	return perk.character == nil
end



local function ResolveIntParam(param) --TODO remove, shouldn't be used anymore
	if type(param) == "table" and param.args[1] ~= nil then
		return tonumber(param.args[1])
	else
		return param
	end
end

local function getUnitById(id)
	--mw.log(id)
	for _,unit in ipairs(units) do
		if unit.id == id then return unit.value end
	end
	return strings.unitNotFound
end

local function removeIconLinks(text, raw)
	local regex
	if raw then
		regex = '( ?%&%#91;%&%#91;' .. cstr.file .. '.-%&%#93;%&%#93;)' --"( %[%[" .. cstr.file .. ".-%]%])" --&#91; &#93; --iconLinks/images
	else
		regex = '( ?%[%[' .. cstr.file .. '.-%]%])' --"( [[" .. cstr.file .. ".-]])" --iconLinks/images
	end
	for m in text:gmatch(regex) do
		text = text:gsub(regex, cstr.empty)--cstr.empty)
	end
	return text
end

local function removeLinks(text, raw)
	local regStart, regEnd
	if raw then
		regStart = '%&%#91;%&%#91;'
		regEnd = '%&%#93;%&%#93;'
	else
		regStart = '%[%['
		regEnd = '%]%]'
	end
	local regex = regStart .. '(.-)' .. regEnd --simple links
	for m in text:gmatch(regex) do
		local currentRegex = regStart .. m .. regEnd
		text = text:gsub(currentRegex, m)--cstr.empty)
	end
	return text
end

local function reparseRawDesc(text)
	--IconLink removal
	text = removeIconLinks(text, true)

	--[[Link]]
	text = removeLinks(text, true)
	
	--line carriage conversion to to <br>
	regex = '%&%#10;'
	if text:gmatch(regex) then
		text = text:gsub(regex, br)
	end

	--quotes:
	regex = '\n([^\n]-clr9[^\n]-&#39;)$'
	if text:gmatch(regex) then
		text = text:gsub(regex, cstr.empty)
	end	
	
	regex = '\n'
	if text:gmatch(regex) then
		text = text:gsub(regex, brnl)
	end
	
	--encoded <br>
	regex = '&#60;br&#62;'
	if text:gmatch(regex) then
		text = text:gsub(regex, br)
	end
	
	--last <br> removal
	regex = "<br>$"
	if text:gmatch(regex) then
		text = text:gsub(regex, cstr.empty)
	end
	
	--mw.log(text)
	return text
end

--Function that actually returns string that will replace the placeholder
local function pl(id, tripplet)
	tripplet = tonumber(tripplet)
	for _,perk in ipairs(perks) do
		if perk.id == id then
			local index = 1 + ((tripplet - 1) * 3) --tripplet is an offset, +1 is indexing from 1 in LUA, * 3 is because every values are grouped by 3 values/tiers
			local unit = getUnitById(perk.units[tripplet]) --If unit is empty, then don't apply bold function
			return bclr(2, perk.values[index]) .. "/" .. bclr(3, perk.values[index + 1]) .. "/" .. bclr(4, perk.values[index + 2]) .. space .. ((unit ~= cstr.empty and b(unit)) or cstr.empty) --Units, Tripplet is an index in 'units' list
		end
	end
	return b(strings.perkValuesNotFound)
end

local function processPtbString(ptbString, perk)
	local patchSub = "#patch#"
	local latestPatchSub = "#lpatch#"
	
	local ptbString = ptbString:gsub(patchSub, (perk and perk.patch) or cstr.empty):gsub(latestPatchSub, data.latestPatch.patch)
	
	return ptbString
end

local function wrapPtb(perkDesc, perk)
	if perkDesc.desc ~= nil then
		local processedString = processPtbString(strings.ptbHeader, perk)
		--mw.log(ptb(perkDesc.desc, processedString, perk.patch))
		perkDesc.desc = ptb(perkDesc.desc, processedString, perk.patch)
	end
	return perkDesc
end

--Function replaces "#pl(x)" string with tripplet value of according number in brackets
local function subValues(perkDesc)
	local regexString = "#pl%((%d)%)" -- looking and extracting number from "#pl(x)"
	if perkDesc.desc ~= nil then
		for m in perkDesc.desc:gmatch(regexString) do --TODO the first index shouldn't be hardcoded due to history log (if the description will be copied, then it won't be the first)
			local currentRegexString = "#pl%(" .. tonumber(m) .. "%)" --you need to replace ONLY CURRENT INDEX, otherwise you'll get replaced all #pl(x) at once when going through the first time (i.e. the first tripplet will replace all #pl() in text
			perkDesc.desc = perkDesc.desc:gsub(currentRegexString, pl(perkDesc.id, tonumber(m)))
			--mw.log(perkDesc.desc)
		end
	end
	--mw.log("PL: " .. pl)
	return perkDesc --result
end

local function subNames(perkDesc)
	local regexString = "#pn"
	if perkDesc.desc ~= nil then
		for m in perkDesc.desc:gmatch(regexString) do --TODO the first index shouldn't be hardcoded due to history log (if the description will be copied, then it won't be the first)
			perkDesc.desc = perkDesc.desc:gsub(regexString, "''".. p.getPerkById(perkDesc.id).name .. "''")
		end
	end
	return perkDesc
end

local function prependRetire(perkDesc)
	if perkDesc.desc ~= nil then
		perkDesc.desc = perkStrings.retiredPerk .. pg .. perkDesc.desc
	end
	return perkDesc
end

local function prependRawDesc(perkDesc)
	if perkDesc.desc ~= nil then
		perkDesc.desc = 
			'<div class = "switchArea"></div>' ..
			'<div class = "rawPerkDesc" style="display:none;">' .. dnl .. reparseRawDesc(mw.text.nowiki(perkDesc.desc)) .. dnl .. '</div>' ..
			'<div class = "formattedPerkDesc">' .. perkDesc.desc .. '</div>'
	end
	return perkDesc
end

function p.getPerkById(id)
	for _, perk in ipairs(perks) do
		if perk.id == id then
			return perk
		end
	end
end

function p.getPerkByName(name)
	name = utils.resolveParameter(name)
	for _, perk in ipairs(perks) do
		if perk.techName == name or perk.name == name then
			return perk
		end
	end
end

local function processPerkDescription(perkDesc, perk)
	local PD = {desc = perkDesc.desc[1][1], id = perkDesc.id}
	PD = subValues(PD) --pl(#) => Perk # trio Values
	PD = subNames(PD) -- #pn => Perk Name
	if perk.retired then PD = prependRetire(PD) end
	PD = wrapPtb(PD, perk)
	PD = prependRawDesc(PD)
	
	--mw.log(PD.desc)
	return PD.desc
end

function p.getPerkDescription(perk)
	perk = utils.resolveParameter(perk)
	if perkDescription[perk.id] and perkDescription[perk.id].id == perk.id then
		local perkDesc = perkDescription[perk.id]
		return processPerkDescription(perkDesc, perk) 
	end
	for i, perkDesc in ipairs(perkDescription) do
		if perkDesc.id == perk.id then
			return processPerkDescription(perkDesc, perk)
		end
	end
	return strings.descNotFound .. ((perk and perk.name and colon .. space .. perk.name) or cstr.empty)
end

function p.getPerkDescriptionById(id)
	id = tonumber(utils.resolveParameter(id))
	return p.getPerkDescription(p.getPerkById(id))
end

function p.getPerkDescriptionByName(name)
	name = utils.resolveParameter(name)
	return p.getPerkDescription(p.getPerkByName(name))
end


function p.getPerkOwnerByPerk(perk)
	if perk.character == nil then return notUniquePerk end
	if perk.charType == 'S' then
		return utils.getCharacterById(perk.character, survivors)
	elseif perk.charType == 'K' then
		return utils.getCharacterById(perk.character, killers)
	--else
	--	return "Unknown Character"
	end
end

function p.getPerksOwnerNameByPerk(perk)
	return p.getPerkOwnerByPerk(perk).name
end



function p.getPortraitOfPerkOwnerByPerk(perk)
	return perk.charType .. string.format("%02d", p.getPerkOwnerByPerk(perk).id) .. '_charSelect_portrait.png'
end

local function getPerkOwnerFirstName(perk)
	local owner = p.getPerkOwnerByPerk(perk)
	if perk.charType == 'S' then
		if owner.shortName ~= nil then
			return string.split(owner.shortName)[1]
		else
			return string.split(owner.name)[1]
		end
	else --Killer name
		return owner.name
	end
end

--*********** Perk Row Functions ***********
local function getCharTableRowPerk(perk, ext) --using gif version of perk (character page)
	return
		hl .. (ext == cstr.png and file(utils.getIcon(perk.name), perk.name, '128px') or utils.assembleImage("perk", perk.name, 128)) .. nl ..
		hl .. link(perk.name) .. nl ..
		tl .. (p.getPerkDescription(perk) or cstr.empy) .. nl
end

--*********** END Perk Row Functions ***********

function p.getPerkDescriptions(params, last) --temporary function, not used anywhere permanently
	first = tonumber(utils.resolveParameter(params))
	last = tonumber(last or utils.resolveParameter(params, 2))
	local result = cstr.empty
	
	utils.sortTableById(perks)
	for _, perk in ipairs(perks) do
		if perk.id >= first and perk.id <= last then
			result = result .. hl .. perk.id .. nl .. 
			hl .. (perk.techName or perk.name) .. nl ..
			'| ' .. p.getPerkDescription(perk) .. nl
			if perk.id ~= last then
				result = result .. ntl .. nl
			end
		end
	end
	
	result = utils.wrapBasicTable(result)
	--mw.log(result)
	return result
end
--************************************
function p.getPerkIconFilenameByPerk(perk, ext, forceName, teachable)
	return p.getPerkIconFilename(nil, ext, perk, forceName, teachable)
end

--forceName => in order to avoid calling expensive file existence check we can force the name regardless it's uploaded on server or not
function p.getPerkIconFilename(args, ext, perk, forceName, teachable)
	local name = (utils.resolveParameter(args, 1)) --should be (args, 1, true)?
	ext = (ext or utils.resolveParameter(args, 2, true))
	perk = (perk or p.getPerkByName(name))
	
	local owner = p.getPerkOwnerByPerk(perk)
	local isOwnerLive = (owner and utils.isCharacterLive(owner))
	if perk then
		local perkFilename = utils.resolveFileName(((teachable and "Teachable_") or cstr.empty) .. (perk.techName or perk.name), false, true)
		if not isOwnerLive then
			if utils.isValidFileName(perkFilename, ext) then
				return perkFilename .. ((ext and  dot .. ext) or name)
			else
				return 'Teachable unknown.png'
			end
		elseif forceName or utils.isValidFileName(perkFilename, ext) then
			return perkFilename .. ((ext and  dot .. ext) or name)
		end
	end
	if forceName then
		return name .. dot .. ext
	end
	
	return 'Teachable unknown.png'
end

--Currently probably used only at SoS
function p.getTeachablePerkIconFilename(args)
	return p.getPerkIconFilename(args, cstr.png, nil, false, true)
end

function p.getTeachablePerkIcon(perk, forceName)
	return p.getPerkIconFilenameByPerk(perk, cstr.png, forceName, true)
end

function p.getPerksByCharacter(character)
	local result = {}
	charType = (utils.isKiller(character) and 'K') or 'S'
	
	for _, perk in ipairs(perks) do
		if character.id == perk.character and charType == perk.charType then
			result[#result + 1] = perk
		end
	end
	return result
end

function p.resolveCharPerks(character, ext) --character can be character object as well (or string, or .args[1] = char name)
	ext = ext or utils.resolveParameter(character, 2, true)
	character = utils.resolveParameter(character)
	character = (character.name and character) or utils.getCharacterByName(character)
	if not character then return strings.charNotFound end
	local perkList = p.getPerksByCharacter(character)
	local result = cstr.empty
	
	utils.sortPerksByLevel(perkList)
	for _, perk in ipairs(perkList) do
		result = result .. getCharTableRowPerk(perk, ext)
		if perk.id ~= perkList[#perkList].id then
			result = result .. ntl .. nl
		end
	end
	
	result = utils.wrapBasicTable(result)
	
	--mw.log(result)
	return result
end

--used directly on wiki
function p.getPerkNameByLevel(level, character)
	character = character or utils.resolveParameter(level, 2)
	level = tonumber(utils.resolveParameter(level))
	local perk = p.getPerkByCharAndLevel(character, level)
	
	return (type(perk) == types.table and perk.name) or strings.noChar
end

function p.getPerkByCharAndLevel(character, level)
	level = level or utils.resolveParameter(character, 2)
	character = utils.getCharacterByName(utils.resolveParameter(character))
	if not character then return nil end
	local charPerks = p.getCharPerks(character)
	
	for _, perk in ipairs(charPerks) do
		if perk.level == level then
			return perk
		end
	end
	
	return strings.noPerk
end

function p.getCharPerks(character)
	if not character then return nil end
	local charType = utils.isCharacterKiller(character) and 'K' or 'S'
	charPerks = {}
	
	for _, perk in ipairs(perks) do
		if perk.character == character.id and perk.charType == charType then
			table.insert(charPerks, perk)
		end
	end
	
	return #charPerks > 0 and charPerks or nil
end

--returns characters from DLC with added "perks" table inside
function p.getCharsWithPerksFromDLC(charType, order, dlcName)
	local dlcs = require("Module:DLCs")
	dlcName = (dlcName and dlcs.getShortName(dlcName)) or dlcs.getShortName(utils.getPageTitle())
	order = order or tonumber(utils.resolveParameter(charType, 2, true)) or 1
	charType = utils.resolveParameter(charType)
	
	local dlc = dlcs.getDlcByName(dlcName)
	if not dlc then return strings.dlcNotFound end
	local characters = utils.getCharsByDlc(dlc)

	if #characters > 0 then
		for i, ch in ipairs(characters) do
			ch.perks = p.getPerksByCharacter(characters[i])
		end
		return characters
	end
	return nil
end

--charType - K/S
--[order] - #th character from DLC
function p.getCharPerksByDLC(charType, order, dlcName)
	local dlcs = require("Module:DLCs")
	local dlcName = (dlcName and dlcs.getShortName(dlcName)) or dlcs.getShortName(utils.getPageTitle())
	order = order or tonumber(utils.resolveParameter(charType, 2, true)) or 1
	charType = utils.resolveParameter(charType)
	local dlc = dlcs.getDlcByName(dlcName)
	if not dlc then return strings.dlcNotFound end
	local characters = utils.getCharsByDlc(dlc, charType)
	
	if #characters > 0 then
		return p.resolveCharPerks((characters[order] or characters[1]), "png")
	end
	return dlcName .. dot .. space .. strings.noChar
end

------------------------------ ---------------------
--                     COUNTS                     --
----------------------------------------- ----------
local function getUnusedPerksCount()
	local result = 0
	
	for _, perk in ipairs(perks) do
		if perk.unused then result = result + 1 end
	end

	return result
end

function p.getRetiredPerksCount()
	local result = 0
	
	for _, perk in ipairs(perks) do
		if perk.retired then result = result + 1 end
	end

	return result
end

local function getCommonPerksCount()
	local result = 0
	
	for _, perk in ipairs(perks) do
		if perk.character == nil and perk.unused ~= true then result = result + 1 end
	end
	
	return result
end

function p.getCountPerksByType(pType)
	pType = utils.resolveParameter(pType)
	local result = 0
	
	for _, perk in ipairs(perks) do
		if perk.charType == pType and perk.unused ~= true then result = result + 1 end
	end
	--mw.log(result)
	return result
end

local _unusedPerksCount = getUnusedPerksCount()
local _commonPerksCount = getCommonPerksCount()
local _uniquePerksCount = perksData.count - _unusedPerksCount - _commonPerksCount
local _nonUniquePerksCount = _unusedPerksCount + _commonPerksCount

p._nonUniquePerksCount = _nonUniquePerksCount
p._allPerksCount = perksData.count

function p.getPerksCount() --active in game
	return _uniquePerksCount + _commonPerksCount
end

----------------------------------------------------
--                  COUNTS - END                  --
----------------------------------------------------
return p
Advertisement