From Dark and Darker Wiki

Revision as of 22:30, 28 February 2025 by Sur (talk | contribs) (fix required_gem being appended as nil instead of blank)

Overview

Functions for Enchantments. Data comes from Data:Enchantments.json.

Functions

draw_roll_range_table

Create's a table of enchants for the Enchantments page

Parameters

  • base_or_gem - List 'base' (traditional) or 'gem' enchant roll ranges?

Examples

{{#invoke:Enchantments|draw_roll_range_table|gem}}


Required GemEnchantments1H1H Shield2H Shield2H Physical2H Hybrid2H MagicalChestLegsFootHeadHandsCloakNecklaceRingMax Total Possible
MinMaxMinMaxMinMaxMinMaxMinMaxMinMaxMinMaxMinMaxMinMaxMinMaxMinMaxMinMaxMinMaxMinMax
Attributes
All AttributesDiamond1113
StrengthDiamond131312121212131221
VigorDiamond131312121212131221
AgilityDiamond131312121212131221
DexterityDiamond131312121212131221
WillDiamond131312121212131221
KnowledgeDiamond131312121212131221
ResourcefulnessDiamond131312121212131221
Physical Damage
Physical Power BonusRuby12122323232312121212231221
Physical PowerRuby121313131312121212131221
Physical Gear Weapon DamageRuby1112120
Physical Damage AddRuby11115
True Physical DamageRuby11115
Armor PenetrationRuby233434343423232323342330
Magical Damage
Magical Power BonusRuby122323232312121212231221
Magical PowerBlue Sapphire121313131312121212131221
Magical Damage AddBlue Sapphire11115
True Magical DamageBlue Sapphire11115
Magical Penetration0
Reductions
Armor Rating AddEmerald510515515515510510510510515510105
Physical Damage ReductionEmerald12232323121212122311.520
Projectile Damage ReductionEmerald1223232312121212231221
Magical Damage ReductionBlue Sapphire12232323121212122311.520
Magical ResistanceBlue Sapphire5101020102010205105105105101020510120
Cooldown Reduction Bonus0
Actions
Action SpeedBlue Sapphire121223232323232312121212231221
Regular Interaction Speed0
Magical Interaction Speed0
Spell Casting SpeedBlue Sapphire122323232312121212121220
Move Speed AddBlue Sapphire131314141414141413131313141330
Move Speed BonusBlue Sapphire0.510.511212121212120.510.510.510.51120.5112
Health
Max Health AddEmerald131314141414141413131313141330
Max Health BonusEmerald121223232323232312121212231221
Healing
Outgoing Physical Healing AddEmerald13131210
Outgoing Magical Healing AddEmerald1212131313131210
Statuses
Buff Duration BonusEmerald232334343434343423232323342330
Debuff Duration BonusEmerald232334343434343423232323342330
Memory
Memory Capacity AddEmerald131414141413131313141330
Memory Capacity BonusEmerald364848484836363636483660
Misc
LuckBlue Sapphire40504050152515251525152540501525300

draw_socket_cost_table

Create's a table of socket's cost per rarity for the Enchantments page

Parameters

none

Examples

{{#invoke:Enchantments|draw_socket_cost_table}}


RarityCost
Poor10
Common20
Uncommon30
Rare50
Epic100
Legend150
Unique200

local enchantments_data = mw.loadJsonData("Data:Enchantments.json")
local utils = require("Module:Utilities")
local p = {}

function p.get_roll(slots_data, slot_name, base_or_gem, min_or_max, if_not_exist)
	if min_or_max ~= "min" and min_or_max ~= "max" then
		min_or_max = "max"
	end
	
	if if_not_exist == nil then
		if_not_exist = 0
	end
	
	slot_data = slots_data[slot_name]
	if slot_data == nil then
		return if_not_exist
	end
	roll_data = slot_data[base_or_gem]
	if roll_data == nil then
		return if_not_exist
	end
	
	roll = roll_data[min_or_max]
	if roll == nil then
		return if_not_exist
	end
	
	return roll
end

function p.draw_roll_range_table(base_or_gem)
	-- Handle based on how it was called
	if type(base_or_gem) == "table" and base_or_gem.args then -- if called via wikitext instead of lua
        local frame = base_or_gem
        base_or_gem = frame.args[1]
	end
	
	-- Validate
	if base_or_gem ~= "base" and base_or_gem ~= "gem" then return "1st parameter 'base_or_gem' must be either 'base' or 'gem'." end
	
	local slot_headers = '<th rowspan="2" colspan="2">Enchantments</th>'
	local min_max_headers = ''

	-- Create enchant_name_headers (row1) and min/max (row2)
	-- Iterate enchant groups
	for i, slot_name in ipairs(enchantments_data["slottype_order"]) do
		slot_headers = slot_headers .. '<th colspan="2">' .. slot_name .. '</th>'
		min_max_headers = min_max_headers .. '<th>Min</th>' .. '<th>Max</th>'
	end
	
	-- Add required gem col header
	if base_or_gem == 'gem' then
		slot_headers = '<th>Required Gem</th>' .. slot_headers
		min_max_headers = '<th></th>' .. min_max_headers
	end
	
	-- Add body rows
	local enchant_rows = ""
	local enchant_row
	for i, enchant_group_name in ipairs(enchantments_data["enchant_group_order"]) do
		local enchants_in_group = enchantments_data["enchant_order"][enchant_group_name]
		if enchants_in_group == nil then return "Error: " .. enchant_group_name .. " not found in \"enchant_order\"" end
		
		-- Iterate enchants in the group
		-- First just determine how many enchants are in the group to get the proper rowspan
		local num_enchants_in_group = 0
		for i, enchant_name in ipairs(enchants_in_group) do
			num_enchants_in_group = num_enchants_in_group + 1
		end
		
		local is_first = true
		for i, enchant_name in ipairs(enchants_in_group) do
			-- Get that enchant's data
			local slots_data = enchantments_data["enchant_rolls"][enchant_name]["slots"]
			if slots_data == nil then return "Error: " .. enchant_name .. " not found in \"enchant_rolls\"" end
			
			-- Iterate slottypes
			local min_max_cols = ""
			for i, slot_type in ipairs(enchantments_data["slottype_order"]) do
				-- Get rolls, default to blank if missing
				local min_roll = p.get_roll(slots_data, slot_type, base_or_gem, "min", "")
				local max_roll = p.get_roll(slots_data, slot_type, base_or_gem, "max", "")
				if min_roll == 0 then min_roll = "" end
				if max_roll == 0 then max_roll = "" end
				
				if min_roll == max_roll then
					min_max_cols = min_max_cols .. "<td colspan=\"2\">" .. min_roll .. "</td>"
				else
					min_max_cols = min_max_cols .. "<td>" .. min_roll .. "</td><td>" .. max_roll .. "</td>"
				end
			end
			
			-- Calc max
			--Max Total Possible = MAX(1H Shield + 1H Weapon, 2 * 1H Weapon, 2H Physical, 2H Magical, 2H Hybrid) + Head + Chest + Legs + Hands + Foot + Cloak + Necklace) + 2*Ring
			local weapons = math.max(
				p.get_roll(slots_data, "One-handed Weapon", base_or_gem) + p.get_roll(slots_data, "One-handed Shield", base_or_gem),
				p.get_roll(slots_data, "One-handed Weapon", base_or_gem)*2,
				p.get_roll(slots_data, "Two-handed PhysicalWeapon", base_or_gem),
				p.get_roll(slots_data, "Two-handed Shield", base_or_gem),
				p.get_roll(slots_data, "Two-handed HybridWeapon", base_or_gem),
				p.get_roll(slots_data, "Two-handed MagicOnly", base_or_gem)
				)
			
			local armor = (
				p.get_roll(slots_data, "Head", base_or_gem) +
				p.get_roll(slots_data, "Chest", base_or_gem) + 
				p.get_roll(slots_data, "Legs", base_or_gem) + 
				p.get_roll(slots_data, "Hands", base_or_gem) + 
				p.get_roll(slots_data, "Foot", base_or_gem) + 
				p.get_roll(slots_data, "Cloak", base_or_gem) + 
				p.get_roll(slots_data, "Necklace", base_or_gem) + 
				p.get_roll(slots_data, "Ring", base_or_gem)*2 
				)
			local max_total_possible = weapons + armor
			
			-- Get the required gem
			local required_gem_td = ''
			if base_or_gem == 'gem' then
				required_gem = enchantments_data["enchant_rolls"][enchant_name]["required_gem"]
				if required_gem == nil then
					required_gem = ""
				end
				required_gem_td = '<td>' .. required_gem .. '</td>'
			end
			
			-- Add cells to row
			local rowspanned_cell = ''
			local row_id = ' id="' .. utils.dash_for_space(enchant_group_name) .. '"'
			if is_first then
				rowspan = ' rowspan="' .. num_enchants_in_group+1 .. '"'
				rowspanned_cell = '<td' .. rowspan .. '>' .. enchant_group_name .. '</td></tr><tr' .. row_id .. '>'
			end
			enchant_row = '' .. rowspanned_cell
			enchant_row = enchant_row .. "<td>" .. enchant_name .. "</td>"
			enchant_row = enchant_row .. required_gem_td
			enchant_row = enchant_row .. min_max_cols
			enchant_row = enchant_row .. "<td>" .. max_total_possible .. "</td>"
			
			enchant_rows = enchant_rows .. '<tr' .. row_id .. '>' .. enchant_row .. "</tr>"
			
			is_first = false
		end
	end
	
	
	
	local slot_headers = '<tr>' .. slot_headers .. '<th rowspan="2">Max Total Possible</th>' .. '</tr>'
	local min_max_headers = '<tr>' .. min_max_headers .. '</tr>'
	
	local table_str = '<table class="enchantmenttable">' .. slot_headers .. min_max_headers .. enchant_rows .. "</table>"
	return table_str
end

function p.draw_socket_cost_table(frame)
	local output_str = ""
	local data_rows = ""
	local header_row = "<tr>" .. "<th>Rarity</td>" .. "<th>Cost</th>" .. "</tr>"
	local row
	local i = 1 --display rarity_nums starting at i=1 (Poor), skipping Junk
	local ending_i = 7 --end with Unique=7
	
	-- this is O(n^2), but since theres only 8 elements, its inconsequential
	-- Iterate costs in data first
	local rarity_num
	while i <= ending_i do
		for rarity_name, cost in pairs(enchantments_data["enchant_costs"]) do
			-- Determine the rarity_num
			rarity_num = utils.rarity_name_to_num(rarity_name)
			
			if i == rarity_num then
				-- This is the next rarity that should be displayed
				row = "<td>" .. "<span class=\"colorrarity" .. i .. "\">" .. rarity_name .. "</span>" .. "</td>" .. "<td>" .. cost .. "</td>" 
				data_rows = data_rows .. "<tr>" ..  row .. "</tr>"
				
				i = i+1 -- look for the next rarity
				break -- end the current rarity-search
			end
		end
	end
	
	return "<table class=\"wikitable\">" .. header_row .. data_rows .. "</table>"
end

return p