sunder2.1/clan/
sunder2.1/class/
sunder2.1/class/bak/
sunder2.1/doc/ideas/
sunder2.1/gods/
sunder2.1/log/
sunder2.1/msgbase/
sunder2.1/src/o/
sunder2.1/time/
/**********************************************************
 *************** S U N D E R M U D *** 2 . 0 **************
 **********************************************************
 * The unique portions of the SunderMud code as well as   *
 * the integration efforts for code from other sources is *
 * based primarily on the efforts of:                     *
 *                                                        *
 * Lotherius <aelfwyne@operamail.com> (Alvin W. Brinson)  *
 *    and many others, see "help sundermud" in the mud.   *
 **********************************************************/

/* channels.c
*  Zeran - major cleanup of the channel code resides in this file.
*          Adding a channel can be done by simply adding an entry
*          into channel_table and calling channel_message from
*          the parent function (ie, do_gossip, do_say, do_foo etc)
*/

#include "everything.h"

/* local functions */
int                 channel_lookup ( char *argument );

/* Zeran - channel structure and declaration */
struct channel_type
{
     char               *name;
     char               *pre_str_speaker;
     char               *pre_str_receiver;
     char               *format_str;
     bool                use_language;
     bool                use_drunk;
     bool                check_nochannel;
     bool                check_quiet;
     bool                mob_trigger;
     int                 pos;
     int                 min_level;
     int                 channel_id;
     long		 chan_flag;
};

struct channel_type channel_table[] =
{

/*  { "name", "pre_str_speaker", "pre_str_receiver", "format",
		language, drunk, nochannel, quiet,
		mob_trigger, pos, min_level, channel_id, channel_flag
	},
*/
     {"gossip", "{cYou gossip", "{c$n gossips", "'{C$t{c'{x",
               FALSE, FALSE, TRUE, TRUE,
               FALSE, POS_SLEEPING, 1, CHAN_GOSSIP, COMM_NOGOSSIP
     },

     {"auction", "{yYou auction", "{y$n auctions", "'{Y$t{y'{x",
               FALSE, FALSE, TRUE, TRUE,
               FALSE, POS_SLEEPING, 1, CHAN_AUCTION, COMM_NOAUCTION
     },

     {"music", "{mYou sing", "{m$n sings", "'{M$t{m'{x",
               FALSE, FALSE, TRUE, TRUE,
               FALSE, POS_DEAD, 1, CHAN_MUSIC, COMM_NOMUSIC
     },

     {"question", "{gYou question", "{g$n questions", "'{G$t{g'{x",
               FALSE, FALSE, TRUE, TRUE,
               FALSE, POS_DEAD, 1, CHAN_QUESTION, COMM_NOQUESTION
     },

     {"answer", "{gYou answer", "{g$n answers", "'{G$t{g'{x",
               FALSE, FALSE, TRUE, TRUE,
               FALSE, POS_DEAD, 1, CHAN_ANSWER, COMM_NOQUESTION
     },

     {"shout", "{xYou shout", "{x$n shouts", "'{x$t{x'{x",
               FALSE, FALSE, TRUE, TRUE,
               FALSE, POS_RESTING, 1, CHAN_SHOUT, COMM_DEAF
     },

     {"yell", "{xYou yell", "{x$n yells", "'{x$t{x'{x",
               FALSE, FALSE, TRUE, TRUE,
               FALSE, POS_RESTING, 1, CHAN_YELL, 0
     },

     {"immtalk", "{c[{Y$n{c]:", "{c[{Y$n{c]:", "{c$t{x",
               FALSE, FALSE, FALSE, TRUE,
               FALSE, POS_DEAD, LEVEL_HERO, CHAN_IMMTALK, 0
     },

     {"imptalk", "[{rI{gM{bP{x] [{Y$n{x]:",
               "[{rI{gM{bP{x] [{Y$n{x]:", "{Y$t{x",
               FALSE, FALSE, FALSE, FALSE,
               FALSE, POS_DEAD, MAX_LEVEL, CHAN_IMPTALK, 0
     },

     {"say", "{gYou say", "{g$n says", "'{G$t{g'{x",
               TRUE, TRUE, FALSE, FALSE,
               TRUE, POS_RESTING, 1, CHAN_SAY, 0
     },

     {"clantalk", "{rYou tell the clan", "{r$n tells the clan",
               "'{R$t{r'{x",
               FALSE, FALSE, TRUE, TRUE,
               FALSE, POS_SLEEPING, 1, CHAN_CLAN, COMM_NOCLANTELL
     },

