LOP/
LOP/area/
LOP/boards/
LOP/channels/
LOP/clans/
LOP/classes/
LOP/color/
LOP/councils/
LOP/deity/
LOP/races/
LOP/src/specials/
/*****************************************************************************
 * DikuMUD (C) 1990, 1991 by:                                                *
 *   Sebastian Hammer, Michael Seifert, Hans Henrik Staefeldt, Tom Madsen,   *
 *   and Katja Nyboe.                                                        *
 *---------------------------------------------------------------------------*
 * MERC 2.1 (C) 1992, 1993 by:                                               *
 *   Michael Chastain, Michael Quan, and Mitchell Tse.                       *
 *---------------------------------------------------------------------------*
 * SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by: Derek Snider.                    *
 *   Team: Thoric, Altrag, Blodkai, Narn, Haus, Scryn, Rennard, Swordbearer, *
 *         gorog, Grishnakh, Nivek, Tricops, and Fireblade.                  *
 *---------------------------------------------------------------------------*
 * SMAUG 1.7 FUSS by: Samson and others of the SMAUG community.              *
 *                    Their contributions are greatly appreciated.           *
 *---------------------------------------------------------------------------*
 * LoP (C) 2006, 2007, 2008 by: the LoP team.                                *
 *---------------------------------------------------------------------------*
 *                           Deity handling module                           *
 *****************************************************************************/

/* Put together by Rennard for Realms of Despair.  Brap on...*/
#include <stdio.h>
#include "h/mud.h"

DEITY_DATA *first_deity, *last_deity;

/* local routines */
int get_pc_race( char *type );
int get_pc_class( char *Class );

void free_member( MEMBER_DATA *member );

void free_deity_worshippers( DEITY_DATA *deity )
{
   MEMBER_DATA *member, *member_next;

   if( !deity )
      return;
   for( member = deity->first_worshipper; member; member = member_next )
   {
      member_next = member->next;
      UNLINK( member, deity->first_worshipper, deity->last_worshipper, next, prev );
      free_member( member );
   }
}

bool is_deity_worshipper( DEITY_DATA *deity, char *name )
{
   MEMBER_DATA *member;

   if( !deity || !name || name[0] == '\0' )
      return false;
   for( member = deity->first_worshipper; member; member = member->next )
   {
      if( !str_cmp( member->name, name ) )
         return true;
   }
   return false;
}

void add_deity_worshipper( DEITY_DATA *deity, char *name )
{
   MEMBER_DATA *member;

   if( !deity || !name || name[0] == '\0' )
      return;
   if( is_deity_worshipper( deity, name ) )
      return;
   CREATE( member, MEMBER_DATA, 1 );
   member->name = STRALLOC( name );
   LINK( member, deity->first_worshipper, deity->last_worshipper, next, prev );
   if( ( deity->worshippers + 1 ) > 0 )
      deity->worshippers++;
}

bool remove_deity_worshipper( DEITY_DATA *deity, char *name )
{
   MEMBER_DATA *member;

   if( !deity || !name || name[0] == '\0' )
      return false;
   for( member = deity->first_worshipper; member; member = member->next )
   {
      if( !str_cmp( member->name, name ) )
      {
         UNLINK( member, deity->first_worshipper, deity->last_worshipper, next, prev );
         free_member( member );
         if( --deity->worshippers < 0 )
            deity->worshippers = 0;
         return true;
      }
   }
   return false;
}

void free_deity( DEITY_DATA *deity )
{
   UNLINK( deity, first_deity, last_deity, next, prev );
   free_deity_worshippers( deity );
   STRFREE( deity->name );
   STRFREE( deity->description );
   STRFREE( deity->filename );
   DISPOSE( deity );
}

void free_deities( void )
{
   DEITY_DATA *deity, *deity_next;

   for( deity = first_deity; deity; deity = deity_next )
   {
      deity_next = deity->next;
      free_deity( deity );
   }
}

/* Get pointer to deity structure from deity name */
DEITY_DATA *get_deity( char *name )
{
   DEITY_DATA *deity;

   for( deity = first_deity; deity; deity = deity->next )
      if( !str_cmp( name, deity->name ) )
         return deity;
   return NULL;
}

void write_deity_list( void )
{
   DEITY_DATA *deity;
   FILE *fp;

   if( !( fp = fopen( DEITY_LIST, "w" ) ) )
   {
      bug( "%s: FATAL: can't open %s for writing!", __FUNCTION__, DEITY_LIST );
      perror( DEITY_LIST );
      return;
   }
   for( deity = first_deity; deity; deity = deity->next )
      if( deity && deity->filename )
         fprintf( fp, "%s\n", deity->filename );
   fprintf( fp, "$\n" );
   fclose( fp );
   fp = NULL;
}

