// game lib for lua #include "g_lua.h" #ifdef G_LUA /*** This module provides access to some of the servers functionality. @module game */ /*** Prints text to the servers console. @function Print @param test Text to print. */ static int Game_Print(lua_State *L) { int i; char buf[MAX_STRING_CHARS]; int n = lua_gettop(L); memset(buf, 0, sizeof(buf)); lua_getglobal(L, "tostring"); LUA_DEBUG("BEGIN - game.Print"); for(i = 1; i <= n; i++) { const char *s; lua_pushvalue(L, -1); lua_pushvalue(L, i); lua_call(L, 1, 1); s = lua_tostring(L, -1); if(s == NULL) { LUA_DEBUG("ERROR - game.Print - no string"); return 1; } Q_strcat(buf, sizeof(buf), s); lua_pop(L, 1); } G_Printf("%s\n", buf); LUA_DEBUG("END - game.Print"); return 0; } /*** Prints text to the center of the screen of the client with client number clientNum. If clientNum is -1 the text gets printed for all clients. @function CenterPrint @param clientNum Client number. @param text Text to print. */ static int Game_CenterPrint(lua_State *L) { int i; char buf[MAX_STRING_CHARS]; int n = lua_gettop(L); int clNum = luaL_checknumber(L, 1); memset(buf, 0, sizeof(buf)); lua_getglobal(L, "tostring"); LUA_DEBUG("BEGIN - game.CenterPrint"); for(i = 1; i < n; i++) { const char *s; lua_pushvalue(L, -1); lua_pushvalue(L, i); lua_call(L, 1, 1); s = lua_tostring(L, 2); if(s == NULL) { LUA_DEBUG("ERROR - game.CenterPrint - no string"); lua_pushboolean(L, qfalse); return 1; } Q_strcat(buf, sizeof(buf), s); lua_pop(L, 1); } trap_SendServerCommand(clNum, va("servercprint \"" S_COLOR_WHITE "%s\n\"", buf)); LUA_DEBUG("END - game.CenterPrint"); lua_pushboolean(L, qtrue); return 1; } /*** Prints text to the clients console that has the client number clientNum. If clientNum is -1 the text gets printed to all clients consoles. @function ClientPrint @param clientNum Client number. @param text Text to print. */ static int Game_ClientPrint(lua_State *L) { int i; char buf[MAX_STRING_CHARS]; int n = lua_gettop(L); int clNum = luaL_checknumber(L, 1); gentity_t *player; memset(buf, 0, sizeof(buf)); lua_getglobal(L, "tostring"); LUA_DEBUG("BEGIN - game.ClientPrint"); for(i = 1; i < n; i++) { const char *s; lua_pushvalue(L, -1); lua_pushvalue(L, i); lua_call(L, 1, 1); s = lua_tostring(L, 2); if(s == NULL) { LUA_DEBUG("BEGIN - game.ClientPrint - no string"); lua_pushboolean(L, qfalse); return 1; } Q_strcat(buf, sizeof(buf), s); lua_pop(L, 1); } if(clNum != -1) { player = &g_entities[clNum]; if(player && player->client) { G_PrintfClient(player, "%s", buf); } } else { G_PrintfClientAll("%s", buf); } LUA_DEBUG("END - game.ClientPrint"); lua_pushboolean(L, qtrue); return 1; } /*** Prints text to the lower right corner of the screen of the client with client number clientNum. If clientNum is -1 the text gets printed for all clients. @functiton MessagePrint @param clientNum Client number. @param text Text tp print. */ static int Game_MessagePrint(lua_State *L) { int i; char buf[MAX_STRING_CHARS]; int n = lua_gettop(L); int clNum = luaL_checknumber(L, 1); memset(buf, 0, sizeof(buf)); lua_getglobal(L, "tostring"); LUA_DEBUG("BEGIN - game.MessagePrint"); for(i = 1; i < n; i++) { const char *s; lua_pushvalue(L, -1); lua_pushvalue(L, i); lua_call(L, 1, 1); s = lua_tostring(L, 2); if(s == NULL) { LUA_DEBUG("ERROR - game.MessagePrint - no string"); lua_pushboolean(L, qfalse); return 1; } Q_strcat(buf, sizeof(buf), s); lua_pop(L, 1); } trap_SendServerCommand(clNum, va("servermsg \"" S_COLOR_WHITE "%s\n\"", buf)); LUA_DEBUG("END - game.MessagePrint"); lua_pushboolean(L, qfalse); return 1; } /*** Sets a global Lua variable which is called name to value. Creates a new global variable if a variable of name does not exist. Value can be of any type. @function SetGlobal @param name Name of global variable. @param value New value for global variable. */ static int Game_SetGlobal(lua_State *L) { char *name; LUA_DEBUG("BEGIN - game.SetGlobal"); name = (char *)luaL_checkstring(L, 1); if(name == NULL) { LUA_DEBUG("ERROR - game.SetGlobal - name NULL"); lua_pushboolean(L, qfalse); return 0; } lua_pushvalue(L, 2); lua_setglobal(L, name); LUA_DEBUG("END - game.SetGlobal"); lua_pushboolean(L, qtrue); return 0; } /*** Returns the value of the global variable name. Returns nil if the variable does not exist. @function GetGlobal @param name Name of Global variable. @return value of Global variable. */ static int Game_GetGlobal(lua_State *L) { char *name; LUA_DEBUG("BEGIN - game.SetGlobal"); name = (char *)luaL_checkstring(L, 1); if(name == NULL) { LUA_DEBUG("ERROR - game.SetGlobal - name NULL"); lua_pushnil(L); return 0; } lua_getglobal(L, name); LUA_DEBUG("END - game.SetGlobal"); return 1; } // Alert-Stuff... I don't know. I feel like removing this and stick to the entity spawning and setup. // game.AlertSetup(entity ent, string greentarget, string yellowtarget, string redtarget, string bluetarget, // string greensound, string yellowsound, string redsound, string bluesound, integer mode) static int Game_AlertSetup(lua_State *L) { LUA_DEBUG("BEGIN - game.AlertSetup"); if(luaAlertState != NULL) { LUA_DEBUG("ERROR - game.AlertSetup - luaArlterState != NULL"); lua_pushboolean(L, 0); return 1; } luaAlertState = (luaAlertState_t *)malloc(sizeof(luaAlertState_t)); if(luaAlertState == NULL) { LUA_DEBUG("ERROR - game.AlertSetup - luaAlertState NULL"); lua_pushboolean(L, 0); return 1; } luaAlertState->targets[0] = (char *)luaL_checkstring(L, 1); luaAlertState->targets[1] = (char *)luaL_checkstring(L, 2); luaAlertState->targets[2] = (char *)luaL_checkstring(L, 3); luaAlertState->targets[3] = (char *)luaL_checkstring(L, 4); luaAlertState->sounds[0] = (char *)luaL_checkstring(L, 5); luaAlertState->sounds[1] = (char *)luaL_checkstring(L, 6); luaAlertState->sounds[2] = (char *)luaL_checkstring(L, 7); luaAlertState->sounds[3] = (char *)luaL_checkstring(L, 8); luaAlertState->mode = luaL_checkint(L, 9); luaAlertState->cond = 0; LUA_DEBUG("END - game.AlertSetup"); lua_pushboolean(L, 1); return 1; } static int Game_AlertAddShader(lua_State *L) { int cond; char *shader; LUA_DEBUG("BEGIN - game.AlertAddShader"); if(luaAlertState == NULL) { LUA_DEBUG("ERROR - game.AlertAddShader - luaAlertShader NULL"); lua_pushboolean(L, 0); return 1; } cond = luaL_checkint(L, 1); if(cond < 0 || cond > 3) { LUA_DEBUG("ERROR - game.AlertAddShader - cond out of range"); lua_pushboolean(L, 0); return 1; } shader = (char *)luaL_checkstring(L, 2); if(shader == NULL) { LUA_DEBUG("ERROR - game.AlertAddShader - shader NULL"); lua_pushboolean(L, 0); return 1; } if((strlen(shader) + 1) > MAX_QPATH) { LUA_DEBUG("ERROR - game.AlertAddShader - strlen(shader)+1 > MAX_QPATH"); lua_pushboolean(L, 0); return 1; } if(luaAlertState->shaders[cond] == NULL) { luaAlertState->shaders[cond] = (char *)malloc(sizeof(char) * (strlen(shader) + 1)); if(luaAlertState->shaders[cond] == NULL) { LUA_DEBUG("ERROR - game.AlertAddShader - alloc failed"); lua_pushboolean(L, 0); return 1; } strncpy(luaAlertState->shaders[cond], shader, sizeof(luaAlertState->shaders[cond])); } else { void *tmp = realloc(luaAlertState->shaders[cond], sizeof(char) * (strlen(luaAlertState->shaders[cond]) + strlen(shader) + 1)); if(tmp == NULL){ LUA_DEBUG("ERROR - game.AlertAddShader - realloc failed"); lua_pushboolean(L, 0); return 1; } luaAlertState->shaders[cond] = tmp; Com_sprintf(luaAlertState->shaders[cond], sizeof(luaAlertState->shaders[cond]), "%s\n%s", luaAlertState->shaders[cond], shader); } lua_pushboolean(L, 1); LUA_DEBUG("END - game.AlertAddShader"); return 1; } // game.Alert(entity ent, integer target, boolean silent) static int Game_Alert(lua_State *L) { /*lent_t *lent; int current, target; qboolean silent;*/ return 0; } /*** Get the current level time in milliseconds. Level time is the time since level start. @function LevelTime @return Level time in milliseconds. */ static int Game_Leveltime(lua_State * L) { LUA_DEBUG("BEGIN - game.Leveltime"); lua_pushinteger(L, level.time); LUA_DEBUG("INFO - game.Leveltime - start/return: leveltime=%d", level.time); LUA_DEBUG("BEGIN - game.Leveltime"); return 1; } /*** Damage and player or entity. @function Damage @param target Target entity. @param inflictor Inflicting entity. Can be nil. @param attacker Attacking entity. Can be nil. @param direction Direction of knockback. Can be nil. @param point Point where the damage is inflicted. Can be nil. @param damage Ammount of damage. @param dflags Damage flags. @param mod Means of death. @return Success or fail. */ static int Game_Damage(lua_State *L) { lent_t *lent; gentity_t *targ = NULL, *inflictor = NULL, *attacker = NULL; vec_t *dir = NULL, *point = NULL; int damage = 0, dflags = 0, mod = 0; LUA_DEBUG("BEGIN - game.Damage"); lent = Lua_GetEntity(L, 1); if(lent == NULL || lent->e == NULL) { LUA_DEBUG("ERROR - game.Damage - entity NULL"); lua_pushboolean(L, qfalse); return 1; } targ = lent->e; if(!lua_isnil(L, 2)) { lent = Lua_GetEntity(L, 2); if(lent && lent->e) { inflictor = lent->e; } } if(!lua_isnil(L, 3)) { lent = Lua_GetEntity(L, 3); if(lent && lent->e) { attacker = lent->e; } } if(!lua_isnil(L, 4)) { dir = Lua_GetVector(L, 4); } if(!lua_isnil(L, 5)) { point = Lua_GetVector(L, 5); } damage = (int)luaL_checknumber(L, 6); dflags = (int)luaL_checknumber(L, 7); mod = (int)luaL_checknumber(L, 8); G_Damage(targ, inflictor, attacker, dir, point, damage, dflags, mod); lua_pushboolean(L, qtrue); LUA_DEBUG("END - game.Damage"); return 1; } /*** Repair an entity. @function Repair @param target Target entity. @param rate Repair rate. @return Success or fail. */ static int Game_Repair(lua_State *L) { lent_t *lent; float rate; LUA_DEBUG("BEGIN - game.Repair"); lent = Lua_GetEntity(L, 1); if(lent == NULL || lent->e == NULL) { LUA_DEBUG("ERROR - game.Repair - entity NULL"); lua_pushboolean(L, qfalse); return 1; } rate = (float)luaL_checknumber(L, 2); G_Repair(lent->e, NULL, rate); // FIXME ... trance ent? LUA_DEBUG("END - game.Repair"); lua_pushboolean(L, qtrue); return 1; } static const luaL_Reg lib_game[] = { { "Damage", Game_Damage }, { "Repair", Game_Repair }, { "Print", Game_Print }, { "MessagePrint", Game_MessagePrint }, { "CenterPrint", Game_CenterPrint }, { "ClientPrint", Game_ClientPrint }, { "GetTime", Game_Leveltime }, { "AlertSetup", Game_AlertSetup }, { "AlertAddShader", Game_AlertAddShader }, { "Alert", Game_Alert }, { "SetGlobal", Game_SetGlobal }, { "GetGlobal", Game_GetGlobal }, { NULL, NULL } }; int Luaopen_Game(lua_State *L) { luaL_register(L, "game", lib_game); lua_pushliteral(L, "_GAMEVERSION"); lua_pushliteral(L, GAMEVERSION); return 1; } #endif