Troll Face Script Lua C

  1. Lua Script Tutorial
  2. Troll Face Script Lua Cua

Here is all you need:My official Twitter accountpaypal.me/JRivera735My DiscordRoblox Ga.

All scripts should have a function Base_Definitions defined, either directly or in one of their required scripts. This is called by the engine when the script is first loaded.

Contains all galactic AI plans as well as subfolders 'LandMode' and 'SpaceMode' which contain the plans for the corresponding game modes.Note that scripts in this folder are only recognized by the game if they are in the main game directory (i.e. not in a mod folder) or if a script of the same name is contained in a loaded .meg file. In the latter case the script from this folder overrides the one in the .meg.

Scripts in this folder can be invoked by perceptions to run Lua commands to compute something. They contain a function Evaluate which is called when a perception invokes the script. Its return value is passed back to the perception.They also contain a function Clean_Up to reset variables containing pointers. The engine will actually call Evaluator_Clean_Up which is implemented in PGBaseDefinitions and calls Clean_Up.

The scripts in this folder handle the AI freestore, i.e. they control those units that are not needed for any active AI plans.

Contains scripts that are attached to units with the Lua_Script tag. The game loads several instances of these scripts at once (given by the ScriptPoolCount) even if not all of them are needed. Each unit is assigned its own script instance. When a unit with a script dies, rather than discarding and reloading the script the game cleans up the script instance by calling Flush_G and Base_Definitions again and assigns it to the next unit that requires it.The main function is called when the unit is spawned. Usually, object scripts simply require PGStateMachine which implements the main function and offers state machine functionality instead.Object scripts require the variable ServiceRate to be set in the setup phase, otherwise the main function won't be run.

Here, the base game intervention scripts are defined. They are simply AI plans for the player that use some specific logic.

This folder contains library scripts that do not have a specific purpose on their own but rather provide common base functionality for other scripts.

PGDebug

Contains commands for debugging which are deactivated for the release build.

FunctionArgumentsDescription
DebugEventAlert(event, params)event, list of parametersTriggers a MessageBox with information on the event and parameters.
MessageBox(...)String and optionally values for formattingTriggers a MessageBox with the formatted string.
ScriptMessage(...)String and optionally values for formattingLogs the formatted string in the AI log.
DebugMessage(...)String and optionally values for formattingLogs the formatted string in the AI log.
OutputDebug(...)String and optionally values for formattingLogs the formatted string in the log file.
ScriptError(...)String and optionally values for formattingLogs the formatted string in the log file and the AI log and exits the script.
DebugPrintTable(unit_table)tablePrints all values to the AI log.

PGBase

Requires PGDebug. Defines some basic functionality.

FunctionArgumentsDescription
ScriptExit()-Immediately terminates the script without executing any other statements.
Sleep(time)time in secondsContinue pumping events without doing anything else until the given game time has passed.
BlockOnCommand(block, max_duration, alternate_break_func)block: an object that has methods IsFinished and ResultWaits until block.IsFinished() returns true, alternate_break_func() returns true or the given time runs out. If the block has finished, this returns block.Result(). Mainly used for unit movement commands and the reinforce command.
max_duration in seconds (optional)
alternate_break_func (optional)
BreakBlock()-Breaks a BlockOnCommand (may have unexpected effects if a BlockOnCommand is running in multiple threads)
TestCommand(block)block: an object that has a method IsFinishedRuns PumpEvents once and returns block.IsFinished()
PumpEvents()-Implements threading and calls event handlers. Returns control to 'C' and continues on next service (i.e. after ServiceRate seconds).
TestValid(wrapper)wrapper: nil, game objectUsed to check validity of game objects. Returns false if wrapper is nil, doesn't have a function Is_Valid or wrapper.Is_Valid() is false.
Clamp(value, min, max)value, min, max: numbers
Dirty_Floor(val)val: numberReturns val as string. Requires implicit string to int conversion of the return value.
Simple_Mod(a,b)a,bModulus function.
Chance(seed, percent)seed, percentRequires a random seed between 0 and 99. Under those conditions it returns true with percent chance.
GetCurrentMinute()-
GetAbilityChanceSeed()-Just the current game time in seconds
GetChanceAllowed(difficulty)-Supposed to be difficulty dependent but always returns 100
PlayerSpecificName(player_object, var_name)player_object, var_name(string)Returns var_name with a player specific prefix
Flush_G()-Used to reset object scripts. Deletes all tables except for a few 'very important' ones. Also deletes most userdata.

