Getting information about the game world
A global variable called
game is set for all scripts. Using it you are able to get information about the game world, and perform actions. You should view the API documentation for the Game class to get a deeper understanding of what information is available to your script. This is the main entry point for a script to talk to the game client.
[!NOTE] All running scripts get a unique instance of the Game class. This allows shutdown / error'ed scripts to get properly cleaned up when unloading, and generally keep scripts sandboxed from each other. Some things like the Action Queue, or Script Events are shared between scripts to allow them to work simultaneously with minimal effort.
Using the game global
Lets start by getting some basic information about our character. Log into the game and type the following command to get your character's object id:
/ub lexec return game.CharacterId
You should see something like the following in the chat window output, although your character Id will be different:
[UB] Evaluating script (context `Global`): "return game.characterId" [UB] Result: (Double) 1342204037 (0.036ms)
In our example above, we are getting the value stored in Game.CharacterId.
game is a global lua variable that is an instance of the Game object. CharacterId is a property stored on the Game object. Properties store values that can be read by our scripts.
[!TIP] When referencing the API Docs you will notice that method/event/property names will generally start with an uppercase letter, but the example above starts
characterIdwith a lowercase letter. When scripting in lua, you are able to lowercase the first letter of the method/event/property name and still have it match the API call. For more information, check out reading the API docs
Lets try getting another property on the Game object. This time we'll get the name of the server we are currently connected to.
/ub lexec return game.ServerName
You should see something like the following in the chat window output, although your server name may be different:
[UB] Evaluating script (context `Global`): "return game.serverName" [UB] Result: (String) My Asherons Call Server (0.035ms)
In Asheron's Call, every object you can interact with is what's known as a World Object (you may also see these referred to as Weenies). This includes all monsters, npcs, spell projectiles, doors, inventory items, your character, etc (if you can select it, it is a world object). It does not include things like trees. The World interface provides access to these world objects. You can access the World interface using the World property on the global
game variable, ie
Finding world objects
Lets use the World interface to get a list of all landscape world objects. Landscape objects are objects that don't have a parent / container, like monsters, portals, etc. Type the following into the ingame chatbox:
/ub lexec return game.World.GetLandscape()
You should see something like the following in your chat window output:
[UB] Evaluating script (context `Global`): "return game.world.getLandscape()" [UB] Result: [ (MoonSharp.Interpreter.Interop.EnumerableWrapper) MoonSharp.Interpreter.Interop.EnumerableWrapper, null, null ] (0.084ms)
We called the World.GetLandscape() method, which returns a collection of all landscape Worldobject's. Notice that the return type is a
MoonSharp.Interpreter.Interop.EnumerableWrapper. This is a collection of items that we can loop through, and act on each object. Lets run the following to print out the name and id of every object in the landscape:
for wobject in game.World.GetLandscape() do print(wobject.Id, wobject.Name) end
The above should print a new line in the chatbox for each landscape object it found, similar to the following:
[UB] [Script:Global] 2154558015 Ixirs Staff of Eyes [UB] [Script:Global] 2153110655 Weeping Wand [UB] [Script:Global] 2161627415 Orb of the Bunny Booty [UB] Result: null (12.258ms)
[!NOTE] A note about world objects. World Objects instances each have a unique id, accessed via the WorldObject.Id property. Ids are used to refer to specific world object instances. Anywhere in the API that takes a world object id can also take a WorldObject instance, and vice versa.
Take a look at some of the other
Get*() methods exposed on the World class. For example, you can grab all world object instances of a certain ObjectType with the World.GetAll(ObjectType), or get a world object instance with a specific id using the World.Get(objectId) method. The world interface also has an indexer defined, so an alternative to
game.world.get(objectId) for getting a specific world object instance by id could be
Lets take a look at an advanced filtering example. Maybe we want to get a list of all nearby players that are within 10 meters. One of the overloads of the World.GetLandscape(func) method takes a function as the first argument. The function is called with each of the objects found by the Get query, and if the function returns true the object will be included in the resulting collection. The following example gets all landscape objects within 10 meters, and prints out their name and id to the chat window.
local nearby_objects = game.World.GetLandscape(function(check_wobj) return game.Character.DistanceTo(check_wobj) <= 10 end) for wobject in nearby_objects do print(wobject.Id, wobject.Name) end
Accessing world object properties
World objects have "properties" of different value types (not to be confused with class properties). These include Ints, Int64s, Floats, Bools, Strings, Data, and Instances. Most of the information about a world object is stored within these properties, although some data is exposed directly on the WorldObject class. Use the /ub propertydump command with an object selected to view a dump of all of its available properties. These will vary depending on the object type, if you have appraised the object, and the state of the object. You can use the WorldObject.HasValue(PropType*) methods to see if a property of the specified type exists on an object.
[!TIP] To get a full list of available properties on an object instance when using /ub propertydump, make sure to appraise the object first. You can do this by right clicking the object in game, or pragmatically by calling Appraise() on a world object instance.
Lets grab all player objects and print their name and level. We can filter all objects down to just ones that match ObjectClass.Player using the World.GetAll(ObjectClass) method. Try running the following:
for wobject in game.World.GetAll(ObjectClass.Player) do print(wobject.Name, "is level", wobject.Value(IntId.Level)) end
You should see something similar to the following in your chat window:
[UB] Evaluating script (context `Global`): "for wobject in game.world.getAll(ObjectClass.Player) do print(wobject.name, "is level", wobject.value(IntId.Level)) end" [UB] [Script:Global] Brycters Money Dump I is level 41 [UB] [Script:Global] Sellin Eighths is level 190 [UB] [Script:Global] Smart Saves is level 129 [UB] [Script:Global] Lan is level 244 [UB] Result: null (6.092ms)