/***************************************************************************** *---------------------------------------------------------------------------* * LoP (C) 2006, 2007, 2008 by: the LoP team. * *---------------------------------------------------------------------------* * Dynamic Channel Handler * *****************************************************************************/ #include <ctype.h> #include <stdio.h> #include <stdarg.h> #include <string.h> #include <time.h> #include <sys/time.h> #include "h/mud.h" void add_phistory( int type, CHAR_DATA *ch, char *argument ); char *drunk_speech( const char *argument, CHAR_DATA *ch ); #define CHANNEL_DIR "channels/" #define CHANNEL_FILE CHANNEL_DIR "channels.dat" typedef struct chistory_data CHISTORY_DATA; typedef struct channel_data CHANNEL_DATA; CHANNEL_DATA *first_channel, *last_channel; struct chistory_data { CHISTORY_DATA *next, *prev; char *name; char *text; char *restrict; time_t chtime; int speaking; }; struct channel_data { CHANNEL_DATA *next, *prev; CHISTORY_DATA *first_chistory, *last_chistory; char *name; char *color; int type; int permission; int currhistory; int maxhistory; }; int bug_report = 0; bool check_is_ignoring( CHAR_DATA *ch, char *name ) { IGNORE_DATA *temp; if( is_npc( ch ) ) return false; for( temp = ch->pcdata->first_ignored; temp; temp = temp->next ) { if( nifty_is_name( temp->name, name ) ) return true; } return false; } void save_chistory( CHANNEL_DATA *channel ) { CHISTORY_DATA *chistory; FILE *fp; char filename[MSL]; if( !channel ) return; sprintf( filename, "%s%s", CHANNEL_DIR, channel->name ); if( !channel->first_chistory ) { remove_file( filename ); return; } if( !( fp = fopen( filename, "w" ) ) ) { if( ++bug_report > 1 ) return; bug( "%s: Can't open %s for writing.", __FUNCTION__, filename ); perror( filename ); return; } bug_report = 0; for( chistory = channel->first_chistory; chistory; chistory = chistory->next ) { if( !chistory->text ) continue; fprintf( fp, "%s", "#CHISTORY\n" ); if( chistory->name ) fprintf( fp, "Name %s~\n", chistory->name ); fprintf( fp, "Time %ld\n", chistory->chtime ); if( chistory->speaking != -1 ) fprintf( fp, "Speaking %d\n", chistory->speaking ); fprintf( fp, "Text %s~\n", chistory->text ); if( chistory->restrict ) fprintf( fp, "Restrict %s~\n", chistory->restrict ); fprintf( fp, "%s", "End\n\n" ); } fprintf( fp, "%s", "#END\n" ); fclose( fp ); fp = NULL; } void save_all_chistorys( void ) { CHANNEL_DATA *channel; for( channel = first_channel; channel; channel = channel->next ) save_chistory( channel ); } void save_channels( void ) { CHANNEL_DATA *channel; FILE *fp; if( !( fp = fopen( CHANNEL_FILE, "w" ) ) ) { bug( "%s: Can't open %s for writing.", __FUNCTION__, CHANNEL_FILE ); perror( CHANNEL_FILE ); return; } for( channel = first_channel; channel; channel = channel->next ) { fprintf( fp, "%s", "#CHANNEL\n" ); fprintf( fp, "Name %s~\n", channel->name ); fprintf( fp, "Color %s~\n", channel->color ); if( channel->type >= 0 && channel->type < CHANNEL_MAX ) fprintf( fp, "Type %s~\n", channelflags[channel->type] ); if( channel->permission >= 0 && channel->permission < PERM_MAX ) fprintf( fp, "Permission %s~\n", perms_flag[channel->permission] ); fprintf( fp, "MaxHistory %d\n", channel->maxhistory ); fprintf( fp, "%s", "End\n\n" ); } fprintf( fp, "%s", "#END\n" ); fclose( fp ); fp = NULL; } void free_chistory( CHISTORY_DATA *chistory ) { if( !chistory ) return; STRFREE( chistory->name ); STRFREE( chistory->text ); STRFREE( chistory->restrict ); DISPOSE( chistory ); } void free_channel( CHANNEL_DATA *channel ) { CHISTORY_DATA *chistory, *chistory_next; if( !channel ) return; STRFREE( channel->name ); STRFREE( channel->color ); for( chistory = channel->first_chistory; chistory; chistory = chistory_next ) { chistory_next = chistory->next; UNLINK( chistory, channel->first_chistory, channel->last_chistory, next, prev ); free_chistory( chistory ); } DISPOSE( channel ); } CHANNEL_DATA *get_channel( char *argument ) { CHANNEL_DATA *channel; for( channel = first_channel; channel; channel = channel->next ) { if( !str_cmp( channel->name, argument ) ) { return channel; } } return NULL; } void show_chistory( CHAR_DATA *ch, CHANNEL_DATA *channel, bool showall ) { CHISTORY_DATA *chistory; bool found = false; if( !ch || !channel ) return; for( chistory = channel->first_chistory; chistory; chistory = chistory->next ) { if( !showall && chistory->restrict && ch->pcdata ) { if( channel->type == CHANNEL_RACETALK && ( !race_table[ch->race] || str_cmp( chistory->restrict, race_table[ch->race]->name ) ) ) continue; if( channel->type == CHANNEL_CLASS && ( !class_table[ch->Class] || str_cmp( chistory->restrict, class_table[ch->Class]->name ) ) ) continue; if( channel->type == CHANNEL_CLAN && ( !ch->pcdata || !ch->pcdata->clan || str_cmp( chistory->restrict, ch->pcdata->clan->name ) ) ) continue; if( channel->type == CHANNEL_NATION && ( !ch->pcdata || !ch->pcdata->nation || str_cmp( chistory->restrict, ch->pcdata->nation->name ) ) ) continue; if( channel->type == CHANNEL_COUNCIL && ( !ch->pcdata || !ch->pcdata->council || str_cmp( chistory->restrict, ch->pcdata->council->name ) ) ) continue; if( channel->type == CHANNEL_YELL && ( !ch->in_room || !ch->in_room->area || str_cmp( chistory->restrict, ch->in_room->area->name ) ) ) continue; if( channel->type == CHANNEL_LOG && get_trust( ch ) < atoi( chistory->restrict ) ) continue; } if( !showall && chistory->name && check_is_ignoring( ch, chistory->name ) ) continue; found = true; ch_printf( ch, "%s[%s]", channel->color ? channel->color : "&[plain]", distime( chistory->chtime ) ); if( chistory->name ) { if( !str_cmp( ch->name, chistory->name ) ) ch_printf( ch, " You %s", channel->name ); else ch_printf( ch, " %s %ss", chistory->name, channel->name ); } send_to_char( " ' ", ch ); if( chistory->speaking == -1 ) send_to_char( chistory->text, ch ); else { int speakswell = knows_language( ch, chistory->speaking ); char *sbuf = chistory->text; if( speakswell < 85 ) sbuf = translate( speakswell, chistory->text, lang_names[chistory->speaking] ); send_to_char( sbuf, ch ); } ch_printf( ch, " &D%s'\r\n", channel->color ? channel->color : "&[plain]" ); } if( !found ) ch_printf( ch, "Nothing has been said on %s.\r\n", channel->name ); } CMDF( do_setchannel ) { CHANNEL_DATA *channel; char arg[MIL], arg2[MIL]; int col = 0; if( !argument || argument[0] == '\0' ) { send_to_char( "Usage: setchannel <channel>\r\n", ch ); send_to_char( "Usage: setchannel <channel> create/delete/clearhistory\r\n", ch ); send_to_char( "Usage: setchannel <channel> name/color/type/perm/maxhistory <setting>\r\n", ch ); for( channel = first_channel; channel; channel = channel->next ) { ch_printf( ch, "%s[%3d]", channel->color ? channel->color : "&[plain]", channel->currhistory ); ch_printf( ch, "%-20.20s", channel->name ); if( ++col == 3 ) { col = 0; send_to_char( "\r\n", ch ); } } if( col != 0 ) send_to_char( "\r\n", ch ); return; } argument = one_argument( argument, arg ); argument = one_argument( argument, arg2 ); channel = get_channel( arg ); if( !arg2 || arg2[0] == '\0' ) { if( !channel ) { ch_printf( ch, "No channel by the name of %s.\r\n", arg ); return; } ch_printf( ch, "&CName: &W%s\r\n", channel->name ); ch_printf( ch, "&CColor: %sColored&D\r\n", channel->color ); ch_printf( ch, "&CType: &W%s\r\n", channelflags[channel->type] ); ch_printf( ch, "&CPerm: &W%s\r\n", perms_flag[channel->permission] ); ch_printf( ch, "&CHistory: &W%d\r\n", channel->currhistory ); ch_printf( ch, "&CMaxhistory: &W%d&D\r\n", channel->maxhistory ); send_to_char( "Full channel history:\r\n", ch ); show_chistory( ch, channel, true ); return; } if( !str_cmp( arg2, "create" ) ) { if( channel ) { ch_printf( ch, "There is already a channel named %s.\r\n", channel->name ); return; } CREATE( channel, CHANNEL_DATA, 1 ); channel->name = STRALLOC( arg ); channel->color = STRALLOC( "&[plain]" ); channel->type = CHANNEL_GLOBAL; channel->permission = PERM_ALL; channel->maxhistory = 20; channel->currhistory = 0; channel->first_chistory = channel->last_chistory = NULL; LINK( channel, first_channel, last_channel, next, prev ); save_channels( ); ch_printf( ch, "%s channel created.\r\n", channel->name ); return; } if( !channel ) { ch_printf( ch, "No channel by the name of %s.\r\n", arg ); return; } if( !str_cmp( arg2, "delete" ) ) { UNLINK( channel, first_channel, last_channel, next, prev ); free_channel( channel ); save_channels( ); ch_printf( ch, "%s channel has been deleted.\r\n", arg ); return; } if( !str_cmp( arg2, "clearhistory" ) ) { char filename[MSL]; CHISTORY_DATA *chistory, *chistory_next; for( chistory = channel->first_chistory; chistory; chistory = chistory_next ) { chistory_next = chistory->next; UNLINK( chistory, channel->first_chistory, channel->last_chistory, next, prev ); free_chistory( chistory ); } sprintf( filename, "%s%s", CHANNEL_DIR, channel->name ); remove_file( filename ); channel->currhistory = 0; ch_printf( ch, "%s's history has been cleared.\r\n", channel->name ); return; } if( !str_cmp( arg2, "color" ) ) { STRSET( channel->color, argument ); save_channels( ); ch_printf( ch, "%s's color has been set.\r\n", channel->name ); return; } if( !str_cmp( arg2, "type" ) ) { int value = get_flag( argument, channelflags, CHANNEL_MAX ); if( value < 0 || value >= CHANNEL_MAX ) { send_to_char( "Invalid channel type.\r\n", ch ); return; } channel->type = value; save_channels( ); ch_printf( ch, "%s type has been set to %s.\r\n", channel->name, channelflags[channel->type] ); return; } if( !str_cmp( arg2, "perm" ) ) { int value = get_flag( argument, perms_flag, PERM_MAX ); if( value < 0 || value >= PERM_MAX ) { send_to_char( "Invalid permission.\r\n", ch ); return; } channel->permission = value; save_channels( ); ch_printf( ch, "%s permission has been set to %s.\r\n", channel->name, perms_flag[channel->permission] ); return; } if( !str_cmp( arg2, "maxhistory" ) ) { channel->maxhistory = atoi( argument ); channel->maxhistory = URANGE( 0, channel->maxhistory, 100 ); save_channels( ); ch_printf( ch, "%s maxhistory has been set to %d.\r\n", channel->name, channel->maxhistory ); return; } if( !str_cmp( arg2, "name" ) ) { STRSET( channel->name, argument ); save_channels( ); ch_printf( ch, "%s channel has been changed to %s.\r\n", arg, channel->name ); return; } do_setchannel( ch, "" ); } void fread_chistory( CHANNEL_DATA *channel, FILE *fp ) { const char *word; bool fMatch; CHISTORY_DATA *chistory; CREATE( chistory, CHISTORY_DATA, 1 ); chistory->name = NULL; chistory->text = NULL; chistory->restrict = NULL; chistory->speaking = -1; for( ;; ) { word = feof( fp ) ? "End" : fread_word( fp ); fMatch = false; switch( UPPER( word[0] ) ) { case '*': fMatch = true; fread_to_eol( fp ); break; case 'E': if( !str_cmp( word, "End" ) ) { LINK( chistory, channel->first_chistory, channel->last_chistory, next, prev ); channel->currhistory++; return; } break; case 'N': KEY( "Name", chistory->name, fread_string( fp ) ); break; case 'R': KEY( "Restrict", chistory->restrict, fread_string( fp ) ); break; case 'S': KEY( "Speaking", chistory->speaking, fread_number( fp ) ); break; case 'T': KEY( "Text", chistory->text, fread_string( fp ) ); KEY( "Time", chistory->chtime, fread_time( fp ) ); break; } if( !fMatch ) { bug( "%s: no match: %s", __FUNCTION__, word ); fread_to_eol( fp ); } } free_chistory( chistory ); } void load_chistorys( CHANNEL_DATA *channel ) { FILE *fp; char filename[MSL]; if( !channel || !channel->name ) return; sprintf( filename, "%s%s", CHANNEL_DIR, channel->name ); if( !( fp = fopen( filename, "r" ) ) ) return; for( ;; ) { char letter; char *word; letter = fread_letter( fp ); if( letter == '*' ) { fread_to_eol( fp ); continue; } if( letter != '#' ) { bug( "%s: # not found.", __FUNCTION__ ); break; } word = fread_word( fp ); if( !str_cmp( word, "CHISTORY" ) ) { fread_chistory( channel, fp ); continue; } else if( !str_cmp( word, "END" ) ) break; else { bug( "%s: bad section (%s).", __FUNCTION__, word ); fread_to_eol( fp ); continue; } } fclose( fp ); fp = NULL; } void fread_channel( FILE *fp ) { const char *word; char *infoflags, flag[MIL]; bool fMatch; CHANNEL_DATA *channel; int value; CREATE( channel, CHANNEL_DATA, 1 ); channel->name = NULL; channel->type = CHANNEL_GLOBAL; channel->permission = PERM_ALL; channel->maxhistory = 0; channel->currhistory = 0; channel->first_chistory = channel->last_chistory = NULL; for( ;; ) { word = feof( fp ) ? "End" : fread_word( fp ); fMatch = false; switch( UPPER( word[0] ) ) { case '*': fMatch = true; fread_to_eol( fp ); break; case 'C': KEY( "Color", channel->color, fread_string( fp ) ); break; case 'E': if( !str_cmp( word, "End" ) ) { if( !channel->color ) channel->color = STRALLOC( "&[plain]" ); LINK( channel, first_channel, last_channel, next, prev ); load_chistorys( channel ); return; } break; case 'M': KEY( "MaxHistory", channel->maxhistory, fread_number( fp ) ); break; case 'N': KEY( "Name", channel->name, fread_string( fp ) ); break; case 'P': SKEY( "Permission", channel->permission, fp, perms_flag, PERM_MAX ); break; case 'T': SKEY( "Type", channel->type, fp, channelflags, CHANNEL_MAX ); break; } if( !fMatch ) { bug( "%s: no match: %s", __FUNCTION__, word ); fread_to_eol( fp ); } } free_channel( channel ); } void load_channels( void ) { FILE *fp; first_channel = last_channel = NULL; if( !( fp = fopen( CHANNEL_FILE, "r" ) ) ) return; for( ;; ) { char letter; char *word; letter = fread_letter( fp ); if( letter == '*' ) { fread_to_eol( fp ); continue; } if( letter != '#' ) { bug( "%s: # not found.", __FUNCTION__ ); break; } word = fread_word( fp ); if( !str_cmp( word, "CHANNEL" ) ) { fread_channel( fp ); continue; } else if( !str_cmp( word, "END" ) ) break; else { bug( "%s: bad section (%s).", __FUNCTION__, word ); fread_to_eol( fp ); continue; } } fclose( fp ); fp = NULL; } void free_all_channels( void ) { CHANNEL_DATA *channel, *channel_next; for( channel = first_channel; channel; channel = channel_next ) { channel_next = channel->next; UNLINK( channel, first_channel, last_channel, next, prev ); free_channel( channel ); } } void add_to_history( CHANNEL_DATA *channel, CHAR_DATA *ch, int trust, int speaking, char *argument ) { CHISTORY_DATA *chistory, *chistory_next, *chistory_remove = NULL; int y = 0; if( !channel || !argument || argument[0] == '\0' ) return; if( !channel->first_chistory && channel->maxhistory <= 0 ) return; for( chistory = channel->first_chistory; chistory; chistory = chistory_next ) { chistory_next = chistory->next; if( chistory->restrict && ch && ch->pcdata ) { if( channel->type == CHANNEL_RACETALK && ( !race_table[ch->race] || str_cmp( chistory->restrict, race_table[ch->race]->name ) ) ) continue; if( channel->type == CHANNEL_CLASS && ( !class_table[ch->Class] || str_cmp( chistory->restrict, class_table[ch->Class]->name ) ) ) continue; if( channel->type == CHANNEL_CLAN && ( !ch->pcdata || !ch->pcdata->clan || str_cmp( chistory->restrict, ch->pcdata->clan->name ) ) ) continue; if( channel->type == CHANNEL_NATION && ( !ch->pcdata || !ch->pcdata->nation || str_cmp( chistory->restrict, ch->pcdata->nation->name ) ) ) continue; if( channel->type == CHANNEL_COUNCIL && ( !ch->pcdata || !ch->pcdata->council || str_cmp( chistory->restrict, ch->pcdata->council->name ) ) ) continue; if( channel->type == CHANNEL_YELL && ( !ch->in_room || !ch->in_room->area || str_cmp( chistory->restrict, ch->in_room->area->name ) ) ) continue; } if( !chistory_remove ) chistory_remove = chistory; if( ++y >= channel->maxhistory ) { UNLINK( chistory_remove, channel->first_chistory, channel->last_chistory, next, prev ); free_chistory( chistory_remove ); channel->currhistory--; chistory_remove = NULL; y--; } } if( channel->maxhistory <= 0 ) return; chistory = NULL; CREATE( chistory, CHISTORY_DATA, 1 ); chistory->speaking = speaking; smash_tilde( argument ); chistory->text = STRALLOC( argument ); chistory->restrict = NULL; if( ch ) { chistory->name = STRALLOC( ch->name ); if( channel->type == CHANNEL_RACETALK && race_table[ch->race] ) chistory->restrict = STRALLOC( race_table[ch->race]->name ); if( channel->type == CHANNEL_CLASS && class_table[ch->Class] ) chistory->restrict = STRALLOC( class_table[ch->Class]->name ); if( channel->type == CHANNEL_CLAN && ch->pcdata && ch->pcdata->clan && ch->pcdata->clan->name ) chistory->restrict = STRALLOC( ch->pcdata->clan->name ); if( channel->type == CHANNEL_NATION && ch->pcdata && ch->pcdata->nation && ch->pcdata->nation->name ) chistory->restrict = STRALLOC( ch->pcdata->nation->name ); if( channel->type == CHANNEL_COUNCIL && ch->pcdata && ch->pcdata->council && ch->pcdata->council->name ) chistory->restrict = STRALLOC( ch->pcdata->council->name ); if( channel->type == CHANNEL_YELL && ch->in_room && ch->in_room->area && ch->in_room->area->name ) chistory->restrict = STRALLOC( ch->in_room->area->name ); if( channel->type == CHANNEL_LOG ) { char buf[MSL]; snprintf( buf, sizeof( buf ), "%d", get_trust( ch ) ); chistory->restrict = STRALLOC( buf ); } } else if( channel->type == CHANNEL_LOG && trust ) { char buf[MSL]; snprintf( buf, sizeof( buf ), "%d", trust ); chistory->restrict = STRALLOC( buf ); } chistory->chtime = current_time; LINK( chistory, channel->first_chistory, channel->last_chistory, next, prev ); channel->currhistory++; save_chistory( channel ); } bool can_use_channel( CHAR_DATA *ch, CHANNEL_DATA *channel ) { if( !channel ) return false; if( !ch ) return true; if( get_trust( ch ) < channel->permission ) return false; if( channel->type == CHANNEL_RACETALK && !race_table[ch->race] ) return false; if( channel->type == CHANNEL_CLASS && !class_table[ch->Class] ) return false; if( channel->type == CHANNEL_CLAN && ( !ch->pcdata || !ch->pcdata->clan ) ) return false; if( channel->type == CHANNEL_NATION && ( !ch->pcdata || !ch->pcdata->nation ) ) return false; if( channel->type == CHANNEL_COUNCIL && ( !ch->pcdata || !ch->pcdata->council ) ) return false; if( channel->type == CHANNEL_YELL && ( !ch->in_room || !ch->in_room->area ) ) return false; return true; } CMDF( do_channels ) { CHANNEL_DATA *channel; int col = 0; if( !ch ) return; for( channel = first_channel; channel; channel = channel->next ) { if( !can_use_channel( ch, channel ) ) continue; ch_printf( ch, "%s%20.20s", channel->color ? channel->color : "&[plain]", channel->name ); if( ++col == 4 ) { col = 0; send_to_char( "\r\n", ch ); } } if( col != 0 ) send_to_char( "\r\n", ch ); } bool is_listening( CHAR_DATA *ch, CHANNEL_DATA *channel ) { char *listening, chan[MIL]; if( !ch || !channel ) return false; listening = ch->pcdata->channels; while( listening && listening[0] != '\0' ) { listening = one_argument( listening, chan ); if( !str_cmp( channel->name, chan ) ) return true; } return false; } bool handle_channels( CHAR_DATA *ch, CHANNEL_DATA *channel, int trust, char *argument ) { DESCRIPTOR_DATA *d, *d_next; PER_HISTORY *phistory; char buf[MSL], hbuf[MSL], thbuf[MSL]; int speaking = -1, lang; if( !channel ) return false; if( !ch && ( !argument || argument[0] == '\0' ) ) return false; if( ch && !can_use_channel( ch, channel ) ) return false; hbuf[0] = '\0'; if( ch ) { if( !argument || argument[0] == '\0' || channel->type == CHANNEL_LOG ) { if( !is_npc( ch ) && channel->type == CHANNEL_YELL ) { if( !ch->pcdata->first_yell ) send_to_char( "You haven't heard anyone yell.\r\n", ch ); else { for( phistory = ch->pcdata->first_yell; phistory; phistory = phistory->next ) send_to_char( phistory->text, ch ); } return true; } show_chistory( ch, channel, false ); return true; } for( lang = 0; lang_array[lang] != LANG_UNKNOWN; lang++ ) { if( xIS_SET( ch->speaking, lang_array[lang] ) ) { speaking = lang; break; } } ch_printf( ch, "%sYou %s ' %s &D%s'\r\n", channel->color ? channel->color : "&[plain]", channel->name, argument, channel->color ? channel->color : "&[plain]" ); snprintf( buf, sizeof( buf ), "%s%s %ss ' %s &D%s'\r\n", channel->color ? channel->color : "&[plain]", ch->name, channel->name, argument, channel->color ? channel->color : "&[plain]" ); if( channel->type == CHANNEL_YELL ) snprintf( hbuf, sizeof( hbuf ), "%s%s yelled ' %s &D%s'\r\n", channel->color ? channel->color : "&[plain]", capitalize( is_npc( ch ) ? ch->short_descr : ch->name ), argument, channel->color ? channel->color : "&[plain]" ); } else { snprintf( buf, sizeof( buf ), "%s%s: %s\r\n", channel->color, channel->name, argument ); if( channel->type == CHANNEL_YELL ) snprintf( hbuf, sizeof( hbuf ), "%s%s yelled ' %s &D%s'\r\n", channel->color ? channel->color : "&[plain]", ch ? ( capitalize( is_npc( ch ) ? ch->short_descr : ch->name ) ) : "Unknown", argument, channel->color ? channel->color : "&[plain]" ); } add_to_history( channel, ch, trust, speaking, argument ); for( d = first_descriptor; d; d = d_next ) { d_next = d->next; if( !d->character ) continue; if( ch && d->character == ch ) continue; if( !can_use_channel( d->character, channel ) ) continue; if( ch && ch->pcdata && d->character && d->character->pcdata ) { if( channel->type == CHANNEL_RACETALK && ch->race != d->character->race ) continue; if( channel->type == CHANNEL_CLASS && ch->Class != d->character->Class ) continue; if( channel->type == CHANNEL_CLAN && ch->pcdata->clan != d->character->pcdata->clan ) continue; if( channel->type == CHANNEL_NATION && ch->pcdata->nation != d->character->pcdata->nation ) continue; if( channel->type == CHANNEL_COUNCIL && ch->pcdata->council != d->character->pcdata->council ) continue; if( channel->type == CHANNEL_YELL && ( !ch->in_room || !d->character->in_room || ch->in_room->area != d->character->in_room->area ) ) continue; } if( channel->type == CHANNEL_LOG && get_trust( d->character ) < ( ch ? get_trust( ch ) : trust ) ) continue; if( !is_listening( d->character, channel ) ) continue; /* Check to see if character is ignoring speaker */ if( ch && d->character && is_ignoring( d->character, ch ) ) { /* continue unless speaker is an immortal */ if( !is_immortal( ch ) || get_trust( d->character ) > get_trust( ch ) ) continue; else { set_char_color( AT_IGNORE, d->character ); ch_printf( d->character, "You attempt to ignore %s, but are unable to do so.\r\n", ch->name ); } } if( speaking == -1 ) { send_to_char( buf, d->character ); snprintf( thbuf, sizeof( thbuf ), "%s", hbuf ); } else { int speakswell = knows_language( d->character, speaking ); char *sbuf = argument; if( speakswell < 85 ) sbuf = translate( speakswell, argument, lang_names[speaking] ); if( ch ) { sbuf = drunk_speech( sbuf, ch ); snprintf( buf, sizeof( buf ), "%s%s %ss ' %s &D%s'\r\n", channel->color ? channel->color : "&[plain]", ch->name, channel->name, sbuf, channel->color ? channel->color : "&[plain]" ); } else snprintf( buf, sizeof( buf ), "%s%s: %s\r\n", channel->color, channel->name, sbuf ); send_to_char( buf, d->character ); if( channel->type == CHANNEL_YELL ) snprintf( thbuf, sizeof( thbuf ), "%s%s yelled ' %s &D%s'\r\n", channel->color ? channel->color : "&[plain]", capitalize( is_npc( ch ) ? ch->short_descr : ch->name ), sbuf, channel->color ? channel->color : "&[plain]" ); } if( channel->type == CHANNEL_YELL ) { if( !is_npc( d->character ) ) add_phistory( 2, d->character, thbuf ); } } return true; } bool check_channel( CHAR_DATA *ch, char *command, char *argument ) { CHANNEL_DATA *channel; for( channel = first_channel; channel; channel = channel->next ) { if( !channel->name ) continue; if( ch && !can_use_channel( ch, channel ) ) continue; if( !str_prefix( command, channel->name ) ) { handle_channels( ch, channel, get_trust( ch ), argument ); return true; } } return false; } /* Writes a string to the log, extended version - Thoric */ void log_string_plus( const char *str, short log_type, int level ) { CHANNEL_DATA *channel; struct timeval now_time; /* Update time. */ gettimeofday( &now_time, NULL ); current_time = ( time_t ) now_time.tv_sec; current_time += ( time_t ) TIME_MODIFY; fprintf( stderr, "%s :: %s\n", distime( current_time ), str ); switch( log_type ) { default: if( ( channel = get_channel( "log" ) ) ) handle_channels( NULL, channel, level, ( char * )str ); break; case LOG_BUG: if( ( channel = get_channel( "bug" ) ) ) handle_channels( NULL, channel, level, ( char * )str ); break; case LOG_BUILD: if( ( channel = get_channel( "build" ) ) ) handle_channels( NULL, channel, level, ( char * )str ); break; case LOG_COMM: if( ( channel = get_channel( "comm" ) ) ) handle_channels( NULL, channel, level, ( char * )str ); break; case LOG_WARN: if( ( channel = get_channel( "warn" ) ) ) handle_channels( NULL, channel, level, ( char * )str ); break; case LOG_ALL: break; } } void log_printf_plus( short log_type, int level, const char *fmt, ... ) { char buf[MSL * 2]; va_list args; va_start( args, fmt ); vsnprintf( buf, sizeof( buf ), fmt, args ); va_end( args ); log_string_plus( buf, log_type, level ); } void log_printf( const char *fmt, ... ) { char buf[MSL * 2]; va_list args; va_start( args, fmt ); vsnprintf( buf, sizeof( buf ), fmt, args ); va_end( args ); log_string_plus( buf, LOG_NORMAL, PERM_LOG ); } void to_channel( char *argument, char *channel, int level ) { CHANNEL_DATA *chandata; if( argument[0] == '\0' ) return; if( ( chandata = get_channel( channel ) ) ) handle_channels( NULL, chandata, level, argument ); } void to_channel_printf( char *channel, int level, char *fmt, ... ) { char buf[MAX_STRING_LENGTH * 2]; va_list args; va_start( args, fmt ); vsnprintf( buf, MAX_STRING_LENGTH * 2, fmt, args ); va_end( args ); to_channel( buf, channel, level ); } CMDF( do_listen ) { CHANNEL_DATA *c; char arg[MIL]; if( !argument || argument[0] == '\0' ) { send_to_char( "&cCurrently tuned into:\r\n", ch ); if( ch->pcdata->channels ) { char *listening = ch->pcdata->channels; int col = 0; while( listening && listening[0] != '\0' ) { listening = one_argument( listening, arg ); ch_printf( ch, "&W%20.20s", arg ); if( ++col == 4 ) { col = 0; send_to_char( "\r\n", ch ); } } if( col != 0 ) send_to_char( "\r\n", ch ); } else send_to_char( "&WNone\r\n", ch ); { char chan_new[MSL]; char tmp_chan[MSL]; int col = 0; chan_new[0] = '\0'; for( c = first_channel; c; c = c->next ) { if( get_trust( ch ) >= c->permission ) { /* Listening to this channel? */ if( is_listening( ch, c ) ) continue; snprintf( tmp_chan, sizeof( tmp_chan ), "&R%20.20s", c->name ); mudstrlcat( chan_new, tmp_chan, sizeof( chan_new ) ); if( ++col == 4 ) { col = 0; mudstrlcat( chan_new, "\r\n", sizeof( chan_new ) ); } } } if( chan_new && chan_new[0] != '\0' ) { if( col != 0 ) mudstrlcat( chan_new, "\r\n", sizeof( chan_new ) ); send_to_char( "&cCurrently not listening to:\r\n", ch ); send_to_char( chan_new, ch ); } } return; } if( !str_cmp( argument, "all" ) ) { char chan_new[MSL]; chan_new[0] = '\0'; for( c = first_channel; c; c = c->next ) { if( get_trust( ch ) >= c->permission ) { if( chan_new && chan_new[0] != '\0' ) mudstrlcat( chan_new, " ", sizeof( chan_new ) ); mudstrlcat( chan_new, c->name, sizeof( chan_new ) ); } } if( !chan_new || chan_new[0] == '\0' ) send_to_char( "&YNo channels for you to listen to.\r\n", ch ); else { STRSET( ch->pcdata->channels, chan_new ); send_to_char( "&YYou are now listening to all available channels.\r\n", ch ); } return; } if( !str_cmp( argument, "none" ) ) { STRFREE( ch->pcdata->channels ); send_to_char( "&YYou no longer listen to any available channels.\r\n", ch ); return; } while( argument && argument[0] != '\0' ) { char *chan_buf, chan_tmp[MIL], chan_new[MSL]; bool cremoved = false; argument = one_argument( argument, arg ); if( !( c = get_channel( arg ) ) || get_trust( ch ) < c->permission ) { ch_printf( ch, "No channel named %s.\r\n", arg ); continue;; } chan_buf = ch->pcdata->channels; mudstrlcpy( chan_new, "", sizeof( chan_new ) ); while( chan_buf && chan_buf[0] != '\0' ) { chan_buf = one_argument( chan_buf, chan_tmp ); if( !str_cmp( chan_tmp, c->name ) ) cremoved = true; else { if( chan_new && chan_new[0] != '\0' ) mudstrlcat( chan_new, " ", sizeof( chan_new ) ); mudstrlcat( chan_new, chan_tmp, sizeof( chan_new ) ); } } if( cremoved ) ch_printf( ch, "You are no longer listening to %s.\r\n", c->name ); else { if( chan_new && chan_new[0] != '\0' ) mudstrlcat( chan_new, " ", sizeof( chan_new ) ); mudstrlcat( chan_new, c->name, sizeof( chan_new ) ); ch_printf( ch, "You are now listening to %s.\r\n", c->name ); } STRSET( ch->pcdata->channels, chan_new ); } }