PGBaseDefinitions

Requires PGBase. Mainly defines/resets commonly used variables but also some additional functions.

FunctionArgumentsDescription
Common_Base_Definitions()-(Re)Sets all kinds of global variables. Only used in Base_Definitions()
Base_Definitions()-Calls Common_Base_Definitions() and Definitions() if it exists.
Evaluator_Clean_Up()-Basic clean up function for evaluator scripts. Calls Clean_Up().
UnitListIsObscured(unit_list)unit_listReturns true if all given units are obscured by some space field.
Cull_Unit_List(unit_list)unit_listRemoves all dead or otherwise invalid units from a list and returns it.

PGCommands

Requires PGBaseDefinitions. Contains functions to set callbacks for certain events and some advanced unit/taskforce functionality.

FunctionArgumentsDescription
WaitForever()-Wait forever ...
Register_Timer(func, timeout, param)func, timeout, param(optional)Sets up a callback func(param) after timeout (in seconds) has expired.
Process_Timers()-Internal function to manage timers.
Cancel_Timer(func)funcCancel timer for a given function.
Register_Death_Event(obj, func)obj, funcSets up a call to func when the given object dies.
Process_Death_Events()-Internal function to manage death callbacks.
Register_Attacked_Event(obj, func)obj, funcSets up a call func(true, attacker, obj) when the given object is first attacked and a call func(true, nil, obj) when the given object is no longer under attack. The callback is not cancelled automatically at any point.
Process_Attacked_Events()-Internal function to manage attack callbacks.
Cancel_Attacked_Event(obj)obj
Register_Prox(obj, func, range, player_filter)obj, func, range, player_filter(optional)Sets up a callback to func(obj, trigger). The callback is executed continuously if not cancelled. Cancel by calling obj.Cancel_Event_Object_In_Range(func).
Process_Proximities()-Internal function that calls Service_Wrapper on units registered for proximity callbacks.
Pump_Service()-Internal function that runs processing functions and Story_Mode_Service if it exists. Is called by PumpEvents.
Try_Ability(thing, ability_name, target)thing, ability_name, target(optional, depends on ability)thing can be a unit or taskforce. Activates ability if possible. Only activates ability if an ability dependent chance is successful. However, in vanilla that chance is always 100%.
Use_Ability_If_Able(thing, ability_name, target)thing, ability_name, target(optional, depends on ability)thing can be a unit or taskforce. Activates ability if possible.
Is_A_Taskforce(thing)thing
ConsiderDivertAndAOE(object, ability_name, area_of_effect, recent_enemy_units, min_threat_to_use_ability)object, ability_name, area_of_effect(number), recent_enemy_units(unit list), min_threat_to_use_ability(number)This will consider diverting the passed object in order to use an area of effect ability centered on the unit.
OneOrMoreInRange(origin_unit, target_unit_list, range)origin_unit, target_unit_list, rangeReturns true if at least one of target_unit_list is inside the given range of origin_unit
PruneFriendlyObjects(obj_table)obj_tableRemoves any objects in obj_table that do not belong to PlayerObject and returns them in a new list.
Try_Garrison(tf, unit, offensive_only, range)tf(optional), unit, offensive_only, rangeTries to garrison unit. Prefers places from which the unit can fire but will also find others if offensive_only is false. If tf is given, releases unit from tf.
Try_Deploy_Garrison(object, target, health_threshold)object, target(optional), health_threshold(number)Deploys units garrisoned in object if their health is high enough and there is no target or the garrisoned unit is good against the target.
Get_Special_Healer_Property_Flag(unit)unitDefines which heroes are healed by which type of healer. Also done for some special units. Used in free store and PGEvents.
Set_Land_AI_Targeting_Priorities(tf)tfSets targeting priorities for the given taskforce.
Try_Weapon_Switch(object, target)object, targetSwitches weapons if they are more effective against the given target. Requires a custom entry for each unit type that can switch weapons.
Determine_Magic_Wait_Duration()-Returns a wait duration for magic plans.

