Module:EnemyStats2/Table

From Darkest Dungeon Wiki
Jump to navigation Jump to search
Template-info.svg Documentation

This module defines a single function, query (with both Lua and Wikitext variants) that renders a table for a subset of enemies. A few methods are currently supported for filtering out enemies:

  • type=... for all enemies which have a specific type.
  • category=... for all enemies in a particular category. See Template:EnemyStats2 for more information about how categories are defined, or look at the table directly.
  • region=... returns all enemies that can appear in a region. This includes both enemies native to that region, along with enemies that can appear in any region.

If you don't specify any filters, it will create a table with all the enemies. This is what's currently done on Enemies (Darkest Dungeon II)/Stats.

Sorting Criteria

The sorting keys are a bit complicated. Each enemy has a category, an attribute that exists only on the wiki for the purposes of sorting. Enemies are sorted in the following order:

  • First they are sorted by their category. Each category has its own order, defined in the Special:CargoTables/EnemyStats2CategoryInfo table.
  • Then they are sorted by tier:
    • Normal enemies appear first
    • Then champion enemies
    • Then minions (enemies that are only summoned by bosses or only appear in a boss fight). If an enemy is both a champion and a minion, it is considered a champion for sorting purposes.
    • Bosses come last
  • Then sorted by HP
  • Then sorted in alphabetical order

Note that both tier and minion are terms that only appear on the wiki in order to make sorting easier—we'd like to group minions along with their bosses, and we'd like to put bosses at the bottom of the list. tier and minion do not appear anywhere in the game as far as I know.

Examples

type=creature

Searching by type often produces a lot of unwanted results so it's usually not the best way to get specific data.

EnemyRegionTypesTiersHPSpeedDeath ArmorBleedBlightBurnStunMoveDebuff
Combat turnorder enemy shared pillager mongrel new.png
Mongrel
AnyCreature136040%40%30%10%10%10%
Combat turnorder enemy shared spider webber.png
Webber
AnyCreature125010%60%30%10%10%10%
Combat turnorder enemy shared rabid gnasher.png
Rabid Gnasher
AnyCreature144040%40%20%20%10%10%
Combat turnorder enemy shared spider spitter.png
Spitter
AnyCreature143010%60%30%10%10%10%
Combat turnorder enemy shared carrion eater.png
Carrion Eater
AnyCreature171010%40%20%20%10%10%
Combat turnorder enemy shared carrion eater champion.png
Carrion Devourer
AnyCreatureChampion232120%60%30%20%30%10%
Combat turnorder enemy shared rabid gnasher champion.png
Gander
AnyCreatureChampion232275%40%20%40%30%20%
Combat turnorder enemy pe livestock.png
Livestock
The FoetorCreature141010%50%20%30%10%10%
Combat turnorder enemy pe livestock b.png
Black Phillip
The FoetorCreatureChampion292020%60%20%30%10%20%
Combat turnorder enemy swine skulker.png
Swine Skulker
The SluiceCreature154020%40%30%10%20%10%
Combat turnorder enemy cave swine skiver.png
Swine Skiver
The SluiceCreature203030%40%20%20%20%20%
Combat turnorder enemy swine brute.png
Swine Brute
The SluiceCreature400220%40%20%40%50%20%
Combat turnorder enemy cave swine skiver b.png
Fulgore
The SluiceCreatureChampion294040%60%20%40%20%20%
Combat turnorder enemy swine brute b.png
Wilbur
The SluiceCreatureChampion480320%40%20%50%50%30%

category=creature_den

Here is the same table, but with enemies restricted to those that show up at the Creature Den.