     {"", "", "", "", FALSE, FALSE, FALSE, FALSE, FALSE, 0, 0, 0}

};

void channel_message ( CHAR_DATA * ch, char *argument, char *channel )
{
     DESCRIPTOR_DATA    *d;
     char                buf_to_speaker[MAX_STRING_LENGTH];
     char                buf_to_receiver[MAX_STRING_LENGTH];
     char                lang_name[MAX_STRING_LENGTH];
     char               *pre_str_speaker;
     char               *pre_str_receiver;
     char               *format_str;
     char               *outbuf = NULL;
     char                tmpbuf[MAX_STRING_LENGTH];
     bool                use_language;
     bool                use_drunk_speech;
     bool                do_mob_trigger;
     bool                check_quiet;
     bool                check_nochannel;
     int                 pos;
     int                 lang_skill = 0;
     int                 channel_no = -1;
     int                 channel_id;
     int		 chan_flag;
     int                 min_level;

     tmpbuf[0] = '\0';

     channel_no = channel_lookup ( channel );
     if ( channel_no == -1 )
     {
          bugf ( "Invalid channel [%s] in channel_message", channel );
          return;
     }

     /* Ok, get the values from the channel table that we need */
     pre_str_speaker = channel_table[channel_no].pre_str_speaker;
     pre_str_receiver = channel_table[channel_no].pre_str_receiver;
     format_str = channel_table[channel_no].format_str;
     use_language = channel_table[channel_no].use_language;
     use_drunk_speech = channel_table[channel_no].use_drunk;
     check_quiet = channel_table[channel_no].check_quiet;
     check_nochannel = channel_table[channel_no].check_nochannel;
     do_mob_trigger = channel_table[channel_no].mob_trigger;
     min_level = channel_table[channel_no].min_level;
     pos = channel_table[channel_no].pos;
     channel_id = channel_table[channel_no].channel_id;
     chan_flag = channel_table[channel_no].chan_flag;

     /* Check quiet and nochannel settings */
     if ( check_quiet && IS_SET ( ch->comm, COMM_QUIET ) )
     {
          send_to_char ( "You must turn off quiet mode first.\n\r", ch );
          return;
     }
     if ( check_quiet && IS_SET ( ch->comm, COMM_NOCHANNELS ) )
     {
          send_to_char  ( "The gods have revoked your channel priviliges.\n\r", ch );
          return;
     }
     // Imms like to make ppl noshout, this isn't checked elsewhere.
     if ( channel_id == CHAN_SHOUT && IS_SET ( ch->comm, COMM_NOSHOUT ) )
     {
          send_to_char ( "You find your voice very scratchy, and can't shout. Odd, that.\n\r", ch );
          return;
     }

     // Hey Z why didn't you just move this here instead of also having it in 40 diff places?
     if ( argument[0] == '\0' && chan_flag != 0 )
     {
          if ( IS_SET ( ch->comm, chan_flag ) )
          {
               form_to_char ( ch, "%s is now ON.\n\r",
                              capitalize ( channel_table[channel_no].name ) );
               REMOVE_BIT ( ch->comm, chan_flag);
          }
          else
          {
               form_to_char ( ch, "%s is now OFF.\n\r",
                              capitalize ( channel_table[channel_no].name ) );
               SET_BIT ( ch->comm, chan_flag );
          }
          return;
     }
     if ( !IS_NPC ( ch ) ) // Make sure channel is on for the speaker.
          REMOVE_BIT ( ch->comm, chan_flag );

     /* Build message to speaker */
     if ( use_language )
     {
          if ( !IS_NPC ( ch ) )
               SNP ( lang_name, "%s tongue", ch->speaking );
          else
               SNP ( lang_name, "common tongue" );
          SNP ( buf_to_speaker, "%s in %s %s",
                    pre_str_speaker, lang_name, format_str );
     }
     else
          SNP ( buf_to_speaker, "%s %s",
                    pre_str_speaker, format_str );

     /* Send message to speaker */
     act_new ( buf_to_speaker, ch, argument, NULL, TO_CHAR, POS_DEAD );

     /* Build message to receivers */
     /* Scramble for language if speaker is NOT NPC */
     if ( use_language )
     {
          lang_skill = skill_lookup ( lang_name );
          if ( !IS_NPC ( ch ) )
               argument = scramble ( argument, ch->pcdata->learned[lang_skill] );
          SNP ( buf_to_receiver, "%s in %s %s", pre_str_receiver,
                    lang_name, format_str );
     }
     else
          SNP ( buf_to_receiver, "%s %s",
                    pre_str_receiver, format_str );

     /* Set outbuf to point to argument */
     SLCPY ( tmpbuf, argument );

     /* Ok, send the messages */
     for ( d = descriptor_list; d != NULL; d = d->next )
     {
          CHAR_DATA          *victim;

          if ( d->connected != CON_PLAYING || d->connected >= CON_NOTE_TO )
               continue;
          /* You would not believe how hard the bug that led to the above two lines */
          /* was to track down. */

          victim = d->original ? d->original : d->character;

          /* Check for something freaky - Lotherius */
          /* This was for some obscure bug I finally axxed, I think. Leaving it here in case it shows back up. */
          if (!victim)
          {
               send_to_char (":1: We were about to crash! Aborted instead. Report to imms.\n\r", ch);
               bugf ( "Null victim in channel_message found." );
               return;
          }

          /* List of checks to skip current receiver */
          if ( d->character != ch )
          {

               /* Check quiet */
               if ( check_quiet && IS_SET ( victim->comm, COMM_QUIET ) )
                    continue;

               /* Check minimum level */
               if ( get_trust ( victim ) < min_level && victim->level < min_level )
                    continue;

               /* Channel dependent exclusions */
               switch ( channel_id )
               {
               case CHAN_GOSSIP:
                    {
                         if ( IS_SET ( victim->comm, COMM_NOGOSSIP ) )
                              continue;
                         break;
                    }
               case CHAN_MUSIC:
                    {
                         if ( IS_SET ( victim->comm, COMM_NOMUSIC ) )
                              continue;
                         break;
                    }
               case CHAN_AUCTION:
                    {
                         if ( IS_SET ( victim->comm, COMM_NOAUCTION ) )
                              continue;
                         break;
                    }
               case CHAN_QUESTION:
                    {
                         if ( IS_SET ( victim->comm, COMM_NOQUESTION ) )
                              continue;
                         break;
                    }
               case CHAN_ANSWER:
                    {
                         if ( IS_SET ( victim->comm, COMM_NOQUESTION ) )
                              continue;
                         break;
                    }
               case CHAN_IMMTALK:
                    {
                         if ( IS_SET ( victim->comm, COMM_NOWIZ ) )
                              continue;
                         break;
                    }
               case CHAN_IMPTALK:
                    {
                         break;
                    }
               case CHAN_YELL:
                    {
                         if ( victim->in_room->area != ch->in_room->area )
                              continue;
                         break;
                    }
               case CHAN_SHOUT:
                    {
                         if ( IS_SET ( victim->comm, COMM_DEAF ) )
                              continue;
                         break;
                    }
               case CHAN_SAY:
                    {
                         if ( victim->in_room && ( victim->in_room != ch->in_room ) )
                              continue;
                         break;
                    }
               case CHAN_CLAN:
                    {
                         if ( IS_SET ( victim->comm, COMM_NOCLANTELL ) )
                              continue;
                         if ( !is_same_clan(victim, ch) )
                              continue;
                         break;
                    }
               default:
                    {
                         bugf( "Invalid channel_id [%d] in channel_message", channel_id );
                         return;
                    }
               }
               /* end switch */
          }

          /* end if */

          /* Check for something freaky */
          if (!victim)
          {
               send_to_char (":2: We were about to crash! Aborted instead. Report to imms.\n\r", ch);
               continue;
          }

          /* Check language and drunk, then send the message */
          if ( (!IS_NPC (victim) ) && (use_language) )
               outbuf = scramble ( tmpbuf, victim->pcdata->learned[lang_skill] );
          else
               outbuf = tmpbuf;

          if ( ( use_drunk_speech ) && (!IS_NPC (victim) ) )
               outbuf = drunk_speech ( outbuf, ch );

          act_new ( buf_to_receiver, ch, outbuf, d->character, TO_VICT, pos );

     }
     /* end for descriptor loop */

     // Moved this elsewhere... I think... -- Lotherius
     //    if ( do_mob_trigger )
     //	mprog_speech_trigger ( argument, ch );

}
/* end channel_message */

void do_channels ( CHAR_DATA * ch, char *argument )
{
     /* lists all channels and their status */
     send_to_char ("Use the new \"config\" command.\n\r", ch);
     return;

}

int channel_lookup ( char *argument )
{
     int                 count = 0;

     while ( channel_table[count].name[0] != '\0' )
     {
          if ( !str_cmp ( channel_table[count].name, argument ) )
               return count;
          count++;
     }
     return -1;
}