mirror of
https://github.com/UberGames/rpgxEF.git
synced 2024-11-10 15:21:34 +00:00
1127 lines
No EOL
23 KiB
C
1127 lines
No EOL
23 KiB
C
// g_lua.c
|
|
|
|
#include "g_lua.h"
|
|
|
|
#ifdef G_LUA
|
|
|
|
lvm_t *lVM[NUM_VMS];
|
|
|
|
void QDECL LUA_DEBUG(const char *fmt, ...)
|
|
{
|
|
va_list argptr;
|
|
char text[1024];
|
|
|
|
if(g_debugLua.integer >= 1)
|
|
{
|
|
va_start(argptr, fmt);
|
|
Com_sprintf(text, sizeof(text), fmt, argptr);
|
|
va_end(argptr);
|
|
G_Printf(S_COLOR_YELLOW "LUA DEBUG:" S_COLOR_WHITE " %s\n", text);
|
|
}
|
|
}
|
|
|
|
void QDECL LUA_LOG(const char *fmt, ...)
|
|
{
|
|
va_list argptr;
|
|
char buff[1024], string[1024];
|
|
int min, tens, sec;
|
|
|
|
va_start(argptr, fmt);
|
|
Com_sprintf(buff, sizeof(buff), fmt, argptr);
|
|
va_end(argptr);
|
|
|
|
if(g_dedicated.integer)
|
|
{
|
|
trap_Printf(buff);
|
|
}
|
|
|
|
if(level.logFile)
|
|
{
|
|
sec = level.time / 1000;
|
|
min = sec / 60;
|
|
sec -= min * 60;
|
|
tens = sec / 10;
|
|
sec -= tens * 10;
|
|
|
|
Com_sprintf(string, sizeof(string), "%i:%i%i %s", min, tens, sec, buff);
|
|
|
|
trap_FS_Write(string, strlen(string), level.logFile);
|
|
}
|
|
}
|
|
|
|
qboolean LoadLuaFile(char *path, int num_vm)
|
|
{
|
|
int flen = 0;
|
|
char *code;
|
|
fileHandle_t f;
|
|
lvm_t *vm;
|
|
|
|
flen = trap_FS_FOpenFile(path, &f, FS_READ);
|
|
if(flen < 0)
|
|
{
|
|
LUA_LOG("Lua: can not open file %s\n", path);
|
|
G_Printf(S_COLOR_YELLOW "Lua: can not open file %s\n", path);
|
|
trap_FS_FCloseFile(f);
|
|
return qfalse;
|
|
}
|
|
else
|
|
{
|
|
code = (char *)malloc(flen + 1);
|
|
if(!code) return qfalse;
|
|
trap_FS_Read(code, flen, f);
|
|
*(code + flen) = '\0';
|
|
trap_FS_FCloseFile(f);
|
|
|
|
vm = (lvm_t *) malloc(sizeof(lvm_t));
|
|
if(vm == NULL)
|
|
{
|
|
LUA_LOG("Lua: failed to allocate memory for lua VM\n");
|
|
G_Printf(S_COLOR_YELLOW "Lua: failed to allocate memory for lua VM\n");
|
|
return qfalse;
|
|
}
|
|
memset(vm, 0, sizeof(lvm_t));
|
|
vm->id = -1;
|
|
Q_strncpyz(vm->filename, path, sizeof(vm->filename));
|
|
vm->code = code;
|
|
vm->code_size = flen;
|
|
vm->error = 0;
|
|
|
|
if(G_LuaStartVM(vm) == qfalse)
|
|
{
|
|
G_LuaStopVM(vm);
|
|
vm = NULL;
|
|
return qfalse;
|
|
}
|
|
else
|
|
{
|
|
vm->id = num_vm;
|
|
lVM[num_vm] = vm;
|
|
return qtrue;
|
|
}
|
|
}
|
|
}
|
|
|
|
qboolean G_LuaInit()
|
|
{
|
|
int i, num_vm = 0;
|
|
char buff[128];
|
|
|
|
int numdirs;
|
|
int numFiles;
|
|
char filename[128];
|
|
char dirlist[1024];
|
|
char *dirptr;
|
|
int dirlen;
|
|
|
|
G_Printf("------- G_LuaInit -------\n");
|
|
|
|
numFiles = 0;
|
|
trap_Cvar_VariableStringBuffer("mapname", buff, sizeof(buff));
|
|
sprintf(filename, "scripts/lua/%s/", buff);
|
|
numdirs = trap_FS_GetFileList(filename, ".lua", dirlist, 1024);
|
|
dirptr = dirlist;
|
|
for(i = 0; i < numdirs; i++, dirptr += dirlen + 1)
|
|
{
|
|
dirlen = strlen(dirptr);
|
|
strcpy(filename, "scripts/lua/");
|
|
strcat(filename, buff);
|
|
strcat(filename, "/");
|
|
strcat(filename, dirptr);
|
|
numFiles++;
|
|
|
|
if(LoadLuaFile(filename, num_vm))
|
|
{
|
|
num_vm++;
|
|
G_Printf(" %s Loaded\n", filename);
|
|
}
|
|
else
|
|
{
|
|
G_Printf(" %s Failed\n", filename);
|
|
}
|
|
|
|
if(num_vm >= NUM_VMS)
|
|
{
|
|
LUA_LOG("Lua: too many lua files specified, only the first %d have been loaded\n", NUM_VMS);
|
|
G_Printf(S_COLOR_YELLOW "Lua: too many lua files specified, only the first %d have been loaded\n", NUM_VMS);
|
|
break;
|
|
}
|
|
}
|
|
|
|
Com_Printf("%i map files parsed\n", numFiles);
|
|
|
|
G_Printf("------- G_LuaInit Finish -------\n");
|
|
|
|
return qtrue;
|
|
}
|
|
|
|
qboolean G_LuaResume(lvm_t *vm, lua_State *T, char *func, int nargs) {
|
|
int res = lua_resume(T, NULL, nargs);
|
|
|
|
if(res == LUA_ERRRUN) {
|
|
LUA_LOG("Lua: %s error running lua script: %s\n", func, lua_tostring(T, -1));
|
|
G_Printf(S_COLOR_YELLOW "Lua: %s error running lua script: %s\n", func, lua_tostring(T, -1));
|
|
lua_pop(T, 1);
|
|
vm->error++;
|
|
return qfalse;
|
|
} else if(res == LUA_ERRMEM) {
|
|
LUA_LOG("Lua: memory allocation error #2 ( %s )\n", vm->filename);
|
|
vm->error++;
|
|
return qfalse;
|
|
} else if(res == LUA_ERRERR) {
|
|
LUA_LOG("Lua: traceback error ( %s )\n", vm->filename);
|
|
G_Printf(S_COLOR_YELLOW "Lua: traceback error ( %s )\n", vm->filename);
|
|
vm->error++;
|
|
return qfalse;
|
|
}
|
|
|
|
if(vm->L != T) { // this is a thread
|
|
int n = lua_gettop(vm->L);
|
|
int i;
|
|
lua_State *p;
|
|
|
|
for(i = 0; i <= n; i++) {
|
|
if(lua_isthread(vm->L, i)) {
|
|
p = lua_tothread(vm->L, i);
|
|
|
|
if(p == T) {
|
|
lua_remove(vm->L, i);
|
|
G_LuaCollectGarbage();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return qtrue;
|
|
}
|
|
|
|
qboolean G_LuaCall(lvm_t * vm, char *func, int nargs, int nresults)
|
|
{
|
|
int res = lua_pcall(vm->L, nargs, nresults, 0);
|
|
|
|
if(res == LUA_ERRRUN)
|
|
{
|
|
LUA_LOG("Lua: %s error running lua script: %s\n", func, lua_tostring(vm->L, -1));
|
|
G_Printf(S_COLOR_YELLOW "Lua: %s error running lua script: %s\n", func, lua_tostring(vm->L, -1));
|
|
lua_pop(vm->L, 1);
|
|
vm->error++;
|
|
return qfalse;
|
|
}
|
|
else if(res == LUA_ERRMEM)
|
|
{
|
|
LUA_LOG("Lua: memory allocation error #2 ( %s )\n", vm->filename);
|
|
vm->error++;
|
|
return qfalse;
|
|
}
|
|
else if(res == LUA_ERRERR)
|
|
{
|
|
LUA_LOG("Lua: traceback error ( %s )\n", vm->filename);
|
|
G_Printf(S_COLOR_YELLOW "Lua: traceback error ( %s )\n", vm->filename);
|
|
vm->error++;
|
|
return qfalse;
|
|
}
|
|
return qtrue;
|
|
}
|
|
|
|
#define SAY_ALL 0
|
|
#define SAY_TEAM 1
|
|
|
|
qboolean G_LuaGetFunctionT(lua_State *T, char *name)
|
|
{
|
|
if(T)
|
|
{
|
|
lua_getglobal(T, name);
|
|
if(lua_isfunction(T, -1))
|
|
{
|
|
return qtrue;
|
|
}
|
|
else
|
|
{
|
|
lua_pop(T, 1);
|
|
return qfalse;
|
|
}
|
|
}
|
|
return qfalse;
|
|
}
|
|
|
|
qboolean G_LuaGetFunction(lvm_t * vm, char *name)
|
|
{
|
|
if(vm->L)
|
|
{
|
|
lua_getglobal(vm->L, name);
|
|
if(lua_isfunction(vm->L, -1))
|
|
{
|
|
return qtrue;
|
|
}
|
|
else
|
|
{
|
|
lua_pop(vm->L, 1);
|
|
return qfalse;
|
|
}
|
|
}
|
|
return qfalse;
|
|
}
|
|
|
|
qboolean G_LuaStartVM(lvm_t * vm)
|
|
{
|
|
int res = 0;
|
|
char homepath[MAX_QPATH], gamepath[MAX_QPATH];
|
|
|
|
vm->L = luaL_newstate();
|
|
if(!vm->L)
|
|
{
|
|
LUA_LOG("Lua: Lua failed to initialise.\n");
|
|
return qfalse;
|
|
}
|
|
|
|
luaL_openlibs(vm->L);
|
|
|
|
trap_Cvar_VariableStringBuffer("fs_homepath", homepath, sizeof(homepath));
|
|
trap_Cvar_VariableStringBuffer("fs_game", gamepath, sizeof(gamepath));
|
|
|
|
lua_getglobal(vm->L, LUA_LOADLIBNAME);
|
|
if(lua_istable(vm->L, -1))
|
|
{
|
|
lua_pushstring(vm->L, va("%s%s%s%s?.lua;%s%s%s%slualib%slua%s?.lua",
|
|
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP,
|
|
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, LUA_DIRSEP, LUA_DIRSEP));
|
|
lua_setfield(vm->L, -2, "path");
|
|
lua_pushstring(vm->L, va("%s%s%s%s?.%s;%s%s%s%slualib%sclibs%s?.%s",
|
|
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, EXTENSION,
|
|
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, LUA_DIRSEP, LUA_DIRSEP, EXTENSION));
|
|
lua_setfield(vm->L, -2, "cpath");
|
|
}
|
|
lua_pop(vm->L, 1);
|
|
|
|
Lua_RegisterGlobal(vm->L, "LUA_PATH", va("%s%s%s%s?.lua;%s%s%s%slualib%slua%s?.lua",
|
|
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP,
|
|
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, LUA_DIRSEP, LUA_DIRSEP));
|
|
Lua_RegisterGlobal(vm->L, "LUA_CPATH", va("%s%s%s%s?.%s;%s%s%s%slualib%sclibs%s?.%s",
|
|
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, EXTENSION,
|
|
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, LUA_DIRSEP, LUA_DIRSEP, EXTENSION));
|
|
Lua_RegisterGlobal(vm->L, "LUA_DIRSEP", LUA_DIRSEP);
|
|
|
|
lua_newtable(vm->L);
|
|
Lua_RegConstInteger(vm->L, CS_PLAYERS);
|
|
Lua_RegConstInteger(vm->L, EXEC_NOW);
|
|
Lua_RegConstInteger(vm->L, EXEC_INSERT);
|
|
Lua_RegConstInteger(vm->L, EXEC_APPEND);
|
|
Lua_RegConstInteger(vm->L, FS_READ);
|
|
Lua_RegConstInteger(vm->L, FS_WRITE);
|
|
Lua_RegConstInteger(vm->L, FS_APPEND);
|
|
Lua_RegConstInteger(vm->L, FS_APPEND_SYNC);
|
|
Lua_RegConstInteger(vm->L, SAY_ALL);
|
|
Lua_RegConstInteger(vm->L, SAY_TEAM);
|
|
Lua_RegConstString(vm->L, HOSTARCH);
|
|
|
|
luaopen_base(vm->L);
|
|
luaopen_string(vm->L);
|
|
luaopen_coroutine(vm->L);
|
|
Luaopen_Game(vm->L);
|
|
Luaopen_Qmath(vm->L);
|
|
Luaopen_Mover(vm->L);
|
|
Luaopen_Vector(vm->L);
|
|
Luaopen_Entity(vm->L);
|
|
Luaopen_Cinematic(vm->L);
|
|
Luaopen_Sound(vm->L);
|
|
Luaopen_Trace(vm->L);
|
|
|
|
res = luaL_loadbuffer(vm->L, vm->code, vm->code_size, vm->filename);
|
|
if(res == LUA_ERRSYNTAX)
|
|
{
|
|
LUA_LOG("Lua: syntax error during pre-compilation: %s\n", (char *)lua_tostring(vm->L, -1));
|
|
G_Printf(S_COLOR_YELLOW "Lua: syntax error: %s\n", (char *)lua_tostring(vm->L, -1));
|
|
lua_pop(vm->L, 1);
|
|
vm->error++;
|
|
return qfalse;
|
|
}
|
|
else if(res == LUA_ERRMEM)
|
|
{
|
|
LUA_LOG("Lua: memory allocation error #1 ( %s )\n", vm->filename);
|
|
vm->error++;
|
|
return qfalse;
|
|
}
|
|
|
|
if(!G_LuaCall(vm, "G_LuaStartVM", 0, 0))
|
|
return qfalse;
|
|
|
|
LUA_LOG("Lua: Loading %s\n", vm->filename);
|
|
return qtrue;
|
|
}
|
|
|
|
void G_LuaStopVM(lvm_t * vm)
|
|
{
|
|
if(vm == NULL)
|
|
return;
|
|
if(vm->code != NULL)
|
|
{
|
|
free(vm->code);
|
|
vm->code = NULL;
|
|
}
|
|
if(vm->id >= 0)
|
|
{
|
|
if(lVM[vm->id] == vm)
|
|
lVM[vm->id] = NULL;
|
|
if(!vm->error)
|
|
{
|
|
LUA_LOG("Lua: Lua module [%s] unloaded.\n", vm->filename);
|
|
}
|
|
}
|
|
free(vm);
|
|
}
|
|
|
|
void G_LuaShutdown()
|
|
{
|
|
int i;
|
|
lvm_t *vm;
|
|
|
|
for(i = 0; i < NUM_VMS; i++)
|
|
{
|
|
vm = lVM[i];
|
|
if(vm)
|
|
{
|
|
G_LuaStopVM(vm);
|
|
}
|
|
}
|
|
}
|
|
|
|
void G_LuaStatus(gentity_t * ent)
|
|
{
|
|
int i, cnt = 0;
|
|
|
|
for(i = 0; i < NUM_VMS; i++)
|
|
if(lVM[i])
|
|
cnt++;
|
|
|
|
if(ent)
|
|
{
|
|
if(cnt == 0)
|
|
{
|
|
G_PrintfClient(ent, "Lua: no scripts loaded.");
|
|
return;
|
|
}
|
|
else if(cnt == 1)
|
|
{
|
|
G_PrintfClient(ent, "Lua: showing lua information ( 1 module loaded )");
|
|
}
|
|
else
|
|
{
|
|
G_PrintfClient(ent, "Lua: showing lua information ( %d modules loaded )", cnt);
|
|
}
|
|
G_PrintfClient(ent, "%-2s %-24s", "VM","Filename");
|
|
G_PrintfClient(ent, "-- ------------------------");
|
|
for(i = 0; i < NUM_VMS; i++)
|
|
{
|
|
if(lVM[i])
|
|
{
|
|
G_PrintfClient(ent, "%2d %-24s", lVM[i]->id, lVM[i]->filename);
|
|
}
|
|
}
|
|
G_PrintfClient(ent, "-- ------------------------");
|
|
}
|
|
else
|
|
{
|
|
if(cnt == 0)
|
|
{
|
|
G_Printf("Lua: no scripts loaded.\n");
|
|
return;
|
|
}
|
|
else if(cnt == 1)
|
|
{
|
|
G_Printf("Lua: showing lua information ( 1 module loaded )\n");
|
|
}
|
|
else
|
|
{
|
|
G_Printf("Lua: showing lua information ( %d modules loaded )\n", cnt);
|
|
}
|
|
G_Printf("%-2s %-24s\n", "VM", "Filename");
|
|
G_Printf("-- ------------------------\n");
|
|
for(i = 0; i < NUM_VMS; i++)
|
|
{
|
|
if(lVM[i])
|
|
{
|
|
G_Printf("%2d %-24s\n", lVM[i]->id, lVM[i]->filename);
|
|
}
|
|
}
|
|
G_Printf("-- ------------------------\n");
|
|
}
|
|
|
|
}
|
|
|
|
lvm_t *G_LuaGetVM(lua_State * L)
|
|
{
|
|
int i;
|
|
|
|
for(i = 0; i < NUM_VMS; i++)
|
|
if(lVM[i] && lVM[i]->L == L)
|
|
return lVM[i];
|
|
return NULL;
|
|
}
|
|
|
|
void LuaHook_G_InitGame(int levelTime, unsigned int randomSeed, int restart)
|
|
{
|
|
int i;
|
|
lvm_t *vm;
|
|
|
|
for(i = 0; i < NUM_VMS; i++)
|
|
{
|
|
vm = lVM[i];
|
|
if(vm)
|
|
{
|
|
if(vm->id < 0 )
|
|
continue;
|
|
if(!G_LuaGetFunction(vm, "InitGame"))
|
|
continue;
|
|
lua_pushinteger(vm->L, levelTime);
|
|
lua_pushinteger(vm->L, randomSeed);
|
|
lua_pushinteger(vm->L, restart);
|
|
if(!G_LuaCall(vm, "InitGame", 3, 0))
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void LuaHook_G_Shutdown(int restart)
|
|
{
|
|
int i;
|
|
lvm_t *vm;
|
|
|
|
for(i = 0; i < NUM_VMS; i++)
|
|
{
|
|
vm = lVM[i];
|
|
if(vm)
|
|
{
|
|
if(vm->id < 0 )
|
|
continue;
|
|
if(!G_LuaGetFunction(vm, "ShutdownGame"))
|
|
continue;
|
|
lua_pushinteger(vm->L, restart);
|
|
if(!G_LuaCall(vm, "ShutdownGame", 1, 0))
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void LuaHook_G_RunFrame(int levelTime)
|
|
{
|
|
int i;
|
|
lvm_t *vm;
|
|
|
|
for(i = 0; i < NUM_VMS; i++)
|
|
{
|
|
vm = lVM[i];
|
|
if(vm)
|
|
{
|
|
if(vm->id < 0 )
|
|
continue;
|
|
if(!G_LuaGetFunction(vm, "RunFrame"))
|
|
continue;
|
|
lua_pushinteger(vm->L, levelTime);
|
|
if(!G_LuaCall(vm, "RunFrame", 1, 0))
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void LuaHook_G_ClientPrint(char *text, int entnum) {
|
|
int i;
|
|
lvm_t *vm;
|
|
gentity_t *ent;
|
|
|
|
if(!entnum) return;
|
|
|
|
for(i = 0; i < NUM_VMS; i++) {
|
|
vm = lVM[i];
|
|
if(vm) {
|
|
if(vm->id < 0)
|
|
continue;
|
|
if(!G_LuaGetFunction(vm, "GClientPrint"))
|
|
continue;
|
|
lua_pushstring(vm->L, text);
|
|
ent = &g_entities[entnum];
|
|
if(!ent || !ent->inuse)
|
|
lua_pushnil(vm->L);
|
|
else
|
|
Lua_PushEntity(vm->L, ent);
|
|
|
|
if(!G_LuaCall(vm, "GClientPrint", 2, 0))
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
void LuaHook_G_Print(char *text)
|
|
{
|
|
int i;
|
|
lvm_t *vm;
|
|
|
|
for(i = 0; i < NUM_VMS; i++)
|
|
{
|
|
vm = lVM[i];
|
|
if(vm)
|
|
{
|
|
if(vm->id < 0 )
|
|
continue;
|
|
if(!G_LuaGetFunction(vm, "GPrint"))
|
|
continue;
|
|
lua_pushstring(vm->L, text);
|
|
if(!G_LuaCall(vm, "GPrint", 1, 0))
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void LuaHook_G_EntityThink(char *function, int entnum)
|
|
{
|
|
int i;
|
|
lvm_t *vm;
|
|
lua_State *t;
|
|
gentity_t *ent;
|
|
|
|
for(i = 0; i < NUM_VMS; i++)
|
|
{
|
|
vm = lVM[i];
|
|
if(vm)
|
|
{
|
|
if(vm->id < 0 )
|
|
continue;
|
|
t = lua_newthread(vm->L);
|
|
if(!t) {
|
|
if(!G_LuaGetFunction(vm, function))
|
|
continue;
|
|
ent = &g_entities[entnum];
|
|
if(!ent || !ent->inuse)
|
|
lua_pushnil(vm->L);
|
|
else
|
|
Lua_PushEntity(vm->L, ent);
|
|
if(!G_LuaCall(vm, function, 1, 0))
|
|
{
|
|
continue;
|
|
}
|
|
} else {
|
|
t = vm->L;
|
|
if(!G_LuaGetFunctionT(t, function))
|
|
continue;
|
|
ent = &g_entities[entnum];
|
|
if(!ent || !ent->inuse)
|
|
lua_pushnil(t);
|
|
else
|
|
Lua_PushEntity(t, ent);
|
|
if(!G_LuaResume(vm, t, function, 1))
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void LuaHook_G_EntityTouch(char *function, int entnum, int othernum)
|
|
{
|
|
int i;
|
|
lvm_t *vm;
|
|
lua_State *t;
|
|
gentity_t *ent;
|
|
gentity_t *other;
|
|
|
|
for(i = 0; i < NUM_VMS; i++)
|
|
{
|
|
vm = lVM[i];
|
|
if(vm)
|
|
{
|
|
if(vm->id < 0)
|
|
continue;
|
|
t = lua_newthread(vm->L);
|
|
if(!t) {
|
|
if(!G_LuaGetFunction(vm, function))
|
|
continue;
|
|
ent = &g_entities[entnum];
|
|
if(!ent || !ent->inuse)
|
|
lua_pushnil(vm->L);
|
|
else
|
|
Lua_PushEntity(vm->L, ent);
|
|
other = &g_entities[othernum];
|
|
if(!other || !other->inuse)
|
|
lua_pushnil(vm->L);
|
|
else
|
|
Lua_PushEntity(vm->L, other);
|
|
if(!G_LuaCall(vm, function, 2, 0))
|
|
{
|
|
continue;
|
|
}
|
|
} else {
|
|
if(!G_LuaGetFunctionT(t, function))
|
|
continue;
|
|
ent = &g_entities[entnum];
|
|
if(!ent || !ent->inuse)
|
|
lua_pushnil(t);
|
|
else
|
|
Lua_PushEntity(t, ent);
|
|
other = &g_entities[othernum];
|
|
if(!other || !other->inuse)
|
|
lua_pushnil(t);
|
|
else
|
|
Lua_PushEntity(t, other);
|
|
if(!G_LuaResume(vm, t, function, 2))
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void LuaHook_G_EntityUse(char *function, int entnum, int othernum, int activatornum)
|
|
{
|
|
int i;
|
|
lvm_t *vm;
|
|
lua_State *t;
|
|
gentity_t *ent;
|
|
gentity_t *other;
|
|
gentity_t *activator;
|
|
|
|
for(i = 0; i < NUM_VMS; i++)
|
|
{
|
|
vm = lVM[i];
|
|
if(vm)
|
|
{
|
|
if(vm->id < 0)
|
|
continue;
|
|
t = lua_newthread(vm->L);
|
|
if(!t) {
|
|
if(!G_LuaGetFunction(vm, function))
|
|
continue;
|
|
ent = &g_entities[entnum];
|
|
if(!ent || !ent->inuse)
|
|
lua_pushnil(vm->L);
|
|
else
|
|
Lua_PushEntity(vm->L, ent);
|
|
other = &g_entities[othernum];
|
|
if(!other || !other->inuse)
|
|
lua_pushnil(vm->L);
|
|
else
|
|
Lua_PushEntity(vm->L, other);
|
|
activator = &g_entities[activatornum];
|
|
if(!activator || !activator->inuse)
|
|
lua_pushnil(vm->L);
|
|
else
|
|
Lua_PushEntity(vm->L, activator);
|
|
if(!G_LuaCall(vm, function, 3, 0))
|
|
{
|
|
continue;
|
|
}
|
|
} else {
|
|
if(!G_LuaGetFunctionT(t, function))
|
|
continue;
|
|
ent = &g_entities[entnum];
|
|
if(!ent || !ent->inuse)
|
|
lua_pushnil(t);
|
|
else
|
|
Lua_PushEntity(t, ent);
|
|
other = &g_entities[othernum];
|
|
if(!other || !other->inuse)
|
|
lua_pushnil(t);
|
|
else
|
|
Lua_PushEntity(t, other);
|
|
activator = &g_entities[activatornum];
|
|
if(!activator || !activator->inuse)
|
|
lua_pushnil(t);
|
|
else
|
|
Lua_PushEntity(t, activator);
|
|
G_LuaResume(vm, t, function, 3);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void LuaHook_G_EntityHurt(char *function, int entnum, int inflictornum, int attackernum)
|
|
{
|
|
int i;
|
|
lvm_t *vm;
|
|
lua_State *t;
|
|
gentity_t *ent;
|
|
gentity_t *inflictor;
|
|
gentity_t *attacker;
|
|
|
|
for(i = 0; i < NUM_VMS; i++)
|
|
{
|
|
vm = lVM[i];
|
|
if(vm)
|
|
{
|
|
if(vm->id < 0)
|
|
continue;
|
|
t = lua_newthread(vm->L);
|
|
if(!t) {
|
|
if(!G_LuaGetFunction(vm, function))
|
|
continue;
|
|
ent = &g_entities[entnum];
|
|
if(!ent || !ent->inuse)
|
|
lua_pushnil(vm->L);
|
|
else
|
|
Lua_PushEntity(vm->L, ent);
|
|
inflictor = &g_entities[inflictornum];
|
|
if(!inflictor || !inflictor->inuse)
|
|
lua_pushnil(vm->L);
|
|
else
|
|
Lua_PushEntity(vm->L, inflictor);
|
|
attacker = &g_entities[attackernum];
|
|
if(!attacker || !attacker->inuse)
|
|
lua_pushnil(vm->L);
|
|
else
|
|
Lua_PushEntity(vm->L, attacker);
|
|
if(!G_LuaCall(vm, function, 3, 0))
|
|
{
|
|
continue;
|
|
}
|
|
} else {
|
|
if(!G_LuaGetFunctionT(t, function))
|
|
continue;
|
|
ent = &g_entities[entnum];
|
|
if(!ent || !ent->inuse)
|
|
lua_pushnil(t);
|
|
else
|
|
Lua_PushEntity(t, ent);
|
|
inflictor = &g_entities[inflictornum];
|
|
if(!inflictor || !inflictor->inuse)
|
|
lua_pushnil(t);
|
|
else
|
|
Lua_PushEntity(t, inflictor);
|
|
attacker = &g_entities[attackernum];
|
|
if(!attacker || !attacker->inuse)
|
|
lua_pushnil(t);
|
|
else
|
|
Lua_PushEntity(t, attacker);
|
|
if(!G_LuaResume(vm, t, function, 3))
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void LuaHook_G_EntityDie(char *function, int entnum, int inflictornum, int attackernum, int dmg, int mod)
|
|
{
|
|
int i;
|
|
lvm_t *vm;
|
|
lua_State *t;
|
|
gentity_t *ent;
|
|
gentity_t *inflictor;
|
|
gentity_t *attacker;
|
|
|
|
for(i = 0; i < NUM_VMS; i++)
|
|
{
|
|
vm = lVM[i];
|
|
if(vm)
|
|
{
|
|
if(vm->id < 0)
|
|
continue;
|
|
t = lua_newthread(vm->L);
|
|
if(!t) {
|
|
if(!G_LuaGetFunction(vm, function))
|
|
continue;
|
|
ent = &g_entities[entnum];
|
|
if(!ent || !ent->inuse)
|
|
lua_pushnil(vm->L);
|
|
else
|
|
Lua_PushEntity(vm->L, ent);
|
|
inflictor = &g_entities[inflictornum];
|
|
if(!inflictor || !inflictor->inuse)
|
|
lua_pushnil(vm->L);
|
|
else
|
|
Lua_PushEntity(vm->L, inflictor);
|
|
attacker = &g_entities[attackernum];
|
|
if(!attacker || !attacker->inuse)
|
|
lua_pushnil(vm->L);
|
|
else
|
|
Lua_PushEntity(vm->L, attacker);
|
|
lua_pushinteger(vm->L, dmg);
|
|
lua_pushinteger(vm->L, mod);
|
|
if(!G_LuaCall(vm, function, 5, 0))
|
|
{
|
|
continue;
|
|
}
|
|
} else {
|
|
if(!G_LuaGetFunctionT(t, function))
|
|
continue;
|
|
ent = &g_entities[entnum];
|
|
if(!ent || !ent->inuse)
|
|
lua_pushnil(t);
|
|
else
|
|
Lua_PushEntity(t, ent);
|
|
inflictor = &g_entities[inflictornum];
|
|
if(!inflictor || !inflictor->inuse)
|
|
lua_pushnil(t);
|
|
else
|
|
Lua_PushEntity(t, inflictor);
|
|
attacker = &g_entities[attackernum];
|
|
if(!attacker || !attacker->inuse)
|
|
lua_pushnil(t);
|
|
else
|
|
Lua_PushEntity(t, attacker);
|
|
lua_pushinteger(t, dmg);
|
|
lua_pushinteger(t, mod);
|
|
if(!G_LuaResume(vm, t, function, 5))
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void LuaHook_G_EntityFree(char *function, int entnum)
|
|
{
|
|
int i;
|
|
lvm_t *vm;
|
|
lua_State *t;
|
|
gentity_t *ent;
|
|
|
|
for(i = 0; i < NUM_VMS; i++)
|
|
{
|
|
vm = lVM[i];
|
|
if(vm)
|
|
{
|
|
if(vm->id < 0)
|
|
continue;
|
|
t = lua_newthread(vm->L);
|
|
if(!t) {
|
|
if(!G_LuaGetFunction(vm, function))
|
|
continue;
|
|
ent = &g_entities[entnum];
|
|
if(!ent || !ent->inuse)
|
|
lua_pushnil(vm->L);
|
|
else
|
|
Lua_PushEntity(vm->L, ent);
|
|
if(!G_LuaCall(vm, function, 1, 0))
|
|
{
|
|
continue;
|
|
}
|
|
} else {
|
|
if(!G_LuaGetFunctionT(t, function))
|
|
continue;
|
|
ent = &g_entities[entnum];
|
|
if(!ent || !ent->inuse)
|
|
lua_pushnil(t);
|
|
else
|
|
Lua_PushEntity(t, ent);
|
|
if(!G_LuaResume(vm, t, function, 1))
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void LuaHook_G_EntityReached(char *function, int entnum) {
|
|
int i;
|
|
lvm_t *vm;
|
|
lua_State *t;
|
|
gentity_t *ent;
|
|
|
|
for(i = 0; i < NUM_VMS; i++) {
|
|
vm = lVM[i];
|
|
if(vm) {
|
|
if(vm->id < 0)
|
|
continue;
|
|
t = lua_newthread(vm->L);
|
|
if(!t) {
|
|
if(!G_LuaGetFunction(vm, function))
|
|
continue;
|
|
ent = &g_entities[entnum];
|
|
if(!ent || !ent->inuse)
|
|
lua_pushnil(vm->L);
|
|
else
|
|
Lua_PushEntity(vm->L, ent);
|
|
if(!G_LuaCall(vm, function, 1, 0))
|
|
continue;
|
|
} else {
|
|
if(!G_LuaGetFunctionT(t, function))
|
|
continue;
|
|
ent = &g_entities[entnum];
|
|
if(!ent || !ent->inuse)
|
|
lua_pushnil(t);
|
|
else
|
|
Lua_PushEntity(t, ent);
|
|
if(!G_LuaResume(vm, t, function, 1))
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void LuaHook_G_EntityReachedAngular(char *function, int entnum) {
|
|
int i;
|
|
lvm_t *vm;
|
|
lua_State *t;
|
|
gentity_t *ent;
|
|
|
|
for(i = 0; i < NUM_VMS; i++) {
|
|
vm = lVM[i];
|
|
if(vm) {
|
|
if(vm->id < 0)
|
|
continue;
|
|
t = lua_newthread(vm->L);
|
|
if(!t) {
|
|
if(!G_LuaGetFunction(vm, function))
|
|
continue;
|
|
ent = &g_entities[entnum];
|
|
if(!ent || !ent->inuse)
|
|
lua_pushnil(vm->L);
|
|
else
|
|
Lua_PushEntity(vm->L, ent);
|
|
if(!G_LuaCall(vm, function, 1, 0))
|
|
continue;
|
|
} else {
|
|
if(!G_LuaGetFunctionT(t, function))
|
|
continue;
|
|
ent = &g_entities[entnum];
|
|
if(!ent || !ent->inuse)
|
|
lua_pushnil(t);
|
|
else
|
|
Lua_PushEntity(t, ent);
|
|
if(!G_LuaResume(vm, t, function, 1))
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void LuaHook_G_EntityTrigger(char *function, int entnum, int othernum)
|
|
{
|
|
int i;
|
|
lvm_t *vm;
|
|
lua_State *t;
|
|
gentity_t *ent;
|
|
gentity_t *other;
|
|
|
|
for(i = 0; i < NUM_VMS; i++)
|
|
{
|
|
vm = lVM[i];
|
|
if(vm)
|
|
{
|
|
if(vm->id < 0)
|
|
continue;
|
|
t = lua_newthread(vm->L);
|
|
if(!t) {
|
|
if(!G_LuaGetFunction(vm, function))
|
|
continue;
|
|
ent = &g_entities[entnum];
|
|
if(!ent || !ent->inuse)
|
|
lua_pushnil(vm->L);
|
|
else
|
|
Lua_PushEntity(vm->L, ent);
|
|
other = &g_entities[othernum];
|
|
if(!other || !other->inuse)
|
|
lua_pushnil(vm->L);
|
|
else
|
|
Lua_PushEntity(vm->L, other);
|
|
if(!G_LuaCall(vm, function, 2, 0))
|
|
{
|
|
continue;
|
|
}
|
|
} else {
|
|
if(!G_LuaGetFunctionT(t, function))
|
|
continue;
|
|
ent = &g_entities[entnum];
|
|
if(!ent || !ent->inuse)
|
|
lua_pushnil(t);
|
|
else
|
|
Lua_PushEntity(t, ent);
|
|
other = &g_entities[othernum];
|
|
if(!other || !other->inuse)
|
|
lua_pushnil(t);
|
|
else
|
|
Lua_PushEntity(t, other);
|
|
if(!G_LuaResume(vm, t, function, 2))
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void LuaHook_G_EntitySpawn(char *function, int entnum)
|
|
{
|
|
int i;
|
|
lvm_t *vm;
|
|
lua_State *t;
|
|
gentity_t *ent;
|
|
|
|
for(i = 0; i < NUM_VMS; i++)
|
|
{
|
|
vm = lVM[i];
|
|
if(vm)
|
|
{
|
|
if(vm->id < 0)
|
|
continue;
|
|
t = lua_newthread(vm->L);
|
|
if(!t) {
|
|
if(!G_LuaGetFunction(vm, function))
|
|
continue;
|
|
ent = &g_entities[entnum];
|
|
if(!ent || !ent->inuse)
|
|
lua_pushnil(vm->L);
|
|
else
|
|
Lua_PushEntity(vm->L, ent);
|
|
if(!G_LuaCall(vm, function, 1, 0))
|
|
{
|
|
continue;
|
|
}
|
|
} else {
|
|
if(!G_LuaGetFunctionT(t, function))
|
|
continue;
|
|
ent = &g_entities[entnum];
|
|
if(!ent || !ent->inuse)
|
|
lua_pushnil(t);
|
|
else
|
|
Lua_PushEntity(t, ent);
|
|
if(!G_LuaResume(vm, t, function, 1))
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void G_LuaNumThreads(void) {
|
|
lvm_t* vm = lVM[0];
|
|
|
|
if(vm) {
|
|
lua_State *p;
|
|
int n = lua_gettop(vm->L);
|
|
int i, cnt = 0;
|
|
|
|
for(i = 0; i <= n; i++) {
|
|
if(lua_isthread(vm->L, i)) {
|
|
cnt++;
|
|
p = lua_tothread(vm->L, i);
|
|
if(lua_status(p) == LUA_YIELD) {
|
|
G_Printf("lua thread %d is YIELDED\n", i);
|
|
} else if(lua_status(vm->L) == 0) {
|
|
G_Printf("lua thread %d is RUNNING\n", i);
|
|
}
|
|
}
|
|
}
|
|
G_Printf("Total lua thread count: %d\n", cnt);
|
|
}
|
|
}
|
|
|
|
void G_LuaCollectGarbage(void) {
|
|
lvm_t *vm;
|
|
lua_State *p;
|
|
int i, n, m;
|
|
|
|
for(i = 0; i < NUM_VMS; i++) {
|
|
vm = lVM[i];
|
|
|
|
if(vm) {
|
|
n = lua_gettop(vm->L);
|
|
|
|
for(m = n; m > 0; m--) {
|
|
if(lua_isthread(vm->L, m)) {
|
|
p = lua_tothread(vm->L, m);
|
|
lua_gc(p, LUA_GCCOLLECT, 0);
|
|
}
|
|
}
|
|
lua_gc(vm->L, LUA_GCCOLLECT, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif |