Borderlands Wiki
Advertisement
Borderlands Wiki
8066
страниц

Для документации этого модуля может быть создана страница Модуль:Element/doc

-- модуль выдачи стихийных шаблонов. см [[template:стихия]]
-- <pre>
local p = {}

-- data
local d = {
    -- список игр
    -- здесь перечислены все игры, которые понимает модуль
    -- этот список нужен для быстрой проверки и облегчения модификации в будущем
    -- * игры обычно перечислены в порядке выхода
    -- * теперь этот порядок должен быть единственно верным для шаблона
    games = {
        ['borderlands'] = 'borderlands',
        -- стихии goty работают по правилам ванили
        --  во всех внутренних вызовах goty будет заменена на bl1
        ['borderlands goty enhanced'] = 'borderlands',
        ['borderlands 2'] = 'borderlands 2',
        ['borderlands: the pre-sequel'] = 'borderlands: the pre-sequel',
        ['borderlands 3'] = 'borderlands 3'
    },
    -- список стихий
    -- здесь перечислены все параметры стихий
    -- этот список нужен для быстрой проверки и облегчения модификации в будущем
    elements = {
        ['без стихии'] = 'без стихии',
        ['взрыв'] = 'взрыв',
        ['коррозия'] = 'коррозия',
        ['огонь'] = 'огонь',
        ['радиация'] = 'радиация',
        ['удар'] = 'удар',
        ['холод'] = 'холод',
        ['шлак'] = 'шлак',
        ['шок'] = 'шок',
        ['любая'] = 'любая',
        ['любая или без стихии'] = 'любая или без стихии',
        -- запятые будут удалены
        ['любая кроме взрыва'] = 'любая кроме взрыва',
        ['любая кроме взрыва или без стихии'] = 'любая кроме взрыва или без стихии',
        -- в bl3 взрыв заменён ударным уроном (kinetic)
        ['любая кроме удара'] = 'любая кроме удара',
        ['любая кроме удара или без стихии'] = 'любая кроме удара или без стихии'
    },
    -- данные по играм
    -- здесь лежат все пары имя:значения для всех стихий игры
    -- пример: если модуль получает имя стихии "любая", то преобразует его
    --  во "{{взрыв}} {{коррозия}} {{огонь}} {{шок}}"
    -- forbiddenElements: пары вида "тип предмета":"стихия/список стихий"
    --  показывают, что "тип предмета" не может иметь указанные стихии
    --  пример: если щиты в бл2 не могут быть шлаковыми и шоковыми,
    --      то: forbiddenElements = { ["щиты"] = {'шлак', 'шок'} }
    borderlands = {
        -- список доступных для игры стихий
        elements = {
            ['без стихии'] = 'без стихии',
            ['взрыв'] = 'взрыв',
            ['коррозия'] = 'коррозия',
            ['огонь'] = 'огонь',
            ['шок'] = 'шок',
            ['любая'] = { 'взрыв', 'коррозия', 'огонь', 'шок' },
            ['любая или без стихии'] = { 'без стихии', 'взрыв', 'коррозия', 'огонь', 'шок' },
            ['любая кроме взрыва'] = { 'коррозия', 'огонь', 'шок' },
            ['любая кроме взрыва или без стихии'] = { 'без стихии', 'коррозия', 'огонь', 'шок' },
            ['взрыв.borderlands 3'] = 'удар'
        }
    },
    ['borderlands 2'] = {
        elements = {
            ['без стихии'] = 'без стихии',
            ['взрыв'] = 'взрыв',
            ['коррозия'] = 'коррозия',
            ['огонь'] = 'огонь',
            ['шок'] = 'шок',
            ['шлак'] = 'шлак',
            ['любая'] = { 'взрыв', 'коррозия', 'огонь', 'шок', 'шлак' },
            ['любая или без стихии'] = { 'без стихии', 'взрыв', 'коррозия', 'огонь', 'шок', 'шлак' },
            ['любая кроме взрыва'] = { 'коррозия', 'огонь', 'шок', 'шлак' },
            ['любая кроме взрыва или без стихии'] = { 'без стихии', 'коррозия', 'огонь', 'шок', 'шлак' },
            -- альтернативные стихии для разных игр
            --  указываются в формате "стихия.игра"
            --  нужны для предметов, которые встречаются в нескольких играх,
            --  в которых одна стихия заменена другай
            --  пример: шлак в бл2 был заменён на холод в тпс,
            --      а шлаковое оружие стало холодным
            -- игры обычно перечислены в порядке выхода
            --  теперь это должен быть единственно верный порядок
            ['шлак.borderlands: the pre-sequel'] = 'холод',
            ['шлак.borderlands 3'] = { 'холод', 'радиация' },
            ['взрыв.borderlands 3'] = 'удар'
        },
        -- запрещённые элементы для типов снаряжения (нет щитов от шлака в бл2 и тп)
        -- массивы значений допускаются
        forbiddenElements = {
            ['щиты'] = 'шлак'
        }
    },
    ['borderlands: the pre-sequel'] = {
        elements = {
            ['без стихии'] = 'без стихии',
            ['взрыв'] = 'взрыв',
            ['коррозия'] = 'коррозия',
            ['огонь'] = 'огонь',
            ['шок'] = 'шок',
            ['холод'] = 'холод',
            ['любая'] = { 'взрыв', 'коррозия', 'огонь', 'шок', 'холод' },
            ['любая или без стихии'] = { 'без стихии', 'взрыв', 'коррозия', 'огонь', 'шок', 'холод' },
            ['любая кроме взрыва'] = { 'коррозия', 'огонь', 'шок', 'холод' },
            ['любая кроме взрыва или без стихии'] = { 'без стихии', 'коррозия', 'огонь', 'шок', 'холод' },
            -- альтернативные стихии для разных игр
            ['холод.borderlands 2'] = 'шлак',-- не должно быть использовано, тк поглощено на этапе бл2
            ['холод.borderlands 3'] = { 'холод', 'радиация' },
            ['взрыв.borderlands 3'] = 'удар'
        }
    },
    ['borderlands 3'] = {
        elements = {
            ['без стихии'] = 'без стихии',
            ['взрыв'] = 'удар',-- переименован
            ['коррозия'] = 'коррозия',
            ['огонь'] = 'огонь',
            ['удар'] = 'удар',
            ['шок'] = 'шок',
            ['холод'] = 'холод',
            ['радиация'] = 'радиация',
            ['любая'] = { 'удар', 'коррозия', 'огонь', 'шок', 'холод', 'радиация' },
            ['любая или без стихии'] = { 'без стихии', 'удар', 'коррозия', 'огонь', 'шок', 'холод', 'радиация' },
            ['любая кроме взрыва'] = { 'коррозия', 'огонь', 'шок', 'холод', 'радиация' },
            ['любая кроме взрыва или без стихии'] = { 'без стихии', 'коррозия', 'огонь', 'шок', 'холод', 'радиация' },
            ['любая кроме удара'] = { 'коррозия', 'огонь', 'шок', 'холод', 'радиация' },
            ['любая кроме удара или без стихии'] = { 'без стихии', 'коррозия', 'огонь', 'шок', 'холод', 'радиация' },
            -- альтернативные стихии для разных игр
            -- тк игры перечисляются в порядке выхода
            --  следующие привязки не должны быть использованы
            --  тк они уже должны быть обработаны предыдущими версиями (бл2 и тпс)
            -- ['холод.borderlands 2'] = 'шлак',-- уже не приведёт к двойному шлаку при холод + радиация
            --  но ситуация с холодом-шлаком в бл3-бл2 пока не ясна
            ['радиация.borderlands 2'] = 'шлак',
            ['радиация.borderlands the pre-sequel'] = 'холод',
            -- взрыв был переименован в удар
            -- эта привязка здесь не нужна (поглощена предыдущими играми),
            --  но висит в качестве напоминания
            ['взрыв.borderlands'] = 'удар'
        }
    }
}