/* Save a deity's data to its data file */
void save_deity( DEITY_DATA *deity )
{
   FILE *fp;
   MEMBER_DATA *member;
   char filename[256];

   if( !deity )
   {
      bug( "%s: NULL deity!", __FUNCTION__ );
      return;
   }

   if( !deity->name )
   {
      bug( "%s: NULL deity name!", __FUNCTION__ );
      return;
   }

   if( !deity->filename )
   {
      bug( "%s: %s has no filename", __FUNCTION__, deity->name );
      return;
   }

   snprintf( filename, sizeof( filename ), "%s%s", DEITY_DIR, deity->filename );
   if( !( fp = fopen( filename, "w" ) ) )
   {
      bug( "%s: couldn't open %s for writing.", __FUNCTION__, filename );
      perror( filename );
      return;
   }

   fprintf( fp, "Filename     %s~\n", deity->filename );
   fprintf( fp, "Name         %s~\n", deity->name );
   if( deity->description )
      fprintf( fp, "Description  %s~\n", deity->description );
   if( !xIS_EMPTY( deity->affected ) )
      fprintf( fp, "Affected     %s~\n", ext_flag_string( &deity->affected, a_flags ) );
   if( !xIS_EMPTY( deity->resist ) )
      fprintf( fp, "Resist       %s~\n", ext_flag_string( &deity->resist, ris_flags ) );
   if( !xIS_EMPTY( deity->suscept ) )
      fprintf( fp, "Suscept      %s~\n", ext_flag_string( &deity->suscept, ris_flags ) );
   if( deity->alignment )
      fprintf( fp, "Alignment    %d\n", deity->alignment );
   if( deity->flee )
      fprintf( fp, "Flee         %d\n", deity->flee );
   if( deity->kill )
      fprintf( fp, "Kill         %d\n", deity->kill );
   if( deity->kill_magic )
      fprintf( fp, "Kill_magic   %d\n", deity->kill_magic );
   if( deity->sac )
      fprintf( fp, "Sac          %d\n", deity->sac );
   if( deity->bury_corpse )
      fprintf( fp, "Bury_corpse  %d\n", deity->bury_corpse );
   if( deity->aid_spell )
      fprintf( fp, "Aid_spell    %d\n", deity->aid_spell );
   if( deity->aid )
      fprintf( fp, "Aid          %d\n", deity->aid );
   if( deity->steal )
      fprintf( fp, "Steal        %d\n", deity->steal );
   if( deity->backstab )
      fprintf( fp, "Backstab     %d\n", deity->backstab );
   if( deity->die )
      fprintf( fp, "Die          %d\n", deity->die );
   if( deity->spell_aid )
      fprintf( fp, "Spell_aid    %d\n", deity->spell_aid );
   if( deity->dig_corpse )
      fprintf( fp, "Dig_corpse   %d\n", deity->dig_corpse );
   if( deity->scorpse )
      fprintf( fp, "Scorpse      %d\n", deity->scorpse );
   if( deity->savatar )
      fprintf( fp, "Savatar      %d\n", deity->savatar );
   if( deity->sdeityobj )
      fprintf( fp, "Sdeityobj    %d\n", deity->sdeityobj );
   if( deity->srecall )
      fprintf( fp, "Srecall      %d\n", deity->srecall );
   if( !xIS_EMPTY( deity->Class ) )
      fprintf( fp, "Class        %s~\n", ext_class_string( &deity->Class ) );
   if( !xIS_EMPTY( deity->race ) )
      fprintf( fp, "Race         %s~\n", ext_race_string( &deity->race ) );
   if( deity->sex )
      fprintf( fp, "Sex          %d\n", deity->sex );
   if( deity->susceptnum )
      fprintf( fp, "Susceptnum   %d\n", deity->susceptnum );
   if( deity->resistnum )
      fprintf( fp, "Resistnum    %d\n", deity->resistnum );
   if( deity->affectednum )
      fprintf( fp, "Affectednum  %d\n", deity->affectednum );
   if( deity->objvnum )
      fprintf( fp, "Objvnum      %d\n", deity->objvnum );
   if( deity->mobvnum )
      fprintf( fp, "Mobvnum      %d\n", deity->mobvnum );

   for( member = deity->first_worshipper; member; member = member->next )
      fprintf( fp, "Worshipper   %s~\n", member->name );

   fprintf( fp, "%s", "End\n" );
   fclose( fp );
   fp = NULL;
}