EnemyRegionTypesTiersHPSpeedDeath ArmorBleedBlightBurnStunMoveDebuff
Combat turnorder enemy shared spider webber.png
Webber
AnyCreature125010%60%30%10%10%10%
Combat turnorder enemy shared rabid gnasher.png
Rabid Gnasher
AnyCadaver,
Creature
144040%40%20%20%10%10%
Combat turnorder enemy shared spider spitter.png
Spitter
AnyCreature143010%60%30%10%10%10%
Combat turnorder enemy shared carrion eater.png
Carrion Eater
AnyCreature171010%40%20%20%10%10%
Combat turnorder enemy shared carrion eater champion.png
Carrion Devourer
AnyCreatureChampion232120%60%30%20%30%10%
Combat turnorder enemy shared rabid gnasher champion.png
Gander
AnyCadaver,
Creature
Champion232275%40%20%40%30%20%

category=sluice

Enemies in The Sluice. This is actually identical to querying by type=swine.

EnemyRegionTypesTiersHPSpeedDeath ArmorBleedBlightBurnStunMoveDebuff
Combat turnorder enemy swine skulker.png
Swine Skulker
The SluiceCreature,
Swine
154020%40%30%10%20%10%
Combat turnorder enemy cave swine skiver.png
Swine Skiver
The SluiceCreature,
Swine
203030%40%20%20%20%20%
Combat turnorder enemy swine brute.png
Swine Brute
The SluiceCreature,
Swine
400220%40%20%40%50%20%
Combat turnorder enemy cave swine skiver b.png
Fulgore
The SluiceCreature,
Swine
Champion294040%60%20%40%20%20%
Combat turnorder enemy swine brute b.png
Wilbur
The SluiceCreature,
Swine
Champion480320%40%20%50%50%30%

category=tangle

Enemies in The Tangle. We can't use type=cadaver because that also gets Rabid Gnasher and Gander.

EnemyRegionTypesTiersHPSpeedDeath ArmorBleedBlightBurnStunMoveDebuff
Combat turnorder enemy lost battalion arbalist.png
Arbalist
The TangleCadaver151030%30%10%10%10%10%
Combat turnorder enemy lost battalion foot soldier.png
Foot Soldier
The TangleCadaver171130%30%10%50%10%10%
Combat turnorder enemy lost battalion drummer.png
Drummer
The TangleCadaver195030%30%10%30%10%20%
Combat turnorder enemy lost battalion bishop.png
Bishop
The TangleCadaver222030%30%20%20%20%30%
Combat turnorder enemy lost battalion knight.png
Knight
The TangleCadaver360340%20%10%40%40%30%
Combat turnorder enemy lost battalion arbalist b.png
Bullseye Barrett
The TangleCadaverChampion201140%40%10%10%20%10%
Combat turnorder enemy lost battalion knight b.png
Fallen Templar
The TangleCadaverChampion412350%30%10%40%40%30%
Tap RootThe TangleNoneBoss,
Minion
Invulnerable100ImmuneImmuneImmuneImmuneImmuneImmune
Combat turnorder enemy lost battalion dreaming general.png
Dreaming General
The TangleCadaverBoss1853250%30%20%ImmuneImmune40%

local Cargo = mw.ext.cargo
local getArgs = require("Module:Arguments").getArgs

local Histogram = require("Module:Histogram")
local Utils = require("Module:EnemyStats2/Utils")

local LINK_LABEL = '[[%s|%s]]<i id="%s"></i>'

local REGIONS = {
	valley={article="The Valley", sort_key="0"},
	sprawl={article="The Sprawl", sort_key="10"},
	tangle={article="The Tangle", sort_key="11"},
	foetor={article="The Foetor", sort_key="12"},
	shroud={article="The Shroud", sort_key="13"},
	sluice={article="The Sluice", sort_key="20"},
	mountain={article="The Mountain", sort_key="30"}
}

local function text_cell(label, sort_key)
	return mw.html.create("td")
		:attr("data-sort-value", sort_key)
		:addClass("ctr")
		:wikitext(label)
end

local function name_cell(enemy)
	local label = LINK_LABEL:format(enemy.article, enemy.name, enemy.name)
	if enemy.icon ~= nil then
		label = ("[[File:%s|40px]]<br>"):format(enemy.icon) .. label
	end
	return text_cell(label, enemy.name)
