Adding Lua

Adding Lua to is fairly straightforward, and you can set up multiple instances quite easily.
== Prerequisites==
You'll need to download and add Lua to your SDK project: 
*Go to the LuaBinaries Sourceforge
*Click the latest version > Windows Libraries > Static, and pick one that uses Win32.
*Extract it, and add the header files that are located in it's "include" directory to your Server project.
*Move the Lua Library (.lib) to somewhere in 
Add these two source files to your project:
*ge_luamanager.cpp
*ge_luamanager.h
== Project Settings ==
Right click your Server project, and click Properties, then:
*Add the Lua Library to linker dependencies. (Linker -> Input -> Additional Dependencies)
*Add to your preprocessor definitions. (C/C++ -> Preprocessor -> Preprocessor Definitions)
== Initializing Lua == 
In , you'll need to include ge_luamanager.h:
#ifdef GE_LUA
#include "ge_luamanager.h"
#endif
Insert this into CServerGameDLL::DLLInit, right before the return true statement:
#ifdef GE_LUA
	// Start LUA
	GELua()->InitDll();
#endif
And in the CServerGameDLL::DLLShutdown method, add this:
#ifdef GE_LUA
	// Shutdown LUA, close all open gameplays
	GELua()->ShutdownDll();
#endif
== Writing Your Own Lua Instance ==
You will need to write your own class that inherits from LuaHandle and provides functionality for the methods: Init, Shutdown, RegFunctions and RegGlobals.
class MyLuaHandle : LuaHandle {
public:
	MyLuaHandle();
	~MyLuaHandle();
	void Init();
	void Shutdown();
	void RegFunctions();
	void RegGlobals();
}
=== Init ===
Init is called after Lua gets initialized, and this provides the best place to load your script.
void MyLuaHandle::Init()
{
	const char* luaFile = "myLuaFile.lua";
	//Load into buffer
	FileHandle_t f = filesystem->Open( luaFile, "rb", "MOD" );
	if (!f)
		return;
	// load file into a null-terminated buffer
	int fileSize = filesystem->Size(f);
	unsigned bufSize = ((IFileSystem *)filesystem)->GetOptimalReadSize( f, fileSize + 1 );
	char *buffer = (char*)((IFileSystem *)filesystem)->AllocOptimalReadBuffer( f, bufSize );
	Assert(buffer);
	((IFileSystem *)filesystem)->ReadEx( buffer, bufSize, fileSize, f ); // read into local buffer
	buffer[fileSize] = '\0'; // null terminate file as EOF
	filesystem->Close( f );	// close file after reading
	int error = luaL_loadbuffer( GetLua(), buffer, fileSize, luaFile );
	if (error)
	{
		Warning("[LUA-ERR] %s\n", lua_tostring(GetLua(), -1));
		lua_pop(GetLua(), 1); /* pop error message from the stack */
		Warning("[LUA-ERR] One or more errors occured while loading lua script!\n");
		return;
	}
	CallLUA(GetLua(), 0, LUA_MULTRET, 0, luaFile );
	m_bLuaLoaded = true;
}
=== Shutdown ===
Shutdown handles the shutting down of Lua, and should do things like call any shutdown functions in your script.
void MyLuaHandle::Shutdown()
{
// Do stuff
}
=== RegGlobals ===
RegGlobals allows us to register global variables in Lua.
void MyLuaHandle::RegGlobals()
{
	LG_DEFINE_INT("FOR_ALL_PLAYERS", -1);
	LG_DEFINE_INT("INVALID_ENTITY", -1);
	LG_DEFINE_INT("NULL", 0);
	LG_DEFINE_INT("GE_MAX_HEALTH", MAX_HEALTH);
	LG_DEFINE_INT("GE_MAX_ARMOR", MAX_ARMOR);
	LG_DEFINE_INT("MAX_PLAYERS", gpGlobals->maxClients);
	//Team Indices
	LG_DEFINE_INT("TEAM_NONE",TEAM_UNASSIGNED);
	LG_DEFINE_INT("TEAM_SPECTATOR",TEAM_SPECTATOR);
	LG_DEFINE_INT("TEAM_MI6",TEAM_MI6);
	LG_DEFINE_INT("TEAM_JANUS",TEAM_JANUS);
	//ClientPrintAll Types
	LG_DEFINE_INT("HUD_PRINTNOTIFY",HUD_PRINTNOTIFY);
	LG_DEFINE_INT("HUD_PRINTCONSOLE",HUD_PRINTCONSOLE);
	LG_DEFINE_INT("HUD_PRINTTALK",HUD_PRINTTALK);
	LG_DEFINE_INT("HUD_PRINTCENTER",HUD_PRINTCENTER);
}
=== RegFunctions ===
RegFunctions is where you put any and all C functions that you want to expose to Lua.
void MyLuaHandle::RegFunctions()
{
	REG_FUNCTION( Msg );
	REG_FUNCTION( ConMsg );
	REG_FUNCTION( ClientPrintAll );
	REG_FUNCTION( GetTime );
}
extern "C"
{
	#include <lua.h>
	#include <lauxlib.h>
	#include <lualib.h>
}
int luaClientPrintAll(lua_State *L)
{
	int n = lua_gettop(L); /* number of arguments */
	switch(n)
	{
	case 2:
		UTIL_ClientPrintAll( lua_tointeger(L,1), lua_tostring(L,2));
		break;
	case 3:
		UTIL_ClientPrintAll( lua_tointeger(L,1), lua_tostring(L,2),lua_tostring(L,3));
		break;
	case 4:
		UTIL_ClientPrintAll( lua_tointeger(L,1), lua_tostring(L,2),lua_tostring(L,3),lua_tostring(L,4));
		break;
	case 5:
		UTIL_ClientPrintAll( lua_tointeger(L,1), lua_tostring(L,2),lua_tostring(L,3),lua_tostring(L,4),lua_tostring(L,5));
		break;
	case 6:
		UTIL_ClientPrintAll( lua_tointeger(L,1), lua_tostring(L,2),lua_tostring(L,3),lua_tostring(L,4),lua_tostring(L,5),lua_tostring(L,6));
		break;
	}
	return 0;
}
int luaMsg(lua_State *L)
{
	Msg("%s\n",lua_tostring(L,1));
	return 0;
}
int luaConMsg(lua_State *L)
{
	return luaMsg(L);
}
int luaGetTime(lua_State *L)
{
	lua_pushnumber( L, gpGlobals->curtime );
	return 1;
}
== Creating The Instance ==
You'll need to add a function allowing global access to your Lua instance. Add something like this:
LuaHandle* g_LuaHandle = NULL;
LuaHandle* GetLuaHandle()
{
	return g_LuaHandle;
}
In the constructor of your LuaHandle, add a call to set the global access pointer to your instance when you make a new one:
MyLuaHandle::MyLuaHandle() : LuaHandle()
{
	g_LuaHandle = this;
	Register();
}
Finally, in your game rules constructor, instantiate a new LuaHandle: 
CGameRules::CGameRules()
{
	//other stuff here
	// Start our LUA GamePlay Engine
	if (!GetLuaHandle())
		new MyLuaHandle();
}
 
== Calling Lua functions from C ==
You may need to consult the Lua documents for this, but here is an example on how you might do something like it:
Lua:
function RoundStart()
	Msg("The round has started!")
end
C:
void PostRoundBegin()
{
	LuaHandle* lh = GetLuaHandle();
	if (lh && lh->m_bLuaLoaded)
	{
		lua_getglobal(lh->GetLua(), "RoundStart");
		CallLUA(lh->GetLua(), 0, 0, 0, "RoundStart");
	}
}
Category:Source
Category:C++
Category:Scripting
Category:Free source code