AddOn Quick Questions/ru

From ESOUI Wiki

Jump to: navigation, search

Страница находится на стадии перевода!


Как мне установить аддон?

Как мне сохранить настройки на локальной машине?

Настройки аддона могут быть сохранены на локальной машине, используя переменные сохранения. Переменная сохранения, это таблица которую ваш аддон объявляет в своем txt файле. При загрузке вашего аддона, таблица создается в памяти, используя значения из файла сохранения. Когда ваш аддон выгружается, данные таблицы, из памяти сохраняются в файл на диске. Файл находится в Windows: Documents/Elder Scrolls Online/<build>/SavedVariables/<addonName>.lua, Mac: ~/Documents/Elder Scrolls Online/<build>/SavedVariables/<addonName>.lua. Для использования переменной сохранения:

## SavedVariables: MyAddOn_SavedVariables

В вашем коде инициализации:

EVENT_MANAGER:RegisterForEvent("MyAddOn", EVENT_ADD_ON_LOADED, OnAddOnLoaded)

В вашем коде обработчика события:

local function OnAddOnLoaded(eventCode, addOnName)
    if(addOnName == "<<your add-on's name>>") then
        --create the saved variable here.
local savedVars = ZO_SavedVars:New(savedVariableName, version, namespace, defaults, profile)
local defaults =
    offsetX = 0,
    offsetY = 0,

Чтение и запись из переменной сохранения:

local offsetX = savedVars.offsetX
offsetX = 200
savedVars.offsetX = offsetX

Почему я не могу вызвать функции MoveForwardStart / TurnLeftStart ?

Некоторые из функций в lua-API помечены, как accessControl="private." Эти функции не могут быть вызваны и на них нельзя ссылаться в аддоне пол соображениям безопасности (боты?). Посмотрите на документацию по ESO UI, чтобы увидеть как accessControl устанавливается для функции. Если accessControl не был задан явно, то значит что он будет иметь тип public.

Is there a way to dynamically create controls like buttons or labels?

Controls can be created dynamically using the CreateControlFromVirtual function and a virtual template defined in XML. The template defines what the created control will look like and can be as complex as a normal control (with sub-controls, properties, etc).

<Button name="DynamicButton" virtual="true" text="Click">
        <Label name="$(parent)InnerLabel" text="Label" font="ZoFontGame">

To use the template we call CreateControlFromVirtual. It has the following arguments:

for i = 1, 10 do
    local dynamicControl = CreateControlFromVirtual("DynamicButton", MyAddOnWindow, "DynamicButton", i)

How do events work?

Events allow your add-on to be notified when a specific "event" happens in the game client. These events vary widely and include things like getting new inventory items, receiving chat messages, and accepting quests. You add-on is "notified" in the form of the game client running a function that you registered earlier on. For example, when the client receives a group invitation for the player, EVENT_GROUP_INVITE_RECEIVED is triggered, calling all functions that have registered to be notified of it. When the functions are ran, they may be passed arguments that offer more information about the event. The first argument is always eventCode which is a number identifying the event. In the case of EVENT_GROUP_INVITE_RECEIVED, the second argument is the name of the person that is inviting the player to the group. You can look up what arguments come with each event in the ESO UI Documentation files.

So how does this look in lua?

Event handler function

local function OnGroupInviteReceived(eventCode, inviterName)
    --print the inviter's name to chat

Register the event

function MyAddOn_OnInitialized(self)
    --Register on the top level control...
    self:RegisterForEvent(EVENT_GROUP_INVITE_RECEIVED, OnGroupInviteReceived)
    --OR, register with a string unique to your add-on
    EVENT_MANAGER:RegisterForEvent("MyAddOn", EVENT_GROUP_INVITE_RECEIVED, OnGroupInviteReceived)

You may also unregister events with the UnregisterEvent function.

How does screen resolution impact the UI?

To understand how the game lays out the UI we should start by talking about UI units. UI units are what you are specifying when you set the width, height, offsets, or any other positional values of a control. They are not the same as pixels and are based on aspect ratio instead of the resolution. The number of pixels that a UI unit actually represents varies based on the resolution of the player's screen. The reason why we use UI units is it allows up to guarantee that we have at least 1680 x 1050 UI unit space regardless of the player's resolution. This means that if we wanted to put a 1680 UI unit wide window into to game, it would fit on monitors from 1280 x 1024 pixels, to 2560 x 1980 pixels, to anything else. Lets look at some examples to see how UI units map to pixels in the game.