/* Read in actual deity data */
void fread_deity( DEITY_DATA *deity, FILE *fp )
{
   const char *word;
   bool fMatch;
   char *infoflags, flag[MIL];
   int value;

   CREATE( deity, DEITY_DATA, 1 );
   deity->sex = -1;
   deity->first_worshipper = NULL;
   deity->last_worshipper = NULL;
   deity->worshippers = 0;
   xCLEAR_BITS( deity->Class );
   xCLEAR_BITS( deity->race );
   xCLEAR_BITS( deity->suscept );
   xCLEAR_BITS( deity->resist );
   xCLEAR_BITS( deity->affected );

   for( ;; )
   {
      word = feof( fp ) ? "End" : fread_word( fp );
      fMatch = false;

      switch( UPPER( word[0] ) )
      {
         case '*':
            fMatch = true;
            fread_to_eol( fp );
            break;

         case 'A':
            WEXTKEY( "Affected", deity->affected, fp, a_flags, AFF_MAX );
            KEY( "Affectednum", deity->affectednum, fread_number( fp ) );
            KEY( "Aid", deity->aid, fread_number( fp ) );
            KEY( "Aid_spell", deity->aid_spell, fread_number( fp ) );
            KEY( "Alignment", deity->alignment, fread_number( fp ) );
            break;

         case 'B':
            KEY( "Backstab", deity->backstab, fread_number( fp ) );
            KEY( "Bury_corpse", deity->bury_corpse, fread_number( fp ) );
            break;

         case 'C':
            if( !str_cmp( word, "Class" ) )
            {
               int iclass;

               infoflags = fread_flagstring( fp );
               while( infoflags && infoflags[0] != '\0' )
               {
                  infoflags = one_argument( infoflags, flag );
                  for( iclass = 0; iclass < MAX_PC_CLASS; iclass++ )
                  {
                     if( !class_table[iclass] || !class_table[iclass]->name )
                        continue;
                     if( !str_cmp( class_table[iclass]->name, flag ) )
                     {
                        xSET_BIT( deity->Class, iclass );
                        break;
                     }
                  }
               }
               fMatch = true;
               break;
            }
            break;

         case 'D':
            KEY( "Description", deity->description, fread_string( fp ) );
            KEY( "Die", deity->die, fread_number( fp ) );
            KEY( "Dig_corpse", deity->dig_corpse, fread_number( fp ) );
            break;

         case 'E':
            if( !str_cmp( word, "End" ) )
            {
               LINK( deity, first_deity, last_deity, next, prev );
               return;
            }
            break;

         case 'F':
            KEY( "Filename", deity->filename, fread_string( fp ) );
            KEY( "Flee", deity->flee, fread_number( fp ) );
            break;

         case 'K':
            KEY( "Kill", deity->kill, fread_number( fp ) );
            KEY( "Kill_magic", deity->kill_magic, fread_number( fp ) );
            break;

         case 'M':
            KEY( "Mobvnum", deity->mobvnum, fread_number( fp ) );
            break;

         case 'N':
            KEY( "Name", deity->name, fread_string( fp ) );
            break;

         case 'O':
            KEY( "Objvnum", deity->objvnum, fread_number( fp ) );
            break;

         case 'R':
            WEXTKEY( "Resist", deity->resist, fp, ris_flags, RIS_MAX );
            KEY( "Resistnum", deity->resistnum, fread_number( fp ) );
            if( !str_cmp( word, "Race" ) )
            {
               int irace;

               infoflags = fread_flagstring( fp );
               while( infoflags && infoflags[0] != '\0' )
               {
                  infoflags = one_argument( infoflags, flag );
                  for( irace = 0; irace < MAX_PC_RACE; irace++ )
                  {
                     if( !race_table[irace] || !race_table[irace]->name )
                        continue;
                     if( !str_cmp( race_table[irace]->name, flag ) )
                     {
                        xSET_BIT( deity->race, irace );
                        break;
                     }
                  }
               }
               fMatch = true;
               break;
            }
            break;

         case 'S':
            KEY( "Sac", deity->sac, fread_number( fp ) );
            KEY( "Savatar", deity->savatar, fread_number( fp ) );
            KEY( "Scorpse", deity->scorpse, fread_number( fp ) );
            KEY( "Sdeityobj", deity->sdeityobj, fread_number( fp ) );
            KEY( "Srecall", deity->srecall, fread_number( fp ) );
            KEY( "Sex", deity->sex, fread_number( fp ) );
            KEY( "Spell_aid", deity->spell_aid, fread_number( fp ) );
            KEY( "Steal", deity->steal, fread_number( fp ) );
            WEXTKEY( "Suscept", deity->suscept, fp, ris_flags, RIS_MAX );
            KEY( "Susceptnum", deity->susceptnum, fread_number( fp ) );
            break;

         case 'W':
            if( !str_cmp( word, "Worshipper" ) )
            {
               char *name = fread_flagstring( fp );

               if( valid_pfile( name ) )
                  add_deity_worshipper( deity, name );
               else
                  bug( "%s: not adding worshipper %s because no pfile found.", __FUNCTION__, name );
               fMatch = true;
               break;
            }
            break;
      }

      if( !fMatch )
      {
         bug( "%s: no match: %s", __FUNCTION__, word );
         fread_to_eol( fp );
      }
   }
   free_deity( deity );
}

/* Load a deity file */
void load_deity_file( const char *deityfile )
{
   char filename[256];
   DEITY_DATA *deity;
   FILE *fp;

   snprintf( filename, sizeof( filename ), "%s%s", DEITY_DIR, deityfile );
   if( !( fp = fopen( filename, "r" ) ) )
   {
      bug( "%s: couldn't open %s for reading.", __FUNCTION__, filename );
      perror( filename );
      return;
   }

   fread_deity( deity, fp );

   fclose( fp );
   fp = NULL;
}

/* Load in all the deity files */
void load_deity( void )
{
   FILE *fp;
   const char *filename;

   first_deity = last_deity = NULL;

   log_string( "Loading deities..." );
   if( !( fp = fopen( DEITY_LIST, "r" ) ) )
   {
      bug( "%s: couldn't open %s for reading.", __FUNCTION__, DEITY_LIST );
      perror( DEITY_LIST );
      return;
   }

   for( ;; )
   {
      filename = feof( fp ) ? "$" : fread_word( fp );
      if( filename[0] == '$' )
         break;
      log_string( filename );
      load_deity_file( filename );
   }
   fclose( fp );
   fp = NULL;
   log_string( " Done loading deities " );
}

