evolve
商店/共享库

menu_form

Splits a top group into its main rows and an "Advanced" list.

hunnyc0 个脚本在用
支持源码公开
在脚本中使用
pack.json
"requires": { "menu_form": "^1.0" }
你的 lua
local menu_form = require("lib/menu_form")

玩家无需安装:脚本会自动带上库,取范围内的任一版本。发布前可在开发会话中修改 scripts/lib/menu_form/ 来试验。

API
menu_form.tracker(): MenuTracker#

which rows moved by hand, against a snapshot. a config load has no event, so what moved

返回
MenuTracker

with the menu closed, or in a batch of 5+ between two looks, goes into the snapshot.

menu_form.page(tab: string, top: string): MenuPage#

the page of a top group; the same object on a second call

参数
tab string
top string first segment of the group path
返回
MenuPage
menu_form.toggle(id: string)#

switch a page between its main rows and its advanced list

参数
id string "tab.top"
menu_form.toggle_fine(id: string, sid: string)#

switch a page between its main rows and one section's list (Page:fine)

参数
id string "tab.top"
sid string
menu_form.apply()#

bring every page in line; run after a menu rebuild

menu_form.tick()#

per frame. a click in the menu fires no on_change, so values are polled, part of the rows

each frame with the menu open. a list stays open over a menu close: the sub-page the player stood on lives in it

menu_form.release()#

give every hidden row back: the script that owns the pages is going away. a reload takes

the controls with it, so no handle is kept; the next apply finds or makes them again

MenuTracker

字段
base: table
MenuTracker.see(key: string, c: userdata)#

first sight of a row: its value goes into the snapshot

参数
key string
c userdata
MenuTracker.touched(key: string, c: userdata): boolean#

true when the row differs from the snapshot

参数
key string
c userdata
返回
boolean
MenuTracker.poll(open: boolean): table?#

one whole look; once on close, or often with few rows

参数
open boolean the menu is open
返回
table? key -> value
MenuTracker.step(n: integer): table?#

part of a look, for a frame: a look at every row of every hero is a hitch

参数
n integer rows
返回
table? key -> value, when the look ended here

MenuPage

MenuPage.advanced(group: string, label: string): MenuPage#

mark a row as advanced. rows of subgroups go here too: the list swaps the whole top group

参数
group string full group path in the tab
label string the row's store label
返回
MenuPage
MenuPage.advanced_rest(): MenuPage#

every row of the page goes to the list, a row added later too, except what main names.

返回
MenuPage

for a page where the main rows are the short list

MenuPage.main(group: string, label?: string): MenuPage#

a main row of an advanced_rest page. without a label: every row of the group

参数
group string full group path in the tab
label string
返回
MenuPage
MenuPage.reset_main(): MenuPage#

forget every main row named so far: for a page whose owner lays it out again

返回
MenuPage
MenuPage.fine(sid: string, keys: string[], opts?: {group?: string, order?: integer, back_order?: integer, head?: string, back?: string}): MenuPage#