The above examples ignore one feature of the UI which is called global scale. This is the slider in the UI options that lets you make the UI larger or smaller. Global scale functions by changing the size of the canvas to impact the relative size of the windows. A small global scale makes the canvas bigger, which makes the windows seem smaller. A larger global scale makes the canvas smaller, which makes the windows seem bigger in comparison. For example, consider a 1000 x 1000 canvas with a 500 x 500 window centered in it. At a global scale of 0.5 the canvas becomes 2000 x 2000 (Original Canvas * (1 / Global Scale)). Whereas the 500 x 500 window used to be half the height and width (500 / 1000), it is now 25% of the height and width (500 / 2000).

What are Draw Level, Layer and Tier?

For a discussion of the difference between these control ordering settings see: Control Ordering

How do I generate my own "events" in Lua?

Lua uses ZO_CallbackObject to implement its own Lua-only event system. Instead of registering an event on a control or with EVENT_MANAGER, you register on an object or CALLBACK_MANAGER. Here's an example of using CALLBACK_MANAGER:


local function OnTrackStateChanged(questTracker, tracked, trackType, arg1, arg2)
    if tracked then
        d("A quest was tracked")
        d("A quest was untracked")
CALLBACK_MANAGER:RegisterCallback("QuestTrackerTrackingStateChanged", OnTrackStateChanged)


CALLBACK_MANAGER:FireCallbacks("QuestTrackerTrackingStateChanged", self, true, TRACK_TYPE_QUEST, 0)

You can choose any name you want for the event as long as it's unique. You can register or unregister as many callback functions are you want on any particular event.

You can also let your object be the callback registry. All you have to do is have it subclass ZO_CallbackObject instead of ZO_Object. For example:

MyObject = ZO_CallbackObject:Subclass()
function MyObject:New()
    return ZO_CallbackObject.New(self)
function MyObject:DoThing()
local obj = MyObject:New()
obj:RegisterCallback("ThingDone", OnThingDone)

Are there Keypress events that we can tie into?

If you want custom bindings (like in the keybinding window), you can make a bindings.xml file for your add-on and add them there. You can look at the bindings.xml files for examples. You will also need to make a string entry with the name "SI_BINDING_NAME_X" using ZO_CreateStringId("SI_BINDING_NAME_X", "My Custom Bind Name") where X is the name of the binding you added and it should appear in the bindings window. For example:

  <Layer name="SI_LAYER_NAME_STRING">
    <Category name="SI_CATEGORY_NAME_STRING">
      <Action name="TURN_RIGHT">


ZO_CreateStringId("SI_BINDING_NAME_TURN_RIGHT", "Turn Right")

You can choose to add sections for up, down, or both. The code in the section will be run each time the binding is activated (<Down> for key down and <Up> for key up).

You can also make a top level window keyboardEnabled="1" in the xml and it will eat up all keypress events when it’s shown. This is best used for when your window has a completely different use of the keyboard and you don't care that bindings aren't triggered. For example, if your wrote a Tetris add-on and wanted WASD to control the piece, keyboardEnabled can do it. The script handlers for keys are <OnKeyDown>, <OnKeyUp>, and <OnChar>. OnChar passes the key, while OnKeyUp and OnKeyDown pass the key, ctrl, alt, and shift arguments as booleans. Search ESO UI Documentation for KEY_ globals and you will find all the key definitions. For example, KEY_A, KEY_Z, KEY_ENTER, KEY_BACKSPACE. If you want to add controls for moving the tetris piece left and right you might do the following:

    if(key == KEY_A) then
        --Start Moving Piece Left
    elseif(key == KEY_D) then
        --Start Moving Piece Right
    if(key == KEY_A) then
        --Stop Moving Piece Left
    elseif(key == KEY_D) then
        --Stop Moving Piece Right

Can I add my own sound files to play with PlaySound()?

At the moment this is not possible.

Nothing seems to load from my Addon LUA file

Make sure the file end-of-line format is set to windows mode (\r\n) instead of linux mode (\n). It can silently ignore the file if you have the incorrect line ending.

Personal tools