|
|
(6 intermediate revisions by 2 users not shown) |
Line 1: |
Line 1: |
| -- Cargo reworked item module | | -- This is not an actual module. Do not add code. |
| | |
| -- ----------------------------------------------------------------------------
| |
| -- TODO
| |
| -- ----------------------------------------------------------------------------
| |
| -- Items
| |
| -- -----
| |
| -- Check if abyss jewels actually have radius modifiers
| |
| --
| |
| -- Aggregate ids from skill id from modifiers
| |
| --
| |
| -- DROP restriction improvements:
| |
| -- drop monster type(s)
| |
| --
| |
| -- unique items:
| |
| -- 3D art
| |
| -- supporter attribution
| |
| --
| |
| -- Maps:
| |
| -- Area level can be retrieved eventually
| |
| --
| |
| -- Essence:
| |
| -- type column
| |
| -- monster modifier info
| |
| --
| |
| -- random modifier
| |
| -- -> sell price must consider random mods
| |
| --
| |
| -- prophecy base item -> i18n
| |
| -- ----------
| |
| -- Item class
| |
| -- ----------
| |
| --
| |
| -- remove the ul if name_list is not provided
| |
| -- maybe smw
| |
| | |
| -- ----------------------------------------------------------------------------
| |
| -- Imports
| |
| -- ----------------------------------------------------------------------------
| |
| local xtable = require('Module:Table')
| |
| local m_util = require('Module:Util')
| |
| local getArgs = require('Module:Arguments').getArgs
| |
| local m_game = require('Module:Game')
| |
| local m_skill = require('Module:Skill')
| |
| local m_area = require('Module:Area')
| |
| local m_cargo = require('Module:Cargo')
| |
| local f_item_link = require('Module:Item link').item_link
| |
| | |
| local p = {}
| |
| local c = {}
| |
| c.image_size = 39
| |
| c.image_size_full = c.image_size * 2
| |
| c.query_default = 50
| |
| c.query_max = 200
| |
| | |
| c.lang = mw.language.new('en')
| |
| | |
| -- ----------------------------------------------------------------------------
| |
| -- Strings
| |
| -- ----------------------------------------------------------------------------
| |
| -- This section contains strings used by this module.
| |
| -- Add new strings here instead of in-code directly, this will help other
| |
| -- people to correct spelling mistakes easier and help with translation to
| |
| -- other PoE wikis.
| |
| --
| |
| -- TODO: Maybe move this out to a separate sub-page module
| |
| local i18n = {
| |
| inventory_icon = 'File:%s inventory icon.png',
| |
| status_icon = 'File:%s status icon.png',
| |
| divination_card_art = 'File:%s card art.png',
| |
| gem_tag_category = '[[:Category:%s (gem tag)|%s]]',
| |
| | |
| categories = {
| |
| -- maintenance cats
| |
| improper_modifiers = 'Items with improper modifiers',
| |
| missing_release_version = 'Items without a release version',
| |
| broken_upgraded_from_reference = 'Items with broken item references in upgraded from parameters',
| |
| duplicate_query_area_ids = 'Items with duplicate area ids from queries',
| |
| base_items = 'Base items',
| |
| derived_items = 'Derived items',
| |
| sell_prices_override = 'Items with sell prices overrides',
| |
| | |
| -- regular cats
| |
| alternate_artwork = 'Items with alternate artwork',
| |
| | |
| -- misc
| |
| gem_tag_affix = '%s (gem tag)',
| |
| unique_affix = 'Unique %s',
| |
|
| |
| prophecies = 'Prophecies',
| |
| talismans = 'Talismans',
| |
| essences = 'Essences',
| |
| },
| |
| | |
| stat_skip_patterns = {
| |
| maps = {
| |
| '%d+%% increased Quantity of Items found in this Area',
| |
| '%d+%% increased Rarity of Items found in this Area',
| |
| '%+%d+%% Monster pack size',
| |
| -- ranges
| |
| '%(%d+%-%d+%)%% increased Quantity of Items found in this Area',
| |
| '%(%d+%-%d+%)%% increased Rarity of Items found in this Area',
| |
| '%+%(%d+%-%d+%)%% Monster pack size',
| |
| },
| |
| jewels = {
| |
| 'Limited to %d+ %(Hidden%)',
| |
| 'Jewel has a radius of %d+ %(Hidden%)',
| |
| },
| |
| },
| |
| | |
| | |
| help_text_defaults = {
| |
| active_gem = 'Place into an item socket of the right colour to gain this skill. Right click to remove from a socket.',
| |
| support_gem = 'This is a Support Gem. It does not grant a bonus to your character, but skills in sockets connected to it. Place into an item socket connected to a socket containing the Active Skill Gem you wish to augment. Right click to remove from a socket.',
| |
| hideout_doodad = 'Right click on this item then left click on a location on the ground to create the object.',
| |
| jewel = 'Place into an allocated Jewel Socket on the Passive Skill Tree. Right click to remove from the Socket.',
| |
| },
| |
| | |
| -- Used by the item info box
| |
| tooltips = {
| |
| corrupted = 'Corrupted',
| |
| support_icon = 'Icon: %s',
| |
| radius = 'Radius: %s',
| |
| mana_reserved = 'Mana Reserved: %s',
| |
| mana_cost = 'Mana Cost: %s',
| |
| mana_multiplier = 'Mana Multiplier: %s',
| |
| vaal_souls_per_use = 'Souls Per Use: %s',
| |
| stored_uses = 'Can Store %s Use(s)',
| |
| vaal_soul_gain_prevention_time = 'Soul Gain Prevention: %s',
| |
| cooldown_time = 'Cooldown Time: %s',
| |
| cast_time = 'Cast Time: %s',
| |
| critical_strike_chance = 'Critical Strike Chance: %s',
| |
| damage_effectiveness = 'Damage Effectiveness: %s',
| |
| projectile_speed = 'Projectile Speed: %s',
| |
| quality = 'Quality: %s',
| |
| physical_damage = 'Physical Damage: %s',
| |
| elemental_damage = 'Elemental Damage:%s',
| |
| chaos_damage = 'Chaos Damage: %s',
| |
| attacks_per_second = 'Attacks per Second: %s',
| |
| weapon_range = 'Weapon Range: %s',
| |
| map_level = 'Map Level: %s',
| |
| map_tier = 'Map Tier: %s',
| |
| map_guild_character = m_util.html.abbr('Guild Character', 'When used in guild creation, this map can be used for the listed character') .. ': %s',
| |
| item_quantity = 'Item Quantity: %s',
| |
| item_rarity = 'Item Rarity: %s',
| |
| monster_pack_size = 'Monster Pack Size: %s',
| |
| limited_to = 'Limited to: %s',
| |
| flask_mana_recovery = 'Recovers %s Mana over %s seconds',
| |
| flask_life_recovery = 'Recovers %s Life over %s seconds',
| |
| flask_duration = 'Lasts %s Seconds',
| |
| flask_charges_per_use = 'Consumes %s of %s Charges on use',
| |
| chance_to_block = 'Chance to Block: %s',
| |
| armour = 'Armour: %s',
| |
| evasion = 'Evasion: %s',
| |
| energy_shield = 'Energy Shield: %s',
| |
| talisman_tier = 'Talisman Tier: %s',
| |
| stack_size = 'Stack Size: %s',
| |
| essence_level = 'Essence Level: %s',
| |
| requires = 'Requires %s',
| |
| level_inline = 'Level %s',
| |
| level = 'Level: %s',
| |
| gem_quality = 'Per 1% Quality:',
| |
| variation_singular = 'Variation',
| |
| variation_plural = 'Variations',
| |
| favour_cost = 'Favour cost: %s',
| |
| seal_cost = 'Seal Cost: <br>%s',
| |
| cannot_be_traded_or_modified = 'Cannot be traded or modified',
| |
|
| |
| item_class_map = {
| |
| ['Staff'] = 'Staff',
| |
| ['Bow'] = 'Bow',
| |
| ['Wand'] = 'Wand',
| |
| ['Two Hand Axe'] = 'Two Handed Axe',
| |
| ['Two Hand Sword'] = 'Two Hand Sword',
| |
| ['Two Hand Mace'] = 'Two Hand Mace',
| |
| ['Sceptre'] = 'One Handed Mace',
| |
| ['One Hand Mace'] = 'One Handed Mace',
| |
| ['One Hand Axe'] = 'One Handed Axe',
| |
| ['One Hand Sword'] = 'One Handed Sword',
| |
| ['Thrusting One Hand Sword'] = 'One Handed Sword',
| |
| ['Claw'] = 'Claw',
| |
| ['Dagger'] = 'Dagger',
| |
| ['FishingRod'] = 'Fishing Rod',
| |
| },
| |
|
| |
| random_mod = '<<random modifier %s>>',
| |
|
| |
| --
| |
| -- secondary infobox
| |
| --
| |
| drop_restrictions = 'Acquisition',
| |
| league_restriction = m_util.html.abbr('League(s):', 'Item can be obtained in relation to these league(s)') .. ' %s',
| |
| drop_disabled = 'DROP DISABLED',
| |
|
| |
| purchase_costs = m_util.html.abbr('Purchase Costs', 'Cost of purchasing an item of this type at NPC vendors. This does not indicate whether NPCs actually sell the item.'),
| |
| sell_price = m_util.html.abbr('Sell Price', 'Items or currency received when selling this item at NPC vendors. Certain vendor recipes may override this value.'),
| |
|
| |
| damage_per_second = 'Weapon DPS',
| |
| physical_dps = 'Physical',
| |
| fire_dps = 'Fire',
| |
| cold_dps = 'Cold',
| |
| lightning_dps = 'Lightning',
| |
| chaos_dps = 'Chaos',
| |
| elemental_dps = 'Elemental',
| |
| poison_dps = 'Phys+Chaos',
| |
| dps = 'Total',
| |
|
| |
| misc = 'Miscellaneous',
| |
| item_class = 'Item class: %s',
| |
| metadata_id = 'Metadata ID: %s',
| |
| },
| |
| | |
| item_class_infobox = {
| |
| page = '[[Item class]]',
| |
| info = m_util.html.abbr('(?)', 'Item classes categorize items. Classes are often used to restrict items or skill gems to a specific class or by item filters'),
| |
| also_referred_to_as = 'Also referred to as:',
| |
| },
| |
| | |
| debug = {
| |
| base_item_field_not_found = 'Base item property not found: %s.%s',
| |
| field_value_mismatch = 'Value for argument "%s" is set to something else then default: %s',
| |
| },
| |
| | |
| errors = {
| |
| missing_base_item = 'Rarity is set to above normal, but base item is not set. A base item for rarities above normal is required!',
| |
| missing_rarity = 'Base item parameter is set, but rarity is set to normal. A rarity above normal is required!',
| |
| missing_amount = 'Item amount is missing or not a number (%s)',
| |
| upgraded_from_broken_reference = 'Item reference in %s is broken (results: %s)',
| |
| duplicate_base_items = 'More then one result found for the specified base item. Consider using base_item_page or base_item_id to narrow down the results.',
| |
| base_item_not_found = 'Base item could not be found in the database. Check for spelling mistakes or whether the base item page exists on the wiki. If the base item page exists on the wiki, but it can not be found please null-edit the page.',
| |
| invalid_league = '%s is not a recognized league',
| |
| invalid_tag = '%s is not a valid tag',
| |
| generic_argument_parameter = 'Unrecognized %s parameter "%s"',
| |
| invalid_item_class = 'Invalid item class',
| |
| non_unique_relic = 'Only unique items can be be relics',
| |
| duplicate_area_id_from_query = 'Query found duplicate area ids that do not need to be set on the item. Duplicate ids: "%s"',
| |
| duplicate_metadata = 'Duplicate metadata id "%s" on page "%s"',
| |
| invalid_class = 'The item class name "%s" is invalid.',
| |
| invalid_class_id = 'The item class id "%s" is invalid. Using the correct item class id is required for the template to work correctly.',
| |
| },
| |
| }
| |
| | |
| -- ----------------------------------------------------------------------------
| |
| -- Other stuff
| |
| -- ----------------------------------------------------------------------------
| |
| | |
| local h = {}
| |
| | |
| function h.debug(tpl_args, func)
| |
| if tpl_args.debug == nil then
| |
| return
| |
| end
| |
| func()
| |
| end
| |
| | |
| function h.na_or_val(tr, value, func)
| |
| if value == nil then
| |
| tr:wikitext(m_util.html.td.na())
| |
| else
| |
| local raw_value = value
| |
| if func ~= nil then
| |
| value = func(value)
| |
| end
| |
| tr
| |
| :tag('td')
| |
| :attr('data-sort-value', raw_value)
| |
| :wikitext(value)
| |
| :done()
| |
| end
| |
| end
| |
| | |
| -- helper to loop over the range variables easier
| |
| h.range_map = {
| |
| min = {
| |
| var = '_range_minimum',
| |
| },
| |
| max = {
| |
| var = '_range_maximum',
| |
| },
| |
| avg = {
| |
| var = '_range_average',
| |
| },
| |
| }
| |
| | |
| h.range_fields = {
| |
| {
| |
| field = '_range_minimum',
| |
| type = nil,
| |
| },
| |
| {
| |
| field = '_range_maximum',
| |
| type = nil,
| |
| },
| |
| {
| |
| field = '_range_average',
| |
| type = nil,
| |
| },
| |
| {
| |
| field = '_range_text',
| |
| type = 'Text',
| |
| },
| |
| {
| |
| field = '_range_colour',
| |
| type = 'String',
| |
| },
| |
| {
| |
| field = '_html',
| |
| type = 'Text',
| |
| },
| |
| | |
| }
| |
| | |
| function h.handle_range_args(tpl_args, frame, argument_key, field, value, fmt_options)
| |
| fmt_options = mw.clone(fmt_options)
| |
| fmt_options.return_color = true
| |
| local html, colour = m_util.html.format_value(tpl_args, frame, value, fmt_options)
| |
| tpl_args[argument_key .. '_html'] = html
| |
| tpl_args[field .. '_html'] = html
| |
| tpl_args[field .. '_range_colour'] = colour
| |
|
| |
| fmt_options = mw.clone(fmt_options)
| |
| fmt_options.no_color = true
| |
| tpl_args[field .. '_range_text'] = m_util.html.format_value(tpl_args, frame, value, fmt_options)
| |
| end
| |
| | |
| function h.stats_update(tpl_args, id, value, modid, key)
| |
| if tpl_args[key][id] == nil then
| |
| tpl_args[key][id] = {
| |
| references = {modid},
| |
| min = value.min,
| |
| max = value.max,
| |
| avg = value.avg,
| |
| }
| |
| else
| |
| if modid ~= nil then
| |
| table.insert(tpl_args[key][id].references, modid)
| |
| end
| |
| tpl_args[key][id].min = tpl_args[key][id].min + value.min
| |
| tpl_args[key][id].max = tpl_args[key][id].max + value.max
| |
| tpl_args[key][id].avg = tpl_args[key][id].avg + value.avg
| |
| end
| |
| end
| |
| | |
| h.stat = {}
| |
| function h.stat.add (value, stat_cached)
| |
| value.min = value.min + stat_cached.min
| |
| value.max = value.max + stat_cached.max
| |
| end
| |
| | |
| function h.stat.more (value, stat_cached)
| |
| value.min = value.min * (1 + stat_cached.min / 100)
| |
| value.max = value.max * (1 + stat_cached.max / 100)
| |
| end
| |
| | |
| function h.stat.more_inverse (value, stat_cached)
| |
| value.min = value.min / (1 + stat_cached.min / 100)
| |
| value.max = value.max / (1 + stat_cached.max / 100)
| |
| end
| |
| | |
| -- ----------------------------------------------------------------------------
| |
| -- core
| |
| -- ----------------------------------------------------------------------------
| |
| | |
| local core = {}
| |
| | |
| function core.build_cargo_data(tpl_args, frame)
| |
| for _, table_name in ipairs(core.item_classes[tpl_args.class_id].tables) do
| |
| for k, field_data in pairs(core.cargo[table_name].fields) do
| |
| field_data.table = table_name
| |
| for _, stat_data in pairs(core.stat_map) do
| |
| if stat_data.field == k then
| |
| for _, range_field in ipairs(h.range_fields) do
| |
| local field_name = stat_data.field .. range_field.field
| |
|
| |
| local data = {
| |
| no_copy = true,
| |
| table = table_name,
| |
| field = field_name,
| |
| -- if the type is nil, use the parent type
| |
| -- this is set integer/float values correctly
| |
| type = range_field.type or field_data.type,
| |
| }
| |
|
| |
| core.cargo[table_name].fields[field_name] = data
| |
| core.map[field_name] = data
| |
| end
| |
| break
| |
| end
| |
| end
| |
| if table_name == 'weapons' then
| |
| for _, dps_data in ipairs(core.dps_map) do
| |
| for _, range_field in ipairs(h.range_fields) do
| |
| local field_name = dps_data.field .. range_field.field
| |
|
| |
| local data = {
| |
| no_copy = true,
| |
| table = table_name,
| |
| field = field_name,
| |
| -- dps values are floating points
| |
| type = range_field.type or 'Float',
| |
| }
| |
|
| |
| core.cargo[table_name].fields[field_name] = data
| |
| core.map[field_name] = data
| |
| end
| |
| end
| |
| end
| |
| end
| |
| end
| |
| end
| |
| | |
| function core.validate_mod(tpl_args, frame, args)
| |
| -- args:
| |
| -- key - implict or explicit
| |
| -- i
| |
| -- value
| |
| local prefix = args.key .. args.i
| |
| local value = tpl_args[prefix]
| |
| local out = {
| |
| result=nil,
| |
| -- commited to cargo at a later point
| |
| id=nil,
| |
| stat_text=nil,
| |
| is_implicit=(args.key == 'implicit'),
| |
| is_random=nil,
| |
| }
| |
|
| |
| if value ~= nil then
| |
| out.id = value
| |
| out.stat_text = tpl_args[prefix .. '_text']
| |
| out.is_random = false
| |
| table.insert(tpl_args._mods, out)
| |
|
| |
| return true
| |
| elseif tpl_args[prefix .. '_random_list'] then
| |
| tpl_args._flags.random_mods = true
| |
| value = m_util.string.split(tpl_args[prefix .. '_random_list'], ',%s*')
| |
| for _, mod_id in ipairs(value) do
| |
| table.insert(tpl_args._mods, {
| |
| result = nil,
| |
| id = mod_id,
| |
| stat_text = tpl_args[prefix .. '_text'] or string.format(i18n.tooltips.random_mod, args.i),
| |
| is_implicit = (args.key == 'implicit'),
| |
| is_random = true,
| |
| })
| |
| end
| |
|
| |
| return true
| |
| elseif tpl_args[prefix .. '_text'] then
| |
| value = tpl_args[prefix .. '_text']
| |
| tpl_args._flags.text_modifier = true
| |
| out.result = value
| |
| out.stat_text = value
| |
| out.is_random = false
| |
| table.insert(tpl_args._mods, out)
| |
|
| |
| return true
| |
| end
| |
|
| |
| return false
| |
| end
| |
| | |
| function core.process_smw_mods(tpl_args, frame)
| |
| if #tpl_args._mods > 0 then
| |
| local mods = {}
| |
| local mod_ids = {}
| |
| local non_random_mod_ids = {}
| |
| for _, mod_data in ipairs(tpl_args._mods) do
| |
| if mod_data.result == nil then
| |
| mods[mod_data.id] = mod_data
| |
| mod_ids[#mod_ids+1] = mod_data.id
| |
| if not mod_data.is_random then
| |
| table.insert(non_random_mod_ids, mod_data.id)
| |
| end
| |
| end
| |
| tpl_args._subobjects[#tpl_args._subobjects+1] = {
| |
| _table = 'item_mods',
| |
| id = mod_data.id,
| |
| text = mod_data.stat_text,
| |
| is_implicit = mod_data.is_implicit,
| |
| is_random = mod_data.is_random,
| |
| }
| |
| end
| |
|
| |
| local results = m_cargo.array_query{
| |
| tables={'mods'},
| |
| fields={'mods._pageName', 'mods.id', 'mods.required_level', 'mods.stat_text'},
| |
| id_field='mods.id',
| |
| id_array=mod_ids,
| |
| }
| |
|
| |
| for _, data in ipairs(results) do
| |
| local mod_data = mods[data['mods.id']]
| |
| mod_data.result = data
| |
|
| |
| if mod_data.is_random == false then
| |
| -- update item level requirement
| |
| local keys = {'required_level_final'}
| |
| -- only update base item requirement if this is an implicit
| |
| if mod_data.key == 'implicit' then
| |
| keys[#keys+1] = 'required_level'
| |
| end
| |
|
| |
| for _, key in ipairs(keys) do
| |
| local req = math.floor(tonumber(data['mods.required_level']) * 0.8)
| |
| if req > tpl_args[key] then
| |
| tpl_args[key] = req
| |
| end
| |
| end
| |
| end
| |
| end
| |
|
| |
| -- fetch stats
| |
|
| |
| results = m_cargo.query(
| |
| {'mods', 'mod_stats'},
| |
| {'mods.id', 'mod_stats.id', 'mod_stats.min', 'mod_stats.max'},
| |
| {
| |
| join='mods._pageID=mod_stats._pageID',
| |
| where=string.format('mod_stats.id IS NOT NULL AND mods.id IN ("%s")', table.concat(mod_ids, '", "')),
| |
| }
| |
| )
| |
| for _, data in ipairs(results) do
| |
| -- Stat subobject
| |
| local mod_data = mods[data['mods.id']]
| |
| if mod_data.result.stats == nil then
| |
| mod_data.result.stats = {data, }
| |
| else
| |
| mod_data.result.stats[#mod_data.result.stats+1] = data
| |
| end
| |
|
| |
| local id = data['mod_stats.id']
| |
| local value = {
| |
| min = tonumber(data['mod_stats.min']),
| |
| max = tonumber(data['mod_stats.max']),
| |
| }
| |
| value.avg = (value.min+value.max)/2
| |
|
| |
| local prefix = ''
| |
| if mod_data.is_random then
| |
| prefix = '_random'
| |
| end
| |
| h.stats_update(tpl_args, id, value, mod_data.result['mods.id'], prefix .. '_stats')
| |
| if mod_data.is_implicit then
| |
| h.stats_update(tpl_args, id, value, mod_data.result['mods.id'], prefix .. '_implicit_stats')
| |
| else
| |
| h.stats_update(tpl_args, id, value, mod_data.result['mods.id'], prefix .. '_explicit_stats')
| |
| end
| |
| end
| |
|
| |
| if tpl_args._flags.sell_prices_override ~= true then
| |
| -- fetch sell prices
| |
| results = m_cargo.query(
| |
| {'mods', 'mod_sell_prices'},
| |
| {'mods.id', 'mod_sell_prices.amount', 'mod_sell_prices.name'},
| |
| {
| |
| join='mods._pageID=mod_sell_prices._pageID',
| |
| -- must be non random mods to avoid accumulating sell prices of randomized modifiers
| |
| where=string.format('mod_sell_prices.amount IS NOT NULL AND mods.id IN ("%s")', table.concat(non_random_mod_ids, '", "')),
| |
| }
| |
| )
| |
|
| |
| for _, data in ipairs(results) do
| |
| local mod_data = mods[data['mods.id']]
| |
| if not mod_data.is_implicit then
| |
| local values = {
| |
| name = data['mod_sell_prices.name'],
| |
| amount = tonumber(data['mod_sell_prices.amount']),
| |
| }
| |
| -- sell_prices is defined in tpl_args.sell_prices_override
| |
| tpl_args.sell_prices[values.name] = (tpl_args.sell_prices[values.name] or 0) + values.amount
| |
| end
| |
| end
| |
| end
| |
| end
| |
| if tpl_args._flags.sell_prices_override ~= true then
| |
| local missing_sell_price = true
| |
| for _, _ in pairs(tpl_args.sell_prices) do
| |
| missing_sell_price = false
| |
| break
| |
| end
| |
|
| |
| if missing_sell_price then
| |
| tpl_args.sell_prices['Scroll Fragment'] = 1
| |
| end
| |
|
| |
| -- Set sell price on page
| |
| for name, amount in pairs(tpl_args.sell_prices) do
| |
| -- sell_price_order is defined in tpl_args.sell_prices_override
| |
| tpl_args.sell_price_order[#tpl_args.sell_price_order+1] = name
| |
| tpl_args._subobjects[#tpl_args._subobjects+1] = {
| |
| _table = 'item_sell_prices',
| |
| amount = amount,
| |
| name = name,
| |
| }
| |
| end
| |
| table.sort(tpl_args.sell_price_order)
| |
| end
| |
| end
| |
| | |
| function core.process_base_item(tpl_args, frame, args)
| |
| local where
| |
| if tpl_args.base_item_id ~= nil then
| |
| where = string.format('items.metadata_id="%s"', tpl_args.base_item_id)
| |
| elseif tpl_args.base_item_page ~= nil then
| |
| where = string.format('items._pageName="%s"' , tpl_args.base_item_page)
| |
| elseif tpl_args.base_item ~= nil then
| |
| where = string.format('items.name="%s"' , tpl_args.base_item)
| |
| elseif tpl_args.rarity ~= 'Normal' then
| |
| error(m_util.html.error{msg=i18n.errors.missing_base_item})
| |
| else
| |
| return
| |
| end
| |
|
| |
| if where ~= nil and tpl_args.rarity == 'Normal' and not tpl_args._flags.is_prophecy then
| |
| error(m_util.html.error{msg=i18n.errors.missing_rarity})
| |
| end
| |
|
| |
| where = string.format('%s AND items.class_id="%s" AND items.rarity="Normal"', where, tpl_args.class_id)
| |
|
| |
| local join = {}
| |
|
| |
| for _, table_name in ipairs(core.item_classes[tpl_args.class_id].tables) do
| |
| if table_name ~= 'items' then
| |
| join[#join+1] = string.format('items._pageID=%s._pageID', table_name)
| |
| end
| |
| end
| |
|
| |
| local fields = {
| |
| 'items._pageName',
| |
| 'items.name',
| |
| 'items.metadata_id',
| |
| }
| |
|
| |
| for _, k in ipairs(tpl_args._base_item_args) do
| |
| local data = core.map[k]
| |
| if data.field ~= nil then
| |
| fields[#fields+1] = string.format('%s.%s', data.table, data.field)
| |
| end
| |
| end
| |
|
| |
| local result = m_util.cargo.query(
| |
| core.item_classes[tpl_args.class_id].tables,
| |
| fields,
| |
| {
| |
| where=where,
| |
| join=table.concat(join, ','),
| |
| groupBy='items._pageID',
| |
| }
| |
| )
| |
|
| |
| if #result > 1 then
| |
| error(m_util.html.error{msg=i18n.errors.duplicate_base_items})
| |
| -- TODO be more explicit in the error?
| |
| elseif #result == 0 then
| |
| error(m_util.html.error{msg=i18n.errors.base_item_not_found})
| |
| end
| |
|
| |
| result = result[1]
| |
|
| |
| tpl_args.base_item_data = result
| |
| core.process_arguments(tpl_args, frame, {array={'base_item', 'base_item_page', 'base_item_id'}})
| |
| | |
| --Copy values..
| |
| for _, k in ipairs(tpl_args._base_item_args) do
| |
| local data = core.map[k]
| |
| if data.field ~= nil and data.func_fetch == nil then
| |
| local value = result[string.format('%s.%s', data.table, data.field)]
| |
| -- I can just use data.default since it will be nil if not provided (nil == nil). Neat! ;)
| |
| if value ~= nil and (tpl_args[k] == data.default or type(data.default) == 'function') then
| |
| tpl_args[k] = value
| |
| if data.func ~= nil then
| |
| data.func(tpl_args, frame)
| |
| end
| |
| if data.func_copy ~= nil then
| |
| data.func_copy(tpl_args, frame)
| |
| end
| |
| elseif value == nil then
| |
| h.debug(tpl_args, function ()
| |
| mw.logObject(string.format(i18n.debug.base_item_field_not_found, data.table, data.field))
| |
| end)
| |
| elseif tpl_args[k] ~= data.default then
| |
| h.debug(tpl_args, function ()
| |
| mw.logObject(string.format(i18n.debug.field_value_mismatch, k, tostring(tpl_args[k])))
| |
| end)
| |
| end
| |
| elseif data.func_fetch ~= nil then
| |
| data.func_fetch(tpl_args, frame)
| |
| end
| |
| end
| |
| end
| |
| | |
| function core.process_arguments(tpl_args, frame, args)
| |
| for _, k in ipairs(args.array) do
| |
| local data = core.map[k]
| |
| if data == nil then
| |
| error(string.format('Invalid key or missing data for "%s"', k))
| |
| end
| |
| if data.no_copy == nil then
| |
| table.insert(tpl_args._base_item_args, k)
| |
| end
| |
| if data.func ~= nil then
| |
| data.func(tpl_args, frame)
| |
| --[[local status, err = pcall(data.func)
| |
| -- an error was raised, return the error string instead of the template
| |
| if not status then
| |
| return err
| |
| end
| |
| ]]--
| |
| end
| |
| if tpl_args[k] == nil then
| |
| if tpl_args.class_id and core.item_classes[tpl_args.class_id].defaults ~= nil and core.item_classes[tpl_args.class_id].defaults[k] ~= nil then
| |
| tpl_args[k] = core.item_classes[tpl_args.class_id].defaults[k]
| |
| elseif data.default ~= nil then
| |
| if type(data.default) == 'function' then
| |
| tpl_args[k] = data.default()
| |
| else
| |
| tpl_args[k] = data.default
| |
| end
| |
| end
| |
| end
| |
| end
| |
| end
| |
|
| |
| function core.process_mod_stats(tpl_args, args)
| |
| local lines = {}
| |
|
| |
| local skip = core.class_specifics[tpl_args.class_id]
| |
| if skip then
| |
| skip = skip.skip_stat_lines
| |
| end
| |
|
| |
| local random_mods = {}
| |
|
| |
| for _, modinfo in ipairs(tpl_args._mods) do
| |
| if modinfo.is_implicit == args.is_implicit then
| |
| if modinfo.is_random == true then
| |
| if random_mods[modinfo.stat_text] then
| |
| table.insert(random_mods[modinfo.stat_text], modinfo)
| |
| else
| |
| random_mods[modinfo.stat_text] = {modinfo}
| |
| end
| |
| else
| |
| if modinfo.id == nil then
| |
| table.insert(lines, modinfo.result)
| |
| -- Allows the override of the SMW fetched mod texts for this modifier via <modtype><id>_text parameter
| |
| elseif modinfo.text ~= nil then
| |
| table.insert(lines, modinfo.text)
| |
| else
| |
| for _, line in ipairs(m_util.string.split(modinfo.result['mods.stat_text'] or '', '<br>')) do
| |
| if line ~= '' then
| |
| if skip == nil then
| |
| table.insert(lines, line)
| |
| else
| |
| local skipped = false
| |
| for _, pattern in ipairs(skip) do
| |
| if string.match(line, pattern) then
| |
| skipped = true
| |
| break
| |
| end
| |
| end
| |
| if not skipped then
| |
| table.insert(lines, line)
| |
| end
| |
| end
| |
| end
| |
| end
| |
| end
| |
| end
| |
| end
| |
| end
| |
|
| |
| for stat_text, modinfo_list in pairs(random_mods) do
| |
| local text = {}
| |
| for _, modinfo in ipairs(modinfo_list) do
| |
| table.insert(text, modinfo.result['mods.stat_text'])
| |
| end
| |
|
| |
| local tbl = mw.html.create('table')
| |
| tbl
| |
| :attr('class', 'random-modifier-stats mw-collapsed')
| |
| :attr('style', 'text-align: left')
| |
| :tag('tr')
| |
| :tag('th')
| |
| :attr('class', 'mw-customtoggle-31')
| |
| :wikitext(stat_text)
| |
| :done()
| |
| :done()
| |
| :tag('tr')
| |
| :attr('class', 'mw-collapsible mw-collapsed')
| |
| :attr('id', 'mw-customcollapsible-31')
| |
| :tag('td')
| |
| :wikitext(table.concat(text, '<hr style="width: 20%">'))
| |
| :done()
| |
| :done()
| |
| table.insert(lines, tostring(tbl))
| |
| end
| |
|
| |
| if #lines == 0 then
| |
| return
| |
| else
| |
| return table.concat(lines, '<br>')
| |
| end
| |
| end
| |
| | |
| function core.process_upgraded_from(tpl_args, frame)
| |
| local sets = {}
| |
| local setid = 1
| |
| local set
| |
| repeat
| |
| local prefix = string.format('upgraded_from_set%s_', setid)
| |
| local groupid = 1
| |
| local group
| |
| set = {
| |
| groups = {},
| |
| optional = m_util.cast.boolean(tpl_args[prefix .. 'optional']),
| |
| text = m_util.cast.text(tpl_args[prefix .. 'text']),
| |
| }
| |
| repeat
| |
| local group_prefix = string.format('%sgroup%s_', prefix, groupid)
| |
| group = {
| |
| item_name = tpl_args[group_prefix .. 'item_name'],
| |
| item_id = tpl_args[group_prefix .. 'item_id'],
| |
| item_page = tpl_args[group_prefix .. 'item_page'],
| |
| amount = tonumber(tpl_args[group_prefix .. 'amount']),
| |
| notes = m_util.cast.text(tpl_args[group_prefix .. 'notes']),
| |
| }
| |
|
| |
| if group.item_name ~= nil or group.item_id ~= nil or group.item_page ~= nil then
| |
| if group.amount == nil then
| |
| error(string.format(i18n.errors.missing_amount, group_prefix .. 'amount'))
| |
| else
| |
| -- for verification purposes
| |
| local where
| |
| if group.item_id then
| |
| where = string.format('items.metadata_id="%s"', group.item_id)
| |
| elseif group.item_page then
| |
| where = string.format('items._pageName="%s"', group.item_page)
| |
| elseif group.item_name then
| |
| where = string.format('items.name="%s"', group.item_name)
| |
| end
| |
|
| |
| local results = m_util.cargo.query(
| |
| {'items'},
| |
| {'items._pageName', 'items.name', 'items.metadata_id'},
| |
| {
| |
| where=where,
| |
| }
| |
| )
| |
| if #results ~= 1 then
| |
| tpl_args._errors[#tpl_args._errors+1] = string.format(i18n.errors.upgraded_from_broken_reference, string.sub(group_prefix, 1, -2), #results)
| |
| tpl_args._flags.broken_upgraded_from_reference = true
| |
| else
| |
| results = results[1]
| |
| if results['items.metadata_id'] then
| |
| group.item_id = results['items.metadata_id']
| |
| end
| |
| group.item_name = results['items.name']
| |
| group.page = results['items._pageName']
| |
| set.groups[#set.groups+1] = group
| |
| end
| |
| end
| |
| end
| |
|
| |
| groupid = groupid + 1
| |
| until group.item_name == nil and group.item_id == nil and group.item_page == nil
| |
|
| |
| -- set was empty, can terminate safely
| |
| if #set.groups == 0 then
| |
| set = nil
| |
| else
| |
| setid = setid + 1
| |
| sets[#sets+1] = set
| |
| end
| |
| until set == nil
| |
|
| |
| if #sets == 0 then
| |
| return
| |
| end
| |
| | |
| tpl_args.upgrade_from_sets = sets
| |
|
| |
| -- set upgraded_from data
| |
| for i, set in ipairs(sets) do
| |
| tpl_args._subobjects[#tpl_args._subobjects+1] = {
| |
| _table = 'upgraded_from_sets',
| |
| set_id = i,
| |
| text = set.text,
| |
| --'optional' = set.optional,
| |
| }
| |
|
| |
| for j, group in ipairs(set.groups) do
| |
| tpl_args._subobjects[#tpl_args._subobjects+1] = {
| |
| _table = 'upgraded_from_groups',
| |
| group_id = j,
| |
| set_id = i,
| |
| item_name = group.item_name,
| |
| item_id = group.item_id,
| |
| item_page = group.page,
| |
| amount = group.amount,
| |
| notes = group.notes,
| |
| }
| |
| end
| |
| end
| |
| end
| |
| | |
| --
| |
| -- function factory
| |
| --
| |
| core.factory = {}
| |
| | |
| function core.factory.cast_text(k, args)
| |
| args = args or {}
| |
| return function (tpl_args, frame)
| |
| tpl_args[args.key_out or k] = m_util.cast.text(tpl_args[k])
| |
| end
| |
| end
| |
| | |
| function core.factory.display_value(args)
| |
| -- args:
| |
| -- type: Type of the keys (nil = regular, gem = skill gems, stat = stats)
| |
| -- options<Array>:
| |
| -- key: key to use
| |
| -- allow_zero: allow zero values
| |
| -- hide_default: hide the value if this is set
| |
| -- hide_default_key: key to use if it isn't equal to the key parameter
| |
| -- -- from m_util.html.format_value --
| |
| -- fmt: formatter to use for the value instead of valfmt
| |
| -- fmt_range: formatter to use for the range values. Default: (%s to %s)
| |
| -- insert: insert results into this object
| |
| -- func: Function to adjust the value with before output
| |
| -- color: colour code for m_util.html.poe_color, overrides mod colour
| |
| -- no_color: set to true to ingore colour entirely
| |
| -- truncate: set to true to truncate the line
| |
|
| |
| for k, default in pairs({options = {}}) do
| |
| if args[k] == nil then
| |
| args[k] = default
| |
| end
| |
| end
| |
|
| |
| return function (tpl_args, frame)
| |
| local base_values = {}
| |
| local temp_values = {}
| |
| if args.type == 'gem' then
| |
| if not core.class_groups.gems.keys[tpl_args.class_id] then
| |
| return
| |
| end
| |
| for i, data in ipairs(args.options) do
| |
| local value = tpl_args.skill_levels[0][data.key]
| |
| if value ~= nil then
| |
| base_values[#base_values+1] = value
| |
| temp_values[#temp_values+1] = {value={min=value,max=value}, index=i}
| |
| else
| |
| value = {
| |
| min=tpl_args.skill_levels[1][data.key],
| |
| max=tpl_args.skill_levels[tpl_args.max_level][data.key],
| |
| }
| |
| if value.min == nil or value.max == nil then
| |
| else
| |
| base_values[#base_values+1] = value.min
| |
| temp_values[#temp_values+1] = {value=value, index=i}
| |
| end
| |
| end
| |
| end
| |
| elseif args.type == 'stat' then
| |
| for i, data in ipairs(args.options) do
| |
| local value = tpl_args._stats[data.key]
| |
| if value ~= nil then
| |
| base_values[i] = value.min
| |
| temp_values[#temp_values+1] = {value=value, index=i}
| |
| end
| |
| end
| |
| else
| |
| for i, data in ipairs(args.options) do
| |
| base_values[i] = tpl_args[data.key]
| |
| local value = {}
| |
| if tpl_args[data.key .. '_range_minimum'] ~= nil then
| |
| value.min = tpl_args[data.key .. '_range_minimum']
| |
| value.max = tpl_args[data.key .. '_range_maximum']
| |
| elseif tpl_args[data.key] ~= nil then
| |
| value.min = tpl_args[data.key]
| |
| value.max = tpl_args[data.key]
| |
| end
| |
| if value.min == nil then
| |
| else
| |
| temp_values[#temp_values+1] = {value=value, index=i}
| |
| end
| |
| end
| |
| end
| |
|
| |
| local final_values = {}
| |
| for i, data in ipairs(temp_values) do
| |
| local opt = args.options[data.index]
| |
| local insert = false
| |
| if opt.hide_default == nil then
| |
| insert = true
| |
| elseif opt.hide_default_key == nil then
| |
| local v = data.value
| |
| if opt.hide_default ~= v.min and opt.hide_default ~= v.max then
| |
| insert = true
| |
| end
| |
| else
| |
| local v = {
| |
| min = tpl_args[opt.hide_default_key .. '_range_minimum'],
| |
| max = tpl_args[opt.hide_default_key .. '_range_maximum'],
| |
| }
| |
| if v.min == nil or v.max == nil then
| |
| if opt.hide_default ~= tpl_args[opt.hide_default_key] then
| |
| insert = true
| |
| end
| |
| elseif opt.hide_default ~= v.min and opt.hide_default ~= v.max then
| |
| insert = true
| |
| end
| |
| end
| |
|
| |
| if insert == true then
| |
| table.insert(final_values, data)
| |
| end
| |
| end
| |
|
| |
| -- all zeros = dont display and return early
| |
| if #final_values == 0 then
| |
| return nil
| |
| end
| |
|
| |
| local out = {}
| |
|
| |
| for i, data in ipairs(final_values) do
| |
| local value = data.value
| |
| value.base = base_values[data.index]
| |
|
| |
| local options = args.options[data.index]
| |
|
| |
| if options.color == nil and args.type == 'gem' then
| |
| value.color = 'value'
| |
| end
| |
| if options.truncate then
| |
| options.class = 'u-truncate-line -mod'
| |
| end
| |
|
| |
| out[#out+1] = m_util.html.format_value(tpl_args, frame, value, options)
| |
| end
| |
|
| |
| if args.inline then
| |
| return m_util.html.poe_color('default', string.format(args.inline, unpack(out)), options.class)
| |
| else
| |
| return table.concat(out, '')
| |
| end
| |
| end
| |
| end
| |
| | |
| function core.factory.display_value_only(key)
| |
| return function(tpl_args, frame)
| |
| return tpl_args[key]
| |
| end
| |
| end
| |
| | |
| function core.factory.descriptor_value(args)
| |
| -- Arguments:
| |
| -- key
| |
| -- tbl
| |
| args = args or {}
| |
| return function (tpl_args, frame, value)
| |
| args.tbl = args.tbl or tpl_args
| |
| if args.tbl[args.key] then
| |
| value = m_util.html.abbr(value, args.tbl[args.key])
| |
| end
| |
| return value
| |
| end
| |
| end
| |
| | |
| function core.factory.damage_html(args)
| |
| return function(tpl_args, frame)
| |
| if args.key ~= 'physical' then
| |
| args.color = args.key
| |
| args.no_color = true
| |
| end
| |
| local keys = {
| |
| min=args.key .. '_damage_min',
| |
| max=args.key .. '_damage_max',
| |
| }
| |
| local value = {}
| |
|
| |
| for ktype, key in pairs(keys) do
| |
| value[ktype] = core.factory.display_value{options={ [1] = {
| |
| key = key,
| |
| no_color = args.no_color,
| |
| hide_default = 0
| |
| }}}(tpl_args, frame)
| |
| end
| |
|
| |
| if value.min and value.max then
| |
| value = value.min .. '–' .. value.max
| |
| if args.color ~= nil then
| |
| value = m_util.html.poe_color(args.color, value)
| |
| end
| |
| tpl_args[args.key .. '_damage_html'] = value
| |
| end
| |
| end
| |
| end
| |
| | |
| core.display = {}
| |
| function core.display.make_main_container(tpl_args, frame, container_type)
| |
| local container = mw.html.create('span')
| |
| :attr( 'class', 'item-box -' .. tpl_args.frame_type)
| |
|
| |
| if tpl_args.class_id == 'DivinationCard' then
| |
| container
| |
| :tag('span')
| |
| :attr( 'class', 'divicard-wrapper')
| |
| :tag('span')
| |
| :attr('class', 'divicard-art')
| |
| :wikitext( '[[' .. tpl_args.card_art .. '|link=|alt=]]' )
| |
| :done()
| |
| :tag('span')
| |
| :attr('class', 'divicard-frame')
| |
| :wikitext( '[[File:Divination card frame.png|link=|alt=]]' )
| |
| :done()
| |
| :tag('span')
| |
| :attr('class', 'divicard-header')
| |
| :wikitext(tpl_args.name)
| |
| :done()
| |
| :tag('span')
| |
| :attr('class', 'divicard-stack')
| |
| :wikitext(tpl_args.stack_size)
| |
| :done()
| |
| :tag('span')
| |
| :attr('class', 'divicard-reward')
| |
| :tag('span')
| |
| :wikitext(tpl_args.description)
| |
| :done()
| |
| :done()
| |
| :tag('span')
| |
| :attr('class', 'divicard-flavour text-color -flavour')
| |
| :tag('span')
| |
| :wikitext(tpl_args.flavour_text)
| |
| :done()
| |
| :done()
| |
| :done()
| |
| --TODO Extras?
| |
| else
| |
| local header_css
| |
| if tpl_args.base_item and tpl_args.rarity ~= 'Normal' then
| |
| line_type = 'double'
| |
| else
| |
| line_type = 'single'
| |
| end
| |
|
| |
| local name_line = tpl_args.name
| |
| if tpl_args.base_item and not tpl_args._flags.is_prophecy then
| |
| name_line = name_line .. '<br>' .. tpl_args.base_item
| |
| end
| |
|
| |
| container
| |
| :tag('span')
| |
| :attr( 'class', 'header -' .. line_type )
| |
| :wikitext( name_line )
| |
| :done()
| |
|
| |
| core.display.add_to_container_from_map(tpl_args, frame, container, core.item_display_groups, container_type)
| |
| end
| |
|
| |
| if tpl_args.skill_icon ~= nil then
| |
| container:wikitext(string.format('[[%s]]', tpl_args.skill_icon))
| |
| end
| |
|
| |
| return container
| |
| end
| |
| | |
| function core.display.add_to_container_from_map(tpl_args, frame, container, mapping, container_type)
| |
| local grpcont
| |
| local valid
| |
| local statcont = mw.html.create('span')
| |
| statcont
| |
| :attr('class', 'item-stats')
| |
| :done()
| |
|
| |
| local count = 0
| |
|
| |
| for _, group in ipairs(mapping) do
| |
| grpcont = {}
| |
| if group.func == nil then
| |
| for _, disp in ipairs(group) do
| |
| valid = true
| |
| if container_type == 'inline' and disp.inline == false then
| |
| valid = false
| |
| else
| |
| -- No args to verify which means always valid
| |
| if disp.args == nil then
| |
| elseif type(disp.args) == 'table' then
| |
| for _, key in ipairs(disp.args) do
| |
| if tpl_args[key] == nil then
| |
| valid = false
| |
| break
| |
| end
| |
| end
| |
| elseif type(disp.args) == 'function' then
| |
| valid = disp.args(tpl_args, frame, container_type)
| |
| end
| |
| end
| |
| if valid then
| |
| grpcont[#grpcont+1] = disp.func(tpl_args, frame, container_type)
| |
| end
| |
| end
| |
| else
| |
| grpcont = group.func(tpl_args, frame, container_type)
| |
| end
| |
|
| |
| if #grpcont > 0 then
| |
| count = count + 1
| |
| local header = ''
| |
| if group.header == nil then
| |
| elseif type(group.header) == 'function' then
| |
| header = group.header()
| |
| else
| |
| header = string.format('<em class="header">%s</em><br>', group.header)
| |
| end
| |
| statcont
| |
| :tag('span')
| |
| :attr('class', 'group ' .. (group.css_class or ''))
| |
| :wikitext(header .. table.concat(grpcont, '<br>'))
| |
| :done()
| |
| end
| |
| end
| |
|
| |
| -- Don't add empty containers
| |
| if count > 0 then
| |
| container:node(statcont)
| |
| end
| |
| end
| |
| | |
| function core.display.strip_random_stats(tpl_args, frame, stat_text, container_type)
| |
| if tpl_args._flags.random_mods and container_type == 'inline' then
| |
| repeat
| |
| local text = string.match(stat_text, '<th class="mw%-customtoggle%-31">(.+)</th>')
| |
| if text ~= nil then
| |
| stat_text = string.gsub(stat_text, '<table class="random%-modifier%-stats.+</table>', text, 1)
| |
| end
| |
| until text == nil
| |
| end
| |
| return stat_text
| |
| end
| |
| | |
| --
| |
| -- argument mapping
| |
| --
| |
| -- format:
| |
| -- tpl_args key = {
| |
| -- no_copy = true or nil -- When loading an base item, dont copy this key
| |
| -- property = 'prop', -- Property associated with this key
| |
| -- property_func = function or nil -- Function to unpack the property into a native lua value.
| |
| -- If not specified, func is used.
| |
| -- If neither is specified, value is copied as string
| |
| -- func = function or nil -- Function to unpack the argument into a native lua value and validate it.
| |
| -- If not specified, value will not be set.
| |
| -- default = object -- Default value if the parameter is nil
| |
| -- }
| |
| core.map = {
| |
| -- special params
| |
| html = {
| |
| no_copy = true,
| |
| field = 'html',
| |
| type = 'Text',
| |
| func = nil,
| |
| },
| |
| implicit_stat_text = {
| |
| field = 'implicit_stat_text',
| |
| type = 'Text',
| |
| func = function(tpl_args, frame)
| |
| tpl_args.implicit_stat_text = core.process_mod_stats(tpl_args, {is_implicit=true})
| |
| end,
| |
| },
| |
| explicit_stat_text = {
| |
| field = 'explicit_stat_text',
| |
| type = 'Text',
| |
| func = function(tpl_args, frame)
| |
| tpl_args.explicit_stat_text = core.process_mod_stats(tpl_args, {is_implicit=false})
| |
|
| |
| if tpl_args.is_talisman or tpl_args.is_corrupted then
| |
| if tpl_args.explicit_stat_text == nil or tpl_args.explicit_stat_text == '' then
| |
| tpl_args.explicit_stat_text = m_util.html.poe_color('corrupted', i18n.tooltips.corrupted)
| |
| else
| |
| tpl_args.explicit_stat_text = (tpl_args.explicit_stat_text or '') .. '<br>' .. m_util.html.poe_color('corrupted', i18n.tooltips.corrupted)
| |
| end
| |
| end
| |
| end,
| |
| },
| |
| stat_text = {
| |
| field = 'stat_text',
| |
| type = 'Text',
| |
| func = function(tpl_args, frame)
| |
| local sep = ''
| |
| if tpl_args.implicit_stat_text and tpl_args.explicit_stat_text then
| |
| sep = string.format('<span class="item-stat-separator -%s"></span>', tpl_args.frame_type)
| |
| end
| |
| local text = (tpl_args.implicit_stat_text or '') .. sep .. (tpl_args.explicit_stat_text or '')
| |
|
| |
| if string.len(text) > 0 then
| |
| tpl_args.stat_text = text
| |
| end
| |
| end,
| |
| },
| |
| class = {
| |
| no_copy = true,
| |
| field = 'class',
| |
| type = 'String',
| |
| func = function (tpl_args, frame)
| |
| tpl_args.class = m_game.constants.item.classes[tpl_args.class_id]['long_upper']
| |
| end,
| |
| },
| |
| -- processed in core.build_item_classes
| |
| class_id = {
| |
| no_copy = true,
| |
| field = 'class_id',
| |
| type = 'String',
| |
| func = function (tpl_args, frame)
| |
| if m_game.constants.item.classes[tpl_args.class_id] == nil then
| |
| error(string.format(i18n.errors.invalid_class_id, tostring(tpl_args.class_id)))
| |
| end
| |
| end
| |
| },
| |
| -- generic
| |
| rarity = {
| |
| no_copy = true,
| |
| field = 'rarity',
| |
| type = 'String',
| |
| func = m_util.cast.factory.table('rarity', {key={'full', 'long_lower'}, tbl=m_game.constants.item.rarity, rtrkey='full'}),
| |
| },
| |
| name = {
| |
| no_copy = true,
| |
| field = 'name',
| |
| type = 'String',
| |
| func = nil,
| |
| },
| |
| size_x = {
| |
| field = 'size_x',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('size_x'),
| |
| },
| |
| size_y = {
| |
| field = 'size_y',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('size_y'),
| |
| },
| |
| drop_enabled = {
| |
| no_copy = true,
| |
| field = 'drop_enabled',
| |
| type = 'Boolean',
| |
| func = m_util.cast.factory.boolean('drop_enabled'),
| |
| default = true,
| |
| },
| |
| drop_level = {
| |
| no_copy = true,
| |
| field = 'drop_level',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('drop_level'),
| |
| },
| |
| drop_level_maximum = {
| |
| no_copy = true,
| |
| field = 'drop_level_maximum',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('drop_level_maximum'),
| |
| },
| |
| drop_leagues = {
| |
| no_copy = true,
| |
| field = 'drop_leagues',
| |
| type = 'List (,) of String',
| |
| func = m_util.cast.factory.assoc_table('drop_leagues', {tbl=m_game.constants.leagues, errmsg=i18n.errors.invalid_league}),
| |
| },
| |
| drop_areas = {
| |
| no_copy = true,
| |
| field = 'drop_areas',
| |
| type = 'List (,) of String',
| |
| func = function(tpl_args, frame)
| |
| if tpl_args.drop_areas ~= nil then
| |
| tpl_args.drop_areas = m_util.string.split(tpl_args.drop_areas, ',%s*')
| |
| tpl_args.drop_areas_data = m_cargo.array_query{
| |
| tables={'areas'},
| |
| fields={'areas._pageName', 'areas.id', 'areas.name', 'areas.main_page'},
| |
| id_field='areas.id',
| |
| id_array=tpl_args.drop_areas,
| |
| query={limit=5000},
| |
| }
| |
| end
| |
|
| |
| -- find areas based on item tags for atlas bases
| |
| local query_data
| |
| for _, tag in ipairs(tpl_args.tags or {}) do
| |
| if string.match(tag, '%s*atlas%s*') ~= nil and tag ~= 'atlas_base_type' then
| |
| query_data = m_util.cargo.query(
| |
| {'areas', 'spawn_weights'},
| |
| {'areas._pageName', 'areas.id', 'areas.name', 'areas.main_page'},
| |
| {
| |
| join='areas._pageID=spawn_weights._pageID',
| |
| where=string.format('spawn_weights.tag = "%s" AND spawn_weights.weight > 0', tag),
| |
| groupBy='areas.id',
| |
| }
| |
| )
| |
| break
| |
| end
| |
| end
| |
|
| |
| if query_data ~= nil then
| |
| -- in case no manual drop areas have been set
| |
| if tpl_args.drop_areas == nil then
| |
| tpl_args.drop_areas = {}
| |
| tpl_args.drop_areas_data = {}
| |
| end
| |
| local drop_areas_assoc = {}
| |
| for _, id in ipairs(tpl_args.drop_areas) do
| |
| drop_areas_assoc[id] = true
| |
| end
| |
|
| |
| local duplicates = {}
| |
|
| |
| for _, row in ipairs(query_data) do
| |
| if drop_areas_assoc[row['areas.id']] == nil then
| |
| tpl_args.drop_areas[#tpl_args.drop_areas+1] = row['areas.id']
| |
| tpl_args.drop_areas_data[#tpl_args.drop_areas_data+1] = row
| |
| else
| |
| duplicates[#duplicates+1] = row['areas.id']
| |
| end
| |
| end
| |
|
| |
| if #duplicates > 0 then
| |
| tpl_args._errors[#tpl_args._errors+1] = string.format(i18n.errors.duplicate_area_id_from_query, table.concat(duplicates, ', '))
| |
| tpl_args._flags.duplicate_query_area_ids = true
| |
| end
| |
| end
| |
| end,
| |
| },
| |
| drop_text = {
| |
| no_copy = true,
| |
| field = 'drop_text',
| |
| type = 'Text',
| |
| func = core.factory.cast_text('drop_text'),
| |
| },
| |
| required_level = {
| |
| field = 'required_level_base',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('required_level'),
| |
| default = 1,
| |
| },
| |
| required_level_final = {
| |
| field = 'required_level',
| |
| type = 'Integer',
| |
| func = function(tpl_args, frame)
| |
| tpl_args.required_level_final = tpl_args.required_level
| |
| end,
| |
| default = 1,
| |
| },
| |
| required_dexterity = {
| |
| field = 'required_dexterity',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('required_dexterity'),
| |
| default = 0,
| |
| },
| |
| required_strength = {
| |
| field = 'required_strength',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('required_strength'),
| |
| default = 0,
| |
| },
| |
| required_intelligence = {
| |
| field = 'required_intelligence',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('required_intelligence'),
| |
| default = 0,
| |
| },
| |
| inventory_icon = {
| |
| no_copy = true,
| |
| field = 'inventory_icon',
| |
| type = 'String',
| |
| func = function(tpl_args, frame)
| |
| if tpl_args.class_id == 'DivinationCard' then
| |
| tpl_args.inventory_icon = tpl_args.inventory_icon or 'Divination card'
| |
| end
| |
| tpl_args.inventory_icon_id = tpl_args.inventory_icon or tpl_args.name
| |
| tpl_args.inventory_icon = string.format(i18n.inventory_icon, tpl_args.inventory_icon_id)
| |
| end,
| |
| },
| |
| -- note: this must be called after inventory item to work correctly as it depends on tpl_args.inventory_icon_id being set
| |
| alternate_art_inventory_icons = {
| |
| no_copy = true,
| |
| field = 'alternate_art_inventory_icons',
| |
| type = 'List (,) of String',
| |
| func = function(tpl_args, frame)
| |
| local icons = {}
| |
| if tpl_args.alternate_art_inventory_icons ~= nil then
| |
| local names = m_util.string.split(tpl_args.alternate_art_inventory_icons, ',%s*')
| |
|
| |
| for _, name in ipairs(names) do
| |
| icons[#icons+1] = string.format(i18n.inventory_icon, string.format('%s %s', tpl_args.inventory_icon_id, name))
| |
| end
| |
| end
| |
| tpl_args.alternate_art_inventory_icons = icons
| |
| end,
| |
| default = function () return {} end,
| |
| },
| |
| cannot_be_traded_or_modified = {
| |
| no_copy = true,
| |
| field = 'cannot_be_traded_or_modified',
| |
| type = 'Boolean',
| |
| func = m_util.cast.factory.boolean('cannot_be_traded_or_modified'),
| |
| default = false,
| |
| },
| |
| help_text = {
| |
| field = 'help_text',
| |
| type = 'Text',
| |
| func = core.factory.cast_text('help_text'),
| |
| },
| |
| flavour_text = {
| |
| no_copy = true,
| |
| field = 'flavour_text',
| |
| type = 'Text',
| |
| func = core.factory.cast_text('flavour_text'),
| |
| },
| |
| tags = {
| |
| field = 'tags',
| |
| type = 'List (,) of String',
| |
| func = m_util.cast.factory.assoc_table('tags', {
| |
| tbl = m_game.constants.tags,
| |
| errmsg = i18n.errors.invalid_tag,
| |
| }),
| |
| },
| |
| metadata_id = {
| |
| no_copy = true,
| |
| field = 'metadata_id',
| |
| type = 'String',
| |
| --type = 'String(unique; size=200)',
| |
| func = function(tpl_args, frame)
| |
| if tpl_args.metadata_id == nil then
| |
| return
| |
| end
| |
| local results = m_util.cargo.query(
| |
| {'items'},
| |
| {'items._pageName'},
| |
| {
| |
| where=string.format('items.metadata_id="%s" AND items._pageName != "%s"', tpl_args.metadata_id, mw.title.getCurrentTitle().fullText)
| |
| }
| |
| )
| |
| if #results > 0 and tpl_args.debug_id == nil and not tpl_args.debug then
| |
| error(string.format(i18n.errors.duplicate_metadata, tpl_args.metadata_id, results[1]['items._pageName']))
| |
| end
| |
| end,
| |
| },
| |
| is_corrupted = {
| |
| no_copy = true,
| |
| field = 'is_corrupted',
| |
| type = 'Boolean',
| |
| func = m_util.cast.factory.boolean('is_corrupted'),
| |
| default = false,
| |
| },
| |
| is_relic = {
| |
| no_copy = true,
| |
| field = 'is_relic',
| |
| type = 'Boolean',
| |
| func = function(tpl_args, frame)
| |
| m_util.cast.factory.boolean('is_relic')(tpl_args, frame)
| |
| if tpl_args.is_relic == true and tpl_args.rarity ~= 'Unique' then
| |
| error(i18n.errors.non_unique_relic)
| |
| end
| |
| end,
| |
| default = false,
| |
| },
| |
| is_prophecy = {
| |
| no_copy = true,
| |
| field = nil,
| |
| type = nil,
| |
| func = function(tpl_args, frame)
| |
| tpl_args._flags.is_prophecy = (tpl_args.metadata_id == 'Metadata/Items/Currency/CurrencyItemisedProphecy' or tpl_args.base_item == 'Prophecy' or tpl_args.base_item_page == 'Prophecy' or tpl_args.base_item_id == 'Metadata/Items/Currency/CurrencyItemisedProphecy')
| |
| end
| |
| },
| |
| purchase_costs = {
| |
| func = function(tpl_args, frame)
| |
| local purchase_costs = {}
| |
| for _, rarity_names in ipairs(m_game.constants.item.rarity) do
| |
| local rtbl = {}
| |
| local prefix = string.format('purchase_cost_%s', rarity_names.long_lower)
| |
| local i = 1
| |
| while i ~= -1 do
| |
| prefix = prefix .. i
| |
| local values = {
| |
| name = tpl_args[prefix .. '_name'],
| |
| amount = tonumber(tpl_args[prefix .. '_amount']),
| |
| rarity = rarity_names.long_upper,
| |
| }
| |
| if values.name ~= nil and values.amount ~= nil then
| |
| rtbl[#rtbl+1] = values
| |
| i = i + 1
| |
|
| |
| tpl_args._subobjects[#tpl_args._subobjects+1] = {
| |
| _table = 'item_purchase_costs',
| |
| amount = values.amount,
| |
| name = values.name,
| |
| rarity = values.rarity,
| |
| }
| |
| else
| |
| i = -1
| |
| end
| |
| end
| |
|
| |
| purchase_costs[rarity_names.long_lower] = rtbl
| |
| end
| |
|
| |
| tpl_args.purchase_costs = purchase_costs
| |
| end,
| |
| func_fetch = function(tpl_args, frame)
| |
| if tpl_args.rarity ~= 'Unique' then
| |
| return
| |
| end
| |
|
| |
| local results = m_util.cargo.query(
| |
| {'items' ,'item_purchase_costs'},
| |
| {'item_purchase_costs.amount', 'item_purchase_costs.name', 'item_purchase_costs.rarity'},
| |
| {
| |
| join = 'items._pageID=item_purchase_costs._pageID',
| |
| where = string.format('items._pageName="%s" AND item_purchase_costs.rarity="Unique"', tpl_args.base_item_page),
| |
| }
| |
| )
| |
|
| |
| for _, row in ipairs(results) do
| |
| local values = {
| |
| rarity = row['item_purchase_costs.rarity'],
| |
| name = row['item_purchase_costs.name'],
| |
| amount = tonumber(row['item_purchase_costs.amount']),
| |
| }
| |
| local datavar = tpl_args.purchase_costs[string.lower(values.rarity)]
| |
| datavar[#datavar+1] = values
| |
|
| |
| tpl_args._subobjects[#tpl_args._subobjects+1] = {
| |
| _table = 'item_purchase_costs',
| |
| amount = values.amount,
| |
| name = values.name,
| |
| rarity = values.rarity,
| |
| }
| |
| end
| |
| end,
| |
| },
| |
| sell_prices_override = {
| |
| no_copy = true,
| |
| func = function(tpl_args, frame)
| |
| -- these variables are also used by mods when setting automatic sell prices
| |
| tpl_args.sell_prices = {}
| |
| tpl_args.sell_price_order = {}
| |
|
| |
|
| |
| local name
| |
| local amount
| |
| local i = 0
| |
| repeat
| |
| i = i + 1
| |
| name = tpl_args[string.format('sell_price%s_name', i)]
| |
| amount = tpl_args[string.format('sell_price%s_amount', i)]
| |
|
| |
| if name ~= nil and amount ~= nil then
| |
| tpl_args.sell_price_order[#tpl_args.sell_price_order+1] = name
| |
| tpl_args.sell_prices[name] = amount
| |
| tpl_args._subobjects[#tpl_args._subobjects+1] = {
| |
| _table = 'item_sell_prices',
| |
| amount = amount,
| |
| name = name,
| |
| }
| |
| end
| |
| until name == nil or amount == nil
| |
|
| |
| -- if sell prices are set, the override is active
| |
| for _, _ in pairs(tpl_args.sell_prices) do
| |
| tpl_args._flags.sell_prices_override = true
| |
| break
| |
| end
| |
| end,
| |
| },
| |
| --
| |
| -- specific section
| |
| --
| |
|
| |
| -- Most item classes
| |
| quality = {
| |
| no_copy = true,
| |
| field = 'quality',
| |
| type = 'Integer',
| |
| -- Can be set manually, but default to Q20 for unique weapons/body armours
| |
| -- Also must copy to stat for the stat adjustments to work properly
| |
| func = function(tpl_args, frame)
| |
| local quality = tonumber(tpl_args.quality)
| |
| --
| |
| if quality == nil then
| |
| if tpl_args.rarity ~= 'Unique' then
| |
| quality = 0
| |
| elseif core.class_groups.weapons.keys[tpl_args.class_id] or core.class_groups.armor.keys[tpl_args.class_id] then
| |
| quality = 20
| |
| else
| |
| quality = 0
| |
| end
| |
| end
| |
|
| |
| tpl_args.quality = quality
| |
|
| |
| local stat = {
| |
| min = quality,
| |
| max = quality,
| |
| avg = quality,
| |
| }
| |
|
| |
| h.stats_update(tpl_args, 'quality', stat, nil, '_stats')
| |
|
| |
| if tpl_args.class_id == 'UtilityFlask' or tpl_args.class_id == 'UtilityFlaskCritical' then
| |
| h.stats_update(tpl_args, 'quality_flask_duration', stat, nil, '_stats')
| |
| -- quality is added to quantity for maps
| |
| elseif tpl_args.class_id == 'Map' then
| |
| h.stats_update(tpl_args, 'map_item_drop_quantity_+%', stat, nil, '_stats')
| |
| end
| |
| end,
| |
| },
| |
| -- amulets
| |
| is_talisman = {
| |
| field = 'is_talisman',
| |
| type = 'Boolean',
| |
| func = m_util.cast.factory.boolean('is_talisman'),
| |
| default = false,
| |
| },
| |
|
| |
| talisman_tier = {
| |
| field = 'talisman_tier',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('talisman_tier'),
| |
| },
| |
|
| |
| -- flasks
| |
| charges_max = {
| |
| field = 'charges_max',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('charges_max'),
| |
| },
| |
| charges_per_use = {
| |
| field = 'charges_per_use',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('charges_per_use'),
| |
| },
| |
| flask_mana = {
| |
| field = 'mana',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('flask_mana'),
| |
| },
| |
| flask_life = {
| |
| field = 'life',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('flask_life'),
| |
| },
| |
| flask_duration = {
| |
| field = 'duration',
| |
| type = 'Float',
| |
| func = m_util.cast.factory.number('flask_duration'),
| |
| },
| |
| buff_id = {
| |
| field = 'id',
| |
| type = 'String',
| |
| func = nil,
| |
| },
| |
| buff_values = {
| |
| field = 'buff_values',
| |
| type = 'List (,) of Integer',
| |
| func = function(tpl_args, frame)
| |
| local values = {}
| |
| local i = 0
| |
| repeat
| |
| i = i + 1
| |
| local key = 'buff_value' .. i
| |
| values[i] = tonumber(tpl_args[key])
| |
| tpl_args[key] = nil
| |
| until values[i] == nil
| |
|
| |
| -- needed so the values copyied from unique item base isn't overriden
| |
| if #values >= 1 then
| |
| tpl_args.buff_values = values
| |
| end
| |
| end,
| |
| func_copy = function(tpl_args, frame)
| |
| tpl_args.buff_values = m_util.string.split(tpl_args.buff_values, ',%s*')
| |
| end,
| |
| default = function () return {} end,
| |
| },
| |
| buff_stat_text = {
| |
| field = 'stat_text',
| |
| type = 'String',
| |
| func = nil,
| |
| },
| |
| buff_icon = {
| |
| field = 'icon',
| |
| type = 'String',
| |
| func = function(tpl_args, frame)
| |
| tpl_args.buff_icon = string.format(i18n.status_icon, tpl_args.name)
| |
| end,
| |
| },
| |
|
| |
| -- weapons
| |
| critical_strike_chance = {
| |
| field = 'critical_strike_chance',
| |
| type = 'Float',
| |
| func = m_util.cast.factory.number('critical_strike_chance'),
| |
| },
| |
| attack_speed = {
| |
| field = 'attack_speed',
| |
| type = 'Float',
| |
| func = m_util.cast.factory.number('attack_speed'),
| |
| },
| |
| weapon_range = {
| |
| field = 'weapon_range',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('weapon_range'),
| |
| },
| |
| physical_damage_min = {
| |
| field = 'physical_damage_min',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('physical_damage_min'),
| |
| },
| |
| physical_damage_max = {
| |
| field = 'physical_damage_max',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('physical_damage_max'),
| |
| },
| |
| fire_damage_min = {
| |
| field = 'fire_damage_min',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('fire_damage_min'),
| |
| default = 0,
| |
| },
| |
| fire_damage_max = {
| |
| field = 'fire_damage_max',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('fire_damage_max'),
| |
| default = 0,
| |
| },
| |
| cold_damage_min = {
| |
| field = 'cold_damage_min',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('cold_damage_min'),
| |
| default = 0,
| |
| },
| |
| cold_damage_max = {
| |
| field = 'cold_damage_max',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('cold_damage_max'),
| |
| default = 0,
| |
| },
| |
| lightning_damage_min = {
| |
| field = 'lightning_damage_min',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('lightning_damage_min'),
| |
| default = 0,
| |
| },
| |
| lightning_damage_max = {
| |
| field = 'lightning_damage_max',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('lightning_damage_max'),
| |
| default = 0,
| |
| },
| |
| chaos_damage_min = {
| |
| field = 'chaos_damage_min',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('chaos_damage_min'),
| |
| default = 0,
| |
| },
| |
| chaos_damage_max = {
| |
| field = 'chaos_damage_max',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('chaos_damage_max'),
| |
| default = 0,
| |
| },
| |
| -- armor-type stuff
| |
| armour = {
| |
| field = 'armour',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('armour'),
| |
| default = 0,
| |
| },
| |
| energy_shield = {
| |
| field = 'energy_shield',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('energy_shield'),
| |
| default = 0,
| |
| },
| |
| evasion = {
| |
| field = 'evasion',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('evasion'),
| |
| default = 0,
| |
| },
| |
| -- shields
| |
| block = {
| |
| field = 'block',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('block'),
| |
| },
| |
| -- skill gem stuff
| |
| gem_description = {
| |
| field = 'gem_description',
| |
| type = 'Text',
| |
| func = core.factory.cast_text('gem_description'),
| |
| },
| |
| dexterity_percent = {
| |
| field = 'dexterity_percent',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.percentage('dexterity_percent'),
| |
| },
| |
| strength_percent = {
| |
| field = 'strength_percent',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.percentage('strength_percent'),
| |
| },
| |
| intelligence_percent = {
| |
| field = 'intelligence_percent',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.percentage('intelligence_percent'),
| |
| },
| |
| primary_attribute = {
| |
| field = 'primary_attribute',
| |
| type = 'String',
| |
| func = function(tpl_args, frame)
| |
| for _, attr in ipairs(m_game.constants.attributes) do
| |
| local val = tpl_args[attr.long_lower .. '_percent']
| |
| if val and val >= 60 then
| |
| tpl_args['primary_attribute'] = attr.long_upper
| |
| return
| |
| end
| |
| end
| |
| tpl_args['primary_attribute'] = 'None'
| |
| end,
| |
| },
| |
| gem_tags = {
| |
| field = 'gem_tags',
| |
| type = 'List (,) of String',
| |
| -- TODO: default rework
| |
| func = m_util.cast.factory.array_table('gem_tags', {
| |
| tbl = m_game.constants.item.gem_tags,
| |
| errmsg = i18n.errors.invalid_tag,
| |
| }),
| |
| default = function () return {} end,
| |
| },
| |
| -- Support gems only
| |
| support_gem_letter = {
| |
| field = 'support_gem_letter',
| |
| type = 'String(size=1)',
| |
| func = nil,
| |
| },
| |
| support_gem_letter_html = {
| |
| field = 'support_gem_letter_html',
| |
| type = 'Text',
| |
| func = function(tpl_args, frame)
| |
| if tpl_args.support_gem_letter == nil then
| |
| return
| |
| end
| |
|
| |
| -- TODO replace this with a loop possibly
| |
| local css_map = {
| |
| strength = 'red',
| |
| intelligence = 'blue',
| |
| dexterity = 'green',
| |
| }
| |
| local id
| |
| for k, v in pairs(css_map) do
| |
| k = string.format('%s_percent', k)
| |
| if tpl_args[k] and tpl_args[k] > 50 then
| |
| id = v
| |
| break
| |
| end
| |
| end
| |
|
| |
| if id ~= nil then
| |
| local container = mw.html.create('span')
| |
| container
| |
| :attr('class', string.format('support-gem-id-%s', id))
| |
| :wikitext(tpl_args.support_gem_letter)
| |
| :done()
| |
| tpl_args.support_gem_letter_html = tostring(container)
| |
| end
| |
| end,
| |
| },
| |
| -- Maps
| |
| map_tier = {
| |
| field = 'tier',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('tier'),
| |
| },
| |
| map_guild_character = {
| |
| field = 'guild_character',
| |
| type = 'String(size=1)',
| |
| func = nil,
| |
| },
| |
| map_area_id = {
| |
| field = 'area_id',
| |
| type = 'String',
| |
| func = nil, -- TODO: Validate against a query?
| |
| },
| |
| map_area_level = {
| |
| field = 'area_level',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('map_area_level'),
| |
| },
| |
| unique_map_guild_character = {
| |
| field = 'unique_guild_character',
| |
| type = 'String(size=1)',
| |
| func_copy = function(tpl_args, frame)
| |
| tpl_args.map_guild_character = tpl_args.unique_map_guild_character
| |
| end,
| |
| func = nil,
| |
| },
| |
| unique_map_area_id = {
| |
| field = 'unique_area_id',
| |
| type = 'String',
| |
| func = nil, -- TODO: Validate against a query?
| |
| func_copy = function(tpl_args, frame)
| |
| tpl_args.map_area_id = tpl_args.unique_map_area_id
| |
| end,
| |
| },
| |
| unique_map_area_level = {
| |
| field = 'unique_area_level',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('unique_map_area_level'),
| |
| func_copy = function(tpl_args, frame)
| |
| tpl_args.map_area_level = tpl_args.unique_map_area_level
| |
| end,
| |
| },
| |
| --
| |
| -- Currency-like items
| |
| --
| |
| stack_size = {
| |
| field = 'stack_size',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('stack_size'),
| |
| },
| |
| stack_size_currency_tab = {
| |
| field = 'stack_size_currency_tab',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('stack_size_currency_tab'),
| |
| },
| |
| description = {
| |
| field = 'description',
| |
| type = 'Text',
| |
| func = core.factory.cast_text('description'),
| |
| },
| |
| cosmetic_type = {
| |
| field = 'cosmetic_type',
| |
| type = 'String',
| |
| func = core.factory.cast_text('cosmetic_type'),
| |
| },
| |
| -- for essences
| |
| is_essence = {
| |
| field = nil,
| |
| func = m_util.cast.factory.boolean('is_essence'),
| |
| default = false,
| |
| },
| |
| essence_level_restriction = {
| |
| field = 'level_restriction',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('essence_level_restriction'),
| |
| },
| |
| essence_level = {
| |
| field = 'level',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('essence_level'),
| |
| },
| |
| --
| |
| -- hideout doodads (HideoutDoodads.dat)
| |
| --
| |
| is_master_doodad = {
| |
| field = 'is_master_doodad',
| |
| type = 'Boolean',
| |
| func = m_util.cast.factory.boolean('is_master_doodad'),
| |
| },
| |
| master = {
| |
| field = 'master',
| |
| type = 'String',
| |
| -- todo validate against list of master names
| |
| func = m_util.cast.factory.table('master', {key='full', tbl=m_game.constants.masters}),
| |
| },
| |
| master_level_requirement = {
| |
| field = 'level_requirement',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('master_level_requirement'),
| |
| },
| |
| master_favour_cost = {
| |
| field = 'favour_cost',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('master_favour_cost'),
| |
| },
| |
| variation_count = {
| |
| field = 'variation_count',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('variation_count'),
| |
| },
| |
| -- Propehcy
| |
| prophecy_id = {
| |
| field = 'prophecy_id',
| |
| type = 'String',
| |
| func = nil,
| |
| },
| |
| prediction_text = {
| |
| field = 'prediction_text',
| |
| type = 'Text',
| |
| func = core.factory.cast_text('prediction_text'),
| |
| },
| |
| seal_cost = {
| |
| field = 'seal_cost',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('seal_cost'),
| |
| },
| |
| prophecy_reward = {
| |
| field = 'reward',
| |
| type = 'Text',
| |
| func = core.factory.cast_text('prophecy_reward'),
| |
| },
| |
| prophecy_objective = {
| |
| field = 'objective',
| |
| type = 'Text',
| |
| func = core.factory.cast_text('prophecy_objective'),
| |
| },
| |
| -- Divination cards
| |
| card_art = {
| |
| field = 'card_art',
| |
| type = 'Page',
| |
| func = function(tpl_args, frame)
| |
| tpl_args.card_art = string.format(i18n.divination_card_art, tpl_args.name)
| |
| end,
| |
| },
| |
| -- ------------------------------------------------------------------------
| |
| -- derived stats
| |
| -- ------------------------------------------------------------------------
| |
|
| |
| -- For rarity != normal, rarity already verified
| |
| base_item = {
| |
| no_copy = true,
| |
| field = 'base_item',
| |
| type = 'String',
| |
| func = function(tpl_args, frame)
| |
| tpl_args.base_item = tpl_args.base_item_data['items.name']
| |
| end,
| |
| },
| |
| base_item_id = {
| |
| no_copy = true,
| |
| field = 'base_item_id',
| |
| type = 'String',
| |
| func = function(tpl_args, frame)
| |
| tpl_args.base_item_id = tpl_args.base_item_data['items.metadata_id']
| |
| end,
| |
| },
| |
| base_item_page = {
| |
| no_copy = true,
| |
| field = 'base_item_page',
| |
| type = 'Page',
| |
| func = function(tpl_args, frame)
| |
| tpl_args.base_item_page = tpl_args.base_item_data['items._pageName']
| |
| end,
| |
| },
| |
| name_list = {
| |
| no_copy = true,
| |
| field = 'name_list',
| |
| type = 'List (�) of String',
| |
| func = function(tpl_args, frame)
| |
| if tpl_args.name_list ~= nil then
| |
| tpl_args.name_list = m_util.string.split(tpl_args.name_list, ',%s*')
| |
| tpl_args.name_list[#tpl_args.name_list+1] = tpl_args.name
| |
| else
| |
| tpl_args.name_list = {tpl_args.name}
| |
| end
| |
| end,
| |
| },
| |
| frame_type = {
| |
| no_copy = true,
| |
| field = 'frame_type',
| |
| type = 'String',
| |
| property = nil,
| |
| func = function(tpl_args, frame)
| |
| if tpl_args._flags.is_prophecy then
| |
| tpl_args.frame_type = 'prophecy'
| |
| return
| |
| end
| |
|
| |
| local var = core.class_specifics[tpl_args.class_id]
| |
| if var ~= nil and var.frame_type ~= nil then
| |
| tpl_args.frame_type = var.frame_type
| |
| return
| |
| end
| |
|
| |
| if tpl_args.is_relic then
| |
| tpl_args.frame_type = 'relic'
| |
| return
| |
| end
| |
|
| |
| tpl_args.frame_type = string.lower(tpl_args.rarity)
| |
| end,
| |
| },
| |
| --
| |
| -- args populated by mod validation
| |
| --
| |
| mods = {
| |
| default = function () return {} end,
| |
| func_fetch = function (tpl_args, frame)
| |
| local results = m_cargo.query(
| |
| {'items' ,'item_mods'},
| |
| {'item_mods.id', 'item_mods.is_implicit', 'item_mods.is_random', 'item_mods.text'},
| |
| {
| |
| join = 'items._pageID=item_mods._pageID',
| |
| where = string.format('items._pageName="%s" AND item_mods.is_implicit=1', tpl_args.base_item_page),
| |
| }
| |
| )
| |
| for _, row in ipairs(results) do
| |
| -- Handle text-only mods
| |
| local result
| |
| if row['item_mods.id'] == nil then
| |
| result = row['item_mods.text']
| |
| end
| |
| tpl_args._mods[#tpl_args._mods+1] = {
| |
| result=result,
| |
| id=row['item_mods.id'],
| |
| stat_text=row['item_mods.text'],
| |
| is_implicit=m_util.cast.boolean(row['item_mods.is_implicit']),
| |
| is_random=m_util.cast.boolean(row['item_mods.is_random']),
| |
| }
| |
| end
| |
| end,
| |
| },
| |
| physical_damage_html = {
| |
| no_copy = true,
| |
| field = 'physical_damage_html',
| |
| type = 'Text',
| |
| func = core.factory.damage_html{key='physical'},
| |
| },
| |
| fire_damage_html = {
| |
| no_copy = true,
| |
| field = 'fire_damage_html',
| |
| type = 'Text',
| |
| func = core.factory.damage_html{key='fire'},
| |
| },
| |
| cold_damage_html = {
| |
| no_copy = true,
| |
| field = 'cold_damage_html',
| |
| type = 'Text',
| |
| func = core.factory.damage_html{key='cold'},
| |
| },
| |
| lightning_damage_html = {
| |
| no_copy = true,
| |
| field = 'lightning_damage_html',
| |
| type = 'Text',
| |
| func = core.factory.damage_html{key='lightning'},
| |
| },
| |
| chaos_damage_html = {
| |
| no_copy = true,
| |
| field = 'chaos_damage_html',
| |
| type = 'Text',
| |
| func = core.factory.damage_html{key='chaos'},
| |
| },
| |
| damage_avg = {
| |
| no_copy = true,
| |
| field = 'damage_avg',
| |
| type = 'Text',
| |
| func = function(tpl_args, frame)
| |
| local dmg = {min=0, max=0}
| |
| for key, _ in pairs(dmg) do
| |
| for _, data in ipairs(m_game.constants.damage_types) do
| |
| dmg[key] = dmg[key] + tpl_args[string.format('%s_damage_%s_range_average', data.short_lower, key)]
| |
| end
| |
| end
| |
|
| |
| dmg = (dmg.min + dmg.max) / 2
| |
|
| |
| tpl_args.damage_avg = dmg
| |
| end,
| |
| },
| |
| damage_html = {
| |
| no_copy = true,
| |
| field = 'damage_html',
| |
| type = 'Text',
| |
| func = function(tpl_args, frame)
| |
| local text = {}
| |
| for _, data in ipairs(m_game.constants.damage_types) do
| |
| local value = tpl_args[data.short_lower .. '_damage_html']
| |
| if value ~= nil then
| |
| text[#text+1] = value
| |
| end
| |
| end
| |
| if #text > 0 then
| |
| tpl_args.damage_html = table.concat(text, '<br>')
| |
| end
| |
| end,
| |
| },
| |
| item_limit = {
| |
| no_copy = true,
| |
| field = 'item_limit',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('item_limit'),
| |
| },
| |
| jewel_radius_html = {
| |
| no_copy = true,
| |
| field = 'radius_html',
| |
| type = 'Text',
| |
| func = function(tpl_args, frame)
| |
| local radius = tpl_args._stats.local_jewel_effect_base_radius
| |
| if radius then
| |
| radius = radius.min
| |
| tpl_args.jewel_radius_html = string.format('%s (%i)', (m_game.constants.item.jewel_radius_to_size[radius] or '?'), radius)
| |
| end
| |
| end,
| |
| },
| |
| drop_areas_html = {
| |
| no_copy = true,
| |
| field = 'drop_areas_html',
| |
| type = 'Text',
| |
| func = function(tpl_args, frame)
| |
| if tpl_args.drop_areas_data == nil then
| |
| return
| |
| end
| |
|
| |
| if tpl_args.drop_areas_html ~= nil then
| |
| return
| |
| end
| |
|
| |
| local areas = {}
| |
| for _, data in pairs(tpl_args.drop_areas_data) do
| |
| -- skip legacy maps in the drop html listing
| |
| if not (string.match(data['areas.id'], '^MapAtlas.*') or string.match(data['areas.id'], '^Map2.*')) then
| |
| local page
| |
| if data['areas.main_page'] then
| |
| page = data['areas.main_page']
| |
| else
| |
| page = data['areas._pageName']
| |
| end
| |
| areas[#areas+1] = string.format('[[%s]]', page)
| |
| end
| |
| end
| |
|
| |
| tpl_args.drop_areas_html = table.concat(areas, ' • ')
| |
| end,
| |
| },
| |
| release_version = {
| |
| no_copy = true,
| |
| field = 'release_version',
| |
| type = 'String'
| |
| },
| |
| removal_version = {
| |
| no_copy = true,
| |
| field = 'removal_version',
| |
| type = 'String',
| |
| },
| |
| --
| |
| -- args governing use of the template itself
| |
| --
| |
| suppress_improper_modifiers_category = {
| |
| no_copy = true,
| |
| field = nil,
| |
| func = m_util.cast.factory.boolean('suppress_improper_modifiers_category'),
| |
| default = false,
| |
| },
| |
| }
| |
| | |
| core.stat_map = {
| |
| required_level_final = {
| |
| field = 'required_level',
| |
| stats_add = {
| |
| 'local_level_requirement_+',
| |
| },
| |
| stats_override = {
| |
| ['local_unique_tabula_rasa_no_requirement_or_energy_shield'] = {min=1, max=1},
| |
| },
| |
| minimum = 1,
| |
| html_fmt_options = {
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| weapon_range = {
| |
| field = 'weapon_range',
| |
| stats_add = {
| |
| 'local_weapon_range_+',
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| physical_damage_min = {
| |
| field = 'physical_damage_min',
| |
| stats_add = {
| |
| 'local_minimum_added_physical_damage',
| |
| },
| |
| stats_increased = {
| |
| 'local_physical_damage_+%',
| |
| 'quality',
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| physical_damage_max = {
| |
| field = 'physical_damage_max',
| |
| stats_add = {
| |
| 'local_maximum_added_physical_damage',
| |
| },
| |
| stats_increased = {
| |
| 'local_physical_damage_+%',
| |
| 'quality',
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| fire_damage_min = {
| |
| field = 'fire_damage_min',
| |
| stats_add = {
| |
| 'local_minimum_added_fire_damage',
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| color = 'fire',
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| fire_damage_max = {
| |
| field = 'fire_damage_max',
| |
| stats_add = {
| |
| 'local_maximum_added_fire_damage',
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| color = 'fire',
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| cold_damage_min = {
| |
| field = 'cold_damage_min',
| |
| stats_add = {
| |
| 'local_minimum_added_cold_damage',
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| color = 'cold',
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| cold_damage_max = {
| |
| field = 'cold_damage_max',
| |
| stats_add = {
| |
| 'local_maximum_added_cold_damage',
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| color = 'cold',
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| lightning_damage_min = {
| |
| field = 'lightning_damage_min',
| |
| stats_add = {
| |
| 'local_minimum_added_lightning_damage',
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| color = 'lightning',
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| lightning_damage_max = {
| |
| field = 'lightning_damage_max',
| |
| stats_add = {
| |
| 'local_maximum_added_lightning_damage',
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| color = 'lightning',
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| chaos_damage_min = {
| |
| field = 'chaos_damage_min',
| |
| stats_add = {
| |
| 'local_minimum_added_chaos_damage',
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| color = 'chaos',
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| chaos_damage_max = {
| |
| field = 'chaos_damage_max',
| |
| stats_add = {
| |
| 'local_maximum_added_chaos_damage',
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| color = 'chaos',
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| critical_strike_chance = {
| |
| field = 'critical_strike_chance',
| |
| stats_add = {
| |
| 'local_critical_strike_chance',
| |
| },
| |
| stats_increased = {
| |
| 'local_critical_strike_chance_+%',
| |
| },
| |
| stats_override = {
| |
| ['local_weapon_always_crit'] = {min=100, max=100},
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| fmt = '%.2f%%',
| |
| },
| |
| },
| |
| attack_speed = {
| |
| field = 'attack_speed',
| |
| stats_increased = {
| |
| 'local_attack_speed_+%',
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| fmt = '%.2f',
| |
| },
| |
| },
| |
| flask_life = {
| |
| field = 'life',
| |
| stats_add = {
| |
| 'local_flask_life_to_recover',
| |
| },
| |
| stats_increased = {
| |
| 'local_flask_life_to_recover_+%',
| |
| 'local_flask_amount_to_recover_+%',
| |
| 'quality',
| |
| },
| |
| html_fmt_options = {
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| flask_mana = {
| |
| field = 'mana',
| |
| stats_add = {
| |
| 'local_flask_mana_to_recover',
| |
| },
| |
| stats_increased = {
| |
| 'local_flask_mana_to_recover_+%',
| |
| 'local_flask_amount_to_recover_+%',
| |
| 'quality',
| |
| },
| |
| },
| |
| flask_duration = {
| |
| field = 'duration',
| |
| stats_increased = {
| |
| 'local_flask_duration_+%',
| |
| -- regular quality isn't used here because it doesn't increase duration of life/mana/hybrid flasks
| |
| 'quality_flask_duration',
| |
| },
| |
| stats_increased_inverse = {
| |
| 'local_flask_recovery_speed_+%',
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| fmt = '%.2f',
| |
| },
| |
| },
| |
| charges_per_use = {
| |
| field = 'charges_per_use',
| |
| stats_increased = {
| |
| 'local_charges_used_+%',
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| charges_max = {
| |
| field = 'charges_max',
| |
| stats_add = {
| |
| 'local_extra_max_charges',
| |
| },
| |
| stats_increased = {
| |
| 'local_max_charges_+%',
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| block = {
| |
| field = 'block',
| |
| stats_add = {
| |
| 'local_additional_block_chance_%',
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| fmt = '%i%%',
| |
| },
| |
| },
| |
| armour = {
| |
| field = 'armour',
| |
| stats_add = {
| |
| 'local_base_physical_damage_reduction_rating',
| |
| },
| |
| stats_increased = {
| |
| 'local_physical_damage_reduction_rating_+%',
| |
| 'local_armour_and_energy_shield_+%',
| |
| 'local_armour_and_evasion_+%',
| |
| 'local_armour_and_evasion_and_energy_shield_+%',
| |
| 'quality',
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| evasion = {
| |
| field = 'evasion',
| |
| stats_add = {
| |
| 'local_base_evasion_rating',
| |
| 'local_evasion_rating_and_energy_shield',
| |
| },
| |
| stats_increased = {
| |
| 'local_evasion_rating_+%',
| |
| 'local_evasion_and_energy_shield_+%',
| |
| 'local_armour_and_evasion_+%',
| |
| 'local_armour_and_evasion_and_energy_shield_+%',
| |
| 'quality',
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| energy_shield = {
| |
| field = 'energy_shield',
| |
| stats_add = {
| |
| 'local_energy_shield',
| |
| 'local_evasion_rating_and_energy_shield',
| |
| },
| |
| stats_increased = {
| |
| 'local_energy_shield_+%',
| |
| 'local_armour_and_energy_shield_+%',
| |
| 'local_evasion_and_energy_shield_+%',
| |
| 'local_armour_and_evasion_and_energy_shield_+%',
| |
| 'quality',
| |
| },
| |
| stats_override = {
| |
| ['local_unique_tabula_rasa_no_requirement_or_energy_shield'] = {min=0, max=0},
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| required_dexterity = {
| |
| field = 'required_dexterity',
| |
| stats_add = {
| |
| 'local_dexterity_requirement_+'
| |
| },
| |
| stats_increased = {
| |
| 'local_dexterity_requirement_+%',
| |
| 'local_attribute_requirements_+%',
| |
| },
| |
| stats_override = {
| |
| ['local_unique_tabula_rasa_no_requirement_or_energy_shield'] = {min=0, max=0},
| |
| ['local_no_attribute_requirements'] = {min=0, max=0},
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| required_intelligence = {
| |
| field = 'required_intelligence',
| |
| stats_add = {
| |
| 'local_intelligence_requirement_+'
| |
| },
| |
| stats_increased = {
| |
| 'local_intelligence_requirement_+%',
| |
| 'local_attribute_requirements_+%',
| |
| },
| |
| stats_override = {
| |
| ['local_unique_tabula_rasa_no_requirement_or_energy_shield'] = {min=0, max=0},
| |
| ['local_no_attribute_requirements'] = {min=0, max=0},
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| required_strength = {
| |
| field = 'required_strength',
| |
| stats_add = {
| |
| 'local_strength_requirement_+'
| |
| },
| |
| stats_increased = {
| |
| 'local_strength_requirement_+%',
| |
| 'local_attribute_requirements_+%',
| |
| },
| |
| stats_override = {
| |
| ['local_unique_tabula_rasa_no_requirement_or_energy_shield'] = {min=0, max=0},
| |
| ['local_no_attribute_requirements'] = {min=0, max=0},
| |
| },
| |
| minimum = 0,
| |
| html_fmt_options = {
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| map_area_level = {
| |
| field = 'map_area_level',
| |
| stats_override = {
| |
| ['map_item_level_override'] = true,
| |
| },
| |
| },
| |
| }
| |
| | |
| core.dps_map = {
| |
| {
| |
| name = 'physical_dps',
| |
| field = 'physical_dps',
| |
| damage_args = {'physical_damage', },
| |
| label_infobox = i18n.tooltips.physical_dps,
| |
| html_fmt_options = {
| |
| color = 'value',
| |
| fmt = '%.1f',
| |
| },
| |
| },
| |
| {
| |
| name = 'fire_dps',
| |
| field = 'fire_dps',
| |
| damage_args = {'fire_damage'},
| |
| label_infobox = i18n.tooltips.fire_dps,
| |
| html_fmt_options = {
| |
| color = 'fire',
| |
| fmt = '%.1f',
| |
| },
| |
| },
| |
| {
| |
| name = 'cold_dps',
| |
| field = 'cold_dps',
| |
| damage_args = {'cold_damage'},
| |
| label_infobox = i18n.tooltips.cold_dps,
| |
| html_fmt_options = {
| |
| color = 'cold',
| |
| fmt = '%.1f',
| |
| },
| |
| },
| |
| {
| |
| name = 'lightning_dps',
| |
| field = 'lightning_dps',
| |
| damage_args = {'lightning_damage'},
| |
| label_infobox = i18n.tooltips.lightning_dps,
| |
| html_fmt_options = {
| |
| color = 'lightning',
| |
| fmt = '%.1f',
| |
| },
| |
| },
| |
| {
| |
| name = 'chaos_dps',
| |
| field = 'chaos_dps',
| |
| damage_args = {'chaos_damage'},
| |
| label_infobox = i18n.tooltips.chaos_dps,
| |
| html_fmt_options = {
| |
| color = 'chaos',
| |
| fmt = '%.1f',
| |
| },
| |
| },
| |
| {
| |
| name = 'elemental_dps',
| |
| field = 'elemental_dps',
| |
| damage_args = {'fire_damage', 'cold_damage', 'lightning_damage'},
| |
| label_infobox = i18n.tooltips.elemental_dps,
| |
| html_fmt_options = {
| |
| color = 'value',
| |
| fmt = '%.1f',
| |
| },
| |
| },
| |
| {
| |
| name = 'poison_dps',
| |
| field = 'poison_dps',
| |
| damage_args = {'physical_damage', 'chaos_damage'},
| |
| label_infobox = i18n.tooltips.poison_dps,
| |
| html_fmt_options = {
| |
| color = 'value',
| |
| fmt = '%.1f',
| |
| },
| |
| },
| |
| {
| |
| name = 'dps',
| |
| field = 'dps',
| |
| damage_args = {'physical_damage', 'fire_damage', 'cold_damage', 'lightning_damage', 'chaos_damage'},
| |
| label_infobox = i18n.tooltips.dps,
| |
| html_fmt_options = {
| |
| color = 'value',
| |
| fmt = '%.1f',
| |
| },
| |
| },
| |
| }
| |
| | |
| core.cargo = {}
| |
| core.cargo.items = {
| |
| table = 'items',
| |
| fields = {
| |
| html = core.map.html,
| |
| implicit_stat_text = core.map.implicit_stat_text,
| |
| explicit_stat_text = core.map.explicit_stat_text,
| |
| stat_text = core.map.stat_text,
| |
| class = core.map.class,
| |
| class_id = core.map.class_id,
| |
| rarity = core.map.rarity,
| |
| name = core.map.name,
| |
| size_x = core.map.size_x,
| |
| size_y = core.map.size_y,
| |
| drop_enabled = core.map.drop_enabled,
| |
| drop_level = core.map.drop_level,
| |
| drop_level_maximum = core.map.drop_level_maximum,
| |
| drop_leagues = core.map.drop_leagues,
| |
| drop_areas = core.map.drop_areas,
| |
| drop_areas_html = core.map.drop_areas_html,
| |
| drop_text = core.map.drop_text,
| |
| required_level = core.map.required_level,
| |
| required_level_final = core.map.required_level_final,
| |
| required_dexterity = core.map.required_dexterity,
| |
| required_strength = core.map.required_strength,
| |
| required_intelligence = core.map.required_intelligence,
| |
| inventory_icon = core.map.inventory_icon,
| |
| alternate_art_inventory_icons = core.map.alternate_art_inventory_icons,
| |
| buff_icon = core.map.buff_icon,
| |
| cannot_be_traded_or_modified = core.map.cannot_be_traded_or_modified,
| |
| help_text = core.map.help_text,
| |
| flavour_text = core.map.flavour_text,
| |
| tags = core.map.tags,
| |
| metadata_id = core.map.metadata_id,
| |
| is_corrupted = core.map.is_corrupted,
| |
| is_relic = core.map.is_relic,
| |
| quality = core.map.quality,
| |
| base_item = core.map.base_item,
| |
| base_item_id = core.map.base_item_id,
| |
| base_item_page = core.map.base_item_page,
| |
| frame_type = core.map.frame_type,
| |
| name_list = core.map.name_list,
| |
| description = core.map.description,
| |
| release_version = core.map.release_version,
| |
| removal_version = core.map.removal_version,
| |
| },
| |
| }
| |
| | |
| core.cargo.item_sell_prices = {
| |
| table = 'item_sell_prices',
| |
| fields = {
| |
| amount = {
| |
| field = 'amount',
| |
| type = 'Integer',
| |
| },
| |
| name = {
| |
| field = 'name',
| |
| type = 'String',
| |
| },
| |
| },
| |
| }
| |
| | |
| | |
| core.cargo.item_purchase_costs = {
| |
| table = 'item_purchase_costs',
| |
| fields = {
| |
| amount = {
| |
| field = 'amount',
| |
| type = 'Integer',
| |
| },
| |
| name = {
| |
| field = 'name',
| |
| type = 'String',
| |
| },
| |
| rarity = {
| |
| field = 'rarity',
| |
| type = 'String',
| |
| },
| |
| },
| |
| }
| |
| | |
| core.cargo.item_mods = {
| |
| table = 'item_mods',
| |
| fields = {
| |
| id = {
| |
| field = 'id',
| |
| type = 'String',
| |
| },
| |
| stat_text = {
| |
| field = 'text',
| |
| type = 'Text',
| |
| },
| |
| is_implicit = {
| |
| field = 'is_implicit',
| |
| type = 'Boolean',
| |
| },
| |
| is_random = {
| |
| field = 'is_random',
| |
| type = 'Boolean',
| |
| },
| |
| },
| |
| }
| |
| | |
| core.cargo.item_stats = {
| |
| table = 'item_stats',
| |
| fields = {
| |
| id = {
| |
| field = 'id',
| |
| type = 'String',
| |
| },
| |
| min = {
| |
| field = 'min',
| |
| type = 'Integer',
| |
| },
| |
| max = {
| |
| field = 'max',
| |
| type = 'Integer',
| |
| },
| |
| avg = {
| |
| field = 'avg',
| |
| type = 'Integer',
| |
| },
| |
| is_implicit = {
| |
| field = 'is_implicit',
| |
| type = 'Boolean',
| |
| },
| |
| is_random = {
| |
| field = 'is_random',
| |
| type = 'Boolean',
| |
| },
| |
| },
| |
| }
| |
| | |
| -- There probably will be a table named "buffs" in the future, so "item_buffs" is the best solution here
| |
| core.cargo.item_buffs = {
| |
| table = 'item_buffs',
| |
| fields = {
| |
| id = core.map.buff_id,
| |
| buff_values = core.map.buff_values,
| |
| stat_text = core.map.buff_stat_text,
| |
| icon = core.map.buff_icon,
| |
| },
| |
| }
| |
| | |
| core.cargo.upgraded_from_sets = {
| |
| table = 'upgraded_from_sets',
| |
| fields = {
| |
| set_id = {
| |
| field = 'set_id',
| |
| type = 'Integer',
| |
| },
| |
| text = {
| |
| field = 'text',
| |
| type = 'Text',
| |
| },
| |
| }
| |
| }
| |
| | |
| core.cargo.upgraded_from_groups = {
| |
| table = 'upgraded_from_groups',
| |
| fields = {
| |
| group_id = {
| |
| field = 'group_id',
| |
| type = 'Integer',
| |
| },
| |
| set_id = {
| |
| field = 'set_id',
| |
| type = 'Integer',
| |
| },
| |
| item_id = {
| |
| field = 'item_id',
| |
| type = 'String',
| |
| },
| |
| item_name = {
| |
| field = 'item_name',
| |
| type = 'String',
| |
| },
| |
| item_page = {
| |
| field = 'item_page',
| |
| type = 'Page',
| |
| },
| |
| integer = {
| |
| field = 'amount',
| |
| type = 'Integer',
| |
| },
| |
| notes = {
| |
| field = 'notes',
| |
| type = 'Text',
| |
| },
| |
| }
| |
| }
| |
| | |
| core.cargo.amulets = {
| |
| table = 'amulets',
| |
| fields = {
| |
| is_talisman = core.map.is_talisman,
| |
| talisman_tier = core.map.talisman_tier,
| |
| },
| |
| }
| |
| | |
| core.cargo.flasks = {
| |
| table = 'flasks',
| |
| fields = {
| |
| -- All flasks
| |
| duration = core.map.flask_duration,
| |
| charges_max = core.map.charges_max,
| |
| charges_per_use = core.map.charges_per_use,
| |
| -- Life/Mana/Hybrid flasks
| |
| life = core.map.flask_life,
| |
| mana = core.map.flask_mana,
| |
| },
| |
| }
| |
| | |
| core.cargo.weapons = {
| |
| table = 'weapons',
| |
| fields = {
| |
| critical_strike_chance = core.map.critical_strike_chance,
| |
| attack_speed = core.map.attack_speed,
| |
| weapon_range = core.map.weapon_range,
| |
| physical_damage_min = core.map.physical_damage_min,
| |
| physical_damage_max = core.map.physical_damage_max,
| |
| physical_damage_html = core.map.physical_damage_html,
| |
| fire_damage_html = core.map.fire_damage_html,
| |
| cold_damage_html = core.map.cold_damage_html,
| |
| lightning_damage_html = core.map.lightning_damage_html,
| |
| chaos_damage_html = core.map.chaos_damage_html,
| |
| damage_avg = core.map.damage_avg,
| |
| damage_html = core.map.damage_html,
| |
|
| |
| -- Values added via stat population
| |
| fire_damage_min = core.map.fire_damage_min,
| |
| fire_damage_max = core.map.fire_damage_max,
| |
| cold_damage_min = core.map.cold_damage_min,
| |
| cold_damage_max = core.map.cold_damage_max,
| |
| lightning_damage_min = core.map.lightning_damage_min,
| |
| lightning_damage_max = core.map.lightning_damage_max,
| |
| chaos_damage_min = core.map.chaos_damage_min,
| |
| chaos_damage_max = core.map.chaos_damage_max,
| |
| },
| |
| }
| |
| | |
| core.cargo.armours = {
| |
| table = 'armours',
| |
| fields = {
| |
| armour = core.map.armour,
| |
| energy_shield = core.map.energy_shield,
| |
| evasion = core.map.evasion,
| |
| },
| |
| }
| |
| | |
| core.cargo.shields = {
| |
| table = 'shields',
| |
| fields = {
| |
| block = core.map.block,
| |
| }
| |
| }
| |
| | |
| core.cargo.skill_gems = {
| |
| table = 'skill_gems',
| |
| fields = {
| |
| gem_description = core.map.gem_description,
| |
| dexterity_percent = core.map.dexterity_percent,
| |
| strength_percent = core.map.strength_percent,
| |
| intelligence_percent = core.map.intelligence_percent,
| |
| primary_attribute = core.map.primary_attribute,
| |
| gem_tags = core.map.gem_tags,
| |
| -- Support Skill Gems
| |
| support_gem_letter = core.map.support_gem_letter,
| |
| support_gem_letter_html = core.map.support_gem_letter_html,
| |
| },
| |
| }
| |
| | |
| core.cargo.maps = {
| |
| table = 'maps',
| |
| fields = {
| |
| tier = core.map.map_tier,
| |
| guild_character = core.map.map_guild_character,
| |
| unique_guild_character = core.map.unique_map_guild_character,
| |
| area_id = core.map.map_area_id,
| |
| unique_area_id = core.map.unique_map_area_id,
| |
|
| |
| -- REMOVE?
| |
| area_level = core.map.map_area_level,
| |
| unique_area_level = core.map.unique_map_area_level,
| |
| },
| |
| }
| |
| | |
| core.cargo.stackables = {
| |
| table = 'stackables',
| |
| fields = {
| |
| stack_size = core.map.stack_size,
| |
| stack_size_currency_tab = core.map.stack_size_currency_tab,
| |
| cosmetic_type = core.map.cosmetic_type,
| |
| },
| |
| }
| |
| | |
| core.cargo.essences = {
| |
| table = 'essences',
| |
| fields = {
| |
| level_restriction = core.map.essence_level_restriction,
| |
| level = core.map.essence_level,
| |
| },
| |
| }
| |
| | |
| core.cargo.hideout_doodads = {
| |
| table = 'hideout_doodads',
| |
| fields = {
| |
| is_master_doodad = core.map.is_master_doodad,
| |
| master = core.map.master,
| |
| master_level_requirement = core.map.master_level_requirement,
| |
| master_favour_cost = core.map.master_favour_cost,
| |
| variation_count = core.map.variation_count,
| |
| },
| |
| }
| |
| | |
| core.cargo.prophecies = {
| |
| table = 'prophecies',
| |
| fields = {
| |
| prophecy_id = core.map.prophecy_id,
| |
| prediction_text = core.map.prediction_text,
| |
| seal_cost = core.map.seal_cost,
| |
| objective = core.map.prophecy_objective,
| |
| reward = core.map.prophecy_reward,
| |
| },
| |
| }
| |
| | |
| core.cargo.divination_cards = {
| |
| table = 'divination_cards',
| |
| fields = {
| |
| card_art = core.map.card_art,
| |
| },
| |
| }
| |
| | |
| core.cargo.jewels = {
| |
| table = 'jewels',
| |
| fields = {
| |
| item_limit = core.map.item_limit,
| |
| radius_html = core.map.jewel_radius_html,
| |
| },
| |
| }
| |
| | |
| -- TODO: Second pass for i18n item classes
| |
| -- base item is default, but will be validated later
| |
| -- Notes:
| |
| -- inventory_icon must always be before alternate_art_inventory_icons
| |
| -- drop_areas after tags
| |
| -- is_relic after rarity
| |
| core.default_args = {
| |
| 'rarity', 'name', 'name_list', 'size_x', 'size_y',
| |
| 'drop_enabled', 'drop_level', 'drop_level_maximum', 'drop_leagues', 'drop_text', 'required_level', 'required_level_final',
| |
| 'inventory_icon', 'alternate_art_inventory_icons', 'flavour_text',
| |
| 'cannot_be_traded_or_modified', 'help_text', 'tags', 'metadata_id', 'is_corrupted', 'is_relic', 'purchase_costs', 'sell_prices_override', 'mods',
| |
| 'drop_areas', 'drop_areas_html',
| |
|
| |
| 'suppress_improper_modifiers_category',
| |
| 'is_prophecy',
| |
| 'class',
| |
| }
| |
| -- frame_type is needed in stat_text
| |
| core.late_args = {'frame_type', 'implicit_stat_text', 'explicit_stat_text', 'stat_text'}
| |
| core.prophecy_args = {'prophecy_id', 'prediction_text', 'seal_cost', 'prophecy_objective', 'prophecy_reward'}
| |
| core.tables = {'items'}
| |
| core.class_groups = {
| |
| flasks = {
| |
| tables = {'flasks'},
| |
| keys = {['LifeFlask'] = true, ['ManaFlask'] = true, ['HybridFlask'] = true, ['UtilityFlask'] = true, ['UtilityFlaskCritical'] = true},
| |
| args = {'quality', 'flask_duration', 'charges_max', 'charges_per_use'},
| |
| },
| |
| weapons = {
| |
| tables = {'weapons'},
| |
| keys = {['Claw'] = true, ['Dagger'] = true, ['Wand'] = true, ['One Hand Sword'] = true, ['Thrusting One Hand Sword'] = true, ['One Hand Axe'] = true, ['One Hand Mace'] = true, ['Bow'] = true, ['Staff'] = true, ['Two Hand Sword'] = true, ['Two Hand Axe'] = true, ['Two Hand Mace'] = true, ['Sceptre'] = true, ['FishingRod'] = true},
| |
| args = {'quality', 'required_dexterity', 'required_intelligence', 'required_strength', 'critical_strike_chance', 'attack_speed', 'physical_damage_min', 'physical_damage_max', 'lightning_damage_min', 'lightning_damage_max', 'cold_damage_min', 'cold_damage_max', 'fire_damage_min', 'fire_damage_max', 'chaos_damage_min', 'chaos_damage_max', 'weapon_range'},
| |
| late_args = {'physical_damage_html', 'fire_damage_html', 'cold_damage_html', 'lightning_damage_html', 'chaos_damage_html', 'damage_avg', 'damage_html'},
| |
| },
| |
| gems = {
| |
| tables = {'skill_gems'},
| |
| keys = {['Active Skill Gem'] = true, ['Support Skill Gem'] = true},
| |
| args = {'dexterity_percent', 'strength_percent', 'intelligence_percent', 'primary_attribute', 'gem_tags'},
| |
| },
| |
| armor = {
| |
| tables = {'armours'},
| |
| keys = {['Gloves'] = true, ['Boots'] = true, ['Body Armour'] = true, ['Helmet'] = true, ['Shield'] = true},
| |
| args = {'quality', 'required_dexterity', 'required_intelligence', 'required_strength', 'armour', 'energy_shield', 'evasion'},
| |
| },
| |
| stackable = {
| |
| tables = {'stackables'},
| |
| keys = {['Currency'] = true, ['StackableCurrency'] = true, ['HideoutDoodad'] = true, ['Microtransaction'] = true, ['DivinationCard'] = true, ['DelveSocketableCurrency'] = true},
| |
| args = {'stack_size', 'stack_size_currency_tab', 'description', 'cosmetic_type'},
| |
| },
| |
| }
| |
| | |
| core.class_specifics = {
| |
| ['Amulet'] = {
| |
| tables = {'amulets'},
| |
| args = {'is_talisman', 'talisman_tier'},
| |
| },
| |
| ['LifeFlask'] = {
| |
| args = {'flask_life'},
| |
| },
| |
| ['ManaFlask'] = {
| |
| args = {'flask_mana'},
| |
| },
| |
| ['HybridFlask'] = {
| |
| args = {'flask_life', 'flask_mana'},
| |
| },
| |
| ['UtilityFlask'] = {
| |
| tables = {'item_buffs'},
| |
| args = {'buff_id', 'buff_values', 'buff_stat_text', 'buff_icon'},
| |
| },
| |
| ['UtilityFlaskCritical'] = {
| |
| tables = {'item_buffs'},
| |
| args = {'buff_id', 'buff_values', 'buff_stat_text', 'buff_icon'},
| |
| },
| |
| ['Active Skill Gem'] = {
| |
| defaults = {
| |
| help_text = i18n.help_text_defaults.active_gem,
| |
| size_x = 1,
| |
| size_y = 1,
| |
| },
| |
| frame_type = 'gem',
| |
| },
| |
| ['Support Skill Gem'] = {
| |
| args = {'support_gem_letter', 'support_gem_letter_html'},
| |
| defaults = {
| |
| help_text = i18n.help_text_defaults.support_gem,
| |
| size_x = 1,
| |
| size_y = 1,
| |
| },
| |
| frame_type = 'gem',
| |
| },
| |
| ['Shield'] = {
| |
| tables = {'shields'},
| |
| args = {'block'},
| |
| },
| |
| ['Map'] = {
| |
| tables = {'maps'},
| |
| args = {'quality', 'map_tier', 'map_guild_character', 'map_area_id', 'map_area_level', 'unique_map_area_id', 'unique_map_area_level', 'unique_map_guild_character'},
| |
| skip_stat_lines = i18n.stat_skip_patterns.maps,
| |
| },
| |
| ['Currency'] = {
| |
| frame_type = 'currency',
| |
| },
| |
| ['StackableCurrency'] = {
| |
| tables = {'essences', 'prophecies'},
| |
| args = {'is_essence', 'essence_level_restriction', 'essence_level'},
| |
| frame_type = 'currency',
| |
| },
| |
| ['Microtransaction'] = {
| |
| frame_type = 'currency',
| |
| },
| |
| ['HideoutDoodad'] = {
| |
| tables = {'hideout_doodads'},
| |
| args = {'is_master_doodad', 'master', 'master_level_requirement', 'master_favour_cost', 'variation_count'},
| |
| defaults = {
| |
| help_text = i18n.help_text_defaults.hideout_doodad,
| |
| },
| |
| frame_type = 'currency',
| |
| },
| |
| ['Jewel'] = {
| |
| tables = {'jewels'},
| |
| late_args = {'item_limit', 'jewel_radius_html'},
| |
| defaults = {
| |
| help_text = i18n.help_text_defaults.jewel,
| |
| },
| |
| skip_stat_lines = i18n.stat_skip_patterns.jewels,
| |
| },
| |
| ['AbyssJewel'] = {
| |
| tables = {'jewels'},
| |
| late_args = {'item_limit', 'jewel_radius_html'},
| |
| skip_stat_lines = i18n.stat_skip_patterns.jewels,
| |
| },
| |
| ['QuestItem'] = {
| |
| args = {'description'},
| |
| frame_type = 'quest',
| |
| },
| |
| ['DivinationCard'] = {
| |
| tables = {'divination_cards'},
| |
| args = {'card_art',},
| |
| frame_type = 'divicard',
| |
| },
| |
| ['LabyrinthItem'] = {
| |
| frame_type = 'currency',
| |
| },
| |
| ['LabyrinthTrinket'] = {
| |
| tables = {'item_buffs'},
| |
| args = {'description', 'buff_icon'},
| |
| frame_type = 'currency',
| |
| },
| |
| ['PantheonSoul'] = {
| |
| defaults = {
| |
| cannot_be_traded_or_modified = true,
| |
| },
| |
| },
| |
| ['IncursionItem'] = {
| |
| frame_type = 'currency',
| |
| },
| |
| }
| |
| | |
| -- add defaults from class specifics and class groups
| |
| core.item_classes = {}
| |
| core.item_classes_extend = {'tables', 'args', 'late_args'}
| |
| function core.build_item_classes(tpl_args, frame)
| |
| core.map.class.func(tpl_args, frame)
| |
|
| |
| -- Skip building for anything but the specified class.
| |
|
| |
| for id, data in pairs(m_game.constants.item.classes) do
| |
| if id == tpl_args.class_id then
| |
| core.item_classes[id] = {
| |
| tables = xtable:new(),
| |
| args = xtable:new(),
| |
| late_args = xtable:new(),
| |
| defaults = {},
| |
| }
| |
|
| |
| core.item_classes[id].tables:insertT(core.tables)
| |
| break
| |
| end
| |
| end
| |
| | |
| for _, row in pairs(core.class_groups) do
| |
| for class, _ in pairs(row.keys) do
| |
| if class == tpl_args.class_id then
| |
| for _, k in ipairs(core.item_classes_extend) do
| |
| if row[k] ~= nil then
| |
| core.item_classes[class][k]:insertT(row[k])
| |
| end
| |
| end
| |
| break
| |
| end
| |
| end
| |
| end
| |
| | |
| local class_specifics = core.class_specifics[tpl_args.class_id]
| |
| if class_specifics then
| |
| for _, k in ipairs(core.item_classes_extend) do
| |
| if class_specifics[k] ~= nil then
| |
| core.item_classes[tpl_args.class_id][k]:insertT(class_specifics[k])
| |
| end
| |
| end
| |
| if class_specifics.defaults ~= nil then
| |
| for key, value in pairs(class_specifics.defaults) do
| |
| core.item_classes[tpl_args.class_id].defaults[key] = value
| |
| end
| |
| end
| |
| end
| |
| end
| |
| | |
| -- GroupTable -> RowTable -> formatter function
| |
| --
| |
| --
| |
| | |
| --
| |
| -- Contents here are meant to resemble the ingame infobox of items
| |
| --
| |
| core.item_display_groups = {
| |
| -- Tags, stats, level, etc
| |
| -- group
| |
| -- group[n].args -
| |
| -- group[n].func -
| |
| -- group[n].inline - if set to false, don't add to html for the inline infobox, but still show this field on the item page
| |
| {
| |
| {
| |
| args = {'cosmetic_type'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'cosmetic_type',
| |
| fmt = '%s',
| |
| color = 'default'
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = function(tpl_args, frame)
| |
| if tpl_args.class_id == nil then
| |
| return false
| |
| end
| |
|
| |
| return core.class_groups.weapons.keys[tpl_args.class_id] ~= nil
| |
| end,
| |
| func = function(tpl_args, frame)
| |
| local v = i18n.tooltips.item_class_map[tpl_args.class_id]
| |
| return m_util.html.format_value(tpl_args, frame, {min=v, max=v}, {color = 'default'})
| |
| end,
| |
| },
| |
| {
| |
| args = {'gem_tags'},
| |
| func = function(tpl_args, frame)
| |
| local out = {}
| |
| for i, tag in ipairs(tpl_args.gem_tags) do
| |
| out[#out+1] = string.format(i18n.gem_tag_category, tag, tag)
| |
| end
| |
|
| |
| return table.concat(out, ', ')
| |
| end,
| |
| },
| |
| {
| |
| args = {'support_gem_letter_html'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'support_gem_letter_html',
| |
| inline = i18n.tooltips.support_icon,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = {'radius'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'radius',
| |
| inline = i18n.tooltips.radius,
| |
| func = core.factory.descriptor_value{key='radius_description'},
| |
| },
| |
| [2] = {
| |
| key = 'radius_secondary',
| |
| inline = ' / %s',
| |
| func = core.factory.descriptor_value{key='radius_secondary_description'},
| |
| },
| |
| [3] = {
| |
| key = 'radius_tertiary',
| |
| inline = ' / %s',
| |
| func = core.factory.descriptor_value{key='radius_tertiary_description'},
| |
| },
| |
| },
| |
| },
| |
| },
| |
| -- TODO: gem level here. Maybe put max level here?
| |
| {
| |
| args = nil,
| |
| func = core.factory.display_value{
| |
| type='gem',
| |
| options = {
| |
| [1] = {
| |
| key = 'mana_cost',
| |
| hide_default = 100,
| |
| fmt = function (tpl_args, frame)
| |
| if tpl_args.has_percentage_mana_cost then
| |
| return '%i%%'
| |
| else
| |
| return '%i'
| |
| end
| |
| end,
| |
| inline = function (tpl_args, frame)
| |
| if tpl_args.has_reservation_mana_cost then
| |
| return i18n.tooltips.mana_reserved
| |
| else
| |
| return i18n.tooltips.mana_cost
| |
| end
| |
| end,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = nil,
| |
| func = core.factory.display_value{
| |
| type='gem',
| |
| options = {
| |
| [1] = {
| |
| key = 'mana_multiplier',
| |
| hide_default = 100,
| |
| fmt = '%i%%',
| |
| inline = i18n.tooltips.mana_multiplier,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| -- TODO: i18n
| |
| {
| |
| args = nil,
| |
| func = core.factory.display_value{
| |
| type='gem',
| |
| options = {
| |
| [1] = {
| |
| key = 'vaal_souls_requirement',
| |
| hide_default = 0,
| |
| fmt = '%i (N) / ',
| |
| inline = i18n.tooltips.vaal_souls_per_use,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = nil,
| |
| func = core.factory.display_value{
| |
| type='gem',
| |
| options = {
| |
| [1] = {
| |
| key = 'vaal_stored_uses',
| |
| hide_default = 0,
| |
| fmt = '%i',
| |
| inline = i18n.tooltips.stored_uses,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = nil,
| |
| func = core.factory.display_value{
| |
| type='gem',
| |
| options = {
| |
| [1] = {
| |
| key = 'stored_uses',
| |
| hide_default = 0,
| |
| fmt = '%i',
| |
| inline = i18n.tooltips.stored_uses,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = nil,
| |
| func = core.factory.display_value{
| |
| type='gem',
| |
| options = {
| |
| [1] = {
| |
| key = 'vaal_soul_gain_prevention_time',
| |
| hide_default = 0,
| |
| -- Technically it rounds to nearest, but it is given in milliseconds in the data,
| |
| fmt = '%.3f sec',
| |
| inline = i18n.tooltips.vaal_soul_gain_prevention_time,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = nil,
| |
| func = core.factory.display_value{
| |
| type='gem',
| |
| options = {
| |
| [1] = {
| |
| key = 'cooldown',
| |
| hide_default = 0,
| |
| fmt = '%.2f sec',
| |
| inline = i18n.tooltips.cooldown_time,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = {'cast_time'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'cast_time',
| |
| hide_default = 0,
| |
| fmt = '%.2f sec',
| |
| inline = i18n.tooltips.cast_time,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = nil,
| |
| func = core.factory.display_value{
| |
| type='gem',
| |
| options = {
| |
| [1] = {
| |
| key = 'critical_strike_chance',
| |
| hide_default = 0,
| |
| fmt = '%.2f%%',
| |
| inline = i18n.tooltips.critical_strike_chance,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = nil,
| |
| func = core.factory.display_value{
| |
| type='gem',
| |
| options = {
| |
| [1] = {
| |
| key = 'damage_effectiveness',
| |
| hide_default = 100,
| |
| fmt = '%i%%',
| |
| inline = i18n.tooltips.damage_effectiveness,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = {'projectile_speed'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'projectile_speed',
| |
| inline = i18n.tooltips.projectile_speed,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| -- Quality is before item stats, but after gem stuff and item class
| |
| {
| |
| args = {'quality'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'quality',
| |
| fmt = '+%i%%',
| |
| color = 'mod',
| |
| inline = i18n.tooltips.quality,
| |
| hide_default = 0,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| -- Weapon only
| |
| {
| |
| args = {'physical_damage_html'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'physical_damage_html',
| |
| fmt = '%s',
| |
| inline = i18n.tooltips.physical_damage,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = nil,
| |
| func = function(tpl_args, frame)
| |
| local text = ''
| |
| for _, dtype in ipairs({'fire_damage_html', 'cold_damage_html', 'lightning_damage_html'}) do
| |
| local value = tpl_args[dtype]
| |
| if value ~= nil then
| |
| text = text .. ' ' .. value
| |
| end
| |
| end
| |
|
| |
| if text ~= '' then
| |
| return string.format(i18n.tooltips.elemental_damage, text)
| |
| else
| |
| return
| |
| end
| |
| end,
| |
| },
| |
| {
| |
| args = {'chaos_damage_html'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'chaos_damage_html',
| |
| fmt = '%s',
| |
| inline = i18n.tooltips.chaos_damage,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = {'critical_strike_chance_html'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'critical_strike_chance_html',
| |
| fmt = '%s',
| |
| inline = i18n.tooltips.critical_strike_chance,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = {'attack_speed_html'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'attack_speed_html',
| |
| fmt = '%s',
| |
| inline = i18n.tooltips.attacks_per_second,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = {'weapon_range_html'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'weapon_range_html',
| |
| fmt = '%s',
| |
| inline = i18n.tooltips.weapon_range,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| -- Map only
| |
| {
| |
| args = {'map_area_level'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'map_area_level',
| |
| fmt = '%i',
| |
| inline = i18n.tooltips.map_level,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = {'map_tier'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'map_tier',
| |
| fmt = '%i',
| |
| inline = i18n.tooltips.map_tier,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = function(tpl_args, frame)
| |
| return tpl_args.map_guild_character ~= nil and tpl_args.rarity == 'Normal'
| |
| end,
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'map_guild_character',
| |
| fmt = '%s',
| |
| inline = i18n.tooltips.map_guild_character,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = function(tpl_args, frame)
| |
| return tpl_args.unique_map_guild_character ~= nil and tpl_args.rarity == 'Unique'
| |
| end,
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'unique_map_guild_character',
| |
| fmt = '%s',
| |
| inline = i18n.tooltips.map_guild_character,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = nil,
| |
| func = core.factory.display_value{
| |
| type = 'stat',
| |
| options = {
| |
| [1] = {
| |
| key = 'map_item_drop_quantity_+%',
| |
| fmt = '+%i%%',
| |
| color = 'mod',
| |
| inline = i18n.tooltips.item_quantity,
| |
| hide_default = 0,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = nil,
| |
| func = core.factory.display_value{
| |
| type = 'stat',
| |
| options = {
| |
| [1] = {
| |
| key = 'map_item_drop_rarity_+%',
| |
| fmt = '+%i%%',
| |
| color = 'mod',
| |
| inline = i18n.tooltips.item_rarity,
| |
| hide_default = 0,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = nil,
| |
| func = core.factory.display_value{
| |
| type = 'stat',
| |
| options = {
| |
| [1] = {
| |
| key = 'map_pack_size_+%',
| |
| fmt = '+%i%%',
| |
| color = 'mod',
| |
| inline = i18n.tooltips.monster_pack_size,
| |
| hide_default = 0,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| -- Jewel Only
| |
| {
| |
| args = nil,
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'item_limit',
| |
| fmt = '%i',
| |
| inline = i18n.tooltips.limited_to,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = {'jewel_radius_html'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'jewel_radius_html',
| |
| fmt = '%s',
| |
| inline = i18n.tooltips.radius,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| -- Flask only
| |
| {
| |
| args = {'flask_mana_html', 'flask_duration_html'},
| |
| --func = core.factory.display_flask('flask_mana'),
| |
| func = core.factory.display_value{
| |
| inline = i18n.tooltips.flask_mana_recovery,
| |
| options = {
| |
| [1] = {
| |
| key = 'flask_mana_html',
| |
| fmt = '%s',
| |
| },
| |
| [2] = {
| |
| key = 'flask_duration_html',
| |
| fmt = '%s',
| |
| },
| |
| }
| |
| },
| |
| },
| |
| {
| |
| args = {'flask_life_html', 'flask_duration_html'},
| |
| func = core.factory.display_value{
| |
| inline = i18n.tooltips.flask_life_recovery,
| |
| options = {
| |
| [1] = {
| |
| key = 'flask_life_html',
| |
| fmt = '%s',
| |
| },
| |
| [2] = {
| |
| key = 'flask_duration_html',
| |
| fmt = '%s',
| |
| },
| |
| }
| |
| },
| |
| },
| |
| {
| |
| -- don't display for mana/life flasks
| |
| args = function(tpl_args, frame)
| |
| for _, k in ipairs({'flask_life_html', 'flask_mana_html'}) do
| |
| if tpl_args[k] ~= nil then
| |
| return false
| |
| end
| |
| end
| |
|
| |
| return tpl_args['flask_duration_html'] ~= nil
| |
| end,
| |
| func = core.factory.display_value{
| |
| inline = i18n.tooltips.flask_duration,
| |
| options = {
| |
| [1] = {
| |
| key = 'flask_duration_html',
| |
| fmt = '%s',
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = {'charges_per_use_html', 'charges_max_html'},
| |
| func = core.factory.display_value{
| |
| inline = i18n.tooltips.flask_charges_per_use,
| |
| options = {
| |
| [1] = {
| |
| key = 'charges_per_use_html',
| |
| fmt = '%s',
| |
| },
| |
| [2] = {
| |
| key = 'charges_max_html',
| |
| fmt = '%s',
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = {'buff_stat_text'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'buff_stat_text',
| |
| color = 'mod',
| |
| },
| |
| },
| |
| },
| |
| },
| |
| -- armor
| |
| {
| |
| args = {'block_html'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'block_html',
| |
| inline = i18n.tooltips.chance_to_block,
| |
| fmt = '%s',
| |
| hide_default = 0,
| |
| hide_default_key = 'block',
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = {'armour_html'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'armour_html',
| |
| inline = i18n.tooltips.armour,
| |
| fmt = '%s',
| |
| hide_default = 0,
| |
| hide_default_key = 'armour',
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = {'evasion_html'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'evasion_html',
| |
| inline = i18n.tooltips.evasion,
| |
| fmt = '%s',
| |
| hide_default = 0,
| |
| hide_default_key = 'evasion',
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = {'energy_shield_html'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'energy_shield_html',
| |
| inline = i18n.tooltips.energy_shield,
| |
| fmt = '%s',
| |
| hide_default = 0,
| |
| hide_default_key = 'energy_shield',
| |
| },
| |
| },
| |
| },
| |
| },
| |
| -- Amulet only
| |
| {
| |
| args = {'talisman_tier'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'talisman_tier',
| |
| fmt = '%i',
| |
| inline = i18n.tooltips.talisman_tier,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| -- Misc
| |
| {
| |
| args = {'stack_size'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'stack_size',
| |
| hide_default = 1,
| |
| fmt = '%i',
| |
| inline = i18n.tooltips.stack_size,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| -- Essence stuff
| |
| {
| |
| args = {'essence_level'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'essence_level',
| |
| fmt = '%i',
| |
| inline = i18n.tooltips.essence_level,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| },
| |
| -- Requirements
| |
| {
| |
| -- TODO: i18n Master name?
| |
| {
| |
| args = {'master', 'master_level_requirement'},
| |
| func = function(tpl_args, frame)
| |
| -- masters have been validated before
| |
| local data
| |
| for i, rowdata in ipairs(m_game.constants.masters) do
| |
| if tpl_args.master == rowdata.full then
| |
| data = rowdata
| |
| break
| |
| end
| |
| end
| |
|
| |
| return m_util.html.poe_color('default', i18n.tooltips.requires, string.format('[[%s|%s %s]]', data.full, data.short_upper, tpl_args.master_level_requirement))
| |
| end
| |
| },
| |
| -- Instead of item level, show drop level if any
| |
| {
| |
| args = nil,
| |
| func = function(tpl_args, frame)
| |
| local opt = {
| |
| [1] = {
| |
| key = 'required_level_final_html',
| |
| hide_default = 1,
| |
| hide_default_key = 'required_level_final',
| |
| inline = i18n.tooltips.level_inline,
| |
| inline_color = false,
| |
| },
| |
| }
| |
|
| |
| for _, attr in ipairs(m_game.constants.attributes) do
| |
| opt[#opt+1] = {
| |
| key = string.format('required_%s_html', attr['long_lower']),
| |
| hide_default = 0,
| |
| hide_default_key = string.format('required_%s', attr['long_lower']),
| |
| inline = ', %s ' .. attr['short_upper'],
| |
| inline_color = false,
| |
| }
| |
| end
| |
|
| |
| local requirements = core.factory.display_value{options = opt}(tpl_args, frame)
| |
|
| |
| -- return early
| |
| if requirements == nil then
| |
| return
| |
| end
| |
|
| |
| requirements = string.gsub(requirements, '^, ', '')
| |
|
| |
| return m_util.html.poe_color('default', string.format(i18n.tooltips.requires, requirements))
| |
| end,
| |
| },
| |
| },
| |
| -- Gem description
| |
| {
| |
| css_class = 'tc -gemdesc',
| |
| {
| |
| args = {'gem_description'},
| |
| func = core.factory.display_value_only('gem_description'),
| |
| },
| |
| },
| |
| -- Gem Quality Stats
| |
| {
| |
| css_class = 'tc -mod',
| |
| {
| |
| args = {'quality_stat_text'},
| |
| func = function(tpl_args, frame)
| |
| lines = {}
| |
| lines[#lines+1] = m_util.html.poe_color('default', i18n.tooltips.gem_quality)
| |
| lines[#lines+1] = tpl_args.quality_stat_text
| |
|
| |
| return table.concat(lines, '<br>')
| |
| end,
| |
| },
| |
| },
| |
| -- Gem Implicit Stats
| |
| {
| |
| css_class = 'tc -mod',
| |
| {
| |
| args = function(tpl_args, frame)
| |
| return core.class_groups.gems.keys[tpl_args.class_id] and tpl_args.stat_text
| |
| end,
| |
| func = function(tpl_args, frame)
| |
| lines = {}
| |
| lines[#lines+1] = tpl_args.stat_text
| |
| if tpl_args.gem_tags:contains('Vaal') then
| |
| lines[#lines+1] = m_util.html.poe_color('corrupted', i18n.tooltips.corrupted)
| |
| end
| |
| return table.concat(lines, '<br>')
| |
| end,
| |
| },
| |
| },
| |
| -- Implicit Stats
| |
| {
| |
| css_class = 'tc -mod',
| |
| func = function(tpl_args, frame, container_type)
| |
| if tpl_args.implicit_stat_text then
| |
| return {core.display.strip_random_stats(tpl_args, frame, tpl_args.implicit_stat_text, container_type)}
| |
| else
| |
| return {}
| |
| end
| |
| end,
| |
| },
| |
| -- Stats
| |
| {
| |
| css_class = 'tc -mod',
| |
| func = function(tpl_args, frame, container_type)
| |
| if tpl_args.explicit_stat_text then
| |
| return {core.display.strip_random_stats(tpl_args, frame, tpl_args.explicit_stat_text, container_type)}
| |
| else
| |
| return {}
| |
| end
| |
| end,
| |
| },
| |
| -- Experience
| |
| --[[{
| |
| {
| |
| args = {'experience'},
| |
| func = core.factory.display_value{
| |
| key = 'experience',
| |
| options = {
| |
| [1] = {
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| },
| |
| },
| |
| },]]--
| |
| -- Description (currency, doodads)
| |
| {
| |
| css_class = 'tc -mod',
| |
| {
| |
| args = {'description'},
| |
| func = core.factory.display_value_only('description'),
| |
| },
| |
| },
| |
| -- Variations (for doodads)
| |
| {
| |
| css_class = 'tc -mod',
| |
| {
| |
| args = {'variation_count'},
| |
| func = function(tpl_args, frame)
| |
| local txt
| |
| if tpl_args.variation_count == 1 then
| |
| txt = i18n.tooltips.variation_singular
| |
| else
| |
| txt = i18n.tooltips.variation_plural
| |
| end
| |
| return string.format('%i %s', tpl_args.variation_count, txt)
| |
| end,
| |
| },
| |
| },
| |
| -- Flavour Text
| |
| {
| |
| css_class = 'tc -flavour',
| |
| {
| |
| args = {'flavour_text'},
| |
| func = core.factory.display_value_only('flavour_text'),
| |
| },
| |
| },
| |
| -- Prophecy text
| |
| {
| |
| css_class = 'tc -value',
| |
| {
| |
| args = {'prediction_text'},
| |
| func = core.factory.display_value_only('prediction_text'),
| |
| },
| |
| },
| |
| -- Can not be traded or modified
| |
| {
| |
| css_class = 'tc -canttradeormodify',
| |
| {
| |
| args = {'cannot_be_traded_or_modified'},
| |
| func = function(tpl_args, frame)
| |
| if tpl_args.cannot_be_traded_or_modified == true then
| |
| return i18n.tooltips.cannot_be_traded_or_modified
| |
| end
| |
| end,
| |
| },
| |
| },
| |
| -- Help text
| |
| {
| |
| css_class = 'tc -help',
| |
| {
| |
| args = {'help_text'},
| |
| func = core.factory.display_value_only('help_text'),
| |
| --inline = false,
| |
| },
| |
| },
| |
| -- Cost (i.e. vendor costs)
| |
| {
| |
| --css_class = '',
| |
| {
| |
| args = {'master_favour_cost'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'master_favour_cost',
| |
| inline = i18n.tooltips.favour_cost,
| |
| color = 'currency',
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = {'seal_cost'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'seal_cost',
| |
| fmt = '%dx ',
| |
| color = 'currency',
| |
| inline = function (tpl_args, frame)
| |
| return i18n.tooltips.seal_cost .. f_item_link{item_name_exact='Silver Coin', html=''}
| |
| end,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| },
| |
| }
| |
| | |
| --
| |
| -- This is meant to show additional information about the item in a separate infobox
| |
| --
| |
| core.extra_display_groups = {
| |
| -- Drop info
| |
| {
| |
| header = i18n.tooltips.drop_restrictions,
| |
| css_class = '',
| |
| {
| |
| args = {'drop_enabled'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'drop_level',
| |
| fmt = '%i',
| |
| inline = i18n.tooltips.level,
| |
| },
| |
| [2] = {
| |
| key = 'drop_level_maximum',
| |
| hide_default = 100,
| |
| fmt = '%i',
| |
| inline = ' / %s',
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = {'drop_leagues'},
| |
| func = function(tpl_args, frame)
| |
| return string.format(i18n.tooltips.league_restriction, m_util.html.poe_color('value', table.concat(tpl_args.drop_leagues, ', ')))
| |
| end
| |
| },
| |
| {
| |
| args = {'drop_areas_html'},
| |
| func = core.factory.display_value_only('drop_areas_html'),
| |
| },
| |
| {
| |
| args = {'drop_text'},
| |
| func = core.factory.display_value_only('drop_text'),
| |
| },
| |
| {
| |
| args = function(tpl_args, frame)
| |
| if tpl_args.drop_enabled == true then
| |
| return false
| |
| end
| |
| return true
| |
| end,
| |
| func = function(tpl_args, frame)
| |
| local span = mw.html.create('span')
| |
| span
| |
| :attr('class', 'infobox-disabled-drop')
| |
| :wikitext(i18n.tooltips.drop_disabled)
| |
| :done()
| |
| return tostring(span)
| |
| end,
| |
| },
| |
| },
| |
| {
| |
| header = i18n.tooltips.purchase_costs,
| |
| {
| |
| args = function(tpl_args, frame)
| |
| for rarity, data in pairs(tpl_args.purchase_costs) do
| |
| if #data > 0 then
| |
| return true
| |
| end
| |
| end
| |
| return false
| |
| end,
| |
| func = function(tpl_args, frame)
| |
| local tbl = mw.html.create('table')
| |
| tbl
| |
| --:attr('class', 'wikitable')
| |
| :attr('style', 'width: 100%; margin-top: 0px;')
| |
|
| |
| for _, rarity_names in ipairs(m_game.constants.item.rarity) do
| |
| local data = tpl_args.purchase_costs[rarity_names.long_lower]
| |
| if #data > 0 then
| |
| local tr = tbl:tag('tr')
| |
| tr
| |
| :tag('td')
| |
| :wikitext(rarity_names.long_upper)
| |
| local td = tr:tag('td')
| |
| for _, purchase_data in ipairs(data) do
| |
| td:wikitext(string.format('%dx [[%s]]<br />', purchase_data.amount, purchase_data.name))
| |
| end
| |
| end
| |
| end
| |
|
| |
| return tostring(tbl)
| |
| end,
| |
| },
| |
| },
| |
| {
| |
| header = i18n.tooltips.sell_price,
| |
| {
| |
| args = {'sell_price_order'},
| |
| func = function(tpl_args, frame)
| |
| local out = {}
| |
| for _, item_name in ipairs(tpl_args.sell_price_order) do
| |
| out[#out+1] = string.format('%dx [[%s]]', tpl_args.sell_prices[item_name], item_name)
| |
| end
| |
|
| |
| return table.concat(out, '<br />')
| |
| end,
| |
| },
| |
| },
| |
| -- Damage per second
| |
| {
| |
| header = i18n.tooltips.damage_per_second,
| |
| -- Autoinsert here from dps map
| |
| },
| |
| {
| |
| header = i18n.tooltips.misc,
| |
| {
| |
| args = {'class'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'class',
| |
| fmt = '%s',
| |
| inline = i18n.tooltips.item_class,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| args = {'metadata_id'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'metadata_id',
| |
| fmt = '%s',
| |
| inline = i18n.tooltips.metadata_id,
| |
| truncate = true,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| },
| |
| }
| |
| | |
| for i, data in ipairs(core.dps_map) do
| |
| table.insert(core.extra_display_groups[4], {
| |
| args = {data.name .. '_html'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = data.name .. '_html',
| |
| inline = data.label_infobox .. ': %s',
| |
| fmt = '%s',
| |
| -- the html already contains the colour
| |
| no_color = true,
| |
| },
| |
| },
| |
| },
| |
| })
| |
| if i == 5 then
| |
| table.insert(core.extra_display_groups[4], {
| |
| args = function (tpl_args, frame)
| |
| return tpl_args.elemental_dps_html ~= nil or tpl_args.poison_dps_html ~= nil
| |
| end,
| |
| func = function (tpl_args, frame)
| |
| return ''
| |
| end,
| |
| })
| |
| elseif i == 7 then
| |
| table.insert(core.extra_display_groups[4], {
| |
| args = {'dps_html'},
| |
| func = function (tpl_args, frame)
| |
| return ''
| |
| end,
| |
| })
| |
| end
| |
| end
| |
| | |
| -- ----------------------------------------------------------------------------
| |
| -- Tables
| |
| -- ----------------------------------------------------------------------------
| |
| | |
| function cargo_declare(data)
| |
| return function(frame)
| |
| local tpl_args = getArgs(frame, {
| |
| parentFirst = true
| |
| })
| |
| frame = m_util.misc.get_frame(frame)
| |
|
| |
| local dcl_args = {}
| |
| dcl_args._table = data.table
| |
| for k, field_data in pairs(data.fields) do
| |
| if field_data.field then
| |
| dcl_args[field_data.field] = field_data.type
| |
| for _, stat_data in pairs(core.stat_map) do
| |
| if stat_data.field == k then
| |
| for _, range_fields in ipairs(h.range_fields) do
| |
| -- if the type is nil, use the parent type
| |
| -- so this is set integer/float values correctly
| |
| dcl_args[stat_data.field .. range_fields.field] = range_fields.type or field_data.type
| |
| end
| |
| break
| |
| end
| |
| end
| |
| end
| |
| end
| |
|
| |
| if dcl_args._table == 'weapons' then
| |
| for _, dps_data in ipairs(core.dps_map) do
| |
| for _, range_fields in ipairs(h.range_fields) do
| |
| -- since there is no parent, the default is float
| |
| dcl_args[dps_data.field .. range_fields.field] = range_fields.type or 'Float'
| |
| end
| |
| end
| |
| end
| |
| if tpl_args.debug then
| |
| mw.logObject(dcl_args)
| |
| end
| |
| return m_util.cargo.declare(frame, dcl_args)
| |
| end
| |
| end
| |
| | |
| p.table_items = cargo_declare(core.cargo.items)
| |
| p.table_item_sell_prices = cargo_declare(core.cargo.item_sell_prices)
| |
| p.table_item_purchase_costs = cargo_declare(core.cargo.item_purchase_costs)
| |
| p.table_item_mods = cargo_declare(core.cargo.item_mods)
| |
| p.table_item_stats = cargo_declare(core.cargo.item_stats)
| |
| p.table_item_buffs = cargo_declare(core.cargo.item_buffs)
| |
| p.table_upgraded_from_sets = cargo_declare(core.cargo.upgraded_from_sets)
| |
| p.table_upgraded_from_groups = cargo_declare(core.cargo.upgraded_from_groups)
| |
| p.table_amulets = cargo_declare(core.cargo.amulets)
| |
| p.table_flasks = cargo_declare(core.cargo.flasks)
| |
| p.table_weapons = cargo_declare(core.cargo.weapons)
| |
| p.table_armours = cargo_declare(core.cargo.armours)
| |
| p.table_shields = cargo_declare(core.cargo.shields)
| |
| p.table_skill_gems = cargo_declare(core.cargo.skill_gems)
| |
| p.table_maps = cargo_declare(core.cargo.maps)
| |
| p.table_stackables = cargo_declare(core.cargo.stackables)
| |
| p.table_essences = cargo_declare(core.cargo.essences)
| |
| p.table_hideout_doodads = cargo_declare(core.cargo.hideout_doodads)
| |
| p.table_prophecies = cargo_declare(core.cargo.prophecies)
| |
| p.table_divination_cards = cargo_declare(core.cargo.divination_cards)
| |
| p.table_jewels = cargo_declare(core.cargo.jewels)
| |
| | |
| -- ----------------------------------------------------------------------------
| |
| -- Page views
| |
| -- ----------------------------------------------------------------------------
| |
| | |
| --
| |
| -- Template:Item
| |
| --
| |
| | |
| function p.itembox (frame)
| |
| --
| |
| -- Args/Frame
| |
| --
| |
| local t = os.clock()
| |
|
| |
| local tpl_args = getArgs(frame, {
| |
| parentFirst = true
| |
| })
| |
| frame = m_util.misc.get_frame(frame)
| |
|
| |
| --
| |
| -- Shared args
| |
| --
| |
|
| |
| tpl_args._flags = {}
| |
| tpl_args._base_item_args = {}
| |
| tpl_args._mods = {}
| |
| for _, k in ipairs({'', '_random'}) do
| |
| for _, prefix in ipairs({'', '_implicit', '_explicit'}) do
| |
| tpl_args[k .. prefix .. '_stats'] = {}
| |
| end
| |
| end
| |
| tpl_args._subobjects = {}
| |
| tpl_args._properties = {}
| |
| tpl_args._errors = {}
| |
|
| |
| core.process_arguments(tpl_args, frame, {array={'class_id'}})
| |
| core.build_item_classes(tpl_args, frame)
| |
| core.build_cargo_data(tpl_args, frame)
| |
| -- TODO: Found out wtf is going on. Need to call this twice to fix
| |
| core.build_cargo_data(tpl_args, frame)
| |
|
| |
| -- Using general purpose function to handle release and removal versions
| |
| m_util.args.version(tpl_args, {frame=frame, set_properties=true})
| |
|
| |
| -- Must validate some argument early. It is required for future things
| |
| core.process_arguments(tpl_args, frame, {array=core.default_args})
| |
| core.process_arguments(tpl_args, frame, {array=core.item_classes[tpl_args.class_id].args})
| |
|
| |
| -- Base Item
| |
| | |
| core.process_base_item(tpl_args, frame)
| |
|
| |
| -- Prophecy special snowflake
| |
| if tpl_args._flags.is_prophecy then
| |
| err = core.process_arguments(tpl_args, frame, {array=core.prophecy_args})
| |
| if err then
| |
| return err
| |
| end
| |
|
| |
| tpl_args.inventory_icon = string.format(i18n.inventory_icon, 'Prophecy')
| |
| end
| |
|
| |
| -- Mods
| |
| | |
| for _, k in ipairs({'implicit', 'explicit'}) do
| |
| local success = true
| |
| local i = 1
| |
| while success do
| |
| success = core.validate_mod(tpl_args, frame, {key=k, i=i})
| |
| i = i + 1
| |
| end
| |
| end
| |
|
| |
| core.process_smw_mods(tpl_args, frame)
| |
|
| |
| -- Add stats - this is for when mods are not set, but we still need stats to calcuate new armour values etc
| |
| m_util.args.stats(tpl_args, {prefix='extra_'})
| |
| for _, stat in ipairs(tpl_args.extra_stats) do
| |
| if stat.value ~= nil then
| |
| stat.min = stat.value
| |
| stat.max = stat.value
| |
| stat.avg = stat.value
| |
| end
| |
| h.stats_update(tpl_args, stat.id, stat, nil, '_stats')
| |
| h.stats_update(tpl_args, stat.id, stat, nil, '_explicit_stats')
| |
| end
| |
| | |
| -- Transpose stats into cargo data
| |
| for _, random_prefix in ipairs({'', '_random'}) do
| |
| for _, type_prefix in ipairs({'', '_implicit', '_explicit'}) do
| |
| for id, data in pairs(tpl_args[random_prefix .. type_prefix .. '_stats']) do
| |
| local is_implicit
| |
| if type_prefix == '_implicit' then
| |
| is_implicit = true
| |
| elseif type_prefix == '_explicit' then
| |
| is_implicit = false
| |
| end
| |
| tpl_args._subobjects[#tpl_args._subobjects+1] = {
| |
| _table = 'item_stats',
| |
| id = id,
| |
| min = data.min,
| |
| max = data.max,
| |
| avg = data.avg,
| |
| is_implicit = is_implicit,
| |
| is_random = random_prefix == '_random',
| |
| }
| |
| end
| |
| end
| |
| end
| |
|
| |
| -- Handle extra stats (for gems)
| |
|
| |
| if core.class_groups.gems.keys[tpl_args.class_id] then
| |
| m_skill.skill(frame, tpl_args)
| |
| end
| |
|
| |
| --
| |
| -- Handle local stats increases/reductions/additions
| |
| --
| |
|
| |
| local skip = {}
| |
|
| |
| -- general stats
| |
| for k, data in pairs(core.stat_map) do
| |
| local value = tpl_args[k]
| |
|
| |
| if value ~= nil and skip[k] == nil then
| |
| value = {min=value, max=value, base=value}
| |
| -- If stats are overriden we scan save some CPU time here
| |
| local overridden = false
| |
| if data.stats_override ~= nil then
| |
| for stat_id, override_value in pairs(data.stats_override) do
| |
| local stat_value = tpl_args._stats[stat_id]
| |
| if stat_value ~= nil then
| |
| -- Use the value of stat
| |
| if override_value == true then
| |
| value.min = stat_value.min
| |
| value.max = stat_value.max
| |
| overridden = true
| |
| elseif stat_value ~= 0 then
| |
| value.min = override_value.min
| |
| value.max = override_value.max
| |
| overridden = true
| |
| end
| |
| end
| |
| end
| |
| end
| |
|
| |
| if overridden == false then
| |
| -- The simple cases; this must be using ipairs as "add" must apply before
| |
| for _, operator in ipairs({'add', 'more'}) do
| |
| local st = data['stats_' .. operator]
| |
| if st ~= nil then
| |
| for _, statid in ipairs(st) do
| |
| if tpl_args._stats[statid] ~= nil then
| |
| h.stat[operator](value, tpl_args._stats[statid])
| |
| end
| |
| end
| |
| end
| |
| end
| |
|
| |
| -- For increased stats we need to add them up first
| |
| for stat_key, stat_func in pairs({increased=h.stat.more, increased_inverse=h.stat.more_inverse}) do
| |
| local st = data['stats_' .. stat_key]
| |
| if st ~= nil then
| |
| local total_increase = {min=0, max=0}
| |
| for _, statid in ipairs(st) do
| |
| if tpl_args._stats[statid] ~= nil then
| |
| for var, current_value in pairs(total_increase) do
| |
| total_increase[var] = current_value + tpl_args._stats[statid][var]
| |
| end
| |
| end
| |
| end
| |
| stat_func(value, total_increase)
| |
| end
| |
| end
| |
|
| |
| if data.minimum ~= nil then
| |
| for _, key in ipairs({'min', 'max'}) do
| |
| if value[key] < data.minimum then
| |
| value[key] = data.minimum
| |
| end
| |
| end
| |
| end
| |
| else
| |
| | |
| end
| |
|
| |
| value.avg = (value.min + value.max) / 2
| |
|
| |
| -- don't add the properties unless we need to
| |
| if (data.default ~= nil and (value.min ~= data.default or value.max ~= data.default)) or data.default == nil then
| |
| for short_key, range_data in pairs(h.range_map) do
| |
| tpl_args[data.field .. range_data.var] = value[short_key]
| |
| end
| |
|
| |
| -- process to HTML to use on list pages or other purposes
| |
| h.handle_range_args(tpl_args, frame, k, data.field, value, data.html_fmt_options or {})
| |
| end
| |
|
| |
| for short_key, range_data in pairs(h.range_map) do
| |
| tpl_args[k .. range_data.var] = value[short_key]
| |
| end
| |
| end
| |
| end
| |
| | |
| -- calculate and handle weapon dps
| |
| if core.class_groups.weapons.keys[tpl_args.class_id] then
| |
| for _, data in ipairs(core.dps_map) do
| |
| local damage = {
| |
| min = {},
| |
| max = {},
| |
| }
| |
|
| |
| for var_type, value in pairs(damage) do
| |
| -- covers the min/max/avg range
| |
| for short_key, range_data in pairs(h.range_map) do
| |
| value[short_key] = 0
| |
| for _, damage_key in ipairs(data.damage_args) do
| |
| value[short_key] = value[short_key] + (tpl_args[string.format('%s_%s%s', damage_key, var_type, range_data.var)] or 0)
| |
| end
| |
| end
| |
| end
| |
| | |
| local value = {}
| |
| for short_key, range_data in pairs(h.range_map) do
| |
| local result = (damage.min[short_key] + damage.max[short_key]) / 2 * tpl_args[string.format('attack_speed%s', range_data.var)]
| |
| value[short_key] = result
| |
| tpl_args[string.format('%s%s', data.field, range_data.var)] = result
| |
| end
| |
|
| |
| if value.avg > 0 then
| |
| h.handle_range_args(tpl_args, frame, data.name, data.field, value, data.html_fmt_options or {})
| |
| end
| |
| end
| |
| end
| |
|
| |
| -- late processing
| |
| core.process_arguments(tpl_args, frame, {array=core.late_args})
| |
| core.process_arguments(tpl_args, frame, {array=core.item_classes[tpl_args.class_id].late_args})
| |
|
| |
| -- Handle upgrade from restrictions/info
| |
| core.process_upgraded_from(tpl_args, frame)
| |
|
| |
| -- ------------------------------------------------------------------------
| |
| -- Infobox handling
| |
| -- ------------------------------------------------------------------------
| |
| -- Store the infobox so it can be accessed with ease on other pages
| |
| tpl_args.html = tostring(core.display.make_main_container(tpl_args, frame, 'inline'))
| |
| local container = core.display.make_main_container(tpl_args, frame, 'infobox')
| |
|
| |
| if tpl_args.inventory_icon ~= nil and tpl_args.class_id ~= 'DivinationCard' then
| |
| container:wikitext(string.format('[[%s|%sx%spx]]', tpl_args.inventory_icon, c.image_size_full*tpl_args.size_x, c.image_size_full*tpl_args.size_y))
| |
| end
| |
|
| |
| --
| |
| -- Secondary infobox
| |
| --
| |
|
| |
| local extra_infobox = mw.html.create('span')
| |
| :attr( 'class', 'item-box -' .. tpl_args.frame_type)
| |
|
| |
| core.display.add_to_container_from_map(tpl_args, frame, extra_infobox, core.extra_display_groups)
| |
|
| |
| --
| |
| -- Output
| |
| --
| |
|
| |
| local infobox = mw.html.create('span')
| |
| infobox
| |
| :attr('class', 'infobox-page-container')
| |
| :node(container)
| |
| :node(extra_infobox)
| |
|
| |
| -- skill_screenshot is set in skill module
| |
| if tpl_args.skill_screenshot then
| |
| infobox:wikitext(string.format('<br>[[%s|300px]]', tpl_args.skill_screenshot))
| |
| end
| |
|
| |
| local out = tostring(infobox)
| |
|
| |
| -- ------------------------------------------------------------------------
| |
| -- Category handling
| |
| -- ------------------------------------------------------------------------
| |
|
| |
| local cats = {}
| |
| if tpl_args.rarity == 'Unique' then
| |
| cats[#cats+1] = string.format(i18n.categories.unique_affix, tpl_args.class)
| |
| elseif tpl_args._flags.is_prophecy then
| |
| cats[#cats+1] = i18n.categories.prophecies
| |
| elseif tpl_args.is_talisman then
| |
| cats[#cats+1] = i18n.categories.talismans
| |
| elseif tpl_args.is_essence then
| |
| cats[#cats+1] = i18n.categories.essences
| |
| else
| |
| cats[#cats+1] = tpl_args.class
| |
| end
| |
|
| |
| if tpl_args.rarity ~= 'Normal' or tpl_args.base_item == 'Prophecy' or tpl_args.base_item_id == 'Metadata/Items/Currency/CurrencyItemisedProphecy' then
| |
| cats[#cats+1] = i18n.categories.derived_items
| |
| else
| |
| cats[#cats+1] = i18n.categories.base_items
| |
| end
| |
|
| |
| for _, attr in ipairs(m_game.constants.attributes) do
| |
| if tpl_args[attr.long_lower .. '_percent'] then
| |
| cats[#cats+1] = string.format('%s %s', attr.long_upper, tpl_args.class)
| |
| end
| |
| end
| |
|
| |
| local affix
| |
| if tpl_args.class_id == 'Active Skill Gem' or tpl_args.class_id == 'Support Skill Gem' then
| |
| affix = i18n.categories.gem_tag_affix
| |
| end
| |
| if affix ~= nil then
| |
| for _, tag in ipairs(tpl_args.gem_tags) do
| |
| cats[#cats+1] = string.format(affix, tag)
| |
| end
| |
| end
| |
|
| |
| if #tpl_args.alternate_art_inventory_icons > 0 then
| |
| cats[#cats+1] = i18n.categories.alternate_artwork
| |
| end
| |
|
| |
| -- TODO: add maintenance categories
| |
|
| |
| if tpl_args.release_version == nil then
| |
| cats[#cats+1] = i18n.categories.missing_release_version
| |
| end
| |
|
| |
| if tpl_args._flags.text_modifier and not tpl_args.suppress_improper_modifiers_category then
| |
| cats[#cats+1] = i18n.categories.improper_modifiers
| |
| end
| |
|
| |
| --
| |
| for _, k in ipairs({'broken_upgraded_from_reference', 'duplicate_query_area_ids', 'sell_prices_override'}) do
| |
| if tpl_args._flags[k] then
| |
| cats[#cats+1] = i18n.categories[k]
| |
| end
| |
| end
| |
|
| |
| out = out .. m_util.misc.add_category(cats, {ingore_blacklist=tpl_args.debug})
| |
|
| |
| --
| |
| -- Misc
| |
| --
| |
|
| |
| -- Also show the infobox for areas right away for maps, since they're both on the same page
| |
| local query_id
| |
| if tpl_args.rarity == 'Normal' and tpl_args.map_area_id ~= nil then
| |
| query_id = tpl_args.map_area_id
| |
| elseif tpl_args.rarity == 'Unique' and tpl_args.unique_map_area_id ~= nil then
| |
| query_id = tpl_args.unique_map_area_id
| |
| end
| |
| | |
| if query_id then
| |
| out = out .. m_area.query_area_info{cats=yes, where=string.format('areas.id="%s"', query_id)}
| |
| end
| |
|
| |
| -- ------------------------------------------------------------------------
| |
| -- Store cargo data
| |
| -- ------------------------------------------------------------------------
| |
| -- Map argument values for cargo storage
| |
| for _, table_name in ipairs(core.item_classes[tpl_args.class_id].tables) do
| |
| tpl_args._subobjects[table_name] = {
| |
| _table = table_name,
| |
| }
| |
| end
| |
| for k, v in pairs(tpl_args) do
| |
| local data = core.map[k]
| |
| if data ~= nil then
| |
| if data.table ~= nil and data.field ~= nil then
| |
| tpl_args._subobjects[data.table][data.field] = v
| |
| elseif data.table == nil and data.field ~= nil then
| |
| error(string.format('Missing table for field "%s", key "%s", \nvalue:\n "%s" \ndata:\n%s', data.field, k, mw.dumpObject(v), mw.dumpObject(data)))
| |
| elseif data.table ~= nil and data.field == nil then
| |
| error(string.format('Missing field for table "%s", key "%s", \nvalue:\n "%s" \ndata:\n%s', data.table, k, mw.dumpObject(v), mw.dumpObject(data)))
| |
| end
| |
| end
| |
| end
| |
|
| |
| -- Don't actually save data in testing mode
| |
| if not tpl_args.test then
| |
| for _, data in pairs(tpl_args._subobjects) do
| |
| m_util.cargo.store(frame, data, {
| |
| debug=tpl_args.debug,
| |
| sep={
| |
| name_list='�',
| |
| },
| |
| })
| |
| end
| |
| end
| |
|
| |
| -- Show additional error messages in console to help fixing them
| |
| if #tpl_args._errors > 0 then
| |
| mw.logObject(table.concat(tpl_args._errors, '\n'))
| |
| end
| |
|
| |
| if tpl_args.test then
| |
| tpl_args.out = out
| |
| return tpl_args
| |
| else
| |
| mw.logObject(os.clock() - t)
| |
| return out
| |
| end
| |
| end
| |
| | |
| -- ----------------------------------------------------------------------------
| |
| -- Result formatting templates for SMW queries
| |
| -- ----------------------------------------------------------------------------
| |
| | |
| --
| |
| -- Template:
| |
| --
| |
| | |
| function p.simple_item_list(frame)
| |
| -- Args
| |
| local tpl_args = getArgs(frame, {
| |
| parentFirst = true
| |
| })
| |
| frame = m_util.misc.get_frame(frame)
| |
|
| |
| local query = {}
| |
| for key, value in pairs(tpl_args) do
| |
| if string.sub(key, 0, 2) == 'q_' then
| |
| query[string.sub(key, 3)] = value
| |
| end
| |
| end
| |
|
| |
| local fields = {
| |
| 'items._pageName',
| |
| 'items.name',
| |
| }
| |
|
| |
| if tpl_args.no_icon == nil then
| |
| fields[#fields+1] = 'items.inventory_icon'
| |
| end
| |
|
| |
| if tpl_args.no_html == nil then
| |
| fields[#fields+1] = 'items.html'
| |
| end
| |
|
| |
| local tables = m_util.string.split(tpl_args.q_tables or '', ',%s*')
| |
| table.insert(tables, 'items')
| |
|
| |
| query.groupBy = query.groupBy or 'items._pageID'
| |
|
| |
| local results = m_util.cargo.query(
| |
| tables,
| |
| fields,
| |
| query
| |
| )
| |
|
| |
| local out = {}
| |
| for _, row in ipairs(results) do
| |
| local link = f_item_link{page=row['items._pageName'], name=row['items.name'], inventory_icon=row['items.inventory_icon'] or '', html=row['items.html'] or '', skip_query=true}
| |
| if tpl_args.format == nil then
| |
| out[#out+1] = string.format('* %s', link)
| |
| elseif tpl_args.format == 'none' then
| |
| out[#out+1] = link
| |
| elseif tpl_args.format == 'li' then
| |
| out[#out+1] = string.format('<li>%s</li>', link)
| |
| else
| |
| error(string.format(i18n.errors.generic_argument_parameter, 'format', tpl_args.format))
| |
| end
| |
| end
| |
|
| |
| if tpl_args.format == nil then
| |
| return table.concat(out, '\n')
| |
| elseif tpl_args.format == 'none' then
| |
| return table.concat(out, '\n')
| |
| elseif tpl_args.format == 'li' then
| |
| return table.concat(out)
| |
| end
| |
| end
| |
| | |
| -- ----------------------------------------------------------------------------
| |
| -- Misc. Item templates
| |
| -- ----------------------------------------------------------------------------
| |
| | |
| --
| |
| -- Template:Item class
| |
| --
| |
| | |
| function p.item_class (frame)
| |
| -- Get args
| |
| local tpl_args = getArgs(frame, {
| |
| parentFirst = true
| |
| })
| |
| frame = m_util.misc.get_frame(frame)
| |
|
| |
| if not doInfoCard then
| |
| doInfoCard = require('Module:Infocard')._main
| |
| end
| |
|
| |
| local err = true
| |
| for _, row in pairs(m_game.constants.item.classes) do
| |
| if row['full'] == tpl_args.name then
| |
| err = false
| |
| break
| |
| end
| |
| end
| |
|
| |
| if err then
| |
| error(string.format(i18n.errors.invalid_class, tostring(tpl_args.name)))
| |
| end
| |
|
| |
| if tpl_args.name_list ~= nil then
| |
| tpl_args.name_list = m_util.string.split(tpl_args.name_list, ',%s*')
| |
| else
| |
| tpl_args.name_list = {}
| |
| end
| |
|
| |
| --
| |
|
| |
| local ul = mw.html.create('ul')
| |
| for _, item in ipairs(tpl_args.name_list) do
| |
| ul
| |
| :tag('li')
| |
| :wikitext(item)
| |
| :done()
| |
| end
| |
|
| |
| | |
| -- Output Infocard
| |
|
| |
| local tplargs = {
| |
| ['header'] = tpl_args.name,
| |
| ['subheader'] = i18n.item_class_infobox.page .. i18n.item_class_infobox.info,
| |
| [1] = i18n.item_class_infobox.also_referred_to_as .. tostring(ul),
| |
| }
| |
|
| |
| -- cats
| |
|
| |
| local cats = {
| |
| 'Item classes',
| |
| tpl_args.name,
| |
| }
| |
|
| |
| -- Done
| |
|
| |
| return doInfoCard(tplargs) .. m_util.misc.add_category(cats, {ingore_blacklist=tpl_args.debug})
| |
| end
| |
| | |
| -- ----------------------------------------------------------------------------
| |
| -- Debug stuff
| |
| -- ----------------------------------------------------------------------------
| |
| | |
| p.debug = {}
| |
| | |
| -- ----------------------------------------------------------------------------
| |
| -- Return
| |
| -- ----------------------------------------------------------------------------
| |
| | |
| return p
| |