diff options
author | Tony J. White <tjw@tjw.org> | 2009-10-03 11:45:20 +0000 |
---|---|---|
committer | Tim Angus <tim@ngus.net> | 2013-01-03 00:15:18 +0000 |
commit | 412d3c9c3479012d687139f891d14cfe18b6e6ee (patch) | |
tree | c8ca701ac8e4ef8cac3a35fbe8460b058e25bbda /src/game | |
parent | a60e24850d73f8d807bab40f256a3e017219f17e (diff) |
* UI_Text_* emoticon drawing support (e.g. [dretch] draws
/emoticons/dretch.tga inline with text)
* emoticons are square .tga images placed in the /emoticons dir of fs_game
* emoticons should probably be 64x64 to look nice
* g_emoticonsAllowedInNames (default ON) is an optional server setting to
prevent players from using them in names
* emoticons can be escaped by prefixing with an additional [
* cvars ui_emoticons and cg_emoticons can be set to 0 to disable drawing
of emoticons in ui or cgame contexts respectively
* fix color code continuation on wrapped lines
* prefix all wrapped lines with a space to prevent chat shenanigans
Diffstat (limited to 'src/game')
-rw-r--r-- | src/game/bg_misc.c | 61 | ||||
-rw-r--r-- | src/game/bg_public.h | 1 | ||||
-rw-r--r-- | src/game/g_client.c | 57 | ||||
-rw-r--r-- | src/game/g_local.h | 5 | ||||
-rw-r--r-- | src/game/g_main.c | 6 |
5 files changed, 127 insertions, 3 deletions
diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c index 9f8ce9e4..244ee482 100644 --- a/src/game/bg_misc.c +++ b/src/game/bg_misc.c @@ -31,6 +31,7 @@ void trap_FS_Read( void *buffer, int len, fileHandle_t f ); void trap_FS_Write( const void *buffer, int len, fileHandle_t f ); void trap_FS_FCloseFile( fileHandle_t f ); void trap_FS_Seek( fileHandle_t f, long offset, fsOrigin_t origin ); // fsOrigin_t +int trap_FS_GetFileList( const char *path, const char *extension, char *listbuf, int bufsize ); static const buildableAttributes_t bg_buildableList[ ] = { @@ -3855,3 +3856,63 @@ weapon_t BG_PrimaryWeapon( int stats[ ] ) return WP_NONE; } +/* +============ +BG_LoadEmoticons +============ +*/ +int BG_LoadEmoticons( char names[ ][ MAX_EMOTICON_NAME_LEN ] ) +{ + int numFiles; + char fileList[ MAX_EMOTICONS * ( MAX_EMOTICON_NAME_LEN + 5 ) ] = {""}; + int i; + char *filePtr; + int fileLen; + char emoticon[ MAX_EMOTICON_NAME_LEN + 5 ] = {""}; + int loaded = 0; + int count; + + numFiles = trap_FS_GetFileList( "emoticons", ".tga", fileList, + sizeof( fileList ) ); + + if( numFiles < 1 ) + return 0; + + filePtr = fileList; + fileLen = 0; + count = 0; + for( i = 0; i < numFiles; i++, filePtr += fileLen + 1 ) + { + if( count >= MAX_EMOTICONS ) + { + count++; + continue; + } + + fileLen = strlen( filePtr ); + if( fileLen > MAX_EMOTICON_NAME_LEN + 5 ) + { + Com_Printf( S_COLOR_YELLOW "WARNING: MAX_EMOTICON_NAME_LEN is %d. " + "skipping \"%s\", filename too long", MAX_EMOTICON_NAME_LEN, filePtr ); + continue; + } + if( !trap_FS_FOpenFile( va( "emoticons/%s", filePtr ), NULL, FS_READ ) ) + { + Com_Printf( S_COLOR_YELLOW "WARNING: BG_LoadEmoticons(): detected " + " an unreadable .tga file name \"emoticons/%s\" in emoticon detection", + filePtr ); + break; + } + Q_strncpyz( emoticon, filePtr, sizeof( emoticon ) ); + emoticon[ fileLen - 4 ] = '\0'; + + Q_strncpyz( names[ count ], emoticon, sizeof( names[ count ] ) ); + count++; + loaded = count; + } + + Com_Printf( "Loaded %d of %d emoticons (MAX_EMOTICONS is %d)\n", + loaded, count, MAX_EMOTICONS ); + return loaded; +} + diff --git a/src/game/bg_public.h b/src/game/bg_public.h index 1e1c98ac..2a6f1874 100644 --- a/src/game/bg_public.h +++ b/src/game/bg_public.h @@ -1298,3 +1298,4 @@ voiceTrack_t *BG_VoiceTrackFind( voiceTrack_t *head, team_t team, class_t class, weapon_t weapon, int enthusiasm, int *trackNum ); +int BG_LoadEmoticons( char names[ ][ MAX_EMOTICON_NAME_LEN ] ); diff --git a/src/game/g_client.c b/src/game/g_client.c index 0e8051b8..4d674905 100644 --- a/src/game/g_client.c +++ b/src/game/g_client.c @@ -764,16 +764,54 @@ void respawn( gentity_t *ent ) } } +static qboolean G_IsEmoticon( const char *s, qboolean *escaped ) +{ + int i, j; + const char *p = s; + char emoticon[ MAX_EMOTICON_NAME_LEN ] = {""}; + qboolean escape = qfalse; + + if( *p != '[' ) + return qfalse; + p++; + if( *p == '[' ) + { + escape = qtrue; + p++; + } + i = 0; + while( *p && i < ( MAX_EMOTICON_NAME_LEN - 1 ) ) + { + if( *p == ']' ) + { + for( j = 0; j < level.emoticonCount; j++ ) + { + if( !Q_stricmp( emoticon, level.emoticons[ j ] ) ) + { + *escaped = escape; + return qtrue; + } + } + return qfalse; + } + emoticon[ i++ ] = *p; + emoticon[ i ] = '\0'; + p++; + } + return qfalse; +} + /* =========== -ClientCleanName +G_ClientCleanName ============ */ -static void ClientCleanName( const char *in, char *out, int outSize ) +static void G_ClientCleanName( const char *in, char *out, int outSize ) { int len, colorlessLen; char *p; int spaces; + qboolean escaped; //save room for trailing null byte outSize--; @@ -808,6 +846,19 @@ static void ClientCleanName( const char *in, char *out, int outSize ) len += 2; continue; } + else if( !g_emoticonsAllowedInNames.integer && G_IsEmoticon( in, &escaped ) ) + { + // make sure room in dest for both chars + if( len > outSize - 2 ) + break; + + *out++ = '['; + *out++ = '['; + len += 2; + if( escaped ) + in++; + continue; + } // don't allow too many consecutive spaces if( *in == ' ' ) @@ -942,7 +993,7 @@ void ClientUserinfoChanged( int clientNum ) // set name Q_strncpyz( oldname, client->pers.netname, sizeof( oldname ) ); s = Info_ValueForKey( userinfo, "name" ); - ClientCleanName( s, newname, sizeof( newname ) ); + G_ClientCleanName( s, newname, sizeof( newname ) ); if( strcmp( oldname, newname ) ) { diff --git a/src/game/g_local.h b/src/game/g_local.h index db15d208..05f1fe21 100644 --- a/src/game/g_local.h +++ b/src/game/g_local.h @@ -619,6 +619,9 @@ typedef struct team_t surrenderTeam; voice_t *voices; + + char emoticons[ MAX_EMOTICONS ][ MAX_EMOTICON_NAME_LEN ]; + int emoticonCount; } level_locals_t; #define CMD_CHEAT 0x01 @@ -1142,6 +1145,8 @@ extern vmCvar_t g_mapConfigs; extern vmCvar_t g_layouts; extern vmCvar_t g_layoutAuto; +extern vmCvar_t g_emoticonsAllowedInNames; + extern vmCvar_t g_admin; extern vmCvar_t g_adminLog; extern vmCvar_t g_adminParseSay; diff --git a/src/game/g_main.c b/src/game/g_main.c index 34793cb2..e3db3c23 100644 --- a/src/game/g_main.c +++ b/src/game/g_main.c @@ -124,6 +124,8 @@ vmCvar_t g_chatTeamPrefix; vmCvar_t g_layouts; vmCvar_t g_layoutAuto; +vmCvar_t g_emoticonsAllowedInNames; + vmCvar_t g_admin; vmCvar_t g_adminLog; vmCvar_t g_adminParseSay; @@ -244,6 +246,8 @@ static cvarTable_t gameCvarTable[ ] = { &g_layouts, "g_layouts", "", CVAR_LATCH, 0, qfalse }, { &g_layoutAuto, "g_layoutAuto", "1", CVAR_ARCHIVE, 0, qfalse }, + + { &g_emoticonsAllowedInNames, "g_emoticonsAllowedInNames", "1", CVAR_LATCH|CVAR_ARCHIVE, 0, qfalse }, { &g_admin, "g_admin", "admin.dat", CVAR_ARCHIVE, 0, qfalse }, { &g_adminLog, "g_adminLog", "admin.log", CVAR_ARCHIVE, 0, qfalse }, @@ -603,6 +607,8 @@ void G_InitGame( int levelTime, int randomSeed, int restart ) trap_LocateGameData( level.gentities, level.num_entities, sizeof( gentity_t ), &level.clients[ 0 ].ps, sizeof( level.clients[ 0 ] ) ); + level.emoticonCount = BG_LoadEmoticons( level.emoticons ); + trap_SetConfigstring( CS_INTERMISSION, "0" ); // test to see if a custom buildable layout will be loaded |