2015-03-10 07:19:51 -07:00
|
|
|
/* Copyright (C) 2015 Graham Sanderson, All Rights Reserved */
|
|
|
|
#include "extdll.h"
|
|
|
|
#include "util.h"
|
2015-03-12 01:53:44 -07:00
|
|
|
|
|
|
|
#include "cbase.h"
|
|
|
|
#include "player.h"
|
|
|
|
#include "trains.h"
|
|
|
|
#include "nodes.h"
|
|
|
|
#include "weapons.h"
|
|
|
|
#include "soundent.h"
|
|
|
|
#include "monsters.h"
|
|
|
|
#include "shake.h"
|
|
|
|
#include "decals.h"
|
|
|
|
#include "gamerules.h"
|
2015-03-10 07:19:51 -07:00
|
|
|
#include "game.h"
|
2015-03-12 01:53:44 -07:00
|
|
|
#include "pm_shared.h"
|
|
|
|
#include "hltv.h"
|
2015-03-10 07:19:51 -07:00
|
|
|
#include "gslua.h"
|
|
|
|
#include "lua/lua.hpp"
|
|
|
|
|
|
|
|
#define MAX_LUA_LIB_FUNCS 200
|
2015-03-10 07:55:52 -07:00
|
|
|
#define MAX_LUA_LIB_GLOBALS 200
|
2015-03-10 07:19:51 -07:00
|
|
|
|
2015-03-11 20:16:43 -07:00
|
|
|
static void LuaRegisterGlobals(void);
|
2015-03-12 01:53:44 -07:00
|
|
|
static void LuaRegisterPlayerUData(void);
|
2015-03-11 20:16:43 -07:00
|
|
|
static int LUA_PrintConsole(lua_State *L);
|
|
|
|
|
|
|
|
struct gsLuaRun_s g_gsLuaRun;
|
2015-03-10 07:19:51 -07:00
|
|
|
|
2015-03-10 11:04:36 -07:00
|
|
|
typedef enum gsLuaType
|
2015-03-10 07:55:52 -07:00
|
|
|
{
|
|
|
|
LTYPE_INT,
|
2015-03-10 11:04:36 -07:00
|
|
|
LTYPE_STRING,
|
|
|
|
LTYPE_FLOAT,
|
|
|
|
LTYPE_FUNC
|
2015-03-10 07:55:52 -07:00
|
|
|
} gsLuaType;
|
|
|
|
|
2015-03-10 11:04:36 -07:00
|
|
|
typedef union gsLuaGlobal
|
2015-03-10 07:55:52 -07:00
|
|
|
{
|
|
|
|
int i;
|
2015-03-10 11:04:36 -07:00
|
|
|
char const *str;
|
|
|
|
float f;
|
|
|
|
lua_CFunction fn;
|
2015-03-10 07:55:52 -07:00
|
|
|
} gsLuaGlobal;
|
|
|
|
|
|
|
|
typedef struct gsLuaRegGlobal
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
gsLuaGlobal value;
|
|
|
|
gsLuaType type;
|
|
|
|
} gsLuaRegGlobal;
|
|
|
|
|
2015-03-10 11:04:36 -07:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
LF_PRINT_CONSOLE = 6
|
|
|
|
};
|
|
|
|
|
|
|
|
static gsLuaRegGlobal gsLib_GLOBALS[] = {
|
|
|
|
{ "at_notice", at_notice, LTYPE_INT },
|
|
|
|
{ "at_console", at_console, LTYPE_INT },
|
|
|
|
{ "at_aiconsole", at_aiconsole, LTYPE_INT },
|
|
|
|
{ "at_warning", at_warning, LTYPE_INT },
|
|
|
|
{ "at_error", at_error, LTYPE_INT },
|
|
|
|
{ "at_logged", at_logged, LTYPE_INT },
|
2015-03-11 20:16:43 -07:00
|
|
|
{ "Print_Console", 0, LTYPE_FUNC }, // [marrub] c++ hates unions so this must be 0 and later be given a pointer
|
2015-03-10 07:55:52 -07:00
|
|
|
{ NULL }
|
|
|
|
};
|
|
|
|
|
2015-03-10 07:19:51 -07:00
|
|
|
// --- Init/quit ---
|
|
|
|
|
|
|
|
void LuaInit(void)
|
|
|
|
{
|
2015-03-10 11:04:36 -07:00
|
|
|
gsLib_GLOBALS[LF_PRINT_CONSOLE].value.fn = LUA_PrintConsole;
|
|
|
|
|
2015-03-10 07:19:51 -07:00
|
|
|
g_L = luaL_newstate();
|
2015-03-10 13:14:12 -07:00
|
|
|
luaopen_base(g_L);
|
|
|
|
luaopen_math(g_L);
|
|
|
|
luaopen_string(g_L);
|
|
|
|
|
2015-03-10 07:19:51 -07:00
|
|
|
g_bLuaInitialized = TRUE;
|
|
|
|
ALERT(at_console, "[HLua] Lua initialized.\n");
|
|
|
|
|
2015-03-10 07:55:52 -07:00
|
|
|
LuaRegisterGlobals();
|
2015-03-12 01:53:44 -07:00
|
|
|
LuaRegisterPlayerUData();
|
2015-03-10 07:19:51 -07:00
|
|
|
|
2015-03-11 20:16:43 -07:00
|
|
|
if(luaL_dostring(g_L, "Print_Console(at_console, \"[HLua::Lua] Initialization success!\")") == TRUE)
|
2015-03-10 07:19:51 -07:00
|
|
|
{
|
2015-03-11 20:16:43 -07:00
|
|
|
LuaError("[HLua] Failed initial Lua test.\n");
|
2015-03-10 07:19:51 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LuaQuit(void)
|
|
|
|
{
|
|
|
|
lua_close(g_L);
|
|
|
|
ALERT(at_console, "[HLua] Lua shutdown.\n");
|
|
|
|
}
|
|
|
|
|
2015-03-11 20:16:43 -07:00
|
|
|
void LuaReload(void)
|
|
|
|
{
|
|
|
|
LuaQuit();
|
|
|
|
LuaInit();
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL LuaCheckNull(void const *vpToCheck)
|
|
|
|
{
|
|
|
|
BOOL bReturn;
|
|
|
|
|
|
|
|
bReturn = (vpToCheck == NULL);
|
|
|
|
|
|
|
|
if(bReturn)
|
|
|
|
{
|
|
|
|
LuaWarning("[HLua] Null pointer exception!\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
return bReturn;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LuaCall(char *szFuncName)
|
|
|
|
{
|
|
|
|
if(lua_pcall(g_L, 0, 0, 0) != LUA_OK)
|
|
|
|
{
|
|
|
|
LuaWarning("[HLua] Failed to run function %s\nLua: %s\n", szFuncName, lua_tostring(g_L, -1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LuaCall(char *szFuncName, int iArgs)
|
2015-03-10 09:06:42 -07:00
|
|
|
{
|
2015-03-11 20:16:43 -07:00
|
|
|
if(lua_pcall(g_L, iArgs, 0, 0) != LUA_OK)
|
2015-03-10 09:06:42 -07:00
|
|
|
{
|
2015-03-11 20:16:43 -07:00
|
|
|
LuaWarning("[HLua] Failed to run function %s\nLua: %s\n", szFuncName, lua_tostring(g_L, -1));
|
2015-03-10 09:06:42 -07:00
|
|
|
}
|
|
|
|
}
|
2015-03-10 07:19:51 -07:00
|
|
|
|
2015-03-11 20:16:43 -07:00
|
|
|
void LuaSetTable(char *szIndex, float fValue)
|
|
|
|
{
|
|
|
|
lua_pushstring(g_L, szIndex);
|
|
|
|
lua_pushnumber(g_L, fValue);
|
|
|
|
lua_settable(g_L, -3);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LuaSetTable(int iIndex, float fValue)
|
|
|
|
{
|
|
|
|
lua_pushinteger(g_L, iIndex);
|
|
|
|
lua_pushnumber(g_L, fValue);
|
|
|
|
lua_settable(g_L, -3);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LuaSetTable(char *szIndex, vec3_t vValue)
|
|
|
|
{
|
|
|
|
lua_pushstring(g_L, szIndex);
|
|
|
|
lua_createtable(g_L, 3, 0);
|
2015-03-12 01:53:44 -07:00
|
|
|
LuaSetTable(1, vValue.x);
|
|
|
|
LuaSetTable(2, vValue.y);
|
|
|
|
LuaSetTable(3, vValue.z);
|
2015-03-11 20:16:43 -07:00
|
|
|
lua_settable(g_L, -3);
|
|
|
|
}
|
|
|
|
|
2015-03-10 09:06:42 -07:00
|
|
|
void LuaRunScript(char *szFileName)
|
2015-03-10 07:19:51 -07:00
|
|
|
{
|
2015-03-10 09:06:42 -07:00
|
|
|
if(luaL_dofile(g_L, szFileName) == TRUE)
|
|
|
|
{
|
2015-03-11 20:16:43 -07:00
|
|
|
LuaWarning("[HLua] Failed to run script %s\nLua: %s\n", szFileName, lua_tostring(g_L, -1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL LuaGet(char *szName, int iType, BOOL bGetField, BOOL bWarn)
|
|
|
|
{
|
|
|
|
BOOL bReturn;
|
|
|
|
int iGottenType;
|
|
|
|
|
|
|
|
if(bGetField)
|
|
|
|
{
|
|
|
|
bReturn = ((iGottenType = lua_getfield(g_L, -1, szName)) == iType);
|
2015-03-10 09:06:42 -07:00
|
|
|
}
|
2015-03-11 20:16:43 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
bReturn = ((iGottenType = lua_getglobal(g_L, szName)) == iType);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(bWarn && !bReturn) LuaWarning("[HLua] Incorrect type for %s (expected %d, got %d)\n", szName, iType, iGottenType);
|
|
|
|
|
|
|
|
return bReturn;
|
2015-03-10 07:19:51 -07:00
|
|
|
}
|
|
|
|
|
2015-03-10 09:06:42 -07:00
|
|
|
void LuaParseScripts(void)
|
2015-03-10 07:19:51 -07:00
|
|
|
{
|
2015-03-10 09:06:42 -07:00
|
|
|
FILE *fScripts;
|
|
|
|
char szLn[1024];
|
|
|
|
char szFilenamePulledOutOfMyAss[MAX_PATH];
|
|
|
|
char szAlsoPulledOutOfMyAss[MAX_PATH];
|
|
|
|
|
|
|
|
GET_GAME_DIR(szAlsoPulledOutOfMyAss);
|
|
|
|
strcat(szAlsoPulledOutOfMyAss, "/lua");
|
|
|
|
CreateDirectory(szAlsoPulledOutOfMyAss, NULL);
|
|
|
|
strcpy(szFilenamePulledOutOfMyAss, szAlsoPulledOutOfMyAss);
|
|
|
|
strcat(szFilenamePulledOutOfMyAss, "/scripts.txt");
|
|
|
|
|
|
|
|
fScripts = fopen(szFilenamePulledOutOfMyAss, "r");
|
|
|
|
|
2015-03-11 20:16:43 -07:00
|
|
|
ALERT(at_console, "[HLua] Running script table.\n");
|
|
|
|
|
2015-03-10 09:06:42 -07:00
|
|
|
if(fScripts == NULL)
|
|
|
|
{
|
|
|
|
LuaError("[HLua] Failed to open lua/scripts.txt!\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
while(fgets(szLn, 1024, fScripts) != NULL)
|
2015-03-10 07:19:51 -07:00
|
|
|
{
|
2015-03-10 09:06:42 -07:00
|
|
|
BOOL bContinue = FALSE;
|
|
|
|
if(szLn[0] == '\r' || szLn[0] == '\n') continue;
|
|
|
|
|
|
|
|
char ch = szLn[0], pvch = szLn[0];
|
|
|
|
for(int i = 1; ch != '\0'; pvch = ch, ch = szLn[i++])
|
|
|
|
{
|
|
|
|
if(i == 1) continue;
|
|
|
|
|
|
|
|
if(pvch == '/' && ch == '/')
|
|
|
|
{
|
|
|
|
bContinue = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ch == '\n' || ch == '\r')
|
|
|
|
{
|
|
|
|
szLn[i-1] = '\0';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(bContinue == TRUE) continue;
|
|
|
|
|
|
|
|
char szSeriouslyIHaveALotOfThingsInMyAss[MAX_PATH];
|
|
|
|
strcpy(szSeriouslyIHaveALotOfThingsInMyAss, szAlsoPulledOutOfMyAss);
|
|
|
|
strcat(szSeriouslyIHaveALotOfThingsInMyAss, szLn);
|
|
|
|
|
|
|
|
LuaRunScript(szSeriouslyIHaveALotOfThingsInMyAss);
|
2015-03-10 07:19:51 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-10 07:55:52 -07:00
|
|
|
// --- Binded lua functions and globals ---
|
2015-03-10 07:19:51 -07:00
|
|
|
|
2015-03-11 20:16:43 -07:00
|
|
|
static void LuaRegisterGlobals(void)
|
2015-03-10 07:55:52 -07:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
ALERT(at_console, "[HLua] Registering globals.\n");
|
|
|
|
|
|
|
|
for(i = 0; i < MAX_LUA_LIB_GLOBALS; i++)
|
|
|
|
{
|
|
|
|
if(gsLib_GLOBALS[i].name == NULL) break;
|
|
|
|
|
|
|
|
switch(gsLib_GLOBALS[i].type)
|
|
|
|
{
|
|
|
|
case LTYPE_INT: lua_pushnumber(g_L, gsLib_GLOBALS[i].value.i); break;
|
2015-03-10 11:04:36 -07:00
|
|
|
case LTYPE_STRING: lua_pushstring(g_L, gsLib_GLOBALS[i].value.str); break;
|
|
|
|
case LTYPE_FLOAT: lua_pushnumber(g_L, gsLib_GLOBALS[i].value.f); break;
|
|
|
|
case LTYPE_FUNC: lua_pushcfunction(g_L, gsLib_GLOBALS[i].value.fn); break;
|
2015-03-10 09:06:42 -07:00
|
|
|
default: LuaError("[HLua] Invalid type in global initializer!\n"); return;
|
2015-03-10 07:55:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
lua_setglobal(g_L, gsLib_GLOBALS[i].name);
|
|
|
|
}
|
|
|
|
|
|
|
|
ALERT(at_console, "[HLua] Global registry success, put out %d globals.\n", i);
|
|
|
|
}
|
|
|
|
|
2015-03-11 20:16:43 -07:00
|
|
|
static int LUA_PrintConsole(lua_State *L)
|
2015-03-10 07:19:51 -07:00
|
|
|
{
|
2015-03-10 07:55:52 -07:00
|
|
|
const char *szToWrite = luaL_checkstring(L, 2);
|
|
|
|
ALERT_TYPE eType = (ALERT_TYPE)luaL_checkinteger(L, 1);
|
2015-03-10 07:19:51 -07:00
|
|
|
LuaCheckNull(szToWrite);
|
2015-03-10 07:55:52 -07:00
|
|
|
ALERT(eType, "%s\n", szToWrite);
|
2015-03-10 07:19:51 -07:00
|
|
|
return 0;
|
|
|
|
}
|
2015-03-12 01:53:44 -07:00
|
|
|
|
|
|
|
// --- Player userdata ---
|
|
|
|
|
|
|
|
struct PLAYER_s *PLAYER_New(CBasePlayer *pPlayer)
|
|
|
|
{
|
|
|
|
struct PLAYER_s *player = (struct PLAYER_s *)lua_newuserdata(g_L, sizeof(struct PLAYER_s));
|
|
|
|
luaL_getmetatable(g_L, "PLAYER_s");
|
|
|
|
lua_setmetatable(g_L, -2);
|
|
|
|
|
|
|
|
player->ply = pPlayer;
|
|
|
|
player->pev = pPlayer->pev;
|
|
|
|
|
|
|
|
return player;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct PLAYER_s *PLAYER_Get(lua_State *L)
|
|
|
|
{
|
|
|
|
struct PLAYER_s *player;
|
|
|
|
|
|
|
|
luaL_checktype(L, 1, LUA_TUSERDATA);
|
|
|
|
player = (struct PLAYER_s *)luaL_checkudata(L, 1, "PLAYER_s");
|
|
|
|
if(player == NULL) LuaWarning("[HLua] PLAYER got invalid type\n");
|
|
|
|
|
|
|
|
return player;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define TEDIUM_REMOVER(n, v, nv) \
|
|
|
|
static int n(lua_State *L) \
|
|
|
|
{ \
|
|
|
|
struct PLAYER_s *player = PLAYER_Get(L);\
|
|
|
|
v;\
|
|
|
|
return nv;\
|
|
|
|
}
|
|
|
|
|
|
|
|
TEDIUM_REMOVER(PLAYER_GetHealth, lua_pushnumber(L, player->pev->health), 1)
|
|
|
|
TEDIUM_REMOVER(PLAYER_GetMaxHealth, lua_pushnumber(L, player->pev->max_health), 1)
|
|
|
|
TEDIUM_REMOVER(PLAYER_GetArmor, lua_pushnumber(L, player->pev->armorvalue), 1)
|
|
|
|
TEDIUM_REMOVER(PLAYER_GetPosition,
|
|
|
|
lua_createtable(g_L, 3, 0);
|
|
|
|
LuaSetTable(1, player->pev->origin.x);
|
|
|
|
LuaSetTable(2, player->pev->origin.y);
|
|
|
|
LuaSetTable(3, player->pev->origin.z), 1)
|
|
|
|
TEDIUM_REMOVER(PLAYER_GetVelocity,
|
|
|
|
lua_createtable(g_L, 3, 0);
|
|
|
|
LuaSetTable(1, player->pev->velocity.x);
|
|
|
|
LuaSetTable(2, player->pev->velocity.y);
|
|
|
|
LuaSetTable(3, player->pev->velocity.z), 1)
|
|
|
|
TEDIUM_REMOVER(PLAYER_SetHealth, float fNewVal = luaL_checknumber(L, 2); player->pev->health = fNewVal, 0)
|
|
|
|
TEDIUM_REMOVER(PLAYER_SetMaxHealth, float fNewVal = luaL_checknumber(L, 2); player->pev->max_health = fNewVal, 0)
|
|
|
|
TEDIUM_REMOVER(PLAYER_SetArmor, float fNewVal = luaL_checknumber(L, 2); player->pev->armorvalue = fNewVal, 0)
|
|
|
|
TEDIUM_REMOVER(PLAYER_SetPosition,
|
|
|
|
float fX = luaL_checknumber(L, 2); float fY = luaL_checknumber(L, 3); float fZ = luaL_checknumber(L, 4);
|
|
|
|
(player->pev->origin.x = fX, player->pev->origin.y = fY, player->pev->origin.z = fZ), 0)
|
|
|
|
TEDIUM_REMOVER(PLAYER_SetVelocity,
|
|
|
|
float fX = luaL_checknumber(L, 2); float fY = luaL_checknumber(L, 3); float fZ = luaL_checknumber(L, 4);
|
|
|
|
(player->pev->velocity.x = fX, player->pev->velocity.y = fY, player->pev->velocity.z = fZ), 0)
|
|
|
|
|
|
|
|
static const luaL_Reg gsLib_PLAYER[] = {
|
|
|
|
{ "GetHealth", PLAYER_GetHealth },
|
|
|
|
{ "GetMaxHealth", PLAYER_GetMaxHealth },
|
|
|
|
{ "GetArmor", PLAYER_GetArmor },
|
|
|
|
{ "GetPosition", PLAYER_GetPosition },
|
|
|
|
{ "GetVelocity", PLAYER_GetVelocity },
|
|
|
|
{ "SetHealth", PLAYER_SetHealth },
|
|
|
|
{ "SetMaxHealth", PLAYER_SetMaxHealth },
|
|
|
|
{ "SetArmor", PLAYER_SetArmor },
|
|
|
|
{ "SetPosition", PLAYER_SetPosition },
|
|
|
|
{ "SetVelocity", PLAYER_SetVelocity },
|
|
|
|
{ NULL, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
static void LuaRegisterPlayerUData(void)
|
|
|
|
{
|
|
|
|
luaL_newmetatable(g_L, "PLAYER_s");
|
|
|
|
lua_pushstring(g_L, "__index");
|
|
|
|
luaL_newlibtable(g_L, gsLib_PLAYER);
|
|
|
|
luaL_setfuncs(g_L, gsLib_PLAYER, 0);
|
|
|
|
lua_settable(g_L, -3);
|
|
|
|
}
|