diff options
27 files changed, 377 insertions, 52 deletions
diff --git a/assets/credits.txt b/assets/credits.txt index 2e6cd27..e4a63c5 100644 --- a/assets/credits.txt +++ b/assets/credits.txt @@ -6,6 +6,13 @@ Cuboid - a Tremulous 1.2 mod focused on cuboids and fixing balance issues. Version Release date ______________________________________________________________________________________________ +0.1.4 Sep 12 2013 +NON-GAMEPLAY: +- Announcer now announces things like "Aliens win" or "1 minute remaining", not just votes. +- /register was implemented +- Admin titles were implemented (/settitle, /listplayers). +- Death obituaries were improved (now show killer's health and victim's class (if alien)). + 0.1.3 Sep 10 2013 GAMEPLAY: - It's not longer possible to avoid buildtimer by reconnecting. @@ -15,8 +22,6 @@ NON-GAMEPLAY: - A lot of visual changes in the voting system. - Added vote sounds. - -______________________________________________________________________________________________ 0.1.2 Sep 09 2013 GAMEPLAY: - Wall impact effects no longer appear on players or buildables (the MD passing through players bug). @@ -145,7 +150,7 @@ sound/cuboid/slime/dstr0.wav Michael Manzke @ freesound.org sound/cuboid/slime/dstr1.wav Audionautics @ freesound.org cc-by sound/cuboid/slime/pain0.wav anechoix @ freesound.org cc-by-nc sound/cuboid/slime/pain1.wav anechoix @ freesound.org cc-by-nc -sound/feedback/vote*.wav ?? ?? +sound/feedback/*.wav Pikachu cc0 sound/player/alienhatch.wav Darklegion Development, theinvsblman cc-by-sa sound/player/alienfailedhatch.wav Darklegion Development, theinvsblman cc-by-sa sound/upgrades/jetpack/hi.wav Pikachu cc0 diff --git a/assets/sound/feedback/1minremains.wav b/assets/sound/feedback/1minremains.wav Binary files differnew file mode 100644 index 0000000..155da04 --- /dev/null +++ b/assets/sound/feedback/1minremains.wav diff --git a/assets/sound/feedback/5minremain.wav b/assets/sound/feedback/5minremain.wav Binary files differnew file mode 100644 index 0000000..545ec43 --- /dev/null +++ b/assets/sound/feedback/5minremain.wav diff --git a/assets/sound/feedback/aliensadmit.wav b/assets/sound/feedback/aliensadmit.wav Binary files differnew file mode 100644 index 0000000..0389669 --- /dev/null +++ b/assets/sound/feedback/aliensadmit.wav diff --git a/assets/sound/feedback/alienslocked.wav b/assets/sound/feedback/alienslocked.wav Binary files differnew file mode 100644 index 0000000..2063f2c --- /dev/null +++ b/assets/sound/feedback/alienslocked.wav diff --git a/assets/sound/feedback/aliensunlocked.wav b/assets/sound/feedback/aliensunlocked.wav Binary files differnew file mode 100644 index 0000000..a56acdf --- /dev/null +++ b/assets/sound/feedback/aliensunlocked.wav diff --git a/assets/sound/feedback/alienswin.wav b/assets/sound/feedback/alienswin.wav Binary files differnew file mode 100644 index 0000000..cce0617 --- /dev/null +++ b/assets/sound/feedback/alienswin.wav diff --git a/assets/sound/feedback/humansadmit.wav b/assets/sound/feedback/humansadmit.wav Binary files differnew file mode 100644 index 0000000..e8f0e16 --- /dev/null +++ b/assets/sound/feedback/humansadmit.wav diff --git a/assets/sound/feedback/humanslocked.wav b/assets/sound/feedback/humanslocked.wav Binary files differnew file mode 100644 index 0000000..2b35168 --- /dev/null +++ b/assets/sound/feedback/humanslocked.wav diff --git a/assets/sound/feedback/humansunlocked.wav b/assets/sound/feedback/humansunlocked.wav Binary files differnew file mode 100644 index 0000000..7d74f63 --- /dev/null +++ b/assets/sound/feedback/humansunlocked.wav diff --git a/assets/sound/feedback/humanswin.wav b/assets/sound/feedback/humanswin.wav Binary files differnew file mode 100644 index 0000000..bd4cd37 --- /dev/null +++ b/assets/sound/feedback/humanswin.wav diff --git a/assets/sound/feedback/sdimminent.wav b/assets/sound/feedback/sdimminent.wav Binary files differnew file mode 100644 index 0000000..f90ca15 --- /dev/null +++ b/assets/sound/feedback/sdimminent.wav diff --git a/assets/sound/feedback/stalemate.wav b/assets/sound/feedback/stalemate.wav Binary files differnew file mode 100644 index 0000000..5ee654f --- /dev/null +++ b/assets/sound/feedback/stalemate.wav diff --git a/assets/sound/feedback/suddendeath.wav b/assets/sound/feedback/suddendeath.wav Binary files differnew file mode 100644 index 0000000..c75aca9 --- /dev/null +++ b/assets/sound/feedback/suddendeath.wav diff --git a/src/cgame/cg_event.c b/src/cgame/cg_event.c index 40df8b9..c8ca2e6 100644 --- a/src/cgame/cg_event.c +++ b/src/cgame/cg_event.c @@ -41,7 +41,7 @@ static void CG_Obituary( entityState_t *ent ) const char *attackerInfo; char targetName[ MAX_NAME_LENGTH ]; char attackerName[ MAX_NAME_LENGTH ]; - char className[ 64 ]; + char className[ 64 ], victimClassName[ 64 ]; gender_t gender; clientInfo_t *ci; qboolean teamKill = qfalse; @@ -77,6 +77,12 @@ static void CG_Obituary( entityState_t *ent ) message2 = ""; + if( ent->modelindex >= PCL_ALIEN_BUILDER0 && + ent->modelindex <= PCL_ALIEN_LEVEL4 ) + Com_sprintf( victimClassName, 64, "'s %s", BG_ClassConfig( ent->modelindex )->humanName ); + else + victimClassName[ 0 ] = '\0'; + // check for single client messages switch( mod ) @@ -196,7 +202,7 @@ static void CG_Obituary( entityState_t *ent ) if( message ) { - CG_Printf( "%s" S_COLOR_WHITE " %s\n", targetName, message ); + CG_Printf( "%s" S_COLOR_WHITE "%s %s\n", targetName, victimClassName, message ); return; } @@ -360,10 +366,10 @@ static void CG_Obituary( entityState_t *ent ) if( message ) { - CG_Printf( "%s" S_COLOR_WHITE " %s %s%s" S_COLOR_WHITE "%s\n", - targetName, message, + CG_Printf( "%s" S_COLOR_WHITE "%s %s %s%s" S_COLOR_WHITE "%s, %iHP left\n", + targetName, victimClassName, message, ( teamKill ) ? S_COLOR_RED "TEAMMATE " S_COLOR_WHITE : "", - attackerName, message2 ); + attackerName, message2, ent->groundEntityNum ); if( teamKill && attacker == cg.clientNum ) { CG_CenterPrint( va ( "You killed " S_COLOR_RED "TEAMMATE " @@ -375,7 +381,7 @@ static void CG_Obituary( entityState_t *ent ) } // we don't know what it was - CG_Printf( "%s" S_COLOR_WHITE " died\n", targetName ); + CG_Printf( "%s" S_COLOR_WHITE "%s died\n", targetName, victimClassName ); } diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h index 7dd951b..43e1701 100644 --- a/src/cgame/cg_local.h +++ b/src/cgame/cg_local.h @@ -941,6 +941,8 @@ typedef struct // After this many msec the crosshair name fades out completely #define CROSSHAIR_CLIENT_TIMEOUT 1000 +#define MAX_ANNOUNCER_STACK 16 + typedef struct { int clientFrame; // incremented each frame @@ -1185,9 +1187,15 @@ typedef struct qboolean forbidCuboids; //if true then dont let player build a cuboid int latestCBNumber; //wait for this number from server before building a cuboid int lastCuboidError; //last time error sound was played + + qhandle_t announcerStack[ MAX_ANNOUNCER_STACK ]; + int announcerStackPos; + int announcerStackLatest; } cg_t; + + // all of the model, shader, and sound references that are // loaded at gamestate time are stored in cgMedia_t // Other media that can be tied to clients, weapons, or items are @@ -1939,6 +1947,10 @@ void CG_WritePTRCode( int code ); const char *CG_TutorialText( void ); // +// cg_svcmds.c +void CG_ProcessAnnouncer( void ); + +// //=============================================== // @@ -2171,12 +2183,13 @@ typedef enum // mod version data -#define MODVER_CURRENT 4 +#define MODVER_CURRENT 5 +#define MODVER_C2_0_1_4 5 #define MODVER_C2_0_1_3 4 #define MODVER_C2_0_1_2 3 #define MODVER_C2_0_1_1 2 #define MODVER_C2_0_1_0 1 -#define MODVER_TITLE "0.1.3 (Sep 10)" +#define MODVER_TITLE "0.1.4 (Sep 12)" diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c index 4191cc7..427a571 100644 --- a/src/cgame/cg_main.c +++ b/src/cgame/cg_main.c @@ -1921,6 +1921,9 @@ void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum ) CG_ShaderStateChanged( ); trap_S_ClearLoopingSounds( qtrue ); + + cg.announcerStackLatest = -1; + cg.announcerStackPos = -1; } /* diff --git a/src/cgame/cg_servercmds.c b/src/cgame/cg_servercmds.c index f11aa7e..2a71b62 100644 --- a/src/cgame/cg_servercmds.c +++ b/src/cgame/cg_servercmds.c @@ -1261,12 +1261,36 @@ static void CG_PoisonCloud_f( void ) /* ================= -CG_VoteEvent_f +CG_ProcessAnnouncer +================= +*/ +#define ANNOUNCER_DELAY 2000 +void CG_ProcessAnnouncer( void ) +{ + static int last = -ANNOUNCER_DELAY; + + if( cg.announcerStackPos == cg.announcerStackLatest ) + return; -Vote sounds use commands to save on events and entities + if( last + ANNOUNCER_DELAY > cg.time ) + return; + + cg.announcerStackPos++; + cg.announcerStackPos %= MAX_ANNOUNCER_STACK; + + trap_S_StartLocalSound( cg.announcerStack[ cg.announcerStackPos ], CHAN_VOICE ); + + last = cg.time; +} + +/* +================= +CG_Announce_f + +Play an announcer sound ================= */ -static void CG_VoteEvent( void ) +static void CG_Announce( void ) { const char *event, *soundName; @@ -1278,12 +1302,31 @@ static void CG_VoteEvent( void ) if( !Q_stricmp( event, "votenow" ) || !Q_stricmp( event, "votecancelled" ) || !Q_stricmp( event, "votefailed" ) || - !Q_stricmp( event, "votepassed" ) ) + !Q_stricmp( event, "votepassed" ) || + !Q_stricmp( event, "timelimit_hit" ) || + !Q_stricmp( event, "timelimit_1min" ) || + !Q_stricmp( event, "timelimit_5min" ) || + !Q_stricmp( event, "suddendeath" ) || + !Q_stricmp( event, "sdimminent" ) || + !Q_stricmp( event, "alienswin" ) || + !Q_stricmp( event, "aliensadmit" ) || + !Q_stricmp( event, "alienslocked" ) || + !Q_stricmp( event, "aliensunlocked" ) || + !Q_stricmp( event, "humanswin" ) || + !Q_stricmp( event, "humansadmit" ) || + !Q_stricmp( event, "humanslocked" ) || + !Q_stricmp( event, "humansunlocked" ) || + !Q_stricmp( event, "stalemate" ) || + !Q_stricmp( event, "1minremains" ) || + !Q_stricmp( event, "5minremains" ) ) soundName = va( "sound/feedback/%s.wav", event ); else return; - trap_S_StartLocalSound( trap_S_RegisterSound( soundName, qfalse ), CHAN_VOICE ); + cg.announcerStackLatest++; + cg.announcerStackLatest %= MAX_ANNOUNCER_STACK; + + cg.announcerStack[ cg.announcerStackLatest ] = trap_S_RegisterSound( soundName, qfalse ); } static void CG_GameCmds_f( void ) @@ -1303,6 +1346,7 @@ static void CG_GameCmds_f( void ) static consoleCommand_t svcommands[ ] = { + { "announce", CG_Announce }, { "cb2", CG_Cuboid_Response }, // set local cuboid { "cb3", CG_Cuboid_Response }, // set local cuboid and print a "limit exceeded" warning { "chat", CG_Chat_f }, @@ -1317,8 +1361,7 @@ static consoleCommand_t svcommands[ ] = { "serverclosemenus", CG_ServerCloseMenus_f }, { "servermenu", CG_ServerMenu_f }, { "tinfo", CG_ParseTeamInfo }, - { "voice", CG_ParseVoice }, - { "voteevent", CG_VoteEvent } + { "voice", CG_ParseVoice } }; /* diff --git a/src/cgame/cg_view.c b/src/cgame/cg_view.c index cd5e384..4b2b254 100644 --- a/src/cgame/cg_view.c +++ b/src/cgame/cg_view.c @@ -1459,6 +1459,9 @@ void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demo // update audio positions trap_S_Respatialize( cg.snap->ps.clientNum, cg.refdef.vieworg, cg.refdef.viewaxis, inwater ); + + // update announcer + CG_ProcessAnnouncer( ); // make sure the lagometerSample and frame timing isn't done twice when in stereo if( stereoView != STEREO_RIGHT ) diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c index 3b667a9..a9ae715 100644 --- a/src/game/bg_misc.c +++ b/src/game/bg_misc.c @@ -2781,11 +2781,12 @@ static const upgradeAttributes_t bg_upgrades[ ] = { UP_BIORES, //int upgradeNum; BIORES_PRICE, //int price; - ( 1 << S2 )|( 1 << S3 ), //int stages + ( 1 << S2 )|( 1 << S3 ),//int stages SLOT_NONE, //int slots; "biores", //char *upgradeName; "Biores", //char *humanName; - "figure out a description later", + "A bioresistance implant that enhances the user's natural ability " + "to heal", "icons/iconu_biokit", qtrue, //qboolean purchasable qfalse, //qboolean usable diff --git a/src/game/g_admin.c b/src/game/g_admin.c index 35d57ed..cdc87c3 100644 --- a/src/game/g_admin.c +++ b/src/game/g_admin.c @@ -160,6 +160,11 @@ g_admin_cmd_t g_admin_cmds[ ] = "" }, + {"register", G_admin_register, qfalse, "register", + "register your name", + "" + }, + {"rename", G_admin_rename, qfalse, "rename", "rename a player", "[^3name|slot#^7] [^3new name^7]" @@ -180,6 +185,11 @@ g_admin_cmd_t g_admin_cmds[ ] = "[^3name|slot#|admin#^7] [^3level^7]" }, + {"settitle", G_admin_settitle, qfalse, "settitle", + "sets the title of a player", + "[^3name|slot#|admin#^7] [^3title^7]" + }, + {"showbans", G_admin_showbans, qtrue, "showbans", "display a (partial) list of active bans", "(^5name|IP(/mask)^7) (^5start at ban#^7)" @@ -440,6 +450,9 @@ static qboolean admin_higher_admin( g_admin_admin_t *a, g_admin_admin_t *b ) if( !b ) return qtrue; + if( a == b ) + return qfalse; + if( admin_permission( b->flags, ADMF_IMMUTABLE, &perm ) ) return !perm; @@ -458,6 +471,9 @@ static qboolean admin_higher( gentity_t *admin, gentity_t *victim ) // console always wins if( !admin ) return qtrue; + + if( admin == victim ) + return qfalse; return admin_higher_admin( admin->client->pers.admin, victim->client->pers.admin ); @@ -526,6 +542,8 @@ static void admin_writeconfig( void ) admin_writeconfig_int( a->level, f ); trap_FS_Write( "flags = ", 10, f ); admin_writeconfig_string( a->flags, f ); + trap_FS_Write( "title = ", 10, f ); + admin_writeconfig_string( a->title, f ); trap_FS_Write( "\n", 1, f ); } for( b = g_admin_bans; b; b = b->next ) @@ -805,14 +823,23 @@ static void admin_out( void *admin, char *str ) { g_admin_admin_t *a = (g_admin_admin_t *)admin; g_admin_level_t *l = G_admin_level( a->level ); + char *title; int lncol = 0, i; for( i = 0; l && l->name[ i ]; i++ ) { if( Q_IsColorString( l->name + i ) ) lncol += 2; } - Com_sprintf( str, MAX_STRING_CHARS, "%-6d %*s^7 %s", - a->level, admin_level_maxname + lncol - 1, l ? l->name : "(null)", + + if( Q_stricmp( a->title, "" ) ) + title = a->title; + else if ( l ) + title = l->name; + else + title = "(null)"; + + Com_sprintf( str, MAX_STRING_CHARS, "%-2d %*s^7 %s", + a->level, admin_level_maxname + lncol - 1, title, a->name ); } static int admin_listadmins( gentity_t *ent, int start, char *search ) @@ -1166,6 +1193,13 @@ qboolean G_admin_readconfig( gentity_t *ent ) { admin_readconfig_string( &cnf, a->flags, sizeof( a->flags ) ); } + else if( !Q_stricmp( t, "title" ) ) + { + admin_readconfig_string( &cnf, a->title, sizeof( a->title ) ); + len = Q_PrintStrlen( a->title ); + if( len > admin_level_maxname ) + admin_level_maxname = len; + } else { COM_ParseError( "[admin] unrecognized token \"%s\"", t ); @@ -1399,8 +1433,7 @@ qboolean G_admin_setlevel( gentity_t *ent ) if( ent && !admin_higher_admin( ent->client->pers.admin, a ) ) { - ADMP( "^3setlevel: ^7sorry, but your intended victim has a higher" - " admin level than you\n" ); + ADMP( "^3setlevel: ^7indented victim is immune to your actions\n" ); return qfalse; } @@ -1563,8 +1596,7 @@ qboolean G_admin_kick( gentity_t *ent ) vic = &g_entities[ pid ]; if( !admin_higher( ent, vic ) ) { - ADMP( "^3kick: ^7sorry, but your intended victim has a higher admin" - " level than you\n" ); + ADMP( "^3kick: ^7indented victim is immune to your actions\n" ); return qfalse; } if( vic->client->pers.localClient ) @@ -1676,8 +1708,7 @@ qboolean G_admin_ban( gentity_t *ent ) if( ent && !admin_higher_guid( ent->client->pers.guid, match->guid ) ) { - ADMP( "^3ban: ^7sorry, but your intended victim has a higher admin" - " level than you\n" ); + ADMP( "^3ban: ^7indented victim is immune to your actions\n" ); return qfalse; } if( match->slot > -1 && level.clients[ match->slot ].pers.localClient ) @@ -1930,8 +1961,7 @@ qboolean G_admin_putteam( gentity_t *ent ) vic = &g_entities[ pid ]; if( !admin_higher( ent, vic ) ) { - ADMP( "^3putteam: ^7sorry, but your intended victim has a higher " - " admin level than you\n" ); + ADMP( "^3putteam: ^7indented victim is immune to your actions\n" ); return qfalse; } teamnum = G_TeamFromString( team ); @@ -2018,8 +2048,7 @@ qboolean G_admin_mute( gentity_t *ent ) if( ent && !admin_higher_admin( ent->client->pers.admin, G_admin_admin( vic->guid ) ) ) { - ADMP( va( "^3%s: ^7sorry, but your intended victim has a higher admin" - " level than you\n", command ) ); + ADMP( va( "^3%s: ^7indented victim is immune to your actions\n", command ) ); return qfalse; } if( vic->muted ) @@ -2194,7 +2223,7 @@ qboolean G_admin_listplayers( gentity_t *ent ) gclient_t *p; char c, t; // color and team letter char *registeredname; - char lname[ MAX_NAME_LENGTH ]; + char lname[ MAX_ADMIN_TITLE ]; char muted, denied; int colorlen; char namecleaned[ MAX_NAME_LENGTH ]; @@ -2250,7 +2279,9 @@ qboolean G_admin_listplayers( gentity_t *ent ) } } - if( l ) + if( Q_stricmp( p->pers.admin->title, "" ) ) + Q_strncpyz( lname, p->pers.admin->title, sizeof( lname ) ); + else if( l ) Q_strncpyz( lname, l->name, sizeof( lname ) ); for( colorlen = j = 0; lname[ j ]; j++ ) @@ -2272,7 +2303,7 @@ qboolean G_admin_listplayers( gentity_t *ent ) p->pers.netname, ( registeredname ) ? "(a.k.a. " : "", ( registeredname ) ? registeredname : "", - ( registeredname ) ? S_COLOR_WHITE ")" : "" ) ); + ( registeredname ) ? S_COLOR_WHITE ")" : "" ) ) ; } ADMBP_end(); @@ -2454,6 +2485,7 @@ qboolean G_admin_adminhelp( gentity_t *ent ) qboolean G_admin_admintest( gentity_t *ent ) { g_admin_level_t *l; + char *title; if( !ent ) { @@ -2463,12 +2495,19 @@ qboolean G_admin_admintest( gentity_t *ent ) l = G_admin_level( ent->client->pers.admin ? ent->client->pers.admin->level : 0 ); - AP( va( "print \"^3admintest: ^7%s^7 is a level %d admin %s%s^7%s\n\"", + if( !l ) + return qfalse; + + if( ent->client->pers.admin && + Q_stricmp( ent->client->pers.admin->title, "" ) ) + title = ent->client->pers.admin->title; + else + title = l->name; + + AP( va( "print \"^3admintest: ^7%s^7 is %s^7 (level %d)\n\"", ent->client->pers.netname, - l ? l->level : 0, - l ? "(" : "", - l ? l->name : "", - l ? ")" : "" ) ); + title, + l->level ) ); return qtrue; } @@ -2931,6 +2970,21 @@ qboolean G_admin_lock( gentity_t *ent ) command, BG_TeamName( team ), lock ? "" : "un", ent ? ent->client->pers.netname : "console" ) ); + if( team == TEAM_ALIENS ) + { + if( lock ) + trap_SendServerCommand( -1, "announce alienslocked" ); + else + trap_SendServerCommand( -1, "announce aliensunlocked" ); + } + else + { + if( lock ) + trap_SendServerCommand( -1, "announce humanslocked" ); + else + trap_SendServerCommand( -1, "announce humansunlocked" ); + } + return qtrue; } @@ -3276,3 +3330,172 @@ void G_admin_cleanup( void ) g_admin_commands = NULL; BG_DefragmentMemory( ); } + +/* +================ +G_admin_settitle +================ +*/ +qboolean G_admin_settitle( gentity_t *ent ) +{ + char title[ MAX_ADMIN_TITLE ]; + char name[ MAX_NAME_LENGTH ]; + char testname[ MAX_NAME_LENGTH ]; + int i; + gentity_t *vic = NULL; + g_admin_admin_t *a = NULL; + g_admin_level_t *l = NULL; + int na; + int len; + + + if( trap_Argc() < 3 ) + { + ADMP( "^3settitle: ^7usage: settitle [name|slot#] [title]\n" ); + return qfalse; + } + + trap_Argv( 1, testname, sizeof( testname ) ); + trap_Argv( 2, title, sizeof( title ) ); + + for( na = 0, a = g_admin_admins; a; na++, a = a->next ); + for( i = 0; testname[ i ] && isdigit( testname[ i ] ); i++ ); + if( !testname[ i ] ) + { + int id = atoi( testname ); + if( id < MAX_CLIENTS ) + { + vic = &g_entities[ id ]; + if( !vic || !vic->client || vic->client->pers.connected == CON_DISCONNECTED ) + { + ADMP( va( "^3settitle: ^7no player connected in slot %d\n", id ) ); + return qfalse; + } + } + else if( id < na + MAX_CLIENTS ) + for( i = 0, a = g_admin_admins; i < id - MAX_CLIENTS; i++, a = a->next ); + else + { + ADMP( va( "^3settitle: ^7%s not in range 1-%d\n", + testname, na + MAX_CLIENTS - 1 ) ); + return qfalse; + } + } + else + G_SanitiseString( testname, name, sizeof( name ) ); + + if( vic ) + a = vic->client->pers.admin; + else if( !a ) + { + g_admin_admin_t *wa; + int matches = 0; + + for( wa = g_admin_admins; wa && matches < 2; wa = wa->next ) + { + G_SanitiseString( wa->name, testname, sizeof( testname ) ); + if( strstr( testname, name ) ) + { + a = wa; + matches++; + } + } + + for( i = 0; i < level.maxclients && matches < 2; i++ ) + { + if( level.clients[ i ].pers.connected == CON_DISCONNECTED ) + continue; + + if( matches && level.clients[ i ].pers.admin && + level.clients[ i ].pers.admin == a ) + { + vic = &g_entities[ i ]; + continue; + } + + G_SanitiseString( level.clients[ i ].pers.netname, testname, + sizeof( testname ) ); + if( strstr( testname, name ) ) + { + vic = &g_entities[ i ]; + a = vic->client->pers.admin; + matches++; + } + } + + if( matches == 0 ) + { + ADMP( "^3settitle:^7 no match. use listplayers or listadmins to " + "find an appropriate number to use instead of name.\n" ); + return qfalse; + } + if( matches > 1 ) + { + ADMP( "^3settitle:^7 more than one match. Use the admin number " + "instead:\n" ); + admin_listadmins( ent, 0, name ); + return qfalse; + } + } + + if( !a ) + { + ADMP( "^3settitle: ^7indented victim has no admin record\n" ); + return qfalse; + } + + if( ent && admin_higher_admin( a, ent->client->pers.admin ) ) + { + ADMP( "^3settitle: ^7indented victim is immune to your actions\n" ); + return qfalse; + } + + Q_strncpyz( a->title, title, sizeof( title ) ); + + len = Q_PrintStrlen( a->title ); + if( len > admin_level_maxname ) + admin_level_maxname = len; + + AP( va( "print \"^3settitle: ^7%s^7 was granted the title '%s^7' by %s^7\n\"", + a->name, a->title, ( ent ) ? ent->client->pers.netname : "console" ) ); + + admin_writeconfig(); + return qtrue; +} + +/* +================ +G_admin_register +================ +*/ +qboolean G_admin_register( gentity_t *ent ) +{ + if( !ent ) + return qfalse; + + if( !ent->client->pers.admin ) + { + g_admin_admin_t *a; + + for( a = g_admin_admins; a && a->next; a = a->next ); + + if( a ) + a = a->next = BG_Alloc( sizeof( g_admin_admin_t ) ); + else + a = g_admin_admins = BG_Alloc( sizeof( g_admin_admin_t ) ); + + ent->client->pers.admin = a; + Q_strncpyz( a->guid, ent->client->pers.guid, sizeof( a->guid ) ); + a->level = g_adminRegisterLevel.integer; + + AP( va( "print \"^3register: ^7'%s'^7 is now a registered nickname\n\"", ent->client->pers.netname ) ); + } + else + ADMP( "^3register: ^7you have updated your nick protection" ); + + Q_strncpyz( ent->client->pers.admin->name, + ent->client->pers.netname, + sizeof( ent->client->pers.admin->name ) ); + + return qtrue; +} diff --git a/src/game/g_admin.h b/src/game/g_admin.h index 8024fc8..9a0fedf 100644 --- a/src/game/g_admin.h +++ b/src/game/g_admin.h @@ -35,6 +35,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define MAX_ADMIN_FLAGS 1024 #define MAX_ADMIN_CMD_LEN 20 #define MAX_ADMIN_BAN_REASON 50 +#define MAX_ADMIN_TITLE 30 /* * IMMUNITY - cannot be vote kicked, vote muted @@ -50,7 +51,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * INCOGNITO - does not show up as an admin in !listplayers * ALLFLAGS - all flags (including command flags) apply to this player * ADMINCHAT - receieves and can send /a admin messages - * ALWAYSFRIEND - always marked as a friendly entity during buildgames */ #define ADMF_IMMUNITY "IMMUNITY" #define ADMF_NOCENSORFLOOD "NOCENSORFLOOD" @@ -66,8 +66,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define ADMF_ALLFLAGS "ALLFLAGS" #define ADMF_ADMINCHAT "ADMINCHAT" -#define ADMF_ALWAYSFRIEND "ALWAYSFRIEND" - #define MAX_ADMIN_LISTITEMS 20 #define MAX_ADMIN_SHOWBANS 10 @@ -100,6 +98,7 @@ typedef struct g_admin_admin char guid[ 33 ]; char name[ MAX_NAME_LENGTH ]; char flags[ MAX_ADMIN_FLAGS ]; + char title[ MAX_ADMIN_TITLE ]; } g_admin_admin_t; @@ -186,6 +185,10 @@ qboolean G_admin_builder( gentity_t *ent ); qboolean G_admin_buildlog( gentity_t *ent ); qboolean G_admin_revert( gentity_t *ent ); +qboolean G_admin_settitle( gentity_t *ent ); +qboolean G_admin_register( gentity_t *ent ); + + void G_admin_print( gentity_t *ent, char *m ); void G_admin_buffer_print( gentity_t *ent, char *m ); void G_admin_buffer_begin( void ); diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c index c9c6213..ef5a864 100644 --- a/src/game/g_cmds.c +++ b/src/game/g_cmds.c @@ -1572,7 +1572,7 @@ void Cmd_CallVote_f( gentity_t *ent ) G_Vote( ent, team, qtrue ); level.voteAborted[ team ] = qfalse; - trap_SendServerCommand( -1, "voteevent votenow" ); + trap_SendServerCommand( -1, "announce votenow" ); } /* @@ -3295,9 +3295,16 @@ void Cmd_Damage_f( gentity_t *ent ) Cmd_Debug1_f ================= */ -void Cmd_Debug1_f( gentity_t *ent ) +void Cmd_Debug1_f( gentity_t *self ) { - AddScore( ent, random() * 15000.0f ); + gentity_t *ent; + ent = G_TempEntity( self->r.currentOrigin, EV_OBITUARY ); + ent->s.eventParm = MOD_MACHINEGUN; + ent->s.otherEntityNum = self->s.number; + ent->s.modelindex = self->client->ps.stats[ STAT_CLASS ]; + ent->s.otherEntityNum2 = 1; + ent->s.groundEntityNum = 666; + ent->r.svFlags = SVF_BROADCAST; // send to everyone } /* diff --git a/src/game/g_combat.c b/src/game/g_combat.c index a9e8e68..1b6708f 100644 --- a/src/game/g_combat.c +++ b/src/game/g_combat.c @@ -235,7 +235,7 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int { gentity_t *ent, *ent2; int anim; - int killer; + int killer, killerHP; int i; char *killerName, *obit; vec3_t dir; @@ -254,14 +254,17 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int killer = attacker->s.number; if( attacker->client ) - killerName = attacker->client->pers.netname; + killerName = attacker->client->pers.netname, + killerHP = attacker->health; else - killerName = "<world>"; + killerName = "<world>", + killerHP = 0; } else { killer = ENTITYNUM_WORLD; killerName = "<world>"; + killerHP = 0; } if( meansOfDeath < 0 || meansOfDeath >= sizeof( modNames ) / sizeof( modNames[0] ) ) @@ -287,7 +290,9 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int ent = G_TempEntity( self->r.currentOrigin, EV_OBITUARY ); ent->s.eventParm = meansOfDeath; ent->s.otherEntityNum = self->s.number; + ent->s.modelindex = self->client->ps.stats[ STAT_CLASS ]; ent->s.otherEntityNum2 = killer; + ent->s.groundEntityNum = killerHP; ent->r.svFlags = SVF_BROADCAST; // send to everyone self->enemy = attacker; diff --git a/src/game/g_local.h b/src/game/g_local.h index f836875..3bd8642 100644 --- a/src/game/g_local.h +++ b/src/game/g_local.h @@ -1209,6 +1209,7 @@ extern vmCvar_t g_emoticonsAllowedInNames; extern vmCvar_t g_admin; extern vmCvar_t g_adminTempBan; extern vmCvar_t g_adminMaxBan; +extern vmCvar_t g_adminRegisterLevel; extern vmCvar_t g_privateMessages; extern vmCvar_t g_specChat; diff --git a/src/game/g_main.c b/src/game/g_main.c index 7775fc8..1750e26 100644 --- a/src/game/g_main.c +++ b/src/game/g_main.c @@ -138,6 +138,7 @@ vmCvar_t g_emoticonsAllowedInNames; vmCvar_t g_admin; vmCvar_t g_adminTempBan; vmCvar_t g_adminMaxBan; +vmCvar_t g_adminRegisterLevel; vmCvar_t g_privateMessages; vmCvar_t g_specChat; @@ -281,6 +282,7 @@ static cvarTable_t gameCvarTable[ ] = { &g_admin, "g_admin", "admin.dat", CVAR_ARCHIVE, 0, qfalse }, { &g_adminTempBan, "g_adminTempBan", "2m", CVAR_ARCHIVE, 0, qfalse }, { &g_adminMaxBan, "g_adminMaxBan", "2w", CVAR_ARCHIVE, 0, qfalse }, + { &g_adminRegisterLevel, "g_adminRegisterLevel", "1", CVAR_ARCHIVE, 0, qfalse }, { &g_privateMessages, "g_privateMessages", "1", CVAR_ARCHIVE, 0, qfalse }, { &g_specChat, "g_specChat", "1", CVAR_ARCHIVE, 0, qfalse }, @@ -1220,6 +1222,7 @@ void G_CalculateBuildPoints( void ) G_LogPrintf( "Beginning Sudden Death\n" ); trap_SendServerCommand( -1, "cp \"Sudden Death!\"" ); trap_SendServerCommand( -1, "print \"Beginning Sudden Death.\n\"" ); + trap_SendServerCommand( -1, "announce suddendeath" ); level.suddenDeathWarning = TW_PASSED; G_ClearDeconMarks( ); @@ -1237,6 +1240,7 @@ void G_CalculateBuildPoints( void ) (int)( G_TimeTilSuddenDeath( ) / 1000 ) ) ); trap_SendServerCommand( -1, va( "print \"Sudden Death will begin in %d seconds.\n\"", (int)( G_TimeTilSuddenDeath( ) / 1000 ) ) ); + trap_SendServerCommand( -1, "announce sdimminent" ); level.suddenDeathWarning = TW_IMMINENT; } @@ -2112,6 +2116,7 @@ void CheckExitRules( void ) { level.lastWin = TEAM_NONE; trap_SendServerCommand( -1, "print \"Timelimit hit\n\"" ); + trap_SendServerCommand( -1, "announce stalemate" ); trap_SetConfigstring( CS_WINNER, "Stalemate" ); LogExit( "Timelimit hit." ); return; @@ -2120,12 +2125,14 @@ void CheckExitRules( void ) level.timelimitWarning < TW_IMMINENT ) { trap_SendServerCommand( -1, "cp \"5 minutes remaining!\"" ); + trap_SendServerCommand( -1, "announce 5minremain" ); level.timelimitWarning = TW_IMMINENT; } else if( level.time - level.startTime >= ( g_timelimit.integer - 1 ) * 60000 && level.timelimitWarning < TW_PASSED ) { trap_SendServerCommand( -1, "cp \"1 minute remaining!\"" ); + trap_SendServerCommand( -1, "announce 1minremains" ); level.timelimitWarning = TW_PASSED; } } @@ -2140,6 +2147,7 @@ void CheckExitRules( void ) //humans win level.lastWin = TEAM_HUMANS; trap_SendServerCommand( -1, "print \"Humans win\n\""); + trap_SendServerCommand( -1, "announce humanswin" ); trap_SetConfigstring( CS_WINNER, "Humans Win" ); LogExit( "Humans win." ); } @@ -2152,6 +2160,7 @@ void CheckExitRules( void ) //aliens win level.lastWin = TEAM_ALIENS; trap_SendServerCommand( -1, "print \"Aliens win\n\""); + trap_SendServerCommand( -1, "announce alienswin" ); trap_SetConfigstring( CS_WINNER, "Aliens Win" ); LogExit( "Aliens win." ); } @@ -2265,15 +2274,15 @@ void G_CheckVote( team_t team ) if( pass ) { if( !level.voteAborted[ team ] ) - trap_SendServerCommand( -1, "voteevent votepassed" ); + trap_SendServerCommand( -1, "announce votepassed" ); level.voteExecuteTime[ team ] = level.time + level.voteDelay[ team ]; } else { if( !level.voteAborted[ team ] ) - trap_SendServerCommand( -1, "voteevent votefailed" ); + trap_SendServerCommand( -1, "announce votefailed" ); else - trap_SendServerCommand( -1, "voteevent votecancelled" ); + trap_SendServerCommand( -1, "announce votecancelled" ); } G_LogPrintf( "EndVote: %s %s %d %d %d %f %f\n", diff --git a/src/game/g_svcmds.c b/src/game/g_svcmds.c index 16cb6b8..da32326 100644 --- a/src/game/g_svcmds.c +++ b/src/game/g_svcmds.c @@ -285,11 +285,13 @@ static void Svcmd_AdmitDefeat_f( void ) { G_TeamCommand( TEAM_ALIENS, "cp \"Hivemind Link Broken\" 1"); trap_SendServerCommand( -1, "print \"Alien team has admitted defeat\n\"" ); + trap_SendServerCommand( -1, "announce aliensadmit" ); } else if( team == TEAM_HUMANS ) { G_TeamCommand( TEAM_HUMANS, "cp \"Life Support Terminated\" 1"); trap_SendServerCommand( -1, "print \"Human team has admitted defeat\n\"" ); + trap_SendServerCommand( -1, "announce humansadmit" ); } else { @@ -324,6 +326,7 @@ static void Svcmd_TeamWin_f( void ) static void Svcmd_Evacuation_f( void ) { trap_SendServerCommand( -1, "print \"Evacuation ordered\n\"" ); + trap_SendServerCommand( -1, "announce stalemate" ); level.lastWin = TEAM_NONE; trap_SetConfigstring( CS_WINNER, "Evacuation" ); LogExit( "Evacuation." ); |