a section's own list: its rows leave the page for a button at the section's end ("Fine

参数
sid string section id, unique on the page
keys string[] group .. "\0" .. label of each row
opts {group?: string, order?: integer, back_order?: integer, head?: string, back?: string}
返回
MenuPage

tuning · N"), which swaps the page to the head of the section and these rows, and back. the page's advanced list does not count them. a second call with the same id replaces the rows group: where the button lives (default the top group); order: its draw order, back_order while the list is open; head: a row kept in view while the list is open; back: the page name its back caption prints

MenuPage.quiet(fn: fun(key: string): boolean): MenuPage#

rows whose value something else wrote: a move of theirs is not a hand

参数
fn fun(key: string): boolean key = group .. "\0" .. label
返回
MenuPage
介绍

lib/menu_form

Splits a top group into its main rows and an "Advanced" list. A button at the bottom of the group swaps the page to the advanced rows and back; the list stays open over a menu close. Config keys and values do not change. Hidden rows stay in search. Built on ui.group_controls, ui.reference, ui.button, c:visible, c:findable, c:is_default, so any pack can use it. uTEA's tables are utea/core/menu_view_data.lua (outside the heroes) and utea/core/menu_view_heroes.lua (hero pages), both generated (#555).

local Form = require("lib/menu_form")
local P = Form.page("Misc", "my pack")
P:advanced("my pack", "Retry delay")
P:advanced("my pack.Fine", "Sample rate")    -- rows of subgroups are named by their full group
Form.apply()                                 -- after building the menu, and after a rebuild
-- once a frame, also before a game starts:
Form.tick()
-- on unload:
Form.release()

A page where the main rows are the short list names those instead, and every other row, a later one too, goes to the list:

Form.page("Combo", "Heroes.Axe"):advanced_rest()
    :main("Heroes.Axe", "1. Call")            -- one row
    :main("Heroes.Axe.Combo editor")          -- every row of a group, made at runtime or not
    :quiet(function(key) return styled[key] end)   -- key = group .. "\0" .. label

quiet names rows something else writes: their move does not keep them on the page and is not counted on the button.

A page with no marked rows gets no button. A row whose owner hid it stays hidden, and is not counted on the button. In the list a main row stays when a list row is numbered under it (1. for 1.1, and 1. and 1.1 for 1.1.1): it is the heading of their card.

What stays on the main page although it is marked advanced:

row why
value changed by hand this launch the player sees what they did
bound hotkey the Keys page lists shown hotkeys only

A value that came from a config stays in the list and is counted on the button ("Advanced · 12 · changed 3"). The api has no config-load event, so M.tracker() tells the two apart: what moved with the menu closed, or in a batch of 5+ rows in one look, goes into the snapshot. A look takes 400 rows a frame (t:step(n)), so 6000 rows are 15 frames. A second consumer of the same rule can use the tracker alone: t:see(key, c), t:touched(key, c), t:step(n), t:poll(menu_open).

A page laid out in sections gives each section its own list (Page:fine, #651). Its rows leave the page and the "Advanced" count for a button at the end of the section, "Fine tuning · N"; a press shows the section's head row and these rows only, with the button turned into the way back. reset_main() forgets the main rows named so far, for an owner that lays the page out again:

Form.page("Combo", "Heroes.Pudge"):reset_main():main("Heroes.Pudge", "1. Meat Hook")
    :fine("1", { "Heroes.Pudge\0" .. "1.1 Hook lead (%)" },
          { group = "Heroes.Pudge", order = 1900, back_order = 999,
            head = "Heroes.Pudge\0" .. "1. Meat Hook", back = "Pudge" })

The "Advanced" button then shows only while a row is left outside every section list.

The list is one page of the same group: subgroups stay tabs, because a row's group is part of its config key, unless the owner draws them on the parent page (ui.group_meta(tab, group, { inline = true })). A subgroup with no row shown has no tab on that page.

Test: tools\lua\lua.exe scripts\lib\menu_form\selftest.lua from the repo root.

源码

1.2.0 版本的代码,即客户端拿到的内容。包内字节码由这些文件编译而来。

init.lua507 行
--- lib/menu_form -- a group's main rows on its page, the rest in a separate "Advanced" list (#555).
--- the page stays one level: a button at the bottom swaps the group to its advanced rows and
--- back, no row unfolds in place. config keys and values do not move. a hidden row stays in
--- search. a row the player changed by hand stays on the main page; a value that came from a
--- config does not, it is counted on the button. built on open calls only, any pack can use it.
do
    local g = rawget(_G, "__EVOLVE_LIB_REG")
    if g and g.menu_form then return g.menu_form end
end

local M = {}

local BTN = "Advanced settings"    -- the button's store label, a button has no config key
local ORDER = 1000100              -- after menu_fine's rows
local STEP = 400                   -- rows looked at per frame, menu open: 127 heroes are 5000+ rows
local MASS = 5                     -- rows moved between two looks: not a hand, a config load
local TXT = {
    en = { n = "Advanced · %d", ch = "Advanced · %d · changed %d", back = "Back to main settings",
           hint = "Thresholds and exceptions. A value you change here stays on the main page until the next launch",
           back_hint = "The main settings of this group" },
    ru = { n = "Расширенные · %d", ch = "Расширенные · %d · изменено %d", back = "Назад к основным",
           hint = "Пороги и исключения. Значение, которое вы здесь поменяете, останется на основной странице до следующего запуска",
           back_hint = "Основные настройки этой группы" },
    zh = { n = "高级 · %d", ch = "高级 · %d · 已更改 %d", back = "返回主要设置",
           hint = "阈值和例外。在这里更改的值会留在主页面,直到下次启动",
           back_hint = "此分组的主要设置" },
}
-- a section's own list (Page:fine)
local FINE = "Fine tuning · "      -- + section id, a button's store label
local FTXT = {
    en = { n = "Fine tuning · %d", ch = "Fine tuning · %d · changed %d", back = "‹ Back to %s",
           hint = "Thresholds of this section. A value you change here stays in view until the next launch" },
    ru = { n = "Тонкая настройка · %d", ch = "Тонкая настройка · %d · изменено %d", back = "‹ Назад к %s",
           hint = "Пороги этой секции. Значение, которое вы здесь поменяете, останется на виду до следующего запуска" },
    zh = { n = "微调 · %d", ch = "微调 · %d · 已更改 %d", back = "‹ 返回 %s",
           hint = "此部分的阈值。在这里更改的值会一直显示,直到下次启动" },
}

local reg = rawget(_G, "__EVOLVE_LIB_REG") or {}
rawset(_G, "__EVOLVE_LIB_REG", reg)
-- survives a reload of this file: pages hold what they hid
local ST = reg.menu_form_state or { pages = {}, list = {}, of = {} }
reg.menu_form_state = ST

local function call(c, name, ...)
    local ok, v = pcall(function(...) return c[name](c, ...) end, ...)
    if ok then return v end
end

local function lang()
    local ok, l = pcall(ui.menu_lang)
    return ok and TXT[l] and l or "en"
end

local function menu_open()
    local ok, v = pcall(ui.menu_open)
    return not ok or v ~= false
end

-- what a row holds, as one string
local function value_of(c)
    local t = call(c, "type")
    -- a hotkey's get is "held now", its binding only shows through is_default
    if t == "hotkey" then return tostring(call(c, "is_default")) end
    if t == "button" or t == "label" then return "" end
    local v = call(c, "get")
    local tv = type(v)
    if tv == "table" then
        local p = {}
        for k, x in pairs(v) do p[#p + 1] = tostring(k) .. "=" .. tostring(x) end
        table.sort(p)
        return table.concat(p, ",")
    end
    if tv == "userdata" then
        local ok, s = pcall(function() return v.r .. "," .. v.g .. "," .. v.b .. "," .. v.a end)
        return ok and s or tostring(call(c, "is_default"))
    end
    return tostring(v)
end

---@class MenuTracker
---@field base table
local Tracker = {}
Tracker.__index = Tracker

--- which rows moved by hand, against a snapshot. a config load has no event, so what moved
--- with the menu closed, or in a batch of 5+ between two looks, goes into the snapshot.
---@return MenuTracker
function M.tracker()
    return setmetatable({ base = {}, last = {}, rows = {}, order = {}, moved = {}, n = 0, at = 0, open = false }, Tracker)
end

--- first sight of a row: its value goes into the snapshot
---@param key string
---@param c userdata
function Tracker:see(key, c)
    if not self.rows[key] then self.order[#self.order + 1] = key end
    self.rows[key] = c
    if self.base[key] == nil then
        local v = value_of(c)
        self.base[key], self.last[key] = v, v
    end
end

--- true when the row differs from the snapshot
---@param key string
---@param c userdata
---@return boolean
function Tracker:touched(key, c)
    local b = self.base[key]
    return b ~= nil and value_of(c) ~= b
end

local function look(self, key)
    local v = value_of(self.rows[key])
    if v ~= self.last[key] then
        self.moved[key] = v
        self.n = self.n + 1
        self.last[key] = v
    end
end

-- a look is over: what moved in it goes to the snapshot, or stays a hand change
local function settle(self, open)
    local moved = self.moved
    if not self.open or self.n >= MASS then
        for key, v in pairs(moved) do self.base[key] = v end
    end
    self.moved, self.n, self.at, self.open = {}, 0, 0, open
    return moved
end

--- one whole look; once on close, or often with few rows
---@param open boolean the menu is open
---@return table? moved key -> value
function Tracker:poll(open)
    if not open and not self.open then return end
    for i = self.at + 1, #self.order do look(self, self.order[i]) end
    return settle(self, open)
end

--- part of a look, for a frame: a look at every row of every hero is a hitch
---@param n integer rows
---@return table? moved key -> value, when the look ended here
function Tracker:step(n)
    local total = #self.order
    local to = math.min(self.at + n, total)
    for i = self.at + 1, to do look(self, self.order[i]) end
    self.at = to
    if to >= total then return settle(self, true) end
end

-- a script reload took the controls: handles go, what was the snapshot stays
local function forget(self)
    self.rows, self.order, self.moved, self.n, self.at, self.open = {}, {}, {}, 0, 0, false
end

ST.tracker = ST.tracker and setmetatable(ST.tracker, Tracker) or M.tracker()
local T = ST.tracker

local function ref(tab, group, label)
    local ok, c = pcall(ui.reference, tab, group, label)
    if not (ok and c) then return nil end
    -- a miss is an empty handle, not nil
    if call(c, "type") == "none" or call(c, "label") == "" then return nil end
    return c
end

local function fine_caption(P, F)
    if not F.btn then return end
    local X = FTXT[lang()]
    if P.open_sid == F.sid then
        call(F.btn, "caption", string.format(X.back, F.back or P.top))
    else
        call(F.btn, "caption", F.changed > 0 and string.format(X.ch, F.n, F.changed) or string.format(X.n, F.n))
    end
    call(F.btn, "hint", X.hint)
end

local function caption(P)
    for _, F in pairs(P.fines or {}) do fine_caption(P, F) end
    if not P.btn then return end
    local X = TXT[lang()]
    if P.open then
        call(P.btn, "caption", X.back)
        call(P.btn, "hint", X.back_hint)
    else
        call(P.btn, "caption", P.changed > 0 and string.format(X.ch, P.n, P.changed) or string.format(X.n, P.n))
        call(P.btn, "hint", X.hint)
    end
end

local function hide(P, key, c)
    local h = P.hid[key]
    if h then
        h.c = c     -- may be a new control under the old key
        call(c, "visible", false)
        call(c, "findable", true)
        return
    end
    local info = call(c, "info")
    -- a row its owner hid stays the owner's
    if type(info) == "table" and info.visible == false then return end
    call(c, "visible", false)
    P.hid[key] = { c = c, findable = type(info) == "table" and info.findable == true }
    call(c, "findable", true)   -- off the page, not out of reach
end

local function show(P, key, c)
    local h = P.hid[key]
    if not h then return end
    call(c, "visible", true)
    call(c, "findable", h.findable)
    P.hid[key] = nil
end

-- asks the menu every time: a handle from before a reload still reads, the control is gone
local function ensure_button(P)
    local b = ref(P.tab, P.top, BTN)
    if not b then
        local id = P.id
        local ok, made = pcall(ui.button, P.tab .. "." .. P.top, BTN, function()
            local r = rawget(_G, "__EVOLVE_LIB_REG")
            if r and r.menu_form then r.menu_form.toggle(id) end
        end)
        b = ok and made or nil
    end
    if b then call(b, "order", ORDER) end
    P.btn = b
end

local function ensure_fine_button(P, F)
    local b = ref(P.tab, F.group, FINE .. F.sid)
    if not b then
        local id, sid = P.id, F.sid
        local ok, made = pcall(ui.button, P.tab .. "." .. F.group, FINE .. F.sid, function()
            local r = rawget(_G, "__EVOLVE_LIB_REG")
            if r and r.menu_form then r.menu_form.toggle_fine(id, sid) end
        end)
        b = ok and made or nil
    end
    if b then
        call(b, "order", F.order)
        call(b, "indent", 1)
    end
    F.btn = b
end

---@class MenuPage
local Page = {}
Page.__index = Page

--- the page of a top group; the same object on a second call
---@param tab string
---@param top string first segment of the group path
---@return MenuPage
function M.page(tab, top)
    local id = tab .. "." .. top
    local P = ST.pages[id]
    if not P then
        P = { id = id, tab = tab, top = top, adv = {}, keep = {}, keep_group = {}, hid = {},
              open = false, n = 0, changed = 0 }
        ST.pages[id] = P
        ST.list[#ST.list + 1] = P
    end
    return setmetatable(P, Page)
end

--- mark a row as advanced. rows of subgroups go here too: the list swaps the whole top group
---@param group string full group path in the tab
---@param label string the row's store label
---@return MenuPage
function Page:advanced(group, label)
    self.adv[group .. "\0" .. label] = true
    return self
end

--- every row of the page goes to the list, a row added later too, except what main names.
--- for a page where the main rows are the short list
---@return MenuPage
function Page:advanced_rest()
    self.rest = true
    return self
end

--- a main row of an advanced_rest page. without a label: every row of the group
---@param group string full group path in the tab
---@param label? string
---@return MenuPage
function Page:main(group, label)
    if label then self.keep[group .. "\0" .. label] = true else self.keep_group[group] = true end
    return self
end

--- forget every main row named so far: for a page whose owner lays it out again
---@return MenuPage
function Page:reset_main()
    self.keep, self.keep_group = {}, {}
    return self
end

--- a section's own list: its rows leave the page for a button at the section's end ("Fine
--- tuning · N"), which swaps the page to the head of the section and these rows, and back. the
--- page's advanced list does not count them. a second call with the same id replaces the rows
---@param sid string section id, unique on the page
---@param keys string[] group .. "\0" .. label of each row
---@param opts? {group?: string, order?: integer, back_order?: integer, head?: string, back?: string}
--- group: where the button lives (default the top group); order: its draw order, back_order while
--- the list is open; head: a row kept in view while the list is open; back: the page name its
--- back caption prints
---@return MenuPage
function Page:fine(sid, keys, opts)
    opts = opts or {}
    self.fines = self.fines or {}
    self.fine_of = self.fine_of or {}
    local F = self.fines[sid]
    if F then for k in pairs(F.keys) do if self.fine_of[k] == sid then self.fine_of[k] = nil end end end
    F = F or { sid = sid, n = 0, changed = 0 }
    F.keys, F.group, F.order, F.head, F.back = {}, opts.group or self.top, opts.order or ORDER - 1, opts.head, opts.back
    F.back_order = opts.back_order or F.order
    for _, k in ipairs(keys or {}) do F.keys[k] = true; self.fine_of[k] = sid end
    self.fines[sid] = F
    return self
end

--- rows whose value something else wrote: a move of theirs is not a hand
---@param fn fun(key: string): boolean key = group .. "\0" .. label
---@return MenuPage
function Page:quiet(fn)
    self.is_quiet = fn
    return self
end

-- the Keys page lists shown hotkeys only: a bound key off the page would drop out of it
local function bound(c)
    return call(c, "type") == "hotkey" and call(c, "is_default") == false
end

local function stays(P, key, c)
    if T:touched(key, c) and not (P.is_quiet and P.is_quiet(key)) then return true end
    return bound(c)
end

-- "1.2.1 Net worth" -> "1.2.1"; "1. Call" -> "1"
local function number_of(label)
    local n = label:match("^(%d[%d%.]*)%s")
    return n and (n:gsub("%.$", "")) or nil
end

local function apply_page(P)
    local ok, list = pcall(ui.group_controls, P.tab, P.top, true)
    if not ok or type(list) ~= "table" then return end
    local fine_of, fine = P.fine_of or {}, P.fines or {}
    if P.open_sid and not fine[P.open_sid] then P.open_sid = nil end
    local rows, heads, any, left = {}, {}, false, false
    for _, c in ipairs(list) do
        local l = call(c, "label")
        if l and l ~= BTN and l:sub(1, #FINE) ~= FINE then
            local g, name = tostring(call(c, "group")), tostring(l)
            local key = g .. "\0" .. name
            local num = number_of(name)
            local adv = P.adv[key]
            if P.rest and not P.keep[key] and not P.keep_group[g] then adv = true end
            local sid = adv and fine_of[key] or nil
            if adv then
                any = true
                T:see(key, c)
                ST.of[key] = P
                if not sid then
                    left = true
                    -- every number above it is a heading in the list
                    local up = num
                    while up do
                        up = up:match("^(.*)%.%d+$")
                        if up then heads[g .. "\0" .. up] = true end
                    end
                end
            end
            rows[#rows + 1] = { key = key, c = c, adv = adv, fine = sid, head = num and g .. "\0" .. num }
        end
    end
    if not any then return end
    -- no way to the rows: leave them where they are
    if left or P.open then
        ensure_button(P)
        if not P.btn then return end
    else
        P.btn = ref(P.tab, P.top, BTN)
    end
    for _, F in pairs(fine) do
        if next(F.keys) then ensure_fine_button(P, F) else F.btn = nil end
        F.n, F.changed = 0, 0
    end
    local open_head = P.open_sid and fine[P.open_sid].head
    local count, changed = 0, 0
    for _, r in ipairs(rows) do
        local want
        if P.open_sid then
            want = r.fine == P.open_sid or r.key == open_head
        elseif P.open then
            -- a main switch heads its advanced rows, they have no card without it
            want = (r.adv and not r.fine) or (r.head and heads[r.head])
        else
            want = not r.adv or stays(P, r.key, r.c)
        end
        if want then show(P, r.key, r.c) else hide(P, r.key, r.c) end
        if r.adv then
            local info = call(r.c, "info")
            local here = P.hid[r.key] or (type(info) == "table" and info.visible ~= false)
            local ch = call(r.c, "is_default") == false and not (P.is_quiet and P.is_quiet(r.key))
            local F = r.fine and fine[r.fine]
            if F then
                if here then F.n = F.n + 1 end
                if ch then F.changed = F.changed + 1 end
            else
                if here then count = count + 1 end
                if ch then changed = changed + 1 end
            end
        end
    end
    P.n, P.changed = count, changed
    if P.btn then call(P.btn, "visible", P.open or (not P.open_sid and count > 0)) end
    for _, F in pairs(fine) do
        if F.btn then
            local mine = P.open_sid == F.sid
            call(F.btn, "visible", mine or (not P.open_sid and not P.open and F.n > 0))
            -- the way back stands above the section: a folded card would hide it
            call(F.btn, "order", mine and F.back_order or F.order)
            call(F.btn, "indent", mine and 0 or 1)
        end
    end
    caption(P)
end

--- switch a page between its main rows and its advanced list
---@param id string "tab.top"
function M.toggle(id)
    local P = ST.pages[id]
    if not P then return end
    P.open = not P.open
    P.open_sid = nil
    apply_page(P)
end

--- switch a page between its main rows and one section's list (Page:fine)
---@param id string "tab.top"
---@param sid string
function M.toggle_fine(id, sid)
    local P = ST.pages[id]
    if not P then return end
    P.open_sid = P.open_sid ~= sid and sid or nil
    P.open = false
    apply_page(P)
end

--- bring every page in line; run after a menu rebuild
function M.apply()
    for _, P in ipairs(ST.list) do apply_page(P) end
end

-- pages that hold a row that moved
local function redraw(moved)
    if not moved or next(moved) == nil then return end
    local done = {}
    for key in pairs(moved) do
        local P = ST.of[key]
        if P and not done[P] then done[P] = true; apply_page(P) end
    end
end

--- per frame. a click in the menu fires no on_change, so values are polled, part of the rows
--- each frame with the menu open. a list stays open over a menu close: the sub-page the player
--- stood on lives in it
function M.tick()
    if not menu_open() then
        if ST.was_open then
            ST.was_open = false
            redraw(T:poll(false))
        end
        return
    end
    ST.was_open = true
    redraw(T:step(STEP))
    local L = lang()
    if L ~= ST.lang then
        ST.lang = L
        for _, P in ipairs(ST.list) do caption(P) end
    end
end

--- give every hidden row back: the script that owns the pages is going away. a reload takes
--- the controls with it, so no handle is kept; the next apply finds or makes them again
function M.release()
    for _, P in ipairs(ST.list) do
        for key, h in pairs(P.hid) do show(P, key, h.c) end
        P.open, P.btn, P.open_sid = false, nil, nil
        for _, F in pairs(P.fines or {}) do F.btn = nil end
    end
    forget(T)
end

M.BTN = BTN
M.FINE = FINE

reg.menu_form = M
return M
pack.json2 行
{ "kind": "lib", "version": "1.2.0" }
更新日志

这个作品没有版本说明。

使用它的脚本

还没有已发布的脚本需要它。

该作者的其他作品

该作者的其他作品

escape

作者 hunnyc

How many seconds a unit dropped at a point stays out of reach of what saves him: his towers, his fountain, his heroes walking at him, and his heroes in the fog from where `lib/fog_seen` last put them

pack.json
"requires": { "escape": "^1.0" }
你的 lua
local escape = require("lib/escape")
0 个脚本在用还没有已发布的版本

config_defaults

作者 hunnyc

Moves a saved setting to a new default once, if it still holds the old one.

pack.json
"requires": { "config_defaults": "^1.0" }
你的 lua
local config_defaults = require("lib/config_defaults")
0 个脚本在用还没有已发布的版本

screen_presets

作者 hunnyc

Screen presets for what evolve draws: "minimum", "usual" and "everything" over the groups the menu lists under the "screen" category (sections over heroes, map, timers, panels; the camera section is l

pack.json
"requires": { "screen_presets": "^1.0" }
你的 lua
local screen_presets = require("lib/screen_presets")
0 个脚本在用还没有已发布的版本