void show_deity( CHAR_DATA *ch, DEITY_DATA *deity )
{
   MEMBER_DATA *member;
   int cnt = 0;

   if( !ch || is_npc( ch ) )
      return;

   if( !deity )
   {
      send_to_char( "No such deity.\r\n", ch );
      return;
   }

   if( deity->name )
      ch_printf( ch, "Deity      : %s\r\n", deity->name );
   if( deity->filename )
      ch_printf( ch, "Filename   : %s\r\n", deity->filename );
   if( deity->description )
      ch_printf( ch, "Description:\r\n%s\r\n", deity->description );
   if( !xIS_EMPTY( deity->race ) )
      ch_printf( ch, "Races      : %s\r\n", ext_race_string( &deity->race ) );
   if( !xIS_EMPTY( deity->Class ) )
      ch_printf( ch, "Classes    : %s\r\n", ext_class_string( &deity->Class ) );
   if( deity->sex != -1 )
      ch_printf( ch, "Sex        : %s\r\n", sex_names[deity->sex] );

   ch_printf( ch, "Alignment  : %d\r\n", deity->alignment );
   ch_printf( ch, "Mobvnum    : %d\r\n", deity->mobvnum );
   ch_printf( ch, "Objvnum    : %d\r\n", deity->objvnum );
   if( !xIS_EMPTY( deity->affected ) )
   {
      ch_printf( ch, "Affected   : %s\r\n", ext_flag_string( &deity->affected, a_flags ) );
      ch_printf( ch, "Affectednum: %d\r\n", deity->affectednum );
   }
   if( !xIS_EMPTY( deity->suscept ) )
   {
      ch_printf( ch, "Suscept    : %s\r\n", ext_flag_string( &deity->suscept, ris_flags ) );
      ch_printf( ch, "Susceptnum : %d\r\n", deity->susceptnum );
   }
   if( !xIS_EMPTY( deity->resist ) )
   {
      ch_printf( ch, "Resist     : %s\r\n", ext_flag_string( &deity->resist, ris_flags ) );
      ch_printf( ch, "Resistnum  : %d\r\n", deity->resistnum );
   }
   ch_printf( ch, "Flee       : %d\r\n", deity->flee );
   ch_printf( ch, "Kill       : %-5d  Kill_magic: %d\r\n", deity->kill, deity->kill_magic );
   ch_printf( ch, "Aid        : %-5d  Aid_spell : %-5d  Spell_aid  : %d\r\n", deity->aid, deity->aid_spell, deity->spell_aid );
   ch_printf( ch, "Sac        : %d\r\n", deity->sac );
   ch_printf( ch, "Bury_corpse: %-5d  Dig_corpse: %d\r\n", deity->bury_corpse, deity->dig_corpse );
   ch_printf( ch, "Steal      : %d\r\n", deity->steal );
   ch_printf( ch, "Backstab   : %d\r\n", deity->backstab );
   ch_printf( ch, "Die        : %d\r\n", deity->die );
   ch_printf( ch, "Scorpse    : %d\r\n", deity->scorpse );
   ch_printf( ch, "Savatar    : %d\r\n", deity->savatar );
   ch_printf( ch, "Sdeityobj  : %d\r\n", deity->sdeityobj );
   ch_printf( ch, "Srecall    : %d\r\n", deity->srecall );

   ch_printf( ch, "Worshippers: %d\r\n", deity->worshippers );
   for( member = deity->first_worshipper; member; member = member->next )
   {
      ch_printf( ch, "  %15.15s", member->name );
      if( ++cnt == 4 )
      {
         cnt = 0;
         send_to_char( "\r\n", ch );
      }
   }
   if( cnt != 0 )
      send_to_char( "\r\n", ch );
}

