mirror of
https://github.com/UberGames/rpgxEF.git
synced 2024-11-15 01:11:25 +00:00
7827 lines
220 KiB
C
7827 lines
220 KiB
C
// Copyright (C) 1999-2000 Id Software, Inc.
|
|
//
|
|
|
|
#include "g_cmds.h"
|
|
#include "g_local.h"
|
|
#include "g_sql.h"
|
|
#include "g_main.h"
|
|
|
|
//#include <windows.h>
|
|
|
|
|
|
static void G_SayTo( gentity_t *ent, gentity_t *other, int mode, int color, const char *name, const char *message );
|
|
|
|
extern void G_CheckReplaceQueen( int clientNum );
|
|
extern qboolean PlaceDecoy( gentity_t *ent );
|
|
extern qboolean G_CallSpawn(gentity_t *ent);
|
|
|
|
extern clInitStatus_t clientInitialStatus[];
|
|
|
|
void DeathmatchScoreboardMessage( gentity_t *ent ) {
|
|
char entry[1024];
|
|
char string[1400];
|
|
int stringlength;
|
|
int i, j;
|
|
gclient_t *cl;
|
|
int numSorted;
|
|
int scoreFlags;
|
|
|
|
// send the latest information on all clients
|
|
string[0] = 0;
|
|
stringlength = 0;
|
|
scoreFlags = 0;
|
|
|
|
// don't send more than 32 scores (FIXME?)
|
|
numSorted = level.numConnectedClients;
|
|
if ( numSorted > 32 ) {
|
|
numSorted = 32;
|
|
}
|
|
|
|
for (i=0 ; i < numSorted ; i++) {
|
|
int ping;
|
|
|
|
cl = &level.clients[level.sortedClients[i]];
|
|
|
|
if ( cl->pers.connected == CON_CONNECTING ) {
|
|
ping = -1;
|
|
} else {
|
|
ping = cl->ps.ping < 999 ? cl->ps.ping : 999;
|
|
}
|
|
// TODO ajust me some things here might not be needed anymore
|
|
Com_sprintf (entry, sizeof(entry),
|
|
" %i %i %i %i %i %i %i %i %i %i %i", level.sortedClients[i],
|
|
cl->ps.persistant[PERS_SCORE], ping, (level.time - cl->pers.enterTime)/60000,
|
|
scoreFlags, g_entities[level.sortedClients[i]].s.powerups,
|
|
0,
|
|
0,
|
|
0,
|
|
cl->ps.persistant[PERS_KILLED],
|
|
((g_entities[cl->ps.clientNum].r.svFlags&SVF_ELIMINATED)!=0) );
|
|
j = strlen(entry);
|
|
if (stringlength + j > 1024)
|
|
break;
|
|
strcpy (string + stringlength, entry);
|
|
stringlength += j;
|
|
}
|
|
|
|
trap_SendServerCommand( ent-g_entities, va("scores %i %i %i%s", i,
|
|
level.teamScores[TEAM_RED], level.teamScores[TEAM_BLUE],
|
|
string ) );
|
|
}
|
|
|
|
void Cmd_Score_f( gentity_t *ent ) {
|
|
DeathmatchScoreboardMessage( ent );
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
==================
|
|
CheatsOk
|
|
==================
|
|
*/
|
|
static qboolean CheatsOk( gentity_t *ent ) {
|
|
if ( !g_cheats.integer || IsAdmin( ent ) == qfalse) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"You can't use cheats in a Roleplay Session!\n\""));
|
|
return qfalse;
|
|
}
|
|
if ( ent->health <= 0 ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"You cheat! However you're dead - so haha...\n\""));
|
|
return qfalse;
|
|
}
|
|
return qtrue;
|
|
}
|
|
|
|
char *ConcatArgs( int start ) {
|
|
int i, c, tlen;
|
|
static char line[MAX_STRING_CHARS];
|
|
int len;
|
|
char arg[MAX_STRING_CHARS];
|
|
|
|
len = 0;
|
|
c = trap_Argc();
|
|
for ( i = start ; i < c ; i++ ) {
|
|
trap_Argv( i, arg, sizeof( arg ) );
|
|
tlen = strlen( arg );
|
|
if ( len + tlen >= MAX_STRING_CHARS - 1 ) {
|
|
break;
|
|
}
|
|
memcpy( line + len, arg, tlen );
|
|
len += tlen;
|
|
if ( i != c - 1 ) {
|
|
line[len] = ' ';
|
|
len++;
|
|
}
|
|
}
|
|
|
|
line[len] = 0;
|
|
|
|
return line;
|
|
}
|
|
|
|
/*
|
|
==================
|
|
SanitizeString
|
|
|
|
Remove case and control characters
|
|
==================
|
|
*/
|
|
static void SanitizeString( char *in, char *out ) {
|
|
while ( *in ) {
|
|
if ( *in == 27 ) {
|
|
in += 2; // skip color code
|
|
continue;
|
|
}
|
|
if ( *in < 32 ) {
|
|
in++;
|
|
continue;
|
|
}
|
|
*out++ = tolower( *in++ );
|
|
}
|
|
|
|
*out = 0;
|
|
}
|
|
|
|
/*
|
|
==================
|
|
ClientNumberFromString
|
|
|
|
Returns a player number for either a number or name string
|
|
Returns -1 if invalid
|
|
==================
|
|
*/
|
|
static int ClientNumberFromString( gentity_t *to, char *s ) {
|
|
gclient_t *cl;
|
|
int idnum;
|
|
char s2[MAX_STRING_CHARS];
|
|
char n2[MAX_STRING_CHARS];
|
|
|
|
// numeric values are just slot numbers
|
|
if (s[0] >= '0' && s[0] <= '9') {
|
|
idnum = atoi( s );
|
|
if ( idnum < 0 || idnum >= level.maxclients ) {
|
|
trap_SendServerCommand( to-g_entities, va("print \"Bad client slot: %i\n\"", idnum));
|
|
return -1;
|
|
}
|
|
|
|
cl = &level.clients[idnum];
|
|
if ( cl->pers.connected != CON_CONNECTED ) {
|
|
trap_SendServerCommand( to-g_entities, va("print \"Client %i is not active\n\"", idnum));
|
|
return -1;
|
|
}
|
|
return idnum;
|
|
}
|
|
|
|
// check for a name match
|
|
SanitizeString( s, s2 );
|
|
for ( idnum=0,cl=level.clients ; idnum < level.maxclients ; idnum++,cl++ ) {
|
|
if ( cl->pers.connected != CON_CONNECTED ) {
|
|
continue;
|
|
}
|
|
SanitizeString( cl->pers.netname, n2 );
|
|
if ( !strcmp( n2, s2 ) ) {
|
|
return idnum;
|
|
}
|
|
}
|
|
|
|
trap_SendServerCommand( to-g_entities, va("print \"User %s is not on the server\n\"", s));
|
|
return -1;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
==================
|
|
Cmd_Give_f
|
|
|
|
Give items to a client
|
|
|
|
TiM: Rebuilt from scratch so
|
|
as to allow giving between yourself
|
|
and other clients.
|
|
Also, incorporated a dynamic item list
|
|
to optimize the data between the game
|
|
and the UI module.
|
|
==================
|
|
*/
|
|
|
|
static void Cmd_Give_f( gentity_t *ent ) {
|
|
char arg[64];
|
|
int clientNum;
|
|
gentity_t *targEnt;
|
|
int i;
|
|
giveItem_t *item = NULL;
|
|
qboolean self;
|
|
gclient_t *client;
|
|
playerState_t *ps;
|
|
|
|
if(!ent || !ent->client) return;
|
|
|
|
client = ent->client;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_GIVE) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
trap_Argv( 1, arg, sizeof( arg ) );
|
|
|
|
if ( !arg[0] )
|
|
return;
|
|
|
|
//lets assume the target is the player for now
|
|
clientNum = client->ps.clientNum;
|
|
ps = &client->ps;
|
|
|
|
//if first char is a num, assume we're directing to another client
|
|
if ( arg[0] >='0' && arg[0] <= '9' ) {
|
|
clientNum = atoi( arg );
|
|
|
|
if ( clientNum < 0 || clientNum >= MAX_CLIENTS ) {
|
|
trap_SendServerCommand( ent-g_entities, va( "print \"Invalid client num specified.\n\" " ) );
|
|
return;
|
|
}
|
|
|
|
targEnt = &g_entities[ clientNum ];
|
|
|
|
if ( !targEnt || !targEnt->client ) {
|
|
trap_SendServerCommand( ent-g_entities, va( "print \"Client was invalid.\n\" " ) );
|
|
return;
|
|
}
|
|
|
|
Q_strncpyz( arg, ConcatArgs( 2 ), sizeof( arg ) );
|
|
|
|
if ( !arg[0] ) {
|
|
trap_SendServerCommand( ent-g_entities, va( "print \"No Item Specified.\n\" " ) );
|
|
return;
|
|
}
|
|
|
|
client = targEnt->client;
|
|
ps = &client->ps;
|
|
|
|
self = qfalse;
|
|
}
|
|
else
|
|
{
|
|
targEnt = &g_entities[ clientNum ];
|
|
|
|
if ( !targEnt || !targEnt->client ) {
|
|
trap_SendServerCommand( ent-g_entities, va( "print \"Client was invalid.\n\" " ) );
|
|
return;
|
|
}
|
|
|
|
trap_Argv( 1, arg, sizeof( arg ) );
|
|
|
|
if ( !arg[0] ) {
|
|
trap_SendServerCommand( ent-g_entities, va( "print \"No Item Specified.\n\" " ) );
|
|
return;
|
|
}
|
|
|
|
self = qtrue;
|
|
}
|
|
|
|
if ( ps->pm_type == PM_DEAD ) {
|
|
if ( !self )
|
|
trap_SendServerCommand( ent-g_entities, va( "print \"ERROR: You cannot give items to a dead player.\"") );
|
|
else
|
|
trap_SendServerCommand( ent-g_entities, va( "print \"ERROR: You cannot receive items when you're dead.\"") );
|
|
|
|
return;
|
|
}
|
|
|
|
//loop thru all the item data we have - GSIO: changed from i++ to i--
|
|
for ( i = bg_numGiveItems - 1; i > -1; i-- ) {
|
|
item = &bg_giveItem[i];
|
|
|
|
if(item == NULL) {
|
|
continue;
|
|
}
|
|
|
|
if ( !Q_stricmp( arg, item->consoleName ) ) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( i >= bg_numGiveItems ) {
|
|
trap_SendServerCommand( ent-g_entities, va( "print \"ERROR: Specified item not found.\"") );
|
|
return;
|
|
}
|
|
|
|
if ( !self ) {
|
|
trap_SendServerCommand( ent-g_entities, va( "print \"Gave item %s to %s^7.\n\"", arg, targEnt->client->pers.netname) );
|
|
trap_SendServerCommand( targEnt-g_entities, va( "print \"Received item: %s.\n\"", arg ) );
|
|
}
|
|
|
|
//Fuck this. Why does ioEF crash if you don't break a case statement with code in it? :S
|
|
|
|
if(item == NULL) {
|
|
return;
|
|
}
|
|
|
|
switch ( item->giveType ) {
|
|
case TYPE_ALL:
|
|
targEnt->health = ps->stats[STAT_MAX_HEALTH];
|
|
|
|
ps->stats[STAT_WEAPONS] = (1 << WP_NUM_WEAPONS) - 1 - ( 1 << WP_0 );
|
|
|
|
//RPG-X: J2J - Added so you dont just get empty weapons
|
|
for ( i = MAX_WEAPONS - 1; i > -1; i-- ) { /* RPG-X | Marcin | 30/12/2008 */ // GSIO: Changed from i++ to i--
|
|
targEnt->client->ps.ammo[i] += 1;
|
|
}
|
|
|
|
ps->stats[STAT_HOLDABLE_ITEM] = BG_FindItemForHoldable( HI_SHIELD ) - bg_itemlist;
|
|
|
|
break;
|
|
case TYPE_HEALTH:
|
|
targEnt->health = ps->stats[STAT_MAX_HEALTH];
|
|
break;
|
|
case TYPE_WEAPONS:
|
|
ps->stats[STAT_WEAPONS] = (1 << WP_NUM_WEAPONS) - 1 - ( 1 << WP_0 );
|
|
|
|
//RPG-X: J2J - Added so you dont just get empty weapons
|
|
for ( i = MAX_WEAPONS -1; i > -1 ; i-- ) { // GSIO: changed from i++ to i--
|
|
targEnt->client->ps.ammo[i] += 1;
|
|
}
|
|
|
|
break;
|
|
case TYPE_AMMO:
|
|
for ( i = MAX_WEAPONS - 1; i > -1 ; i-- ) { // GSIO: changed from i++ to i--
|
|
targEnt->client->ps.ammo[i] += 1;
|
|
}
|
|
break;
|
|
case TYPE_HOLDABLE:
|
|
ps->stats[STAT_HOLDABLE_ITEM] = BG_FindItemForHoldable( (holdable_t)item->giveValue ) - bg_itemlist;
|
|
break;
|
|
case TYPE_WEAPON:
|
|
ps->stats[STAT_WEAPONS] ^= ( 1 << item->giveValue);
|
|
|
|
if ( ps->stats[STAT_WEAPONS] & ( 1 << item->giveValue) )
|
|
ps->ammo[item->giveValue] += 1;
|
|
else
|
|
ps->ammo[item->giveValue] = 0;
|
|
break;
|
|
|
|
case TYPE_POWERUP:
|
|
{
|
|
int flag = 0;
|
|
int arrayNum = 0;
|
|
|
|
if ( !Q_stricmp( item->consoleName, "god" ) ) {
|
|
flag = FL_GODMODE;
|
|
arrayNum = -1;
|
|
}
|
|
else if ( !Q_stricmp( item->consoleName, "cloak" ) ) {
|
|
flag = FL_CLOAK;
|
|
arrayNum = PW_INVIS;
|
|
}
|
|
else if ( !Q_stricmp( item->consoleName, "flight" ) ) {
|
|
flag = FL_FLY;
|
|
arrayNum = PW_FLIGHT;
|
|
}
|
|
else if ( !Q_stricmp( item->consoleName, "evasuit" ) ) {
|
|
flag = FL_FLY;
|
|
arrayNum = PW_FLIGHT;
|
|
}
|
|
|
|
targEnt->flags ^= flag;
|
|
|
|
if ( arrayNum >= 0 ) {
|
|
if( targEnt->flags & flag ) {
|
|
ps->powerups[arrayNum] = level.time + 10000000;
|
|
}
|
|
else
|
|
{
|
|
ps->powerups[arrayNum] = level.time;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
//What the absolute fudge?! What the hell is causing the EVA Suit to activate!?
|
|
if (!(ent->flags & FL_EVOSUIT))
|
|
ps->powerups[PW_EVOSUIT] = 0;
|
|
}
|
|
|
|
/*
|
|
==================
|
|
Cmd_God_f
|
|
|
|
Sets client to godmode
|
|
|
|
argv(0) god
|
|
==================
|
|
*/
|
|
static void Cmd_God_f (gentity_t *ent)
|
|
{
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_GOD) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
ent->flags ^= FL_GODMODE;
|
|
if (!(ent->flags & FL_GODMODE) )
|
|
G_PrintfClient(ent, "%s", "godmode OFF\n");
|
|
else
|
|
G_PrintfClient(ent, "%s", "godmode ON\n");
|
|
}
|
|
|
|
/*
|
|
==================
|
|
Cmd_Notarget_f
|
|
|
|
Sets client to notarget
|
|
|
|
argv(0) notarget
|
|
==================
|
|
*/
|
|
// Harry -- Do we need this? I believe this is for bots only.
|
|
static void Cmd_Notarget_f( gentity_t *ent ) {
|
|
|
|
if ( IsAdmin( ent ) == qfalse ) {
|
|
return;
|
|
}
|
|
|
|
ent->flags ^= FL_NOTARGET;
|
|
if (!(ent->flags & FL_NOTARGET) )
|
|
G_PrintfClient(ent, "%s", "notarget OFF\n");
|
|
else
|
|
G_PrintfClient(ent, "%s", "notarget ON\n");
|
|
}
|
|
|
|
|
|
/*
|
|
==================
|
|
Cmd_Noclip_f
|
|
|
|
argv(0) noclip
|
|
==================
|
|
*/
|
|
static void Cmd_Noclip_f( gentity_t *ent ) {
|
|
gclient_t *client;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_NOCLIP) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
client = ent->client;
|
|
if ( client->ps.pm_type == PM_DEAD ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"You can't noclip when you're dead!\n\""));
|
|
return;
|
|
}
|
|
|
|
if ( client->noclip ) {
|
|
G_PrintfClient(ent, "%s", "noclip OFF\n");
|
|
} else {
|
|
G_PrintfClient(ent, "%s", "noclip ON\n");
|
|
}
|
|
client->noclip = (qboolean)!client->noclip;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
==================
|
|
Cmd_LevelShot_f
|
|
|
|
This is just to help generate the level pictures
|
|
for the menus. It goes to the intermission immediately
|
|
and sends over a command to the client to resize the view,
|
|
hide the scoreboard, and take a special screenshot
|
|
==================
|
|
*/
|
|
static void Cmd_LevelShot_f( gentity_t *ent ) {
|
|
if ( !CheatsOk( ent ) ) {
|
|
return;
|
|
}
|
|
|
|
// doesn't work in single player
|
|
if ( g_gametype.integer != 0 ) {
|
|
trap_SendServerCommand( ent-g_entities,
|
|
"print \"Must be in g_gametype 0 for levelshot\n\"" );
|
|
return;
|
|
}
|
|
|
|
level.intermissiontime = -1;
|
|
// Special 'level shot' setting -- Terrible ABUSE!!! HORRIBLE NASTY HOBBITTESSSES
|
|
|
|
G_Client_BeginIntermission();
|
|
trap_SendServerCommand( ent-g_entities, "clientLevelShot" );
|
|
}
|
|
|
|
|
|
/*
|
|
=================
|
|
Cmd_Kill_f
|
|
|
|
TiM: Okay... I think
|
|
instead of making a new
|
|
func, we can just tweak this one a bit. :)
|
|
=================
|
|
*/
|
|
int lastKillTime[MAX_CLIENTS];
|
|
static void Cmd_Kill_f( gentity_t *ent )
|
|
{
|
|
int meansOfDeath = MOD_SUICIDE; //Means of death set to suicide by default
|
|
char deathMsg[MAX_STRING_TOKENS]; //The death message will never be this long, but just to be sure....
|
|
clientSession_t *sess = &ent->client->sess;
|
|
int clientNum = ent->client->ps.clientNum;
|
|
playerState_t *ps = &ent->client->ps;
|
|
clientPersistant_t *pers = &ent->client->pers;
|
|
|
|
//RPG-X: Redtechie - haha too stupid to kill them selves!
|
|
if ( g_classData[sess->sessionClass].isn00b )
|
|
{
|
|
trap_SendServerCommand( ent-g_entities, "print \"Sorry, you're too n00bish to handle this command.\n\"" );
|
|
return;
|
|
}
|
|
|
|
if ( sess->sessionTeam == TEAM_SPECTATOR ) {
|
|
return;
|
|
}
|
|
|
|
if ( rpg_allowsuicide.integer == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( lastKillTime[clientNum] > level.time - 5000 ) // Marcin - changed
|
|
{//can't flood-kill
|
|
trap_SendServerCommand( clientNum, va("cp \"Cannot suicide for %d seconds", (lastKillTime[ent->client->ps.clientNum]-(level.time-60000))/1000 ) );
|
|
return;
|
|
}
|
|
|
|
//TiM: Check for whether we have args or not
|
|
if ( trap_Argc() > 1 ) {
|
|
//Load the arguments
|
|
Q_strncpyz( deathMsg, ConcatArgs( 1 ), sizeof(deathMsg) );
|
|
|
|
//If the args are valid
|
|
if ( deathMsg[0] ) {
|
|
//switch the MOD
|
|
meansOfDeath = MOD_CUSTOM_DIE;
|
|
|
|
//broadcast the message
|
|
trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " %s\n\" ", ent->client->pers.netname, deathMsg ) );
|
|
}
|
|
}
|
|
|
|
lastKillTime[clientNum] = level.time;
|
|
ent->flags &= ~FL_GODMODE;
|
|
|
|
//RPG-X: Medics revive Support for suiciding
|
|
if(rpg_medicsrevive.integer != 0 ){
|
|
ps->stats[STAT_WEAPONS] = ( 1 << WP_0 );
|
|
ps->stats[STAT_HOLDABLE_ITEM] = HI_NONE;
|
|
ps->stats[STAT_HEALTH] = ent->health = 1;
|
|
G_Client_Die (ent, ent, ent, 1, meansOfDeath ); //MOD_SUICIDE
|
|
}else{
|
|
ps->stats[STAT_HEALTH] = ent->health = 0;
|
|
G_Client_Die (ent, ent, ent, 100000, meansOfDeath ); //MOD_SUICIDE
|
|
}
|
|
|
|
if ( rpg_kicksuiciders.integer > 0 )
|
|
{
|
|
pers->suicideCount++;
|
|
if ( pers->suicideCount >= rpg_kicksuiciders.integer )
|
|
{
|
|
trap_DropClient( clientNum, "Kicked: Too many suicides");
|
|
}
|
|
}
|
|
}
|
|
|
|
void BroadcastTeamChange( gclient_t *client, int oldTeam )
|
|
{
|
|
clientSession_t *sess = &client->sess;
|
|
clientPersistant_t *pers = &client->pers;
|
|
if ( levelExiting )
|
|
{//no need to do this during level changes
|
|
return;
|
|
}
|
|
if ( sess->sessionTeam == TEAM_RED ) {
|
|
char red_team[MAX_QPATH];
|
|
trap_GetConfigstring( CS_RED_GROUP, red_team, sizeof( red_team ) );
|
|
if (!red_team[0]) {
|
|
Q_strncpyz( red_team, "red team", sizeof( red_team ) );
|
|
}
|
|
trap_SendServerCommand( -1, va("cp \"%.15s" S_COLOR_WHITE " joined the %s.\n\"", pers->netname, red_team ) );
|
|
} else if ( sess->sessionTeam == TEAM_BLUE ) {
|
|
char blue_team[MAX_QPATH];
|
|
trap_GetConfigstring( CS_BLUE_GROUP, blue_team, sizeof( blue_team ) );
|
|
if (!blue_team[0]) {
|
|
Q_strncpyz( blue_team, "blue team", sizeof( blue_team ) );
|
|
}
|
|
trap_SendServerCommand( -1, va("cp \"%.15s" S_COLOR_WHITE " joined the %s.\n\"", pers->netname, blue_team ) );
|
|
} else if ( sess->sessionTeam == TEAM_SPECTATOR && oldTeam != TEAM_SPECTATOR ) {
|
|
trap_SendServerCommand( -1, va("cp \"%.15s" S_COLOR_WHITE " is now spectating.\n\"",
|
|
pers->netname));
|
|
} else if ( sess->sessionTeam == TEAM_FREE ) {
|
|
trap_SendServerCommand( -1, va("cp \"%.15s" S_COLOR_WHITE " joined the Roleplay Session.\n\"",
|
|
pers->netname));
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
BroadCastClassChange
|
|
|
|
Let everyone know about a team change
|
|
=================
|
|
*/
|
|
void BroadcastClassChange( gclient_t *client, pclass_t oldPClass )
|
|
{
|
|
if ( levelExiting )
|
|
{//no need to do this during level changes
|
|
return;
|
|
}
|
|
|
|
if ( g_classData[client->sess.sessionClass].message[0] )
|
|
trap_SendServerCommand( -1, va("cp \"%.15s" S_COLOR_WHITE "%s\n\"", client->pers.netname, g_classData[client->sess.sessionClass].message) );
|
|
}
|
|
|
|
qboolean SetTeam( gentity_t *ent, char *s ) {
|
|
int team, oldTeam;
|
|
gclient_t *client;
|
|
int clientNum;
|
|
spectatorState_t specState;
|
|
int specClient;
|
|
int isBot;
|
|
char info[MAX_INFO_STRING];
|
|
clientSession_t *sess;
|
|
isBot = atoi( Info_ValueForKey( info, "skill" ) );
|
|
|
|
|
|
//
|
|
// see what change is requested
|
|
//
|
|
client = ent->client;
|
|
|
|
clientNum = client - level.clients;
|
|
specClient = 0;
|
|
|
|
specState = SPECTATOR_NOT;
|
|
|
|
sess = &client->sess;
|
|
|
|
if ( g_gametype.integer >= GT_TEAM && !isBot )
|
|
{
|
|
if ( !( !Q_stricmp( s, "spectator" ) || !Q_stricmp( s, "s" ) || !Q_stricmp( s, "red" ) || !Q_stricmp( s, "r" ) || !Q_stricmp( s, "blue" ) || !Q_stricmp( s, "b" ) ) )
|
|
{
|
|
return qfalse;
|
|
}
|
|
}
|
|
|
|
if ( !Q_stricmp( s, "spectator" ) || !Q_stricmp( s, "s" ) ) {
|
|
team = TEAM_SPECTATOR;
|
|
specState = SPECTATOR_FREE;
|
|
client->noclip = (qboolean)1;
|
|
} else if ( g_gametype.integer >= GT_TEAM ) {
|
|
// if running a team game, assign player to one of the teams
|
|
specState = SPECTATOR_NOT;
|
|
if ( !Q_stricmp( s, "red" ) || !Q_stricmp( s, "r" ) ) {
|
|
team = TEAM_RED;
|
|
} else if ( !Q_stricmp( s, "blue" ) || !Q_stricmp( s, "b" ) ) {
|
|
team = TEAM_BLUE;
|
|
} else {
|
|
// pick the team with the least number of players
|
|
if ( isBot )
|
|
{
|
|
team = G_Client_PickTeam( clientNum );
|
|
}
|
|
else
|
|
{
|
|
team = TEAM_SPECTATOR;
|
|
specState = SPECTATOR_FREE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
team = TEAM_FREE;
|
|
}
|
|
|
|
// override decision if limiting the players
|
|
if ( g_gametype.integer == GT_TOURNAMENT
|
|
&& level.numNonSpectatorClients >= 2 ) {
|
|
team = TEAM_SPECTATOR;
|
|
} else if ( g_maxGameClients.integer > 0 &&
|
|
level.numNonSpectatorClients >= g_maxGameClients.integer ) {
|
|
team = TEAM_SPECTATOR;
|
|
}
|
|
|
|
//
|
|
// decide if we will allow the change
|
|
//
|
|
oldTeam = sess->sessionTeam;
|
|
if ( team == oldTeam && team != TEAM_SPECTATOR ) {
|
|
return qfalse;
|
|
}
|
|
|
|
//
|
|
// execute the team change
|
|
//
|
|
|
|
// he starts at 'base'
|
|
client->pers.teamState.state = TEAM_BEGIN;
|
|
|
|
if ( oldTeam != TEAM_SPECTATOR ) {
|
|
// Kill him (makes sure he loses flags, etc)
|
|
ent->flags &= ~FL_GODMODE;
|
|
ent->client->ps.stats[STAT_HEALTH] = ent->health = 0;
|
|
G_Client_Die (ent, NULL, NULL, 100000, MOD_RESPAWN);
|
|
|
|
}
|
|
// they go to the end of the line for tournements
|
|
if ( team == TEAM_SPECTATOR ) {
|
|
sess->spectatorTime = level.time;
|
|
}
|
|
|
|
sess->sessionTeam = (team_t)team;
|
|
sess->spectatorState = specState;
|
|
sess->spectatorClient = specClient;
|
|
|
|
BroadcastTeamChange( client, oldTeam );
|
|
|
|
// get and distribute relevent paramters
|
|
G_Client_UserinfoChanged( clientNum );
|
|
|
|
G_Client_Begin( clientNum, qfalse, qfalse, qfalse );
|
|
|
|
return qtrue;
|
|
}
|
|
|
|
char *ClassNameForValue( pclass_t pClass )
|
|
{
|
|
char buffer[MAX_QPATH];
|
|
char *ptr;
|
|
|
|
trap_Cvar_VariableStringBuffer( va( "rpg_%sPass", g_classData[pClass].consoleName ), buffer, sizeof(buffer) );
|
|
|
|
ptr = buffer;
|
|
|
|
return ptr;
|
|
}
|
|
|
|
/*
|
|
=================
|
|
ValueNameForClass
|
|
|
|
TiM: I removed this portion from the SetClass
|
|
function so I could use it in several other
|
|
sections of the code.
|
|
|
|
More effective code recycling. :)
|
|
=================
|
|
*/
|
|
|
|
pclass_t ValueNameForClass ( char* s ) {
|
|
|
|
pclass_t pclass;
|
|
char buffer[MAX_QPATH];
|
|
|
|
for ( pclass = 0; pclass < MAX_CLASSES; pclass++ )
|
|
{
|
|
if ( !g_classData[pclass].consoleName[0])
|
|
break;
|
|
|
|
trap_Cvar_VariableStringBuffer( va( "rpg_%sPass", g_classData[pclass].consoleName ), buffer, sizeof( buffer ));
|
|
|
|
if ( !Q_stricmp( buffer, s ) )
|
|
return pclass;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
=================
|
|
ValueNameForClass
|
|
|
|
TiM: Created so we can get the class
|
|
name off of the actual class, and not user input
|
|
|
|
More effective code recycling. :)
|
|
=================
|
|
*/
|
|
|
|
static char* ClassForValueName ( pclass_t pclass ) {
|
|
|
|
return g_classData[pclass].formalName;
|
|
}
|
|
|
|
/*
|
|
=================
|
|
SetClass
|
|
=================
|
|
*/
|
|
qboolean SetClass( gentity_t *ent, char *s, /*@null@*/ char *teamName, qboolean SaveToCvar ) {
|
|
int pclass, oldPClass;
|
|
gclient_t *client;
|
|
int clientNum;
|
|
qboolean wasAdmin = ent->client->LoggedAsAdmin;
|
|
clientSession_t *sess;
|
|
playerState_t *ps;
|
|
//int OldType;
|
|
|
|
//FIXME: check for appropriate game mod being on first
|
|
|
|
//FIXME: can't change class while playing
|
|
|
|
//
|
|
// see what change is requested
|
|
//
|
|
|
|
if(s == NULL || ent == NULL) {
|
|
return qfalse;
|
|
}
|
|
|
|
client = ent->client;
|
|
|
|
sess = &client->sess;
|
|
ps = &client->ps;
|
|
|
|
clientNum = client - level.clients;
|
|
|
|
//RPG-X: TiM - Code Recyclables :)
|
|
pclass = ValueNameForClass( s );
|
|
|
|
if (pclass < 0 ) {
|
|
trap_SendServerCommand( ps->clientNum, va("print \"Class doesn't exist!\n\""));
|
|
return qfalse;
|
|
}
|
|
|
|
//
|
|
// decide if we will allow the change
|
|
//
|
|
oldPClass = sess->sessionClass;
|
|
|
|
|
|
if ( pclass == oldPClass )
|
|
{
|
|
return qfalse;
|
|
}
|
|
|
|
//
|
|
// execute the class change
|
|
//
|
|
|
|
if ( g_classData[pclass].isAdmin ) {
|
|
// RPG-X | Phenix | 21/11/2004 | If they go into the admin class remove other
|
|
// admin settings
|
|
client->AdminFailed = 0;
|
|
client->LoggedAsAdmin = qfalse;
|
|
client->LoggedAsDeveloper = qfalse;
|
|
}
|
|
|
|
sess->sessionClass = pclass;
|
|
|
|
//SetPlayerClassCvar(ent);
|
|
|
|
BroadcastClassChange( client, oldPClass );
|
|
|
|
if ( teamName != NULL && SetTeam( ent, teamName ) )
|
|
{
|
|
return qtrue;
|
|
}
|
|
else
|
|
{//not changing teams or couldn't change teams
|
|
// get and distribute relevent paramters
|
|
G_Client_UserinfoChanged( clientNum );
|
|
|
|
//if in the game already, kill and respawn him, else just wait to join
|
|
if ( sess->sessionTeam == TEAM_SPECTATOR )
|
|
{// they go to the end of the line for tournaments
|
|
sess->spectatorTime = level.time;
|
|
}
|
|
else
|
|
{
|
|
//RPG-X: RedTechie - No respawn for n00bs set all info and frap that a n00b needs HERE this eliminates respawns for n00bs
|
|
if(g_classData[pclass].isn00b/*pclass == PC_N00B*/){
|
|
|
|
G_Client_Spawn(ent, 1, qfalse);
|
|
ps->stats[STAT_WEAPONS] = ( 1 << WP_0 );
|
|
ps->stats[STAT_HOLDABLE_ITEM] = HI_NONE;
|
|
|
|
//Take some admin powerups away and give some n00b powerps ;)
|
|
ent->flags &= ~FL_GODMODE;
|
|
ps->powerups[PW_FLIGHT] = 0;
|
|
ps->powerups[PW_INVIS] = 0;
|
|
ps->powerups[PW_EVOSUIT] = 0;
|
|
ps->powerups[PW_GHOST] = INT_MAX;
|
|
|
|
//Turn no clip on for the N00B so he dosnt disturb rp's
|
|
client->noclip = qtrue;
|
|
ent->r.contents = CONTENTS_CORPSE;
|
|
|
|
|
|
trap_SendServerCommand(ps->clientNum, "playN00bInsult");
|
|
}else{
|
|
// he starts at 'base' - Removed phenix
|
|
client->pers.teamState.state = TEAM_BEGIN;
|
|
|
|
// Kill him (makes sure he loses flags, etc)
|
|
ent->flags &= ~FL_GODMODE;
|
|
ps->stats[STAT_HEALTH] = ent->health = 0;
|
|
|
|
G_Client_Die (ent, NULL, NULL, 100000, MOD_RESPAWN);
|
|
G_Client_Begin( clientNum, qfalse, qfalse, qfalse );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( wasAdmin ) { // RPG-X: Marcin: people requested this... - 03/01/2009
|
|
client->LoggedAsAdmin = qtrue;
|
|
}
|
|
|
|
return qtrue;
|
|
}
|
|
|
|
void StopFollowing( gentity_t *ent ) {
|
|
playerState_t *ps = &ent->client->ps;
|
|
clientSession_t *sess = &ent->client->sess;
|
|
ps->persistant[ PERS_TEAM ] = TEAM_SPECTATOR;
|
|
sess->sessionTeam = TEAM_SPECTATOR;
|
|
sess->spectatorState = SPECTATOR_FREE;
|
|
ps->pm_flags &= ~PMF_FOLLOW;
|
|
ent->r.svFlags &= ~SVF_BOT;
|
|
ps->clientNum = ent - g_entities;
|
|
//don't be dead
|
|
ps->stats[STAT_HEALTH] = ps->stats[STAT_MAX_HEALTH];
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_Team_f
|
|
=================
|
|
*/
|
|
static void Cmd_Team_f( gentity_t *ent ) {
|
|
int oldTeam;
|
|
char s[MAX_TOKEN_CHARS];
|
|
int j;
|
|
char send[100];
|
|
gentity_t *other;
|
|
clientSession_t *sess = &ent->client->sess;
|
|
|
|
//RPG-X: Redtechie - haha to stupid to change teams!
|
|
if ( g_classData[sess->sessionClass].isn00b )
|
|
{
|
|
Com_sprintf (send, sizeof(send), "%s ^7 doesn't know when to quit trying to change teams!", ent->client->pers.netname);
|
|
|
|
for (j = MAX_GENTITIES - 1; j > -1; j--) { // GSIO: change j++ to j--, also why the gell 1023 and not MAX_GENTITIES???
|
|
if(g_entities[j].client){
|
|
other = &g_entities[j];
|
|
G_SayTo( ent, other, 5, COLOR_CYAN, "^7Server: ", send );
|
|
}
|
|
}
|
|
|
|
trap_SendServerCommand( ent-g_entities, "print \"Sorry, you're too n00bish to handle this command.\n\"" );
|
|
return;
|
|
}
|
|
|
|
oldTeam = sess->sessionTeam;
|
|
|
|
if ( trap_Argc() != 2 ) {
|
|
switch ( oldTeam ) {
|
|
case TEAM_BLUE:
|
|
trap_SendServerCommand( ent-g_entities, "print \"Blue team\n\"" );
|
|
break;
|
|
case TEAM_RED:
|
|
trap_SendServerCommand( ent-g_entities, "print \"Red team\n\"" );
|
|
break;
|
|
case TEAM_FREE:
|
|
trap_SendServerCommand( ent-g_entities, "print \"Free team\n\"" );
|
|
break;
|
|
case TEAM_SPECTATOR:
|
|
trap_SendServerCommand( ent-g_entities, "print \"Spectator team\n\"" );
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
trap_Argv( 1, s, sizeof( s ) );
|
|
|
|
// if they are playing a tournement game, count as a loss
|
|
if ( g_gametype.integer == GT_TOURNAMENT && sess->sessionTeam == TEAM_FREE )
|
|
{
|
|
sess->losses++;
|
|
}
|
|
|
|
//if this is a manual change, not an assimilation, uninitialize the clInitStatus data
|
|
SetTeam( ent, s );
|
|
|
|
ent->client->switchTeamTime = level.time + 2000;
|
|
}
|
|
|
|
/*
|
|
====================
|
|
Cmd_Ready_f
|
|
====================
|
|
*/
|
|
/**
|
|
* This function is called from the ui_sp_postgame.c as a result of clicking on the
|
|
* "next" button in non GT_TOURNAMENT games. This replaces the old system of waiting
|
|
* for the user to click an ATTACK or USE button to signal ready
|
|
* (see ClientIntermissionThink())
|
|
*
|
|
* when all clients have signaled ready, the game continues to the next match.
|
|
*/
|
|
void Cmd_Ready_f (gentity_t *ent)
|
|
{
|
|
gclient_t *client;
|
|
client = ent->client;
|
|
|
|
client->readyToExit = qtrue;
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_Class_f
|
|
=================
|
|
*/
|
|
static void Cmd_Class_f( gentity_t *ent ) {
|
|
int OldScoreclass;
|
|
char s[MAX_TOKEN_CHARS];
|
|
int j;
|
|
char send[100];
|
|
gentity_t *other;
|
|
char *className;
|
|
gclient_t *client;
|
|
clientSession_t *sess;
|
|
playerState_t *ps;
|
|
|
|
if(!ent || !ent->client)
|
|
return;
|
|
|
|
if ( ent->flags & FL_CLAMPED )
|
|
return;
|
|
|
|
client = ent->client;
|
|
sess = &client->sess;
|
|
ps = &client->ps;
|
|
|
|
//RPG-X: Marcin - fragger respawn prevention - 03/01/2009
|
|
if ( (ent->s.eFlags & EF_DEAD) && (client->fraggerTime != -1) && (client->fraggerTime > level.time)) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Sorry, you can't directly respawn after having been caught fragging.\n\"");
|
|
return;
|
|
}
|
|
|
|
//RPG-X: Redtechie - haha to stupid to change classes!
|
|
if ( g_classData[sess->sessionClass].isn00b )
|
|
{
|
|
Com_sprintf (send, sizeof(send), "%s ^7 doesn't know when to quit trying to change classes from n00bie", ent->client->pers.netname);
|
|
|
|
for (j = 0; j < MAX_CLIENTS - 1; j++) {
|
|
if(g_entities[j].client){
|
|
other = &g_entities[j];
|
|
G_SayTo( ent, other, 5, COLOR_CYAN, "^7Server: ", send );
|
|
}
|
|
}
|
|
|
|
trap_SendServerCommand( ent-g_entities, "print \"Sorry, you're too n00bish to handle this command.\n\"" );
|
|
return;
|
|
}
|
|
|
|
OldScoreclass = ps->persistant[PERS_SCORE];
|
|
|
|
if ( trap_Argc() == 1 )
|
|
{
|
|
className = g_classData[sess->sessionClass].formalName;
|
|
|
|
trap_SendServerCommand( ent-g_entities, va( "print \"\nCurrent Class: %s\nUsage: Changes the user to a different class\nCommand: Class <Class Name>\n\nType '/classlist' into the console for a more complete list\n\"", className ) );
|
|
return;
|
|
}
|
|
|
|
//trying to set your class
|
|
trap_Argv( 1, s, sizeof( s ) );
|
|
|
|
//if this is a manual change, not an assimilation, uninitialize the clInitStatus data
|
|
clientInitialStatus[ent->s.number].initialized = qfalse;
|
|
if ( SetClass( ent, s, NULL, qtrue ) )
|
|
{
|
|
ent->client->classChangeDebounceTime = level.time + (g_classChangeDebounceTime.integer*1000);
|
|
|
|
trap_SendServerCommand( ent-g_entities, va ( "pc %s", s ) );
|
|
}
|
|
ps->persistant[PERS_SCORE] = OldScoreclass;
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_Cloak_f
|
|
=================
|
|
*/
|
|
static void Cmd_Cloak_f( gentity_t *ent )
|
|
{
|
|
char arg[16];
|
|
char *msg;
|
|
playerState_t *ps;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_CLOAK) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
ps = &ent->client->ps;
|
|
|
|
trap_Argv(1, arg, sizeof(arg));
|
|
if(!arg[0]) {
|
|
G_PrintfClient(ent, "Usage: cloak 1 = cloak silent, cloak 0 = qflash\n");
|
|
return;
|
|
}
|
|
|
|
G_AddEvent(ent, EV_SET_CLOAK, atoi(arg)); //GSIO01 I know this sucks but at least it works
|
|
|
|
ent->flags ^= FL_CLOAK;
|
|
if (!(ent->flags & FL_CLOAK))
|
|
{
|
|
msg = "Cloak Is Off\n";
|
|
ps->powerups[PW_INVIS] = level.time;
|
|
}
|
|
else
|
|
{
|
|
msg = "Cloak Is On\n";
|
|
ps->powerups[PW_INVIS] = INT_MAX;
|
|
}
|
|
|
|
trap_SendServerCommand( ent-g_entities, va("print \"%s\"", msg));
|
|
|
|
}
|
|
|
|
/*
|
|
=================
|
|
RPG-X (Admin Feature)
|
|
Cmd_EvoSuit_f
|
|
Phenix - 8/8/2004
|
|
=================
|
|
*/
|
|
// Harry -- Can not call this from ingame...
|
|
static void Cmd_EvoSuit_f( gentity_t *ent )
|
|
{
|
|
char *msg;
|
|
playerState_t *ps;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_EVOSUIT) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
ps = &ent->client->ps;
|
|
|
|
ent->flags ^= FL_EVOSUIT;
|
|
if (!(ent->flags & FL_EVOSUIT))
|
|
{
|
|
msg = "You have taken an EVA Suit off\n";
|
|
ps->powerups[PW_EVOSUIT] = 0; //level.time; //eh? who put this here? -J2J
|
|
}
|
|
else
|
|
{
|
|
msg = "You have put an EVA Suit on\n";
|
|
ps->powerups[PW_EVOSUIT] = INT_MAX;
|
|
}
|
|
trap_SendServerCommand( ent-g_entities, va("print \"%s\"", msg));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
=================
|
|
Cmd_Flight_f
|
|
=================
|
|
*/
|
|
static void Cmd_Flight_f( gentity_t *ent )
|
|
{
|
|
char *msg;
|
|
playerState_t *ps;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_FLIGHT) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
ps = &ent->client->ps;
|
|
|
|
ent->flags ^= FL_FLY;
|
|
if (!(ent->flags & FL_FLY))
|
|
{
|
|
msg = "Flight Is Off\n";
|
|
ps->powerups[PW_FLIGHT] = level.time;
|
|
}
|
|
else
|
|
{
|
|
msg = "Flight Is On\n";
|
|
ps->powerups[PW_FLIGHT] = INT_MAX;
|
|
}
|
|
trap_SendServerCommand( ent-g_entities, va("print \"%s\"", msg));
|
|
}
|
|
|
|
void Cmd_FollowCycle_f( gentity_t *ent, int dir ) {
|
|
int clientnum;
|
|
int original;
|
|
clientSession_t *sess;
|
|
|
|
if ( ent->r.svFlags&SVF_BOT )
|
|
{//bots can't follow!
|
|
return;
|
|
}
|
|
|
|
sess = &ent->client->sess;
|
|
|
|
// if they are playing a tournement game, count as a loss
|
|
if ( g_gametype.integer == GT_TOURNAMENT && sess->sessionTeam == TEAM_FREE ) {
|
|
sess->losses++;
|
|
}
|
|
// first set them to spectator
|
|
if ( sess->spectatorState == SPECTATOR_NOT ) {
|
|
SetTeam( ent, "spectator" );
|
|
}
|
|
|
|
if ( dir != 1 && dir != -1 ) {
|
|
G_Error( "Cmd_FollowCycle_f: bad dir %i", dir );
|
|
}
|
|
|
|
clientnum = sess->spectatorClient;
|
|
original = clientnum;
|
|
do {
|
|
clientnum += dir;
|
|
if ( clientnum >= level.maxclients ) {
|
|
clientnum = 0;
|
|
}
|
|
if ( clientnum < 0 ) {
|
|
clientnum = level.maxclients - 1;
|
|
}
|
|
|
|
// can only follow connected clients
|
|
if ( level.clients[ clientnum ].pers.connected != CON_CONNECTED ) {
|
|
continue;
|
|
}
|
|
|
|
// can't follow another spectator, including myself
|
|
if ( level.clients[ clientnum ].sess.sessionTeam == TEAM_SPECTATOR ) {
|
|
continue;
|
|
}
|
|
|
|
//TiM: Fixed this code so it runs like b4.
|
|
// this is good, we can use it
|
|
sess->spectatorClient = clientnum;
|
|
sess->spectatorState = SPECTATOR_FOLLOW;
|
|
return;
|
|
} while ( clientnum != original );
|
|
|
|
// leave it where it was
|
|
|
|
}
|
|
|
|
/*
|
|
==================
|
|
Same Class
|
|
==================
|
|
*/
|
|
static qboolean OnSameClass( gentity_t *ent1, gentity_t *ent2 ) {
|
|
gclient_t *client1 = ent1->client;
|
|
gclient_t *client2 = ent2->client;
|
|
clientSession_t *sess1 = &client1->sess;
|
|
clientSession_t *sess2 = &client2->sess;
|
|
|
|
if ( !client1 || !client2 ) {
|
|
if ( !client1 && !client2 )
|
|
{
|
|
if ( ent1->classname && ent2->classname && atoi( ent1->classname ) == atoi( ent2->classname ) )
|
|
{
|
|
return qtrue;
|
|
}
|
|
}
|
|
else if ( !client1 )
|
|
{
|
|
if ( ent1->classname && atoi( ent1->classname ) == sess2->sessionClass)
|
|
{
|
|
return qtrue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( ent2->classname && sess1->sessionClass == atoi( ent2->classname ) )
|
|
{
|
|
return qtrue;
|
|
}
|
|
}
|
|
|
|
return qfalse;
|
|
}
|
|
|
|
if ( sess1->sessionClass == sess2->sessionClass ) {
|
|
return qtrue;
|
|
}
|
|
|
|
return qfalse;
|
|
}
|
|
|
|
/*
|
|
==================
|
|
G_Say
|
|
==================
|
|
*/
|
|
|
|
#define SAY_ALL 0
|
|
#define SAY_TEAM 1
|
|
#define SAY_TELL 2
|
|
#define SAY_INVAL 3
|
|
#define SAY_CLASS 4
|
|
#define SAY_ADMIN 5
|
|
#define SAY_TELL2 6
|
|
#define SAY_AREA 7
|
|
|
|
static void G_SayTo( gentity_t *ent, gentity_t *other, int mode, int color, const char *name, const char *message ) {
|
|
clientSession_t *sess;
|
|
|
|
if (!other) {
|
|
return;
|
|
}
|
|
if (!other->inuse) {
|
|
return;
|
|
}
|
|
if (!other->client) {
|
|
return;
|
|
}
|
|
|
|
sess = &ent->client->sess;
|
|
|
|
if ( mode == SAY_CLASS && !OnSameClass(ent, other) && (IsAdmin( other ) == qfalse) ) {
|
|
return;
|
|
}
|
|
if ( mode == SAY_ADMIN && (IsAdmin( other ) == qfalse)) {
|
|
return;
|
|
}
|
|
// no chatting to players in tournements
|
|
if ( g_gametype.integer == GT_TOURNAMENT
|
|
&& other->client->sess.sessionTeam == TEAM_FREE
|
|
&& sess->sessionTeam != TEAM_FREE ) {
|
|
return;
|
|
}
|
|
|
|
//RPG-X: RedTechie - N00B's cant chat at all
|
|
if ( g_classData[sess->sessionClass].isn00b/*ent->client->sess.sessionClass == PC_N00B*/ ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"[You're too stupid to use this command]\n\"");
|
|
return;
|
|
}
|
|
|
|
//TiM : If admins want to not see broadcast messages, here's the check.
|
|
//trap_GetUserinfo( other->client->ps.clientNum, userInfo, sizeof( userInfo ) );
|
|
if ( ( mode == SAY_CLASS || mode == SAY_ADMIN ) && (IsAdmin(other) && (other->client->noAdminChat == qtrue || rpg_respectPrivacy.integer > 0))) {
|
|
return;
|
|
}
|
|
|
|
trap_SendServerCommand( other-g_entities, va("%s \"%s%c%c%s\"",
|
|
mode == SAY_TEAM ? "tchat" : "chat",
|
|
name, Q_COLOR_ESCAPE, color, message));
|
|
}
|
|
|
|
static void G_Say( gentity_t *ent, gentity_t *target, int mode, const char *chatText ) {
|
|
int j;
|
|
gentity_t *other;
|
|
int color;
|
|
char name[80];
|
|
char text[150];
|
|
char location[64];
|
|
char *className;
|
|
gclient_t *entClient = ent->client;
|
|
gclient_t *tarClient = NULL;
|
|
clientPersistant_t *entPers = &entClient->pers;
|
|
clientPersistant_t *tarPers = NULL;
|
|
clientSession_t *entSess = &entClient->sess;
|
|
|
|
if(target && target->client) {
|
|
tarClient = target->client;
|
|
tarPers = &tarClient->pers;
|
|
}
|
|
|
|
if ( g_gametype.integer < GT_TEAM && mode == SAY_TEAM ) {
|
|
mode = SAY_ALL;
|
|
}
|
|
|
|
// DHM - Nerve :: Don't allow excessive spamming of voice chats
|
|
ent->voiceChatSquelch -= (level.time - ent->voiceChatPreviousTime);
|
|
ent->voiceChatPreviousTime = level.time;
|
|
|
|
if ( ent->voiceChatSquelch < 0 )
|
|
{
|
|
ent->voiceChatSquelch = 0;
|
|
}
|
|
|
|
if ( ent->voiceChatSquelch >= 30000 )
|
|
{
|
|
trap_SendServerCommand( ent-g_entities, "print \"^1Spam Protection^7: Chat Ignored\n\"" );
|
|
if ( rpg_kickspammers.integer > 0 )
|
|
{
|
|
entPers->kickCount++;
|
|
if ( entPers->kickCount >= rpg_kickspammers.integer )
|
|
{
|
|
trap_SendConsoleCommand( EXEC_APPEND, va("kick \"%i\"\n", entClient->ps.clientNum ) );
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
if ( rpg_chatsallowed.integer > 0)
|
|
{
|
|
ent->voiceChatSquelch += (34000 / rpg_chatsallowed.integer );
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
// dhm
|
|
|
|
switch ( mode ) {
|
|
default:
|
|
case SAY_ALL:
|
|
G_LogPrintf( "say: %s: %s (%s)\n", entPers->netname, chatText, entPers->ip );
|
|
Com_sprintf (name, sizeof(name), "^7 %s%c%c ^7: ", entPers->netname, Q_COLOR_ESCAPE, COLOR_WHITE );
|
|
color = COLOR_WHITE;
|
|
break;
|
|
case SAY_TEAM:
|
|
// Team Say has become say to all for RPG-X
|
|
G_LogPrintf( "say: %s: %s (%s)\n", entPers->netname, chatText, entPers->ip );
|
|
Com_sprintf (name, sizeof(name), "^7 %s%c%c^7: ", entPers->netname, Q_COLOR_ESCAPE, COLOR_WHITE );
|
|
color = COLOR_WHITE;
|
|
break;
|
|
case SAY_TELL:
|
|
if(tarPers)
|
|
Com_sprintf (name, sizeof(name), "^7%s ^7from %s%c%c: ", tarPers->netname, entPers->netname, Q_COLOR_ESCAPE, COLOR_WHITE );
|
|
else return;
|
|
color = COLOR_MAGENTA;
|
|
break;
|
|
case SAY_TELL2:
|
|
if(tarPers)
|
|
Com_sprintf (name, sizeof(name), "^7%s ^7from %s%c%c: ", tarPers->netname, entPers->netname, Q_COLOR_ESCAPE, COLOR_WHITE );
|
|
else return;
|
|
color = COLOR_MAGENTA;
|
|
target = ent;
|
|
break;
|
|
// CLASS SAY
|
|
case SAY_CLASS:
|
|
|
|
className = g_classData[entSess->sessionClass].formalName;
|
|
|
|
G_LogPrintf( "sayclass: %s: %s (%s)\n", entPers->netname, chatText, entPers->ip);
|
|
Com_sprintf (name, sizeof(name), "^7To all %s^7's from %s%c%c: ", className, entPers->netname, Q_COLOR_ESCAPE, COLOR_WHITE );
|
|
color = COLOR_YELLOW;
|
|
break;
|
|
case SAY_ADMIN:
|
|
if (G_Client_GetLocationMsg(ent, location, sizeof(location)) && tarPers)
|
|
Com_sprintf (name, sizeof(name), "[%s%c%c] [%s] (%s): ", entPers->netname, Q_COLOR_ESCAPE, COLOR_WHITE, tarPers->netname, location );
|
|
else if(tarPers)
|
|
Com_sprintf (name, sizeof(name), "[%s%c%c ^7To %s^7]: ", entPers->netname, Q_COLOR_ESCAPE, COLOR_WHITE, tarPers->netname );
|
|
else return;
|
|
color = COLOR_CYAN;
|
|
target = NULL;
|
|
break;
|
|
case SAY_INVAL:
|
|
G_LogPrintf( "Invalid During Intermission: %s: %s (%s)\n", entPers->netname, chatText, entPers->ip );
|
|
Com_sprintf (name, sizeof(name), "[Invalid During Intermission%c%c]: ", Q_COLOR_ESCAPE, COLOR_WHITE );
|
|
color = COLOR_GREEN;
|
|
target = ent;
|
|
break;
|
|
}
|
|
|
|
Q_strncpyz( text, chatText, sizeof(text) );
|
|
|
|
if ( target ) {
|
|
G_SayTo( ent, target, mode, color, name, text );
|
|
return;
|
|
}
|
|
|
|
// echo the text to the console
|
|
if ( g_dedicated.integer ) {
|
|
G_Printf( "%s%s\n", name, text);
|
|
}
|
|
|
|
// send it to all the apropriate clients
|
|
for (j = level.maxclients - 1; j > -1; j--) { //GSIO changed from i++ to i--
|
|
other = &g_entities[j];
|
|
if(!other)
|
|
continue;
|
|
if(!other->client)
|
|
continue;
|
|
|
|
G_SayTo( ent, other, mode, color, name, text );
|
|
}
|
|
}
|
|
|
|
/*
|
|
==================
|
|
Cmd_SayArea
|
|
==================
|
|
*/
|
|
//RPG-X: J2J - Wrote the say area function becuase the Say function is bloated and wierd memory errors appear.
|
|
static void Cmd_SayArea( gentity_t *ent, char* text)
|
|
{
|
|
|
|
gentity_t* OtherPlayer; //Entity pointers to other players in game (used in loop)
|
|
int i; //Loop Counter
|
|
gclient_t* client = ent->client;
|
|
clientPersistant_t* pers = &client->pers;
|
|
|
|
if ( g_dedicated.integer ) {
|
|
G_Printf( "%s said to area: %s\n", pers->netname, text);
|
|
}
|
|
|
|
|
|
//Loop Through Clients on the server
|
|
//RPG-X: J2J - BugFix: used to be connected clients which meant most clients were missed out and other bugs.
|
|
// Change to max clients and the loop ingores invalid players.
|
|
for(i = level.maxclients - 1; i > -1; i--) //GSIO i-- now instead of i++
|
|
{
|
|
|
|
OtherPlayer = &g_entities[i]; //Point OtherPlayer to next player
|
|
|
|
//Check is OtherPlayer is valid
|
|
if ( !OtherPlayer || !OtherPlayer->inuse || !OtherPlayer->client )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//Send message to admins warning about command being used.
|
|
//TiM - since double spamming is annoying, ensure that the target admin wants this alert
|
|
if ( !OtherPlayer->client->noAdminChat )
|
|
G_SayTo( ent, OtherPlayer, SAY_ADMIN, COLOR_CYAN, va("%s ^7said to area: ", pers->netname ), text ); //^2%s
|
|
|
|
//TiM - I have a better solution. the trap_inPVS function lets u see if two points are within the same Vis cluster
|
|
//in the BSP tree. That should mean as long as they're in the same room, regardless if they can see each other or not,
|
|
//they'll get the message
|
|
|
|
if ( trap_InPVS( client->ps.origin, OtherPlayer->client->ps.origin ) )
|
|
{
|
|
//Communicate to the player
|
|
G_SayTo( ent, OtherPlayer, SAY_TELL, COLOR_GREEN, va("%s^2: ", pers->netname), text );
|
|
}
|
|
|
|
OtherPlayer = NULL; //Reset pointer ready for next iteration.
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
==================
|
|
Cmd_Say_f
|
|
==================
|
|
*/
|
|
static void Cmd_Say_f( gentity_t *ent, int mode, qboolean arg0 ) {
|
|
char *p;
|
|
|
|
if ( trap_Argc () < 2 && !arg0 ) {
|
|
return;
|
|
}
|
|
|
|
if (arg0)
|
|
{
|
|
p = ConcatArgs( 0 );
|
|
}
|
|
else
|
|
{
|
|
p = ConcatArgs( 1 );
|
|
}
|
|
|
|
if(mode == SAY_ALL)
|
|
Cmd_SayArea(ent, p);
|
|
else
|
|
G_Say( ent, NULL, mode, p );
|
|
}
|
|
|
|
/*
|
|
==================
|
|
Cmd_Tell_f
|
|
==================
|
|
*/
|
|
static void Cmd_Tell_f( gentity_t *ent ) {
|
|
int targetNum;
|
|
gentity_t *target;
|
|
char *p;
|
|
char arg[MAX_TOKEN_CHARS];
|
|
|
|
if ( trap_Argc () < 2 ) {
|
|
return;
|
|
}
|
|
|
|
trap_Argv( 1, arg, sizeof( arg ) );
|
|
targetNum = atoi( arg );
|
|
if ( targetNum < 0 || targetNum >= level.maxclients ) {
|
|
return;
|
|
}
|
|
|
|
target = &g_entities[targetNum];
|
|
if ( !target || !target->inuse || !target->client ) {
|
|
return;
|
|
}
|
|
|
|
p = ConcatArgs( 2 );
|
|
|
|
G_LogPrintf( "tell: %s to %s: %s (%s)\n", ent->client->pers.netname, target->client->pers.netname, p, ent->client->pers.ip );
|
|
G_Say( ent, target, SAY_TELL, p );
|
|
G_Say( ent, target, SAY_TELL2, p );
|
|
G_Say( ent, target, SAY_ADMIN, p);
|
|
}
|
|
|
|
|
|
static char *gc_orders[] = {
|
|
"hold your position",
|
|
"hold this position",
|
|
"come here",
|
|
"cover me",
|
|
"guard location",
|
|
"search and destroy",
|
|
"report"
|
|
};
|
|
|
|
static void Cmd_GameCommand_f( gentity_t *ent ) {
|
|
int player;
|
|
int order;
|
|
char str[MAX_TOKEN_CHARS];
|
|
|
|
trap_Argv( 1, str, sizeof( str ) );
|
|
player = atoi( str );
|
|
trap_Argv( 2, str, sizeof( str ) );
|
|
order = atoi( str );
|
|
|
|
if ( player < 0 || player >= MAX_CLIENTS ) {
|
|
return;
|
|
}
|
|
if ( order < 0 || order > sizeof(gc_orders)/sizeof(char *) ) {
|
|
return;
|
|
}
|
|
G_Say( ent, &g_entities[player], SAY_TELL, gc_orders[order] );
|
|
G_Say( ent, ent, SAY_TELL, gc_orders[order] );
|
|
}
|
|
|
|
/*
|
|
==================
|
|
Cmd_Where_f
|
|
==================
|
|
*/
|
|
static void Cmd_Where_f( gentity_t *ent ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", vtos( ent->s.origin ) ) );
|
|
}
|
|
|
|
|
|
/*
|
|
==================
|
|
Cmd_CallVote_f
|
|
==================
|
|
*/
|
|
static void Cmd_CallVote_f( gentity_t *ent ) {
|
|
int i;
|
|
char arg1[MAX_STRING_TOKENS];
|
|
char arg2[MAX_STRING_TOKENS];
|
|
|
|
if ( !g_allowVote.integer ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Voting not allowed here.\n\"" );
|
|
return;
|
|
}
|
|
|
|
if ( level.voteTime ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"A vote is already in progress.\n\"" );
|
|
return;
|
|
}
|
|
|
|
// make sure it is a valid command to vote on
|
|
trap_Argv( 1, arg1, sizeof( arg1 ) );
|
|
trap_Argv( 2, arg2, sizeof( arg2 ) );
|
|
|
|
if( strchr( arg1, ';' ) || strchr( arg2, ';' ) ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Invalid Vote.\n\"" );
|
|
return;
|
|
}
|
|
|
|
if ( !Q_stricmp( arg1, "map_restart" ) ) {
|
|
} else if ( !Q_stricmp( arg1, "map" ) ) {
|
|
} else if ( !Q_stricmp( arg1, "kick" ) && rpg_allowvote.integer > 0 ) {
|
|
} else {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Invalid Vote Command.\n\"" );
|
|
return;
|
|
}
|
|
|
|
if ( rpg_allowspmaps.integer != 1 )
|
|
{
|
|
if ( !Q_stricmp( arg1, "map" ) &&
|
|
( !Q_stricmp( arg2, "_brig" )
|
|
|| !Q_stricmp( arg2, "_holodeck_camelot" ) || !Q_stricmp( arg2, "_holodeck_firingrange" ) || !Q_stricmp( arg2, "_holodeck_garden" ) || !Q_stricmp( arg2, "_holodeck_highnoon" ) || !Q_stricmp( arg2, "_holodeck_minigame" ) || !Q_stricmp( arg2, "_holodeck_proton" ) || !Q_stricmp( arg2, "_holodeck_proton2" ) || !Q_stricmp( arg2, "_holodeck_temple" ) || !Q_stricmp( arg2, "_holodeck_warlord" )
|
|
|| !Q_stricmp( arg2, "borg1" ) || !Q_stricmp( arg2, "borg2" ) || !Q_stricmp( arg2, "borg3" ) || !Q_stricmp( arg2, "borg4" ) || !Q_stricmp( arg2, "borg5" ) || !Q_stricmp( arg2, "borg6" )
|
|
|| !Q_stricmp( arg2, "dn1" ) || !Q_stricmp( arg2, "dn2" ) || !Q_stricmp( arg2, "dn3" ) || !Q_stricmp( arg2, "dn4" ) || !Q_stricmp( arg2, "dn5" ) || !Q_stricmp( arg2, "dn6" ) || !Q_stricmp( arg2, "dn8" )
|
|
|| !Q_stricmp( arg2, "forge1" ) || !Q_stricmp( arg2, "forge2" ) || !Q_stricmp( arg2, "forge3" ) || !Q_stricmp( arg2, "forge4" ) || !Q_stricmp( arg2, "forge5" ) || !Q_stricmp( arg2, "forgeboss" )
|
|
|| !Q_stricmp( arg2, "holodeck" )
|
|
|| !Q_stricmp( arg2, "scav1" ) || !Q_stricmp( arg2, "scav2" ) || !Q_stricmp( arg2, "scav3" ) || !Q_stricmp( arg2, "scav3b" ) || !Q_stricmp( arg2, "scav4" ) || !Q_stricmp( arg2, "scav5" ) || !Q_stricmp( arg2, "scavboss" )
|
|
|| !Q_stricmp( arg2, "stasis1" ) || !Q_stricmp( arg2, "stasis2" ) || !Q_stricmp( arg2, "stasis3" )
|
|
|| !Q_stricmp( arg2, "tour/deck01" ) || !Q_stricmp( arg2, "tour/deck02" ) || !Q_stricmp( arg2, "tour/deck03" ) || !Q_stricmp( arg2, "tour/deck04" ) || !Q_stricmp( arg2, "tour/deck05" ) || !Q_stricmp( arg2, "tour/deck08" ) || !Q_stricmp( arg2, "tour/deck09" ) || !Q_stricmp( arg2, "tour/deck10" ) || !Q_stricmp( arg2, "tour/deck11" ) || !Q_stricmp( arg2, "tour/deck15" )
|
|
|| !Q_stricmp( arg2, "tutorial" )
|
|
|| !Q_stricmp( arg2, "voy1" ) || !Q_stricmp( arg2, "voy13" ) || !Q_stricmp( arg2, "voy14" ) || !Q_stricmp( arg2, "voy15" ) || !Q_stricmp( arg2, "voy16" ) || !Q_stricmp( arg2, "voy17" ) || !Q_stricmp( arg2, "voy2" ) || !Q_stricmp( arg2, "voy20" ) || !Q_stricmp( arg2, "voy3" ) || !Q_stricmp( arg2, "voy4" ) || !Q_stricmp( arg2, "voy5" ) || !Q_stricmp( arg2, "voy6" ) || !Q_stricmp( arg2, "voy7" ) || !Q_stricmp( arg2, "voy8" ) || !Q_stricmp( arg2, "voy9" ) ) )
|
|
{
|
|
trap_SendServerCommand( ent-g_entities, "print \"Invalid Map.\n\"" );
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( !Q_stricmp( arg1, "kick" ) ) {
|
|
//TiM - if we're callvoting to kick an admin, deny it
|
|
int id = ClientNumberFromString( ent, arg2 );
|
|
|
|
//Harry Young - Check if clientnum is valid, else we get a crash
|
|
if ( id == -1 ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Error: no such client.\n\"" );
|
|
return;
|
|
}
|
|
|
|
//TiM - if we're callvoting to kick an admin, deny it
|
|
//only publicly broadcasted admins are checked
|
|
//the hidden admin login people are not to protect their nature
|
|
if ( g_classData[g_entities[id].client->ps.persistant[PERS_CLASS]].isAdmin ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Error: You are not allowed to kick admins.\n\"" );
|
|
return;
|
|
}
|
|
}
|
|
|
|
ent->client->pers.voteCount++;
|
|
|
|
if ( !Q_stricmp( arg1, "map" ) )
|
|
{
|
|
char s[MAX_STRING_CHARS];
|
|
trap_Cvar_VariableStringBuffer( "nextmap", s, sizeof(s) );
|
|
if (*s)
|
|
{
|
|
Com_sprintf( level.voteString, sizeof( level.voteString ), "%s %s; set nextmap \"%s\n\"", arg1, arg2, s );
|
|
}
|
|
else
|
|
{
|
|
Com_sprintf( level.voteString, sizeof( level.voteString ), "%s %s", arg1, arg2 );
|
|
}
|
|
}
|
|
else if ( !Q_stricmp( arg1, "map_restart" ) )
|
|
{
|
|
char serverInfo[MAX_TOKEN_CHARS];
|
|
trap_GetServerinfo( serverInfo, sizeof( serverInfo ) );
|
|
Com_sprintf( level.voteString, sizeof( level.voteString ), "%s %s", "map", Info_ValueForKey( serverInfo, "mapname" ) );
|
|
}
|
|
else
|
|
{
|
|
Com_sprintf( level.voteString, sizeof( level.voteString ), "%s %s", arg1, arg2 );
|
|
}
|
|
|
|
trap_SendServerCommand( -1, va("print \"%s called a vote.\n\"", ent->client->pers.netname ) );
|
|
|
|
// start the voting, the caller autoamtically votes yes
|
|
level.voteTime = level.time;
|
|
level.voteYes = 1;
|
|
level.voteNo = 0;
|
|
|
|
for ( i = 0 ; i < level.maxclients ; i++ ) {
|
|
level.clients[i].ps.eFlags &= ~EF_VOTED;
|
|
}
|
|
ent->client->ps.eFlags |= EF_VOTED;
|
|
|
|
trap_SetConfigstring( CS_VOTE_TIME, va("%i", level.voteTime ) );
|
|
trap_SetConfigstring( CS_VOTE_STRING, level.voteString );
|
|
trap_SetConfigstring( CS_VOTE_YES, va("%i", level.voteYes ) );
|
|
trap_SetConfigstring( CS_VOTE_NO, va("%i", level.voteNo ) );
|
|
}
|
|
|
|
/*
|
|
==================
|
|
Cmd_Vote_f
|
|
==================
|
|
*/
|
|
static void Cmd_Vote_f( gentity_t *ent ) {
|
|
char msg[64];
|
|
|
|
if ( !level.voteTime ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"No vote in progress.\n\"" );
|
|
return;
|
|
}
|
|
if ( ent->client->ps.eFlags & EF_VOTED ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Vote already cast.\n\"" );
|
|
return;
|
|
}
|
|
if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Spectators cannot vote.\n\"" );
|
|
return;
|
|
}
|
|
|
|
trap_SendServerCommand( ent-g_entities, "print \"Vote cast.\n\"" );
|
|
|
|
ent->client->ps.eFlags |= EF_VOTED;
|
|
|
|
trap_Argv( 1, msg, sizeof( msg ) );
|
|
|
|
if ( msg[0] == 'y' || msg[1] == 'Y' || msg[1] == '1' ) {
|
|
level.voteYes++;
|
|
trap_SetConfigstring( CS_VOTE_YES, va("%i", level.voteYes ) );
|
|
} else {
|
|
level.voteNo++;
|
|
trap_SetConfigstring( CS_VOTE_NO, va("%i", level.voteNo ) );
|
|
}
|
|
// a majority will be determined in G_CheckVote, which will also account
|
|
// for players entering or leaving
|
|
}
|
|
|
|
/*
|
|
==================
|
|
Cmd_ForceVote_f
|
|
==================
|
|
*/
|
|
static void Cmd_ForceVote_f( gentity_t *ent ) {
|
|
char msg[64];
|
|
gclient_t *client = ent->client;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_FORCEVOTE) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if(!rpg_adminVoteOverride.integer) { // vote override?
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: Overwrite is not allowed on this server.\n\" ") );
|
|
return;
|
|
}
|
|
|
|
if ( !level.voteTime ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"No vote in progress.\n\"" );
|
|
return;
|
|
}
|
|
if ( client->ps.eFlags & EF_VOTED ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Vote already cast.\n\"" );
|
|
return;
|
|
}
|
|
if ( client->sess.sessionTeam == TEAM_SPECTATOR ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Spectators cannot vote.\n\"" );
|
|
return;
|
|
}
|
|
|
|
trap_SendServerCommand( ent-g_entities, "print \"Vote force cast.\n\"" );
|
|
|
|
client->ps.eFlags |= EF_VOTED;
|
|
|
|
trap_Argv( 1, msg, sizeof( msg ) );
|
|
|
|
if(msg[0] == 'y' || msg[1] == 'Y' || msg[1] == '1') {
|
|
level.voteYes += 999;
|
|
trap_SetConfigstring(CS_VOTE_YES, va("%i", level.voteYes));
|
|
trap_SendServerCommand( ent-g_entities, "print \"You have overridden the vote with yes.\n\"");
|
|
} else {
|
|
level.voteNo += 999;
|
|
trap_SetConfigstring(CS_VOTE_NO, va("%i", level.voteNo));
|
|
trap_SendServerCommand( ent-g_entities, "print \"You have overridden the vote with no.\n\"");
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
=================
|
|
Cmd_SetViewpos_f
|
|
=================
|
|
*/
|
|
static void Cmd_SetViewpos_f( gentity_t *ent ) {
|
|
vec3_t origin, angles;
|
|
char buffer[MAX_TOKEN_CHARS];
|
|
int i;
|
|
|
|
if ( !g_cheats.integer && !IsAdmin( ent )) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"Cheats are not enabled on this server.\n\""));
|
|
return;
|
|
}
|
|
if ( trap_Argc() != 5 ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"usage: setviewpos x y z yaw\n\""));
|
|
return;
|
|
}
|
|
|
|
VectorClear( angles );
|
|
for ( i = 0 ; i < 3 ; i++ ) {
|
|
trap_Argv( i + 1, buffer, sizeof( buffer ) );
|
|
origin[i] = atof( buffer );
|
|
}
|
|
|
|
trap_Argv( 4, buffer, sizeof( buffer ) );
|
|
angles[YAW] = atof( buffer );
|
|
|
|
TeleportPlayer( ent, origin, angles, TP_NORMAL );
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_ForceName_f
|
|
=================
|
|
*/
|
|
static void Cmd_ForceName_f( gentity_t *ent ) {
|
|
gclient_t *cl;
|
|
gentity_t *other;
|
|
gentity_t *sayA;
|
|
int j;
|
|
char send[100];
|
|
char str[MAX_TOKEN_CHARS];
|
|
char *str2;
|
|
char clientCmd[MAX_INFO_STRING];
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_FORCEPARM) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
// find the player
|
|
trap_Argv( 1, str, sizeof( str ) );
|
|
|
|
if ( !str[0] ) { //if user added no args (ie wanted the parameters)
|
|
trap_SendServerCommand( ent->client->ps.clientNum, va("print \"\nUsage: User forces another player's name to what they specify\nCommand: ForceName <Player's ID Number> \"[New Name]\"\n\" ") );
|
|
return;
|
|
}
|
|
|
|
cl = ClientForString( str );
|
|
if ( !cl ) {
|
|
return;
|
|
}
|
|
other = g_entities + cl->ps.clientNum;
|
|
|
|
//Get there new name
|
|
str2 = ConcatArgs( 2 );
|
|
|
|
//Print out some chat text
|
|
G_LogPrintf( "%s renamed %s to %s (%s)\n", ent->client->pers.netname, other->client->pers.netname, str2, ent->client->pers.ip );
|
|
|
|
Com_sprintf (send, sizeof(send), "%s ^7renamed %s ^7to %s", ent->client->pers.netname, other->client->pers.netname, str2);
|
|
|
|
for (j = MAX_GENTITIES - 1; j > -1; j--) { // GSIO change from i++ for to i--, uses MAX_GENTITIES now
|
|
if(g_entities[j].client){
|
|
sayA = &g_entities[j];
|
|
G_SayTo( ent, sayA, SAY_ADMIN, COLOR_CYAN, "^7Server: ", send );
|
|
}
|
|
}
|
|
|
|
//Set the name
|
|
//TiM: Remember to actually load the User's Info into the variable before modifying it
|
|
//The server was parsing a NULL string. O_o
|
|
|
|
//send a command to the client and the client will do all this automatically
|
|
Com_sprintf( clientCmd, sizeof(clientCmd), "changeClientInfo name \"%s\"", str2 );
|
|
trap_SendServerCommand( cl->ps.clientNum, clientCmd );
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_ShakeCamera_f
|
|
|
|
TiM's "How inefficient this is" rant:
|
|
Oh jeez! Cut off my hands and gouge out my eyes!!!!
|
|
This has to be the most in-efficient
|
|
function I've ever seen! >.<
|
|
You don't need passworded checksum
|
|
validation type thingys to protect this from n00b players!
|
|
If you just use an InfoString instead, that's all the security
|
|
you need! Clients can't access that API!
|
|
All this is doing is contributing to un-necessary procs
|
|
and potentially adding more lag to the game O_o
|
|
=================
|
|
*/
|
|
static void Cmd_ShakeCamera_f( gentity_t *ent ) {
|
|
char arg_intensity[5];
|
|
char arg_duration[5];
|
|
int duration;
|
|
int intensity;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_FX) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
trap_Argv( 1, arg_intensity, sizeof( arg_intensity ) );
|
|
|
|
//TiM : More userfriendly
|
|
if ( !arg_intensity[0] ) { //if user added no args (ie wanted the parameters)
|
|
trap_SendServerCommand( ent->client->ps.clientNum, va("print \"\nUsage: User makes every player's screen shake for X seconds\nCommand: Shake [Intensity] [Duration]\n\" ") );
|
|
return;
|
|
}
|
|
|
|
//TiM: Intensity can be a float
|
|
intensity = atoi( arg_intensity );
|
|
|
|
if(intensity <= 0 ){
|
|
return;
|
|
}
|
|
//I'm putting much faith in admins here
|
|
else if(intensity > 9999 ){
|
|
intensity = 9999;
|
|
}
|
|
|
|
trap_Argv( 2, arg_duration, sizeof( arg_duration ) );
|
|
duration = atoi( arg_duration );
|
|
|
|
if(duration < 1){
|
|
duration = 1;
|
|
}
|
|
if(duration > 10000){
|
|
duration = 10000;
|
|
}
|
|
|
|
//More or less, this will be the time the effect ends. As long as cg.time is
|
|
//in sync more or less this should be better. We can't use a raw value, or else
|
|
//joining clients will be out of sync
|
|
duration = ( duration * 1000 ) + (level.time - level.startTime );
|
|
|
|
trap_SetConfigstring( CS_CAMERA_SHAKE, va( "%i %i", intensity, duration ) );
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_ForceClass_f
|
|
=================
|
|
*/
|
|
// Harry -- How to call this one?
|
|
static void Cmd_ForceClass_f( gentity_t *ent ) {
|
|
int targetNum;
|
|
int j;
|
|
gentity_t *target;
|
|
gentity_t *other;
|
|
char send[80];
|
|
char arg[MAX_TOKEN_CHARS];
|
|
char s[MAX_TOKEN_CHARS];
|
|
int OldScoreclass;
|
|
|
|
if ( trap_Argc () < 2 ) {
|
|
return;
|
|
}
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_FORCEPARM) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
trap_Argv( 1, arg, sizeof( arg ) );
|
|
|
|
targetNum = atoi( arg );
|
|
if ( targetNum < 0 || targetNum >= level.maxclients ) {
|
|
return;
|
|
}
|
|
|
|
target = &g_entities[targetNum];
|
|
if ( !target || !target->inuse || !target->client ) {
|
|
return;
|
|
}
|
|
|
|
//RPG-X: RedTechie - Save old rank
|
|
OldScoreclass = target->client->ps.persistant[PERS_SCORE];
|
|
|
|
if ( trap_Argc() != 3 )
|
|
{//Just asking what class they're on
|
|
char *className;
|
|
|
|
className = g_classData[ent->client->sess.sessionClass].formalName;
|
|
|
|
trap_SendServerCommand( ent-g_entities, va( "print \"\nCurrent Class: %s\nUsage: Changes the user to a different class\nCommand: Class <Class Name>\n\nType '/classlist' into the console for a more complete list\n\"", className ) );
|
|
return;
|
|
}
|
|
|
|
//trying to set there class
|
|
trap_Argv( 2, s, sizeof( s ) );
|
|
|
|
//if this is a manual change, not an assimilation, uninitialize the clInitStatus data
|
|
clientInitialStatus[target->s.number].initialized = qfalse;
|
|
if ( !SetClass( target, s, NULL, qfalse ) ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"ERROR: Was unable to change class\n\" " );
|
|
return;
|
|
}
|
|
|
|
//RPG-X: RedTechie - Update rank to old
|
|
target->client->ps.persistant[PERS_SCORE] = OldScoreclass;
|
|
|
|
Com_sprintf (send, sizeof(send), "%s ^7put %s into the ^7%s class", ent->client->pers.netname, target->client->pers.netname, ClassForValueName( target->client->sess.sessionClass ) );
|
|
|
|
for (j = 0; j < MAX_CLIENTS; j++) {
|
|
if(g_entities[j].client){
|
|
other = &g_entities[j];
|
|
G_SayTo( ent, other, SAY_ADMIN, COLOR_CYAN, "^7Server: ", send );
|
|
}
|
|
}
|
|
|
|
G_LogPrintf( "%s made %s a %s (%s)\n", ent->client->pers.netname, target->client->pers.netname, s, ent->client->pers.ip);
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_ForceKill_f //J2J to others: PLEASE CAN WE COMMENT THE CODE!!!! :P
|
|
=================
|
|
*/
|
|
static void Cmd_ForceKill_f( gentity_t *ent ) {
|
|
int targetNum;
|
|
int j, p;
|
|
char send[80];
|
|
gentity_t *target = NULL;
|
|
gentity_t *other;
|
|
char arg[MAX_TOKEN_CHARS];
|
|
playerState_t *ps;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_FORCEKILL) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if ( trap_Argc () < 2 ) {
|
|
return;
|
|
}
|
|
|
|
trap_Argv( 1, arg, sizeof( arg ) );
|
|
targetNum = atoi( arg );
|
|
if ( targetNum >= level.maxclients ) {
|
|
return;
|
|
}
|
|
|
|
if ( targetNum == -1 ) {
|
|
for(p = 0; p < level.maxclients; p++)
|
|
{
|
|
target = &g_entities[p];
|
|
if ( !target || !target->inuse || !target->client ) {
|
|
return;
|
|
}
|
|
|
|
ps = &target->client->ps;
|
|
|
|
lastKillTime[ps->clientNum] = level.time;
|
|
target->flags &= ~FL_GODMODE; //Bypass godmode (?)
|
|
|
|
//RPG-X: Medics revive Support for suiciding
|
|
if(rpg_medicsrevive.integer == 1){
|
|
ps->stats[STAT_WEAPONS] = ( 1 << WP_0 );
|
|
ps->stats[STAT_HOLDABLE_ITEM] = HI_NONE;
|
|
ps->stats[STAT_HEALTH] = target->health = 1;
|
|
G_Client_Die (target, target, target, 100000, MOD_FORCEDSUICIDE);
|
|
}else{
|
|
ps->stats[STAT_HEALTH] = target->health = 0;
|
|
G_Client_Die (target, target, target, 100000, MOD_FORCEDSUICIDE);
|
|
}
|
|
} // end iterations
|
|
|
|
if(target == NULL) {
|
|
return;
|
|
}
|
|
|
|
Com_sprintf (send, sizeof(send), "%s ^7forced %s^7's death", ent->client->pers.netname, target->client->pers.netname);
|
|
|
|
for (j = 0; j < MAX_CLIENTS - 1; j++) {
|
|
if(g_entities[j].client){
|
|
other = &g_entities[j];
|
|
G_SayTo( ent, other, SAY_ADMIN, COLOR_CYAN, "^7Server: ", send );
|
|
}
|
|
}
|
|
|
|
G_LogPrintf( "%s forced everyones death\n", ent->client->pers.netname );
|
|
}
|
|
|
|
else //one vs all
|
|
|
|
{
|
|
target = &g_entities[targetNum];
|
|
if ( !target || !target->inuse || !target->client ) {
|
|
return;
|
|
}
|
|
|
|
ps = &target->client->ps;
|
|
|
|
lastKillTime[ps->clientNum] = level.time;
|
|
target->flags &= ~FL_GODMODE; //Bypass godmode (?)
|
|
|
|
//RPG-X: Medics revive Support for suiciding
|
|
if(rpg_medicsrevive.integer == 1){
|
|
ps->stats[STAT_WEAPONS] = ( 1 << WP_0 );
|
|
ps->stats[STAT_HOLDABLE_ITEM] = HI_NONE;
|
|
ps->stats[STAT_HEALTH] = target->health = 1;
|
|
G_Client_Die (target, target, target, 100000, MOD_FORCEDSUICIDE);
|
|
}else{
|
|
ps->stats[STAT_HEALTH] = target->health = 0;
|
|
G_Client_Die (target, target, target, 100000, MOD_FORCEDSUICIDE);
|
|
}
|
|
|
|
Com_sprintf (send, sizeof(send), "%s ^7forced %s^7's death", ent->client->pers.netname, target->client->pers.netname);
|
|
|
|
for (j = 0; j < MAX_CLIENTS - 1; j++) {
|
|
if(g_entities[j].client){
|
|
other = &g_entities[j];
|
|
G_SayTo( ent, other, SAY_ADMIN, COLOR_CYAN, "^7Server: ", send );
|
|
}
|
|
}
|
|
|
|
G_LogPrintf( "%s forced %s's death (%s)\n", ent->client->pers.netname, target->client->pers.netname, ent->client->pers.ip );
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
ForceKillRadius (RPG-X: J2J)
|
|
=================
|
|
*/
|
|
//Array used to store each players last use of the FKR command. (though only applies to admins)
|
|
int LastFKRadius[MAX_CLIENTS];
|
|
|
|
static void Cmd_ForceKillRadius_f( gentity_t *ent)
|
|
{
|
|
gentity_t* OtherPlayer; //Entity pointers to other players in game (used in loop)
|
|
char arg[MAX_TOKEN_CHARS]; //Arguments
|
|
int i; //Loop Counter
|
|
float DistanceVector[2]; //Distance Vector from client caller to victim
|
|
float Distance; //Real Distance from client caller to victim
|
|
float range;
|
|
int kill_self;
|
|
int clientNum = ent->client->ps.clientNum;
|
|
playerState_t *ePs = &ent->client->ps;
|
|
playerState_t *oPs;
|
|
|
|
memset(arg,0,MAX_TOKEN_CHARS); //Clear aray.
|
|
|
|
//Grab range from command
|
|
trap_Argv( 1, arg, sizeof( arg ) ); //Gets 1st
|
|
range = atoi(arg);
|
|
|
|
memset(arg,0,MAX_TOKEN_CHARS); //Clear aray.
|
|
|
|
//Grab kill_self from command
|
|
trap_Argv( 2, arg, sizeof( arg ) ); //Gets 2nd
|
|
kill_self = atoi(arg);
|
|
|
|
//If client isn't in admin class, exit and disallow command.
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_FORCEKILL) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
//If forcekillradius is not enabled in cvar do not allow it to continue.
|
|
if(rpg_forcekillradius.integer != 1)
|
|
{
|
|
return;
|
|
}
|
|
//If last time FKR was used before the wait time is up..
|
|
if( ( rpg_forcekillradiuswaittime.integer - (level.time - LastFKRadius[clientNum]) > 0) )
|
|
{
|
|
//Send message to client informing them so they can't flood.
|
|
trap_SendServerCommand( clientNum, va("cp \"Cannot use Force Kill Radius Command for %d seconds", (int)(( rpg_forcekillradiuswaittime.integer - (level.time - LastFKRadius[clientNum]) ) * 0.001 ))); // GSIO was / 1000
|
|
return;
|
|
}
|
|
|
|
//Loop Through Clients on the server
|
|
for(i = 0; i < level.numConnectedClients; i++)
|
|
{
|
|
//If current client == caller client, skip this iteration.
|
|
if(i == clientNum)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
OtherPlayer = &g_entities[i]; //Point OtherPlayer to next player
|
|
|
|
//Send message to admins warning about command being used.
|
|
G_SayTo( ent, OtherPlayer, SAY_ADMIN, COLOR_CYAN, "^7Server: ", va("%s has triggred a force kill radius command", ent->client->pers.netname) );
|
|
|
|
//Check is OtherPlayer is valid
|
|
if ( !OtherPlayer || !OtherPlayer->inuse || !OtherPlayer->client )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
//If player is allready dead or in spectator, skip this iteration
|
|
if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR /*|| (ent->client->ps.eFlags&EF_ELIMINATED)*/ )
|
|
{
|
|
OtherPlayer = NULL; //Reset pointer ready for next iteration.
|
|
continue;
|
|
}
|
|
|
|
oPs = &OtherPlayer->client->ps;
|
|
|
|
|
|
//If current player is higer or lower by 1.5 units, do not kill them (probably on another deck), continue to next loop.
|
|
if( (oPs->origin[2] > ePs->origin[2]+15.0f) || (oPs->origin[2] < ePs->origin[2]-15.0f) )
|
|
{
|
|
OtherPlayer = NULL; //Reset pointer ready for next iteration.
|
|
continue;
|
|
}
|
|
|
|
//Vector subtraction, to get distance vector (using player positions as vectors
|
|
DistanceVector[0] = ePs->origin[0] - oPs->origin[0];
|
|
DistanceVector[1] = ePs->origin[1] - oPs->origin[1];
|
|
//Get Length of Distance Vector
|
|
Distance = sqrt( (DistanceVector[0] * DistanceVector[0]) + (DistanceVector[1] * DistanceVector[1]) );
|
|
|
|
//If distance is within the radius given...
|
|
if( Distance <= range)
|
|
{
|
|
//Kill the player.
|
|
lastKillTime[oPs->clientNum] = level.time;
|
|
OtherPlayer->flags &= ~FL_GODMODE; //Bypass godmode (?)
|
|
//RPG-X: Medics revive Support for suiciding
|
|
if(rpg_medicsrevive.integer == 1){
|
|
oPs->stats[STAT_WEAPONS] = ( 1 << WP_0 );
|
|
oPs->stats[STAT_HOLDABLE_ITEM] = HI_NONE;
|
|
oPs->stats[STAT_HEALTH] = OtherPlayer->health = 1;
|
|
G_Client_Die(OtherPlayer,OtherPlayer,OtherPlayer,100000, MOD_FORCEDSUICIDE);
|
|
}else{
|
|
oPs->stats[STAT_HEALTH] = OtherPlayer->health = 0;
|
|
G_Client_Die(OtherPlayer,OtherPlayer,OtherPlayer,100000, MOD_FORCEDSUICIDE);
|
|
}
|
|
}
|
|
|
|
OtherPlayer = NULL; //Reset pointer ready for next iteration.
|
|
}
|
|
|
|
//If kill_self != 0 (they want to kill them selves too)
|
|
if(kill_self != 0)
|
|
{
|
|
lastKillTime[clientNum] = level.time;
|
|
ent->flags &= ~FL_GODMODE; //Bypass godmode (?)
|
|
//RPG-X: Medics revive Support for suiciding
|
|
if(rpg_medicsrevive.integer == 1){
|
|
ePs->stats[STAT_WEAPONS] = ( 1 << WP_0 );
|
|
ePs->stats[STAT_HOLDABLE_ITEM] = HI_NONE;
|
|
ePs->stats[STAT_HEALTH] = ent->health = 1;
|
|
G_Client_Die(ent,ent,ent,100000, MOD_FORCEDSUICIDE);
|
|
}else{
|
|
ePs->stats[STAT_HEALTH] = ent->health = 0;
|
|
G_Client_Die(ent,ent,ent,100000, MOD_FORCEDSUICIDE);
|
|
}
|
|
}
|
|
|
|
LastFKRadius[clientNum] = level.time; // - rpg_forcekillradiuswaittime.integer;
|
|
}
|
|
|
|
/*
|
|
=================
|
|
TargetKick (RPG-X: J2J)
|
|
=================
|
|
*/
|
|
static void Cmd_TargetKick_f( gentity_t *ent)
|
|
{
|
|
gentity_t *target, *other; //Target entity, and other used to tell the
|
|
trace_t trace; //Used to trace target
|
|
vec3_t src, dest, vf; //Used to find target
|
|
int i; //Loop counter
|
|
|
|
//Disallow if not in admin class
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_KICK) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
//////////////////////////////////////
|
|
//All this code below finds the target entity
|
|
|
|
VectorCopy( ent->r.currentOrigin, src );
|
|
src[2] += ent->client->ps.viewheight;
|
|
|
|
AngleVectors( ent->client->ps.viewangles, vf, NULL, NULL );
|
|
|
|
//extend to find end of use trace
|
|
VectorMA( src, -6, vf, src );//in case we're inside something?
|
|
VectorMA( src, 1340, vf, dest );//128+6
|
|
|
|
//Trace ahead to find a valid target
|
|
trap_Trace( &trace, src, vec3_origin, vec3_origin, dest, ent->s.number, CONTENTS_BODY );
|
|
|
|
if ( trace.fraction == 1.0f || trace.entityNum < 0 )
|
|
{
|
|
trap_SendConsoleCommand( EXEC_APPEND, va("echo No target in range to kick.") );
|
|
return;
|
|
}
|
|
|
|
target = &g_entities[trace.entityNum];
|
|
|
|
if ( !target->client || trace.entityNum > MAX_CLIENTS )
|
|
{
|
|
trap_SendConsoleCommand( EXEC_APPEND, va("echo That target cannot be kicked.") );
|
|
return;
|
|
}
|
|
|
|
////////////////////////////////
|
|
|
|
//Send a kick command to kick the target.
|
|
trap_SendConsoleCommand( EXEC_APPEND, va("kick \"%i\"\n", target->client->ps.clientNum ) );
|
|
|
|
for (i = 0; i < level.maxclients; i++)
|
|
{
|
|
other = &g_entities[i];
|
|
G_SayTo( ent, other, SAY_ADMIN, COLOR_CYAN, "^7Server: ", va("%s has kicked %s", ent->client->pers.netname, target->client->pers.netname) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Drag (RPG-X: J2J)
|
|
=================
|
|
*/
|
|
|
|
RPGX_DragData DragDat[MAX_CLIENTS];
|
|
// /DragPlayer <ID> <range>
|
|
// This will start a drag on a player or adjust the range of a drag if its allready started
|
|
static void Cmd_Drag_f( gentity_t *ent)
|
|
{
|
|
char arg[MAX_TOKEN_CHARS]; //Arguments
|
|
int ID, i;
|
|
float range;
|
|
int clientNum;
|
|
|
|
if(!ent || !ent->client)
|
|
return;
|
|
|
|
//If client isn't in admin class, exit and disallow command.
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_DRAG) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
clientNum = ent->client->ps.clientNum;
|
|
|
|
memset(arg,0,MAX_TOKEN_CHARS); //Clear aray.
|
|
//Grab range from command
|
|
trap_Argv( 1, arg, sizeof( arg ) ); //Gets 1st
|
|
|
|
//TiM : Make this a bit more user friendly
|
|
if ( !arg[0] ) { //if user added no args (ie wanted the parameters)
|
|
trap_SendServerCommand( clientNum, va("print \"\nUsage: User can forcefully drag another player\nCommand: Drag [Player ID] [Distance between both Players]\n\" ") );
|
|
return;
|
|
}
|
|
|
|
ID = atoi(arg);
|
|
|
|
if ( ID < 0 || ID >= level.maxclients )
|
|
{
|
|
return;
|
|
}
|
|
|
|
//This prevents a interesting form of no clip where you could move at a speed as range
|
|
if(ent->client->ps.clientNum == ID)
|
|
{
|
|
trap_SendServerCommand( clientNum, "print \"You cannot drag yourself!\n\"" );
|
|
return;
|
|
}
|
|
|
|
memset(arg,0,MAX_TOKEN_CHARS); //Clear aray.
|
|
//Grab range from command
|
|
trap_Argv( 2, arg, sizeof( arg ) ); //Gets 1st
|
|
range = atof(arg);
|
|
|
|
//If target is being dragged.
|
|
if(DragDat[ID].AdminId != -1)
|
|
{
|
|
//This undrag is left here, but can also be done using the undrag command.
|
|
if(DragDat[ID].AdminId == clientNum)
|
|
{
|
|
//Adjust Range if range given
|
|
//QVM HACK!
|
|
if( (Q_stricmp(arg,"")==0) && (range >= 0))
|
|
{
|
|
DragDat[ID].distance = range;
|
|
trap_SendServerCommand( clientNum, va("print \"Adjusted Drag Range of Player %i\n\"", ID) );
|
|
}
|
|
//Else end drag.
|
|
else
|
|
{
|
|
if(!g_entities[ID].client)
|
|
return;
|
|
DragDat[ID].AdminId = -1;
|
|
DragDat[ID].distance = 0;
|
|
g_entities[ID].client->noclip = qfalse;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
trap_SendServerCommand( clientNum, "print \"Cannot Drag, Someone else is already dragging that player!\n\"" );
|
|
}
|
|
return;
|
|
}
|
|
|
|
for(i = 0; i < MAX_CLIENTS; i++)
|
|
{
|
|
if(DragDat[i].AdminId == ID)
|
|
{
|
|
trap_SendServerCommand( clientNum, "print \"Cannot Drag, player is currently dragging.\n\"" );
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
if(!g_entities[ID].client)
|
|
return;
|
|
//Set the struct data for this victim..
|
|
DragDat[ID].AdminId = clientNum;
|
|
DragDat[ID].distance = range;
|
|
//Prevent wierd errors in transit
|
|
g_entities[ID].client->noclip = qtrue;
|
|
|
|
trap_SendServerCommand( clientNum, va("print \"Dragging Client %i\n\"", ID) );
|
|
|
|
//Leave the actaual position calculations to the loop function. (See below)
|
|
}
|
|
|
|
/*
|
|
=================
|
|
UnDrag (RPG-X: J2J)
|
|
=================
|
|
*/
|
|
// /DragPlayer <ID>
|
|
//
|
|
// This is used to stop draging
|
|
// If the argument 'all' is specified then all drags will be haulted.
|
|
// If a client ID is supplied then that play will be droped (by anyone)
|
|
// If no parameters are given, the calling player will be undraged.
|
|
//
|
|
static void Cmd_UnDrag_f( gentity_t *ent)
|
|
{
|
|
char arg[MAX_TOKEN_CHARS]; //Arguments
|
|
int ID, i;
|
|
int clientNum;
|
|
|
|
if(!ent || !ent->client)
|
|
return;
|
|
|
|
//If client isn't in admin class, exit and disallow command.
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_DRAG) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
clientNum = ent->client->ps.clientNum;
|
|
|
|
memset(arg,0,MAX_TOKEN_CHARS); //Clear aray.
|
|
//Grab range from command
|
|
trap_Argv( 1, arg, sizeof( arg ) ); //Gets 1st
|
|
|
|
if(Q_strncmp(arg,"all", 3) == 0)
|
|
{
|
|
for(i = 0; i < MAX_CLIENTS; i++)
|
|
{
|
|
DragDat[i].AdminId = -1;
|
|
DragDat[i].distance = 0;
|
|
if(!g_entities[i].client)
|
|
continue;
|
|
g_entities[i].client->noclip = qfalse;
|
|
}
|
|
trap_SendServerCommand( clientNum, va("print \"Stopped Dragging all Clients.\n\"") );
|
|
return;
|
|
}
|
|
|
|
if(Q_strncmp(arg,"self", 4) == 0)
|
|
{
|
|
DragDat[clientNum].AdminId = -1;
|
|
DragDat[clientNum].distance = 0;
|
|
ent->client->noclip = qfalse;
|
|
|
|
trap_SendServerCommand( clientNum, va("print \"You are UnDragged.\n\"") );
|
|
return;
|
|
}
|
|
|
|
if(arg == NULL)
|
|
{
|
|
for(i = 0; i < MAX_CLIENTS; i++)
|
|
{
|
|
if( DragDat[i].AdminId == clientNum )
|
|
{
|
|
DragDat[i].AdminId = -1;
|
|
DragDat[i].distance = 0;
|
|
if(!g_entities[i].client)
|
|
continue;
|
|
g_entities[i].client->noclip = qfalse;
|
|
}
|
|
}
|
|
trap_SendServerCommand( clientNum, va("print \"Stopped Dragging your Clients\n\"") );
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
ID = atoi(arg);
|
|
|
|
if ( ID < 0 || ID >= level.maxclients )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
if(DragDat[ID].AdminId == -1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(!g_entities[ID].client)
|
|
return;
|
|
|
|
//Set the struct data for this victim..
|
|
DragDat[ID].AdminId = -1;
|
|
DragDat[ID].distance = 0;
|
|
g_entities[ID].client->noclip = qfalse;
|
|
trap_SendServerCommand( clientNum, va("print \"Stopped Dragging Client %i\n\"", ID) );
|
|
}
|
|
|
|
|
|
/*
|
|
=================
|
|
DragCheck (RPG-X: J2J)
|
|
=================
|
|
*/
|
|
//This is used internally and run every frame to check for clients that need to be draged by someone.
|
|
void DragCheck(void)
|
|
{
|
|
gentity_t *ent = NULL;
|
|
gentity_t *target = NULL;
|
|
int i;
|
|
playerState_t *ePs;
|
|
playerState_t *tPs;
|
|
|
|
for ( i = 0; i < MAX_CLIENTS; i++ )
|
|
{
|
|
//If the admin id is < 0 then they are not being draged.
|
|
if(DragDat[i].AdminId < 0)
|
|
continue;
|
|
|
|
//If the starting admin is no longer in admin class:
|
|
if( IsAdmin(&g_entities[DragDat[i].AdminId]) == qfalse)
|
|
{
|
|
//Mark as non-dragging.
|
|
DragDat[i].AdminId = -1;
|
|
if(target && target->client)
|
|
target->client->noclip = qfalse;
|
|
continue;
|
|
}
|
|
|
|
//Get victim and admin entities
|
|
target = &g_entities[i];
|
|
ent = &g_entities[DragDat[i].AdminId];
|
|
|
|
//Error checking
|
|
|
|
if(!target || ! target->client)
|
|
continue;
|
|
|
|
if(!ent || !ent->client)
|
|
continue;
|
|
|
|
//If the target has gone to spec, stop dragging.
|
|
if( target->client->sess.sessionTeam == TEAM_SPECTATOR )
|
|
{
|
|
//Mark as non-dragging.
|
|
DragDat[i].AdminId = -1;
|
|
target->client->noclip = qfalse;
|
|
continue;
|
|
}
|
|
|
|
ePs = &ent->client->ps;
|
|
tPs = &target->client->ps;
|
|
|
|
//Vector math!
|
|
VectorCopy(ePs->origin, tPs->origin);
|
|
tPs->origin[0] += ( DragDat[i].distance * cos(DEG2RAD(ePs->viewangles[1])));//(ent->client->ps.viewangles[1] * 0.017453292222222222222222222222222 ) );
|
|
tPs->origin[1] += ( DragDat[i].distance * sin(DEG2RAD(ePs->viewangles[1])));//(ent->client->ps.viewangles[1] * 0.017453292222222222222222222222222) );
|
|
tPs->origin[2] += ( DragDat[i].distance * -tan(DEG2RAD(ePs->viewangles[0]))) + ePs->viewheight;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
=================
|
|
Disarm Tripmines (RPG-X: RedTechie)
|
|
=================
|
|
*/
|
|
// Harry -- What's the command...
|
|
static void Cmd_disarm_f( gentity_t *ent)
|
|
{
|
|
// /disarm_tripmines <0 or 1 (yours or all)>
|
|
gentity_t *tripwire = NULL;
|
|
int foundTripWires[MAX_GENTITIES] = {ENTITYNUM_NONE};
|
|
int tripcount = 0;
|
|
int i;
|
|
char arg[MAX_TOKEN_CHARS];
|
|
|
|
//If client isn't in admin class, exit and disallow command.
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_DISARM) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
trap_Argv( 1, arg, sizeof( arg ) );
|
|
|
|
if(arg == NULL){ //J2J
|
|
//Just mine
|
|
while ( (tripwire = G_Find( tripwire, FOFS(classname), "tripwire" )) != NULL )
|
|
{
|
|
if ( tripwire->parent != ent )
|
|
{
|
|
continue;
|
|
}
|
|
foundTripWires[tripcount++] = tripwire->s.number;
|
|
}
|
|
}else if(Q_strncmp(arg, "all",3)){ //J2J
|
|
//All Mines
|
|
while ( (tripwire = G_Find( tripwire, FOFS(classname), "tripwire" )) != NULL )
|
|
{
|
|
foundTripWires[tripcount++] = tripwire->s.number;
|
|
}
|
|
}
|
|
else //J2J
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(tripcount != 0){
|
|
for ( i = 0; i < tripcount; i++ )
|
|
{
|
|
//remove it... or blow it?
|
|
if ( &g_entities[foundTripWires[i]] == NULL )
|
|
{
|
|
return;
|
|
}else{
|
|
G_FreeEntity( &g_entities[foundTripWires[i]] );
|
|
foundTripWires[i] = ENTITYNUM_NONE;
|
|
}
|
|
}
|
|
trap_SendServerCommand( ent->client->ps.clientNum, va("print \"Disarmed %i tripmines\n\"", tripcount ) );
|
|
}else{
|
|
trap_SendServerCommand( ent->client->ps.clientNum, va("print \"No tripmines to disarm\n\"" ) );
|
|
}
|
|
}
|
|
|
|
|
|
static void Cmd_Rank_f( gentity_t *ent)
|
|
{
|
|
// const char *info;
|
|
int OldScore;
|
|
char ArgStr[50]; //Argument String
|
|
int i;
|
|
int newScore = -1;
|
|
|
|
char tmpScore[MAX_QPATH]; // TiM
|
|
qboolean MaxRankHit=qfalse;
|
|
|
|
//Still not sure how the hell this condition would ever get tripped O_o
|
|
if(!ent || !ent->client)
|
|
return;
|
|
|
|
if ( ent->flags & FL_CLAMPED )
|
|
return;
|
|
|
|
//TiM | Okay. Ranks are enabled, but only admins can change them
|
|
if ( !rpg_changeRanks.integer )
|
|
{
|
|
trap_SendServerCommand( ent-g_entities, "print \"You cannot change your rank yourself on this server.\n\"");
|
|
return;
|
|
}
|
|
|
|
//Lets get old score first just incase
|
|
OldScore = ent->client->ps.persistant[PERS_SCORE];
|
|
|
|
trap_Argv(1, ArgStr, sizeof(ArgStr)); //Get the raw arguments
|
|
|
|
if ( !ArgStr[0] ) { //If no arguments (ie player wants to see current rank)
|
|
|
|
Com_sprintf(tmpScore, sizeof(tmpScore), "%s - %s", g_rankNames[OldScore].formalName, g_rankNames[OldScore].consoleName ); //Put OldScore in a string variable
|
|
|
|
trap_SendServerCommand( ent-g_entities, va("print \"\nCurrent Rank: %s\nUsage: Changes user to the specified rank\nCommand: Rank <New rank>\n\nType '/ranklist' into the console for a full list of ranks\" ", tmpScore ) );
|
|
return;
|
|
}
|
|
|
|
//TiM: Lemme butt my coding hackiness in here. :P
|
|
//I just realised, that regardless of rank they currently are (even if they're the same),
|
|
//this code always switches rank, which is causing heck in some other bits of the code. :P
|
|
|
|
//RPG-X: TiM - Check if they're already that rank, and return if they are. :P
|
|
//RPG-X: TiM (1.5 years later) - Holy crap man! That really is hacky!!!! >.<
|
|
|
|
//RPG-X: RedTechie - Lets enable score updating without this scores will not be updated
|
|
ent->client->UpdateScore = qtrue;
|
|
|
|
for ( i=0; (g_rankNames[i].consoleName[0] && i < MAX_RANKS); i++ ) {
|
|
if ( !Q_stricmp( ArgStr, g_rankNames[i].consoleName ) ) {
|
|
newScore = i;
|
|
|
|
if ( newScore == OldScore )
|
|
return;
|
|
|
|
if( !MaxRankHit )
|
|
{
|
|
SetScore( ent, newScore );
|
|
trap_SendServerCommand(ent-g_entities, va( "prank %s", g_rankNames[i].consoleName ) );
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if ( !MaxRankHit )
|
|
trap_SendServerCommand( ent-g_entities, va("print \"This rank is disabled\n\""));
|
|
else
|
|
trap_SendServerCommand( ent-g_entities, va("print \"You cannot set your rank that high on this server.\n\""));
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
//Okay... we've hit the highest rank we're allowed to go. If the player tries to change their rank to above this, they'll be pwned lol
|
|
if ( rpg_maxRank.string[0] && !Q_stricmp( g_rankNames[i].consoleName, rpg_maxRank.string ) && IsAdmin(ent) ) {
|
|
MaxRankHit=qtrue;
|
|
}
|
|
}
|
|
|
|
//if we didn't get find a matching name. >.<
|
|
if ( newScore < 0 ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"This rank doesn't exist on this server!\n\"\n"));
|
|
SetScore( ent, OldScore);
|
|
return;
|
|
}
|
|
|
|
if ( OldScore > ent->client->ps.persistant[PERS_SCORE] ) {
|
|
trap_SendServerCommand( -1, va("print \"%s" S_COLOR_WHITE " was demoted to %s\n\"", ent->client->pers.netname, g_rankNames[i].formalName ) );
|
|
}
|
|
else {
|
|
trap_SendServerCommand( -1, va("print \"%s" S_COLOR_WHITE " was promoted to %s\n\"", ent->client->pers.netname, g_rankNames[i].formalName ) );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
=================
|
|
Force Rank (RPG-X: J2J & RedTechie)
|
|
=================
|
|
*/
|
|
static void Cmd_ForceRank_f( gentity_t *ent)
|
|
{
|
|
int OldScore;
|
|
char ArgStr[MAX_TOKEN_CHARS]; //Argument String
|
|
int targetNum;
|
|
gentity_t *other;
|
|
char send[100];
|
|
int i;
|
|
gentity_t *sayA;
|
|
int newScore = -1;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_FORCEPARM) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if(!ent || !ent->client)
|
|
return;
|
|
|
|
// find the player
|
|
trap_Argv( 1, ArgStr, sizeof( ArgStr ) );
|
|
|
|
if ( !ArgStr[0] ) { //if user added no args (ie wanted the parameters)
|
|
trap_SendServerCommand( ent-g_entities, va("print \"\nUsage: User forces another player into a specific rank\nCommand: ForceRank [Player ID] <Rank Name>\n\nType 'rankList' into the console for a full list of ranks\" ") );
|
|
return;
|
|
}
|
|
|
|
targetNum = atoi( ArgStr );
|
|
if ( targetNum < 0 || targetNum >= level.maxclients ) {
|
|
return;
|
|
}
|
|
|
|
other = &g_entities[targetNum];
|
|
|
|
//Lets get old score first just incase
|
|
OldScore = other->client->ps.persistant[PERS_SCORE]; //ent
|
|
|
|
if ( !other || !other->inuse || !other->client ) {
|
|
return;
|
|
}
|
|
|
|
//Get the raw rank value
|
|
trap_Argv(2, ArgStr, sizeof(ArgStr));
|
|
|
|
other->client->UpdateScore = qtrue;
|
|
|
|
for ( i=0; (g_rankNames[i].consoleName && i < MAX_RANKS); i++ ) {
|
|
if ( !Q_stricmp( ArgStr, g_rankNames[i].consoleName ) ) {
|
|
newScore = i;//1 << i;
|
|
|
|
SetScore( other, newScore );
|
|
trap_SendServerCommand(other-g_entities, va( "prank %s", g_rankNames[i].consoleName ) );
|
|
break;
|
|
}
|
|
}
|
|
|
|
//if we didn't get find a matching name. >.<
|
|
if ( newScore < 0 ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"This rank doesn't exist on this server!\n\"\n"));
|
|
SetScore( other, OldScore);
|
|
return;
|
|
}
|
|
|
|
if ( OldScore > ent->client->ps.persistant[PERS_SCORE] ) {
|
|
trap_SendServerCommand( -1, va("print \"%s" S_COLOR_WHITE " was demoted to %s\n\"", other->client->pers.netname, g_rankNames[i].formalName ) );
|
|
}
|
|
else {
|
|
trap_SendServerCommand( -1, va("print \"%s" S_COLOR_WHITE " was promoted to %s\n\"", other->client->pers.netname, g_rankNames[i].formalName ) );
|
|
}
|
|
|
|
G_LogPrintf( "%s changed %s's rank to %s (%s)\n", ent->client->pers.netname, other->client->pers.netname, ArgStr, ent->client->pers.ip );
|
|
|
|
for (i = 0; i < MAX_CLIENTS - 1; i++) {
|
|
if(g_entities[i].client){
|
|
sayA = &g_entities[i];
|
|
Com_sprintf (send, sizeof(send), "%s changed %s's rank to %s\n", ent->client->pers.netname, other->client->pers.netname, ArgStr);
|
|
G_SayTo( ent, sayA, SAY_ADMIN, COLOR_CYAN, "^7Server: ", send );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Admins
|
|
RPG-X | Phenix | 21/11/2004
|
|
=================
|
|
*/
|
|
|
|
static void Cmd_Admins_f( gentity_t *ent)
|
|
{
|
|
char send[MAX_TOKEN_CHARS];
|
|
int j;
|
|
gentity_t *target;
|
|
|
|
Q_strncpyz( send, "The following players are logged in as admins: \n", sizeof(send));
|
|
for (j = 0; j < level.maxclients; j++) {
|
|
target = &g_entities[j];
|
|
if (g_classData[target->client->sess.sessionClass].isAdmin)
|
|
Q_strncpyz( send, va("%s %s \n", send, target->client->pers.netname), sizeof(send));
|
|
|
|
if ((target->client->LoggedAsAdmin == qtrue) && (IsAdmin( ent ) == qtrue))
|
|
Q_strncpyz( send, va("%s %s (hidden) \n", send, target->client->pers.netname), sizeof(send));
|
|
}
|
|
|
|
trap_SendServerCommand( ent->client->ps.clientNum, va("print \"%s\n\"", send ) );
|
|
}
|
|
|
|
/*
|
|
=================
|
|
AdminLogin
|
|
=================
|
|
*/
|
|
static void Cmd_AdminLogin_f( gentity_t *ent)
|
|
{
|
|
char arg[MAX_TOKEN_CHARS];
|
|
char send[MAX_TOKEN_CHARS];
|
|
char classPass[MAX_TOKEN_CHARS];
|
|
int j;
|
|
gentity_t *sayA;
|
|
|
|
trap_Argv( 1, arg, sizeof( arg ) );
|
|
|
|
//logout if no argument and player is admin
|
|
if(!arg[0] && ent->client->LoggedAsAdmin) {
|
|
ent->client->LoggedAsAdmin = qfalse;
|
|
trap_SendServerCommand( ent-g_entities, va("print \"You are now logged out.\n\"") );
|
|
G_Client_UserinfoChanged( ent-g_entities );
|
|
return;
|
|
}
|
|
else if ( !arg[0] ) { //if user added no args (ie wanted the parameters)
|
|
trap_SendServerCommand( ent-g_entities, va("print \"\nUsage: Allows a player to login as an admin\nCommand: AdminLogin <Admin Password>\nWARNING: Entering an incorrect password 3 times will automatically kick you from the server!\nEntering AdminLogin without password will log you out if you are locked in\n\" ") );
|
|
return;
|
|
}
|
|
|
|
//Admin class login thingy
|
|
for ( j=0; g_classData[j].consoleName[0] && j < MAX_CLASSES; j++ )
|
|
{
|
|
trap_Cvar_VariableStringBuffer( va( "rpg_%sPass", g_classData[j].consoleName ), classPass, sizeof(classPass) );
|
|
|
|
if ( g_classData[j].isAdmin && !Q_stricmp( classPass, arg ) )
|
|
{
|
|
if ( IsAdmin( ent ) == qfalse ) {
|
|
ent->client->LoggedAsAdmin = qtrue;
|
|
trap_SendServerCommand( ent-g_entities, va("print \"You are logged in as an admin.\n\"") );
|
|
G_Client_UserinfoChanged( ent-g_entities );
|
|
return;
|
|
} else {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"You are already logged in as an admin or in the admin class.\n\"") );
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
ent->client->AdminFailed++;
|
|
if ( ent->client->AdminFailed == 3 )
|
|
{
|
|
//Tell admins why he was kicked
|
|
Com_sprintf (send, sizeof(send), "%s tried to login as an admin, failed 3 times and so was kicked.\n", ent->client->pers.netname);
|
|
for (j = level.maxclients - 1; j > -1; j--) { // changed j++ for into j--
|
|
sayA = &g_entities[j];
|
|
G_SayTo( ent, sayA, SAY_ADMIN, COLOR_CYAN, "^7Server: ", send );
|
|
}
|
|
|
|
//Kick Client because client has entered the wrong password 3 times
|
|
trap_DropClient( ent->s.number, "Kicked: Too many bad passwords!" );
|
|
} else {
|
|
//Give the client another warning
|
|
trap_SendServerCommand( ent-g_entities, va("print \"You have entered an incorrect password, if you enter a wrong password %i more times you will be kicked.\n\"", (3 - ent->client->AdminFailed) ) );
|
|
|
|
//Send warning to other admins
|
|
Com_sprintf (send, sizeof(send), "%s tried to login as an admin and got an incorrect password, %i tries left.\n", ent->client->pers.netname, (3 - ent->client->AdminFailed));
|
|
for (j = level.maxclients - 1; j > -1; j--) { // changed j++ for into j--
|
|
sayA = &g_entities[j];
|
|
G_SayTo( ent, sayA, SAY_ADMIN, COLOR_CYAN, "^7Server: ", send );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Revive (RPG-X: RedTechie)
|
|
=================
|
|
*/
|
|
static void Cmd_Revive_f( gentity_t *ent)
|
|
{
|
|
char pla_str[50]; //Argument String
|
|
int targetNum;
|
|
gentity_t *other;
|
|
int i;
|
|
playerState_t *ps;
|
|
clientPersistant_t *pers;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) || !rpg_medicsrevive.integer ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_REVIVE) || !rpg_medicsrevive.integer ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if(!ent || !ent->client)
|
|
return;
|
|
|
|
//If for some strange reason medic revive is turned off
|
|
if(rpg_medicsrevive.integer <= 0)
|
|
{
|
|
trap_SendServerCommand( ent-g_entities, va("print \"Medics' Revive is disabled on this server!\n\""));
|
|
return;
|
|
}
|
|
|
|
// find the player
|
|
trap_Argv( 1, pla_str, sizeof( pla_str ) );
|
|
|
|
//If player entered no args AND is alive (So as to not screw up reviving yourself ;) )
|
|
if ( !pla_str[0] && (ent && ent->client) && !(ent->health <= 1) && !(ent->client->ps.pm_type == PM_DEAD) ) { //if user added no args (ie wanted the parameters)
|
|
trap_SendServerCommand( ent-g_entities, va("print \"\nUsage: User revives incapacitated players\nCommand: Revive {Nothing = Revive Self} OR [Player ID] OR 'all'\n\" ") );
|
|
return;
|
|
}
|
|
|
|
pers = &ent->client->pers;
|
|
|
|
if(!Q_strncmp(pla_str, "all", 3))
|
|
{
|
|
//Loop threw all clients
|
|
int j;
|
|
gentity_t *sayA;
|
|
char send[100];
|
|
|
|
for(i = MAX_CLIENTS - 1; i > -1; i--) //eherm MAX_CLIENTS is 128 no 1023, changed from i++ to i--
|
|
{
|
|
if( (g_entities[i].client) && (g_entities[i].health == 1) && (g_entities[i].client->ps.pm_type == PM_DEAD))
|
|
{
|
|
G_Client_Spawn(&g_entities[i], 1, qtrue);
|
|
|
|
ps = &g_entities[i].client->ps;
|
|
|
|
//TiM: Push any users out of the way, and then play a 'getup' emote
|
|
g_entities[i].r.contents = CONTENTS_NONE;
|
|
ps->stats[LEGSANIM] = ( ( ps->stats[LEGSANIM] & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | BOTH_GET_UP1;
|
|
ps->stats[TORSOANIM] = ( ( ps->stats[TORSOANIM] & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | BOTH_GET_UP1;
|
|
ps->stats[TORSOTIMER] = 1700;
|
|
ps->stats[LEGSTIMER] = 1700;
|
|
ps->stats[EMOTES] = EMOTE_BOTH | EMOTE_CLAMP_BODY | EMOTE_OVERRIDE_BOTH;
|
|
ps->legsAnim = 0;
|
|
ps->torsoAnim = 0;
|
|
ps->legsTimer = 0;
|
|
ps->torsoTimer = 0;
|
|
}
|
|
}
|
|
|
|
G_LogPrintf( "%s revived everyone (%s)\n", pers->netname, pers->ip);
|
|
|
|
Com_sprintf (send, sizeof(send), "%s revived everyone\n", pers->netname);
|
|
|
|
for (j = MAX_CLIENTS - 1; j > -1; j--) { // again j++ to j-- and 1023 to MAX_CLIENTS
|
|
if(g_entities[j].client){
|
|
sayA = &g_entities[j];
|
|
G_SayTo( ent, sayA, SAY_ADMIN, COLOR_CYAN, "^7Server: ", send );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!pla_str[0])
|
|
{
|
|
//Just me
|
|
if( (ent && ent->client) && (ent->health <= 1) && (ent->client->ps.pm_type == PM_DEAD))
|
|
{
|
|
G_Client_Spawn(ent, 1, qtrue);
|
|
|
|
ps = &ent->client->ps;
|
|
|
|
ent->r.contents = CONTENTS_NONE;
|
|
ps->stats[LEGSANIM] = ( ( ps->stats[LEGSANIM] & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | BOTH_GET_UP1;
|
|
ps->stats[TORSOANIM] = ( ( ps->stats[TORSOANIM] & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | BOTH_GET_UP1;
|
|
ps->stats[TORSOTIMER] = 1700;
|
|
ps->stats[LEGSTIMER] = 1700;
|
|
ps->stats[EMOTES] = EMOTE_BOTH | EMOTE_OVERRIDE_BOTH | EMOTE_CLAMP_BODY;
|
|
ps->legsAnim = 0;
|
|
ps->torsoAnim = 0;
|
|
ps->legsTimer = 0;
|
|
ps->torsoTimer = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//Specific user
|
|
int j;
|
|
gentity_t *sayA;
|
|
char send[100];
|
|
|
|
targetNum = atoi( pla_str );
|
|
if ( targetNum < 0 || targetNum >= level.maxclients ) {
|
|
return;
|
|
}
|
|
|
|
other = &g_entities[targetNum];
|
|
if ( !other || !other->inuse || !other->client ) {
|
|
return;
|
|
}
|
|
|
|
if( (other && other->client) && (other->health == 1) && (other->client->ps.pm_type == PM_DEAD))
|
|
{
|
|
G_Client_Spawn(other, 1, qtrue);
|
|
|
|
ps = &other->client->ps;
|
|
|
|
other->r.contents = CONTENTS_NONE;
|
|
ps->stats[LEGSANIM] = ( ( ps->stats[LEGSANIM] & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | BOTH_GET_UP1;
|
|
ps->stats[TORSOANIM] = ( ( ps->stats[TORSOANIM] & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | BOTH_GET_UP1;
|
|
ps->stats[TORSOTIMER] = 1700;
|
|
ps->stats[LEGSTIMER] = 1700;
|
|
ps->stats[EMOTES] |= EMOTE_BOTH | EMOTE_CLAMP_BODY | EMOTE_OVERRIDE_BOTH;
|
|
ps->legsAnim = 0;
|
|
ps->torsoAnim = 0;
|
|
ps->legsTimer = 0;
|
|
ps->torsoTimer = 0;
|
|
|
|
G_LogPrintf( "%s revived %s (%s)\n", pers->netname, other->client->pers.netname, pers->ip);
|
|
|
|
Com_sprintf (send, sizeof(send), "%s revived %s\n", pers->netname, other->client->pers.netname);
|
|
|
|
for (j = MAX_CLIENTS - 1; j > -1; j--) // j++ to j-- and 1023 to MAX_CLIENTS
|
|
{
|
|
if(g_entities[j].client)
|
|
{
|
|
sayA = &g_entities[j];
|
|
G_SayTo( ent, sayA, SAY_ADMIN, COLOR_CYAN, "^7Server: ", send );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
N00b (RPG-X: Phenix)
|
|
=================
|
|
*/
|
|
static void Cmd_n00b_f( gentity_t *ent)
|
|
{
|
|
char arg[MAX_TOKEN_CHARS];
|
|
int targetNum;
|
|
int timeToBe;
|
|
gentity_t *target;
|
|
int i;
|
|
|
|
//If client isn'tin admin class, exit and disallow command.
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_NOOB) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if ( !ent || !ent->client ) {
|
|
return; // not fully in game yet
|
|
}
|
|
|
|
memset(arg,0,MAX_TOKEN_CHARS);
|
|
trap_Argv( 1, arg, sizeof( arg ) );
|
|
|
|
//User Friendly
|
|
if ( !arg[0] ) { //if user added no args (ie wanted the parameters)
|
|
trap_SendServerCommand( ent-g_entities, va("print \"\nUsage: User places another player in n00b class for X seconds\nCommand: n00b [Player ID] [Seconds to be in n00b class]\n\" ") );
|
|
return;
|
|
}
|
|
|
|
targetNum = atoi(arg);
|
|
|
|
memset(arg,0,MAX_TOKEN_CHARS);
|
|
trap_Argv( 2, arg, sizeof( arg ) );
|
|
|
|
|
|
timeToBe = atoi(arg);
|
|
|
|
target = g_entities + targetNum;
|
|
|
|
for ( i = 0; g_classData[i].consoleName[0] && i < MAX_CLASSES; i++ ) {
|
|
if ( g_classData[i].isn00b ) {
|
|
char conName[15];
|
|
trap_Cvar_VariableStringBuffer( va( "rpg_%sPass", g_classData[i].consoleName ), conName, 15);
|
|
|
|
Q_strncpyz(target->client->origClass, ClassNameForValue( target->client->sess.sessionClass ), sizeof(target->client->origClass));
|
|
target->client->n00bTime = level.time + (1000 * timeToBe);
|
|
SetClass( target, conName, NULL, qfalse );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Admin Message
|
|
RPG-X | Phenix | 08/06/2005
|
|
=================
|
|
*/
|
|
static void Cmd_admin_message( gentity_t *ent)
|
|
{
|
|
char *arg;
|
|
|
|
if ( trap_Argc () < 1 ) {
|
|
return;
|
|
}
|
|
|
|
//If client isn't in admin class, exit and disallow command.
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_MESSAGE) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if ( !ent || !ent->client ) {
|
|
return; // not fully in game yet
|
|
}
|
|
|
|
arg = ConcatArgs( 1 );
|
|
|
|
if ( !arg[0] ) { //if user added no args (ie wanted the parameters)
|
|
trap_SendServerCommand( ent-g_entities, va("print \"\nUsage: Admin broadcasts a message to all users on the server that stays for several seconds\nCommand: Msg \"<Message>\"\n\" ") );
|
|
return;
|
|
}
|
|
|
|
if ( arg[0] == '\0' )
|
|
{
|
|
return;
|
|
}
|
|
|
|
//RPG-X: Marcin: changed to -1
|
|
trap_SendServerCommand( -1, va("print \"%s\n\" ", arg));
|
|
|
|
trap_SendServerCommand( -1, va("servermsg \"%s\"", arg));
|
|
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_ForceModel_f
|
|
=================
|
|
*/
|
|
static void Cmd_ForceModel_f( gentity_t *ent ) {
|
|
gclient_t *cl;
|
|
gentity_t *other;
|
|
gentity_t *sayA;
|
|
int j;
|
|
char send[100];
|
|
char str[MAX_TOKEN_CHARS];
|
|
char *str2;
|
|
char clientCmd[64];
|
|
clientPersistant_t *pers;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_FORCEPARM) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
//get the first arg
|
|
trap_Argv( 1, str, sizeof( str ) );
|
|
|
|
if ( !str[0] ) { //if user added no args (ie wanted the parameters)
|
|
trap_SendServerCommand( ent-g_entities, va("print \"\nUsage: User forces another player into a specific character model\n\nCommand: ForceModel [Player ID] <Model Name>/<Model Skin Name>\n\" ") );
|
|
return;
|
|
}
|
|
|
|
// find the player
|
|
cl = ClientForString( str );
|
|
if ( !cl ) {
|
|
return;
|
|
}
|
|
other = g_entities + cl->ps.clientNum;
|
|
|
|
//Get the new model
|
|
str2 = ConcatArgs( 2 );
|
|
|
|
pers = &ent->client->pers;
|
|
|
|
//Print out some chat text
|
|
G_LogPrintf( "%s changed %s's model to %s (%s)\n", pers->netname, other->client->pers.netname, str2, pers->ip );
|
|
|
|
Com_sprintf (send, sizeof(send), "%s ^7changed %s^7's model to %s", pers->netname, other->client->pers.netname, str2);
|
|
|
|
for (j = MAX_CLIENTS; j > -1; j--) { // j++ to j--, 1024 to MAX_CLIENTS
|
|
if(g_entities[j].client){
|
|
sayA = &g_entities[j];
|
|
G_SayTo( ent, sayA, SAY_ADMIN, COLOR_CYAN, "^7Server: ", send );
|
|
}
|
|
}
|
|
|
|
//send a command to the client and the client will do all this automatically
|
|
Com_sprintf( clientCmd, sizeof(clientCmd), "changeClientInfo model %s", str2 );
|
|
trap_SendServerCommand( cl->ps.clientNum, clientCmd );
|
|
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_PlayMusic_f
|
|
=================
|
|
*/
|
|
static void Cmd_PlayMusic_f( gentity_t *ent )
|
|
{
|
|
char songIntro[MAX_TOKEN_CHARS];
|
|
char songLoop[MAX_TOKEN_CHARS];
|
|
|
|
//standard checks
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_MUSIC) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if(!ent || !ent->client)
|
|
return;
|
|
|
|
//Load the arguments
|
|
trap_Argv( 1, songIntro, sizeof( songIntro ) );
|
|
trap_Argv( 2, songLoop, sizeof( songLoop ) );
|
|
|
|
//Output the isntructions if no arguments
|
|
if ( !songIntro[0] ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"\nUsage: Plays music throughout the level\n\nCommand: playMusic [songIntro] <songLoop>\n\" ") );
|
|
return;
|
|
}
|
|
|
|
//Broadcast the command
|
|
trap_SetConfigstring( CS_MUSIC, va("%s %s", songIntro, songLoop ) );
|
|
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_StopMusic_f
|
|
=================
|
|
*/
|
|
static void Cmd_StopMusic_f( gentity_t *ent )
|
|
{
|
|
//standard checks
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_MUSIC) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if(!ent || !ent->client)
|
|
return;
|
|
|
|
trap_SetConfigstring( CS_MUSIC, "" );
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_PlaySound_f
|
|
=================
|
|
*/
|
|
static void Cmd_PlaySound_f( gentity_t *ent )
|
|
{
|
|
char soundAddress[MAX_TOKEN_CHARS];
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_MUSIC) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if(!ent || !ent->client)
|
|
return;
|
|
|
|
//Load the arguments
|
|
trap_Argv( 1, soundAddress, sizeof( soundAddress ) );
|
|
|
|
//Output the isntructions if no arguments
|
|
if ( !soundAddress[0] ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"\nUsage: Plays a sound file throughout the level\n\nCommand: playSound [File Address]\n\" ") );
|
|
return;
|
|
}
|
|
|
|
//Broadcast the command
|
|
trap_SendServerCommand( -1, va("playSnd %s\n", soundAddress ) );
|
|
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_Bolton_f
|
|
=================
|
|
*/
|
|
static void Cmd_Bolton_f ( gentity_t *ent )
|
|
{
|
|
gclient_t *client;
|
|
char *msg;
|
|
|
|
client = ent->client;
|
|
|
|
ent->flags ^= FL_HOLSTER;
|
|
if (!(ent->flags & FL_HOLSTER))
|
|
{
|
|
msg = "You took your equipment off.\n";
|
|
client->ps.powerups[PW_BOLTON] = level.time;
|
|
}
|
|
else
|
|
{
|
|
msg = "You put your equipment on.\n";
|
|
client->ps.powerups[PW_BOLTON] = INT_MAX;
|
|
}
|
|
|
|
trap_SendServerCommand( ent-g_entities, va("print \"%s\"", msg));
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_UseEnt_f
|
|
=================
|
|
*/
|
|
//TiM: If called with an int argument, finds that ent and tries to use it.
|
|
//if no argument, it'll 'use' the entity the player's looking at
|
|
//Addendum: if player enters targetname, (checked to make sure it's no valid int in the ent list)
|
|
//activate that one.
|
|
static void Cmd_UseEnt_f ( gentity_t *ent ) {
|
|
char entArg[MAX_TOKEN_CHARS];
|
|
gentity_t *targetEnt;
|
|
int index;
|
|
playerState_t *ps;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_USEENT) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
trap_Argv( 1, entArg, sizeof( entArg ) );
|
|
|
|
ps = &ent->client->ps;
|
|
|
|
//No arguments - Do a trace
|
|
if ( !entArg[0] ) {
|
|
vec3_t start, forward, end;
|
|
trace_t tr;
|
|
|
|
//calc start
|
|
VectorCopy( ent->r.currentOrigin, start );
|
|
start[2] += ps->viewheight;
|
|
|
|
//calc end
|
|
AngleVectors( ps->viewangles, forward, NULL, NULL );
|
|
VectorMA( start, 8192, forward, end );
|
|
|
|
//trace-er-roo
|
|
trap_Trace( &tr, start, NULL, NULL, end, ps->clientNum, MASK_SHOT );
|
|
|
|
index = tr.entityNum;
|
|
}
|
|
else { //We gotz an arg, so put it in
|
|
index = atoi( entArg );
|
|
}
|
|
|
|
//invalid value ... so I guess it could be a targetname
|
|
if ( index < MAX_CLIENTS || index >= ENTITYNUM_WORLD ) {
|
|
targetEnt = G_Find (NULL, FOFS(targetname), entArg );
|
|
|
|
//STILL no dice?? Gah... just eff it then lol.
|
|
if ( !targetEnt ) {
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
targetEnt = &g_entities[index]; //get the ent
|
|
}
|
|
|
|
//find out the ent is valid, and it is useable
|
|
//TiM: Hack. Well... since we can use usables anyway, I'ma gonna disable them here.
|
|
//Doing it this way can screw up maps bigtime. >.<
|
|
//RPG_Chambers may never be the same again.... :S
|
|
if ( ( targetEnt && targetEnt->use) ) {
|
|
if ( !Q_stricmp( targetEnt->classname, "func_usable" ) )
|
|
return;
|
|
|
|
targetEnt->use( targetEnt, ent, ent ); //Activate the Ent
|
|
}
|
|
else { //otherwise berrate the user for being n00bish
|
|
trap_SendServerCommand( ent-g_entities, va( " print \"Entity %i cannot be activated in that way.\n\" ", index ) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_EntList_f
|
|
=================
|
|
TiM: Displays as many ents it can in the console without pwning the network code in the process
|
|
*/
|
|
static void Cmd_EntList_f ( gentity_t *ent ) {
|
|
int i;
|
|
gentity_t *mapEnt;
|
|
char entBuffer[128];
|
|
char mainBuffer[1024]; //16384
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_USEENT) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
//initialise the data holders
|
|
memset( &entBuffer, 0, sizeof( entBuffer ) );
|
|
memset( &mainBuffer, 0, sizeof( mainBuffer ) );
|
|
|
|
for (i = 0, mapEnt = g_entities;
|
|
i < level.num_entities;
|
|
i++, mapEnt++) {
|
|
|
|
if ( ( !Q_stricmpn( mapEnt->classname, "fx_", 3) ) || ( !Q_stricmp( mapEnt->classname, "func_usable" ) && ent->targetname ) ) {
|
|
if ( mapEnt->use ) {
|
|
memset( &entBuffer, 0, sizeof( entBuffer ) );
|
|
|
|
if ( mapEnt->targetname ) {
|
|
Com_sprintf( entBuffer, sizeof( entBuffer ), "ClassName: '%s', TargetName: '%s', ID: %i\n", mapEnt->classname, mapEnt->targetname, i);
|
|
}
|
|
else {
|
|
Com_sprintf( entBuffer, sizeof( entBuffer ), "ClassName: '%s', ID: %i\n", mapEnt->classname, i);
|
|
}
|
|
|
|
if ( strlen(mainBuffer) + strlen(entBuffer) >= sizeof( mainBuffer ) ) {
|
|
break;
|
|
}
|
|
else {
|
|
Q_strcat( mainBuffer, sizeof( mainBuffer ), entBuffer );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( strlen( mainBuffer ) > 0 ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"%s\" ", mainBuffer) );
|
|
}
|
|
else {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"No activatable entities detected.\n\" " ) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_BeamTo_f
|
|
=================
|
|
TiM: Allows people to transport themselves to any target_location entities
|
|
in the map :)
|
|
Syntax:
|
|
beamTo: <location index>
|
|
beamTo: <clientID> <location index>
|
|
*/
|
|
// Harry -- Get the command...
|
|
static void Cmd_BeamToLoc_f( gentity_t *ent ) {
|
|
char argStr[MAX_TOKEN_CHARS];
|
|
gentity_t *locEnt;
|
|
gentity_t *targEnt;
|
|
gentity_t *beamTarget;
|
|
int i;
|
|
int clientNum = 0, locIndex = 0;
|
|
char *strLoc=NULL;
|
|
qboolean all = qfalse;
|
|
|
|
//Has to be an admin.. if anyone had it, the brig would become useless.
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_BEAM) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
trap_Argv( 1, argStr, sizeof( argStr ) );
|
|
if ( !argStr[0] ) {
|
|
trap_SendServerCommand( ent-g_entities, va( "print \"Usage: Allows you to beam yourself to any 'target_location' entity that has a compatible beam-in point\nCommand: (For yourself) - beamToLocation <Index or name of target_location ent> \n(For other players) - beamTo <player ID> <Index or name of target_location ent>\nType '/beamList' into the console for a list of the 'target_location' indexes.\n\" " ) );
|
|
return;
|
|
}
|
|
|
|
//if more than one arg, assume we're beaming a separate client
|
|
//first arg MUST BE AN INTEGER CHIKUSHOYO OR THE THING BREAKS!!!!!! (Japanese expletive)
|
|
//must be an int coz it's the clientNum, anything else is not valid.
|
|
if ( trap_Argc() > 2 && (unsigned char)argStr[0] >= '0' && (unsigned char)argStr[0] <= '9' ) {
|
|
//beam all?
|
|
if(!Q_stricmp(argStr, "all")) {
|
|
all = qtrue;
|
|
} else {
|
|
//Get Client ID
|
|
clientNum = atoi( argStr );
|
|
}
|
|
|
|
if ( clientNum < 0 || clientNum >= MAX_CLIENTS ) {
|
|
trap_SendServerCommand( ent-g_entities, va("chat \"Invalid Client ID Number.\n\" " ) );
|
|
return;
|
|
}
|
|
|
|
beamTarget = &g_entities[clientNum];
|
|
if ( !beamTarget || !beamTarget->client ) {
|
|
trap_SendServerCommand( ent-g_entities, va("chat \"No valid client found.\n\" " ) );
|
|
return;
|
|
}
|
|
|
|
//Get beam location index.
|
|
trap_Argv( 2, argStr, sizeof( argStr ) );
|
|
|
|
//If arg is a string of chars or an integer
|
|
if ( (unsigned char)argStr[0] < '0' || (unsigned char)argStr[0] > '9' ) {
|
|
strLoc = ConcatArgs( 2 );
|
|
}
|
|
else {
|
|
locIndex = atoi( argStr );
|
|
}
|
|
}
|
|
else { //else 1 arg was specified - the index to beam ourselves.
|
|
//If arg is a string of chars or an integer
|
|
if ( (unsigned char)argStr[0] < '0' || (unsigned char)argStr[0] > '9' ) {
|
|
strLoc = ConcatArgs( 1 );
|
|
}
|
|
else {
|
|
locIndex = atoi( argStr );
|
|
}
|
|
|
|
//The target is us!
|
|
beamTarget = ent;
|
|
}
|
|
|
|
//if it's an invalid index, then I'm guessing the player specified location by name then
|
|
if ( locIndex < 1 || locIndex >= MAX_LOCATIONS ) {
|
|
if ( !strLoc ) {
|
|
trap_SendServerCommand( ent-g_entities, va("chat \"Invalid Location Index.\n\" " ) );
|
|
return;
|
|
}
|
|
}
|
|
|
|
//locEnt = &g_entities[iArg];
|
|
//Scan for the right entity
|
|
for ( i=0, locEnt=g_entities; i < level.num_entities; locEnt++, i++ )
|
|
{
|
|
|
|
if ( !Q_stricmp( locEnt->classname, "target_location" ) ) {
|
|
//if we have a health index (which will always be above 0 coz 0 is a default 'unknown' value)
|
|
if ( locEnt->health == locIndex && locEnt->health >= 1 && locIndex >= 1 ) {
|
|
break;
|
|
}
|
|
|
|
//Failing that, compare string values. If all went well you cannot
|
|
//have a string value or an int value valid at the same time in these checks.
|
|
if ( !locIndex && !Q_stricmp( locEnt->message, strLoc ) ) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !locEnt || Q_stricmp( locEnt->classname, "target_location" ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("chat \"Invalid Beam Entity.\n\" " ) );
|
|
return;
|
|
}
|
|
|
|
//locEnt
|
|
if ( locEnt->target ) {
|
|
targEnt = G_PickTarget( locEnt->target );
|
|
}
|
|
else {
|
|
targEnt = locEnt;
|
|
}
|
|
|
|
if (targEnt /*&& TransDat[beamTarget->client->ps.clientNum].beamTime == 0*/ ) {
|
|
vec3_t destPoint;
|
|
//TiM : Leeched this code off elsewhere. instead of hard-coding a value, align it to the ent's bbox.
|
|
//In case they don't use notnulls but something else.
|
|
VectorCopy(targEnt->s.origin, destPoint);
|
|
destPoint[2] += targEnt->r.mins[2];
|
|
destPoint[2] -= beamTarget->r.mins[2];
|
|
destPoint[2] += 1;
|
|
|
|
if ( TransDat[beamTarget->client->ps.clientNum].beamTime == 0 ) {
|
|
trap_SendServerCommand( ent-g_entities, va( "chat \"Initiating transport to location: %s\n\" ", locEnt->message ) );
|
|
if(!all) {
|
|
G_InitTransport( beamTarget->client->ps.clientNum, destPoint, targEnt->s.angles );
|
|
} else {
|
|
for(i = 0; i < MAX_CLIENTS && i < g_maxclients.integer; i++) {
|
|
if(!&g_entities[i] || !&g_entities[i].client) continue;
|
|
G_InitTransport(g_entities[i].client->ps.clientNum, destPoint, g_entities[i].s.angles );
|
|
targEnt = G_PickTarget(locEnt->target);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if ( beamTarget->client->ps.clientNum == ent->client->ps.clientNum ) {
|
|
trap_SendServerCommand( ent-g_entities, va( "chat \"Unable to comply. You are already within a transport cycle.\n\" " ) );
|
|
}
|
|
else {
|
|
trap_SendServerCommand( ent-g_entities, va( "chat \"Unable to comply. Subject is already within a transport cycle.\n\" " ) );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
trap_SendServerCommand( ent-g_entities, va( "chat \"Location entity does not have a valid beam location.\n\" " ) );
|
|
}
|
|
}
|
|
|
|
/*==============
|
|
Cmd_ForcePlayer_cmd
|
|
===============
|
|
TiM : Lets admins change any generic values
|
|
within a client's userinfo settings.
|
|
Things like age, race, height etc. Paramaters
|
|
that are too simple to require their own specific
|
|
function.
|
|
Although, name and model could be changed here too...
|
|
*/
|
|
static void Cmd_ForcePlayer_f ( gentity_t *ent ) {
|
|
gclient_t *cl;
|
|
gentity_t *other;
|
|
gentity_t *sayA;
|
|
int j;
|
|
char send[100];
|
|
char str[MAX_TOKEN_CHARS];
|
|
char *str2;
|
|
char userinfo[MAX_INFO_STRING];
|
|
char clientCmd[MAX_INFO_STRING];
|
|
clientPersistant_t *pers;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_FORCEPARM) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
// find the player
|
|
trap_Argv( 1, str, sizeof( str ) );
|
|
|
|
if ( !str[0] ) { //if user added no args (ie wanted the parameters)
|
|
trap_SendServerCommand( ent-g_entities, va("print \"\nUsage: User force changes a parameter in another player's configuration settings on the server.\nCommand: ForcePlayer <Player's ID Number> \"[Setting to be changed]\" \"[New Value]\"\n\n\" ") );
|
|
return;
|
|
}
|
|
|
|
cl = ClientForString( str );
|
|
if ( !cl ) {
|
|
return;
|
|
}
|
|
other = g_entities + cl->ps.clientNum;
|
|
|
|
//Get the key
|
|
trap_Argv( 2, str, sizeof( str ) );
|
|
if ( !str[0] ) {
|
|
return;
|
|
}
|
|
|
|
//get client's data
|
|
trap_GetUserinfo( cl->ps.clientNum, userinfo, sizeof( userinfo ) );
|
|
if ( !strstr( userinfo, str ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: Invalid setting specified.\n\" ") );
|
|
return;
|
|
}
|
|
|
|
str2 = ConcatArgs( 3 );
|
|
if ( !str2[0] ) {
|
|
return;
|
|
}
|
|
|
|
pers = &ent->client->pers;
|
|
|
|
//Print out some chat text
|
|
G_LogPrintf( "%s changed %s's %s setting to %s (%s)\n", pers->netname, other->client->pers.netname, str, str2, pers->ip );
|
|
|
|
Com_sprintf (send, sizeof(send), "%s ^7changed %s's %s setting to ^7to %s", pers->netname, other->client->pers.netname, str, str2);
|
|
|
|
for (j = 0; j < MAX_CLIENTS; j++) {
|
|
if(g_entities[j].client){
|
|
sayA = &g_entities[j];
|
|
G_SayTo( ent, sayA, SAY_ADMIN, COLOR_CYAN, "^7Server: ", send );
|
|
}
|
|
}
|
|
|
|
Com_sprintf( clientCmd, sizeof(clientCmd), "changeClientInfo %s %s", str, str2 );
|
|
|
|
trap_SendServerCommand( cl->ps.clientNum, clientCmd );
|
|
}
|
|
|
|
/*
|
|
==============
|
|
Cmd_BeamToPlayer_f
|
|
===============
|
|
TiM : Lets players beam to
|
|
other player locations.
|
|
|
|
Marcin : Implemented an 'all' option. (11/12/2008)
|
|
*/
|
|
#define PLAYER_BEAM_DIST 50
|
|
|
|
static void Cmd_BeamToPlayer_f( gentity_t *ent ) {
|
|
char argStr[MAX_TOKEN_CHARS];
|
|
gentity_t *target;
|
|
gentity_t *beamee;
|
|
int clientNum = 0;
|
|
int bClientNum = 0;
|
|
vec3_t mins = { -12, -12, -24 }; //for the volume trace -//12
|
|
vec3_t maxs = { 12, 12, 56 }; //44
|
|
int i, j = 0;
|
|
vec3_t origin, angles, zOrigin;
|
|
trace_t tr;
|
|
qboolean validTraceFound = qfalse;
|
|
int startPoint;
|
|
int totalCount;
|
|
int offsetRA[8][2] = { { 1, 0 }, //offsets for each beam test location
|
|
{ 1, -1 },
|
|
{ 0, -1 },
|
|
{ -1, -1 },
|
|
{ -1, 0 },
|
|
{ -1, 1 },
|
|
{ 0, 1 },
|
|
{ 1, 1 }
|
|
};
|
|
int viewAngleHeading[8] = { 180, 135, 90, 45, 0, -45, -90, -135 };
|
|
qboolean everyone = qfalse;
|
|
|
|
|
|
//Has to be an admin.. if anyone had it, the brig would become useless.
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_BEAM) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
trap_Argv( 1, argStr, sizeof( argStr ) );
|
|
if ( !argStr[0] ) {
|
|
trap_SendServerCommand( ent-g_entities, va( "print \"Usage: Allows you to beam yourself or another player to the location of a separate player.\nCommand: (For yourself) - beamToPlayer <ID of player to beam to> \n(For other players) - beamToPlayer <ID of player to beam> <ID of location player>\n\" " ) );
|
|
return;
|
|
}
|
|
|
|
if ( trap_Argc() == 2 ) {
|
|
clientNum = atoi( argStr );
|
|
bClientNum = ent->client->ps.clientNum;
|
|
everyone = qfalse;
|
|
}
|
|
else if ( trap_Argc() >= 3 ) {
|
|
if ( Q_stricmp( argStr, "all" ) == 0 ) {
|
|
bClientNum = -1;
|
|
everyone = qtrue;
|
|
} else {
|
|
bClientNum = atoi( argStr );
|
|
everyone = qfalse;
|
|
}
|
|
trap_Argv( 2, argStr, sizeof( argStr ) );
|
|
if ( Q_stricmp( argStr, "all" ) == 0 ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"ERROR. You can not beam a player to everyone.\nPerhaps you meant /beamToPlayer all <number>.\n\" " );
|
|
return;
|
|
}
|
|
|
|
clientNum = atoi( argStr );
|
|
}
|
|
|
|
if ( clientNum == bClientNum ) {
|
|
trap_SendServerCommand( ent-g_entities, va( "print \"ERROR. Target location player and target beaming player cannot be the same.\n\" " ) );
|
|
return;
|
|
}
|
|
|
|
if ( ( clientNum < 0 || clientNum >= MAX_CLIENTS ) || ( ( bClientNum < 0 || bClientNum >= MAX_CLIENTS ) && !everyone ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va( "print \"Invalid client specified.\n\" " ) );
|
|
return;
|
|
}
|
|
|
|
do {
|
|
if ( 1 ) { // sorry
|
|
//get our intended beam subject
|
|
if ( !everyone ) {
|
|
beamee = &g_entities[bClientNum];
|
|
j = bClientNum;
|
|
} else {
|
|
if ( g_entities[j].client ) {
|
|
beamee = &g_entities[j];
|
|
} else {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if ( beamee == NULL ) {
|
|
continue;
|
|
}
|
|
|
|
//get our intended target
|
|
target = &g_entities[clientNum];
|
|
if ( target == NULL || !target->client ) {
|
|
continue;
|
|
}
|
|
|
|
if ( g_entities[j].client->ps.clientNum == target->client->ps.clientNum ) {
|
|
continue;
|
|
}
|
|
|
|
startPoint = irandom( 1, 7 ); //we'll randomize where it checks, so players won't potentially beam to the same spot each time.
|
|
|
|
//okay, we're going to test 8 locations around our target. First one we find that's available, we'll take.
|
|
for ( i = startPoint, totalCount = 0; totalCount < 8; i++, totalCount++ ) {
|
|
|
|
//Reset the counter if it exceeds 7
|
|
if ( i >= 8 ) {
|
|
i = 0;
|
|
}
|
|
|
|
//target origin is old origin offsetted in a different direction each loop
|
|
origin[0] = target->r.currentOrigin[0] + PLAYER_BEAM_DIST * offsetRA[i][0]; //set X offset
|
|
origin[1] = target->r.currentOrigin[1] + PLAYER_BEAM_DIST * offsetRA[i][1]; //set Y offset
|
|
origin[2] = target->r.currentOrigin[2];
|
|
|
|
//do a volume trace from our old org to new org
|
|
//This vol trace is set to standard EF bounding box size, so if ANY geometry gets inside, it returns false;
|
|
trap_Trace( &tr, target->r.currentOrigin, mins, maxs, origin, target->client->ps.clientNum, MASK_ALL ); //CONTENTS_SOLID
|
|
|
|
//We didn't hit anything solid
|
|
if ( tr.fraction == 1.0 && !tr.allsolid ) {
|
|
//trace straight down to see if there's some floor immeadiately below us we can use
|
|
VectorCopy( origin, zOrigin );
|
|
zOrigin[2] -= 32;
|
|
|
|
trap_Trace( &tr, origin, NULL, NULL, zOrigin, target->client->ps.clientNum, CONTENTS_SOLID );
|
|
|
|
//ew... seems to be a chasm or something below us... don't wanna beam there
|
|
if ( tr.fraction == 1.0 ) {
|
|
continue;
|
|
}
|
|
else {
|
|
validTraceFound = qtrue;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !validTraceFound ) {
|
|
trap_SendServerCommand( ent-g_entities, va( "print \"No valid beam points next to player found.\n\" " ) );
|
|
continue;
|
|
}
|
|
|
|
VectorCopy( ent->client->ps.viewangles, angles );
|
|
angles[YAW] = (float)viewAngleHeading[i];
|
|
|
|
//Com_Printf( "OldAngle = %f, NewAngle = %f, index = %i\n", ent->client->ps.viewangles[YAW], angles[YAW], i );
|
|
|
|
if ( TransDat[ beamee->client->ps.clientNum ].beamTime == 0 ) {
|
|
if ( j == ent->client->ps.clientNum ) {
|
|
trap_SendServerCommand( ent-g_entities, va( "chat \"Initiating transport to player %s^7's co-ordinates.\n\" ", target->client->pers.netname ) );
|
|
}
|
|
else {
|
|
trap_SendServerCommand( ent-g_entities, va( "chat \"Transporting %s^7 to player %s^7's co-ordinates.\n\" ", beamee->client->pers.netname, target->client->pers.netname ) );
|
|
}
|
|
//commence beaming
|
|
G_InitTransport( beamee->client->ps.clientNum, origin, angles );
|
|
}
|
|
else if ( !everyone ) {
|
|
if ( j == ent->client->ps.clientNum ) {
|
|
trap_SendServerCommand( ent-g_entities, va( "chat \"Unable to comply. You are already within a transport cycle.\n\" " ) );
|
|
|
|
}
|
|
else {
|
|
trap_SendServerCommand( ent-g_entities, va( "chat \"Unable to comply. Subject is already within a transport cycle.\n\" " ) );
|
|
}
|
|
}
|
|
}
|
|
} while ( ( (++j) < g_maxclients.integer ) && everyone );
|
|
|
|
}
|
|
|
|
/*==============
|
|
Cmd_DoEmote_f
|
|
===============
|
|
TiM : T3h emote-zor code
|
|
Phase two. The emote index and
|
|
time length has been received from
|
|
client. Any specific flags the
|
|
emote may have will be checked here.
|
|
*/
|
|
static void Cmd_DoEmote_f ( gentity_t *ent ) {
|
|
char argStr[MAX_QPATH];
|
|
emoteList_t *emote;
|
|
int animLength;
|
|
int i;
|
|
int emoteInt;
|
|
int flagHolder=0;
|
|
qboolean doUpper = qfalse;
|
|
qboolean doLower = qfalse;
|
|
qboolean alreadyEmoting;
|
|
playerState_t *ps;
|
|
|
|
trap_Argv( 1, argStr, sizeof( argStr ) );
|
|
|
|
//RPG-X | Marcin | 24/12/2008
|
|
//n00b check
|
|
if ( g_classData[ent->client->sess.sessionClass].isn00b ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"[You're too stupid to use this command]\n\"");
|
|
return;
|
|
}
|
|
|
|
ps = &ent->client->ps;
|
|
|
|
//Small override for the specific eyes animation emotes.
|
|
//And also the alert mode now
|
|
if ( !Q_stricmp( argStr, "eyes_shut" ) || !Q_stricmp( argStr, "eyes_frown" ) || !Q_stricmpn( argStr, "alert2", 6 ) || !Q_stricmpn( argStr, "alert", 5 ) ) {
|
|
if ( !Q_stricmp( argStr, "eyes_shut" ) ) {
|
|
ps->stats[EMOTES] ^= EMOTE_EYES_SHUT;
|
|
}
|
|
|
|
else if ( !Q_stricmp( argStr, "eyes_frown" ) )
|
|
ps->stats[EMOTES] ^= EMOTE_EYES_PISSED;
|
|
else if ( !Q_stricmpn( argStr, "alert2", 6 ) )
|
|
{
|
|
ps->pm_flags &= ~ANIM_ALERT;
|
|
ps->pm_flags ^= ANIM_ALERT2;
|
|
}
|
|
else if ( !Q_stricmpn( argStr, "alert", 5 ) )
|
|
{
|
|
ps->pm_flags &= ~ANIM_ALERT2;
|
|
ps->pm_flags ^= ANIM_ALERT;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if ( trap_Argc() != 3 ) {
|
|
trap_SendServerCommand( ent-g_entities, va( "print \"Invalid arguments listed. Please use the '/emote' command to perform emotes.\n\" " ) );
|
|
return;
|
|
}
|
|
|
|
emoteInt = atoi( argStr );
|
|
emote = &bg_emoteList[ emoteInt ];
|
|
|
|
if ( !emote ) {
|
|
trap_SendServerCommand( ent-g_entities, va( "print \"Invalid emote specified.\n\" " ) );
|
|
return;
|
|
}
|
|
|
|
trap_Argv( 2, argStr, sizeof( argStr ) );
|
|
animLength = atoi( argStr );
|
|
|
|
if ( animLength > 65000 ) {
|
|
trap_SendServerCommand( ent-g_entities, va( "print \"Invalid emote time length specified.\n\" " ) );
|
|
return;
|
|
}
|
|
|
|
//Before we flush the emotes, perform a check to see if we're loopin any animations
|
|
//If we are, set this one to revert
|
|
ps->torsoAnim = 0;
|
|
ps->legsAnim = 0;
|
|
|
|
if ( emote->bodyFlags & EMOTE_UPPER ) {
|
|
doUpper = qtrue;
|
|
}
|
|
|
|
if ( emote->bodyFlags & EMOTE_LOWER ) {
|
|
doLower = qtrue;
|
|
}
|
|
|
|
if ( ( ps->stats[EMOTES] & EMOTE_UPPER ) &&
|
|
( ps->stats[EMOTES] & EMOTE_LOOP_UPPER ) )
|
|
{
|
|
if ( emote->animFlags & EMOTE_REVERTLOOP_UPPER ) {
|
|
int anim = ps->stats[TORSOANIM];
|
|
anim &= ~ANIM_TOGGLEBIT; //remove the toggle msk
|
|
|
|
for (i=0;i<bg_numEmotes;i++ ) {
|
|
if ( bg_emoteList[i].enumName == anim ) {
|
|
ps->torsoAnim = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ( ps->stats[EMOTES] & EMOTE_LOWER ) &&
|
|
( ps->stats[EMOTES] & EMOTE_LOOP_LOWER ) )
|
|
{
|
|
if ( emote->animFlags & EMOTE_REVERTLOOP_LOWER ) {
|
|
int anim = ps->stats[LEGSANIM];
|
|
anim &= ~ANIM_TOGGLEBIT;
|
|
|
|
for (i=0;i<bg_numEmotes;i++ ) {
|
|
if ( bg_emoteList[i].enumName == anim ) {
|
|
ps->legsAnim = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
alreadyEmoting = (qboolean)( ( ps->stats[EMOTES] & EMOTE_UPPER ) || ( ps->stats[EMOTES] & EMOTE_LOWER ) );
|
|
|
|
if ( alreadyEmoting ) {
|
|
doUpper = (qboolean)( ( emote->animFlags & EMOTE_OVERRIDE_UPPER ) );
|
|
doLower = (qboolean)( ( emote->animFlags & EMOTE_OVERRIDE_LOWER ) );
|
|
}
|
|
else {
|
|
if ( doLower && !( emote->animFlags & EMOTE_OVERRIDE_LOWER ) && ps->powerups[PW_FLIGHT] ) {
|
|
doLower = qfalse;
|
|
}
|
|
}
|
|
|
|
//flush out any previous emotes
|
|
if ( doUpper ) {
|
|
ps->stats[EMOTES] &= ~EMOTE_MASK_UPPER; //Remove all emotes but eye flags
|
|
|
|
flagHolder = ( emote->animFlags | emote->bodyFlags );
|
|
flagHolder &= ~(EMOTE_MASK_LOWER | EMOTE_EYES_SHUT | EMOTE_EYES_PISSED);
|
|
|
|
ps->stats[EMOTES] |= flagHolder;
|
|
}
|
|
|
|
if ( doLower ) {
|
|
ps->stats[EMOTES] &= ~EMOTE_MASK_LOWER; //Remove all emotes but eye flags
|
|
|
|
flagHolder = ( emote->animFlags | emote->bodyFlags );
|
|
flagHolder &= ~(EMOTE_MASK_UPPER | EMOTE_EYES_SHUT | EMOTE_EYES_PISSED);
|
|
|
|
ps->stats[EMOTES] |= flagHolder;
|
|
}
|
|
|
|
//The clamp flag is set here, but is then moved to cState->eFlags on the CG
|
|
//during the next snapshot. A tad more resource savvy, but for some weird reason,
|
|
//it wasn't passing directly from here... might be a scope issue.
|
|
//Huh... turns out the Ravensoft d00ds were having the same trouble too.
|
|
//My guess it's an engine problem when the vars from pState are converted to eState
|
|
//and then sent over the network. It all seems cool game-side, but screwy CG side O_o
|
|
|
|
//TiM : Since we're no longer using legsTimer and torsoTimer,
|
|
//These are great to use for additional args
|
|
|
|
//======================================
|
|
|
|
if ( doUpper ) {
|
|
if ( animLength > 0 ) {
|
|
|
|
//check to see if we don't already have a set loop anim
|
|
if ( ps->torsoAnim <= 0 && emote->enumLoop >= 0) {
|
|
for (i=0; i<bg_numEmotes; i++ ) {
|
|
if ( bg_emoteList[i].enumName == emote->enumLoop ) {
|
|
ps->torsoAnim = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
ps->stats[TORSOTIMER] = animLength;
|
|
}
|
|
else {
|
|
ps->stats[TORSOTIMER] = 0; //Infinite animations (ie sitting/typing )
|
|
}
|
|
|
|
ps->torsoTimer = emoteInt;
|
|
|
|
ps->stats[TORSOANIM] =
|
|
( ( ps->stats[TORSOANIM] & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | emote->enumName;
|
|
}
|
|
|
|
//=====================================
|
|
|
|
if ( doLower ) {
|
|
|
|
//if we had a pre-defined anim length
|
|
if ( animLength > 0 ) {
|
|
ps->stats[LEGSTIMER] = animLength;
|
|
|
|
//check to see if we don't already have a set loop anim
|
|
if ( ps->legsAnim == 0 && emote->enumLoop >= 0) {
|
|
for (i=0; i<bg_numEmotes; i++ ) {
|
|
if ( bg_emoteList[i].enumName == emote->enumLoop ) {
|
|
ps->legsAnim = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
ps->stats[LEGSTIMER] = 0;
|
|
}
|
|
|
|
//set emote num into emote timer so we can use it in pmove
|
|
ps->legsTimer = emoteInt;
|
|
|
|
//ent->client->ps.legsAnim =
|
|
//( ( ent->client->ps.legsAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | anim;
|
|
ps->stats[LEGSANIM] =
|
|
( ( ps->stats[LEGSANIM] & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | emote->enumName;
|
|
}
|
|
}
|
|
|
|
/*==============
|
|
Cmd_EndEmote_f
|
|
Ends all active emotes.
|
|
I originally had it so holding the
|
|
walk button did this, but then found out
|
|
that it's permanently held down in other instances :S
|
|
================*/
|
|
static void Cmd_EndEmote_f( gentity_t *ent ) {
|
|
playerState_t *ps;
|
|
|
|
if( !ent->client )
|
|
return;
|
|
|
|
ps = &ent->client->ps;
|
|
|
|
ps->stats[EMOTES] &= ~EMOTE_MASK_BOTH;
|
|
|
|
ps->legsTimer = 0;
|
|
ps->legsAnim = 0;
|
|
ps->stats[LEGSTIMER] = 0;
|
|
|
|
|
|
ps->torsoTimer = 0;
|
|
ps->torsoAnim = 0;
|
|
ps->stats[TORSOTIMER] = 0;
|
|
}
|
|
|
|
/*==============
|
|
Cmd_Laser_f
|
|
Activates the Laser the same way
|
|
as cloaking or flying. The previous
|
|
code was bad in the fact that it used
|
|
up entity slots, had to constantly
|
|
call think funcs to update, and then
|
|
transmit the origins over the network,
|
|
resulting in sluggish movement for high
|
|
ping d00ds.
|
|
===============*/
|
|
static void Cmd_Laser_f ( gentity_t *ent ) {
|
|
char* message;
|
|
playerState_t *ps = &ent->client->ps;
|
|
|
|
//TiM - Say... what was the max length of time a Q3 server was capable of running
|
|
//nonstop again lol? :)
|
|
if ( !ps->powerups[PW_LASER] ) {
|
|
ps->powerups[PW_LASER] = level.time + 10000000;
|
|
message = "Activated Laser";
|
|
}
|
|
else {
|
|
ps->powerups[PW_LASER] = level.time;
|
|
message = "Deactivated Laser";
|
|
}
|
|
|
|
trap_SendServerCommand( ent-g_entities, va( " print \"%s\n\" ", message ) );
|
|
}
|
|
|
|
/*==============
|
|
Cmd_FlashLight_f
|
|
==============*/
|
|
static void Cmd_FlashLight_f ( gentity_t *ent ) {
|
|
char* message;
|
|
playerState_t *ps = &ent->client->ps;
|
|
|
|
//TiM - Say... what was the max length of time a Q3 server was capable of running
|
|
//nonstop again lol? :)
|
|
if ( !ps->powerups[PW_FLASHLIGHT] ) {
|
|
ps->powerups[PW_FLASHLIGHT] = level.time + 10000000;
|
|
message = "Activated Flashlight";
|
|
}
|
|
else {
|
|
ps->powerups[PW_FLASHLIGHT] = level.time;
|
|
message = "Deactivated Flashlight";
|
|
}
|
|
|
|
trap_SendServerCommand( ent-g_entities, va( " print \"%s\n\" ", message ) );
|
|
}
|
|
|
|
/*==============
|
|
Cmd_fxGun_f
|
|
TiM: Allows admins
|
|
to configure their
|
|
FX guns to emit different FX
|
|
==============*/
|
|
static void Cmd_fxGun_f ( gentity_t *ent ) {
|
|
char arg[MAX_TOKEN_CHARS];
|
|
char fxName[36];
|
|
const int FX_DEFAULT_TIME = 900000;
|
|
fxGunData_t *fxGunData;
|
|
|
|
if ( !ent->client )
|
|
return;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_FX) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
trap_Argv( 1, arg, sizeof( arg ) );
|
|
|
|
//save the name for the end
|
|
Q_strncpyz( fxName, arg, sizeof( fxName ) );
|
|
|
|
fxGunData = &ent->client->fxGunData;
|
|
|
|
if ( !Q_stricmp ( arg, "default" ) ) {
|
|
memset( fxGunData, 0, sizeof( fxGunData ) );
|
|
}
|
|
else if ( !Q_stricmp ( arg, "detpack" ) ) {
|
|
memset( fxGunData, 0, sizeof( fxGunData ) );
|
|
fxGunData->eventNum = EV_DETPACK;
|
|
}
|
|
else if ( !Q_stricmp( arg, "chunks" ) ) {
|
|
memset( fxGunData, 0, sizeof( fxGunData ) );
|
|
//radius
|
|
trap_Argv( 2, arg, sizeof( arg ) );
|
|
if ( !arg[0] ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Syntax: /fxGun chunks <radius> <chunk type: 1-5>\n\" " );
|
|
return;
|
|
}
|
|
|
|
fxGunData->arg_int1 = atoi( arg );
|
|
fxGunData->eventNum = EV_FX_CHUNKS;
|
|
|
|
//radius
|
|
trap_Argv( 3, arg, sizeof( arg ) );
|
|
if ( !arg[0] ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Syntax: /fxGun chunks <radius> <chunk type: 1-5>\n\" " );
|
|
memset( fxGunData, 0, sizeof( fxGunData ) );
|
|
return;
|
|
}
|
|
|
|
fxGunData->arg_int2 = atoi( arg );
|
|
}
|
|
else if ( !Q_stricmp ( arg, "sparks" ) ) {
|
|
memset( fxGunData, 0, sizeof( fxGunData ) );
|
|
trap_Argv( 2, arg, sizeof( arg ) );
|
|
if ( !arg[0] ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Syntax: /fxGun sparks <spark time interval> <time length of effect> | in milliseconds\n\" " );
|
|
return;
|
|
}
|
|
|
|
fxGunData->eventNum = EV_FX_SPARK;
|
|
fxGunData->arg_float1 = atof( arg );
|
|
|
|
//optional arg for timelength
|
|
trap_Argv( 3, arg, sizeof( arg ) );
|
|
if ( arg[0] && atoi( arg ) ) {
|
|
fxGunData->arg_int2 = atoi(arg);
|
|
}
|
|
else {
|
|
fxGunData->arg_int2 = FX_DEFAULT_TIME;
|
|
}
|
|
}
|
|
else if ( !Q_stricmp ( arg, "steam" ) ) {
|
|
memset( fxGunData, 0, sizeof( fxGunData ) );
|
|
fxGunData->eventNum = EV_FX_STEAM;
|
|
|
|
//optional arg for timelength
|
|
trap_Argv( 2, arg, sizeof( arg ) );
|
|
if ( arg[0] && atoi( arg ) ) {
|
|
fxGunData->arg_int2 = atoi(arg);
|
|
}
|
|
else {
|
|
fxGunData->arg_int2 = FX_DEFAULT_TIME;
|
|
}
|
|
}
|
|
else if ( !Q_stricmp( arg, "drips" ) ) {
|
|
memset( fxGunData, 0, sizeof( fxGunData ) );
|
|
//type of drips
|
|
trap_Argv( 2, arg, sizeof( arg ) );
|
|
if ( !arg[0] ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Syntax: /fxGun drips <type of drips: 0,1,2> <drips intensity: 0.0->1.0> <time length of effect: 1000 = 1 second> \n\" " );
|
|
return;
|
|
}
|
|
|
|
fxGunData->eventNum = EV_FX_DRIP;
|
|
fxGunData->arg_int1 = atoi( arg );
|
|
|
|
//intensity of drips
|
|
trap_Argv( 3, arg, sizeof( arg ) );
|
|
if ( !arg[0] ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Syntax: /fxGun drips <type of drips: 0,1,2> <drips intensity: 0.0->1.0> <time length of effect: 1000 = 1 second> \n\" " );
|
|
fxGunData->eventNum = 0;
|
|
fxGunData->arg_int1 = 0;
|
|
return;
|
|
}
|
|
|
|
fxGunData->arg_float1 = atof( arg );
|
|
|
|
//optional time length
|
|
trap_Argv( 4, arg, sizeof( arg ) );
|
|
if ( arg[0] && atoi( arg ) ) {
|
|
fxGunData->arg_int2 = atoi(arg);
|
|
}
|
|
else {
|
|
fxGunData->arg_int2 = FX_DEFAULT_TIME;
|
|
}
|
|
}
|
|
else if ( !Q_stricmp( arg, "smoke" ) ) {
|
|
memset( fxGunData, 0, sizeof( fxGunData ) );
|
|
//smoke radius
|
|
trap_Argv( 2, arg, sizeof( arg ) );
|
|
if ( !arg[0] ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Syntax: /fxGun smoke <smoke radius size> <time length of effect: 1000 = 1 second> \n\" " );
|
|
return;
|
|
}
|
|
|
|
fxGunData->eventNum = EV_FX_SMOKE;
|
|
fxGunData->arg_int1 = atoi( arg );
|
|
|
|
//optional time length
|
|
trap_Argv( 3, arg, sizeof( arg ) );
|
|
if ( arg[0] && atoi( arg )) {
|
|
fxGunData->arg_int2 = atoi(arg);
|
|
}
|
|
else {
|
|
fxGunData->arg_int2 = FX_DEFAULT_TIME;
|
|
}
|
|
|
|
}
|
|
else if ( !Q_stricmp( arg, "surf_explosion" ) ) {
|
|
memset( fxGunData, 0, sizeof( fxGunData ) );
|
|
//explosion radius
|
|
trap_Argv( 2, arg, sizeof( arg ) );
|
|
if ( !arg[0] ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Syntax: /fxGun surf_explosion <explosion radius> <camera shake intensity> \n\" " );
|
|
return;
|
|
}
|
|
|
|
fxGunData->eventNum = EV_FX_SURFACE_EXPLOSION;
|
|
fxGunData->arg_float1 = atof( arg );
|
|
|
|
//explosion cam shake
|
|
trap_Argv( 3, arg, sizeof( arg ) );
|
|
if ( !arg[0] ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Syntax: /fxGun surf_explosion <explosion radius> <camera shake intensity> \n\" " );
|
|
|
|
fxGunData->eventNum = 0;
|
|
fxGunData->arg_float1 = 0;
|
|
return;
|
|
}
|
|
|
|
fxGunData->arg_float2 = atof( arg );
|
|
}
|
|
else if ( !Q_stricmp( arg, "elec_explosion" ) ) {
|
|
memset( fxGunData, 0, sizeof( fxGunData ) );
|
|
//explosion radius
|
|
trap_Argv( 2, arg, sizeof( arg ) );
|
|
if ( !arg[0] ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Syntax: /fxGun elec_explosion <explosion radius> \n\" " );
|
|
return;
|
|
}
|
|
|
|
fxGunData->eventNum = EV_FX_ELECTRICAL_EXPLOSION;
|
|
fxGunData->arg_float1 = atof( arg );
|
|
|
|
}
|
|
else if ( !Q_stricmp( arg, "fire" ) ) {
|
|
memset( fxGunData, 0, sizeof( fxGunData ) );
|
|
//time
|
|
trap_Argv( 2, arg, sizeof( arg ) );
|
|
if ( !arg[0] ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Syntax: /fxGun fire <radius> <time> \n\" " );
|
|
return;
|
|
}
|
|
|
|
fxGunData->eventNum = EV_FX_FIRE;
|
|
fxGunData->arg_int1 = atoi( arg );
|
|
|
|
//optional time length
|
|
trap_Argv( 3, arg, sizeof( arg ) );
|
|
if ( arg[0] && atoi( arg ) ) {
|
|
fxGunData->arg_int2 = atoi( arg );
|
|
}
|
|
else {
|
|
fxGunData->arg_int2 = FX_DEFAULT_TIME;
|
|
}
|
|
|
|
}
|
|
else if ( !Q_stricmp( arg, "shake" ) ) {
|
|
memset( fxGunData, 0, sizeof( fxGunData ) );
|
|
//time
|
|
trap_Argv( 2, arg, sizeof( arg ) );
|
|
if ( !arg[0] ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Syntax: /fxGun shake <radius> <intensity> \n\" " );
|
|
return;
|
|
}
|
|
|
|
fxGunData->eventNum = EV_FX_SHAKE;
|
|
fxGunData->arg_int1 = atoi( arg );
|
|
|
|
//optional intensity
|
|
trap_Argv( 3, arg, sizeof( arg ) );
|
|
if ( !arg[0] ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Syntax: /fxGun shake <radius> <intensity> \n\" " );
|
|
return;
|
|
}
|
|
|
|
fxGunData->arg_int2 = atoi( arg );
|
|
|
|
}
|
|
else {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Syntax: /fxGun <FX_Name>\nValid Effects:\n default\n chunks\n detpack\n sparks\n steam\n drips\n smoke\n surf_explosion\n elec_explosion \n\" " );
|
|
memset( fxGunData, 0, sizeof( fxGunData ) );
|
|
return;
|
|
}
|
|
|
|
trap_SendServerCommand( ent-g_entities, va( "print \"Effect successfully reconfigured to %s.\n\" ", fxName ) );
|
|
}
|
|
|
|
/*==============
|
|
Cmd_flushFX_f
|
|
TiM: Systematically
|
|
purges ALL ACTIVE
|
|
CLIENTSIDE EFFECTS!
|
|
This is a safety feature
|
|
if an admin was a little too
|
|
happy with the FX gun
|
|
==============*/
|
|
static void Cmd_flushFX_f( gentity_t *ent ) {
|
|
if ( !ent->client )
|
|
return;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_FX) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
trap_SendServerCommand( -1, "cg_flushFX" );
|
|
}
|
|
|
|
/*=================
|
|
Cmd_spawnChar_f
|
|
TiM: Takes ur current data, and
|
|
spawns a player model that looks like you with it.
|
|
==================*/
|
|
static void Cmd_spawnChar_f( gentity_t *ent ) {
|
|
if ( !ent->client )
|
|
return;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_CHARS) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if ( !PlaceDecoy(ent) )
|
|
{
|
|
trap_SendServerCommand( ent-g_entities, "cp \"NO ROOM TO PLACE CHARACTER\"" );
|
|
}
|
|
else
|
|
{
|
|
trap_SendServerCommand( ent-g_entities, "cp \"CHARACTER PLACED\"" );
|
|
}
|
|
}
|
|
|
|
/*====================
|
|
Cmd_flushChars_f
|
|
TiM: Purges all the decoys on the server
|
|
====================*/
|
|
static void Cmd_fluchChars_f( gentity_t *ent ) //GSIO01: fluch Chars ehhh? you know fluch means curse in german? :D
|
|
{
|
|
char arg[16];
|
|
int i;
|
|
gentity_t *locEnt;
|
|
|
|
if ( !ent->client )
|
|
return;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_CHARS) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
trap_Argv( 1, arg, sizeof(arg) );
|
|
if ( !arg[0] ) {
|
|
trap_SendServerCommand( ent-g_entities,"print \"Usage: Removes spawn characters from the level.\nSyntax: /flushChars <number> | 0 = Just your spawned characters, 1 = All characters\n\" " );
|
|
return;
|
|
}
|
|
|
|
for ( i=0, locEnt=g_entities; i < level.num_entities; locEnt++, i++ ) {
|
|
if ( !Q_stricmp( locEnt->classname, "decoy" ) ) {
|
|
if ( atoi( arg ) == 0 && locEnt->parent != ent )
|
|
continue;
|
|
else
|
|
G_FreeEntity( locEnt );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*====================
|
|
Cmd_flushDropped_f
|
|
RPG-X: Marcin: Removes all dropped weapons - 04/12/2008
|
|
code stolen from above
|
|
====================*/
|
|
static void Cmd_flushDropped_f( gentity_t *ent )
|
|
{
|
|
char arg[16];
|
|
int i;
|
|
qboolean ans;
|
|
gentity_t *locEnt;
|
|
|
|
if ( !ent->client )
|
|
return;
|
|
|
|
trap_Argv( 1, arg, sizeof(arg) );
|
|
if ( !arg[0] ) {
|
|
ans = (qboolean)0;
|
|
} else {
|
|
ans = (qboolean)atoi( arg );
|
|
}
|
|
|
|
for ( i=0, locEnt=g_entities; i < level.num_entities; locEnt++, i++ ) {
|
|
if ( locEnt->classname && !Q_strncmp( locEnt->classname, "weapon", 6) ) { // everything that begins with weapon_
|
|
if ( ( ans == qfalse || !IsAdmin( ent ) ) && locEnt->parent != ent )
|
|
continue;
|
|
else
|
|
G_FreeEntity( locEnt );
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
===================
|
|
Cmd_Kick2_f
|
|
|
|
kick2 <player> <reason>
|
|
|
|
Boots the user off the server while
|
|
giving them a reason why they deserved it so
|
|
|
|
Credit: Scooter, TiM
|
|
===================
|
|
*/
|
|
static void Cmd_Kick2_f( gentity_t *ent ) {
|
|
gclient_t *cl;
|
|
char str[MAX_TOKEN_CHARS];
|
|
char *str2;
|
|
char reason[MAX_TOKEN_CHARS];
|
|
int i;
|
|
|
|
//standard checks
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_KICK) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if(!ent || !ent->client)
|
|
return;
|
|
|
|
// find the player
|
|
trap_Argv( 1, str, sizeof( str ) );
|
|
//If player adds no args, write a friendly msg saying how it works
|
|
if ( !str[0] ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Usage: Kicks specified user with a reason\n\nCommand: kick [User ID] <Reason>\n\"" );
|
|
return;
|
|
}
|
|
|
|
//if we were told to kick all
|
|
if ( !Q_stricmp( str, "all" ) ) {
|
|
//loop thru everyone
|
|
for (i = 0; i < MAX_CLIENTS; i++ ) {
|
|
//check if they are a client and NOT US LOL
|
|
if ( g_entities[i].client &&
|
|
g_entities[i].client->ps.clientNum != ent->client->ps.clientNum ) {
|
|
//if there was only one arg, just kick em
|
|
if ( trap_Argc() <= 2 ) {
|
|
trap_SendConsoleCommand( EXEC_APPEND, va("kick \"%i\"\n", g_entities[i].client->ps.clientNum ) );
|
|
}
|
|
else { //else give em a reason I guess
|
|
str2 = ConcatArgs( 2 );
|
|
Com_sprintf(reason, MAX_TOKEN_CHARS, "Kicked: %s", str2 );
|
|
|
|
trap_DropClient( g_entities[i].client-level.clients, reason );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//also, if we wanna destroy all bots
|
|
else if ( !Q_stricmp( str, "allbots" ) ) {
|
|
for (i = 0; i < MAX_CLIENTS; i++ ) {
|
|
if ( (g_entities[i].client && g_entities[i].r.svFlags & SVF_BOT) ) {
|
|
trap_SendConsoleCommand( EXEC_APPEND, va("kick \"%i\"\n", g_entities[i].client->ps.clientNum ) );
|
|
}
|
|
}
|
|
}
|
|
//The original kick2 code - crafted by Scooter
|
|
else {
|
|
cl = ClientForString( str );
|
|
if ( !cl ) {
|
|
return;
|
|
}
|
|
|
|
//TiM: trap_Argc works along the principle that the command name itself (ie in this case, "kick2") is an argument too
|
|
if ( trap_Argc() <= 2 ) {
|
|
trap_SendConsoleCommand( EXEC_APPEND, va("kick \"%i\"\n", cl->ps.clientNum ) );
|
|
}
|
|
else {
|
|
// show him the exit
|
|
str2 = ConcatArgs( 2 );
|
|
Com_sprintf(reason, MAX_TOKEN_CHARS, "Kicked: %s", str2 );
|
|
|
|
trap_DropClient( cl - level.clients, reason );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_ClampInfo_f
|
|
|
|
TiM: If an admin does to a player, they'll
|
|
become unable to change any of their
|
|
server side parameters (ie name, model, etc)
|
|
=================
|
|
*/
|
|
|
|
static void Cmd_ClampInfo_f( gentity_t* ent ) {
|
|
char buffer[5];
|
|
char *message;
|
|
gentity_t *targ;
|
|
|
|
if ( !ent->client )
|
|
return;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_CLAMP) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
//get the arg
|
|
trap_Argv( 1, buffer, sizeof( buffer ) );
|
|
|
|
//no arg
|
|
if ( !buffer[0] ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Usage: Force stops players from changing their user info\n\nCommand: clampInfo <client ID>\n\"" );
|
|
return;
|
|
}
|
|
|
|
targ = &g_entities[atoi(buffer)];
|
|
|
|
if( !targ || !targ->client )
|
|
return;
|
|
|
|
targ->flags ^= FL_CLAMPED;
|
|
|
|
if ( targ->flags & FL_CLAMPED )
|
|
message = va( "%s ^7has now had their info clamped.", targ->client->pers.netname);
|
|
else
|
|
message = va( "%s ^7has now had their info un-clamped.", targ->client->pers.netname);
|
|
|
|
trap_SendServerCommand( ent-g_entities, va( "print \"%s\n\"", message ) );
|
|
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_Turbolift_f
|
|
|
|
TiM: Someone entered a turbolift command
|
|
sets up the needed elements
|
|
=================
|
|
*/
|
|
|
|
static void Cmd_Turbolift_f( gentity_t* ent )
|
|
{
|
|
char arg[4];
|
|
int numEnts;
|
|
int touch[MAX_GENTITIES];
|
|
vec3_t mins, maxs;
|
|
int targDeck;
|
|
static vec3_t range = { 40, 40, 52 };
|
|
int i;
|
|
gentity_t *lift=NULL;
|
|
gentity_t *otherLift=NULL;
|
|
playerState_t *ps;
|
|
|
|
if ( !ent->client )
|
|
return;
|
|
|
|
ps = &ent->client->ps;
|
|
|
|
if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR )
|
|
return;
|
|
|
|
if ( ps->stats[STAT_HEALTH] <= 0 ) {
|
|
return;
|
|
}
|
|
|
|
trap_Argv( 2, arg, sizeof(arg) );
|
|
|
|
if ( !arg[0] )
|
|
{
|
|
trap_SendServerCommand( ent-g_entities, "print \"You must specify a deck\n\" " );
|
|
return;
|
|
}
|
|
|
|
targDeck = atoi( arg );
|
|
|
|
if ( targDeck <= 0 )
|
|
{
|
|
trap_SendServerCommand( ent-g_entities, "print \"Error: Deck was not recognized\n\" " );
|
|
return;
|
|
}
|
|
|
|
//checking to make sure we're inside a lift ent right now
|
|
VectorSubtract( ps->origin, range, mins );
|
|
VectorAdd( ps->origin, range, maxs );
|
|
|
|
numEnts = trap_EntitiesInBox( mins, maxs, touch, MAX_GENTITIES );
|
|
|
|
for ( i = 0; i<numEnts; i++ )
|
|
{
|
|
lift = &g_entities[touch[i]];
|
|
|
|
if ( !lift )
|
|
continue;
|
|
|
|
//found our ent!
|
|
if ( !Q_stricmp( lift->classname, "target_turbolift" ) )
|
|
{
|
|
break;
|
|
}
|
|
//reset it
|
|
lift = NULL;
|
|
}
|
|
|
|
if ( !lift )
|
|
{
|
|
trap_SendServerCommand( ent-g_entities, "print \"You are not inside a turbolift\n\" " );
|
|
return;
|
|
}
|
|
|
|
if ( lift->flags & FL_LOCKED && (!IsAdmin(ent)) ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"Turbolift is offline.\n\"" );
|
|
return;
|
|
}
|
|
|
|
if ( lift->count > 0 )
|
|
{
|
|
trap_SendServerCommand( ent-g_entities, "print \"Turbolift is currently in use.\n\" " );
|
|
return;
|
|
}
|
|
|
|
if ( lift->health == targDeck )
|
|
{
|
|
trap_SendServerCommand( ent-g_entities, "print \"You cannot specify your current turbolift\n\" " );
|
|
return;
|
|
}
|
|
|
|
//FIXME: random deck->turbolift search
|
|
//Fixed
|
|
{
|
|
int numLifts=0;
|
|
gentity_t* lifts[12];
|
|
|
|
while ( ( otherLift=G_Find( otherLift, FOFS( classname ), "target_turbolift" )) != NULL )
|
|
{
|
|
if ( otherLift->health == targDeck )
|
|
{
|
|
if ( numLifts >= 12 )
|
|
break;
|
|
|
|
lifts[numLifts] = otherLift;
|
|
numLifts++;
|
|
}
|
|
}
|
|
|
|
if ( !numLifts )
|
|
{
|
|
otherLift = NULL;
|
|
}
|
|
else
|
|
{
|
|
otherLift = lifts[rand() % numLifts];
|
|
}
|
|
}
|
|
|
|
if ( !otherLift )
|
|
{
|
|
trap_SendServerCommand( ent-g_entities, "print \"Could not find desired deck number.\n\" " );
|
|
return;
|
|
}
|
|
|
|
lift->count = otherLift - g_entities;
|
|
otherLift->count = lift - g_entities;
|
|
|
|
lift->nextthink = level.time + FRAMETIME;
|
|
lift->think = target_turbolift_start;
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_Me_f
|
|
=================
|
|
*/
|
|
static void Cmd_MeAction_f( gentity_t* ent )
|
|
{
|
|
char message[512];
|
|
|
|
if ( !ent->client )
|
|
return;
|
|
|
|
if ( trap_Argc() < 2 )
|
|
{
|
|
trap_SendServerCommand( ent-g_entities, "print \"Chat Emote Command.\nUsage: type a 3rd person action sentence.\nExample: 'sits down'.\n\"" );
|
|
return;
|
|
}
|
|
|
|
//RPG-X | Marcin | 24/12/2008
|
|
//n00b check
|
|
if ( g_classData[ent->client->sess.sessionClass].isn00b ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"[You're too stupid to use this command]\n\"");
|
|
return;
|
|
}
|
|
|
|
Q_strncpyz( message, ConcatArgs( 1 ), sizeof( message ) );
|
|
|
|
trap_SendServerCommand( -1, va("print \"%s" S_COLOR_WHITE " %s\n\"", ent->client->pers.netname, message ) );
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_MeLocal_f
|
|
Based of J's code
|
|
=================
|
|
*/
|
|
static void Cmd_MeActionLocal_f( gentity_t* ent )
|
|
{
|
|
char message[512];
|
|
gentity_t* OtherPlayer; //Entity pointers to other players in game (used in loop)
|
|
int i; //Loop Counter
|
|
|
|
if ( !ent->client )
|
|
return;
|
|
|
|
if ( trap_Argc() < 2 )
|
|
{
|
|
trap_SendServerCommand( ent-g_entities, "print \"Chat Emote Command in your Immediate Area.\nUsage: type a 3rd person action sentence.\nExample: 'sits down'.\n\"" );
|
|
return;
|
|
}
|
|
|
|
//RPG-X | Marcin | 24/12/2008
|
|
//n00b check
|
|
if ( g_classData[ent->client->sess.sessionClass].isn00b ) {
|
|
trap_SendServerCommand( ent-g_entities, "print \"[You're too stupid to use this command]\n\"");
|
|
return;
|
|
}
|
|
|
|
Q_strncpyz( message, ConcatArgs( 1 ), sizeof( message ) );
|
|
|
|
if ( g_dedicated.integer ) {
|
|
G_Printf( "%s emoted to area: %s\n", ent->client->pers.netname, message);
|
|
}
|
|
|
|
|
|
//Loop Through Clients on the server
|
|
//RPG-X: J2J - BugFix: used to be connected clients which meant most clients were missed out and other bugs.
|
|
// Change to max clients and the loop ingores invalid players.
|
|
for(i = 0; i < level.maxclients; i++)
|
|
{
|
|
|
|
OtherPlayer = &g_entities[i]; //Point OtherPlayer to next player
|
|
|
|
//Send message to admins warning about command being used.
|
|
//TiM - since double spamming is annoying, ensure that the target admin wants this alert
|
|
if ( !OtherPlayer->client->noAdminChat && IsAdmin(OtherPlayer) )
|
|
trap_SendServerCommand( -1, va("print \"%s" S_COLOR_CYAN" (locally) " S_COLOR_WHITE "%s\n\"", ent->client->pers.netname, message ) );
|
|
|
|
//Check is OtherPlayer is valid
|
|
if ( !OtherPlayer || !OtherPlayer->inuse || !OtherPlayer->client )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ( trap_InPVS( ent->client->ps.origin, OtherPlayer->client->ps.origin ) )
|
|
{
|
|
//Communicate to the player
|
|
trap_SendServerCommand( i, va("print \"%s" S_COLOR_WHITE " %s\n\"", ent->client->pers.netname, message ) );
|
|
}
|
|
|
|
OtherPlayer = NULL; //Reset pointer ready for next iteration.
|
|
}
|
|
}
|
|
|
|
static void Cmd_MapsList_f( gentity_t *ent )
|
|
{
|
|
char mapList[1024];
|
|
char fileList[4096];
|
|
int numFiles;
|
|
char *filePtr;
|
|
int i;
|
|
int len;
|
|
|
|
if ( !ent->client )
|
|
return;
|
|
|
|
numFiles = trap_FS_GetFileList( "maps", "bsp", fileList, sizeof(fileList) );
|
|
|
|
if ( numFiles <= 0 )
|
|
return;
|
|
|
|
filePtr = fileList;
|
|
memset( mapList, 0, sizeof(mapList) );
|
|
|
|
for ( i = 0; i < numFiles; i++, filePtr += (len+1) )
|
|
{
|
|
len = strlen( filePtr );
|
|
|
|
if ( len <= 0 || !filePtr )
|
|
return;
|
|
|
|
if ( strchr(filePtr,'/') || strchr(filePtr,'\\') )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ( strlen(mapList) + len + 20 >= sizeof( mapList ) )
|
|
break;
|
|
|
|
Q_strcat( mapList, sizeof( mapList ), filePtr );
|
|
Q_strcat( mapList, sizeof( mapList ), "\n" );
|
|
}
|
|
|
|
trap_SendServerCommand( ent-g_entities, va( "print \"%s\" ", mapList ) );
|
|
}
|
|
|
|
|
|
/*
|
|
=================
|
|
Cmd_Drop_f
|
|
RPG-X
|
|
Marcin 03/12/2008
|
|
=================
|
|
*/
|
|
static void Cmd_Drop_f( gentity_t *ent ) {
|
|
char txt[512];
|
|
|
|
if ( trap_Argc() < 2 ) {
|
|
txt[0] = '\0';
|
|
}
|
|
|
|
Q_strncpyz( txt, ConcatArgs( 1 ), sizeof( txt ) );
|
|
ThrowWeapon( ent, txt );
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_lockDoor_f
|
|
GSIO01 | 08/05/2009
|
|
=================
|
|
*/
|
|
static void Cmd_lockDoor_f(gentity_t *ent) {
|
|
//RPG-X | GSIO01 | 08/05/2009: I use the useent code as base
|
|
char entArg[MAX_TOKEN_CHARS];
|
|
gentity_t *targetEnt;
|
|
int index;
|
|
playerState_t *ps;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_LOCK) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
trap_Argv( 1, entArg, sizeof( entArg ) );
|
|
|
|
//No arguments - Do a trace
|
|
if ( !entArg[0] ) {
|
|
vec3_t start, forward, end;
|
|
trace_t tr;
|
|
|
|
ps = &ent->client->ps;
|
|
|
|
//calc start
|
|
VectorCopy( ent->r.currentOrigin, start );
|
|
start[2] += ps->viewheight;
|
|
|
|
//calc end
|
|
AngleVectors( ps->viewangles, forward, NULL, NULL );
|
|
VectorMA( start, 8192, forward, end );
|
|
|
|
//trace-er-roo
|
|
trap_Trace( &tr, start, NULL, NULL, end, ps->clientNum, MASK_SHOT );
|
|
|
|
index = tr.entityNum;
|
|
}
|
|
else { //We gotz an arg, so put it in
|
|
index = atoi( entArg );
|
|
}
|
|
|
|
//invalid value ... so I guess it could be a targetname
|
|
if ( index < MAX_CLIENTS || index >= ENTITYNUM_WORLD ) {
|
|
targetEnt = G_Find (NULL, FOFS(targetname), entArg );
|
|
|
|
//STILL no dice?? Gah... just eff it then lol.
|
|
if ( !targetEnt ) {
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
targetEnt = &g_entities[index]; //get the ent
|
|
}
|
|
|
|
//find out the ent is valid, and it is useable
|
|
//TiM: Hack. Well... since we can use usables anyway, I'ma gonna disable them here.
|
|
//Doing it this way can screw up maps bigtime. >.<
|
|
//RPG_Chambers may never be the same again.... :S
|
|
if ( ( targetEnt ) ) {
|
|
if ( Q_stricmp( targetEnt->classname, "func_door" ) ) {
|
|
//GSIO01 not a func_door?? well then check wheter its a rotating door
|
|
if( Q_stricmp(targetEnt->classname, "func_door_rotating") ) {
|
|
trap_SendServerCommand( ent-g_entities, va( " print \"Entity %i isn't a door.\n\" ", index ) );
|
|
return;
|
|
}
|
|
}
|
|
|
|
targetEnt->flags ^= FL_LOCKED;
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_ffColor_f
|
|
GSIO01 | 09/05/2009
|
|
=================
|
|
*/
|
|
static void Cmd_ffColor_f(gentity_t *ent) {
|
|
char arg[16];
|
|
int i;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_FFSTUFF) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
trap_Argv(1, arg, sizeof(arg));
|
|
i = atoi(arg);
|
|
if(i < 0 || i > 3)
|
|
trap_Cvar_Set("rpg_forceFieldColor", "0");
|
|
else
|
|
trap_Cvar_Set("rpg_forceFieldColor", va("%i", i));
|
|
}
|
|
|
|
static int lastRemodulation[3] = { 0, 0 , 0 };
|
|
/*
|
|
=================
|
|
Cmd_remodulate_f
|
|
GSIO01 | 09/05/2009
|
|
=================
|
|
*/
|
|
static void Cmd_remodulate_f(gentity_t *ent) {
|
|
char arg[16];
|
|
int i;
|
|
if(!rpg_allowRemodulation.integer)
|
|
return;
|
|
if(trap_Argc() < 2) {
|
|
G_PrintfClient(ent, "Usage: remodulate i, where i: 1 = phaser, 2 = phaser rifle and 3 = disruptor\n");
|
|
G_PrintfClient(ent, "Usage: phaser, prifle, disruptor\n");
|
|
return;
|
|
}
|
|
trap_Argv(1, arg, sizeof(arg));
|
|
if(!Q_strncmp(arg, "phaser", 6))
|
|
i = 1;
|
|
else if(!Q_strncmp(arg, "prifle", 6))
|
|
i = 2;
|
|
else if(!Q_strncmp(arg, "disruptor", 9))
|
|
i = 3;
|
|
else
|
|
i = atoi(arg);
|
|
|
|
if(i < 1 || i > 3) return;
|
|
|
|
if(lastRemodulation[i-1] && (level.time - lastRemodulation[i-1] > rpg_RemodulationDelay.integer)) {
|
|
G_PrintfClient(ent, "You have to wait some time until you can remodulate again.\n");
|
|
return;
|
|
}
|
|
|
|
switch(i) {
|
|
case 1:
|
|
level.borgAdaptHits[WP_5] = 0;
|
|
trap_SendServerCommand(-1, va("print \"Phasers have been remodulated.\n\""));
|
|
break;
|
|
case 2:
|
|
level.borgAdaptHits[WP_6] = 0;
|
|
trap_SendServerCommand(-1, va("print \"Compression Rifles have been remodulated.\n\""));
|
|
break;
|
|
case 3:
|
|
level.borgAdaptHits[WP_10] = 0;
|
|
trap_SendServerCommand(-1, va("print \"Disruptors have been remodulated.\n\""));
|
|
break;
|
|
default:
|
|
G_PrintfClient(ent, "Usage: remodulate i, where i: 1 = phaser, 2 = phaser rifle and 3 = disruptor\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_unlockAll_f
|
|
GSIO01 | 11/05/2009
|
|
=================
|
|
*/
|
|
static void Cmd_unlockAll_f(gentity_t *ent) {
|
|
int i;
|
|
if(!ent || !ent->client)
|
|
return;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_LOCK) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
for(i = g_maxclients.integer; i < MAX_GENTITIES ; i++) {
|
|
if(Q_stricmp(g_entities[i].classname, "func_door") == 0 && (g_entities[i].flags & FL_LOCKED))
|
|
g_entities[i].flags ^= FL_LOCKED;
|
|
else if(Q_stricmp(g_entities[i].classname, "func_door_rotating") == 0 && (g_entities[i].flags & FL_LOCKED))
|
|
g_entities[i].flags ^= FL_LOCKED;
|
|
}
|
|
G_PrintfClient(ent, "All doors unlocked.\n");
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_Respawn_f
|
|
GSIO01 | 12/05/2009
|
|
=================
|
|
*/
|
|
static void Cmd_Respawn_f(gentity_t *ent) {
|
|
gentity_t *tent;
|
|
if(!ent)
|
|
return;
|
|
if(!ent->client)
|
|
return;
|
|
|
|
G_Client_Spawn(ent, 0, qfalse);
|
|
if(ent->client->sess.sessionTeam != TEAM_SPECTATOR) {
|
|
ent->client->ps.powerups[PW_QUAD] = level.time + 4000;
|
|
tent = G_TempEntity( ent->client->ps.origin, EV_PLAYER_TRANSPORT_IN );
|
|
tent->s.clientNum = ent->s.clientNum;
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_lockAll_f
|
|
GSIO01 | 12/05/2009
|
|
=================
|
|
*/
|
|
static void Cmd_lockAll_f(gentity_t *ent) {
|
|
int i;
|
|
if(!ent || !ent->client)
|
|
return;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_LOCK) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
for(i = g_maxclients.integer; i < MAX_GENTITIES; i++) {
|
|
if(Q_stricmp(g_entities[i].classname, "func_door") == 0 && !(g_entities[i].flags & FL_LOCKED))
|
|
g_entities[i].flags ^= FL_LOCKED;
|
|
else if(Q_stricmp(g_entities[i].classname, "func_door_rotating") == 0 && !(g_entities[i].flags & FL_LOCKED))
|
|
g_entities[i].flags ^= FL_LOCKED;
|
|
}
|
|
G_PrintfClient(ent, "All doors locked.\n");
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_changeFreq
|
|
GSIO01 | 12/05/2009
|
|
=================
|
|
*/
|
|
static void Cmd_changeFreq(gentity_t *ent) {
|
|
float i;
|
|
char arg[16];
|
|
if(!ent || !ent->client)
|
|
return;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_FFSTUFF) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if(trap_Argc() < 2) {
|
|
G_PrintfClient(ent, "Usage: changeFreq value, -1 = level 10 forcefield, 0 = random or any value between 0 and 20\n");
|
|
return;
|
|
}
|
|
trap_Argv(1, arg, sizeof(arg));
|
|
i = atof(arg);
|
|
switch(atoi(arg)) {
|
|
case -1:
|
|
i = -1;
|
|
break;
|
|
case 0:
|
|
i = flrandom(0.1, 20);
|
|
break;
|
|
default:
|
|
if(i < 0 || i > 20) {
|
|
i = flrandom(0.1, 20);
|
|
}
|
|
break;
|
|
}
|
|
trap_Cvar_Set("rpg_forceFieldFreq", va("%f", i));
|
|
G_Printf("%f\n", rpg_forceFieldFreq.value);
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_alert_f
|
|
GSIO01 | 12/05/2009
|
|
=================
|
|
*/
|
|
static void Cmd_alert_f(gentity_t *ent) {
|
|
gentity_t *alertEnt, *te;
|
|
char arg[10], arg2[16];
|
|
int i = 0;
|
|
if(!ent || !ent->client)
|
|
return;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_ALERT) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
alertEnt = G_Find(NULL, FOFS(classname), "target_alert");
|
|
if(!alertEnt) {
|
|
G_PrintfClient(ent, "This map doesn't seem to support the alert command.\n");
|
|
return;
|
|
}
|
|
if(trap_Argc() < 2) {
|
|
G_PrintfClient(ent, "Usage: alert condition, where condition can be yellow, red, green, or blue.\nUsage: alert condition sound, where for condition see above and sound can be 0 = don't toggle and 1 = toggle.\nUsage: alert toggle, toggles the sound.\n");
|
|
return;
|
|
}
|
|
te = G_Spawn();
|
|
trap_Argv(1, arg, sizeof(arg));
|
|
if(trap_Argc() > 2) {
|
|
trap_Argv(2, arg2, sizeof(arg2));
|
|
i = atoi(arg2);
|
|
}
|
|
if(!Q_stricmp(arg, "red"))
|
|
te->target = alertEnt->falsename;
|
|
else if(!Q_stricmp(arg, "yellow"))
|
|
te->target = alertEnt->truename;
|
|
else if(!Q_stricmp(arg, "blue"))
|
|
te->target = alertEnt->bluename;
|
|
else if(!Q_stricmp(arg, "green"))
|
|
te->target = alertEnt->swapname;
|
|
else if(!Q_stricmp(arg, "toggle")) {
|
|
switch(alertEnt->damage) {
|
|
case 0: // green
|
|
te->target = alertEnt->swapname;
|
|
break;
|
|
case 1: // yellow
|
|
te->target = alertEnt->truename;
|
|
break;
|
|
case 2: // red
|
|
te->target = alertEnt->falsename;
|
|
break;
|
|
case 3: // blue
|
|
te->target = alertEnt->bluename;
|
|
break;
|
|
}
|
|
if(i == 1)
|
|
i = 0;
|
|
}
|
|
else {
|
|
G_PrintfClient(ent, "Invalid alert condition \'%s\'. Valid conditions: red, blue, yellow, green.\n", arg);
|
|
return;
|
|
}
|
|
if(i == 1) {
|
|
te->classname = "dummy";
|
|
alertEnt->use(alertEnt, NULL, te);
|
|
te->classname = NULL;
|
|
}
|
|
alertEnt->use(alertEnt, NULL, te);
|
|
if(!te)
|
|
G_Printf("te got removed\n");
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_zonelist_f
|
|
Harry Young | 02/11/2012
|
|
=================
|
|
*/
|
|
static void Cmd_zonelist_f(gentity_t *ent) {
|
|
gentity_t *zone=NULL;
|
|
char arg[16];
|
|
int type;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_SMS ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
trap_Argv(1, arg, sizeof(arg));
|
|
|
|
type = atoi(arg);
|
|
|
|
if(type == 0 || type > 2){
|
|
trap_SendServerCommand( ent-g_entities, va("print \"Usage: zonelist <type> where type is one of the following types of zones:\n--1 = safezones for Selfdestruct\n--2 = MSD-HUD zones\n\" ") );
|
|
return;
|
|
}
|
|
|
|
if(type == 1)
|
|
trap_SendServerCommand( ent-g_entities, va("print \"\nList of safezones on this map: \n\n\""));
|
|
if(type == 2)
|
|
trap_SendServerCommand( ent-g_entities, va("print \"\nList of MSD-HUD-zones on this map: \n\n\""));
|
|
|
|
while((zone = G_Find(zone, FOFS(classname), "target_zone")) != NULL){
|
|
if(zone->count == type){
|
|
trap_SendServerCommand( ent-g_entities, va("print \"Name of zone: %s \n\"", zone->targetname ));
|
|
if(zone->n00bCount == 1)
|
|
trap_SendServerCommand( ent-g_entities, va("print \"Status of safezone: ^2safe \n\""));
|
|
else
|
|
trap_SendServerCommand( ent-g_entities, va("print \"Status of safezone: ^1unsafe \n\""));
|
|
if(zone->spawnflags & 2)
|
|
trap_SendServerCommand( ent-g_entities, va("print \"Flagges as ship: yes \n\n\""));
|
|
else
|
|
trap_SendServerCommand( ent-g_entities, va("print \"Flagged as ship: no \n\n\""));
|
|
}
|
|
}
|
|
trap_SendServerCommand( ent-g_entities, va("print \"End of list \n\n\""));
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_selfdestruct_f
|
|
Harry Young | 25/07/2012
|
|
=================
|
|
*/
|
|
static void Cmd_selfdestruct_f(gentity_t *ent) {
|
|
gentity_t *destructEnt, *safezone=NULL;
|
|
char arg[16], arg2[16], arg6[16], arg7[16], arg8[16];
|
|
double ETAmin, ETAsec;
|
|
if(!ent || !ent->client)
|
|
return;
|
|
|
|
//Trapping all potential args here.
|
|
trap_Argv(1, arg, sizeof(arg));
|
|
trap_Argv(2, arg2, sizeof(arg2));
|
|
trap_Argv(3, arg6, sizeof(arg6));
|
|
trap_Argv(4, arg7, sizeof(arg7));
|
|
trap_Argv(5, arg8, sizeof(arg8));
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_SMS ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
|
|
// Setup command-Execution
|
|
|
|
if (!Q_stricmp(arg, "start")) {
|
|
//Is there sth running alrerady?
|
|
destructEnt = G_Find(NULL, FOFS(classname), "target_selfdestruct");
|
|
if(destructEnt) {
|
|
G_PrintfClient(ent, "^1ERROR: There's already a self destruct in progress, aborting setup.");
|
|
return;
|
|
}
|
|
|
|
//There is not so let's set this up.
|
|
destructEnt = G_Spawn();
|
|
destructEnt->classname = "target_selfdestruct";
|
|
destructEnt->wait = atoi(arg2);
|
|
destructEnt->spawnflags = atoi(arg6);
|
|
destructEnt->bluename = G_NewString(arg7);
|
|
destructEnt->target = G_NewString(arg8);
|
|
|
|
//we need to check a few things here to make sure the entity works properly. Else we free it.
|
|
if ( destructEnt->wait <= 0 )
|
|
G_PrintfClient(ent, "^1ERROR: duration must not be 0. Removing entity.");
|
|
|
|
while((safezone = G_Find(safezone, FOFS(classname), "target_zone")) != NULL){
|
|
if(!destructEnt->bluename && safezone->count == 1 && safezone->spawnflags & 2){
|
|
G_PrintfClient(ent, "^1ERROR: safezone must be given for maps consisting of multiple ships/stations (like rpg_runabout). For a list of safezones use this command: zonelist 1 . Removing entity.");
|
|
destructEnt->wait = 0; //we'll use this next to free the ent
|
|
break;
|
|
}
|
|
}
|
|
if(destructEnt->wait <= 0)
|
|
G_FreeEntity(destructEnt);
|
|
else
|
|
G_CallSpawn(destructEnt);
|
|
return;
|
|
|
|
} else if (!Q_stricmp(arg, "remaining")) {
|
|
//Is there sth running alrerady?
|
|
destructEnt = G_Find(NULL, FOFS(classname), "target_selfdestruct");
|
|
if(!destructEnt) {
|
|
G_PrintfClient(ent, "^1ERROR: There's no self destruct in progress, aborting call.");
|
|
return;
|
|
}
|
|
|
|
if(destructEnt->spawnflags == 1)
|
|
return; //we simply don't need this while there is a visible countdown.
|
|
|
|
//we need the remaining time in minutes and seconds from that entity. Just ask them off and have the command do the math.
|
|
ETAsec = floor(modf((( floor(destructEnt->damage / 1000) - floor(level.time / 1000) ) / 60), &ETAmin)*60); //break it apart, put off the minutes and return the floored secs
|
|
if(ETAsec / 10 < 1) //get leading 0 for secs
|
|
trap_SendServerCommand( -1, va("servermsg \"^1Self Destruct in %.0f:0%.0f\"", ETAmin, ETAsec ));
|
|
else
|
|
trap_SendServerCommand( -1, va("servermsg \"^1Self Destruct in %.0f:%.0f\"", ETAmin, ETAsec ));
|
|
} else if (!Q_stricmp(arg, "abort")) {
|
|
//Is there sth running alrerady?
|
|
destructEnt = G_Find(NULL, FOFS(classname), "target_selfdestruct");
|
|
if(!destructEnt) {
|
|
G_PrintfClient(ent, "^1ERROR: There's no self destruct in progress, aborting call.");
|
|
return;
|
|
}
|
|
destructEnt->use(destructEnt, NULL, NULL); // Use-Function will simply manage the abort
|
|
} else {
|
|
//maybe hook up a setup UI here later.
|
|
G_PrintfClient(ent, "^1ERROR: Invalid or no command-Argument. Arguments are start, remaining and abort");
|
|
G_PrintfClient(ent, "^3Usage: selfdestruct start duration audio [safezone] [target]");
|
|
G_PrintfClient(ent, "duration: total countdown-duration in seconds. Must not be 0.");
|
|
G_PrintfClient(ent, "audio: set this 0 if you do not want to display the countdown-clock in the top center of your screen, else set this 1.");
|
|
G_PrintfClient(ent, "safezone: Only for maps with multiple ships (like rpg_runabout). it will not be used for processing. Set NULL to skip.");
|
|
G_PrintfClient(ent, "target: Optional Argument for Effects to fire once the countdown hist 0.");
|
|
G_PrintfClient(ent, "The entity will automatically shake everyones screen and kill all clients outside an active target_zone configured as safezone.");
|
|
G_PrintfClient(ent, "\n^3Usage: selfdestruct remaining");
|
|
G_PrintfClient(ent, "This will give out the remaining countdown-time to all clients if the count is muted.");
|
|
G_PrintfClient(ent, "\n^3Usage: selfdestruct abort");
|
|
G_PrintfClient(ent, "This will abort any self destruct running");
|
|
return;
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_shipdamage_f
|
|
Harry Young | 02/08/2012
|
|
=================
|
|
*/
|
|
static void Cmd_shipdamage_f(gentity_t *ent) {
|
|
gentity_t *healthEnt=NULL;
|
|
char arg[16];
|
|
char target[512];
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_SMS ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if(trap_Argc() == 0){
|
|
G_PrintfClient(ent, "Usage: shipdamage damage [target] where damage is the total amount dealt and target is the target_shiphealth to recieve it. It is case-dependent and required on maps with 2 or more of such (like rpg_runabout).\n");
|
|
G_PrintfClient(ent, "It will be rendered to shields and hull respectively by the entity. Must be positive. You can not heal with this command.\n");
|
|
return;
|
|
}
|
|
|
|
if(trap_Argc() > 1){
|
|
Q_strncpyz( target, ConcatArgs( 2 ), sizeof( target ) );
|
|
|
|
while((healthEnt = G_Find(healthEnt, FOFS(classname), "target_shiphealth")) != NULL){
|
|
if(!Q_stricmp(healthEnt->targetname, target))//find the right entity if we have a target
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!healthEnt){//specific search did not turn up any results so fall back to the first entity
|
|
trap_SendServerCommand( ent-g_entities, va("print \"^3 Warning: no healthEnt with targetname '%s' found, falling back to first entity found.\n\"", target ) );
|
|
healthEnt = G_Find(NULL, FOFS(classname), "target_shiphealth");
|
|
if(G_Find(healthEnt, FOFS(classname), "target_shiphealth")){//abort if we do have more than one healthEnt
|
|
trap_SendServerCommand( ent-g_entities, va("print \"^1 ERROR: This map has more than one target_shiphealth, therefore a target needs to be specified. Aborting call.\n\"" ) );
|
|
return;
|
|
}
|
|
}
|
|
|
|
if(!healthEnt){
|
|
trap_SendServerCommand( ent-g_entities, "print \"^4This map does not support the shiphealth system.\n\"" );
|
|
return;
|
|
}
|
|
|
|
trap_Argv(1, arg, sizeof(arg));
|
|
|
|
if(atoi(arg) > 0){
|
|
if(healthEnt->count > 0){
|
|
healthEnt->damage = atoi(arg);
|
|
}else{
|
|
G_PrintfClient(ent, "^1ERROR: The ship is destroyed.");
|
|
return;
|
|
}
|
|
} else {
|
|
G_PrintfClient(ent, "^1ERROR: Damage must be a positive value. You can not heal with this command.");
|
|
return;
|
|
}
|
|
healthEnt->use(healthEnt, NULL, NULL);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_shiphealth_f
|
|
Harry Young | 02/08/2012
|
|
=================
|
|
*/
|
|
static void Cmd_shiphealth_f(gentity_t *ent) {
|
|
gentity_t *healthEnt=NULL;
|
|
int THS, CHS, HCI, TSS, CSS, SCI, SI;
|
|
float RHS, RSS;
|
|
|
|
if(!G_Find(NULL, FOFS(classname), "target_shiphealth")){
|
|
trap_SendServerCommand( ent-g_entities, "print \"^3This map does not support the shiphealth system.\n\"" );
|
|
return;
|
|
}
|
|
|
|
while((healthEnt = G_Find(healthEnt, FOFS(classname), "target_shiphealth")) != NULL){ //do this for every healthEnt you find
|
|
|
|
THS = healthEnt->health;
|
|
CHS = healthEnt->count;
|
|
TSS = healthEnt->splashRadius;
|
|
CSS = healthEnt->n00bCount;
|
|
SI = healthEnt->splashDamage;
|
|
|
|
//Restructured the next 2 segments to fix a compiler-warning
|
|
RHS = ((CHS * pow(THS, -1)) * 100);
|
|
if(RHS <= 25)//Hull Color Indicators
|
|
HCI = 1;
|
|
else if(RHS <= 50)
|
|
HCI = 3;
|
|
else if(RHS <= 100)
|
|
HCI = 2;
|
|
else
|
|
HCI = 7;
|
|
|
|
RSS = ((CSS * pow(TSS, -1)) * 100);
|
|
if(RSS <= 25)//Shield Color Indicators
|
|
SCI = 1;
|
|
else if(RSS <= 50)
|
|
SCI = 3;
|
|
else if(RSS <= 100)
|
|
SCI = 2;
|
|
else
|
|
SCI = 7;
|
|
|
|
if(CHS == 0){
|
|
trap_SendServerCommand( ent-g_entities, va("print \"\n^1 %s is destroyed.\n\n\"", healthEnt->targetname ) );
|
|
} else {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"\n^3 %s : Tactical Master Systems Display\n\"", healthEnt->targetname ) );
|
|
switch(SI){
|
|
case -2:
|
|
trap_SendServerCommand( ent-g_entities, "print \"^1 Shields are offline\n\"" );
|
|
break;
|
|
case -1:
|
|
trap_SendServerCommand( ent-g_entities, "print \"^1 Shields are inoperable\n\"" );
|
|
break;
|
|
case 0:
|
|
trap_SendServerCommand( ent-g_entities, "print \"^3 Shields are standing by\n\"" );
|
|
break;
|
|
case 1:
|
|
trap_SendServerCommand( ent-g_entities, "print \"^2 Shields are online\n\"" );
|
|
break;
|
|
}
|
|
if(CSS>0)
|
|
trap_SendServerCommand( ent-g_entities, va("print \"^%i Shield Capactiy at %.0f Percent (%i of %i Points)\n\"", SCI, RSS, CSS, TSS) );
|
|
trap_SendServerCommand( ent-g_entities, va("print \"^%i Structual Integrity at %.0f Percent (%i of %i Points)\n\n\"", HCI, RHS, CHS, THS) );
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_reloadtorpedos_f
|
|
Harry Young | 12/01/2013
|
|
=================
|
|
*/
|
|
static void Cmd_reloadtorpedos_f(gentity_t *ent) {
|
|
gentity_t *torpedo=NULL;
|
|
char arg[16];
|
|
char target[512];
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_SMS ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
trap_Argv(1, arg, sizeof(arg));
|
|
trap_Argv(2, target, sizeof(target));
|
|
|
|
if(atoi(arg) == 0 || !Q_stricmp(target, "")){
|
|
G_PrintfClient(ent, "Usage: reloadtorpedos [amount] [target] where amount is the number of torpedos the launcher will have after the command executed.");
|
|
G_PrintfClient(ent, "Set -2 to depleet, set -1 to max out. You can not load more torpedos than the entity was designed for. If you do it will just Max out.");
|
|
G_PrintfClient(ent, "target is the specific targetname of the fx_torpedo that shall be reloaded.");
|
|
G_PrintfClient(ent, "If set to all every limited launcher on the map will be set to amount or maxed out accordingly.");
|
|
G_PrintfClient(ent, "The targetnames can be extracted trough the command torpedolist.");
|
|
return;
|
|
}
|
|
|
|
if(atoi(arg) < -2){
|
|
G_PrintfClient(ent, "^1ERROR: amount must not be less than -2, aborting call.\n");
|
|
return;
|
|
}
|
|
|
|
if(!G_Find(NULL, FOFS(classname), "fx_torpedo")){
|
|
trap_SendServerCommand( ent-g_entities, "print \"^4This map does not support the fx_torpedo system.\n\"" );
|
|
return;
|
|
}
|
|
|
|
while((torpedo = G_Find(torpedo, FOFS(classname), "fx_torpedo")) != NULL){
|
|
if(!Q_stricmp(torpedo->targetname, target) || !Q_stricmp(target, "all")){ //this entity is generally affectable
|
|
if(torpedo->damage > 0){ //we only need to consider this for restock if it is restockable
|
|
if(atoi(arg) == -1 || atoi(arg) > torpedo->damage)
|
|
torpedo->count = torpedo->damage;
|
|
else if(atoi(arg) == -2)
|
|
torpedo->count = 0;
|
|
else
|
|
torpedo->count = atoi(arg);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_torpedolist_f
|
|
Harry Young | 02/11/2012
|
|
=================
|
|
*/
|
|
static void Cmd_torpedolist_f(gentity_t *ent) {
|
|
gentity_t *torpedo=NULL;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_SMS ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
trap_SendServerCommand( ent-g_entities, va("print \"\nList of fx_torpedo-entities on this map: \n\n\""));
|
|
while((torpedo = G_Find(torpedo, FOFS(classname), "fx_torpedo")) != NULL){
|
|
trap_SendServerCommand( ent-g_entities, va("print \"Name of fx_torpedo: %s \n\"", torpedo->targetname ));
|
|
if(torpedo->spawnflags & 1)
|
|
trap_SendServerCommand( ent-g_entities, va("print \"Type: Quantum \n\""));
|
|
else
|
|
trap_SendServerCommand( ent-g_entities, va("print \"Type: Photon \n\""));
|
|
if(torpedo->count == -1)
|
|
trap_SendServerCommand( ent-g_entities, va("print \"Amount: Unlimited\n\n\""));
|
|
else{
|
|
trap_SendServerCommand( ent-g_entities, va("print \"Current Amount: %i \n\"", torpedo->count));
|
|
trap_SendServerCommand( ent-g_entities, va("print \"Maximum Amount: %i \n\n\"", torpedo->damage));
|
|
}
|
|
}
|
|
trap_SendServerCommand( ent-g_entities, va("print \"End of list \n\n\""));
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_admin_centerprint_f
|
|
GSIO01 | 12/05/2009
|
|
=================
|
|
*/
|
|
static void Cmd_admin_centerprint_f(gentity_t *ent) {
|
|
char *arg;
|
|
|
|
if ( trap_Argc () < 1 ) {
|
|
return;
|
|
}
|
|
|
|
//If client isn't in admin class, exit and disallow command.
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_MESSAGE) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if ( !ent || !ent->client ) {
|
|
return; // not fully in game yet
|
|
}
|
|
|
|
arg = ConcatArgs( 1 );
|
|
|
|
if ( !arg[0] ) { //if user added no args (ie wanted the parameters)
|
|
trap_SendServerCommand( ent-g_entities, va("print \"\nUsage: Admin broadcasts a message to all users on the server that stays for several seconds\nCommand: Msg2 \"<Message>\"\n\" ") );
|
|
return;
|
|
}
|
|
|
|
if ( arg[0] == '\0' )
|
|
{
|
|
return;
|
|
}
|
|
|
|
//RPG-X: Marcin: changed to -1
|
|
trap_SendServerCommand( -1, va("print \"%s\n\" ", arg));
|
|
|
|
trap_SendServerCommand( -1, va("servercprint \"%s\"", arg));
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_getBrushEntCount_f
|
|
=================
|
|
*/
|
|
static void Cmd_getBrushEntCount_f(gentity_t *ent) {
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_DEBUG ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
G_PrintfClient(ent, "Brush Entity Count: %i\n", level.numBrushEnts);
|
|
if(level.numBrushEnts > (MAX_MODELS - 1))
|
|
G_PrintfClient(ent, S_COLOR_YELLOW "Nelson sees this number and says: Ha Ha!\n");
|
|
}
|
|
|
|
|
|
// Dev commands:
|
|
|
|
// not in release
|
|
static void Cmd_listSPs(gentity_t *ent) {
|
|
int i;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_DEBUG ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
G_Printf("Spawnpoint list: \n");
|
|
for(i = 0; i < MAX_GENTITIES; i++) {
|
|
if(!Q_stricmp(g_entities[i].classname, "info_player_start"))
|
|
G_Printf("Spawnpoint type: info_player_start Origin: %s\n", vtos(ent->s.origin));
|
|
if(!Q_stricmp(g_entities[i].classname, "info_player_deathmatch"))
|
|
G_Printf("Spawnpoint type: info_player_deathmatch Origin: %s\n", vtos(ent->s.origin));
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_getEntInfo_f
|
|
=================
|
|
*/
|
|
static void Cmd_getEntInfo_f(gentity_t *ent) {
|
|
int i;
|
|
char arg[10];
|
|
playerState_t *ps;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_DEBUG ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
trap_Argv(1, arg, sizeof(arg));
|
|
|
|
if ( !arg[0] ) {
|
|
vec3_t start, forward, end;
|
|
trace_t tr;
|
|
ps = &ent->client->ps;
|
|
VectorCopy( ent->r.currentOrigin, start );
|
|
start[2] += ps->viewheight;
|
|
AngleVectors( ps->viewangles, forward, NULL, NULL );
|
|
VectorMA( start, 8192, forward, end );
|
|
trap_Trace( &tr, start, NULL, NULL, end, ps->clientNum, MASK_SHOT );
|
|
i = tr.entityNum;
|
|
}
|
|
else {
|
|
i = atoi( arg );
|
|
}
|
|
|
|
if(i > MAX_GENTITIES - 1)
|
|
return;
|
|
|
|
G_PrintfClient(ent, "Classname: %s\n Targetname: %s\n Target: %s\n Spawnflags: %i\n Bmodel: %s\n\"", g_entities[i].classname, g_entities[i].targetname, g_entities[i].target, g_entities[i].spawnflags, g_entities[i].model);
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_getOrigin_f
|
|
=================
|
|
*/
|
|
static void Cmd_getOrigin_f(gentity_t *ent) {
|
|
int i;
|
|
char arg[10];
|
|
playerState_t *ps;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_DEBUG ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
trap_Argv(1, arg, sizeof(arg));
|
|
|
|
if ( !arg[0] ) {
|
|
vec3_t start, forward, end;
|
|
trace_t tr;
|
|
ps = &ent->client->ps;
|
|
VectorCopy( ent->r.currentOrigin, start );
|
|
start[2] += ps->viewheight;
|
|
AngleVectors( ps->viewangles, forward, NULL, NULL );
|
|
VectorMA( start, 8192, forward, end );
|
|
trap_Trace( &tr, start, NULL, NULL, end, ps->clientNum, MASK_SHOT );
|
|
i = tr.entityNum;
|
|
}
|
|
else {
|
|
i = atoi( arg );
|
|
}
|
|
|
|
if( i > MAX_GENTITIES - 1)
|
|
return;
|
|
|
|
G_PrintfClient(ent, "ent->s.origin = %s", vtos(g_entities[i].s.origin));
|
|
G_PrintfClient(ent, "ent->r.currentOrigin = %s", vtos(g_entities[i].r.currentOrigin));
|
|
G_PrintfClient(ent, "ent->pos1 = %s", vtos(g_entities[i].pos1));
|
|
G_PrintfClient(ent, "ent->pos2 = %s", vtos(g_entities[i].pos2));
|
|
G_PrintfClient(ent, "ent->s.pos.trBase = %s", vtos(g_entities[i].s.pos.trBase));
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_getEntByTargetname_f
|
|
=================
|
|
*/
|
|
static void Cmd_getEntByTargetname_f(gentity_t *ent) {
|
|
int i;
|
|
char arg[MAX_STRING_TOKENS];
|
|
gentity_t *t;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_DEBUG ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
trap_Argv(1, arg, sizeof(arg));
|
|
|
|
for(i = 0; i < MAX_GENTITIES; i++) {
|
|
if(!&g_entities[i]) continue;
|
|
t = &g_entities[i];
|
|
if(t->targetname && !Q_stricmpn(t->targetname, arg, strlen(arg)))
|
|
G_PrintfClient(ent, "ENT %i: %s", i, t->classname);
|
|
if(t->targetname2 && !Q_stricmpn(t->targetname2, arg, strlen(arg)))
|
|
G_PrintfClient(ent, "ENT %i: %s (targetname2)", i, t->classname);
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_getEntByTarget_f
|
|
=================
|
|
*/
|
|
static void Cmd_getEntByTarget_f(gentity_t *ent) {
|
|
char arg[MAX_STRING_TOKENS];
|
|
struct list entities;
|
|
list_iter_p iter;
|
|
container_p c;
|
|
gentity_t* t;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_DEBUG ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
trap_Argv(1, arg, sizeof(arg));
|
|
|
|
list_init(&entities, free);
|
|
G_GetEntityByTarget(arg, &entities);
|
|
|
|
iter = entities.iterator(&entities, LIST_FRONT);
|
|
for(c = entities.next(iter); c != NULL; c = entities.next(iter)) {
|
|
t = c->data;
|
|
|
|
if(t == NULL) {
|
|
continue;
|
|
}
|
|
|
|
if(!t->classname) {
|
|
continue;
|
|
}
|
|
|
|
G_PrintfClient(ent, "ENT %i: %s\n\"", t->s.number, t->classname);
|
|
}
|
|
destroy_iterator(iter);
|
|
entities.clear(&entities);
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_getEntByBmodel_f
|
|
=================
|
|
*/
|
|
static void Cmd_getEntByBmodel_f(gentity_t *ent) {
|
|
char arg[MAX_STRING_TOKENS];
|
|
gentity_t *entity;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_DEBUG ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
trap_Argv(1, arg, sizeof(arg));
|
|
|
|
entity = G_Find(NULL, FOFS(model), arg);
|
|
|
|
if(!entity) return;
|
|
|
|
G_PrintfClient(ent, "ENT %i: %s\n\"", entity->s.number, entity->classname);
|
|
}
|
|
|
|
// not in release
|
|
static void Cmd_setOrigin(gentity_t *ent) {
|
|
int i;
|
|
vec3_t origin;
|
|
gentity_t *ent2;
|
|
char arg[10];
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_DEBUG ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
trap_Argv(1, arg, sizeof(arg));
|
|
i = atoi(arg);
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
origin[0] = atof(arg);
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
origin[1] = atof(arg);
|
|
trap_Argv(4, arg, sizeof(arg));
|
|
origin[2] = atof(arg);
|
|
|
|
if(i > MAX_GENTITIES - 1)
|
|
return;
|
|
|
|
ent2 = &g_entities[i];
|
|
|
|
if(!ent2)
|
|
return;
|
|
|
|
VectorCopy(origin, ent2->s.origin);
|
|
VectorCopy(origin, ent2->r.currentOrigin);
|
|
trap_LinkEntity(ent);
|
|
G_SetOrigin(ent2, origin);
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_flushTentities_f
|
|
=================
|
|
*/
|
|
static void Cmd_flushTentities_f(gentity_t *ent) {
|
|
int i;
|
|
int cnt = 0;
|
|
char arg[MAX_QPATH];
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_TESS) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if(!trap_Argc()) {
|
|
|
|
|
|
} else {
|
|
trap_Argv(1, arg, sizeof(arg));
|
|
if(!Q_stricmpn(arg, "all", 3)) {
|
|
for(i = 0; i < MAX_GENTITIES; i++) {
|
|
if(!Q_stricmpn(g_entities[i].classname, "tmp_", 4)) {
|
|
G_FreeEntity(&g_entities[i]);
|
|
cnt++;
|
|
}
|
|
}
|
|
|
|
G_PrintfClient(ent, "Freed %i temporal entities.\n", cnt);
|
|
} else {
|
|
i = atoi(arg);
|
|
if(i < 0 || i > MAX_GENTITIES - 1) {
|
|
G_PrintfClient(ent, "Invalid entity num %i.\n\"", i);
|
|
return;
|
|
}
|
|
if(!Q_stricmpn(g_entities[i].classname, "tmp_", 4)) {
|
|
G_FreeEntity(&g_entities[i]);
|
|
} else {
|
|
G_PrintfClient(ent, "Entity %i is not a temporal entity or does not exist!\n\"", i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_spawnTEntity_f
|
|
=================
|
|
*/
|
|
static void Cmd_spawnTentity_f(gentity_t *ent) {
|
|
char arg[MAX_STRING_TOKENS], *arg2;
|
|
vec3_t origin, start, end, forward, angles;
|
|
float sizeX, sizeY, sizeZ;
|
|
int numArgs;
|
|
int clientNum;
|
|
gentity_t *newEnt;
|
|
trace_t tr;
|
|
char tmp[MAX_STRING_TOKENS];
|
|
|
|
//return; // we don't want this to be avaible in the current release as it's not finised
|
|
|
|
memset(arg, 0, sizeof(arg));
|
|
memset(tmp, 0, sizeof(tmp));
|
|
|
|
numArgs = trap_Argc();
|
|
clientNum = ent->client->ps.clientNum;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_TESS) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if(!numArgs) {
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for spawnTEnt!\n\"");
|
|
return;
|
|
}
|
|
|
|
//get origin and angles
|
|
//calc start
|
|
VectorCopy( ent->r.currentOrigin, start );
|
|
start[2] += ent->client->ps.viewheight;
|
|
|
|
//calc end
|
|
AngleVectors( ent->client->ps.viewangles, forward, NULL, NULL );
|
|
VectorMA( start, 8192, forward, end );
|
|
|
|
//trace-er-roo
|
|
trap_Trace( &tr, start, NULL, NULL, end, clientNum, MASK_SHOT );
|
|
|
|
VectorCopy( tr.endpos, origin );
|
|
VectorCopy( tr.plane.normal, angles);
|
|
|
|
newEnt = G_Spawn();
|
|
|
|
if(!newEnt) {
|
|
trap_SendServerCommand(clientNum, "print \"Could not spawn new entity. Most likely there are no free entities left.\n\"");
|
|
return;
|
|
}
|
|
|
|
newEnt->tmpEntity = qtrue;
|
|
|
|
G_SetOrigin(newEnt, origin);
|
|
VectorCopy(angles, newEnt->s.angles);
|
|
VectorCopy(angles, newEnt->r.currentAngles);
|
|
|
|
trap_Argv(1, arg, sizeof(arg));
|
|
|
|
//check wether this is a valid entity
|
|
if(!Q_stricmpn(arg, "trigger_", 8)) {
|
|
if(!Q_stricmp(arg, "trigger_teleport")) {
|
|
newEnt->classname = G_NewString("trigger_teleport");
|
|
if(numArgs < 5) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for trigger_teleport!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage: spawnTEnt trigger_teleport sizeX sizeY sizeZ target (spawnflags swapname speed)\n\"");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
arg2 = arg;
|
|
sizeX = atof(arg2);
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
arg2 = arg;
|
|
sizeY = atof(arg2);
|
|
trap_Argv(4, arg, sizeof(arg));
|
|
arg2 = arg;
|
|
sizeZ = atof(arg2);
|
|
newEnt->r.mins[0] = newEnt->r.maxs[0] = sizeX;
|
|
newEnt->r.mins[1] = newEnt->r.maxs[1] = sizeY;
|
|
newEnt->r.mins[2] = newEnt->r.maxs[2] = sizeZ;
|
|
VectorScale(newEnt->r.mins, -.5, newEnt->r.mins);
|
|
VectorScale(newEnt->r.maxs, .5, newEnt->r.maxs);
|
|
VectorCopy(newEnt->r.maxs, newEnt->r.absmax);
|
|
VectorCopy(newEnt->r.mins, newEnt->r.absmin);
|
|
trap_Argv(5, arg, sizeof(arg));
|
|
newEnt->target = G_NewString(arg);
|
|
if(numArgs >= 6) {
|
|
trap_Argv(6, arg, sizeof(arg));
|
|
newEnt->spawnflags = atoi(arg);
|
|
}
|
|
if(numArgs >= 7) {
|
|
trap_Argv(7, arg, sizeof(arg));
|
|
newEnt->swapname = G_NewString(arg);
|
|
}
|
|
if(numArgs >= 8) {
|
|
trap_Argv(8, arg, sizeof(arg));
|
|
newEnt->health = atof(arg);
|
|
}
|
|
G_CallSpawn(newEnt);
|
|
}else if(!Q_stricmp(arg, "trigger_once")) { //actually trigger_multiple with wait of -1
|
|
newEnt->classname = G_NewString("trigger_multiple");
|
|
if(numArgs < 5) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of argmuments for trigger_once!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage: spawnTEnt trigger_once sizeX sizeY sizeZ target\n\"");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
arg2 = arg;
|
|
sizeX = atof(arg2);
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
arg2 = arg;
|
|
sizeY = atof(arg2);
|
|
trap_Argv(4, arg, sizeof(arg));
|
|
arg2 = arg;
|
|
sizeZ = atof(arg2);
|
|
newEnt->r.mins[0] = newEnt->r.maxs[0] = sizeX;
|
|
newEnt->r.mins[1] = newEnt->r.maxs[1] = sizeY;
|
|
newEnt->r.mins[2] = newEnt->r.maxs[2] = sizeZ;
|
|
VectorScale(newEnt->r.mins, -.5, newEnt->r.mins);
|
|
VectorScale(newEnt->r.maxs, .5, newEnt->r.maxs);
|
|
VectorCopy(newEnt->r.maxs, newEnt->r.absmax);
|
|
VectorCopy(newEnt->r.mins, newEnt->r.absmin);
|
|
trap_Argv(5, arg, sizeof(arg));
|
|
newEnt->target = G_NewString(arg);
|
|
G_CallSpawn(newEnt);
|
|
newEnt->wait = -1;
|
|
} else if(!Q_stricmp(arg, "trigger_multiple")) {
|
|
newEnt->classname = G_NewString("trigger_multiple");
|
|
if(numArgs < 6) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of argmuments for trigger_multple!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage: spawnTEnt trigger_multiple sizeX sizeY sizeZ target wait\n\"");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
arg2 = arg;
|
|
sizeX = atof(arg2);
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
arg2 = arg;
|
|
sizeY = atof(arg2);
|
|
trap_Argv(4, arg, sizeof(arg));
|
|
arg2 = arg;
|
|
sizeZ = atof(arg2);
|
|
newEnt->r.mins[0] = newEnt->r.maxs[0] = sizeX;
|
|
newEnt->r.mins[1] = newEnt->r.maxs[1] = sizeY;
|
|
newEnt->r.mins[2] = newEnt->r.maxs[2] = sizeZ;
|
|
VectorScale(newEnt->r.mins, -.5, newEnt->r.mins);
|
|
VectorScale(newEnt->r.maxs, .5, newEnt->r.maxs);
|
|
VectorCopy(newEnt->r.maxs, newEnt->r.absmax);
|
|
VectorCopy(newEnt->r.mins, newEnt->r.absmin);
|
|
trap_Argv(5, arg, sizeof(arg));
|
|
newEnt->target = G_NewString(arg);
|
|
G_CallSpawn(newEnt);
|
|
trap_Argv(6, arg, sizeof(arg));
|
|
newEnt->wait = atof(arg);
|
|
} else if(!Q_stricmp(arg, "trigger_hurt")) {
|
|
//newEnt = G_Spawn();
|
|
newEnt->classname = G_NewString("trigger_hurt");
|
|
if(numArgs < 4) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for trigger_hurt!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage: spawnTEnt trigger_hurt sizeX sizeY sizeZ dmg (targetname)");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
arg2 = arg;
|
|
sizeX = atof(arg2);
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
arg2 = arg;
|
|
sizeY = atof(arg2);
|
|
trap_Argv(4, arg, sizeof(arg));
|
|
arg2 = arg;
|
|
sizeZ = atof(arg2);
|
|
newEnt->r.mins[0] = newEnt->r.maxs[0] = sizeX;
|
|
newEnt->r.mins[1] = newEnt->r.maxs[1] = sizeY;
|
|
newEnt->r.mins[2] = newEnt->r.maxs[2] = sizeZ;
|
|
VectorScale(newEnt->r.mins, -.5, newEnt->r.mins);
|
|
VectorScale(newEnt->r.maxs, .5, newEnt->r.maxs);
|
|
VectorCopy(newEnt->r.maxs, newEnt->r.absmax);
|
|
VectorCopy(newEnt->r.mins, newEnt->r.absmin);
|
|
G_CallSpawn(newEnt);
|
|
trap_Argv(5, arg, sizeof(arg));
|
|
newEnt->damage = atoi(arg);
|
|
if(numArgs >= 5) {
|
|
trap_Argv(5, arg, sizeof(arg));
|
|
newEnt->targetname = G_NewString(arg);
|
|
}
|
|
}
|
|
} else if (!Q_stricmpn(arg, "fx_", 3)) {
|
|
if(!Q_stricmp(arg, "fx_spark")) {
|
|
//newEnt = G_Spawn();
|
|
newEnt->classname = G_NewString("fx_spark");
|
|
if(numArgs < 3) {
|
|
G_FreeEntity(ent);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for fx_spark!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage: spawnTEnt fx_spark wait target (targetname spawnflags)\n\"");
|
|
return;
|
|
}
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
newEnt->target = G_NewString(arg);
|
|
if(numArgs >= 4) {
|
|
trap_Argv(4, arg, sizeof(arg));
|
|
newEnt->targetname = G_NewString(arg);
|
|
}
|
|
if(numArgs >= 5) {
|
|
trap_Argv(5, arg, sizeof(arg));
|
|
newEnt->spawnflags = atoi(arg);
|
|
}
|
|
G_CallSpawn(newEnt);
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
newEnt->wait = atof(arg);
|
|
} else if(!Q_stricmp(arg, "fx_surface_explosion")) {
|
|
newEnt->classname = G_NewString("fx_surface_explosion");
|
|
if(numArgs < 2) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for fx_surface_explosion!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage: spawnTEnt fx_surface_explosion targetname (spawnflags target damage radius speed)\"\n");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
newEnt->targetname = G_NewString(arg);
|
|
if(numArgs >= 3) {
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
newEnt->spawnflags = atoi(arg);
|
|
}
|
|
if(numArgs >= 4) {
|
|
trap_Argv(4, arg, sizeof(arg));
|
|
newEnt->target = G_NewString(arg);
|
|
}
|
|
if(numArgs >= 5) {
|
|
trap_Argv(5, arg, sizeof(arg));
|
|
newEnt->damage = atoi(arg);
|
|
}
|
|
if(numArgs >= 6) {
|
|
trap_Argv(6, arg, sizeof(arg));
|
|
newEnt->distance = atof(arg);
|
|
}
|
|
if(numArgs >= 7) {
|
|
trap_Argv(7, arg, sizeof(arg));
|
|
newEnt->speed = atof(arg);
|
|
}
|
|
G_CallSpawn(newEnt);
|
|
} else if(!Q_stricmp(arg, "fx_blow_chunks")) {
|
|
newEnt->classname = G_NewString("fx_blow_chunks");
|
|
if(numArgs < 3) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for fx_blow_chunks!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage: spawnTEnt fx_blow_chunks targetname target (radius material)\n\"");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
newEnt->targetname = G_NewString(arg);
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
newEnt->target = G_NewString(arg);
|
|
if(numArgs>= 4) {
|
|
trap_Argv(4, arg, sizeof(arg));
|
|
newEnt->distance = atof(arg);
|
|
}
|
|
if(numArgs >= 5) {
|
|
trap_Argv(5, arg, sizeof(arg));
|
|
newEnt->s.powerups = atoi(arg);
|
|
}
|
|
G_CallSpawn(newEnt);
|
|
} else if(!Q_stricmp(arg, "fx_electrical_explosion")) {
|
|
newEnt->classname = G_NewString("fx_electrical_explosion");
|
|
if(numArgs < 2) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for fx_electrical_explosion!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage: spawnTEnt fx_electrical_explosion targetname (target radius damage)\n\"");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
newEnt->targetname = G_NewString(arg);
|
|
if(numArgs >= 3) {
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
newEnt->target = G_NewString(arg);
|
|
}
|
|
if(numArgs >= 4) {
|
|
trap_Argv(4, arg, sizeof(arg));
|
|
newEnt->distance = atof(arg);
|
|
}
|
|
if(numArgs >= 5) {
|
|
trap_Argv(5, arg, sizeof(arg));
|
|
newEnt->damage = atoi(arg);
|
|
}
|
|
G_CallSpawn(newEnt);
|
|
}
|
|
} else if(!Q_stricmpn(arg, "info_", 5)) {
|
|
if(!Q_stricmp(arg, "info_notnull")) {
|
|
newEnt->classname = G_NewString("info_notnull");
|
|
if(numArgs < 2) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for info_notnull!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage: spawnTEnt info_notnull targetname\"\n");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
newEnt->targetname = G_NewString(arg);
|
|
G_CallSpawn(newEnt);
|
|
} else if(!Q_stricmp(arg, "info_player_deathmatch") || !Q_stricmp(arg, "info_player_start")) {
|
|
newEnt->classname = G_NewString("info_player_deathmatch");
|
|
G_CallSpawn(newEnt);
|
|
}
|
|
} else if(!Q_stricmpn(arg, "target_", 7)) {
|
|
if(!Q_stricmp(arg, "target_boolean")) {
|
|
newEnt->classname = G_NewString("target_boolean");
|
|
if(numArgs < 5) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for target_boolean!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage: spawnTEnt target_boolean targetname truetarget \"");
|
|
trap_SendServerCommand(clientNum, "print \"falsetarget swapname (spawnflags truename falsename)\n\"");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
newEnt->targetname = G_NewString(arg);
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
newEnt->truetarget = G_NewString(arg);
|
|
trap_Argv(4, arg, sizeof(arg));
|
|
newEnt->falsetarget = G_NewString(arg);
|
|
trap_Argv(5, arg, sizeof(arg));
|
|
newEnt->swapname = G_NewString(arg);
|
|
if(numArgs >= 6) {
|
|
trap_Argv(6, arg, sizeof(arg));
|
|
newEnt->spawnflags = atoi(arg);
|
|
}
|
|
if(numArgs >= 7) {
|
|
trap_Argv(7, arg, sizeof(arg));
|
|
newEnt->truename = G_NewString(arg);
|
|
}
|
|
if(numArgs >= 8) {
|
|
trap_Argv(8, arg, sizeof(arg));
|
|
newEnt->falsename = G_NewString(arg);
|
|
}
|
|
G_CallSpawn(newEnt);
|
|
} else if(!Q_stricmp(arg, "target_counter")) {
|
|
newEnt->classname = G_NewString("target_counter");
|
|
if(numArgs < 4) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for target_count!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage: spawnTEnt target_counter targetname target count\n\"");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
newEnt->targetname = G_NewString(arg);
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
newEnt->target = G_NewString(arg);
|
|
trap_Argv(4, arg, sizeof(arg));
|
|
newEnt->count = atoi(arg);
|
|
G_CallSpawn(newEnt);
|
|
} else if(!Q_stricmp(arg, "target_deactivate")) {
|
|
newEnt->classname = G_NewString("target_deactivate");
|
|
if(numArgs < 3) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for target_deactivate!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage spawnTEnt target_deactivate targetname target\n\"");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
newEnt->targetname = G_NewString(arg);
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
newEnt->target = G_NewString(arg);
|
|
G_CallSpawn(newEnt);
|
|
} else if(!Q_stricmp(arg, "target_doorlock")) {
|
|
newEnt->classname = G_NewString("target_doorlock");
|
|
if(numArgs < 3) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for target_doorlock!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage spawnTEnt target_doorlock target targetname (spawnflags lockMsg unlockMsg)\n\"");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
newEnt->target = G_NewString(arg);
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
newEnt->targetname = G_NewString(arg);
|
|
if(numArgs >= 4) {
|
|
trap_Argv(4, arg, sizeof(arg));
|
|
newEnt->spawnflags = atoi(arg);
|
|
}
|
|
if(numArgs >= 5) {
|
|
trap_Argv(5, arg, sizeof(arg));
|
|
newEnt->swapname = G_NewString(arg);
|
|
}
|
|
if(numArgs >= 6) {
|
|
trap_Argv(5, arg, sizeof(arg));
|
|
newEnt->truename = G_NewString(arg);
|
|
}
|
|
G_CallSpawn(newEnt);
|
|
} else if(!Q_stricmp(arg, "target_relay")) {
|
|
newEnt->classname = G_NewString("target_relay");
|
|
if(numArgs < 3) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for target_relay!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage: spawnTEnt target_relay targetname target (spawnflags)\n\"");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
newEnt->targetname = G_NewString(arg);
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
newEnt->target = G_NewString(arg);
|
|
if(numArgs >= 4) {
|
|
trap_Argv(4, arg, sizeof(arg));
|
|
newEnt->spawnflags = atoi(arg);
|
|
}
|
|
G_CallSpawn(newEnt);
|
|
} else if(!Q_stricmp(arg, "target_delay")) {
|
|
newEnt->classname = G_NewString("target_delay");
|
|
if(numArgs < 3) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for target_delay!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage: spawnTEnt target_delay targetname target delay (spawnflags random)\n\"");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
newEnt->targetname = G_NewString(arg);
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
newEnt->target = G_NewString(arg);
|
|
if(numArgs >= 4) {
|
|
trap_Argv(5, arg, sizeof(arg));
|
|
newEnt->spawnflags = atoi(arg);
|
|
}
|
|
if(numArgs >= 5) {
|
|
trap_Argv(6, arg, sizeof(arg));
|
|
newEnt->random = atof(arg);
|
|
}
|
|
G_CallSpawn(newEnt);
|
|
trap_Argv(4, arg, sizeof(arg));
|
|
newEnt->wait = atoi(arg);
|
|
} else if(!Q_stricmp(arg, "target_evosuit")) {
|
|
newEnt->classname = G_NewString("target_evosuit");
|
|
if(numArgs < 2) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for target_evosuit!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage: spawnTEnt target_evosuit targetname\n\"");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
newEnt->targetname = G_NewString(arg);
|
|
G_CallSpawn(newEnt);
|
|
} else if(!Q_stricmp(arg, "target_give")) {
|
|
newEnt->classname = G_NewString("target_give");
|
|
if(numArgs < 3) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for target_give!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage: spawnTEnt target_give targetname items (example for items: WP_5 | WP_14)\n\"");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
newEnt->targetname = G_NewString(arg);
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
newEnt->target = G_NewString(arg);
|
|
G_CallSpawn(newEnt);
|
|
} else if(!Q_stricmp(arg, "target_gravity")) {
|
|
newEnt->classname = G_NewString("target_gravity");
|
|
if(numArgs < 3) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for target_gravity!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage: spawnTEnt target_gravity targetname gravity (spawnflags)\n\"");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
newEnt->targetname = G_NewString(arg);
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
newEnt->targetname2 = G_NewString(arg);
|
|
if(numArgs >= 4) {
|
|
trap_Argv(4, arg, sizeof(arg));
|
|
newEnt->spawnflags = atoi(arg);
|
|
}
|
|
G_CallSpawn(newEnt);
|
|
} else if(!Q_stricmp(arg, "target_kill")) {
|
|
newEnt->classname = G_NewString("target_kill");
|
|
if(numArgs < 2) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for target_kill!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage: spawnTEnt target_kill targetname\n\"");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
newEnt->targetname = G_NewString(arg);
|
|
G_CallSpawn(newEnt);
|
|
} else if(!Q_stricmp(arg, "target_print")) {
|
|
newEnt->classname = G_NewString("target_print");
|
|
if(numArgs < 3) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for target_print!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage: spawnTEnt target_print targetname message (spawnflags)\n\"");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
newEnt->targetname = G_NewString(arg);
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
newEnt->message = G_NewString(arg);
|
|
if(numArgs >= 4) {
|
|
trap_Argv(4, arg, sizeof(arg));
|
|
newEnt->spawnflags = atoi(arg);
|
|
}
|
|
G_CallSpawn(newEnt);
|
|
} else if(!Q_stricmp(arg, "target_repair")) {
|
|
newEnt->classname = G_NewString("target_repair");
|
|
if(numArgs < 3) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for target_repair!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage: spawnTEnt target_repair targetname target\n\"");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
newEnt->targetname = G_NewString(arg);
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
newEnt->target = G_NewString(arg);
|
|
G_CallSpawn(newEnt);
|
|
} else if(!Q_stricmp(arg, "target_shake")) {
|
|
newEnt->classname = G_NewString("target_shake");
|
|
if(numArgs < 4) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for target_shake!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage: spawnTEnt target_shake targetname intensity length\n\"");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
newEnt->targetname = G_NewString(arg);
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
newEnt->distance = atof(arg);
|
|
G_CallSpawn(newEnt);
|
|
trap_Argv(4, arg, sizeof(arg));
|
|
newEnt->wait = atof(arg);
|
|
} else if(!Q_stricmp(arg, "target_teleporter")) {
|
|
newEnt->classname = G_NewString("target_teleporter");
|
|
if(numArgs < 3) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for target_teleporter!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage: spawnTEnt target_teleporter targetname target (spawnflags swapname)\n\"");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
newEnt->targetname = G_NewString(arg);
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
newEnt->target = G_NewString(arg);
|
|
if(numArgs >= 4) {
|
|
trap_Argv(4, arg, sizeof(arg));
|
|
newEnt->spawnflags = atoi(arg);
|
|
}
|
|
if(numArgs >= 5) {
|
|
trap_Argv(5, arg, sizeof(arg));
|
|
newEnt->swapname = G_NewString(arg);
|
|
}
|
|
G_CallSpawn(newEnt);
|
|
} else if(!Q_stricmp(arg, "target_speaker")) {
|
|
newEnt->classname = G_NewString("target_speaker");
|
|
if(numArgs < 3) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, "print \"Insufficent number of arguments for target_speaker!\n\"");
|
|
trap_SendServerCommand(clientNum, "print \"Usage: spawnTEnt target_speaker targetname sound (spawnflags wait random)\n\"");
|
|
return;
|
|
}
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
newEnt->targetname = G_NewString(arg);
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
if(strlen(arg) > MAX_QPATH - 1) {
|
|
G_FreeEntity(newEnt);
|
|
trap_SendServerCommand(clientNum, va("print \"Length of sound exceeds MAX_QPATH (%i)!\n\"", MAX_QPATH));
|
|
return;
|
|
}
|
|
newEnt->count = G_SoundIndex(arg);
|
|
if(numArgs >= 4) {
|
|
trap_Argv(4, arg, sizeof(arg));
|
|
newEnt->spawnflags = atoi(arg);
|
|
}
|
|
if(numArgs >= 5) {
|
|
trap_Argv(5, arg, sizeof(arg));
|
|
newEnt->wait = atof(arg);
|
|
}
|
|
if(numArgs >= 6 ) {
|
|
trap_Argv(6, arg, sizeof(arg));
|
|
newEnt->random = atof(arg);
|
|
}
|
|
G_CallSpawn(newEnt);
|
|
}
|
|
}
|
|
if(newEnt) {
|
|
Com_sprintf(tmp, sizeof(tmp), "%s%s", "tmp_", newEnt->classname);
|
|
newEnt->classname = G_NewString(tmp);
|
|
if(!Q_stricmp(newEnt->classname, "tmp_trigger_multiple") && ent->wait == -1)
|
|
newEnt->classname = G_NewString("tmp_trigger_once");
|
|
trap_SendServerCommand(clientNum, va("print \"Spawned entity of type %s with entity number %i.\"", newEnt->classname, newEnt->s.number));
|
|
}
|
|
}
|
|
|
|
static void Cmd_UiHolodeck_f(gentity_t *ent) {
|
|
trap_SendServerCommand(ent-g_entities, "ui_holodeck 1");
|
|
}
|
|
|
|
extern void trigger_transporter_delay(gentity_t *ent);
|
|
extern void trigger_transporter_think(gentity_t *ent);
|
|
|
|
/*
|
|
=================
|
|
Cmd_UiTransporterLoc_f
|
|
=================
|
|
*/
|
|
static void Cmd_UiTransporterLoc_f(gentity_t *ent) {
|
|
int entNum, targetLoc, i, delay;
|
|
gentity_t *locTarget = NULL;
|
|
gentity_t *trTrigger;
|
|
char arg[MAX_QPATH];
|
|
|
|
if(trap_Argc() < 2) return;
|
|
|
|
trap_Argv(1, arg, sizeof(arg));
|
|
entNum = atoi(arg);
|
|
|
|
trTrigger = &g_entities[entNum];
|
|
|
|
if(!trTrigger) return;
|
|
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
targetLoc = atoi(arg);
|
|
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
delay = atoi(arg);
|
|
delay *= 1000;
|
|
|
|
for(i = 0; i < MAX_GENTITIES; i++) {
|
|
if(!Q_stricmp(g_entities[i].classname, "target_location")) {
|
|
if(g_entities[i].health == targetLoc && g_entities[i].health >= 1 && targetLoc >= 1) {
|
|
locTarget = &g_entities[i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(locTarget) {
|
|
if(locTarget->sound1to2) {
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
G_PrintfClient(ent, "Destination is a restricted location.\n");
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_BEAM) ) {
|
|
G_PrintfClient(ent, "Destination is a restricted location.\n");
|
|
return;
|
|
}
|
|
#endif
|
|
}
|
|
trTrigger->target_ent = locTarget;
|
|
trTrigger->count = 0;
|
|
if(trTrigger->flags & FL_LOCKED) { // not in use
|
|
if(delay) {
|
|
trTrigger->think = trigger_transporter_delay;
|
|
trTrigger->nextthink = level.time + delay;
|
|
} else {
|
|
trTrigger->flags ^= FL_LOCKED;
|
|
trTrigger->think = trigger_transporter_think;
|
|
trTrigger->nextthink = level.time + trTrigger->wait;
|
|
}
|
|
} else {
|
|
trap_SendServerCommand(trTrigger->target_ent-g_entities, "Transporter is already in a Transport Cycle.\n");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_UiTransporterExt_f
|
|
=================
|
|
*/
|
|
static void Cmd_UiTransporterExt_f(gentity_t *ent) {
|
|
int entNum, srvNum, delay;
|
|
gentity_t *trTrigger;
|
|
char arg[MAX_QPATH];
|
|
|
|
if(!rpg_serverchange.integer) {
|
|
trap_SendServerCommand(ent-g_entities, "print \"Serverchange is disabled.\n\"");
|
|
return;
|
|
}
|
|
|
|
if(trap_Argc() < 2) return;
|
|
|
|
trap_Argv(1, arg, sizeof(arg));
|
|
entNum = atoi(arg);
|
|
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
srvNum = atoi(arg);
|
|
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
delay = atoi(arg);
|
|
delay *= 1000;
|
|
|
|
trTrigger = &g_entities[entNum];
|
|
|
|
if(!trTrigger) return;
|
|
|
|
trTrigger->count = 1;
|
|
trTrigger->health = srvNum;
|
|
if(trTrigger->flags & FL_LOCKED) { // not in use
|
|
if(delay) {
|
|
trTrigger->think = trigger_transporter_delay;
|
|
trTrigger->nextthink = level.time + delay;
|
|
} else {
|
|
trTrigger->flags ^= FL_LOCKED;
|
|
trTrigger->think = trigger_transporter_think;
|
|
trTrigger->nextthink = level.time + trTrigger->wait;
|
|
}
|
|
} else {
|
|
trap_SendServerCommand(trTrigger->target_ent-g_entities, "Transporter is already in a Transport Cycle.\n");
|
|
return;
|
|
}
|
|
}
|
|
|
|
static void UI_DEBUG(gentity_t *ent) {
|
|
char arg[MAX_TOKEN_CHARS];
|
|
|
|
trap_Argv(1, arg, sizeof(arg));
|
|
G_Printf(S_COLOR_GREEN "%s\n", arg);
|
|
}
|
|
|
|
#ifdef SQL
|
|
/*
|
|
=================
|
|
Cmd_SqlLogin_f
|
|
=================
|
|
*/
|
|
static void Cmd_SqlLogin_f(gentity_t *ent) {
|
|
char uName[MAX_TOKEN_CHARS];
|
|
char pwd[MAX_TOKEN_CHARS];
|
|
qboolean res;
|
|
int clientNum;
|
|
gclient_t *client;
|
|
|
|
if(!sql_use.integer || !ent || !ent->client) return;
|
|
|
|
//logout if no argument and player is loged in
|
|
if(!uName[0] && !pwd[0] && ent->client->uid) {
|
|
ent->client->uid = 0;
|
|
trap_SendServerCommand( ent-g_entities, va("print \"You are now logged out.\n\"") );
|
|
G_Client_UserinfoChanged( ent-g_entities );
|
|
return;
|
|
}
|
|
else if ( !uName[0] && !pwd[0] ) { //if user added no args (ie wanted the parameters)
|
|
trap_SendServerCommand( ent-g_entities, va("print \"\nUsage: Allows a player to login via the User-DB\nCommand: userlogin <User Name> <User Password>\nEntering userlogin without password will log you out if you are loged in\n\" ") );
|
|
return;
|
|
}
|
|
|
|
clientNum = ent->client->ps.clientNum;
|
|
client = ent->client;
|
|
|
|
trap_Argv(1, uName, sizeof(uName));
|
|
trap_Argv(2, pwd, sizeof(pwd));
|
|
|
|
res = G_Sql_UserDB_Login(uName, pwd, clientNum);
|
|
|
|
if(res) {
|
|
trap_SendServerCommand(clientNum, "print \"Login Successful.\n\"");
|
|
} else {
|
|
trap_SendServerCommand(clientNum, "print \"Login failed. Wrong password or username?\n\"");
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_SqlUserAdd_f
|
|
=================
|
|
*/
|
|
static void Cmd_SqlUserAdd_f(gentity_t *ent) {
|
|
char uName[MAX_TOKEN_CHARS];
|
|
char password[MAX_TOKEN_CHARS];
|
|
qboolean res;
|
|
|
|
if(!sql_use.integer || !ent || !ent->client) return;
|
|
|
|
if(!IsAdmin(ent)) {
|
|
return;
|
|
}
|
|
|
|
if(trap_Argc() < 2) {
|
|
return;
|
|
}
|
|
|
|
trap_Argv(1, uName, sizeof(uName));
|
|
trap_Argv(2, password, sizeof(password));
|
|
|
|
res = G_Sql_UserDB_Add(uName, password);
|
|
|
|
if(!res) {
|
|
trap_SendServerCommand(ent->client->ps.clientNum, "print \"User could not be added.\n\"");
|
|
} else {
|
|
trap_SendServerCommand(ent->client->ps.clientNum, va("print \"User was added.\n\""));
|
|
}
|
|
}
|
|
|
|
/*
|
|
=================
|
|
Cmd_SqlUserMod_f
|
|
=================
|
|
*/
|
|
static void Cmd_SqlUserMod_f(gentity_t *ent) {
|
|
char uName[MAX_TOKEN_CHARS];
|
|
char right[MAX_TOKEN_CHARS];
|
|
long lright;
|
|
int value;
|
|
qboolean res;
|
|
int clientNum;
|
|
|
|
if(!sql_use.integer || !ent || !ent->client) return;
|
|
|
|
if(!IsAdmin(ent)) {
|
|
return;
|
|
}
|
|
|
|
if(trap_Argc() < 3) {
|
|
return;
|
|
}
|
|
|
|
clientNum = ent->client->ps.clientNum;
|
|
|
|
trap_Argv(3, uName, sizeof(uName));
|
|
value = atoi(uName);
|
|
trap_Argv(1, uName, sizeof(uName));
|
|
trap_Argv(2, right, sizeof(right));
|
|
|
|
/* TODO finish me */
|
|
res = qfalse;
|
|
|
|
switch(res) {
|
|
case 1:
|
|
trap_SendServerCommand(clientNum, "print \"Seems to have worked.\n\"");
|
|
break;
|
|
case 2:
|
|
trap_SendServerCommand(clientNum, "print \"User does not exist.\n\"");
|
|
break;
|
|
case 3:
|
|
trap_SendServerCommand(clientNum, "print \"No entry for user found. Created one.\n\"");
|
|
break;
|
|
case 0:
|
|
trap_SendServerCommand(clientNum, "print \"An SQL Error occured, check server log for more information.\n\"");
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
=================
|
|
Cmd_findEntitiesInRadius
|
|
=================
|
|
*/
|
|
static void Cmd_findEntitiesInRadius(gentity_t *ent) {
|
|
char arg[MAX_QPATH];
|
|
int radius;
|
|
char *classname = NULL;
|
|
qboolean all = qfalse;
|
|
qboolean takeDamage = qfalse;
|
|
struct list entities;
|
|
struct list ignore;
|
|
list_iter_p iter;
|
|
container_p c;
|
|
gentity_t* t;
|
|
|
|
#ifndef SQL
|
|
if ( !IsAdmin( ent ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as an admin.\n\" ") );
|
|
return;
|
|
}
|
|
#else
|
|
if ( !IsAdmin( ent ) || !G_Sql_UserDB_CheckRight(ent->client->uid, SQLF_DEBUG ) ) {
|
|
trap_SendServerCommand( ent-g_entities, va("print \"ERROR: You are not logged in as a user with the appropiate rights.\n\" ") );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if(trap_Argc() < 3) return;
|
|
|
|
trap_Argv(1, arg, sizeof(arg));
|
|
|
|
if(!Q_stricmp(Q_strlwr(arg), "all"))
|
|
all = qtrue;
|
|
else
|
|
classname = G_NewString(Q_strlwr(arg));
|
|
|
|
trap_Argv(2, arg, sizeof(arg));
|
|
radius = atoi(arg);
|
|
if(radius < 0) return;
|
|
|
|
trap_Argv(3, arg, sizeof(arg));
|
|
takeDamage = (qboolean)atoi(arg);
|
|
|
|
list_init(&entities, free);
|
|
list_init(&ignore, free);
|
|
ignore.append_ptr(&ignore, ent, LT_DATA);
|
|
G_RadiusList(ent->r.currentOrigin, radius, &ignore, takeDamage, &entities);
|
|
ignore.clear(&ignore);
|
|
|
|
iter = entities.iterator(&entities, LIST_FRONT);
|
|
for(c = entities.next(iter); c != NULL; c = entities.next(iter)) {
|
|
t = c->data;
|
|
|
|
if(t == NULL) {
|
|
continue;
|
|
}
|
|
|
|
if(all) {
|
|
G_PrintfClient(ent, "Entity: %i, Classname: %s", t-g_entities, t->classname);
|
|
} else {
|
|
if(!Q_stricmpn(t->classname, classname, strlen(classname))) {
|
|
G_PrintfClient(ent, "Entity: %i Classname: %s", t-g_entities, classname);
|
|
}
|
|
}
|
|
}
|
|
destroy_iterator(iter);
|
|
entities.clear(&entities);
|
|
}
|
|
|
|
// CCAM
|
|
extern void Cinematic_ActivateCameraMode(gentity_t *ent, gentity_t *target);
|
|
extern void Cinematic_DeactivateCameraMode(gentity_t *ent);
|
|
static void Cmd_Camtest_f(gentity_t *ent) {
|
|
gentity_t *targ;
|
|
char tname[256];
|
|
|
|
if(trap_Argc() < 1) return;
|
|
|
|
G_Printf("activate cam\n");
|
|
|
|
if(ent->flags & FL_CCAM) return;
|
|
|
|
trap_Argv(1, tname, sizeof(tname));
|
|
|
|
targ = G_Find(NULL, FOFS(targetname), tname);
|
|
if(!targ) return;
|
|
|
|
Cinematic_ActivateCameraMode(ent, targ);
|
|
}
|
|
|
|
void Cmd_CamtestEnd_f(gentity_t *ent) {
|
|
//Cinematic_DeactivateCameraMode(ent);
|
|
G_LuaNumThreads();
|
|
}
|
|
// END CCAM
|
|
|
|
void addShaderToList(list_p list, char *shader) {
|
|
char* s;
|
|
char* t;
|
|
container_p c;
|
|
list_iter_p i;
|
|
|
|
if(shader[0] == 0) return;
|
|
if(list == NULL) return;
|
|
|
|
s = strdup(shader);
|
|
if(s == NULL) {
|
|
return;
|
|
}
|
|
|
|
i = list->iterator(list, LIST_FRONT);
|
|
if(i == NULL) {
|
|
return;
|
|
}
|
|
|
|
for(c = list->next(i); c != NULL; c = list->next(i)) {
|
|
t = c->data;
|
|
if(!strcmp(shader, t)) {
|
|
return;
|
|
}
|
|
}
|
|
destroy_iterator(i);
|
|
|
|
list->append(list, s, LT_STRING, strlen(s)+1);
|
|
}
|
|
|
|
extern target_alert_Shaders_s alertShaders;
|
|
void Cmd_GeneratePrecacheFile(gentity_t *ent) {
|
|
int i;
|
|
char info[MAX_INFO_STRING];
|
|
char file[MAX_QPATH];
|
|
list_p shaders;
|
|
list_iter_p iter;
|
|
qboolean first = qtrue;
|
|
fileHandle_t f;
|
|
char* s;
|
|
container_p c;
|
|
|
|
trap_GetServerinfo(info, MAX_INFO_STRING);
|
|
Com_sprintf(file, MAX_QPATH, "maps/%s.precache", Info_ValueForKey(info, "mapname"));
|
|
trap_FS_FOpenFile(file, &f, FS_APPEND);
|
|
if(!f) {
|
|
G_Printf(S_COLOR_RED "[Error] - Could not create/open 'maps/%s.precache'\n", file);
|
|
return;
|
|
}
|
|
|
|
shaders = create_list();
|
|
if(!shaders) {
|
|
G_Printf(S_COLOR_RED "[Error] - Could not create shader list.\n");
|
|
trap_FS_FCloseFile(f);
|
|
return;
|
|
}
|
|
|
|
G_Printf("Generating precache file '%s' ...\n", file);
|
|
|
|
for(i = 0; i < alertShaders.numShaders; i++) {
|
|
addShaderToList(shaders, alertShaders.blueShaders[i]);
|
|
addShaderToList(shaders, alertShaders.greenShaders[i]);
|
|
addShaderToList(shaders, alertShaders.redShaders[i]);
|
|
addShaderToList(shaders, alertShaders.yellowShaders[i]);
|
|
}
|
|
|
|
for(i = 0; i < MAX_GENTITIES; i++) {
|
|
if(!g_entities[i].inuse) continue;
|
|
|
|
if(g_entities[i].classname != NULL && !strcmp(g_entities[i].classname, "target_turbolift")) {
|
|
if(g_entities[i].falsename != NULL && g_entities[i].falsename[0] != 0) {
|
|
addShaderToList(shaders, g_entities[i].falsename);
|
|
}
|
|
if(g_entities[i].truename != NULL && g_entities[i].truename[0] != 0) {
|
|
addShaderToList(shaders, g_entities[i].truename);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if(g_entities[i].targetShaderNewName != NULL && g_entities[i].targetShaderNewName[0] != 0) {
|
|
addShaderToList(shaders, g_entities[i].targetShaderNewName);
|
|
}
|
|
}
|
|
|
|
iter = shaders->iterator(shaders, LIST_FRONT);
|
|
if(iter == NULL) {
|
|
trap_FS_FCloseFile(f);
|
|
destroy_list(shaders);
|
|
return;
|
|
}
|
|
|
|
for(c = shaders->next(iter); c != NULL; c = shaders->next(iter)) {
|
|
s = c->data;
|
|
G_Printf("\t%s\n", s);
|
|
if(first) {
|
|
trap_FS_Write("\"", 1, f);
|
|
trap_FS_Write(s, strlen(s), f);
|
|
trap_FS_Write("\"", 1, f);
|
|
first = qfalse;
|
|
} else {
|
|
trap_FS_Write("\n\"", 2, f);
|
|
trap_FS_Write(s, strlen(s), f);
|
|
trap_FS_Write("\"", 1, f);
|
|
}
|
|
}
|
|
trap_FS_Write("\n\"END\"", 6, f);
|
|
destroy_iterator(iter);
|
|
|
|
G_Printf("Done.\n");
|
|
|
|
if(shaders != NULL) {
|
|
destroy_list(shaders);
|
|
}
|
|
trap_FS_FCloseFile(f);
|
|
}
|
|
|
|
/*
|
|
=================
|
|
G_Client_Command
|
|
=================
|
|
*/
|
|
void G_Client_Command( int clientNum )
|
|
{
|
|
gentity_t *ent;
|
|
char cmd[MAX_TOKEN_CHARS];
|
|
|
|
//ent = g_entities + clientNum;
|
|
ent = &g_entities[clientNum];
|
|
if ( !ent->client ) {
|
|
return; // not fully in game yet
|
|
}
|
|
|
|
trap_Argv( 0, cmd, sizeof( cmd ) );
|
|
|
|
if (Q_stricmp (cmd, "say") == 0) {
|
|
Cmd_Say_f (ent, SAY_ALL, qfalse);
|
|
return;
|
|
}
|
|
if (Q_stricmp (cmd, "say_team") == 0) {
|
|
Cmd_Say_f (ent, SAY_TEAM, qfalse);
|
|
return;
|
|
}
|
|
if (Q_stricmp (cmd, "say_class") == 0) {
|
|
Cmd_Say_f (ent, SAY_CLASS, qfalse);
|
|
return;
|
|
}
|
|
if (Q_stricmp (cmd, "say_area") == 0) {
|
|
Cmd_Say_f (ent, SAY_AREA, qfalse);
|
|
return;
|
|
}
|
|
if (Q_stricmp (cmd, "tell") == 0) {
|
|
Cmd_Tell_f ( ent );
|
|
return;
|
|
}
|
|
if (Q_stricmp (cmd, "score") == 0) {
|
|
Cmd_Score_f (ent);
|
|
return;
|
|
}
|
|
if (Q_stricmp (cmd, "ready") == 0)
|
|
{
|
|
Cmd_Ready_f(ent);
|
|
return;
|
|
}
|
|
|
|
#ifdef G_LUA
|
|
if(Q_stricmp(cmd, "lua_status") == 0)
|
|
{
|
|
G_LuaStatus(ent);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
// ignore all other commands when at intermission
|
|
if (level.intermissiontime)
|
|
{
|
|
Cmd_Say_f (ent, SAY_INVAL, qtrue);
|
|
return;
|
|
}
|
|
|
|
if (Q_stricmp (cmd, "give") == 0)
|
|
Cmd_Give_f (ent);
|
|
else if (Q_stricmp (cmd, "callvote") == 0)
|
|
Cmd_CallVote_f (ent);
|
|
else if (Q_stricmp (cmd, "vote") == 0)
|
|
Cmd_Vote_f (ent);
|
|
else if (Q_stricmp (cmd, "god") == 0)
|
|
Cmd_God_f (ent);
|
|
else if (Q_stricmp (cmd, "notarget") == 0)
|
|
Cmd_Notarget_f (ent);
|
|
else if (Q_stricmp (cmd, "noclip") == 0)
|
|
Cmd_Noclip_f (ent);
|
|
else if (Q_stricmp (cmd, "kill") == 0)
|
|
Cmd_Kill_f (ent);
|
|
else if (Q_stricmp (cmd, "levelshot") == 0)
|
|
Cmd_LevelShot_f (ent);
|
|
else if (Q_stricmp (cmd, "team") == 0)
|
|
Cmd_Team_f (ent);
|
|
else if (Q_stricmp (cmd, "class") == 0)
|
|
Cmd_Class_f (ent);
|
|
else if (Q_stricmp (cmd, "where") == 0)
|
|
Cmd_Where_f (ent);
|
|
else if (Q_stricmp (cmd, "gc") == 0)
|
|
Cmd_GameCommand_f( ent );
|
|
else if (Q_stricmp (cmd, "setviewpos") == 0)
|
|
Cmd_SetViewpos_f( ent );
|
|
//LASER
|
|
else if (Q_stricmp (cmd, "laser") == 0)
|
|
Cmd_Laser_f( ent );
|
|
else if (Q_stricmp (cmd, "flashlight") == 0)
|
|
Cmd_FlashLight_f( ent );
|
|
else if (Q_stricmp (cmd, "cloak") == 0 && !(rpg_restrictions.integer & 1) )
|
|
Cmd_Cloak_f( ent );
|
|
else if (Q_stricmp (cmd, "flight") == 0 && !(rpg_restrictions.integer & 2) )
|
|
Cmd_Flight_f( ent );
|
|
else if (Q_stricmp (cmd, "evasuit") == 0)
|
|
Cmd_EvoSuit_f( ent );
|
|
else if (Q_stricmp (cmd, "forcename") == 0 )
|
|
Cmd_ForceName_f( ent );
|
|
else if (Q_stricmp (cmd, "forcekill") == 0 )
|
|
Cmd_ForceKill_f( ent );
|
|
else if (Q_stricmp (cmd, "forcekillradius") == 0 )
|
|
Cmd_ForceKillRadius_f( ent );
|
|
else if (Q_stricmp (cmd, "forceclass") == 0 )
|
|
Cmd_ForceClass_f( ent );
|
|
else if (Q_stricmp (cmd, "kicktarget") == 0 )
|
|
Cmd_TargetKick_f(ent);
|
|
else if (Q_stricmp (cmd, "shake") == 0 )
|
|
Cmd_ShakeCamera_f( ent );
|
|
else if (Q_stricmp (cmd, "drag") == 0 )
|
|
Cmd_Drag_f(ent);
|
|
else if (Q_stricmp (cmd, "undrag") == 0 )
|
|
Cmd_UnDrag_f( ent );
|
|
else if (Q_stricmp (cmd, "flushTripmines") == 0 ) //disarm_tripmines
|
|
Cmd_disarm_f(ent);
|
|
else if (Q_stricmp (cmd, "rank") == 0 )
|
|
Cmd_Rank_f(ent);
|
|
else if (Q_stricmp (cmd, "forcerank") == 0 )
|
|
Cmd_ForceRank_f(ent);
|
|
else if (Q_stricmp (cmd, "forcemodel") == 0 )
|
|
Cmd_ForceModel_f(ent);
|
|
else if (Q_stricmp (cmd, "adminlogin") == 0 )
|
|
Cmd_AdminLogin_f(ent);
|
|
else if (Q_stricmp (cmd, "adminList") == 0 )
|
|
Cmd_Admins_f(ent);
|
|
else if (Q_stricmp (cmd, "revive") == 0 )
|
|
Cmd_Revive_f(ent);
|
|
else if (Q_stricmp (cmd, "n00b") == 0 )
|
|
Cmd_n00b_f(ent);
|
|
else if (Q_stricmp (cmd, "msg") == 0 )
|
|
Cmd_admin_message(ent);
|
|
else if (Q_stricmp (cmd, "playMusic") == 0 )
|
|
Cmd_PlayMusic_f(ent);
|
|
else if (Q_stricmp (cmd, "stopMusic") == 0 )
|
|
Cmd_StopMusic_f(ent);
|
|
else if (Q_stricmp (cmd, "playSound") == 0 )
|
|
Cmd_PlaySound_f(ent);
|
|
else if (Q_stricmp(cmd, "equip") == 0 )
|
|
Cmd_Bolton_f(ent);
|
|
else if (Q_stricmp(cmd, "useEnt") == 0 )
|
|
Cmd_UseEnt_f(ent);
|
|
else if (Q_stricmp(cmd, "entList") == 0 )
|
|
Cmd_EntList_f(ent);
|
|
else if (Q_stricmp(cmd, "beamToLocation") == 0 )
|
|
Cmd_BeamToLoc_f(ent);
|
|
else if (Q_stricmp(cmd, "beamToPlayer") == 0 )
|
|
Cmd_BeamToPlayer_f(ent);
|
|
else if (Q_stricmp(cmd, "forcePlayer") == 0 )
|
|
Cmd_ForcePlayer_f(ent);
|
|
else if (Q_stricmp(cmd, "doEmote") == 0 )
|
|
Cmd_DoEmote_f(ent);
|
|
else if (Q_stricmp(cmd, "flushEmote") == 0 )
|
|
Cmd_EndEmote_f(ent);
|
|
else if (Q_stricmp(cmd, "fxGun") == 0 )
|
|
Cmd_fxGun_f(ent);
|
|
else if (Q_stricmp(cmd, "flushFX") == 0 )
|
|
Cmd_flushFX_f(ent);
|
|
else if (Q_stricmp(cmd, "spawnChar") == 0 )
|
|
Cmd_spawnChar_f( ent );
|
|
else if (Q_stricmp(cmd, "flushChars") == 0 )
|
|
Cmd_fluchChars_f(ent);
|
|
else if (Q_stricmp( cmd, "kick2") == 0 )
|
|
Cmd_Kick2_f(ent);
|
|
else if (Q_stricmp( cmd, "clampInfo") == 0 )
|
|
Cmd_ClampInfo_f(ent);
|
|
else if (Q_stricmp( cmd, "deck" ) == 0 )
|
|
Cmd_Turbolift_f(ent);
|
|
else if (Q_stricmp( cmd, "me" ) == 0 )
|
|
Cmd_MeAction_f(ent);
|
|
else if (Q_stricmp( cmd, "meLocal" ) == 0 )
|
|
Cmd_MeActionLocal_f(ent);
|
|
else if (Q_stricmp( cmd, "mapsList" ) == 0 )
|
|
Cmd_MapsList_f(ent);
|
|
else if (Q_stricmp (cmd, "drop") == 0) // RPG-X | Marcin | 03/12/2008
|
|
Cmd_Drop_f(ent);
|
|
else if (Q_stricmp (cmd, "flushDropped") == 0) // RPG-X | Marcin | 04/12/2008
|
|
Cmd_flushDropped_f(ent);
|
|
else if (Q_stricmp (cmd, "lock") == 0) //RPG-X | GSIO01 | 08/05/2009
|
|
Cmd_lockDoor_f(ent);
|
|
else if (Q_stricmp (cmd, "ffColor") == 0) //RPG-X | GSIO01 | 09/05/2009
|
|
Cmd_ffColor_f(ent);
|
|
else if (Q_stricmp (cmd, "remodulate") == 0) //RPG-X | GSIO01 | 10/05/2009
|
|
Cmd_remodulate_f(ent);
|
|
else if (Q_stricmp (cmd, "unlockAll") == 0)
|
|
Cmd_unlockAll_f(ent);
|
|
else if (Q_stricmp (cmd, "respawn") == 0)
|
|
Cmd_Respawn_f(ent);
|
|
else if (Q_stricmp (cmd, "lockAll") == 0)
|
|
Cmd_lockAll_f(ent);
|
|
else if (Q_stricmp (cmd, "changeFreq") == 0)
|
|
Cmd_changeFreq(ent);
|
|
else if (Q_stricmp(cmd, "alert") == 0)
|
|
Cmd_alert_f(ent);
|
|
else if (Q_stricmp(cmd, "zonelist") == 0)
|
|
Cmd_zonelist_f(ent);
|
|
else if (Q_stricmp(cmd, "selfdestruct") == 0)
|
|
Cmd_selfdestruct_f(ent);
|
|
else if (Q_stricmp(cmd, "shipdamage") == 0)
|
|
Cmd_shipdamage_f(ent);
|
|
else if (Q_stricmp(cmd, "shiphealth") == 0)
|
|
Cmd_shiphealth_f(ent);
|
|
else if (Q_stricmp(cmd, "reloadtorpedos") == 0)
|
|
Cmd_reloadtorpedos_f(ent);
|
|
else if (Q_stricmp(cmd, "torpedolist") == 0)
|
|
Cmd_torpedolist_f(ent);
|
|
else if (Q_stricmp(cmd, "msg2") == 0)
|
|
Cmd_admin_centerprint_f(ent);
|
|
else if (Q_stricmp(cmd, "forcevote") == 0)
|
|
Cmd_ForceVote_f(ent);
|
|
else if (Q_stricmp(cmd, "listSPs") == 0)
|
|
Cmd_listSPs(ent);
|
|
else if (Q_stricmp(cmd, "getEntInfo") == 0)
|
|
Cmd_getEntInfo_f(ent);
|
|
else if (Q_stricmp(cmd, "getOrigin") == 0)
|
|
Cmd_getOrigin_f(ent);
|
|
else if (Q_stricmp(cmd, "getEntByTargetname") == 0)
|
|
Cmd_getEntByTargetname_f(ent);
|
|
else if (Q_stricmp(cmd, "getEntByTarget") == 0)
|
|
Cmd_getEntByTarget_f(ent);
|
|
else if (Q_stricmp(cmd, "getEntByBmodel") == 0)
|
|
Cmd_getEntByBmodel_f(ent);
|
|
else if (Q_stricmp(cmd, "setOrigin") == 0)
|
|
Cmd_setOrigin(ent);
|
|
else if (Q_stricmp(cmd, "getBrushEntCount") == 0)
|
|
Cmd_getBrushEntCount_f(ent);
|
|
else if (Q_stricmp(cmd, "findEntitiesInRadius") == 0)
|
|
Cmd_findEntitiesInRadius(ent);
|
|
else if (Q_stricmp(cmd, "spawnTEnt") == 0)
|
|
Cmd_spawnTentity_f(ent);
|
|
else if (Q_stricmp(cmd, "flushTEnts") == 0)
|
|
Cmd_flushTentities_f(ent);
|
|
else if (Q_stricmp(cmd, "ui_transporterLoc") == 0)
|
|
Cmd_UiTransporterLoc_f(ent);
|
|
else if (Q_stricmp(cmd, "ui_transporterExt") == 0)
|
|
Cmd_UiTransporterExt_f(ent);
|
|
else if (Q_stricmp(cmd, "ui_holodeck") == 0)
|
|
Cmd_UiHolodeck_f(ent);
|
|
else if (Q_stricmp(cmd, "ui_debug") == 0)
|
|
UI_DEBUG(ent);
|
|
#ifdef SQL
|
|
else if (Q_stricmp(cmd, "userlogin") == 0)
|
|
Cmd_SqlLogin_f(ent);
|
|
else if (Q_stricmp(cmd, "userAdd") == 0)
|
|
Cmd_SqlUserAdd_f(ent);
|
|
else if (Q_stricmp(cmd, "userMod") == 0)
|
|
Cmd_SqlUserMod_f(ent);
|
|
#endif
|
|
#ifdef OLDSQL // SQL
|
|
else if (Q_stricmp(cmd, "sql_setup") == 0)
|
|
Cmd_SqlSetup_f(ent);
|
|
else if (Q_stricmp(cmd, "userAdd") == 0)
|
|
Cmd_SqlUserAdd_f(ent);
|
|
else if (Q_stricmp(cmd, "userDel") == 0)
|
|
Cmd_SqlUserDel_f(ent);
|
|
#endif
|
|
// CCAM
|
|
else if (Q_stricmp(cmd, "camtest") == 0)
|
|
Cmd_Camtest_f(ent);
|
|
else if (Q_stricmp(cmd, "camtestend") == 0)
|
|
Cmd_CamtestEnd_f(ent);
|
|
// END CCAM
|
|
else if (Q_stricmp (cmd, "generatePrecacheFile") == 0) {
|
|
Cmd_GeneratePrecacheFile(ent);
|
|
}
|
|
else if (Q_strncmp (cmd, "\n", 1) == 0 || Q_strncmp (cmd, " ", 1) == 0 || Q_strncmp (cmd, "\0", 1) == 0) // sorry
|
|
(void)(0);
|
|
else
|
|
trap_SendServerCommand( clientNum, va("print \"unknown cmd %s\n\"", cmd ) );
|
|
}
|
|
|
|
//--------
|