summaryrefslogtreecommitdiff
path: root/src/game/g_admin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/g_admin.c')
-rw-r--r--src/game/g_admin.c163
1 files changed, 144 insertions, 19 deletions
diff --git a/src/game/g_admin.c b/src/game/g_admin.c
index 8a9d130..6208705 100644
--- a/src/game/g_admin.c
+++ b/src/game/g_admin.c
@@ -112,6 +112,11 @@ g_admin_cmd_t g_admin_cmds[ ] =
"(-AHS) [^3message^7]"
},
+ {"control", G_admin_control, "control",
+ "take control of a placeholder client",
+ "[^3name|slot#^7] ..."
+ },
+
{"demo", G_admin_demo, "demo",
"turn admin chat off for the caller so it does not appear in demos. "
"this is a toggle use !demo again to turn warnings back on",
@@ -1808,6 +1813,9 @@ qboolean G_admin_cmd_check( gentity_t *ent, qboolean say )
{
return qfalse;
}
+
+ if (!Q_stricmp(cmd, "control") && ent && ent->client->pers.isPlaceholder)
+ ent = &g_entities[-ent->client->pers.control - 1];
// Flood limit. If they're talking too fast, determine that and return.
if( g_floodMinTime.integer )
@@ -2035,6 +2043,8 @@ void G_admin_namelog_update( gclient_t *client, qboolean disconnect )
Q_strncpyz( namelog->name[ 0 ], client->pers.netname,
sizeof( namelog->name[ 0 ] ) );
namelog->slot = ( disconnect ) ? -1 : clientNum;
+ if (client->pers.isPlaceholder)
+ namelog->smj.ratingTime = 0x70000000;
schachtmeisterProcess( namelog );
g_admin_namelog[ i ] = namelog;
}
@@ -3185,10 +3195,13 @@ qboolean G_admin_kick( gentity_t *ent, int skiparg )
vic->client->pers.karma -= 5000;
- trap_SendServerCommand( pids[ 0 ],
- va( "disconnect \"You have been kicked.\n%s^7\nreason:\n%s\n%s\"",
- ( ent ) ? va( "admin:\n%s", G_admin_adminPrintName( ent ) ) : "admin\nconsole",
- ( *reason ) ? reason : "kicked by admin", notice ) );
+ if (!vic->client->pers.isPlaceholder)
+ {
+ trap_SendServerCommand( pids[ 0 ],
+ va( "disconnect \"You have been kicked.\n%s^7\nreason:\n%s\n%s\"",
+ ( ent ) ? va( "admin:\n%s", G_admin_adminPrintName( ent ) ) : "admin\nconsole",
+ ( *reason ) ? reason : "kicked by admin", notice ) );
+ }
G_LogPrintf( "kick: %i %i [%s] (%s) %s^7 %s^7\n",
vic->client->ps.clientNum,
@@ -3412,12 +3425,15 @@ qboolean G_admin_ban( gentity_t *ent, int skiparg )
if( g_karma.integer )
vic->client->pers.karma -= 5000;
- trap_SendServerCommand( g_admin_namelog[ logmatch ]->slot,
- va( "disconnect \"You have been banned.\n"
- "admin:\n%s^7\nduration:\n%s\nreason:\n%s\n%s\"",
- ( ent ) ? G_admin_adminPrintName( ent ) : "console",
- duration,
- ( *reason ) ? reason : "banned by admin", notice ) );
+ if (!vic->client->pers.isPlaceholder)
+ {
+ trap_SendServerCommand( g_admin_namelog[ logmatch ]->slot,
+ va( "disconnect \"You have been banned.\n"
+ "admin:\n%s^7\nduration:\n%s\nreason:\n%s\n%s\"",
+ ( ent ) ? G_admin_adminPrintName( ent ) : "console",
+ duration,
+ ( *reason ) ? reason : "banned by admin", notice ) );
+ }
trap_DropClient( g_admin_namelog[ logmatch ]->slot,
va( "banned by %s^7, duration: %s, reason: %s",
@@ -3483,8 +3499,9 @@ static void admin_autobahn(gentity_t *ent, int rating)
if (rating > g_schachtmeisterAutobahnThreshold.integer)
return;
- trap_SendServerCommand(ent - g_entities, va("disconnect \"%s\"\n",
- g_schachtmeisterAutobahnMessage.string));
+ if (!ent->client->pers.isPlaceholder)
+ trap_SendServerCommand(ent - g_entities, va("disconnect \"%s\"\n",
+ g_schachtmeisterAutobahnMessage.string));
trap_DropClient(ent - g_entities, "dropped by the Autobahn");
}
@@ -7989,13 +8006,18 @@ qboolean G_admin_drop( gentity_t *ent, int skiparg )
return qfalse;
}
- // victim's message
- if( G_SayArgc() > 2 + skiparg )
- trap_SendServerCommand( pids[ 0 ],
- va( "disconnect \"You have been dropped.\n%s^7\n\"",
- G_SayConcatArgs( 2 + skiparg ) ) );
- else
- trap_SendServerCommand( pids[ 0 ], va( "disconnect" ) );
+ if (!g_clients[pids[0]].pers.isPlaceholder)
+ {
+ // victim's message
+ if( G_SayArgc() > 2 + skiparg )
+ {
+ trap_SendServerCommand( pids[ 0 ],
+ va( "disconnect \"You have been dropped.\n%s^7\n\"",
+ G_SayConcatArgs( 2 + skiparg ) ) );
+ }
+ else
+ trap_SendServerCommand( pids[ 0 ], va( "disconnect" ) );
+ }
// server message
trap_DropClient( pids[ 0 ], va( "disconnected" ) );
@@ -8042,6 +8064,109 @@ qboolean G_admin_bubble( gentity_t *ent, int skiparg )
return qtrue;
}
+qboolean G_admin_control(gentity_t *ent, int skiparg)
+{
+ if (!ent)
+ {
+ ADMP("^3!control: ^7the console cannot be used to take control\n");
+ return qfalse;
+ }
+
+ if (G_SayArgc() <= 1 + skiparg)
+ {
+ ADMP("^3!control: ^7usage: !control [name|slot#] ...\n");
+ return qfalse;
+ }
+
+ int n = ent - g_entities;
+ gclient_t *cl = &g_clients[n];
+
+ byte sel[MAX_CLIENTS];
+ int nsel = 0;
+ int ix = -1;
+ qboolean phc_matched = qfalse;
+
+ for (int a = 1 + skiparg; a < G_SayArgc(); ++a)
+ {
+ char arg[MAX_NAME_LENGTH];
+ G_SayArgv(a, arg, sizeof(arg));
+
+ int sel2[MAX_CLIENTS];
+ int nsel2 = G_ClientNumbersFromString(arg, sel2);
+
+ for (int j = 0; j < nsel2; ++j)
+ {
+ int k = sel2[j];
+ clientPersistant_t *p = &g_clients[k].pers;
+
+ if (k != n)
+ {
+ if (!p->isPlaceholder)
+ continue;
+ phc_matched = qtrue;
+ if (p->control < 0 && (-p->control - 1) != n)
+ continue;
+ }
+
+ for (int i = 0; i < nsel; ++i)
+ {
+ if (sel[i] == k)
+ goto already_included;
+ }
+
+ if ((!cl->pers.control && k == n) || k == cl->pers.control - 1)
+ ix = nsel;
+ sel[nsel++] = k;
+
+ already_included:;
+ }
+ }
+
+ if (nsel == 0)
+ {
+ if (phc_matched)
+ ADMP("^3!control: ^7all matching placeholder clients are currently controlled by others\n");
+ else
+ ADMP("^3!control: ^7no placeholder clients (nor self) matched\n");
+ return qfalse;
+ }
+
+ int k = sel[(ix + 1) % nsel];
+
+ if ((!cl->pers.control && k == n) || k == cl->pers.control - 1)
+ return qfalse;
+
+ if (cl->pers.control)
+ {
+ const gclient_t *c = &g_clients[cl->pers.control - 1];
+
+ g_clients[cl->pers.control - 1].pers.control = 0;
+ cl->pers.control = 0;
+
+ cl->pers.cmd = c->pers.cmd;
+ for (int i = 0; i < 3; ++i)
+ cl->ps.delta_angles[i] = ANGLE2SHORT(cl->ps.viewangles[i]) - cl->pers.cmd.angles[i];
+ }
+
+ gclient_t *c = &g_clients[k];
+
+ trap_set_client_view_entity(n, k);
+
+ ADMP(va("^3!control: ^7took control of %s^7\n", c->pers.netname));
+
+ if (k == n)
+ return qtrue;
+
+ c->pers.cmd = cl->pers.cmd;
+ for (int i = 0; i < 3; ++i)
+ c->ps.delta_angles[i] = ANGLE2SHORT(c->ps.viewangles[i]) - c->pers.cmd.angles[i];
+
+ cl->pers.control = 1 + k;
+ c->pers.control = -1 - n;
+
+ return qfalse;
+}
+
qboolean G_admin_buildlog( gentity_t *ent, int skiparg )
{
#define LOG_DISPLAY_LENGTH 10