Actions

Actions are what allow you to do things in the game. This can span from moving your character around in the game world, to using an item, or to attacking a creature and everything in between.

Embracing the Action Queue

As a default mechanism, actions are enqueued in the ActionQueue. This queue is universally shared across all scripts, preventing conflicts that might arise from multiple scripts trying to execute actions concurrently. By default, the queue employs self-regulating action priorities, enabling automatic prioritization of actions like healing. However, you retain the capability to manually adjust priorities for specific actions as needed. For detailed insights into overriding priorities, refer to Action Priorities further down this page.

Tip

While it is feasible to bypass this queue, it's generally not advisable. If you're considering bypassing it, read into the Advanced Action Queue Usage documentation.

One key advantage of utilizing the action queue is its capacity to detect temporary failures or timeouts inherent to actions, thereby allowing actions to automatically retry themselves. Customizing this retry behavior on a per-action basis is facilitated through Action Options.

Adding actions to the queue

Several methods exist for adding actions to the queue. The simplest approach involves employing the ClientActions interface, which provides centralized access to all supported client actions. To illustrate, let's create a fellowship using this interface.

  1. Open the HelloWorld script from Creating your first script.
  2. Replace the script's contents with the following code snippet:
game.Actions.FellowCreate("My Fellowship")

The ClientActions.FellowCreate(name,shareExperience,options,callback) action creates a new fellowship with the provided name. Upon executing the modified HelloWorld script, a fellowship named My Fellowship should be promptly created. It's important to note that this will only succeed if you're not already a member of a fellowship. The Checking the results of an action section will go into more detail on checking the action for failure or success.

An alternative to using the ClientActions interface is to create the action and manually add it to the queue. We can accomplish the same as above with the following:

local myCreateFellowAction = FellowCreateAction.new("My Fellowship")
game.ActionQueue.add(myCreateFellowAction)

This does the exact same thing as our first script, we just created the FellowCreateAction and added it to the queue manually with ActionQueue.Add(action). This method of creating actions will be useful later, when we are grouping actions.

Action options

When calling or creating an action, you are able to pass it a set of options to change its default behavior. For example you can give it a custom priority, change its default timeout, or change the max retry count. Lets create the same action as above, but this time we'll give it a custom priority and change the maximum number of retries.

local options = ActionOptions.new()
options.priority = 50000
options.maxRetryCount = 1
game.Actions.FellowCreate("My Fellowship", true, options)

This time when we call ClientActions.FellowCreate(name,shareExperience,options,callback), we pass the second argument that sets shareExperience, and a third argument with custom options. The custom options uses a max retry count of 1, and sets the priority to 50000 (see Action priorities for more information about how priorities work).

You can also pass custom options when creating an action manually:

local options = ActionOptions.new()
options.timeoutMilliseconds= 5000
local myCreateFellowAction = FellowCreateAction.new("My Fellowship", true, options)
game.actionQueue.add(myCreateFellowAction)

The above creates a new FellowCreateAction with the specified ActionOptions and adds it to the queue manually with ActionQueue.Add(action).

Checking the results of an action using callbacks

Of course when you perform an action, you probably want to be notified of if it completed, and when. You can do that by using callbacks or awaiting the results. Lets see how callbacks work first. Replace the contents of your script with the following:

game.Actions.FellowCreate("My Fellowship", true, nil, function(action)
  if action.Success then
    print("Successfully created a fellowship called:", action.FellowshipName)
  else
    print("Unable to create a fellowship!", action.Error, ":", action.ErrorDetails)
  end
end)

In the above, we passed nil for options which uses the defaults, and as a fourth parameter we passed a function to be called when the action is completed. Callbacks get passed the action that generated them, so in our case the action parameter in our callback function is a FellowCreateAction. We can check the QueueAction.Success property and print the results or error accordingly. We are able to see what error occurred by checking QueueAction.Error.

Tip

Some errors will provide more details in QueueAction.ErrorDetails. Be sure to check out the api docs to see what properties are available on each action.

Try running the script twice. The first time (assuming you aren't in a fellowship), it should print a success message. The second time you run the script it should fail because you are already in a fellowship.

Awaiting the results of an action

As an alternative to using the callback pattern, we can also use a special function called await that will pause the currently executing chunk of the script until the action is completed.

Tip

Although the current block of code has its execution paused when using await, event handlers for your script will continue to run in the background. It does not pause the entire execution of the script, just the currently scoped block.

-- using await here pauses the execution of the current script block
local result = await(game.Actions.FellowCreate("My Fellowship"))
-- this print does not get called until the action has completed
print(result)

Grouping actions

There is a special action called RunAllOrderedAction that allows running a grouped set of actions in the specified order. This action groups up its child actions into a single action and makes sure to run them in the order passed, regardless of priority. This will also ensures that no other actions will run until the entire set is completed (or errors out along the way). Here's an example grouped action that creates a fellowship and then sets the fellowship open status to false:

local myActions = {
  FellowCreateAction.new("My Fellowship"),
  FellowSetOpenAction.new(false)
}
print(await(game.Actions.RunAllOrdered(myActions)))

This is handy for making sure that the passed set of actions maintains a custom order without messing with priorities, as well as preventing other actions from interrupting this action group. Grouped actions are treated like a singular action, so once it starts running it will only complete once all child actions have completed, or an action in the group fails.

Inspecting the queue

You can inspect the current queue by looking at ActionQueue.Queue or for immediate actions, ActionQueue.ImmediateQueue. For example, here's how you would loop through and print out each action currently in the queue:

for action in game.ActionQueue.Queue do
  print(action)
end

Removing actions from the queue

You can remove an action from the queue manually with ActionQueue.Remove(action). For example:

-- create a new action
local myCreateFellowAction = FellowCreateAction.new("My Fellowship")
-- add the action to the queue
game.ActionQueue.add(myCreateFellowAction)
-- remove the action from the queue
game.ActionQueue.remove(myCreateFellowAction)