CMDF( do_setdeity )
{
   char arg1[MIL], arg2[MIL], arg3[MIL];
   DEITY_DATA *deity;
   int value;

   if( is_npc( ch ) )
   {
      send_to_char( "Huh?\r\n", ch );
      return;
   }

   switch( ch->substate )
   {
      default:
         break;

      case SUB_RESTRICTED:
         send_to_char( "You can't do this while in another command.\r\n", ch );
         return;

      case SUB_DEITYDESC:
         deity = ( DEITY_DATA * ) ch->dest_buf;
         STRFREE( deity->description );
         deity->description = copy_buffer( ch );
         stop_editing( ch );
         save_deity( deity );
         ch->substate = ch->tempnum;
         return;
   }

   argument = one_argument( argument, arg1 );
   argument = one_argument( argument, arg2 );

   if( !arg1 || arg1[0] == '\0' )
   {
      send_to_char( "Usage: setdeity <deity> [create]\r\n", ch );
      send_to_char( "Usage: setdeity <deity> <field> <toggle>\r\n", ch );
      send_to_char( "Field being one of:\r\n", ch );
      send_to_char( "      sex    class    objvnum    alignment  description\r\n", ch );
      send_to_char( "     name    race2    suscept    resistnum\r\n", ch );
      send_to_char( "     race   resist   affected   susceptnum\r\n", ch );
      send_to_char( "     type  mobvnum   filename  affectednum\r\n", ch );
      send_to_char( "Field Favor adjustments:\r\n", ch );
      send_to_char( "      aid     flee   backstab   dig_corpse\r\n", ch );
      send_to_char( "      die     kill  aid_spell   kill_magic\r\n", ch );
      send_to_char( "      sac    steal  spell_aid  bury_corpse\r\n", ch );
      send_to_char( "Field Favor requirements for supplicate:\r\n", ch );
      send_to_char( "  savatar  scorpse    srecall    sdeityobj\r\n", ch );
      return;
   }

   deity = get_deity( arg1 );

   if( !str_cmp( arg2, "create" ) )
   {
      if( deity )
      {
         send_to_char( "There is already a deity with that name.\r\n", ch );
         return;
      }
      CREATE( deity, DEITY_DATA, 1 );
      if( !deity )
      {
         bug( "%s: failed to CREATE deity.", __FUNCTION__ );
         return;
      }
      LINK( deity, first_deity, last_deity, next, prev );
      deity->name = STRALLOC( arg1 );
      deity->filename = STRALLOC( strlower( arg1 ) );
      deity->sex = -1;
      deity->worshippers = 0;
      deity->first_worshipper = NULL;
      deity->last_worshipper = NULL;
      xCLEAR_BITS( deity->race );
      xCLEAR_BITS( deity->Class );
      xCLEAR_BITS( deity->affected );
      xCLEAR_BITS( deity->resist );
      xCLEAR_BITS( deity->suscept );
      write_deity_list( );
      save_deity( deity );
      ch_printf( ch, "%s deity has been created\r\n", deity->name );
      return;
   }

   if( !deity )
   {
      send_to_char( "No such deity to set.\r\n", ch );
      return;
   }

   if( !arg2 || arg2[0] == '\0' )
   {
      show_deity( ch, deity );
      return;
   }

   if( !str_cmp( arg2, "name" ) )
   {
      DEITY_DATA *udeity;

      if( !argument || argument[0] == '\0' )
      {
         send_to_char( "You can't set a deity's name to nothing.\r\n", ch );
         return;
      }
      if( ( udeity = get_deity( argument ) ) )
      {
         send_to_char( "There is already another deity with that name.\r\n", ch );
         return;
      }
      STRSET( deity->name, argument );
      save_deity( deity );
      send_to_char( "Deity name changed.\r\n", ch );
      return;
   }

   if( !str_cmp( arg2, "filename" ) )
   {
      char filename[256];

      if( !argument || argument[0] == '\0' )
      {
         send_to_char( "You can't set a deity's filename to nothing.\r\n", ch );
         return;
      }
      if( !can_use_path( ch, DEITY_DIR, argument ) )
         return;
      if( deity->filename )
      {
         snprintf( filename, sizeof( filename ), "%s%s", DEITY_DIR, deity->filename );
         if( !remove( filename ) )
            send_to_char( "Old deity file deleted.\r\n", ch );
      }
      STRSET( deity->filename, argument );
      save_deity( deity );
      write_deity_list( );
      send_to_char( "Deity filename changed.\r\n", ch );
      return;
   }

   if( !str_cmp( arg2, "description" ) )
   {
      if( ch->substate == SUB_REPEATCMD )
         ch->tempnum = SUB_REPEATCMD;
      else
         ch->tempnum = SUB_NONE;
      ch->substate = SUB_DEITYDESC;
      ch->dest_buf = deity;
      start_editing( ch, deity->description );
      return;
   }

   if( !str_cmp( arg2, "alignment" ) )
   {
      deity->alignment = URANGE( -1000, atoi( argument ), 1000 );
      ch_printf( ch, "Alignment set to %d.\r\n", deity->alignment );
      save_deity( deity );
      return;
   }

   if( !str_cmp( arg2, "objvnum" ) )
   {
      value = URANGE( 0, atoi( argument ), MAX_VNUM );
      if( value != 0 && !get_obj_index( value ) )
      {
         send_to_char( "No object has that vnum. Use 0 for no objvnum.\r\n", ch );
         return;
      }

      deity->objvnum = value;
      save_deity( deity );
      send_to_char( "Deity objvnum changed.\r\n", ch );
      return;
   }

   if( !str_cmp( arg2, "mobvnum" ) )
   {
      value = URANGE( 0, atoi( argument ), MAX_VNUM );
      if( value != 0 && !get_mob_index( value ) )
      {
         send_to_char( "No mobile has that vnum. Use 0 for no mobvnum.\r\n", ch );
         return;
      }

      deity->mobvnum = value;
      save_deity( deity );
      send_to_char( "Deity mobvnum changed.\r\n", ch );
      return;
   }

   if( !str_cmp( arg2, "race" ) )
   {
      bool modified = false;
      int stat;

      while( argument && argument[0] != '\0' )
      {
         argument = one_argument( argument, arg1 );
         stat = get_pc_race( arg1 );
         if( stat < 0 || stat >= MAX_PC_RACE )
            ch_printf( ch, "Invalid race [%s].\r\n", arg1 );
         else
         {
            xTOGGLE_BIT( deity->race, stat );
            modified = true;
         }
      }
      if( modified )
      {
         send_to_char( "Deity Race(s) have been set.\r\n", ch );
         save_deity( deity );
      }
      return;
   }

   if( !str_cmp( arg2, "class" ) )
   {
      bool modified = false;
      int stat;

      while( argument && argument[0] != '\0' )
      {
         argument = one_argument( argument, arg1 );
         stat = get_pc_class( arg1 );
         if( stat < 0 || stat >= MAX_PC_CLASS )
            ch_printf( ch, "Invalid class [%s].\r\n", arg1 );
         else
         {
            xTOGGLE_BIT( deity->Class, stat );
            modified = true;
         }
      }
      if( modified )
      {
         send_to_char( "Deity Class(es) have been set.\r\n", ch );
         save_deity( deity );
      }
      return;
   }

   if( !str_cmp( arg2, "suscept" ) )
   {
      bool fMatch = false;

      while( argument[0] != '\0' )
      {
         argument = one_argument( argument, arg3 );
         if( !str_cmp( arg3, "none" ) )
         {
            fMatch = true;
            xCLEAR_BITS( deity->suscept );
         }
         else
         {
            value = get_flag( arg3, ris_flags, RIS_MAX );
            if( value < 0 || value >= RIS_MAX )
               ch_printf( ch, "Unknown flag: %s\r\n", arg3 );
            else
            {
               xTOGGLE_BIT( deity->suscept, value );
               fMatch = true;
            }
         }
      }

      save_deity( deity );
      if( fMatch )
         send_to_char( "Deity suscept(s) have been set.\r\n", ch );
      return;
   }

   if( !str_cmp( arg2, "resist" ) )
   {
      bool fMatch = false;

      while( argument[0] != '\0' )
      {
         argument = one_argument( argument, arg3 );
         if( !str_cmp( arg3, "none" ) )
         {
            fMatch = true;
            xCLEAR_BITS( deity->resist );
         }
         else
         {
            value = get_flag( arg3, ris_flags, RIS_MAX );
            if( value < 0 || value >= RIS_MAX )
               ch_printf( ch, "Unknown flag: %s\r\n", arg3 );
            else
            {
               xTOGGLE_BIT( deity->resist, value );
               fMatch = true;
            }
         }
      }

      save_deity( deity );
      if( fMatch )
         send_to_char( "Deity resist(s) have been set.\r\n", ch );
      return;
   }

   if( !str_cmp( arg2, "affected" ) )
   {
      bool fMatch = false;

      while( argument[0] != '\0' )
      {
         argument = one_argument( argument, arg3 );
         if( !str_cmp( arg3, "none" ) )
         {
            fMatch = true;
            xCLEAR_BITS( deity->affected );
         }
         else
         {
            value = get_flag( arg3, a_flags, AFF_MAX );
            if( value < 0 || value >= AFF_MAX )
               ch_printf( ch, "Unknown flag: %s\r\n", arg3 );
            else
            {
               xTOGGLE_BIT( deity->affected, value );
               fMatch = true;
            }
         }
      }

      save_deity( deity );
      if( fMatch )
         send_to_char( "Deity affected has been set.\r\n", ch );
      return;
   }

   if( !str_cmp( arg2, "sex" ) )
   {
      deity->sex = URANGE( 0, value, ( SEX_MAX - 1 ) );
      save_deity( deity );
      ch_printf( ch, "Sex set to %d.\r\n", deity->sex );
      return;
   }

   value = atoi( argument );

   if( !str_cmp( arg2, "flee" ) )
      deity->flee = value;
   else if( !str_cmp( arg2, "kill" ) )
      deity->kill = value;
   else if( !str_cmp( arg2, "kill_magic" ) )
      deity->kill_magic = value;
   else if( !str_cmp( arg2, "sac" ) )
      deity->sac = value;
   else if( !str_cmp( arg2, "bury_corpse" ) )
      deity->bury_corpse = value;
   else if( !str_cmp( arg2, "aid_spell" ) )
      deity->aid_spell = value;
   else if( !str_cmp( arg2, "aid" ) )
      deity->aid = value;
   else if( !str_cmp( arg2, "steal" ) )
      deity->steal = value;
   else if( !str_cmp( arg2, "backstab" ) )
      deity->backstab = value;
   else if( !str_cmp( arg2, "die" ) )
      deity->die = value;
   else if( !str_cmp( arg2, "spell_aid" ) )
      deity->spell_aid = value;
   else if( !str_cmp( arg2, "dig_corpse" ) )
      deity->dig_corpse = value;
   else if( !str_cmp( arg2, "scorpse" ) )
      deity->scorpse = value;
   else if( !str_cmp( arg2, "savatar" ) )
      deity->savatar = value;
   else if( !str_cmp( arg2, "sdeityobj" ) )
      deity->sdeityobj = value;
   else if( !str_cmp( arg2, "srecall" ) )
      deity->srecall = value;
   if( !str_cmp( arg2, "susceptnum" ) )
      deity->susceptnum = value;
   else if( !str_cmp( arg2, "resistnum" ) )
      deity->resistnum = value;
   else if( !str_cmp( arg2, "affectednum" ) )
      deity->affectednum = value;
   else
   {
      do_setdeity( ch, "" );
      return;
   }
   save_deity( deity );
   ch_printf( ch, "Deity %s set.\r\n", arg2 );
}

