LuaBridge Information

From ArcEmu-Wiki
Jump to: navigation, search

Contents


Introduction

LuaBridge is the new Lua Engine added by Paroxysm. It adds more functionality to the Lua Engine. LuaBridge allows programmers to easily bind classes and to Lua, which opens the door to C++ methods from Lua using a single line of code. In addition, code is made cleaner. For more information, please see here

Changes

Hello, Lua user. If you are viewing this page it is probably because you are looking to use the new LuaBridge engine. That's great! There are a few changes, though.


Units

Back in the old Lua Engine, we had a single category for functions called Unit functions. These functions would run on anything classed as a Unit - which meant you could invoke (use) :GetPlayerClass() on a GameObject or Creature, for example. LuaBridge has now changed this. When a function passes you a Unit argument you have to define it (if you need to) as a Player, Creature or Gameobject. To do this you would use TO_PLAYER(), TO_CREATURE() or TO_OBJECT() respectively (see individual pages for usage). Upon doing this you will immediately be able to access any previous Unit methods as well as the class specific ones - so for example, you could access all Unit methods and Player methods if you used TO_PLAYER().

This means you may very well end up doing something like this:
TO_PLAYER(pUnit):GetPlayerRace().


Global Variables and Collision

Back in the olden days you would have to use table-orientated scripting to avoid collision and using too many Global Variables was a recipe for disaster. Well, now, with LuaBridge (and the addition of the Map Manager), collision is a thing of the past. You'll read more about it in the next section, but basically, every script (unless it is loaded by another script) will have it's own global environment, which means any variables within that script will stay within that script whether they are localled or not (however we recommend you do use locals since they are faster).

The Map Manager(and conditional script loading)

The Map Manager is a big important change for Lua. Previously, we had one global Lua VM(virtual machine) which held every loaded script and any global declarations of those scripts could be visible to other scripts that may be unrelated. Now, with the Map Manager change, Lua VM's are now spawned and coupled(tied together) with every map instance that is created.

Entering a map that is a dungeon or raid for the first time causes a creation of an instance, this then leads to creation of a Lua VM that will be unique to that instance. Any objects within that instance that are scripted in Lua will have their code handled by that said VM. Thus, with a new VM for every instance created, leads to independant global declarations across VMs.

By default, when the Lua VM is created/instantiated, it will attempt to load all files w/ .lua extension. This means it may load a script that targets nothing in that instance because that script wasn't meant to script content in that instance.(ie You have a script that targets creature ID A, yet there are no spawned creatures of ID A in that instance. The VM ends up loading and allocating resources for a script that will never be executed unless you plan to spawn creature ID A in that instance.) This design allows variable collision that would normally occur across multiple instances/raids of the same map to be eliminated. It ,however, does not guard against variable collision that occurs when the target creature A, is spawned multiple times in the same instance. If you end up scripting objects that can be spawned multiple times in the same instance, you will be required to design their variables to be collision free.

*Conditional Script Loading*

So, what is conditional script loading?

Well, there was a nasty side effect from the new design. Every VM created will always load all .lua files. This leads to redundancies and unwanted script loading that happens across VMs that load scripts that are unrelated to the VM allocating alot of unused resources. So, how do we remedy this? Simple

1. Rename your script extension from .lua to anything you want. Preferably .script since that's what it is.

This hides the said script from being automatically loaded by VMs that are created.

2. Next we want to conditionally load this script using another script that is loaded by every VM.

By now, most of the content you will be scripting will target certain objects of instances. What we want is to design a loader script that will load our script(s). It will be responsible for making sure that it loads our scripts on the maps that we want. If our content is normally spawned in map ID B, the loader script will be expected to check map id of every VM that loads the loader script to verify that it's our intended map id. If not, it simply returns(Remember Lua loads every file as a function and runs that function). By using this method, we can be able to neatly script an entire instance with multiple script files, and have 1 loader script that will load all those files on the VMs that satisfy our wanted map id. You can design a hierarchical system where you create multiple load scripts with a renamed extension for multiple instances, then have a parent loader script that will be responsible for loading our load scripts, which in-turn loads our scripts.
Parent loader script->loads a specific instances loader script->which then loads the files for that instance
In this manner, it makes sense to put the map id checking code in the parent loader script.

The above method is cumbersome and not very robust. A new method that uses headers placed at the top of scripts will be used as a work around. These headers are similar to what XML uses and they will be used to specify which map id you wish the script to be loaded in.


Implementation of C++ Classes

LuaBridge now "implements" C++ classes into the Lua Engine, meaning you can access said classes within Code. This cleans up a lot of mistakes and also makes things more clear. An example is this:

Pointer:Class():Method(args)

Or, a real-life example:

pCreature:GetScript():RegisterAIUpdateEvent(1000)

In the old engine, we would use:

pCreature:RegisterAIUpdateEvent(1000)

But since RegisterAIUpdateEvent was a custom Lua function in LuaHypArc which pointed to GetScript():RegisterAIUpdateEvent() and was now removed, we now invoke the class first.
Note that not all C++ classes or functions are exposed to the Lua Engine. If you wish to add these you will need to edit the appropriate source files and recompile your LuaBridge.dll.

Important Notes

  • LuaBridge will only function on Windows 2008 Server / Vista or newer.
  • You will probably want to use this code snippit at the top of your script to prevent your script throwing up nil value errors when the compiler runs through it.
  • Any Unit method can be invoked on either Unit, GameObject, Creature or Player Object.
Personal tools