function p.getArgs(frame)
    -- собирает и нормализует аргументы
    -- возвращает таблицу вида {el: стихия, mainGame: основная игра, additionalGames: {игры}, t: тип}
    -- страховка для запуска из консоли (для отладки)
    if not frame.getParent then
        frame.getParent = function()end
    end
    local parent = frame:getParent() and frame:getParent() or frame
    local args = parent.args
    local ret = {}
    -- стихия
    ret.el = mw.ustring.lower(mw.text.trim(args['1'] or args[1] or ''))
    -- удаление запятых из стихии
    ret.el = table.concat(mw.text.split(ret.el, ','))
    if #mw.text.trim(ret.el) == 0 then
        -- стихию не прислали
        ret.el = nil
    end
    -- основная игра (первая в списке параметров)
    ret.mainGame = mw.ustring.lower(mw.text.trim(args['2'] or args[2] or ''))
    ret.mainGame = (#ret.mainGame > 0) and ret.mainGame or nil
    -- нормализация основной игры
    --  (вместо bl1 goty вернуть bl1 и тп, если такое возможно)
    ret.mainGame = d.games[ret.mainGame] and d.games[ret.mainGame] or ret.mainGame
    -- тип предмета
    ret.t = mw.ustring.lower(mw.text.trim(args['тип'] or ''))
    ret.t = (#ret.t > 0) and ret.t or nil
    -- есть ли ещё параметры?
    if args['3'] or args[3] then
        ret.additionalGames = {}
        for i = 3, 10 do
            local game = mw.ustring.lower(args[tostring(i)] or args[i] or '')
            game = (#game > 0) and game or nil
            -- если параметр есть и совпадает с именем игры, то добавить его в список игр
            if game then
                -- копия аргументов для передачи в dpl для полного default'a
                --  эти аргументы не должны перебираться через ipairs, так непоследовательны
                --  номера элементов унаследованы от шаблона
                ret[i] = game
                if d.games[game] then-- это точно игра, добавить в корзину
                    -- добавить под внутренним именем, а не под переданным
                    --  (вместо bl1 goty добавить bl1 и тп, если такое возможно)
                    table.insert(ret.additionalGames, d.games[game])
                end
            end
        end
    end
    return ret
end-- getArgs

function p.unique(t)
    -- удаляет из таблицы повторяющиеся записи
    local ret = {}
    local cache = {}
    for _, v in ipairs(t) do
        if not cache[v] then
            cache[v] = 1
            table.insert(ret, v)
        end
    end
    return ret
end-- unique

function p.isElementForbidden(element, typ, game)
    -- проверяет запрет стихии для типа предмета
    if (not element) or (not typ) or (not game) then
        return false
    end
    
    -- список запрещённый стихий для типа предмета
    local fe = d[game].forbiddenElements and d[game].forbiddenElements[typ] or nil
    if not fe then
        return false
    end

    fe = type(fe) == 'table' and fe or { fe }
    for _, el in pairs(fe) do
        if el == element then
            return true
        end
    end
    return false
end-- isElementForbidden

function p.t(name)
    -- ошаблониватель. возвращает {{name}}
    local ret = {}
    table.insert(ret, '{{')
    table.insert(ret, name)
    table.insert(ret, '}}')
    return table.concat(ret)
end-- t

function p.main(frame)
    local args = p.getArgs(frame)
    -- args.el: стихия
    -- args.mainGame: первая в списке игра
    -- args.additionalGames: список остальных игр (вторая и тд)
    -- args.t: тип предмета (щиты и тп)
    -- args[3] - args[10]: копия параметров для формирования умолчаний. унаследовано от шаблона
    
    -- если стихии нет в списке стихий или не указана игра, то вывалиться в дефолт
    if (not d.elements[args.el or '']) or (not args.mainGame) then
        local default = {}
        table.insert(default, '{{#dpl:debug=0|allowcachedresults=1|mode=userformat|ordermethod=titlewithoutnamespace')
        table.insert(default, '|includesubpages=false|count=1|namespace={{!}}10{{!}}14|title=')
        table.insert(default, args.el or 'без стихии')
        table.insert(default, '|format=,{{%PAGE%{{!}}')
        table.insert(default, args[5] or '')-- номера аргументов унаследованы от шаблона; зобыл, что они значат и где
        table.insert(default, '{{!}}')
        table.insert(default, args[6] or '')
        table.insert(default, '{{!}}')
        table.insert(default, args[7] or '')
        table.insert(default, '}}')
        table.insert(default, ',|noresultsheader=')
        table.insert(default, args.el or '')
        table.insert(default, '}}')
        default = table.concat(default)
        return frame.preprocess and frame:preprocess(default) or default
    end-- default
    
    -- упрощённый алгоритм:
    -- взять список стихий из d[игра].elements[стихия]
    -- пройтись по списку стихий
    --  подставить стихии, в том числе из других игр (с1 / с2),
    --      проверяя заигноренность (с учётом игры) типа
    --      подстановка стихий через отдельную таблицу
    --      вычистить повторы и собрать таблицу
    -- собрать вывод
    local ret = {}-- ret values
    
    local elements = d[args.mainGame].elements-- таблица стихий основной игры
    local element = elements[args.el]-- запрошенный элемент
    
    -- элемент может быть и списком элементов
    element = type(element) == 'table' and element or { element }
    
    -- пройтись по списку элементов и собрать их в кучу
    for _, elem in ipairs(element) do
        local elems = {}-- промежуточный список стихий
    
        -- если стихия разрешена в этой игре для этого типа предметов, то можно добавлять
        if not p.isElementForbidden(elem, args.t, args.mainGame) then
            elems = { p.t(elem) }
        end
    
        -- добавить стихии из других игр
        for _, game in ipairs(args.additionalGames or {}) do
            local e = elements[ elem .. '.' .. game ]-- замещающие стихии (холод для шлака и тп)
            if e then
                e = type(e) == 'table' and e or { e }
    
                -- добавить доп стихии
                for _, v in ipairs(e) do
                    -- добавлять только те стихии, что не запрещены
                    if not p.isElementForbidden(v, args.t, game) then
                        table.insert(elems,  p.t(v))-- здесь стихия превращается в шаблон
                    end
                end
            end
        end-- additionalGames
    
        -- убрать дубли (шлак+холод+радиация+холод)
        elems = p.unique(elems)
    
        -- если здесь много стихий из разных игр, то отформатировать: ( стихия / стихия)
        --  скобки и пробелы в соответствии с Тема:155691
        if #elems > 1 then
            elems = '( ' .. table.concat(elems, ' / ') .. ')'
        else
            -- массив стихий может быть пустым, если стихия запрещена
            elems = (#elems > 0) and elems[1] or nil
        end
        
        -- добавить стихию в выходной массив
        if elems then
            table.insert(ret, elems)
        end
    end-- element

    ret = table.concat(ret, ' ')
    return frame.preprocess and frame:preprocess(ret) or ret
end-- main

return p
Advertisement