CMDF( do_devote )
{
   DEITY_DATA *deity;

   if( is_npc( ch ) )
   {
      send_to_char( "Huh?\r\n", ch );
      return;
   }

   if( ch->level < 5 )
   {
      send_to_char( "You aren't yet prepared for such devotion.\r\n", ch );
      return;
   }

   if( !argument || argument[0] == '\0' )
   {
      send_to_char( "Devote yourself to which deity?\r\n", ch );
      return;
   }

   if( !str_cmp( argument, "none" ) )
   {
      if( !ch->pcdata->deity )
      {
         send_to_char( "You aren't worshipping any deity.\r\n", ch );
         return;
      }
      remove_deity_worshipper( ch->pcdata->deity, ch->name );
      save_deity( ch->pcdata->deity );
      ch->pcdata->deity = NULL;
      ch->pcdata->favor = 0;
      send_to_char( "You cease to worship any deity.\r\n", ch );
      update_aris( ch );
      save_char_obj( ch );
      return;
   }

   if( ch->pcdata->deity )
   {
      send_to_char( "You are already devoted to a deity.\r\n", ch );
      return;
   }

   if( !( deity = get_deity( argument ) ) )
   {
      send_to_char( "No such deity holds weight on this world.\r\n", ch );
      return;
   }

   if( xIS_SET( deity->Class, ch->Class ) )
   {
      send_to_char( "That deity won't accept your worship due to your class.\r\n", ch );
      return;
   }

   if( ( deity->sex != -1 ) && ( deity->sex != ch->sex ) )
   {
      send_to_char( "That deity won't accept worshippers of your sex.\r\n", ch );
      return;
   }

   if( xIS_SET( deity->race, ch->race ) )
   {
      send_to_char( "That deity won't accept worshippers of your race.\r\n", ch );
      return;
   }

   add_deity_worshipper( deity, ch->name );
   ch->pcdata->deity = deity;
   act( AT_MAGIC, "Body and soul, you devote yourself to $t!", ch, ch->pcdata->deity->name, NULL, TO_CHAR );
   act( AT_MAGIC, "Body and soul, $n devotes $mself to $t!", ch, ch->pcdata->deity->name, NULL, TO_ROOM );
   save_deity( ch->pcdata->deity );
   ch->pcdata->favor = 0;
   update_aris( ch );
   save_char_obj( ch );
}

CMDF( do_deities )
{
   DEITY_DATA *deity;

   if( !argument || argument[0] == '\0' )
   {
      if( !first_deity )
      {
         send_to_pager( "&gThere are no deities on this world.\r\n", ch );
         return;
      }
      pager_printf( ch, "&G%20s &w| &g%15s\r\n", "Deity", "Worshippers" );
      send_to_pager( "&W-------------------- &w| &W---------------\r\n", ch );
      for( deity = first_deity; deity; deity = deity->next )
         pager_printf( ch, "&G%20s &w| &g%15s\r\n", deity->name, num_punct( deity->worshippers ) );
      send_to_pager( "&gFor detailed information on a deity, try 'deities <deity>' or 'help deities'\r\n", ch );
      return;
   }

   if( !( deity = get_deity( argument ) ) )
   {
      send_to_pager( "&gNo such deity exist.\r\n", ch );
      return;
   }
   pager_printf( ch, "&gDeity: &G%s\r\n", deity->name );
   pager_printf( ch, "&gDescription:\r\n&G%s\r\n", deity->description ? deity->description : "(Not Set)" );
}

