跳到正文
Hiveworkshop· Forsakn·· 3 小时前AI 评分10

DialogUtils

DialogUtils

AI 导读

Forsakn 开发的 DialogUtils 1.1.1 是一款可随时预定义与显示/隐藏原生暴雪对话框的 Lua 脚本库。该库采用面向对象 API,通过 DialogUtils.create 生成 DialogData 实例,并借 addButton、show、hide 方法按玩家 ID 或全体控制对话框显示与隐藏。

正文

Lua:

--[[
* DialogUtils 1.1.1 by Forsakn
*
* DialogUtils provides an easy way to predefine and show/hide native blizzard dialogs at will.
*
* API Functions:
**************************************************************
* The API only offers object-oriented notation. Colons are used after objects to access class-wide methods. Dots refer to attributes of the object itself, even when those are functions.
* ---------------
* | DialogUtils |
* ---------------
*        - This class at the time only has one purpose, to create new instances of the DialogData class.
*
*    DialogUtils.create(title)
*        - Returns a new DialogData instance
*        - Example:
*           local dialog = DialogUtils.create("DialogUtils test")
* --------------
* | DialogData |
* --------------
*        - This class holds on to dialog related data and provides functions for building/showing and hiding a native Blizzard dialog using that data.
*        - No static methods here, all methods must be called on an instance of DialogData, created via the DialogUtils.create method.
*
*    <DialogData>:addButton(text, callback, hotkeyId?)
*        - Adds a button to <DialogData>, this does not actually create a blizzard DialogButton but only adds data to the object for later use.
*        - The callback function has to provide one parameter, "player", this is the player who clicked the button.
*        - Returning true in the callback function will make the dialog stay open on click, useful for invalid choices.
*        - Example:
*           <DialogData>:addButton("button", function(player) print(GetPlayerName(player) end)
*
*    <DialogData>:show(player?)
*        - Builds and shows a blizzard Dialog adding all buttons added to <DialogData>.
*        - Internally the dialogs are indexed by player ID or -1 for a dialog thats shown to all players. Calling this function will destroy previous dialog at this index.
*        - Example:
*           <DialogData>:show() -- Shows the dialog to all players.
*           <DialogData>:show(Player(0)) -- Show the dialog only to red player.
*
*    <DialogData>:hide(player?)
*        - Hides the dialog created from calling <DialogData>:show from provided player.
*        - Example:
*           <DialogData>:hide() -- Hides the dialog from all players.
*           <DialogData>:hide(Player(0)) -- Hides the dialog from red player.
]]

do

    local dialogs = {}
    local dialogIdOccupier = {}
    local triggers = {}

    ----------------
    -- DialogData --
    ----------------

    ---@class dialogdata
    local DialogData = setmetatable({}, {})
    getmetatable(DialogData).__index = DialogData

    -- Define members (mostly to help with editor intellisense, will be overwritten on creation of DialogData)
    DialogData.title = ""
    DialogData.buttons = {}

    ---@param text string
    ---@param callback? function
    ---@param hotkeyId? integer
    function DialogData:addButton(text, callback, hotkeyId)
        table.insert(self.buttons, {text = text, callback = callback, hotkeyId = hotkeyId or 0})
    end

    ---@param player? player
    function DialogData:show(player)
        local dialogId = GetPlayerId(player) or -1
        player = player or GetLocalPlayer()

        -- Destroy old dialog and create new
        if dialogs[dialogId] then
            DialogDestroy(dialogs[dialogId])
        end
        dialogs[dialogId] = DialogCreate()
        local dialog = dialogs[dialogId]

        -- Destroy old trigger
        if triggers[dialogId] then
            DestroyTrigger(triggers[dialogId])
        end

        -- Create new trigger and add buttons to dialog
        local t = CreateTrigger()
        TriggerRegisterDialogEvent(t, dialog)
        for i = 1, #self.buttons do
            local button = self.buttons[i]
            local dialogButton = DialogAddButton(dialog, button.text, button.hotkeyId)
            TriggerAddCondition(t, Condition(function ()
                if GetClickedButton() == dialogButton and button.callback then
                    local clickingPlayer = GetTriggerPlayer()
                    local keepAlive = button.callback(clickingPlayer) == true
                    DialogDisplay(clickingPlayer, dialog, keepAlive)
                end
            end))
        end
        triggers[dialogId] = t

        -- Display dialog to player
        DialogSetMessage(dialog, self.title)
        DialogDisplay(player, dialog, true)

        -- Set self as occupier of this dialog (Used for hiding)
        dialogIdOccupier[dialogId] = self
    end

    ---@param player? player
    function DialogData:hide(player)
        player = player or GetLocalPlayer()
        for id, data in ipairs(dialogIdOccupier) do
            if data == self then
                local dialog = dialogs[id]
                if dialog then
                    if GetLocalPlayer() == player then
                        DialogDisplay(player, dialog, false)
                    end
                end
            end
        end
    end

    -----------------
    -- DialogUtils --
    -----------------

    DialogUtils = {}

    ---@param title string
    ---@return dialogdata
    function DialogUtils.create(title)
        local dialogData = setmetatable({}, getmetatable(DialogData))
        dialogData.title = title
        dialogData.buttons = {}
        return dialogData
    end

end

来源:Hiveworkshop · hiveworkshop.com