Module:Liste d'objets de Fallout 76

Documentation du module

Ce module génère une liste de récompenses pour Fallout 76.

Pour cela, le module part d'un sous-module racine et va boucler sur éléments qui peuvent être soit des objets, soit des listes. Si l'élément est une liste, elle est appelée et on répète l'opération de manière récursive.

Le paramétrage des listes sont des sous-modules de celui-ci. Ils sont rangés dans la catégorie Module Liste d'objets de Fallout 76.

Fonctions exportables :

  • build(frame) – voir la documentation du modèle {{Liste d'objets de Fallout 76}} ;
  • _build(args) – même fonction mais utilisable directement dans un autre module Lua ;

Paramétrage d'une liste

[modifier le wikicode]

Une liste d'objet est décrite par une table présente dans un sous-module de Liste d'objets de Fallout 76. Cette table doit contenir les propriétés suivantes.

Propriété Type Description Obligatoire Valeur par défaut
title string Titre de la liste Oui
auto bool Indique si les probabilités d'obtenir les éléments de la liste doivent être calculées automatiquement Non true
items table Éléments de la liste Oui

La table items elle contient les propriétés suivantes.

Propriété Type Description Obligatoire Valeur par défaut
type string Type d'élément, au choix item ou sublist Oui
value string Nom d'un objet ou d'une liste Oui
quantity string
number
Quantité d'un élément qu'il est possible d'obtenir mais qui n'influence pas les probabilités Non
min number Minimum cet élément qu'il est possible d'obtenir Non 1
max number Maximum de cet élément qu'il est possible d'obtenir Non 1
chance number Nombre entre 0 et 1 représentant la probabilité d'obtenir cet élément Oui si auto == false
level number Niveau du joueur pour obtenir cet élément Non
event string Nom d'un événement, dans le cas où un élément ne serait disponible que lors de sa disponibilité Non
	-- Cas où auto == true
	return {
		title = "Titre de la liste",
		items = {
			{ type = "item", value = "[[Réacteur légendaire]]", max = 3 },
			{ type = "item", value = "[[Note de la Trésorerie]]" },
			{ type = "sublist", value = "LLS_Loot_GoodyBag_Large" }
		}
	}

	-- Cas où auto == false
	return {
		title = "Titre de la liste",
		auto = false,
		items = {
			{ type = "item", value = "[[Réacteur légendaire]]", chance = 0.5 },
			{ type = "item", value = "[[Note de la Trésorerie]]", chance = 0.5 },
			{ type = "sublist", value = "LLS_Loot_GoodyBag_Large", chance = 1 }
		}
	}

Calcul des probabilités

[modifier le wikicode]

Dans le cas du calcul automatique, la probabilité d'obtenir chaque élément dépend :

  • du nombre d'éléments de la liste ;
  • du nombre max de cet élément ;
  • de la probabilité d'obtenir la liste.

Dans ce mode, les probabilités sont donc liées à la liste mère.

	-- Nom = Liste mère
	return {
		title = "Ma liste mère",
		items = {
			{ type = "item", value = "item1", max = 3 },
			{ type = "item", value = "item2" },
			{ type = "sublist", value = "Liste fille", max = 2 }
		}
	}

	-- Nom = Liste fille
	return {
		title = "Ma liste fille",
		items = {
			{ type = "item", value = "item3" },
			{ type = "item", value = "item4" }
		}
	}

Si on appelle le modèle {{Liste d'objets de Fallout 76}}. Alors le calcul se fait ainsi :

Dans Liste mère, il est possible d'obtenir trois fois item1, une fois item2 et deux fois Liste fille. Le probabilités se répartissent ainsi :

  • P(item1) = 3 / 6 = 50.00 %
  • P(item2) = 1 / 6 = 16.67 %
  • P(Liste fille) = 2 / 6 = 33.33 %

Pour Liste fille, on peut obtenir item3 et item4, du coup :

  • P(item3) = P(item4) = P(Liste fille) * 1 / 2 = 16,67 %

Si le mode automatique est désactivé, il faut renseigner les probabilités d'obtenir chaque élément. Dans ce mode, la propriété max n'est plus prise en compte et il n'y a plus de relation entre les probabilités de chaque élément.

-- Nom = Liste mère
return {
	title = 'Liste de vente de marchands itinérants',
	auto = false,
	items = {
		{ type = 'sublist', value = 'Liste fille 1', chance = 1 },
		{ type = 'sublist', value = 'Liste fille 2', chance = 0.5 },
		{ type = 'sublist', value = 'Liste fille 3', chance = 1 }
	}
}

Dans cette exemple, on est sûr à 100 % d'obtenir un objet de la liste Liste fille 1 et un autre objet de la liste Liste fille 3.

Documentation transclues de Module:Liste d'objets de Fallout 76/doc.
local p = {}

-- ============================================================================
-- Module:Liste d'objets de Fallout 76 (v2.0)
-- 
-- Améliorations v2.0 par rapport à v1.x :
--   * Tri alphabétique automatique des items
--   * Affichage des fourchettes : "2 à 6" au lieu de "2-6"
--   * Support du nouveau champ `weight` (poids relatif natif Bethesda)
--   * Détection de boucles infinies (profondeur max = 10)
--   * Gestion propre des sous-modules manquants (message d'erreur clair)
--   * Pas d'erreur visible quand le template est appelé sans paramètre `nom`
--
-- Rétrocompatibilité : tous les anciens modules continuent de fonctionner.
-- ============================================================================

local MAX_DEPTH = 10

-- Fonctions communes -------------------------------------------------------

function getArgs(frame)
	local args = {}
	local argsParent = frame:getParent().args
	for cle, val in pairs(argsParent) do
		if val then
			args[cle] = mw.text.trim(val)
		end
	end
	return args
end

function countItems(moduledata)
	local n = 0
	for i, item in pairs(moduledata.items) do
		local w = item.weight
		if w then
			n = n + w
		else
			local imin = item.min or 1
			local imax = item.max or 1
			n = n + (imax - imin + 1)
		end
	end
	return n
end

function formatChance(chance)
	local chanceCeil = math.ceil(chance)
	if chanceCeil == chance then
		return chanceCeil
	else
		return string.format("%.2f", chance)
	end
end

function formatQuantity(item)
	local itemQuantity = item.quantity
	if itemQuantity then
		return tostring(itemQuantity)
	end
	local imin = item.min or 1
	local imax = item.max or 1
	if imax > 1 then
		if imin == imax then
			return tostring(imin)
		else
			return imin .. ' à ' .. imax
		end
	end
	return nil
end

function buildError(msg)
	return '<span style="color:red; font-weight:bold;">⚠ ' .. msg .. '</span>'
end

-- Ajout d'un élément (récursif) --------------------------------------------

function addItem(item, isAuto, numberOfItems, globalChance, depth)
	if depth > MAX_DEPTH then
		return buildError("Profondeur maximale atteinte (" .. MAX_DEPTH .. ") - boucle infinie probable")
	end

	if type(item) ~= 'table' then
		return buildError("Item : pas une table")
	end

	local itemValue = item.value
	if not itemValue then
		return buildError("Item : propriété 'value' non renseignée")
	end

	local itemType = item.type
	local itemMin = item.min or 1
	local itemMax = item.max or 1

	if itemMin > itemMax then
		return buildError("Item : 'min' > 'max' pour " .. tostring(itemValue))
	end

	local itemChance
	if isAuto == true then
		local w = item.weight or (itemMax - itemMin + 1)
		itemChance = w / numberOfItems
	else
		itemChance = item.chance
	end

	if not itemChance then
		return buildError("Item : propriété 'chance' non renseignée pour " .. tostring(itemValue))
	end

	itemChance = itemChance * globalChance

	local suffix = ' ('
	local qtyStr = formatQuantity(item)
	if qtyStr then
		suffix = suffix .. qtyStr .. ', '
	end
	suffix = suffix .. formatChance(100 * itemChance) .. ' %'

	local itemPlayerLevel = item.level
	local itemEvent = item.event
	if itemPlayerLevel then
		suffix = suffix .. ', dès le niveau ' .. itemPlayerLevel
		if itemEvent then
			suffix = suffix .. " et lors de l'événement " .. itemEvent
		end
	elseif itemEvent then
		suffix = suffix .. ", lors de l'événement " .. itemEvent
	end
	suffix = suffix .. ')'

	if itemType == 'item' then
		return '*' .. itemValue .. suffix

	elseif itemType == 'sublist' then
		local subModulePath = 'Module:Liste d\'objets de Fallout 76/' .. itemValue
		local ok, subModuledata = pcall(require, subModulePath)

		if not ok or not subModuledata then
			return buildError("Sous-module introuvable : " .. tostring(itemValue))
		end

		if not subModuledata.items then
			return buildError("Sous-module sans 'items' : " .. tostring(itemValue))
		end

		local subTitle = subModuledata.title or itemValue

		local sublist = '<div class="avt-dropdown-box mw-collapsible mw-collapsed">' ..
			'<div class="avt-dropdown-box-title">' .. subTitle .. suffix .. '</div>' ..
			'<div class="avt-dropdown-box-content mw-collapsible-content">\n'

		local subIsAuto = subModuledata.auto
		subIsAuto = subIsAuto == nil or subIsAuto == true

		local subNumberOfItems = countItems(subModuledata)

		local sortedItems = {}
		for i, v in ipairs(subModuledata.items) do
			sortedItems[i] = v
		end
		table.sort(sortedItems, function(a, b)
			local va = tostring(a.value or '')
			local vb = tostring(b.value or '')
			return va < vb
		end)

		for i, subitem in ipairs(sortedItems) do
			sublist = sublist .. addItem(subitem, subIsAuto, subNumberOfItems, itemChance, depth + 1) .. '\n'
		end

		sublist = sublist .. '</div></div>'
		return sublist
	else
		return buildError("Type d'item non reconnu : " .. tostring(itemType))
	end
end

-- Construction principale --------------------------------------------------

function p._build(args)
	local moduleName = args.nom
	-- Si pas de paramètre 'nom', retour silencieux (cas des transclusions
	-- automatiques sur les pages de doc, où le template est appelé sans argument)
	if not moduleName or moduleName == '' then
		return ''
	end

	local ok, moduledata = pcall(require, 'Module:Liste d\'objets de Fallout 76/' .. moduleName)
	if not ok or not moduledata then
		return buildError("Module racine introuvable : " .. moduleName)
	end

	if not moduledata.items then
		return buildError("Module sans 'items' : " .. moduleName)
	end

	local title = moduledata.title or moduleName

	local list = '<div class="avt-dropdown-box mw-collapsible">' ..
		'<div class="avt-dropdown-box-title">' .. title .. '</div>' ..
		'<div class="avt-dropdown-box-content mw-collapsible-content">\n'

	local isAuto = moduledata.auto
	isAuto = isAuto == nil or isAuto == true

	local numberOfItems = countItems(moduledata)

	local sortedItems = {}
	for i, v in ipairs(moduledata.items) do
		sortedItems[i] = v
	end
	table.sort(sortedItems, function(a, b)
		local va = tostring(a.value or '')
		local vb = tostring(b.value or '')
		return va < vb
	end)

	for i, item in ipairs(sortedItems) do
		list = list .. addItem(item, isAuto, numberOfItems, 1, 1) .. '\n'
	end

	list = list .. '</div></div>'
	return tostring(list)
end

-- Fonction modèle ----------------------------------------------------------

function p.build(frame) return p._build(getArgs(frame)) end

return p