CMDF( do_supplicate )
{
   int oldfavor;
   CHAR_DATA *rch = NULL;
   DEITY_DATA *deity;

   if( is_npc( ch ) || !ch->pcdata->deity )
   {
      send_to_char( "You have no deity to supplicate to.\r\n", ch );
      return;
   }

   if( !argument || argument[0] == '\0' )
   {
      send_to_char( "Supplicate for what?\r\n", ch );
      return;
   }

   oldfavor = ch->pcdata->favor;
   deity = ch->pcdata->deity;

   if( !str_cmp( argument, "corpse" ) && !is_pkill( ch ) )
   {
      char buf2[MSL];
      OBJ_DATA *obj;
      bool found, althere, charge;

      if( ch->pcdata->favor < deity->scorpse )
      {
         send_to_char( "You aren't favored enough for a corpse retrieval.\r\n", ch );
         return;
      }

      if( xIS_SET( ch->in_room->room_flags, ROOM_CLANSTOREROOM ) )
      {
         send_to_char( "You can't supplicate in a storage room.\r\n", ch );
         return;
      }

      found = false;
      althere = false;
      charge = false;
      snprintf( buf2, sizeof( buf2 ), "the corpse of %s", ch->name );
      for( obj = first_object; obj; obj = obj->next )
      {
         if( obj->in_room && !str_cmp( buf2, obj->short_descr ) && ( obj->pIndexData->vnum == OBJ_VNUM_CORPSE_PC ) )
         {
            if( obj->in_room == ch->in_room )
            {
               althere = true;
               continue;
            }

            found = true;
            if( xIS_SET( obj->in_room->room_flags, ROOM_NOSUPPLICATE ) )
            {
               act( AT_MAGIC, "The image of your corpse appears, but suddenly wavers away...", ch, NULL, NULL, TO_CHAR );
               continue;
            }

            charge = true;
            if( ( rch = obj->in_room->first_person ) && !is_obj_stat( obj, ITEM_BURIED ) )
            {
               act( AT_MAGIC, "$T suddenly vanishes, surrounded by a divine presence...", rch, NULL, buf2, TO_ROOM );
               act( AT_MAGIC, "$T suddenly vanishes, surrounded by a divine presence...", rch, NULL, buf2, TO_CHAR );
            }

            act( AT_MAGIC, "Your corpse appears suddenly, surrounded by a divine presence...", ch, NULL, NULL, TO_CHAR );
            act( AT_MAGIC, "$n's corpse appears suddenly, surrounded by a divine force...", ch, NULL, NULL, TO_ROOM );
            obj_from_room( obj );
            obj = obj_to_room( obj, ch->in_room );
         }
      }

      if( !found )
      {
         if( !althere )
            send_to_char( "No corpse of yours litters the world...\r\n", ch );
         else
            send_to_char( "Your corpse(s) are already in this room...\r\n", ch );
         return;
      }

      if( charge )
         ch->pcdata->favor -= deity->scorpse;
      update_aris( ch );
      return;
   }

   if( !str_cmp( argument, "avatar" ) )
   {
      MOB_INDEX_DATA *pMobIndex;
      CHAR_DATA *victim;

      if( deity->mobvnum <= 0 )
      {
         send_to_char( "Your deity doesn't have an avatar for you to supplicate.\r\n", ch );
         return;
      }
      if( ch->pcdata->favor < deity->savatar )
      {
         send_to_char( "You aren't favored enough for that.\r\n", ch );
         return;
      }
      if( !( pMobIndex = get_mob_index( deity->mobvnum ) ) )
      {
         bug( "%s: mob vnum %d doesn't exist.", __FUNCTION__, deity->mobvnum );
         return;
      }
      if( !( victim = create_mobile( pMobIndex ) ) )
      {
         bug( "%s: couldn't create_mobile for vnum %d.", __FUNCTION__, deity->mobvnum );
         return;
      }
      char_to_room( victim, ch->in_room );
      act( AT_MAGIC, "$n summons $N!", ch, NULL, victim, TO_ROOM );
      act( AT_MAGIC, "You summon $N!", ch, NULL, victim, TO_CHAR );
      add_follower( victim, ch );
      xSET_BIT( victim->affected_by, AFF_CHARM );
      victim->alignment = deity->alignment;
      victim->max_hit = ( ch->hit * 6 + ch->pcdata->favor );
      victim->hit = victim->max_hit;
      ch->pcdata->favor -= deity->savatar;
      update_aris( ch );
      return;
   }

   if( !str_cmp( argument, "object" ) )
   {
      OBJ_DATA *obj;
      OBJ_INDEX_DATA *pObjIndex;

      if( deity->objvnum <= 0 )
      {
         send_to_char( "Your deity doesn't have an object for you to supplicate.\r\n", ch );
         return;
      }
      if( ch->pcdata->favor < deity->sdeityobj )
      {
         send_to_char( "You aren't favored enough for that.\r\n", ch );
         return;
      }

      if( !( pObjIndex = get_obj_index( deity->objvnum ) ) )
      {
         bug( "%s: object vnum %d doesnt exist?", __FUNCTION__, deity->objvnum );
         return;
      }

      if( !( obj = create_object( pObjIndex, ch->level ) ) )
      {
         bug( "%s: couldn't create_object vnum %d.", __FUNCTION__, deity->objvnum );
         return;
      }

      if( !can_wear( obj, ITEM_NO_TAKE ) )
         obj = obj_to_char( obj, ch );
      else
         obj = obj_to_room( obj, ch->in_room );

      act( AT_MAGIC, "$n weaves $p from divine matter!", ch, obj, NULL, TO_ROOM );
      act( AT_MAGIC, "You weave $p from divine matter!", ch, obj, NULL, TO_CHAR );
      ch->pcdata->favor -= ch->pcdata->deity->sdeityobj;
      update_aris( ch );
      return;
   }

   if( !str_cmp( argument, "recall" ) )
   {
      ROOM_INDEX_DATA *location;

      if( ch->pcdata->favor < deity->srecall )
      {
         send_to_char( "Your favor is inadequate for such a supplication.\r\n", ch );
         return;
      }

      if( xIS_SET( ch->in_room->room_flags, ROOM_NOSUPPLICATE ) )
      {
         send_to_char( "You have been forsaken!\r\n", ch );
         return;
      }

      if( get_timer( ch, TIMER_RECENTFIGHT ) > 0 && !is_immortal( ch ) )
      {
         send_to_char( "You can't supplicate recall under adrenaline!\r\n", ch );
         return;
      }

      location = NULL;

      if( !is_npc( ch ) && ch->pcdata->clan )
         location = get_room_index( ch->pcdata->clan->recall );

      if( !is_npc( ch ) && !location && ch->level >= 5 && xIS_SET( ch->pcdata->flags, PCFLAG_DEADLY ) )
         location = get_room_index( sysdata.room_deadly );

      /* 1998-01-02, h */
      if( !location )
         location = get_room_index( race_table[ch->race]->race_recall );
      if( !location )
         location = get_room_index( sysdata.room_temple );
      if( !location )
      {
         send_to_char( "You are completely lost.\r\n", ch );
         return;
      }

      act( AT_MAGIC, "$n disappears in a column of divine power.", ch, NULL, NULL, TO_ROOM );
      char_from_room( ch );
      char_to_room( ch, location );
      if( ch->mount )
      {
         char_from_room( ch->mount );
         char_to_room( ch->mount, location );
      }
      act( AT_MAGIC, "$n appears in the room from a column of divine mist.", ch, NULL, NULL, TO_ROOM );
      do_look( ch, "auto" );
      ch->pcdata->favor -= deity->srecall;
      update_aris( ch );
      return;
   }

   send_to_char( "You can't supplicate for that.\r\n", ch );
}