PGAICommands

Requires PGCommands. Overrides Base_Definitions and sets values used in AI scripts. Also defines unit category contrast values for the AI.

FunctionArgumentsDescription
Base_Definitions()-Calls Common_Base_Definitions, sets some AI plan variables and resets taskforce variables. Also calls Definitions if it exists.
Set_Contrast_Values()-Tells the AI how effective unit categories are against others.
Face

PGTaskForce

Requires PGAICommands. Defines taskforce functions for AI scripts.

PGEvents

Requires PGTaskForce. Defines default event handlers for taskforces and some helper functions.

PGStateMachine

Lua

Requires PGCommands. Implements a state machine.

PGStoryMode

Requires PGStateMachine. Uses the state machine to handle story events.

PGMoveUnits

Requires PGBaseDefinitions. Defines functions to use movement commands for unit lists.

PGSpawnUnits

Requires PGBaseDefinitions. Defines functions for reinforcing and to spawn a list of units.

PGInterventions

Requires PGBaseDefinitions. Basic setup and helper functions for interventions.

GameScoring, FleetEvents and random stuff

This is where all story scripts are as well as the .txt files that define the story logs.

Lua Scripts

Scripts in here can be used for GCs or tactical missions by setting them in a story plot .xml file. Base_Definitions for these scripts is called during load of the GC/tactical mission. main is called when the respective game starts, however story scripts usually rely on PGStoryMode and PGStateMachine rather than implementing their own main functions.Unlike object scripts, story scripts don't pool and are discarded when the game mode ends. As such, they are reloaded directly from the file when they are needed again.

Dialog files

The dialog files in this folder are simple text files with a specific syntax that define the story log entries in GC. The first entry starts with [CHAPTER 0], comments start with #.

CommandArgumentsDescription
TITLETextfile StringThe title shown directly over the main text body, not what is shown in the list of log entries.
MOVIEMovies.xml entry
WAITNumber (or SPEECH?)
SFXSfx event xml namePlay SFX.
TEXTCOLORFour numbers 0-255Set text color of any text entries below this command using rgba color format.
TEXTTextfile StringDisplay textfile entry.
NEWLINENumberAdd given number of empty lines
EXTRA_TEXT-
DIALOGSpeechEvent xml name
MOVIE_ONCE?
MUSIC?
ANIM?
CLEARTEXT?
IMAGE?
CLEARIMAGE?
PAUSE?
LOADCINEMATIC?
HIDECINEMATIC?
STOPMOVIE?
WAIT_SPEECH?

The lua source can be found at the lua website here. We'll be using the latest version, 5.2.3 (though other recent versions of Lua will behave similarly).

Once you have the latest lua source, it's time to build it. (Yes, you could just download header files and the .dll, but what's the fun in that? When available, it's always better to have the source, that way you can see how things are really working -- and you can debug more easily). Using visual studio:

  • Open up Visual Studio, and create a new project
    • Create a win 32 console application
    • In the Project Creation wizard, check the 'static library' radio button to build as a static library.
  • Add the lua source to the project. Just dragging the files directly from their folders into the project works well for this.
  • There are two source files that you don't need: lua.c and luac.c. These files contain the main program for the command line interpreter and the bytecode compiler, respectively. You can remove this files from the project if you wish. If you are building as a static library, having more than one main won't be a problem. However, if you are building as an executable, then you will need to exclude one of these files from the project. Right-click on them in the project explorer and select 'Exclude from Project'

