>OmegaK2 |
>OmegaK2 |
Line 1: |
Line 1: |
| -- SMW reworked item module | | -- Item link module |
| | |
| -- ----------------------------------------------------------------------------
| |
| -- TODO
| |
| -- ----------------------------------------------------------------------------
| |
| -- Items
| |
| -- -----
| |
| -- Check if abyss jewels actually have radius modifiers
| |
| --
| |
| -- Has explicit mod ids (and others) changing order of values in the API.
| |
| -- | | -- |
| -- Aggregate ids from Has granted skill id from modifiers | | -- This is separate from the main item module for small speed ups. |
| -- | | -- |
| -- DROP restriction improvements: | | -- Those speed ups are only sigificant if the module is called a lot of times (100+), in tests this amounted to only a ~10% difference in page load times at best. |
| -- drop monster type(s)
| | -- It should be noted those tests are difficult because of the large variance in page load times |
| --
| |
| -- unique items:
| |
| -- 3D art
| |
| -- supporter attribution
| |
| -- option to hide explicit mods or override text
| |
| --
| |
| -- singular for weapon class in infoboxes
| |
| --
| |
| --
| |
| -- Maps: | |
| -- Area level can be retrieved eventually
| |
| --
| |
| -- Essence:
| |
| -- type column
| |
| -- monster modifier info
| |
| -- ----------
| |
| -- Item table
| |
| -- ----------
| |
| -- Skills need proper range values in their tables
| |
| -- stat_column<i>_stat<j>_id -> make an lua pattern alternative
| |
| -- show drop area etc
| |
| --
| |
| -- ----------
| |
| -- Item class
| |
| -- ----------
| |
| --
| |
| -- remove the ul if name_list is not provided
| |
| -- maybe smw
| |
| -- -----------
| |
| -- rework todo
| |
| -- -----------
| |
| -- check unique map properties copy
| |
| -- REMOVED:
| |
| -- is_essence
| |
| -- RENAMED
| |
| -- essence_tier -> essence_level
| |
| -- release_version
| |
| | |
| | |
|
| |
|
| -- ---------------------------------------------------------------------------- | | -- ---------------------------------------------------------------------------- |
| -- Imports | | -- Imports |
| -- ---------------------------------------------------------------------------- | | -- ---------------------------------------------------------------------------- |
| local xtable = require('Module:Table')
| |
| local m_util = require('Module:Util') | | local m_util = require('Module:Util') |
| local getArgs = require('Module:Arguments').getArgs | | 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 f_item_link = require('Module:Item link').item_link
| |
|
| |
| local cargo = mw.ext.cargo
| |
|
| |
| local p = {}
| |
| local c = {}
| |
| c.image_size = 39
| |
| c.image_size_full = c.image_size * 2
| |
|
| |
| -- ----------------------------------------------------------------------------
| |
| -- Temporary fixes
| |
| -- ----------------------------------------------------------------------------
| |
| -- Move to util
| |
| function m_util.cast.factory.array_table(k, args)
| |
| -- Arguments:
| |
| -- tbl - table to check against
| |
| -- errmsg - error message if no element was found; should accept 1 parameter
| |
| args = args or {}
| |
| return function (tpl_args, frame)
| |
| local elements
| |
|
| |
| if tpl_args[k] ~= nil then
| |
| elements = m_util.string.split(tpl_args[k], ',%s*')
| |
| for _, element in ipairs(elements) do
| |
| local r = m_util.table.find_in_nested_array{value=element, tbl=args.tbl, key='full'}
| |
| if r == nil then
| |
| error(m_util.html.error{msg=string.format(args.errmsg or i18n.errors.missing_element, element)})
| |
| end
| |
| end
| |
| tpl_args[args.key_out or k] = xtable:new(elements)
| |
| end
| |
| end
| |
| end
| |
|
| |
| function m_util.cast.factory.assoc_table(k, args)
| |
| -- Arguments:
| |
| --
| |
| -- tbl
| |
| -- errmsg
| |
| -- key_out
| |
| return function (tpl_args, frame)
| |
| local elements
| |
|
| |
| if tpl_args[k] ~= nil then
| |
| elements = m_util.string.split(tpl_args[k], ',%s*')
| |
| for _, element in ipairs(elements) do
| |
| if args.tbl[element] == nil then
| |
| error(m_util.html.error{msg=string.format(args.errmsg or i18n.errors.missing_element, element)})
| |
| end
| |
| end
| |
| tpl_args[args.key_out or k] = elements
| |
| end
| |
| end
| |
| end
| |
|
| |
| function m_util.cargo.query(tables, fields, query, args)
| |
| -- Wrapper for mw.ext.cargo.query that helps to work around some bugs
| |
| --
| |
| -- Current workarounds:
| |
| -- field names will be "aliased" to themselves
| |
| --
| |
| -- Takes 3 arguments:
| |
| -- tables - array containing tables
| |
| -- fields - array containing fields; these will automatically be renamed to the way they are specified to work around bugs when results are returned
| |
| -- query - array containing cargo sql clauses
| |
| -- args
| |
| -- args.keep_empty
| |
|
| |
| -- Cargo bug workaround
| |
| args = args or {}
| |
| for i, field in ipairs(fields) do
| |
| -- already has some alternate name set, so do not do this.
| |
| if string.find(field, '=') == nil then
| |
| fields[i] = string.format('%s=%s', field, field)
| |
| end
| |
| end
| |
| local results = cargo.query(table.concat(tables, ','), table.concat(fields, ','), query)
| |
| if args.keep_empty == nil then
| |
| for _, row in ipairs(results) do
| |
| for k, v in pairs(row) do
| |
| if v == "" then
| |
| row[k] = nil
| |
| end
| |
| end
| |
| end
| |
| end
| |
| return results
| |
| end
| |
|
| |
| function m_util.cargo.array_query(args)
| |
| -- Performs a long "OR" query from the given array and field validating that there is only exactly one match returned
| |
| --
| |
| -- args:
| |
| -- tables - array of tables (see util.cargo.query)
| |
| -- fields - array of fields (see util.cargo.query)
| |
| -- query - array containing cargo sql clauses [optional] (see util.cargo.query)
| |
| -- id_array - list of ids to query for
| |
| -- id_field - name of the id field, will be automatically added to fields
| |
| --
| |
| -- RETURN:
| |
| -- table - results as given by mw.ext.cargo.query
| |
| --
| |
| args.query = args.query or {}
| |
|
| |
| args.fields[#args.fields+1] = args.id_field
| |
|
| |
| local id_array = {}
| |
| for i, id in ipairs(args.id_array) do
| |
| id_array[i] = string.format('%s="%s"', args.id_field, id)
| |
| end
| |
| if args.query.where then
| |
| args.query.where = string.format('(%s) AND (%s)', args.query.where, table.concat(id_array, ' OR '))
| |
| else
| |
| args.query.where = table.concat(id_array, ' OR ')
| |
| end
| |
|
| |
| --
| |
| -- Check for duplicates
| |
| --
| |
|
| |
| -- The usage of distinct should elimate duplicates here from cargo being bugged while still showing actual data duplicates.
| |
| local results = m_util.cargo.query(
| |
| args.tables,
| |
| {
| |
| string.format('COUNT(DISTINCT %s._pageID)=count', args.tables[1]),
| |
| args.id_field,
| |
| },
| |
| {
| |
| join=args.query.join,
| |
| where=args.query.where,
| |
| groupBy=args.id_field,
| |
| having=string.format('COUNT(DISTINCT %s._pageID) > 1', args.tables[1]),
| |
| }
| |
| )
| |
| if #results > 0 then
| |
| out = {}
| |
| for _, row in ipairs(results) do
| |
| out[#out+1] = string.format('%s (%s pages found)', row[args.id_field], row['count'])
| |
| end
| |
| error(string.format('Found duplicates for field "%s":\n %s', args.id_field, table.concat(out, '\n')))
| |
| end
| |
|
| |
| --
| |
| -- Prepare query
| |
| --
| |
| if args.query.groupBy then
| |
| args.query.groupBy = string.format('%s._pageID,%s', args.tables[1], args.query.groupBy)
| |
| else
| |
| args.query.groupBy = string.format('%s._pageID', args.tables[1])
| |
| end
| |
|
| |
| local results = m_util.cargo.query(
| |
| args.tables,
| |
| args.fields,
| |
| args.query
| |
| )
| |
|
| |
| --
| |
| -- Check missing results
| |
| --
| |
| if #results ~= #args.id_array then
| |
| local missing = {}
| |
| for _, id in ipairs(args.id_array) do
| |
| missing[id] = true
| |
| end
| |
| for _, row in ipairs(results) do
| |
| missing[row[args.id_field]] = nil
| |
| end
| |
|
| |
| local missing_ids = {}
| |
| for k, _ in pairs(missing) do
| |
| missing_ids[#missing_ids+1] = k
| |
| end
| |
|
| |
| error(string.format('Missing results for "%s" field with values: \n%s', args.id_field, table.concat(missing_ids, '\n')))
| |
| end
| |
|
| |
| return results
| |
| end
| |
|
| |
|
| -- ---------------------------------------------------------------------------- | | -- ---------------------------------------------------------------------------- |
Line 253: |
Line 22: |
| -- TODO: Maybe move this out to a separate sub-page module | | -- TODO: Maybe move this out to a separate sub-page module |
| local i18n = { | | local i18n = { |
| range = '(%s to %s)',
| |
| inventory_icon = 'File:%s inventory icon.png',
| |
| status_icon = 'File:%s status icon.png',
| |
| skill_screenshot = 'File:%s skill screenshot.jpg',
| |
| divination_card_art = 'File:%s card art.png',
| |
| gem_tag_category = '[[:Category:%s (gem tag)|%s]]',
| |
|
| |
| categories = { | | categories = { |
| -- maintenance cats | | -- maintenance cats |
| improper_modifiers = 'Items with improper modifiers', | | broken_item_links = '[[Category:Pages with broken item links]]', |
| missing_release_version = 'Items without a release version',
| |
| broken_upgraded_from_reference = 'Items with broken item references in upgraded from parameters',
| |
| | |
| -- 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 table
| |
| item_table = {
| |
| item = 'Item',
| |
| skill_gem = 'Skill gem',
| |
|
| |
| physical_dps = m_util.html.abbr('pDPS', 'physical damage per second'),
| |
| fire_dps = m_util.html.abbr('Fire DPS', 'fire damage per second'),
| |
| cold_dps = m_util.html.abbr('Cold DPS', 'cold damage per second'),
| |
| lightning_dps = m_util.html.abbr('Light. DPS', 'lightning damage per second'),
| |
| chaos_dps = m_util.html.abbr('Chaos DPS', 'chaos damage per second'),
| |
| elemental_dps = m_util.html.abbr('eDPS', 'elemental damage (i.e. fire/cold/lightning) per second'),
| |
| poison_dps = m_util.html.abbr('Poison DPS', 'poison damage (i.e. physical/chaos) per second'),
| |
| dps = m_util.html.abbr('DPS', 'total damage (i.e. physical/fire/cold/lightning/chaos) per second'),
| |
| base_item = 'Base Item',
| |
| item_class = 'Item Class',
| |
| essence_level = 'Essence<br>Level',
| |
| drop_level = 'Drop<br>Level',
| |
| drop_leagues = 'Drop Leagues',
| |
| drop_areas = 'Drop Areas',
| |
| drop_text = 'Additional<br>Drop Restrictions',
| |
| stack_size = 'Stack<br>Size',
| |
| stack_size_currency_tab = m_util.html.abbr('Tab<br>Stack<br>Size', 'Stack size in the currency stash tab'),
| |
| armour = m_util.html.abbr('AR', 'Armour'),
| |
| evasion = m_util.html.abbr('EV', 'Evasion Rating'),
| |
| energy_shield = m_util.html.abbr('ES', 'Energy Shield'),
| |
| block = m_util.html.abbr('Block', 'Chance to Block'),
| |
| damage = m_util.html.abbr('Damage', 'Colour coded damage'),
| |
| attacks_per_second = m_util.html.abbr('APS', 'Attacks per second'),
| |
| local_critical_strike_chance = m_util.html.abbr('Crit', 'Local weapon critical strike chance'),
| |
| flask_life = m_util.html.abbr('Life', 'Life regenerated over the flask duration'),
| |
| flask_mana = m_util.html.abbr('Mana', 'Mana regenerated over the flask duration'),
| |
| flask_duration = 'Duration',
| |
| flask_charges_per_use = m_util.html.abbr('Usage', 'Number of charges consumed on use'),
| |
| flask_maximum_charges = m_util.html.abbr('Capacity', 'Maximum number of flask charges held'),
| |
| item_limit = 'Limit',
| |
| jewel_radius = 'Radius',
| |
| map_tier = 'Map<br>Tier',
| |
| map_level = 'Map<br>Level',
| |
| map_guild_character = m_util.html.abbr('Char', 'Character for the guild tag'),
| |
| buff_effects = 'Buff Effects',
| |
| stats = 'Stats',
| |
| effects = 'Effect(s)',
| |
| flavour_text = 'Flavour Text',
| |
| prediction_text = 'Prediction',
| |
| help_text = 'Help Text',
| |
| seal_cost = m_util.html.abbr('Seal<br>Cost', 'Silver Coin cost of sealing this prophecies into an item'),
| |
| objective = 'Objective',
| |
| reward = 'Reward',
| |
| buff_icon = 'Buff<br>Icon',
| |
|
| |
| -- Skills
| |
| support_gem_letter = m_util.html.abbr('L', 'Support gem letter.'),
| |
| skill_icon = 'Icon',
| |
| description = 'Description',
| |
| skill_critical_strike_chance = m_util.html.abbr('Crit', 'Critical Strike Chance'),
| |
| cast_time = m_util.html.abbr('Cast<br>Time', 'Casting time of the skill in seconds'),
| |
| damage_effectiveness = m_util.html.abbr('Dmg.<br>Eff.', 'Damage Effectiveness'),
| |
| mana_cost_multiplier = m_util.html.abbr('MCM', 'Mana cost multiplier - missing values indicate it changes on gem level'),
| |
| mana_cost = m_util.html.abbr('Mana', 'Mana cost'),
| |
| reserves_mana_suffix = m_util.html.abbr('R', 'reserves mana'),
| |
| vaal_souls_requirement = m_util.html.abbr('Souls', 'Vaal souls requirement in Normal/Cruel/Merciless difficulty'),
| |
| stored_uses = m_util.html.abbr('Uses', 'Maximum number of stored uses'),
| |
| primary_radius = m_util.html.abbr('R1', 'Primary radius'),
| |
| secondary_radius = m_util.html.abbr('R2', 'Secondary radius'),
| |
| tertiary_radius = m_util.html.abbr('R3', 'Tertiary radius'),
| |
| },
| |
|
| |
| -- 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)',
| |
| 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',
| |
|
| |
| -- 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',
| |
| },
| |
|
| |
| acquisition = {
| |
| header = 'Item acquisition',
| |
| area = 'This item can be acquired in the following areas:',
| |
| upgraded_from = 'This item can be acquired through the following upgrade paths or vendor recipes:',
| |
|
| |
| ingredient_header = 'Usage in recipes',
| |
| ingredient = 'This item is used by upgrade paths or vendor recipes to create the following items:',
| |
| },
| |
|
| |
| 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 = { | | 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!', | | invalid_args = 'Item link: page, item_name or item_name_exact must be specified', |
| missing_rarity = 'Base item parameter is set, but rarity is set to normal. A rarity above normal is required!', | | no_results = 'Item link: No results found for search parameter "%s".', |
| missing_amount = 'Item amount is missing or not a number (%s)',
| | too_many_results = 'Item link: Too many results for search parameter "%s". Consider using page parameter instead.', |
| upgraded_from_broken_reference = 'Item reference in %s is broken (results: %s)', | | alt_art_undefined = 'Item link: Image parameter was specified, but there is no alternate art defined on page "%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.',
| | alt_art_invalid_index = 'Item Link: Alternate art with index/name "%s" not found on page "%s"', |
| 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',
| |
| invalid_item_table_mode = 'Invalid mode for item table',
| |
| non_unique_relic = 'Only unique items can be be relics',
| |
| }, | | }, |
| } | | } |
|
| |
|
| -- ---------------------------------------------------------------------------- | | -- ---------------------------------------------------------------------------- |
| -- Other stuff | | -- Constants & Data |
| -- ---------------------------------------------------------------------------- | | -- ---------------------------------------------------------------------------- |
|
| |
|
| local h = {} | | local c = {} |
| | | c.image_size = 39 |
| function h.debug(tpl_args, func)
| | c.image_size_full = c.image_size * 2 |
| if tpl_args.debug == nil then
| | c.parameters = { |
| return
| | name = 'Has name', |
| end
| | inventory_icon = 'Has inventory icon', |
| func()
| | html = 'Has infobox HTML', |
| end
| | width = 'Has inventory width', |
| | | height = 'Has inventory height', |
| 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',
| |
| },
| |
| } | | } |
| | | c.selectors = {'page', 'item_name', 'item_name_exact'} |
| h.range_fields = {
| |
| {
| |
| field = '_range_minimum',
| |
| type = 'Integer',
| |
| },
| |
| {
| |
| field = '_range_maximum',
| |
| type = 'Integer',
| |
| },
| |
| {
| |
| field = '_range_average',
| |
| type = 'Integer',
| |
| },
| |
| {
| |
| 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 = h.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'] = h.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
| |
| | |
| h.tbl = {}
| |
| | |
| function h.tbl.range_fields(field)
| |
| return function()
| |
| local fields = {}
| |
| for _, partial_field in ipairs({'maximum', 'text', 'colour'}) do
| |
| fields[#fields+1] = string.format('%s_range_%s', field, partial_field)
| |
| end
| |
| return fields
| |
| end
| |
| end
| |
| | |
| h.tbl.display = {}
| |
| function h.tbl.display.na_or_val(tr, value, data)
| |
| return h.na_or_val(tr, value)
| |
| end
| |
| | |
| function h.tbl.display.seconds(tr, value, data)
| |
| return h.na_or_val(tr, value, function(value)
| |
| return string.format('%ss', value)
| |
| end)
| |
| end
| |
| | |
| function h.tbl.display.percent(tr, value, data)
| |
| return h.na_or_val(tr, value, function(value)
| |
| return string.format('%s%%', value)
| |
| end)
| |
| end
| |
| | |
| function h.tbl.display.wikilink(tr, value, data)
| |
| return h.na_or_val(tr, value, function(value)
| |
| return string.format('[[%s]]', value)
| |
| end)
| |
| end
| |
| | |
| h.tbl.display.factory = {}
| |
| function h.tbl.display.factory.value(args)
| |
| args.options = args.options or {}
| |
| | |
| return function(tr, data, properties)
| |
| values = {}
| |
|
| |
| for index, prop in ipairs(properties) do
| |
| local value = data[prop]
| |
| if args.options[index] and args.options[index].fmt then
| |
| value = string.format(args.options[index].fmt, value)
| |
| end
| |
| values[#values+1] = value
| |
| end
| |
|
| |
|
| |
| local td = tr:tag('td')
| |
| td:attr('data-sort-value', table.concat(values, ', '))
| |
| td:wikitext(table.concat(values, ', '))
| |
| if args.colour then
| |
| td:attr('class', 'tc -' .. args.colour)
| |
| end
| |
| end
| |
| end
| |
| | |
| function h.tbl.display.factory.range(args)
| |
| -- args: table
| |
| -- property
| |
| return function (tr, data, fields)
| |
| tr
| |
| :tag('td')
| |
| :attr('data-sort-value', data[string.format('%s_range_maximum', args.field)] or '0')
| |
| :attr('class', 'tc -' .. (data[string.format('%s_range_colour', args.field)] or 'default'))
| |
| :wikitext(data[string.format('%s_range_text', args.field)])
| |
| :done()
| |
| end
| |
| end
| |
| | |
| function h.format_value(tpl_args, frame, value, options)
| |
| -- value: table
| |
| -- min:
| |
| -- max:
| |
| -- options: table
| |
| -- fmt: formatter to use for the value instead of valfmt
| |
| -- fmt_range: formatter to use for the range values. Default: (%s to %s)
| |
| -- inline: Use this format string to insert value
| |
| -- inline_color: colour to use for the inline value; false to disable colour
| |
| -- 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
| |
| -- return_color: also return colour
| |
| | |
| if options.no_color == nil then
| |
| if options.color then
| |
| value.color = options.color
| |
| elseif value.base ~= value.min or value.base ~= value.max then
| |
| value.color = 'mod'
| |
| else
| |
| value.color = 'value'
| |
| end
| |
| end
| |
|
| |
| if options.func ~= nil then
| |
| value.min = options.func(tpl_args, frame, value.min)
| |
| value.max = options.func(tpl_args, frame, value.max)
| |
| end
| |
|
| |
| if options.fmt == nil then
| |
| options.fmt = '%s'
| |
| elseif type(options.fmt) == 'function' then
| |
| options.fmt = options.fmt(tpl_args, frame)
| |
| end
| |
|
| |
| if value.min == value.max then
| |
| value.out = string.format(options.fmt, value.min)
| |
| else
| |
| value.out = string.format(string.format(options.fmt_range or i18n.range, options.fmt, options.fmt), value.min, value.max)
| |
| end
| |
|
| |
| if options.no_color == nil then
| |
| value.out = m_util.html.poe_color(value.color, value.out)
| |
| end
| |
|
| |
| local return_color
| |
| if options.return_color ~= nil then
| |
| return_color = value.color
| |
| end
| |
|
| |
| local text = options.inline
| |
|
| |
| if type(text) == 'string' then
| |
| elseif type(text) == 'function' then
| |
| text = text(tpl_args, frame)
| |
| else
| |
| text = nil
| |
| end
| |
|
| |
| if text and text ~= '' then
| |
| local color
| |
| if options.inline_color == nil then
| |
| color = 'default'
| |
| elseif options.inline_color ~= false then
| |
| color = color.inline_color
| |
| end
| |
|
| |
| if color ~= nil then
| |
| text = m_util.html.poe_color(color, text)
| |
| end
| |
|
| |
| return string.format(text, value.out), return_color
| |
| end
| |
|
| |
| -- If we didn't return before, return here
| |
| return value.out, return_color
| |
| end
| |
|
| |
|
| -- ---------------------------------------------------------------------------- | | -- ---------------------------------------------------------------------------- |
| -- core | | -- Invokable code |
| -- ---------------------------------------------------------------------------- | | -- ---------------------------------------------------------------------------- |
|
| |
| local core = {}
| |
|
| |
| function core.build_cargo_data(tpl_args, frame)
| |
| for _, table_name in ipairs(core.item_classes[tpl_args.class].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 == 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,
| |
| type = range_field.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,
| |
| type = range_field.type,
| |
| }
| |
|
| |
| 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 value = tpl_args[args.key .. args.i]
| |
| local out = {
| |
| result=nil,
| |
| modid=nil,
| |
| type=args.key,
| |
| text=nil,
| |
| }
| |
|
| |
| if value ~= nil then
| |
| table.insert(tpl_args.mods, value)
| |
| table.insert(tpl_args[args.key .. '_mods'], value)
| |
| out.modid = value
| |
| out.text = tpl_args[args.key .. args.i .. '_text']
| |
| --out.result = nil
| |
| table.insert(tpl_args._mods, out)
| |
| return true
| |
| else
| |
| value = tpl_args[args.key .. args.i .. '_text']
| |
| if value ~= nil then
| |
| tpl_args._flags.text_modifier = true
| |
| out.result = value
| |
| table.insert(tpl_args._mods, out)
| |
| return true
| |
| end
| |
| end
| |
|
| |
| return false
| |
| end
| |
|
| |
| function core.process_smw_mods(tpl_args, frame)
| |
| tpl_args.sell_prices = {}
| |
|
| |
| if #tpl_args.mods > 0 then
| |
| local mods = {}
| |
| local mod_ids = {}
| |
| for _, mod_data in ipairs(tpl_args._mods) do
| |
| if mod_data.result == nil then
| |
| mods[mod_data.modid] = mod_data
| |
| mod_ids[#mod_ids+1] = mod_data.modid
| |
| mods[#mods+1] = string.format('mods.id="%s"', mod_data.modid)
| |
| end
| |
| end
| |
|
| |
| local results = m_util.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
| |
|
| |
| -- 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
| |
|
| |
| -- fetch stats
| |
|
| |
| results = cargo.query(
| |
| 'mods,mod_stats',
| |
| -- Workaround: Cargo messing up the ids here
| |
| 'mods.id=mods.id, mod_stats.id=mod_stats.id, mod_stats.min, mod_stats.max',
| |
| {
| |
| join='mods._pageID=mod_stats._pageID',
| |
| where='mod_stats.id IS NOT NULL AND (' .. table.concat(mods, ' OR ') .. ')',
| |
| -- Workaround: Fix cargo duplicates
| |
| groupBy='mod_stats._pageID, mod_stats.id',
| |
| }
| |
| )
| |
| 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
| |
|
| |
| h.stats_update(tpl_args, id, value, mod_data.result['mods.id'], '_stats')
| |
| if mod_data.type ~= 'implicit' then
| |
| h.stats_update(tpl_args, id, value, mod_data.result['mods.id'], '_explicit_stats')
| |
| else
| |
| h.stats_update(tpl_args, id, value, mod_data.result['mods.id'], '_implicit_stats')
| |
| end
| |
| end
| |
|
| |
| -- fetch sell prices
| |
| results = cargo.query(
| |
| 'mods,mod_sell_prices',
| |
| 'mods.id, mod_sell_prices.amount, mod_sell_prices.name',
| |
| {
| |
| join='mods._pageID=mod_sell_prices._pageID',
| |
| where='mod_sell_prices.amount IS NOT NULL AND (' .. table.concat(mods, ' OR ') .. ')',
| |
| -- Workaround: Fix cargo duplicates
| |
| groupBy='mod_sell_prices._pageID, mod_sell_prices.name',
| |
| }
| |
| )
| |
|
| |
| for _, data in ipairs(results) do
| |
| local mod_data = mods[data['mods.id']]
| |
| if mod_data.type ~= implicit then
| |
| local values = {
| |
| name = data['mod_sell_prices.name'],
| |
| amount = tonumber(data['mod_sell_prices.amount']),
| |
| }
| |
| tpl_args.sell_prices[values.name] = (tpl_args.sell_prices[values.name] or 0) + values.amount
| |
| end
| |
| end
| |
| end
| |
|
| |
| 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
| |
| tpl_args.sell_price_order = {}
| |
| for name, amount in pairs(tpl_args.sell_prices) do
| |
| 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,
| |
| item_name = name,
| |
| }
| |
| end
| |
| table.sort(tpl_args.sell_price_order)
| |
| 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' then
| |
| error(m_util.html.error{msg=i18n.errors.missing_rarity})
| |
| end
| |
|
| |
| where = string.format('%s AND items.class="%s" AND items.rarity="Normal"', where, tpl_args.class)
| |
|
| |
| local join = {}
| |
|
| |
| for _, table_name in ipairs(core.item_classes[tpl_args.class].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._pageName',
| |
| 'items.name=items.name',
| |
| 'items.metadata_id=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=%s.%s', data.table, data.field, data.table, data.field)
| |
| end
| |
| end
| |
|
| |
| local result = cargo.query(
| |
| table.concat(core.item_classes[tpl_args.class].tables, ','),
| |
| table.concat(fields, ','),
| |
| {
| |
| where=where,
| |
| join=table.concat(join, ','),
| |
| -- Workaround: Fix cargo duplicates
| |
| 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?
| |
| end
| |
|
| |
| result = result[1]
| |
|
| |
| --error(mw.dumpObject(result))
| |
|
| |
| 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 ~= "" 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 == "" 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 and core.item_classes[tpl_args.class].defaults ~= nil and core.item_classes[tpl_args.class].defaults[k] ~= nil then
| |
| tpl_args[k] = core.item_classes[tpl_args.class].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]
| |
| if skip then
| |
| skip = skip.skip_stat_lines
| |
| end
| |
|
| |
| for _, modinfo in ipairs(tpl_args._mods) do
| |
| if modinfo.type == args.type then
| |
| if modinfo.modid == 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
| |
| if m_util.cast.boolean(modinfo.text) then
| |
| table.insert(lines, modinfo.text)
| |
| end
| |
| else
| |
| for _, line in ipairs(m_util.string.split(modinfo.result['mods.stat_text'], '<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
| |
|
| |
| 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 = 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 = 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 = cargo.query(
| |
| 'items',
| |
| 'items._pageName, items.name, items.metadata_id',
| |
| {
| |
| where=where,
| |
| -- Workaround: Fix cargo duplicates
| |
| groupBy='items._pageID',
| |
| }
| |
| )
| |
| 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 | | -- Template:Item link & Template:Sl |
| -- | | -- |
| core.factory = {}
| |
|
| |
|
| function core.factory.display_value(args)
| | local p = {} |
| -- 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 h.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
| |
|
| |
| 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] 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
| |
|
| |
| out[#out+1] = h.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)))
| |
| 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.add_to_container_from_map(tpl_args, frame, container, mapping)
| |
| 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
| |
| -- 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)
| |
| end
| |
| if valid then
| |
| grpcont[#grpcont+1] = disp.func(tpl_args, frame)
| |
| end
| |
| end
| |
| else
| |
| grpcont = group.func(tpl_args, frame)
| |
| 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
| |
| | |
| --
| |
| -- 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, {type='implicit'})
| |
| 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, {type='explicit'})
| |
|
| |
| 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,
| |
| },
| |
| -- processed in core.build_item_classes
| |
| class = {
| |
| no_copy = true,
| |
| field = 'class',
| |
| type = 'String',
| |
| func = m_util.cast.factory.table('class', {key='full', tbl=m_game.constants.item.class}),
| |
| },
| |
| -- 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
| |
| return
| |
| end
| |
|
| |
| tpl_args.drop_areas = m_util.string.split(tpl_args.drop_areas, ',%s*')
| |
| tpl_args.drop_areas_data = m_util.cargo.array_query{
| |
| tables={'areas'},
| |
| fields={'areas._pageName', 'areas.name', 'areas.main_page'},
| |
| id_field='areas.id',
| |
| id_array=tpl_args.drop_areas,
| |
| }
| |
|
| |
| -- TODO: Cargo: Raise error on missing
| |
| local areas = {}
| |
| for _, row in pairs(tpl_args.drop_areas) do
| |
| areas[#areas+1] = row['area.name']
| |
| end
| |
| end,
| |
| },
| |
| drop_text = {
| |
| no_copy = true,
| |
| field = 'drop_text',
| |
| type = 'String',
| |
| },
| |
| 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 == 'Divination Card' 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 = nil,
| |
| },
| |
| flavour_text = {
| |
| no_copy = true,
| |
| field = 'flavour_text',
| |
| type = 'Text',
| |
| func = nil,
| |
| },
| |
| 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',
| |
| func = nil,
| |
| },
| |
| 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,
| |
| },
| |
| 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 = cargo.query(
| |
| 'items, item_purchase_costs',
| |
| 'item_purchase_costs.amount=item_purchase_costs.amount,item_purchase_costs.name=item_purchase_costs.name,item_purchase_costs.rarity=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),
| |
| -- Workaround: Fix cargo duplicates
| |
| groupBy = 'item_purchase_costs._pageName, item_purchase_costs.name, item_purchase_costs.rarity',
| |
| }
| |
| )
| |
|
| |
| 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,
| |
| },
| |
| --
| |
| -- 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] or core.class_groups.armor.keys[tpl_args.class] 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 == 'Utility Flasks' or tpl_args.class == 'Critical Utility Flasks' then
| |
| h.stats_update(tpl_args, 'quality_flask_duration', stat, nil, '_stats')
| |
| -- quality is added to quantity for maps
| |
| elseif tpl_args.class == 'Maps' 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 = 'Integer',
| |
| func = m_util.cast.factory.number('flask_duration'),
| |
| },
| |
| buff_id = {
| |
| field = 'id',
| |
| type = 'String',
| |
| func = nil,
| |
| },
| |
| buff_values = {
| |
| field = '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
| |
|
| |
| tpl_args.buff_values = values
| |
| 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 = 'Integer',
| |
| func = m_util.cast.factory.number('critical_strike_chance'),
| |
| },
| |
| attack_speed = {
| |
| field = 'attack_speed',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('attack_speed'),
| |
| },
| |
| range = {
| |
| field = 'range',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('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 = nil,
| |
| },
| |
| 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,
| |
| },
| |
| skill_screenshot = {
| |
| field = 'skill_screenshot',
| |
| type = 'Page',
| |
| func = function(tpl_args, frame)
| |
| tpl_args.skill_screenshot = string.format(i18n.skill_screenshot, tpl_args.name)
| |
| 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 = {
| |
| ield = '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 = nil,
| |
| },
| |
| cosmetic_type = {
| |
| field = 'cosmetic_type',
| |
| type = 'String',
| |
| func = nil,
| |
| },
| |
| -- 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 = nil,
| |
| },
| |
| seal_cost = {
| |
| field = 'seal_cost',
| |
| type = 'Integer',
| |
| func = m_util.cast.factory.number('seal_cost'),
| |
| },
| |
| prophecy_reward = {
| |
| field = 'reward',
| |
| type = 'Text',
| |
| func = nil,
| |
| },
| |
| prophecy_objective = {
| |
| field = 'objective',
| |
| type = 'Text',
| |
| func = nil,
| |
| },
| |
| -- 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.name == 'Prophecy' or tpl_args.base_item == 'Prophecy' then
| |
| tpl_args.frame_type = 'prophecy'
| |
| return
| |
| end
| |
|
| |
| local var = core.class_specifics[tpl_args.class]
| |
| 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 = {
| |
| no_copy = true,
| |
| field = 'mods',
| |
| type = 'List (,) of String',
| |
| default = function () return {} end,
| |
| },
| |
| implicit_mods = {
| |
| field = 'implicit_mods',
| |
| type = 'List (,) of String',
| |
| func_copy = function (tpl_args)
| |
| tpl_args.implicit_mods = m_util.string.split(tpl_args.implicit_mods, ',%s*')
| |
| for _, modid in ipairs(tpl_args.implicit_mods) do
| |
| tpl_args.mods[#tpl_args.mods+1] = modid
| |
| tpl_args._mods[#tpl_args._mods+1] = {
| |
| result=nil,
| |
| modid=modid,
| |
| type='implicit',
| |
| }
| |
| end
| |
| end,
| |
| default = function () return {} end,
| |
| },
| |
| explicit_mods = {
| |
| field = 'explicit_mods',
| |
| type = 'List (,) of String',
| |
| default = function () return {} 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
| |
| local page
| |
| if data['areas.main_page'] == '' then
| |
| page = data['areas._pageName']
| |
| else
| |
| page = data['areas.main_page']
| |
| end
| |
| areas[#areas+1] = string.format('[[%s]]', page)
| |
| end
| |
|
| |
| tpl_args.drop_areas_html = table.concat(areas, ', ')
| |
| end,
| |
| },
| |
| }
| |
| | |
| 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',
| |
| },
| |
| },
| |
| range = {
| |
| field = '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',
| |
| },
| |
| 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'
| |
| },
| |
| 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},
| |
| },
| |
| 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},
| |
| },
| |
| 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},
| |
| },
| |
| 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 = i18n.item_table.physical_dps,
| |
| label_infobox = i18n.tooltips.physical_dps,
| |
| html_fmt_options = {
| |
| color = 'value',
| |
| fmt = '%.1f',
| |
| },
| |
| },
| |
| {
| |
| name = 'fire_dps',
| |
| field = 'fire_dps',
| |
| damage_args = {'fire_damage'},
| |
| label = i18n.item_table.fire_dps,
| |
| label_infobox = i18n.tooltips.fire_dps,
| |
| html_fmt_options = {
| |
| color = 'fire',
| |
| fmt = '%.1f',
| |
| },
| |
| },
| |
| {
| |
| name = 'cold_dps',
| |
| field = 'cold_dps',
| |
| damage_args = {'cold_damage'},
| |
| label = i18n.item_table.cold_dps,
| |
| label_infobox = i18n.tooltips.cold_dps,
| |
| html_fmt_options = {
| |
| color = 'cold',
| |
| fmt = '%.1f',
| |
| },
| |
| },
| |
| {
| |
| name = 'lightning_dps',
| |
| field = 'lightning_dps',
| |
| damage_args = {'lightning_damage'},
| |
| label = i18n.item_table.lightning_dps,
| |
| label_infobox = i18n.tooltips.lightning_dps,
| |
| html_fmt_options = {
| |
| color = 'lightning',
| |
| fmt = '%.1f',
| |
| },
| |
| },
| |
| {
| |
| name = 'chaos_dps',
| |
| field = 'chaos_dps',
| |
| damage_args = {'chaos_damage'},
| |
| label = i18n.item_table.chaos_dps,
| |
| 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 = i18n.item_table.elemental_dps,
| |
| 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 = i18n.item_table.poison_dps,
| |
| 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 = i18n.item_table.dps,
| |
| 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,
| |
| 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,
| |
| mods = core.map.mods,
| |
| explicit_mods = core.map.explicit_mods,
| |
| implicit_mods = core.map.implicit_mods,
| |
| name_list = core.map.name_list,
| |
| description = core.map.description,
| |
| },
| |
| }
| |
| | |
| 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_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',
| |
| },
| |
| },
| |
| }
| |
| | |
| -- 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,
| |
| 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,
| |
| range = core.map.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,
| |
| skill_screenshot = core.map.skill_screenshot,
| |
| -- 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,
| |
| 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
| |
| -- 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_areas', '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', 'mods', 'implicit_mods', 'explicit_mods',
| |
| 'drop_areas_html',
| |
| }
| |
| -- 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 = {['Life Flasks'] = true, ['Mana Flasks'] = true, ['Hybrid Flasks'] = true, ['Utility Flasks'] = true, ['Critical Utility Flasks'] = true},
| |
| args = {'quality', 'flask_duration', 'charges_max', 'charges_per_use'},
| |
| },
| |
| weapons = {
| |
| tables = {'weapons'},
| |
| keys = {['Claws'] = true, ['Daggers'] = true, ['Wands'] = true, ['One Hand Swords'] = true, ['Thrusting One Hand Swords'] = true, ['One Hand Axes'] = true, ['One Hand Maces'] = true, ['Bows'] = true, ['Staves'] = true, ['Two Hand Swords'] = true, ['Two Hand Axes'] = true, ['Two Hand Maces'] = true, ['Sceptres'] = true, ['Fishing Rods'] = 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', '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 Gems'] = true, ['Support Skill Gems'] = true},
| |
| args = {'dexterity_percent', 'strength_percent', 'intelligence_percent', 'primary_attribute', 'gem_tags'},
| |
| },
| |
| armor = {
| |
| tables = {'armours'},
| |
| keys = {['Gloves'] = true, ['Boots'] = true, ['Body Armours'] = true, ['Helmets'] = true, ['Shields'] = true},
| |
| args = {'quality', 'required_dexterity', 'required_intelligence', 'required_strength', 'armour', 'energy_shield', 'evasion'},
| |
| },
| |
| stackable = {
| |
| tables = {'stackables'},
| |
| keys = {['Currency'] = true, ['Stackable Currency'] = true, ['Hideout Doodads'] = true, ['Microtransactions'] = true, ['Divination Card'] = true},
| |
| args = {'stack_size', 'stack_size_currency_tab', 'description', 'cosmetic_type'},
| |
| },
| |
| }
| |
| | |
| core.class_specifics = {
| |
| ['Amulets'] = {
| |
| args = {'is_talisman', 'talisman_tier'},
| |
| },
| |
| ['Life Flasks'] = {
| |
| args = {'flask_life'},
| |
| },
| |
| ['Mana Flasks'] = {
| |
| args = {'flask_mana'},
| |
| },
| |
| ['Hybrid Flasks'] = {
| |
| args = {'flask_life', 'flask_mana'},
| |
| },
| |
| ['Utility Flasks'] = {
| |
| tables = {'item_buffs'},
| |
| args = {'buff_id', 'buff_values', 'buff_stat_text', 'buff_icon'},
| |
| },
| |
| ['Critical Utility Flasks'] = {
| |
| tables = {'item_buffs'},
| |
| args = {'buff_id', 'buff_values', 'buff_stat_text', 'buff_icon'},
| |
| },
| |
| ['Active Skill Gems'] = {
| |
| args = {'skill_screenshot'},
| |
| defaults = {
| |
| help_text = i18n.help_text_defaults.active_gem,
| |
| size_x = 1,
| |
| size_y = 1,
| |
| },
| |
| frame_type = 'gem',
| |
| },
| |
| ['Support Skill Gems'] = {
| |
| 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',
| |
| },
| |
| ['Shields'] = {
| |
| tables = {'shields'},
| |
| args = {'block'},
| |
| },
| |
| ['Maps'] = {
| |
| 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',
| |
| },
| |
| ['Stackable Currency'] = {
| |
| args = {'is_essence', 'essence_level_restriction', 'essence_level'},
| |
| frame_type = 'currency',
| |
| },
| |
| ['Microtransactions'] = {
| |
| frame_type = 'currency',
| |
| },
| |
| ['Hideout Doodads'] = {
| |
| 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'] = {
| |
| late_args = {'item_limit', 'jewel_radius_html'},
| |
| defaults = {
| |
| help_text = i18n.help_text_defaults.jewel,
| |
| },
| |
| skip_stat_lines = i18n.stat_skip_patterns.jewels,
| |
| },
| |
| ['Abyss Jewel'] = {
| |
| late_args = {'item_limit', 'jewel_radius_html'},
| |
| skip_stat_lines = i18n.stat_skip_patterns.jewels,
| |
| },
| |
| ['Quest Items'] = {
| |
| args = {'description'},
| |
| frame_type = 'quest',
| |
| },
| |
| ['Divination Card'] = {
| |
| tables = {'divination_cards'},
| |
| args = {'card_art',},
| |
| frame_type = 'divicard',
| |
| },
| |
| ['Labyrinth Item'] = {
| |
| frame_type = 'currency',
| |
| },
| |
| ['Labyrinth Trinket'] = {
| |
| args = {tables_assoc, 'buff_icon'},
| |
| frame_type = 'currency',
| |
| },
| |
| ['Pantheon Soul'] = {
| |
| defaults = {
| |
| cannot_be_traded_or_modified = true,
| |
| },
| |
| },
| |
| }
| |
| | |
| -- 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 _, data in ipairs(m_game.constants.item.class) do
| |
| if data['full'] == tpl_args.class then
| |
| core.item_classes[data['full']] = {
| |
| tables = xtable:new(),
| |
| args = xtable:new(),
| |
| late_args = xtable:new(),
| |
| defaults = {},
| |
| }
| |
|
| |
| core.item_classes[data['full']].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 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]
| |
| 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][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].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
| |
| {
| |
| {
| |
| 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 == nil then
| |
| return false
| |
| end
| |
|
| |
| return core.class_groups.weapons.keys[tpl_args.class] ~= nil
| |
| end,
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = 'class',
| |
| color = 'default',
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| 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,
| |
| },
| |
| [2] = {
| |
| key = 'vaal_souls_requirement',
| |
| hide_default = 0,
| |
| fmt = '%i (C) / ',
| |
| func = function (tpl_args, frame, value)
| |
| return value*1.5
| |
| end,
| |
| },
| |
| [3] = {
| |
| key = 'vaal_souls_requirement',
| |
| hide_default = 0,
| |
| fmt = '%i (M)',
| |
| func = function (tpl_args, frame, value)
| |
| return value*2
| |
| end,
| |
| },
| |
| },
| |
| },
| |
| },
| |
| {
| |
| 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 = '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 = {'range_html'},
| |
| func = core.factory.display_value{
| |
| options = {
| |
| [1] = {
| |
| key = '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 = '-textwrap tc -gemdesc',
| |
| {
| |
| args = {'gem_description'},
| |
| func = core.factory.display_value_only('gem_description'),
| |
| },
| |
| },
| |
| -- Gem Quality Stats
| |
| {
| |
| css_class = '-textwrap 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 = '-textwrap tc -mod',
| |
| {
| |
| args = function(tpl_args, frame)
| |
| return core.class_groups.gems.keys[tpl_args.class] 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 = '-textwrap tc -mod',
| |
| func = function(tpl_args, frame)
| |
| if tpl_args.implicit_stat_text ~= '' then
| |
| return {tpl_args.implicit_stat_text}
| |
| else
| |
| return {}
| |
| end
| |
| end,
| |
| },
| |
| -- Stats
| |
| {
| |
| css_class = '-textwrap tc -mod',
| |
| func = function(tpl_args, frame)
| |
| if tpl_args.explicit_stat_text ~= '' then
| |
| return {tpl_args.explicit_stat_text}
| |
| else
| |
| return {}
| |
| end
| |
| end,
| |
| },
| |
| -- Experience
| |
| --[[{
| |
| {
| |
| args = {'experience'},
| |
| func = core.factory.display_value{
| |
| key = 'experience',
| |
| options = {
| |
| [1] = {
| |
| fmt = '%i',
| |
| },
| |
| },
| |
| },
| |
| },
| |
| },]]--
| |
| -- Description (currency, doodads)
| |
| {
| |
| css_class = '-textwrap 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 = '-textwrap tc -flavour',
| |
| {
| |
| args = {'flavour_text'},
| |
| func = core.factory.display_value_only('flavour_text'),
| |
| },
| |
| },
| |
| -- Prophecy text
| |
| {
| |
| css_class = '-textwrap tc -value',
| |
| {
| |
| args = {'prediction_text'},
| |
| func = core.factory.display_value_only('prediction_text'),
| |
| },
| |
| },
| |
| -- Can not be traded or modified
| |
| {
| |
| css_class = '-textwrap 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 = '-textwrap tc -help',
| |
| {
| |
| args = {'help_text'},
| |
| func = core.factory.display_value_only('help_text'),
| |
| },
| |
| },
| |
| -- 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,
| |
| {
| |
| 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
| |
| },
| |
| } | |
|
| |
|
| for i, data in ipairs(core.dps_map) do
| | function p.item_link (frame) |
| 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
| |
| | |
| core.result = {}
| |
| | |
| -- for sort type see:
| |
| -- https://meta.wikimedia.org/wiki/Help:Sorting
| |
| core.result.generic_item = {
| |
| {
| |
| arg = 'base_item',
| |
| header = i18n.item_table.base_item,
| |
| fields = {'items.base_item', 'items.base_item_page'},
| |
| display = function(tr, data)
| |
| tr
| |
| :tag('td')
| |
| :attr('data-sort-value', data['items.base_item'])
| |
| :wikitext(string.format('[[%s|%s]]', data['items.base_item_page'], data['items.base_item']))
| |
| end,
| |
| order = 1000,
| |
| sort_type = 'text',
| |
| },
| |
| {
| |
| arg = 'class',
| |
| header = i18n.item_table.item_class,
| |
| fields = {'items.class'},
| |
| display = h.tbl.display.factory.value{options = {
| |
| [1] = {
| |
| fmt='[[%s]]',
| |
| },
| |
| }},
| |
| order = 1001,
| |
| sort_type = 'text',
| |
| },
| |
| {
| |
| arg = 'essence',
| |
| header = i18n.item_table.essence_level,
| |
| fields = {'essences.level'},
| |
| display = h.tbl.display.factory.value{},
| |
| order = 2000,
| |
| },
| |
| {
| |
| arg = {'drop', 'drop_level'},
| |
| header = i18n.item_table.drop_level,
| |
| fields = {'items.drop_level'},
| |
| display = h.tbl.display.factory.value{},
| |
| order = 3000,
| |
| },
| |
| {
| |
| arg = 'stack_size',
| |
| header = i18n.item_table.stack_size,
| |
| fields = {'stackables.stack_size'},
| |
| display = h.tbl.display.factory.value{},
| |
| order = 4000,
| |
| },
| |
| {
| |
| arg = 'stack_size_currency_tab',
| |
| header = i18n.item_table.stack_size_currency_tab,
| |
| fields = {'stackables.stack_size_currency_tab'},
| |
| display = h.tbl.display.factory.value{},
| |
| order = 4001,
| |
| },
| |
| {
| |
| arg = 'level',
| |
| header = m_game.level_requirement.icon,
| |
| fields = h.tbl.range_fields('items.required_level'),
| |
| display = h.tbl.display.factory.range{field='items.required_level'},
| |
| order = 5000,
| |
| },
| |
| {
| |
| arg = 'ar',
| |
| header = i18n.item_table.armour,
| |
| fields = h.tbl.range_fields('armours.armour'),
| |
| display = h.tbl.display.factory.range{field='armours.armour'},
| |
| order = 6000,
| |
| },
| |
| {
| |
| arg = 'ev',
| |
| header =i18n.item_table.evasion,
| |
| fields = h.tbl.range_fields('armours.evasion'),
| |
| display = h.tbl.display.factory.range{field='armours.evasion'},
| |
| order = 6001,
| |
| },
| |
| {
| |
| arg = 'es',
| |
| header = i18n.item_table.energy_shield,
| |
| fields = h.tbl.range_fields('armours.energy_shield'),
| |
| display = h.tbl.display.factory.range{field='armours.energy_shield'},
| |
| order = 6002,
| |
| },
| |
| {
| |
| arg = 'block',
| |
| header = i18n.item_table.block,
| |
| fields = h.tbl.range_fields('shields.block'),
| |
| display = h.tbl.display.factory.range{field='shields.block'},
| |
| order = 6003,
| |
| },
| |
| --[[{
| |
| arg = 'physical_damage_min',
| |
| header = m_util.html.abbr('Min', 'Local minimum weapon damage'),
| |
| fields = h.tbl.range_fields('minimum physical damage'),
| |
| display = h.tbl.display.factory.range{field='minimum physical damage'},
| |
| order = 7000,
| |
| },
| |
| {
| |
| arg = 'physical_damage_max',
| |
| header = m_util.html.abbr('Max', 'Local maximum weapon damage'),
| |
| fields = h.tbl.range_fields('maximum physical damage'),
| |
| display = h.tbl.display.factory.range{field='maximum physical damage'},
| |
| order = 7001,
| |
|
| |
| },]]--
| |
| {
| |
| arg = {'weapon', 'damage'},
| |
| header = i18n.item_table.damage,
| |
| fields = {'weapons.damage_html', 'weapons.damage_avg'},
| |
| display = function (tr, data)
| |
| tr
| |
| :tag('td')
| |
| :attr('data-sort-value', data['weapons.damage_avg'])
| |
| :wikitext(data['weapons.damage_html'])
| |
| end,
| |
| order = 8000,
| |
| },
| |
| {
| |
| arg = {'weapon', 'aps'},
| |
| header = i18n.item_table.attacks_per_second,
| |
| fields = h.tbl.range_fields('weapons.attack_speed'),
| |
| display = h.tbl.display.factory.range{field='weapons.attack_speed'},
| |
| order = 8001,
| |
| },
| |
| {
| |
| arg = {'weapon', 'crit'},
| |
| header = i18n.item_table.local_critical_strike_chance,
| |
| fields = h.tbl.range_fields('weapons.critical_strike_chance'),
| |
| display = h.tbl.display.factory.range{field='weapons.critical_strike_chance'},
| |
| order = 8002,
| |
| },
| |
| {
| |
| arg = 'flask_life',
| |
| header = i18n.item_table.flask_life,
| |
| fields = h.tbl.range_fields('flasks.life'),
| |
| display = h.tbl.display.factory.range{field='flasks.life'},
| |
| order = 9000,
| |
| },
| |
| {
| |
| arg = 'flask_mana',
| |
| header = i18n.item_table.flask_mana,
| |
| fields = h.tbl.range_fields('flasks.mana'),
| |
| display = h.tbl.display.factory.range{field='flasks.mana'},
| |
| order = 9001,
| |
| },
| |
| {
| |
| arg = 'flask',
| |
| header = i18n.item_table.flask_duration,
| |
| fields = h.tbl.range_fields('flasks.duration'),
| |
| display = h.tbl.display.factory.range{field='flasks.duration'},
| |
| order = 9002,
| |
| },
| |
| {
| |
| arg = 'flask',
| |
| header = i18n.item_table.flask_charges_per_use,
| |
| fields = h.tbl.range_fields('flasks.charges_per_use'),
| |
| display = h.tbl.display.factory.range{field='flasks.charges_per_use'},
| |
| order = 9003,
| |
| },
| |
| {
| |
| arg = 'flask',
| |
| header = i18n.item_table.flask_maximum_charges,
| |
| fields = h.tbl.range_fields('flasks.charges_max'),
| |
| display = h.tbl.display.factory.range{field='flasks.charges_max'},
| |
| order = 9004,
| |
| },
| |
| {
| |
| arg = 'item_limit',
| |
| header = i18n.item_table.item_limit,
| |
| fields = {'jewels.item_limit'},
| |
| display = h.tbl.display.factory.value{},
| |
| order = 10000,
| |
| },
| |
| {
| |
| arg = 'jewel_radius',
| |
| header = i18n.item_table.jewel_radius,
| |
| fields = {'jewels.radius_html'},
| |
| display = function (tr, data)
| |
| tr
| |
| :tag('td')
| |
| :wikitext(data['jewels.radius_html'])
| |
| end,
| |
| order = 10001,
| |
| },
| |
| {
| |
| arg = 'map_tier',
| |
| header = i18n.item_table.map_tier,
| |
| fields = {'maps.tier'},
| |
| display = h.tbl.display.factory.value{},
| |
| order = 11000,
| |
| },
| |
| {
| |
| arg = 'map_level',
| |
| header = i18n.item_table.map_level,
| |
| fields = {'maps.area_level'},
| |
| display = h.tbl.display.factory.value{},
| |
| order = 11010,
| |
| },
| |
| {
| |
| arg = 'map_guild_character',
| |
| header = i18n.item_table.map_guild_character,
| |
| fields = {'maps.guild_character'},
| |
| display = h.tbl.display.factory.value{colour='value'},
| |
| order = 11020,
| |
| sort_type = 'text',
| |
| },
| |
| {
| |
| arg = 'buff',
| |
| header = i18n.item_table.buff_effects,
| |
| fields = {'item_buffs.stat_text'},
| |
| display = h.tbl.display.factory.value{colour='mod'},
| |
| order = 12000,
| |
| sort_type = 'text',
| |
| },
| |
| {
| |
| arg = 'stat',
| |
| header = i18n.item_table.stats,
| |
| fields = {'items.stat_text'},
| |
| display = h.tbl.display.factory.value{colour='mod'},
| |
| order = 12001,
| |
| sort_type = 'text',
| |
| },
| |
| {
| |
| arg = 'description',
| |
| header = i18n.item_table.effects,
| |
| fields = {'items.description'},
| |
| display = h.tbl.display.factory.value{colour='mod'},
| |
| order = 12002,
| |
| sort_type = 'text',
| |
| },
| |
| {
| |
| arg = 'flavour_text',
| |
| header = i18n.item_table.flavour_text,
| |
| fields = {'items.flavour_text'},
| |
| display = h.tbl.display.factory.value{colour='flavour'},
| |
| order = 12003,
| |
| sort_type = 'text',
| |
| },
| |
| {
| |
| arg = 'help_text',
| |
| header = i18n.item_table.help_text,
| |
| fields = {'items.help_text'},
| |
| display = h.tbl.display.factory.value{colour='help'},
| |
| order = 12005,
| |
| sort_type = 'text',
| |
| },
| |
| {
| |
| arg = {'prophecy', 'objective'},
| |
| header = i18n.item_table.objective,
| |
| fields = {'prophecies.objective'},
| |
| display = h.tbl.display.factory.value{},
| |
| order = 13002,
| |
| },
| |
| {
| |
| arg = {'prophecy', 'reward'},
| |
| header = i18n.item_table.reward,
| |
| fields = {'prophecies.reward'},
| |
| display = h.tbl.display.factory.value{},
| |
| order = 13001,
| |
| },
| |
| {
| |
| arg = {'prophecy', 'seal_cost'},
| |
| header = i18n.item_table.seal_cost,
| |
| fields = {'prophecies.seal_cost'},
| |
| display = h.tbl.display.factory.value{colour='currency'},
| |
| order = 13002,
| |
| },
| |
| {
| |
| arg = {'prediction_text'},
| |
| header = i18n.item_table.prediction_text,
| |
| fields = {'prophecies.prediction_text'},
| |
| display = h.tbl.display.factory.value{colour='value'},
| |
| order = 12004,
| |
| sort_type = 'text',
| |
| },
| |
| {
| |
| arg = 'buff_icon',
| |
| header = i18n.item_table.buff_icon,
| |
| fields = {'item_buffs.icon'},
| |
| display = h.tbl.display.factory.value{options = {
| |
| [1] = {
| |
| fmt='[[%s]]',
| |
| },
| |
| }},
| |
| order = 14000,
| |
| sort_type = 'text',
| |
| },
| |
| {
| |
| arg = {'drop', 'drop_leagues'},
| |
| header = i18n.item_table.drop_leagues,
| |
| fields = {'items.drop_leagues'},
| |
| display = function (tr, data)
| |
| tr
| |
| :tag('td')
| |
| :wikitext(table.concat(m_util.string.split(data['items.drop_leagues'], ','), '<br>'))
| |
| end,
| |
| order = 15000,
| |
| },
| |
| {
| |
| arg = {'drop', 'drop_areas'},
| |
| header = i18n.item_table.drop_areas,
| |
| fields = {'items.drop_areas_html'},
| |
| display = h.tbl.display.factory.value{},
| |
| order = 15001,
| |
| },
| |
| {
| |
| arg = {'drop', 'drop_text'},
| |
| header = i18n.item_table.drop_text,
| |
| fields = {'items.drop_text'},
| |
| display = h.tbl.display.factory.value{},
| |
| order = 15002,
| |
| },
| |
| }
| |
| | |
| for i, data in ipairs(core.dps_map) do
| |
| table.insert(core.result.generic_item, {
| |
| arg = data.name,
| |
| header = data.label,
| |
| fields = h.tbl.range_fields(string.format('weapons.%s', data.field)),
| |
| display = h.tbl.display.factory.range{field=string.format('weapons.%s', data.field)},
| |
| order = 8100+i,
| |
| })
| |
| end
| |
| | |
| core.result.skill_gem_new = {
| |
| {
| |
| arg = 'icon',
| |
| header = i18n.item_table.support_gem_letter,
| |
| fields = {'skill_gems.support_gem_letter_html'},
| |
| display = h.tbl.display.factory.value{},
| |
| order = 1000,
| |
| sort_type = 'text',
| |
| },
| |
| {
| |
| arg = 'skill_icon',
| |
| header = i18n.item_table.skill_icon,
| |
| fields = {'skills3.skill_icon'},
| |
| display = h.tbl.display.factory.value{options = {
| |
| [1] = {
| |
| fmt='[[%s]]',
| |
| },
| |
| }},
| |
| order = 1001,
| |
| sort_type = 'text',
| |
| },
| |
| {
| |
| arg = 'description',
| |
| header = i18n.item_table.description,
| |
| fields = {'skills3.description'},
| |
| display = h.tbl.display.factory.value{},
| |
| order = 2000,
| |
| sort_type = 'text',
| |
| },
| |
| {
| |
| arg = 'level',
| |
| header = m_game.level_requirement.icon,
| |
| fields = {'items.level_requirement'},
| |
| display = h.tbl.display.factory.value{},
| |
| order = 3004,
| |
| },
| |
| {
| |
| arg = 'crit',
| |
| header = i18n.item_table.skill_critical_strike_chance,
| |
| fields = {'skill_levels.critical_strike_chance'},
| |
| display = h.tbl.display.factory.value{options = {
| |
| [1] = {
| |
| fmt='%s%%',
| |
| },
| |
| }},
| |
| order = 4000,
| |
| },
| |
| {
| |
| arg = 'cast_time',
| |
| header = i18n.item_table.cast_time,
| |
| fields = {'skill_levels.cast_time'},
| |
| display = h.tbl.display.factory.value{},
| |
| order = 4001,
| |
| },
| |
| {
| |
| arg = 'dmgeff',
| |
| header = i18n.item_table.damage_effectiveness,
| |
| fields = {'skill_levels.damage_effectiveness'},
| |
| display = h.tbl.display.factory.value{options = {
| |
| [1] = {
| |
| fmt='%s%%',
| |
| },
| |
| }},
| |
| order = 4002,
| |
| },
| |
| {
| |
| arg = 'mcm',
| |
| header = i18n.item_table.mana_cost_multiplier,
| |
| fields = {'skill_levels.mana_multiplier'},
| |
| display = h.tbl.display.factory.value{options = {
| |
| [1] = {
| |
| fmt='%s%%',
| |
| },
| |
| }},
| |
| order = 5000,
| |
| },
| |
| {
| |
| arg = 'mana',
| |
| header = i18n.item_table.mana_cost,
| |
| fields = {'skill_levels.mana_cost', 'skills3.has_percentage_mana_cost', 'skills3.has_reservation_mana_cost'},
| |
| display = function (tr, data)
| |
| local appendix = ''
| |
| if m_util.cast.boolean(data['skills3.has_percentage_mana_cost']) then
| |
| appendix = appendix .. '%'
| |
| end
| |
| if m_util.cast.boolean(data['skills3.has_reservation_mana_cost']) then
| |
| appendix = appendix .. ' ' .. i18n.item_table.reserves_mana_suffix
| |
| end
| |
|
| |
| tr
| |
| :tag('td')
| |
| :attr('data-sort-value', data['skill_levels.mana_cost'])
| |
| :wikitext(string.format('%d', data['skill_levels.mana_cost']) .. appendix)
| |
| end,
| |
| order = 5001,
| |
| },
| |
| {
| |
| arg = 'vaal',
| |
| header = i18n.item_table.vaal_souls_requirement,
| |
| fields = {'skill_levels.vaal_souls_requirement'},
| |
| display = function (tr, data)
| |
| local souls = tonumber(data['skill_levels.vaal_souls_requirement'])
| |
| tr
| |
| :tag('td')
| |
| :attr('data-sort-value', souls)
| |
| :wikitext(string.format('%d / %d / %d', souls, souls*1.5, souls*2))
| |
| end,
| |
| order = 6000,
| |
| },
| |
| {
| |
| arg = 'vaal',
| |
| header = i18n.item_table.stored_uses,
| |
| fields = {'skill_levels.vaal_stored_uses'},
| |
| display = h.tbl.display.factory.value{},
| |
| order = 6001,
| |
| },
| |
| {
| |
| arg = 'radius',
| |
| header = i18n.item_table.primary_radius,
| |
| fields = {'skills3.radius', 'skills3.radius_description'},
| |
| options = {[2] = {optional = true}},
| |
| display = function (tr, data)
| |
| tr
| |
| :tag('td')
| |
| :attr('data-sort-value', data['skills3.radius'])
| |
| :wikitext(core.factory.descriptor_value{tbl=data, key='skills3.radius_description'}(nil, nil, data['skills3.radius']))
| |
| end,
| |
| order = 7000,
| |
| },
| |
| {
| |
| arg = 'radius',
| |
| header = i18n.item_table.secondary_radius,
| |
| fields = {'skills3.radius_secondary', 'skills3.radius_secondary_description'},
| |
| options = {[2] = {optional = true}},
| |
| display = function (tr, data)
| |
| tr
| |
| :tag('td')
| |
| :attr('data-sort-value', data['skills3.radius_secondary'])
| |
| :wikitext(core.factory.descriptor_value{tbl=data, key='skills3.radius_secondary_description'}(nil, nil, data['skills3.radius_secondary']))
| |
| end,
| |
| order = 7001,
| |
| },
| |
| {
| |
| arg = 'radius',
| |
| header = i18n.item_table.tertiary_radius,
| |
| fields = {'skills3.radius_tertiary', 'skills3.radius_tertiary_description'},
| |
| options = {[2] = {optional = true}},
| |
| display = function (tr, data)
| |
| tr
| |
| :tag('td')
| |
| :attr('data-sort-value', data['skills3.radius_tertiary'])
| |
| :wikitext(core.factory.descriptor_value{tbl=data, key='skills3.radius_tertiary_description'}(nil, nil, data['skills3.radius_tertiary']))
| |
| end,
| |
| order = 7002,
| |
| },
| |
| }
| |
| | |
| for i, attr in ipairs(m_game.constants.attributes) do
| |
| table.insert(core.result.generic_item, 7, {
| |
| arg = attr.short_lower,
| |
| header = attr.icon,
| |
| fields = h.tbl.range_fields(string.format('items.required_%s', attr.long_lower)),
| |
| display = h.tbl.display.factory.range{field=string.format('items.required_%s', attr.long_lower)},
| |
| order = 5000+i,
| |
| })
| |
| table.insert(core.result.skill_gem_new, 1, {
| |
| arg = attr.short_lower,
| |
| header = attr.icon,
| |
| fields = {string.format('skill_gems.%s_percent', attr.long_lower)},
| |
| display = function (tr, data)
| |
| tr
| |
| :tag('td')
| |
| :attr('data-sort-value', data[string.format('skill_gems.%s_percent', attr.long_lower)])
| |
| :wikitext('[[File:Yes.png|yes|link=]]')
| |
| end,
| |
| order = 3000+i,
| |
| })
| |
| 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
| |
| dcl_args[stat_data.field .. range_fields.field] = range_fields.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
| |
| dcl_args[dps_data.field .. range_fields.field] = range_fields.type
| |
| 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_purchase_costs = cargo_declare(core.cargo.item_purchase_costs)
| |
| 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 | | -- Args/Frame |
| -- | | -- |
| local t = os.clock()
| |
| | | |
| local tpl_args = getArgs(frame, { | | local tpl_args = getArgs(frame, { |
| parentFirst = true | | parentFirst = true, |
| | removeBlanks = false, |
| }) | | }) |
| frame = m_util.misc.get_frame(frame) | | frame = m_util.misc.get_frame(frame) |
| | | |
| -- | | -- Backwards compability |
| -- Shared args
| | tpl_args.item_name = tpl_args.item_name or tpl_args[1] |
| --
| | if tpl_args.item_name ~= nil then |
|
| | tpl_args.item_name = mw.ustring.lower(tpl_args.item_name) |
| tpl_args._flags = {}
| |
| tpl_args._base_item_args = {}
| |
| tpl_args._mods = {}
| |
| tpl_args._stats = {}
| |
| tpl_args._implicit_stats = {}
| |
| tpl_args._explicit_stats = {}
| |
| tpl_args._subobjects = {} | |
| tpl_args._properties = {}
| |
| tpl_args._errors = {}
| |
|
| |
| core.build_item_classes(tpl_args, frame)
| |
| 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].args})
| |
|
| |
| -- Base Item
| |
| | |
| core.process_base_item(tpl_args, frame)
| |
|
| |
| -- Prophecy special snowflake
| |
| if tpl_args.base_item == '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 | | end |
| | tpl_args.name = tpl_args.name or tpl_args[2] |
| | | |
| -- Mods | | if m_util.table.has_all_value(tpl_args, c.selectors) and tpl_args.skip_query == nil then |
| | | error(i18n.errors.invalid_args) |
| 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 | | end |
| | | |
| core.process_smw_mods(tpl_args, frame) | | tpl_args.large = m_util.cast.boolean(tpl_args.large) |
|
| |
| -- 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 id, data in pairs(tpl_args._stats) do
| |
| tpl_args._subobjects[#tpl_args._subobjects+1] = {
| |
| _table = 'item_stats',
| |
| id = id,
| |
| min = data.min,
| |
| max = data.max,
| |
| avg = data.avg,
| |
| is_implicit = nil,
| |
| }
| |
| end
| |
| for id, data in pairs(tpl_args._explicit_stats) do
| |
| tpl_args._subobjects[#tpl_args._subobjects+1] = {
| |
| _table = 'item_stats',
| |
| id = id,
| |
| min = data.min,
| |
| max = data.max,
| |
| avg = data.avg,
| |
| is_implicit = false,
| |
| }
| |
| end
| |
| for id, data in pairs(tpl_args._implicit_stats) do
| |
| tpl_args._subobjects[#tpl_args._subobjects+1] = {
| |
| _table = 'item_stats',
| |
| id = id,
| |
| min = data.min,
| |
| max = data.max,
| |
| avg = data.avg,
| |
| is_implicit = true,
| |
| }
| |
| end
| |
| | | |
| -- Handle extra stats (for gems) | | local img |
| | local result |
| | | |
| if core.class_groups.gems.keys[tpl_args.class] then | | if m_util.table.has_one_value(tpl_args, c.selectors, nil) and tpl_args.skip_query == nil then |
| m_skill.skill(frame, tpl_args) | | local query = {} |
| 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 | | if tpl_args.page ~= nil then |
| value = {min=value, max=value, base=value}
| | -- TODO returns the result even if the + format is specified. |
| -- If stats are overriden we scan save some CPU time here | | query[#query+1] = string.format('[[%s]]', tpl_args.page) |
| local overridden = false
| | else |
| if data.stats_override ~= nil then
| | if tpl_args.item_name ~= nil then |
| for stat_id, override_value in pairs(data.stats_override) do
| | query[#query+1] = string.format('[[Has lowercase names::%s]]', tpl_args.item_name) |
| local stat_value = tpl_args._stats[stat_id]
| | elseif tpl_args.item_name_exact ~= nil then |
| if stat_value ~= nil then
| | query[#query+1] = string.format('[[Has name::%s]]', tpl_args.item_name_exact) |
| -- 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 | | end |
| | | |
| value.avg = (value.min + value.max) / 2 | | query[#query] = query[#query] .. ' [[Has inventory icon::+]] [[Has infobox HTML::+]]' |
| | | |
| -- don't add the properties unless we need to
| | if tpl_args.link_type == 'skill' then |
| if (data.default ~= nil and (value.min ~= data.default or value.max ~= data.default)) or data.default == nil then | | query[#query] = query[#query] .. ' [[Concept:Skill gems]]' |
| 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 | | end |
| end
| |
|
| |
| -- calculate and handle weapon dps
| |
| if core.class_groups.weapons.keys[tpl_args.class] then
| |
| for _, data in ipairs(core.dps_map) do
| |
| local damage = {
| |
| min = {},
| |
| max = {},
| |
| }
| |
| | | |
| for var_type, value in pairs(damage) do
| | query[#query+1] = '?Has name' |
| -- covers the min/max/avg range
| | query[#query+1] = '?Has inventory icon' |
| for short_key, range_data in pairs(h.range_map) do
| | query[#query+1] = '?Has infobox HTML' |
| value[short_key] = 0
| | query[#query+1] = '?Has alternate inventory icons' |
| for _, damage_key in ipairs(data.damage_args) do
| | query[#query+1] = '?Has inventory width' |
| value[short_key] = value[short_key] + (tpl_args[string.format('%s_%s%s', damage_key, var_type, range_data.var)] or 0)
| | query[#query+1] = '?Has inventory height' |
| end
| | |
| end
| | -- attributes |
| end
| | result = m_util.smw.query(query, frame) |
| | | |
| local value = {}
| | local err |
| for short_key, range_data in pairs(h.range_map) do
| | if #result == 0 then |
| local result = (damage.min[short_key] + damage.max[short_key]) / 2 * tpl_args[string.format('attack_speed%s', range_data.var)]
| | err = m_util.misc.raise_error_or_return{raise_required=true, args=tpl_args, msg=string.format( |
| value[short_key] = result
| | i18n.errors.no_results, |
| tpl_args[string.format('%s%s', data.field, range_data.var)] = result
| | tpl_args.page or tpl_args.item_name or tpl_args.item_name_exact |
| end
| | )} |
|
| | elseif #result > 1 then |
| if value.avg > 0 then
| | err = m_util.misc.raise_error_or_return{raise_required=true, args=tpl_args, msg=string.format( |
| h.handle_range_args(tpl_args, frame, data.name, data.field, value, data.html_fmt_options or {})
| | i18n.errors.too_many_results, |
| end
| | tpl_args.page or tpl_args.item_name or tpl_args.item_name_exact |
| 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].late_args})
| |
|
| |
| -- Handle upgrade from restrictions/info
| |
| core.process_upgraded_from(tpl_args, frame)
| |
|
| |
| -- ------------------------------------------------------------------------
| |
| -- Infobox handling
| |
| -- ------------------------------------------------------------------------
| |
|
| |
| local extra_class = ''
| |
| local container = mw.html.create('span')
| |
| :attr( 'class', 'item-box -' .. tpl_args.frame_type) | |
|
| |
| if tpl_args.class == 'Divination Card' 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 | | end |
| | | |
| local name_line = tpl_args.name
| | if err ~= nil then |
| if tpl_args.base_item and tpl_args.base_item ~= 'Prophecy' then | | return err .. i18n.categories.broken_item_links |
| name_line = name_line .. '<br>' .. tpl_args.base_item | |
| end | | end |
| | | |
| container | | result = result[1] |
| :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)
| |
| end
| |
|
| |
| if tpl_args.skill_icon ~= nil then
| |
| container:wikitext(string.format('[[%s]]', tpl_args.skill_icon))
| |
| end
| |
|
| |
| -- Store the infobox so it can be accessed with ease on other pages
| |
| tpl_args.html = tostring(container)
| |
|
| |
| if tpl_args.inventory_icon ~= nil and tpl_args.class ~= 'Divination Card' 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)
| |
|
| |
| 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.base_item == '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 | | else |
| cats[#cats+1] = tpl_args.class | | result = {tpl_args.page or tpl_args.name} |
| end | | end |
| | | |
| for _, attr in ipairs(m_game.constants.attributes) do | | for k, prop in pairs(c.parameters) do |
| if tpl_args[attr.long_lower .. '_percent'] then | | if tpl_args[k] ~= nil then |
| cats[#cats+1] = string.format('%s %s', attr.long_upper, tpl_args.class) | | result[prop] = tpl_args[k] |
| end | | end |
| end | | end |
| | | |
| local affix
| | if tpl_args.image ~= nil then |
| if tpl_args.class == 'Active Skill Gems' or tpl_args.class == 'Support Skill Gems' then | | if result['Has alternate inventory icons'] == '' then |
| affix = i18n.categories.gem_tag_affix
| | return m_util.misc.raise_error_or_return{raise_required=true, args=tpl_args, msg=string.format( |
| end
| | i18n.errors.alt_art_undefined, |
| if affix ~= nil then
| | result[1] |
| for _, tag in ipairs(tpl_args.gem_tags) do
| | ) .. i18n.categories.broken_item_links} |
| cats[#cats+1] = string.format(affix, tag)
| |
| end | | 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 then
| |
| cats[#cats+1] = i18n.categories.improper_modifiers
| |
| end
| |
|
| |
| if tpl_args._flags.broken_upgraded_from_reference then
| |
| cats[#cats+1] = i18n.categories.broken_upgraded_from_reference
| |
| 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 unique_map_area_id ~= nil then
| |
| local 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].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", value "%s", data:\n%s', data.field, k, v, mw.dumpObject(data)))
| |
| elseif data.table ~= nil and data.field == nil then
| |
| error(string.format('Missing field for table "%s", key "%s", value "%s", data:\n%s', data.table, k, v, mw.dumpObject(data)))
| |
| end
| |
| end
| |
| end
| |
|
| |
| for _, data in pairs(tpl_args._subobjects) do
| |
| m_util.cargo.store(frame, data)
| |
| end
| |
|
| |
| mw.logObject(os.clock() - t)
| |
|
| |
| -- Show additional error messages in console to help fixing them
| |
| mw.logObject(table.concat(tpl_args._errors, '\n'))
| |
|
| |
| return out
| |
| 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 results = m_util.cargo.query(
| |
| {'items'},
| |
| fields,
| |
| query
| |
| )
| |
|
| |
| local out = {}
| |
| for _, row in ipairs(results) do
| |
| local link = f_item_link{page=tpl_args['items._pageName'], name=tpl_args['items.name'], inventory_icon=tpl_args['items.inventory_icon'] or '', html=tpl_args['items.html'] or '', skip_query=true}
| |
| if args.format == nil then
| |
| out[#out+1] = string.format('* %s', link)
| |
| elseif args.format == 'none' then
| |
| out[#out+1] = link
| |
| elseif args.format == 'li' then
| |
| out[#out+1] = string.format('<li>%s</li>', link)
| |
| else
| |
| error(string.format(i18n.errors.generic_argument_parameter, 'format', args.format))
| |
| end
| |
| end
| |
|
| |
| if args.format == nil then
| |
| return table.concat(out, '\n')
| |
| elseif args.format == 'none' then
| |
| return table.concat(out, '\n')
| |
| elseif args.format == 'li' then
| |
| return table.concat(out)
| |
| end
| |
| end
| |
|
| |
| -- ----------------------------------------------------------------------------
| |
| -- Reponsibile for subtemplates of Template:SMW item table
| |
| --
| |
|
| |
| function p.item_table(frame)
| |
| -- args
| |
| local tpl_args = getArgs(frame, {
| |
| parentFirst = true
| |
| })
| |
| frame = m_util.misc.get_frame(frame)
| |
|
| |
| local modes = {
| |
| skill = {
| |
| data = core.result.skill_gem_new,
| |
| header = i18n.item_table.skill_gem,
| |
| },
| |
| item = {
| |
| data = core.result.generic_item,
| |
| header = i18n.item_table.item,
| |
| },
| |
| }
| |
|
| |
| if tpl_args.mode == nil then
| |
| tpl_args.mode = 'item'
| |
| end
| |
|
| |
| if modes[tpl_args.mode] == nil then
| |
| error(i18n.errors.invalid_item_table_mode)
| |
| end
| |
|
| |
| local row_infos = {}
| |
| for _, row_info in ipairs(modes[tpl_args.mode].data) do
| |
| local enabled = false
| |
| if row_info.arg == nil then
| |
| enabled = true
| |
| elseif type(row_info.arg) == 'string' and m_util.cast.boolean(tpl_args[row_info.arg]) then
| |
| enabled = true
| |
| elseif type(row_info.arg) == 'table' then
| |
| for _, argument in ipairs(row_info.arg) do
| |
| if m_util.cast.boolean(tpl_args[argument]) then
| |
| enabled = true
| |
| break
| |
| end
| |
| end
| |
| end
| |
|
| |
| if enabled then
| |
| row_info.options = row_info.options or {}
| |
| row_infos[#row_infos+1] = row_info
| |
| end
| |
| end
| |
|
| |
| -- Parse stat arguments
| |
| local stat_columns = {}
| |
| local query_stats = {}
| |
| local stat_results = {}
| |
| local i = 0
| |
| repeat
| |
| i = i + 1
| |
| | | |
| local prefix = string.format('stat_column%s_', i) | | result['Has alternate inventory icons'] = m_util.string.split(result['Has alternate inventory icons'], '<MANY>') |
| local col_info = {
| |
| header = tpl_args[prefix .. 'header'] or tostring(i),
| |
| format = tpl_args[prefix .. 'format'],
| |
| stat_format = tpl_args[prefix .. 'stat_format'] or 'separate',
| |
| order = tonumber(tpl_args[prefix .. 'order']) or (10000000 + i),
| |
| stats = {},
| |
| options = {},
| |
| }
| |
| | | |
| local j = 0 | | local index = tonumber(tpl_args.image) |
| repeat | | if index ~= nil then |
| j = j +1 | | img = result['Has alternate inventory icons'][index] |
| | | else |
| local stat_info = { | | -- offset 1 is needed |
| id = tpl_args[string.format('%sstat%s_id', prefix, j)],
| | local suffix = string.len(' inventory icon.png') + 1 |
| }
| | -- add an extra offset by 1 to account for the space |
| | local prefix = string.len(string.sub(result['Has inventory icon'], 1, -suffix)) + 2 |
| | | |
| if stat_info.id then | | for _, filename in ipairs(result['Has alternate inventory icons']) do |
| col_info.stats[#col_info.stats+1] = stat_info
| | if string.sub(filename, prefix, -suffix) == tpl_args.image then |
| query_stats[stat_info.id] = {}
| | img = filename |
| else
| | break |
| -- Stop iteration entirely if this was the first index but no stat was supplied. We assume that we stop in this case.
| |
| if j == 1 then
| |
| i = nil
| |
| end
| |
| -- stop iteration
| |
| j = nil
| |
| end
| |
| until j == nil
| |
|
| |
| -- Don't add this column if no stats were provided.
| |
| if #col_info.stats > 0 then
| |
| stat_columns[#stat_columns+1] = col_info
| |
| end
| |
| until i == nil
| |
|
| |
| for _, col_info in ipairs(stat_columns) do
| |
| local row_info = {
| |
| --arg
| |
| header = col_info.header,
| |
| fields = {},
| |
| display = function(tr, data, properties)
| |
| if col_info.stat_format == 'separate' then
| |
| local stat_texts = {}
| |
| local num_stats = 0
| |
| local vmax = 0
| |
| for _, stat_info in ipairs(col_info.stats) do
| |
| num_stats = num_stats + 1
| |
| -- stat results from outside body
| |
| local stat = (stat_results[data['items._pageName']] or {})[stat_info.id]
| |
| if stat ~= nil then
| |
| stat_texts[#stat_texts+1] = h.format_value(tpl_args, frame, stat, {no_color=true})
| |
| vmax = vmax + stat.max
| |
| end
| |
| end
| |
|
| |
| if num_stats ~= #stat_texts then
| |
| tr:wikitext(m_util.html.td.na())
| |
| else
| |
| local text
| |
| if col_info.format then
| |
| text = string.format(col_info.format, unpack(stat_texts))
| |
| else
| |
| text = table.concat(stat_texts, ', ')
| |
| end
| |
|
| |
| tr:tag('td')
| |
| :attr('data-sort-value', vmax)
| |
| :attr('class', 'tc -mod')
| |
| :wikitext(text)
| |
| end
| |
| elseif col_info.stat_format == 'add' then
| |
| local total_stat = {
| |
| min = 0,
| |
| max = 0,
| |
| avg = 0,
| |
| }
| |
| for _, stat_info in ipairs(col_info.stats) do
| |
| local stat = (stat_results[data['items._pageName']] or {})[stat_info.id]
| |
| if stat ~= nil then
| |
| for k, v in pairs(total_stat) do
| |
| total_stat[k] = v + stat[k]
| |
| end
| |
| end
| |
| end
| |
|
| |
| if col_info.format == nil then
| |
| col_info.format = '%s'
| |
| end
| |
|
| |
| tr:tag('td')
| |
| :attr('data-sort-value', total_stat.max)
| |
| :attr('class', 'tc -mod')
| |
| :wikitext(string.format(col_info.format, h.format_value(tpl_args, frame, total_stat, {no_color=true})))
| |
| else
| |
| error(string.format(i18n.errors.generic_argument_parameter, 'stat_format', col_info.stat_format))
| |
| end
| |
| end,
| |
| order = col_info.order,
| |
| }
| |
| table.insert(row_infos, row_info)
| |
| end
| |
|
| |
| -- sort the rows
| |
| table.sort(row_infos, function (a, b)
| |
| return (a.order or 0) < (b.order or 0)
| |
| end)
| |
|
| |
| -- Parse query arguments
| |
| local tables_assoc = {items=true}
| |
| local fields = {
| |
| 'items._pageName',
| |
| 'items.name',
| |
| 'items.inventory_icon',
| |
| 'items.html',
| |
| 'items.size_x',
| |
| 'items.size_y',
| |
| }
| |
|
| |
| --
| |
| local prepend = {
| |
| q_join=true,
| |
| q_groupBy=true,
| |
| q_tables=true
| |
| }
| |
|
| |
| local query = {}
| |
| for key, value in pairs(tpl_args) do
| |
| if string.sub(key, 0, 2) == 'q_' then
| |
| if prepend[key] then
| |
| value = ',' .. value
| |
| end
| |
|
| |
| query[string.sub(key, 3)] = value
| |
| end
| |
| end
| |
|
| |
| --query.limit = 5000
| |
|
| |
| for _, rowinfo in ipairs(row_infos) do
| |
| if type(rowinfo.fields) == 'function' then
| |
| rowinfo.fields = rowinfo.fields()
| |
| end
| |
| for index, field in ipairs(rowinfo.fields) do
| |
| rowinfo.options[index] = rowinfo.options[index] or {}
| |
| fields[#fields+1] = field
| |
| tables_assoc[m_util.string.split(field, '%.')[1]] = true
| |
| end
| |
| end
| |
|
| |
| -- reformat the fields & tables so they can be retrieved correctly
| |
| for index, field in ipairs(fields) do
| |
| fields[index] = string.format('%s=%s', field, field)
| |
| end
| |
|
| |
| local tables = {}
| |
| for table_name,_ in pairs(tables_assoc) do
| |
| tables[#tables+1] = table_name
| |
| end
| |
|
| |
| -- take care of required joins according to the tables
| |
| | |
| local joins = {}
| |
| for index, table_name in ipairs(tables) do
| |
| if table_name ~= 'items' then
| |
| joins[#joins+1] = string.format('items._pageID=%s._pageID', table_name)
| |
| end
| |
| end
| |
| query.join = table.concat(joins, ',') .. (query.join or '')
| |
|
| |
| -- Cargo workaround: avoid duplicates using groupBy
| |
| query.groupBy = 'items._pageID' .. (query.groupBy or '')
| |
|
| |
| local results = cargo.query(
| |
| table.concat(tables,',') .. (tpl_args.q_tables or ''),
| |
| table.concat(fields,','),
| |
| query
| |
| )
| |
|
| |
| if #results == 0 and tpl_args.default ~= nil then
| |
| return tpl_args.default
| |
| end
| |
|
| |
| if #stat_columns > 0 then
| |
| local continue = true
| |
| local offset = 0
| |
| while continue do
| |
| if tpl_args.q_where then
| |
| tpl_args.q_where = string.format(' AND (%s)', tpl_args.q_where)
| |
| else
| |
| tpl_args.q_where = ''
| |
| end
| |
|
| |
| local temp = cargo.query(
| |
| 'items,item_stats' .. (tpl_args.q_tables or ''),
| |
| 'item_stats._pageName=item_stats._pageName, item_stats.id=item_stats.id, item_stats.min=item_stats.min, item_stats.avg=item_stats.avg, item_stats.max=item_stats.max',
| |
| {
| |
| where='item_stats.is_implicit IS NULL' .. tpl_args.q_where,
| |
| join='items._pageID=item_stats._pageID' .. (tpl_args.q_join or ''),
| |
| limit=5000,
| |
| --offset = offset,
| |
| }
| |
| )
| |
|
| |
| for _, row in ipairs(temp) do
| |
| if query_stats[row['item_stats.id']] ~= nil then
| |
| local stat = { | |
| min = tonumber(row['item_stats.min']),
| |
| max = tonumber(row['item_stats.max']),
| |
| avg = tonumber(row['item_stats.avg']),
| |
| }
| |
|
| |
| if stat_results[row['item_stats._pageName']] == nil then
| |
| stat_results[row['item_stats._pageName']] = {[row['item_stats.id']] = stat}
| |
| else
| |
| stat_results[row['item_stats._pageName']][row['item_stats.id']] = stat
| |
| end | |
| end | | end |
| end | | end |
|
| |
| -- Cargo doesnt support offset yet
| |
| if #temp == 5000 then
| |
| --TODO: Cargo
| |
| error('Stats > 5000')
| |
| --offset = offset + 5000
| |
| else
| |
| continue = false
| |
| end
| |
| end
| |
| end
| |
|
| |
| local tbl = mw.html.create('table')
| |
| tbl:attr('class', 'wikitable sortable item-table')
| |
|
| |
| -- Header
| |
|
| |
| local tr = tbl:tag('tr')
| |
| tr
| |
| :tag('th')
| |
| :wikitext(modes[tpl_args.mode].header)
| |
| :done()
| |
|
| |
| for _, row_info in ipairs(row_infos) do
| |
| tr
| |
| :tag('th')
| |
| :attr('data-sort-type', row_info.sort_type or 'number')
| |
| :wikitext(row_info.header)
| |
| :done()
| |
| end
| |
|
| |
| for _, row in ipairs(results) do
| |
| tr = tbl:tag('tr')
| |
|
| |
| local il_args = {
| |
| skip_query=true,
| |
| page=row['items._pageName'],
| |
| name=row['items.name'],
| |
| inventory_icon=row['items.inventory_icon'],
| |
| html=row['items.html'],
| |
| width=row['items.size_x'],
| |
| height=row['items.size_y'],
| |
| }
| |
|
| |
| if tpl_args.large then
| |
| il_args.large = tpl_args.large
| |
| end | | end |
| | | |
| tr | | if img == nil then |
| :tag('td')
| | return m_util.misc.raise_error_or_return{raise_required=true, args=tpl_args, msg=string.format( |
| :wikitext(f_item_link(il_args))
| | i18n.errors.alt_art_invalid_index, |
| :done()
| | tpl_args.image, result[1] |
|
| | ) .. i18n.categories.broken_item_links} |
| for _, rowinfo in ipairs(row_infos) do
| |
| -- this has been cast from a function in an earlier step
| |
| local display = true
| |
| for index, field in ipairs(rowinfo.fields) do
| |
| -- this will bet set to an empty value not nil confusingly
| |
| if row[field] == '' then
| |
| if rowinfo.options[index].optional ~= true then
| |
| display = false
| |
| break
| |
| else
| |
| row[field] = nil
| |
| end
| |
| end
| |
| end
| |
| if display then
| |
| rowinfo.display(tr, row, rowinfo.fields) | |
| else | |
| tr:wikitext(m_util.html.td.na())
| |
| end
| |
| end | | end |
| | elseif result['Has inventory icon'] ~= '' then |
| | img = result['Has inventory icon'] |
| end | | end |
| | | |
| return tostring(tbl)
| | -- output |
| end
| |
| | |
| | |
| item_table_factory = {}
| |
| function item_table_factory.intro(args)
| |
| -- args: | |
| -- data_array
| |
| -- header
| |
| | | |
| return function (frame) | | local container = mw.html.create('span') |
| -- Args
| | container:addClass('c-item-hoverbox') |
| local tpl_args = getArgs(frame, {
| |
| parentFirst = true
| |
| })
| |
| frame = m_util.misc.get_frame(frame)
| |
|
| |
| --
| |
| tpl_args.userparam = m_util.string.split_args(tpl_args.userparam, {sep=', '})
| |
|
| |
| local tr = mw.html.create('tr')
| |
| tr
| |
| :tag('th')
| |
| :wikitext(args.header)
| |
| :done()
| |
|
| |
| for _, rowinfo in ipairs(args.data_array) do
| |
| if rowinfo.arg == nil or tpl_args.userparam[rowinfo.arg] then
| |
| tr
| |
| :tag('th')
| |
| :wikitext(rowinfo.header)
| |
| :done()
| |
| end
| |
| end
| |
|
| |
| return '<table class="wikitable sortable item-table">' .. tostring(tr)
| |
| end
| |
| end
| |
| | |
| -- ----------------------------------------------------------------------------
| |
| -- Item lists
| |
| -- ----------------------------------------------------------------------------
| |
| | |
| function p.skill_gem_list_by_gem_tag(frame)
| |
| -- Args
| |
| local tpl_args = getArgs(frame, {
| |
| parentFirst = true
| |
| })
| |
| frame = m_util.misc.get_frame(frame)
| |
| | | |
| if tpl_args.class == 'Support Skill Gems' then | | local activator = mw.html.create('span') |
| elseif tpl_args.class == 'Active Skill Gems' then | | activator:addClass('c-item-hoverbox__activator') |
| else
| |
| error(i18n.errors.invalid_item_class)
| |
| end
| |
|
| |
|
| local query = {} | | if img and not tpl_args.large then |
| query[#query+1] = string.format('[[Has item class::%s]]', tpl_args.class)
| | activator:wikitext(string.format('[[%s|16x16px|link=|alt=]]', img)) |
| query[#query+1] = '?Has gem tags'
| |
| query[#query+1] = '?Has name'
| |
| query[#query+1] = '?Has inventory icon'
| |
| --query[#query+1] = '?Has infobox HTML'
| |
| query.limit = 5000
| |
| query.sort = 'Has name'
| |
|
| |
| local results = m_util.smw.query(query, frame)
| |
|
| |
| local tags = {}
| |
|
| |
| for _, row in ipairs(results) do
| |
| row['Has gem tags'] = m_util.string.split(row['Has gem tags'], '<MANY>')
| |
| for _, tag in ipairs(row['Has gem tags']) do
| |
| if tags[tag] == nil then
| |
| tags[tag] = {}
| |
| end
| |
| table.insert(tags[tag], row)
| |
| end
| |
| end | | end |
| | |
| | activator:wikitext(string.format('[[%s|%s]]', result[1], result['Has name'] or result[1])) |
| | | |
| local tags_sorted = {} | | local display = mw.html.create('span') |
| for tag, _ in pairs(tags) do
| | display:attr('class', 'c-item-hoverbox__display') |
| table.insert(tags_sorted, tag)
| |
| end
| |
| table.sort(tags_sorted)
| |
|
| |
| local tbl = mw.html.create('table')
| |
| tbl | |
| :attr('class', 'wikitable sortable')
| |
| :tag('tr')
| |
| :tag('th')
| |
| :wikitext('Tag')
| |
| :done()
| |
| :tag('th')
| |
| :wikitext('Skills')
| |
| :done()
| |
| :done()
| |
|
| |
| for _, tag in ipairs(tags_sorted) do
| |
| local rows = tags[tag]
| |
| local tr = tbl:tag('tr')
| |
| tr
| |
| :tag('td')
| |
| :wikitext(tag)
| |
|
| |
| local td = tr:tag('td')
| |
| for i, row in ipairs(rows) do
| |
| td:wikitext(f_item_link{page=row[1], name=row['Has Name'], inventory_icon=row['Has inventory icon'], html=row['Has infobox HTML'] or ''})
| |
| if i < #rows then
| |
| td:wikitext('<br>')
| |
| end
| |
| end
| |
| end
| |
|
| |
| return tostring(tbl)
| |
| end
| |
|
| |
|
| -- ----------------------------------------------------------------------------
| | if result['Has infobox HTML'] ~= '' then |
| -- Misc. Item templates
| | display:wikitext(result['Has infobox HTML']) |
| -- ----------------------------------------------------------------------------
| |
| | |
| --
| |
| -- Template: Item acquisition
| |
| --
| |
| | |
| -- Used to duplicate the information from the infobox in a more readable manner on the page.
| |
| | |
| function p.item_acquisition (frame)
| |
| -- Get args
| |
| local tpl_args = getArgs(frame, {
| |
| parentFirst = true
| |
| })
| |
| frame = m_util.misc.get_frame(frame)
| |
|
| |
| tpl_args.page = tpl_args.page or tostring(mw.title.getCurrentTitle())
| |
|
| |
| local out = {}
| |
| local results
| |
| local query
| |
|
| |
| -- -------------------------
| |
| -- Drop restrictions by area
| |
| -- -------------------------
| |
| results = m_util.cargo.query(
| |
| {'items'},
| |
| {'items.drop_areas_html'},
| |
| {
| |
| where=string.format('items._pageName="%s"', tpl_args.page),
| |
| -- Workaround: Fix cargo duplicates
| |
| groupBy='items._pageID',
| |
| }
| |
| )
| |
|
| |
| if #results > 0 then | |
| results = results[1]
| |
| if results['items.drop_areas_html'] then
| |
| local ul = mw.html.create('ul')
| |
| for _, area in ipairs(m_util.string.split(results['items.drop_areas_html'], ',%s*')) do
| |
| ul:tag('li')
| |
| :wikitext(area)
| |
| end
| |
| out[#out+1] = i18n.acquisition.area
| |
| out[#out+1]= '<br>'
| |
| out[#out+1] = tostring(ul)
| |
| end
| |
| end
| |
|
| |
| -- ------------------------------------
| |
| -- Obtained via vendor recipes/upgrades
| |
| -- ------------------------------------
| |
|
| |
| --
| |
| -- Query data
| |
| --
| |
| local sets = {}
| |
| results = m_util.cargo.query(
| |
| {'upgraded_from_sets'},
| |
| {
| |
| 'upgraded_from_sets.set_id',
| |
| 'upgraded_from_sets.text',
| |
| },
| |
| {
| |
| where=string.format('upgraded_from_sets._pageName="%s"', tpl_args.page),
| |
| -- Workaround: Fix cargo duplicates
| |
| groupBy='upgraded_from_sets._pageID,upgraded_from_sets.set_id',
| |
| }
| |
| )
| |
|
| |
| for _, row in ipairs(results) do
| |
| row.groups = {}
| |
| sets[tonumber(row['upgraded_from_sets.set_id'])] = row
| |
| end
| |
|
| |
| results = m_util.cargo.query(
| |
| {'upgraded_from_groups'},
| |
| {
| |
| 'upgraded_from_groups.set_id',
| |
| 'upgraded_from_groups.group_id',
| |
| 'upgraded_from_groups.notes',
| |
| 'upgraded_from_groups.amount',
| |
| 'upgraded_from_groups.item_name',
| |
| 'upgraded_from_groups.item_page',
| |
| },
| |
| {
| |
| where=string.format('upgraded_from_groups._pageName="%s"', tpl_args.page),
| |
| -- Workaround: Fix cargo duplicates
| |
| groupBy='upgraded_from_groups._pageID,upgraded_from_groups.set_id,upgraded_from_groups.group_id',
| |
| }
| |
| )
| |
|
| |
| for _, row in ipairs(results) do
| |
| sets[tonumber(row['upgraded_from_groups.set_id'])].groups[tonumber(row['upgraded_from_groups.group_id'])] = row
| |
| end
| |
|
| |
| --
| |
| -- Build output
| |
| --
| |
|
| |
| if #sets > 0 then
| |
| local ul = mw.html.create('ul') | |
| for _, set in ipairs(sets) do
| |
| local li = ul:tag('li')
| |
| if set['upgraded_from_sets.text'] then
| |
| li:wikitext(set['upgraded_from_sets.text'] .. '<br>')
| |
| end
| |
| | | |
| local str = {}
| | if img then |
| for _, group in ipairs(set.groups) do | | display:wikitext(string.format('[[%s|link=|alt=]]', img)) |
| str[#str+1] = string.format('%sx [[%s|%s]]', group['upgraded_from_groups.amount'], group['upgraded_from_groups.item_page'], group['upgraded_from_groups.item_name'] or group['upgraded_from_groups.item_page'])
| |
| end
| |
| li:wikitext(table.concat(str, ', '))
| |
| end | | end |
|
| |
| out[#out+1] = i18n.acquisition.upgraded_from
| |
| out[#out+1]= '<br>'
| |
| out[#out+1] = tostring(ul)
| |
| end
| |
|
| |
| out[#out+1] = tpl_args.acquisition_insert
| |
| -- -------------------------------------
| |
| -- Ingredient of vendor recipes/upgrades
| |
| -- -------------------------------------
| |
|
| |
| --
| |
| -- Query
| |
| --
| |
|
| |
| -- TODO: IL links
| |
| results = m_util.cargo.query(
| |
| {'upgraded_from_groups'},
| |
| {'upgraded_from_groups._pageName'},
| |
| {
| |
| where=string.format('upgraded_from_groups.item_page="%s"', tpl_args.page),
| |
| -- Only need each page name once
| |
| groupBy='upgraded_from_groups._pageName',
| |
| }
| |
| )
| |
|
| |
| if #results > 0 then
| |
| local head = mw.html.create('h3')
| |
| head:wikitext(i18n.acquisition.ingredient_header)
| |
| out[#out+1] = tostring(head)
| |
| out[#out+1] = i18n.acquisition.ingredient
| |
| out[#out+1]= '<br>'
| |
|
| |
| local ul = mw.html.create('ul')
| |
| for _, row in ipairs(results) do
| |
| ul:tag('li')
| |
| :wikitext(string.format('[[%s]]', row['upgraded_from_groups._pageName']))
| |
| end
| |
|
| |
| out[#out+1] = tostring(ul)
| |
| end
| |
|
| |
| out[#out+1] = tpl_args.ingredient_append
| |
|
| |
| -- ------------------------------------
| |
| -- output
| |
| -- ------------------------------------
| |
|
| |
| local head = mw.html.create('h2')
| |
| head:wikitext(i18n.acquisition.header .. '[[File:Questionmark.png|right|24px|link=Path_of_Exile_Wiki:How_to_edit_item_acquisition]]')
| |
| return tostring(head) .. table.concat(out)
| |
| end
| |
|
| |
|
| |
| --
| |
| -- 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
| |
|
| |
| m_util.cast.factory.table('name', {key='full', tbl=m_game.constants.item.class})(tpl_args, frame)
| |
|
| |
| 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 | | 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 | | if img and tpl_args.large then |
|
| | local width = tonumber(result['Has inventory width']) or tonumber(tpl_args.width) |
| local tplargs = {
| | local height = tonumber(result['Has inventory height']) or tonumber(tpl_args.height) |
| ['header'] = tpl_args.name,
| | if width and height then |
| ['subheader'] = i18n.item_class_infobox.page .. i18n.item_class_infobox.info, | | img = string.format('<br>[[%s|%sx%spx|link=%s|alt=]]', img, width*c.image_size, height*c.image_size, result[1]) |
| [1] = i18n.item_class_infobox.also_referred_to_as .. tostring(ul),
| | elseif width then |
| }
| | img = string.format('<br>[[%s|%spx|link=%s|alt=]]', img, width*c.image_size, result[1]) |
|
| | elseif height then |
| -- cats
| | img = string.format('<br>[[%s|x%spx|link=%s|alt=]]', img, height*c.image_size, result[1]) |
|
| | else |
| local cats = {
| | img = string.format('<br>[[%s|link=%s|alt=]]', img, result[1]) |
| '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 = {}
| |
| function p.debug._tbl_data(tbl)
| |
| keys = {}
| |
| for _, data in ipairs(core.result.generic_item) do
| |
| if type(data.arg) == 'string' then | |
| keys[data.arg] = 1
| |
| elseif type(data.arg) == 'table' then
| |
| for _, arg in ipairs(data.arg) do
| |
| keys[arg] = 1
| |
| end
| |
| end | | end |
| | activator:wikitext(img) |
| end | | end |
|
| |
| local out = {}
| |
| for key, _ in pairs(keys) do
| |
| out[#out+1] = string.format("['%s'] = '1'", key)
| |
| end
| |
|
| |
| return table.concat(out, ', ')
| |
| end
| |
|
| |
|
| function p.debug.generic_item_all()
| | container |
| return p.debug._tbl_data(core.result.generic_item)
| | :node(activator) |
| end
| | :node(display) |
| | | :done() |
| function p.debug.skill_gem_all()
| | |
| return p.debug._tbl_data(core.result.skill_gem_new) | | return tostring(container) |
| end | | end |
|
| |
|
| return p | | return p |