end

local function region_cell(enemy)
	if enemy.region == nil then
		return text_cell("''Any''", -1)
	end
	return text_cell(
		("[[%s]]"):format(REGIONS[enemy.region].article),
		REGIONS[enemy.region].sort_key
	)
end

local function types_cell(enemy)
	local type_links = Utils._type_links(enemy)
	return text_cell(table.concat(type_links, ",<br>"))
end

local function tiers_cell(enemy)
	local tiers = {}
	if enemy.boss == 1 then
		table.insert(tiers, "[[Bosses (Darkest Dungeon II)|Boss]]")
	end
	if enemy.champion_of ~= nil then
		table.insert(tiers, "Champion")
	end
	if enemy.minion_of ~= nil then
		table.insert(tiers, "Minion")
	end
	return text_cell(table.concat(tiers, ",<br>"), enemy.tier_key)
end

local function fetch_data(where)
	local tables = {
		"EnemyStats2",
		"EnemyStats2Types",
		"EnemyStats2CategoryInfo",
	}

	local fields = {
		"EnemyStats2.name=name",
		"icon",
		"article",
		"boss",
		"champion_of",
		"minion_of",
		-- Cargo doesn't support CASE statements?
		[[IF(boss=1, 4,
		IF(champion_of IS NOT NULL, 2,
		IF(minion_of IS NOT NULL, 3,
		1
		)))=tier_key]],
		"region",
		"GROUP_CONCAT(type ORDER BY type SEPARATOR ' ')=types"
	}
	for _, stat in ipairs(Utils.STATS) do
		table.insert(fields, stat.name)
	end

	local join_keys = {
		"EnemyStats2.name=EnemyStats2Types.name",
		"EnemyStats2.category=EnemyStats2CategoryInfo.category"
	}
	local order_keys = {
		"sort_key",
		"tier_key",
		"hp",
		"name",
	}

	local enemies = Cargo.query(
		table.concat(tables, ","),
		table.concat(fields, ","),
		{
			groupBy="name",
			join=table.concat(join_keys, ","),
			orderBy=table.concat(order_keys, ","),
			where=where
		}
	)

	local hs = Histogram._load_table("EnemyStats2Histograms")
	for i, enemy in ipairs(enemies) do
		Utils._parse_enemy(enemy)
		for _, stat in ipairs(Utils.STATS) do
			enemy[stat.name .. "_cdf"] = Histogram._interpolate_cdf(
				hs[stat.name], enemy[stat.name])
		end
	end

	return enemies
end

local function _query(args)
	local where = nil
	if args.category ~= nil then
		where = ("EnemyStats2.category='%s'"):format(args.category)
	elseif args.type ~= nil then
		where = ("EnemyStats2Types.type='%s'"):format(args.type)
	elseif args.region ~= nil then
		where = ("region IS NULL OR region='%s'"):format(args.region)
	end
	local enemies = fetch_data(where)

	local result = mw.html.create("table")
		:addClass("tablebgdd2")
		:addClass("sortable")

	local header = result:tag("tr")
	header:tag("th")
		:wikitext("Enemy")
	header:tag("th")
		:wikitext("[[Regions|Region]]")
	header:tag("th")
		:wikitext("[[Enemy Type (Darkest Dungeon II)|Types]]")
	header:tag("th")
		:wikitext("Tiers")
	for _, stat in ipairs(Utils.STATS) do
		header:tag("th")
			:wikitext(stat:short_label())
	end

	for _, enemy in ipairs(enemies) do
		local row = result:tag("tr")
		row:node(name_cell(enemy))
		row:node(region_cell(enemy))
		row:node(types_cell(enemy))
		row:node(tiers_cell(enemy))
		for _, stat in ipairs(Utils.STATS) do
			row:node(stat:create_cell(enemy))
		end
	end

	return result
end

local function query(frame)
	return _query(getArgs(frame))
end

return {
	_query=_query,
	query=query,
}