You now have a project that you can add to any solution that needs lua. Once you have added the lua project to your game, you need to do a few more steps:

  • In the properties for the project that is using lua, be sure that the directory that contains the lua .h files is included in the set of include paths. If at all possible, make these paths relative, and not absolute
  • Your project will need to get at the .lib files for the lua. There are a few ways to do this:
    • Add a reference from your project to the lua project. Right-click on your project in the project explorer, and select References:
      Add a new reference:
      Select the lua project:
    • Or, add Lua.lib to 'Additional Dependencies' (in the Librarian/Genrerl tab of the Project Property Pages) and add the directory where Lua.lib lives to 'Additional Library Directories' (also in the Librarian/Genrerl tab of the Project Property Pages).

Once we have build Lua, and set up our project dependencies correctly, we are ready to use in on our application,


First off, we need to include the proper header files. Since Lua is ANSI C, if we are coding in C++, we will need to enclose the #includes in extern 'C':

Everything that we need to mantain the current state of the interprer (all global tables, etc) is stored in a variable of type lua_State. The first thing we need to do is create an initial state (essentially, an instantiation of the lua interpreter), which is done by the call:


Every time we want to access the interpreter, we need to pass in this state variable. We can actually have as many instances of Lua state variables as we like (for instance, if we wanted to run separate instances of the interpreter on separate processors, or we wanted different scripts to have different global namespaces), though typically people just use one instance of the interpreter that all scripts use. The global tables in this state variable contain all 'core' functions, but none of the libraries. The libraries contain a bunch of important functions -- including everything in math, and i/o functions like print -- so we'd like to load them. We can load libraries with the call:


So, now we have the skeleton of a main function:

We are ready to start using lua!

Troll Face Text Copy and Paste – 10+Text Face Memes

We will start with the simplest way to use lua -- have the interpreter execute a file. This is functionally equivalent to the dofile command from within lua (and unsurprisingly, has the same name!). To execute the file 'test.lua', we can use the call:

Note that if we are using relative paths other than absolute paths under windows, then the system will look in the current working directory -- which is the directory that the executable file is in (if you double-click on the executable), or the directory that the project is in (if you run from within Visual Studio) You can, of course, change the working directory that the debugger uses under the project settings in Visual Studio.

So, if we use the following myFile.lua:

when the command luaL_dofile(L, 'myFile.lua') is executed, the following will be printed out

Note that the dofile command not only computes these values and prints them out, it also adds the fib function to the global namespace of our lua enviornment (stored in the C variable L).

We can also call lua functions directly from C/C++, and get back the return values to use in our C/C++ code. To call a lua function we:

  • Push the function on the top of the lua stack, using a call to
    • lua_getGlobal(lua_state *L, char *globalName)
  • Push the arguments to the function on the lua stack, using the functions:
    • lua_pushnumber(lua_state *L, float number)
    • lua_pushstring(lua_state *L, char *str)
    • lua_pushboolean(lua_state *L, bool)
    • lua_pushuserdata(lua_state *L, void *userdata)
    • lua_pushnil(lua_state *L)
  • Call the function, using the function:
    • lua_call(lua_state *L, int numArguments, int numReturnValues)
      We need to pass in both the number of arguments that we are passing in, and the number of arguments that we expect in return. Lua is very loose about the number of arguments and return value, but C/C++ is less so -- hence we need to be explicit when calling lua from C/C++.
  • Extract the return values, using the functions:
    • int lua_tointeger(lua_state *L, int stackLocation)
      Grab an integer value off the lua stack. The first return value is at index -1, the second return value is at index -2, and so on.
    • double lua_tonumber(lua_state *L, int stackLocation)
      Grab a double value off the lua stack. The first return value is at index -1, the second return value is at index -2, and so on.
    • const char *lua_tolstring(lua_state *L, int stackLocation)
      Grab a string value of the lua stack
    • int lua_toboolean(lua_state *L, int stackLocation)
      Grab a boolean value off the lua stack
      Note that these functions 'peek' at the lua stack, they don't actually remove any values from the stack. (That is done by the next function)
  • Pop the return value(s) off the top of the sack (this is just to clean up) with a call to
    • lua_pop(lua_state *L, int numReturnValsToPop);