/*
 * Internal function to adjust favor.
 * Fields are:
 *  0 = flee         1 = kill          2 = kill_magic
 *  3 = sac          4 = bury_corpse   5 = aid_spell
 *  6 = aid          7 = steal         8 = backstab
 *  9 = die         10 = spell_aid    11 = dig_corpse
 */
void adjust_favor( CHAR_DATA *ch, int field, int mod )
{
   DEITY_DATA *deity;

   if( is_npc( ch ) || !ch->pcdata->deity )
      return;

   deity = ch->pcdata->deity;

   if( deity->alignment != 0
   && ( ( ch->alignment - deity->alignment ) > 650 || ( ch->alignment - deity->alignment ) < -650 ) )
   {
      ch->pcdata->favor -= 2;
      ch->pcdata->favor = URANGE( -2500, ch->pcdata->favor, 2500 );
      update_aris( ch );
      return;
   }

   if( mod < 1 )
      mod = 1;

   switch( field )
   {
      default:
         return;

      case 0:
         ch->pcdata->favor += ( deity->flee / mod );
         break;

      case 1:
         ch->pcdata->favor += ( deity->kill / mod );
         break;

      case 2:
         ch->pcdata->favor += ( deity->kill_magic / mod );
         break;

      case 3:
         ch->pcdata->favor += ( deity->sac / mod );
         break;

      case 4:
         ch->pcdata->favor += ( deity->bury_corpse / mod );
         break;

      case 5:
         ch->pcdata->favor += ( deity->aid_spell / mod );
         break;

      case 6:
         ch->pcdata->favor += ( deity->aid / mod );
         break;

      case 7:
         ch->pcdata->favor += ( deity->steal / mod );
         break;

      case 8:
         ch->pcdata->favor += ( deity->backstab / mod );
         break;

      case 9:
         ch->pcdata->favor += ( deity->die / mod );
         break;

      case 10:
         ch->pcdata->favor += ( deity->spell_aid / mod );
         break;

      case 11:
         ch->pcdata->favor += ( deity->dig_corpse / mod );
         break;
   }
   ch->pcdata->favor = URANGE( -2500, ch->pcdata->favor, 2500 );
   update_aris( ch );
}

/* 1997, Blodkai */
CMDF( do_remains )
{
   char buf[MSL];
   OBJ_DATA *obj;
   bool found = false;
   int favor = 0;

   if( !ch || is_npc( ch ) )
      return;

   set_char_color( AT_MAGIC, ch );
   if( !ch->pcdata->deity )
   {
      send_to_pager( "You have no deity from which to seek such assistance...\r\n", ch );
      return;
   }

   favor = number_range( ch->level, ch->level * 2 );
   if( ch->pcdata->favor < favor )
   {
      send_to_pager( "Your favor is insufficient for such assistance...\r\n", ch );
      return;
   }

   pager_printf( ch, "%s appears in a vision, revealing that your remains...\r\n", ch->pcdata->deity->name );
   snprintf( buf, sizeof( buf ), "the corpse of %s", ch->name );
   for( obj = first_object; obj; obj = obj->next )
   {
      if( obj->in_room && !str_cmp( buf, obj->short_descr ) && ( obj->pIndexData->vnum == OBJ_VNUM_CORPSE_PC ) )
      {
         found = true;
         pager_printf( ch, "  - at %s will endure for %d ticks\r\n", obj->in_room->name, obj->timer );
      }
   }

   if( !found )
      send_to_pager( "  - no longer exist.\r\n", ch );
   else
      ch->pcdata->favor -= favor;
}