diff options
Diffstat (limited to 'src/game/g_admin.c')
-rw-r--r-- | src/game/g_admin.c | 163 |
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 |