Let's take a look at how we might call the fib function defined in the previous section to find the 13th Fibonacci number:

Let's look at a second example. Assume that we had defined the following lua function add (that we could define by calling lua_dofile):

We could call this function to add from C/C++ with the code:

So now you could write scripts that you can call from your game engine. However, these scripts won't be very useful if they can't interact with your game objects -- you need a way for your scripts to affect the game world. To do that, you need to be able to call C/C++ functions from lua. Since Lua and C++ have very different conventions for how functions are called, there is a little bit of wrapper work that needs to be done. First, write a C function that takes as input a Lua state variable (the parameters for the function will need to be extracted by hand from the lua stack -- this is slightly tedious, but not too difficult.) Then, the function will need to be registered with lua.

Step 1: Writing a C function that Lua can call

C/C++ functions that are called from lua need to take as an input parameter the lua state. The parameters can be examined on the call stack using the functions lua_tointeger, lua_tonumber, etc (described above). The first parameter is at index 1, the second parameter is at index 2, and so on. Once we have extracted the parameters, we do our calculation, and then push the result on the top of the stack.

Let's look at a slightly more complicated C function. We can write C functions that takes a variable number of parameters, and returns more than one return value. While the previous function assumed that we were passed in two parameters, we can instead query the lua state to see how many parameters were actually passed into the function. The number of parameters is stored on the top of the stack, which can be accessed by a call to lua_gettop(lua_state *L). Let's look at a function that takes in multiple parameters, and calculates the sum and average of all parameters that were passed in:

Step 2: Registering the C function for lua

Once we have written the function, we just need to register it with lua. That is, we need to add the name of the function to the global lua namespace, and provide a pointer to the function so that lua cal access it. There is a helpful macro for this: lua_register(lua_state *L, const char *name, functionPointer fn). So, to register the above two functions:

Step 3: Calling the C funcion from lua

Lua Script Tutorial

This part is easy -- once the function is registered, lua can call it like any other function.

So, the complete round trip is:

  • Start the lua interpreter
  • Register the C functions you want lua to use
  • Call a lua function from within C, either by a call to luaL_dofile, or by calling a lua function directly
  • The lua function that you called from C can access the C function

We can also send a string straight to the lua interpreter, and it will be executed just as if that string was in a file that was executed with a dofile. So, we could do something like:

and we would get the output:

We could thus create a braindead interpreter as follows:

Note that this would not work at all in a game environment! We will look at how to embed a command-line lua interpreter within a game next time. For now, this is enough for us to play around with a bit.

Now we are ready to get our fingers dirty!

Troll Face Script Lua Cua

  1. Download the following project, which contains a basic skeleton lua framework
  2. Write a function in C (exposed to Lua, much like average and cAdd) that takes as input an integer n, and returns all prime numbers less than or equal to n.
    • Test your primes function in the interpreter with 'print(primes(100))'
  3. Write a function in lua nthPrime, that takes as input a number n, and returns the nth prime number. So, nthPrime(6) should return 13. We'll define nthPrime(1) to be 2, and nthPrime(0) will be undefined. Your lua function should call the c primes function
    • Small change in how lua does variable numbers of arguments: From the notes

      Alas, this does not work. But we can fix it with a simple change:

  4. Write C code that computes the 100th prime number by calling the lua nthPrime function, and prints the value out using printf. So, C calling Lua that calls C.