mirror of
https://github.com/unknownworlds/NS.git
synced 2024-12-21 01:41:13 +00:00
582 lines
14 KiB
C++
582 lines
14 KiB
C++
|
//======== (C) Copyright 2002 Charles G. Cleveland All rights reserved. =========
|
||
|
//
|
||
|
// The copyright to the contents herein is the property of Charles G. Cleveland.
|
||
|
// The contents may be used and/or copied only with the written permission of
|
||
|
// Charles G. Cleveland, or in accordance with the terms and conditions stipulated in
|
||
|
// the agreement/contract under which the contents have been supplied.
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// $Workfile: AvHScriptServer.cpp $
|
||
|
// $Date: 2002/07/24 18:45:42 $
|
||
|
//
|
||
|
//-------------------------------------------------------------------------------
|
||
|
// $Log: AvHScriptServer.cpp,v $
|
||
|
// Revision 1.3 2002/07/24 18:45:42 Flayra
|
||
|
// - Linux and scripting changes
|
||
|
//
|
||
|
// Revision 1.2 2002/06/25 18:15:52 Flayra
|
||
|
// - Some enhancements and bugfixes for tutorial
|
||
|
//
|
||
|
// Revision 1.1 2002/05/23 02:33:20 Flayra
|
||
|
// - Post-crash checkin. Restored @Backup from around 4/16. Contains changes for last four weeks of development.
|
||
|
//
|
||
|
//===============================================================================
|
||
|
#include "util/nowarnings.h"
|
||
|
#include "dlls/extdll.h"
|
||
|
#include "dlls/util.h"
|
||
|
#include "dlls/cbase.h"
|
||
|
#include "dlls/player.h"
|
||
|
#include "dlls/weapons.h"
|
||
|
#include "mod/AvHScriptManager.h"
|
||
|
#include "mod/AvHGamerules.h"
|
||
|
#include "util/Checksum.h"
|
||
|
#include "util/STLUtil.h"
|
||
|
|
||
|
extern "C" {
|
||
|
#include <lua.h>
|
||
|
}
|
||
|
|
||
|
static int errormessage(lua_State* inState)
|
||
|
{
|
||
|
const char *s = lua_tostring(inState, 1);
|
||
|
if (s == NULL) s = "(no message)";
|
||
|
char theErrorMessage[2048];
|
||
|
sprintf(theErrorMessage, "Script error: %s\n", s);
|
||
|
|
||
|
//fprintf(stderr, "error: %s\n", s);
|
||
|
UTIL_ClientPrintAll(HUD_PRINTNOTIFY, theErrorMessage);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//static int execute(lua_State* inState)
|
||
|
//{
|
||
|
// // Lame hook to call into server tick
|
||
|
// int theNumServerTicks = GetGameRules()->GetServerTick();
|
||
|
//
|
||
|
// lua_getglobal(inState, "serverTick");
|
||
|
// lua_pushnumber(inState, theNumServerTicks);
|
||
|
// lua_call(inState, 1, 0);
|
||
|
//
|
||
|
// return 0;
|
||
|
//}
|
||
|
|
||
|
|
||
|
/* a simple "print". based on the code in lbaselib.c */
|
||
|
static int print(lua_State* inState)
|
||
|
{
|
||
|
int n = lua_gettop(inState);
|
||
|
int i;
|
||
|
string theString;
|
||
|
|
||
|
for (i=1; i<=n; i++)
|
||
|
{
|
||
|
if (i>1) theString = "\t";
|
||
|
if (lua_isstring(inState, i))
|
||
|
theString += string(lua_tostring(inState, i));
|
||
|
else
|
||
|
{
|
||
|
char theBuffer[512];
|
||
|
sprintf(theBuffer, "%s:%p",lua_typename(inState, lua_type(inState, i)),lua_topointer(inState,i));
|
||
|
theString += string(theBuffer);
|
||
|
}
|
||
|
}
|
||
|
//theString += string("\n");
|
||
|
|
||
|
UTIL_ClientPrintAll(HUD_PRINTNOTIFY, theString.c_str());
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// inEntityIndex, returns x, y, z
|
||
|
static int getPos(lua_State* inState)
|
||
|
{
|
||
|
int theNumReturned = 0;
|
||
|
|
||
|
// Get entity index
|
||
|
int theIndex = lua_tonumber(inState, 1);
|
||
|
if(theIndex > 0)
|
||
|
{
|
||
|
// Look it up
|
||
|
CBaseEntity* theEntity = CBaseEntity::Instance(g_engfuncs.pfnPEntityOfEntIndex(theIndex));
|
||
|
if(theEntity)
|
||
|
{
|
||
|
// Return it's angle
|
||
|
lua_pushnumber(inState, theEntity->pev->origin.x);
|
||
|
lua_pushnumber(inState, theEntity->pev->origin.y);
|
||
|
lua_pushnumber(inState, theEntity->pev->origin.z);
|
||
|
theNumReturned = 3;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return theNumReturned;
|
||
|
}
|
||
|
|
||
|
// inEntityIndex, x, y, z
|
||
|
static int setPos(lua_State* inState)
|
||
|
{
|
||
|
// Get entity index
|
||
|
int theIndex = lua_tonumber(inState, 1);
|
||
|
if(theIndex > 0)
|
||
|
{
|
||
|
// Look it up
|
||
|
CBaseEntity* theEntity = CBaseEntity::Instance(g_engfuncs.pfnPEntityOfEntIndex(theIndex));
|
||
|
if(theEntity)
|
||
|
{
|
||
|
// Set it's position
|
||
|
float theX = lua_tonumber(inState, 2);
|
||
|
float theY = lua_tonumber(inState, 3);
|
||
|
float theZ = lua_tonumber(inState, 4);
|
||
|
theEntity->pev->origin = vec3_t(theX, theY, theZ);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Return true or false
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// inEntityIndex, returns yaw, pitch, roll
|
||
|
static int getAngles(lua_State* inState)
|
||
|
{
|
||
|
int theNumReturned = 0;
|
||
|
|
||
|
// Get entity index
|
||
|
int theIndex = lua_tonumber(inState, 1);
|
||
|
if(theIndex > 0)
|
||
|
{
|
||
|
// Look it up
|
||
|
CBaseEntity* theEntity = CBaseEntity::Instance(g_engfuncs.pfnPEntityOfEntIndex(theIndex));
|
||
|
if(theEntity)
|
||
|
{
|
||
|
// Return it's angle
|
||
|
lua_pushnumber(inState, theEntity->pev->angles.x);
|
||
|
lua_pushnumber(inState, theEntity->pev->angles.y);
|
||
|
lua_pushnumber(inState, theEntity->pev->angles.z);
|
||
|
theNumReturned = 3;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return theNumReturned;
|
||
|
}
|
||
|
|
||
|
// string inEntityName
|
||
|
static int getEntityIndexWithName(lua_State* inState)
|
||
|
{
|
||
|
// Get entity name
|
||
|
int theEntityIndex = -1;
|
||
|
|
||
|
const char* theEntityName = lua_tostring(inState, 1);
|
||
|
if(theEntityName)
|
||
|
{
|
||
|
CBaseEntity* theEntity = UTIL_FindEntityByTargetname(NULL, theEntityName);
|
||
|
if(theEntity)
|
||
|
{
|
||
|
theEntityIndex = theEntity->entindex();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
lua_pushnumber(inState, theEntityIndex);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
// string targetName, int entityIndexActivator, int entityIndexCaller, useType, value
|
||
|
static int fireTargets(lua_State* inState)
|
||
|
{
|
||
|
int theNumArgs = lua_gettop(inState);
|
||
|
if(theNumArgs == 5)
|
||
|
{
|
||
|
const char* theTargetName = lua_tostring(inState, 1);
|
||
|
if(theTargetName)
|
||
|
{
|
||
|
int theActivatorIndex = lua_tonumber(inState, 2);
|
||
|
int theCallerIndex = lua_tonumber(inState, 3);
|
||
|
int theIntUseType = lua_tonumber(inState, 4);
|
||
|
float theValue = lua_tonumber(inState, 5);
|
||
|
|
||
|
// Trim to valid use types
|
||
|
theIntUseType = min(max(theIntUseType, 0), 3);
|
||
|
|
||
|
// Lookup entity indices (it's OK if either of these return NULL)
|
||
|
CBaseEntity* theActivatorEntity = CBaseEntity::Instance(g_engfuncs.pfnPEntityOfEntIndex(theActivatorIndex));
|
||
|
CBaseEntity* theCallerEntity = CBaseEntity::Instance(g_engfuncs.pfnPEntityOfEntIndex(theCallerIndex));
|
||
|
USE_TYPE theUseType = USE_TYPE(theIntUseType);
|
||
|
|
||
|
FireTargets(theTargetName, theActivatorEntity, theCallerEntity, theUseType, theValue);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// inEntityIndex, yaw, pitch, roll
|
||
|
static int setAngles(lua_State* inState)
|
||
|
{
|
||
|
bool theSuccess = false;
|
||
|
|
||
|
int theIndex = lua_tonumber(inState, 1);
|
||
|
if(theIndex > 0)
|
||
|
{
|
||
|
// Look it up
|
||
|
CBaseEntity* theEntity = CBaseEntity::Instance(g_engfuncs.pfnPEntityOfEntIndex(theIndex));
|
||
|
if(theEntity)
|
||
|
{
|
||
|
// Return it's angle
|
||
|
theEntity->pev->angles.x = lua_tonumber(inState, 2);
|
||
|
theEntity->pev->angles.y = lua_tonumber(inState, 3);
|
||
|
theEntity->pev->angles.z = lua_tonumber(inState, 4);
|
||
|
theEntity->pev->fixangle = TRUE;
|
||
|
theSuccess = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
lua_pushnumber(inState, theSuccess);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
// int inEntityIndex, returns success, health
|
||
|
static int getHealth(lua_State* inState)
|
||
|
{
|
||
|
bool theSuccess = false;
|
||
|
float theHealth = -1;
|
||
|
|
||
|
int theIndex = lua_tonumber(inState, 1);
|
||
|
if(theIndex > 0)
|
||
|
{
|
||
|
// Look it up
|
||
|
CBaseEntity* theEntity = CBaseEntity::Instance(g_engfuncs.pfnPEntityOfEntIndex(theIndex));
|
||
|
if(theEntity)
|
||
|
{
|
||
|
theHealth = theEntity->pev->health;
|
||
|
theSuccess = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
lua_pushnumber(inState, theSuccess);
|
||
|
lua_pushnumber(inState, theHealth);
|
||
|
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
// int inEntityIndex, int inHealth
|
||
|
static int setHealth(lua_State* inState)
|
||
|
{
|
||
|
bool theSuccess = false;
|
||
|
|
||
|
int theIndex = lua_tonumber(inState, 1);
|
||
|
if(theIndex > 0)
|
||
|
{
|
||
|
// Look it up
|
||
|
CBaseEntity* theEntity = CBaseEntity::Instance(g_engfuncs.pfnPEntityOfEntIndex(theIndex));
|
||
|
if(theEntity)
|
||
|
{
|
||
|
int theHealth = lua_tonumber(inState, 2);
|
||
|
theEntity->pev->health = theHealth;
|
||
|
theSuccess = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
lua_pushnumber(inState, theSuccess);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
// int inEntityIndex, returns success, team
|
||
|
static int getTeam(lua_State* inState)
|
||
|
{
|
||
|
bool theSuccess = false;
|
||
|
int theTeam = 0;
|
||
|
|
||
|
int theIndex = lua_tonumber(inState, 1);
|
||
|
if(theIndex > 0)
|
||
|
{
|
||
|
// Look it up
|
||
|
CBaseEntity* theEntity = CBaseEntity::Instance(g_engfuncs.pfnPEntityOfEntIndex(theIndex));
|
||
|
if(theEntity)
|
||
|
{
|
||
|
theTeam = theEntity->pev->team;
|
||
|
theSuccess = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
lua_pushnumber(inState, theSuccess);
|
||
|
lua_pushnumber(inState, theTeam);
|
||
|
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// takes filename, returns whether errors were encountered, returns whether checksums are identical or not
|
||
|
static int compareWorldChecksum(lua_State* inState)
|
||
|
{
|
||
|
bool theSuccess = false;
|
||
|
bool theChecksumsAreEqual = false;
|
||
|
|
||
|
const char* theFileName = lua_tostring(inState, 1);
|
||
|
Checksum theOldChecksum;
|
||
|
theSuccess = theOldChecksum.ReadFromFile(theFileName);
|
||
|
|
||
|
Checksum theNewChecksum;
|
||
|
GetGameRules()->ComputeWorldChecksum(theNewChecksum);
|
||
|
if(theSuccess)
|
||
|
{
|
||
|
StringList theErrors;
|
||
|
theChecksumsAreEqual = theNewChecksum.Compare(theOldChecksum, theErrors);
|
||
|
}
|
||
|
|
||
|
// Return function success
|
||
|
lua_pushnumber(inState, theSuccess);
|
||
|
|
||
|
// Return checksums are equal
|
||
|
lua_pushnumber(inState, theChecksumsAreEqual);
|
||
|
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
// takes filename, returns success
|
||
|
static int saveWorldChecksum(lua_State* inState)
|
||
|
{
|
||
|
bool theSuccess = false;
|
||
|
|
||
|
Checksum theChecksum;
|
||
|
GetGameRules()->ComputeWorldChecksum(theChecksum);
|
||
|
|
||
|
const char* theFileName = lua_tostring(inState, 1);
|
||
|
theSuccess = theChecksum.SaveToFile(theFileName);
|
||
|
|
||
|
// Return success
|
||
|
lua_pushnumber(inState, theSuccess);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
// int inEntityID, string itemName
|
||
|
static int giveNamedItem(lua_State* inState)
|
||
|
{
|
||
|
// Get entity index
|
||
|
int theIndex = lua_tonumber(inState, 1);
|
||
|
if(theIndex > 0)
|
||
|
{
|
||
|
// Look it up
|
||
|
CBaseEntity* theEntity = CBaseEntity::Instance(g_engfuncs.pfnPEntityOfEntIndex(theIndex));
|
||
|
if(theEntity)
|
||
|
{
|
||
|
AvHPlayer* thePlayer = dynamic_cast<AvHPlayer*>(theEntity);
|
||
|
if(thePlayer)
|
||
|
{
|
||
|
const char* theItemName = lua_tostring(inState, 2);
|
||
|
if(theItemName != NULL)
|
||
|
{
|
||
|
thePlayer->GiveNamedItem(theItemName);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// int destination, string formattedString, returns success
|
||
|
static int printMessage(lua_State* inState)
|
||
|
{
|
||
|
bool theSuccess = false;
|
||
|
|
||
|
int theNumArgs = lua_gettop(inState);
|
||
|
if(theNumArgs == 2)
|
||
|
{
|
||
|
int theMessageDest = lua_tonumber(inState, 1);
|
||
|
ALERT_TYPE theAlertType = ALERT_TYPE(min(max(theMessageDest, 0), 5));
|
||
|
|
||
|
const char* theFormattedCString = lua_tostring(inState, 2);
|
||
|
if(theFormattedCString)
|
||
|
{
|
||
|
char theCharArray[kMaxStrLen];
|
||
|
strcpy(theCharArray, theFormattedCString);
|
||
|
|
||
|
ALERT(theAlertType, theCharArray);
|
||
|
|
||
|
theSuccess = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
lua_pushnumber(inState, theSuccess);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
// int thePlayerIndex, string string (in titles.txt), returns success
|
||
|
static int sendMessage(lua_State* inState)
|
||
|
{
|
||
|
bool theSuccess = false;
|
||
|
|
||
|
int theNumArgs = lua_gettop(inState);
|
||
|
if(theNumArgs == 2)
|
||
|
{
|
||
|
int thePlayerIndex = lua_tonumber(inState, 1);
|
||
|
|
||
|
const char* theCString = lua_tostring(inState, 2);
|
||
|
if(theCString)
|
||
|
{
|
||
|
char theCharArray[kMaxStrLen];
|
||
|
strcpy(theCharArray, theCString);
|
||
|
|
||
|
CBaseEntity* theEntity = CBaseEntity::Instance(g_engfuncs.pfnPEntityOfEntIndex(thePlayerIndex));
|
||
|
if(theEntity)
|
||
|
{
|
||
|
AvHPlayer* thePlayer = dynamic_cast<AvHPlayer*>(theEntity);
|
||
|
if(thePlayer)
|
||
|
{
|
||
|
thePlayer->SendMessage(theCString, TOOLTIP);
|
||
|
theSuccess = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
lua_pushnumber(inState, theSuccess);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
// nothing passed in, nothing returned
|
||
|
static int resetWorld(lua_State* inState)
|
||
|
{
|
||
|
GetGameRules()->DeleteAndResetEntities();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// plays a precached sound
|
||
|
static int playSound(lua_State* inState)
|
||
|
{
|
||
|
int theNumArgs = lua_gettop(inState);
|
||
|
if(theNumArgs >= 2)
|
||
|
{
|
||
|
int theEntIndex = lua_tonumber(inState, 1);
|
||
|
|
||
|
const char* theSoundName = lua_tostring(inState, 2);
|
||
|
|
||
|
CBaseEntity* theEntity = CBaseEntity::Instance(g_engfuncs.pfnPEntityOfEntIndex(theEntIndex));
|
||
|
if(theEntity)
|
||
|
{
|
||
|
float theVolume = 1.0f;
|
||
|
if(theNumArgs >= 3)
|
||
|
{
|
||
|
theVolume = lua_tonumber(inState, 3);
|
||
|
}
|
||
|
|
||
|
float theAttenuation = ATTN_NORM;
|
||
|
if(theNumArgs >= 4)
|
||
|
{
|
||
|
theAttenuation = lua_tonumber(inState, 4);
|
||
|
}
|
||
|
|
||
|
EMIT_SOUND(theEntity->edict(), CHAN_AUTO, theSoundName, theVolume, theAttenuation);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// int playerIndex, string command
|
||
|
static int serverCommand(lua_State* inState)
|
||
|
{
|
||
|
// Get entity index
|
||
|
int theIndex = lua_tonumber(inState, 1);
|
||
|
if(theIndex > 0)
|
||
|
{
|
||
|
// Look it up
|
||
|
CBaseEntity* theEntity = CBaseEntity::Instance(g_engfuncs.pfnPEntityOfEntIndex(theIndex));
|
||
|
if(theEntity)
|
||
|
{
|
||
|
AvHPlayer* thePlayer = dynamic_cast<AvHPlayer*>(theEntity);
|
||
|
if(thePlayer)
|
||
|
{
|
||
|
const char* theServerCommand = lua_tostring(inState, 2);
|
||
|
if(theServerCommand != NULL)
|
||
|
{
|
||
|
GetGameRules()->ClientCommand(thePlayer, theServerCommand);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int runClientScript(lua_State* inState)
|
||
|
{
|
||
|
// Get entity index
|
||
|
int theIndex = lua_tonumber(inState, 1);
|
||
|
if(theIndex > 0)
|
||
|
{
|
||
|
// Look it up
|
||
|
CBaseEntity* theEntity = CBaseEntity::Instance(g_engfuncs.pfnPEntityOfEntIndex(theIndex));
|
||
|
if(theEntity)
|
||
|
{
|
||
|
AvHPlayer* thePlayer = dynamic_cast<AvHPlayer*>(theEntity);
|
||
|
if(thePlayer)
|
||
|
{
|
||
|
const char* theScript = lua_tostring(inState, 2);
|
||
|
if(theScript != NULL)
|
||
|
{
|
||
|
thePlayer->RunClientScript(theScript);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int setServerVariable(lua_State* inState)
|
||
|
{
|
||
|
// Get variable name
|
||
|
const char* theVariableName = lua_tostring(inState, 1);
|
||
|
if(theVariableName)
|
||
|
{
|
||
|
float theValue = lua_tonumber(inState, 2);
|
||
|
CVAR_SET_FLOAT(theVariableName, theValue);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void AvHScriptInstance::InitServer()
|
||
|
{
|
||
|
//lua_register(this->mState, LUA_ERRORMESSAGE, errormessage);
|
||
|
|
||
|
//lua_register(this->mState, "execute", execute);
|
||
|
lua_register(this->mState, "print", print);
|
||
|
|
||
|
lua_register(this->mState, "getAngles", getAngles);
|
||
|
lua_register(this->mState, "setAngles", setAngles);
|
||
|
|
||
|
lua_register(this->mState, "getEntityIndexWithName", getEntityIndexWithName);
|
||
|
lua_register(this->mState, "fireTargets", fireTargets);
|
||
|
|
||
|
lua_register(this->mState, "getPos", getPos);
|
||
|
lua_register(this->mState, "setPos", setPos);
|
||
|
|
||
|
lua_register(this->mState, "getHealth", getHealth);
|
||
|
lua_register(this->mState, "setHealth", setHealth);
|
||
|
|
||
|
lua_register(this->mState, "getTeam", getTeam);
|
||
|
|
||
|
lua_register(this->mState, "compareWorldChecksum", compareWorldChecksum);
|
||
|
lua_register(this->mState, "saveWorldChecksum", saveWorldChecksum);
|
||
|
|
||
|
lua_register(this->mState, "printMessage", printMessage);
|
||
|
lua_register(this->mState, "sendMessage", sendMessage);
|
||
|
|
||
|
lua_register(this->mState, "giveNamedItem", giveNamedItem);
|
||
|
lua_register(this->mState, "playSound", playSound);
|
||
|
lua_register(this->mState, "resetWorld", resetWorld);
|
||
|
lua_register(this->mState, "serverCommand", serverCommand);
|
||
|
lua_register(this->mState, "runClientScript", runClientScript);
|
||
|
|
||
|
lua_register(this->mState, "setServerVariable", setServerVariable);
|
||
|
}
|