From: Jair <jddotter@ou.edu>
Subject: Diety worship system

Greetings.   What follows is my attempt at a working worship/god system
that allows players to pick
a god to worship at creation (I have this restricted by alignment and
even class, you may not want to do this).  Once this god is picked,
there is a pray channel that allows them to 'pray' to their god, and
anyone else who has the same god can also get the messages.  Whenever
you sacrifice something, it goes to your god instead of 'Mota', or
whatever you've set that to.  I also (slightly) modified the mset
command (just set mob etc...)  so that  you can set a characters god
from inside the game.  However, this is not restricted by alighment or
class (to allow for special RP situations).  Also, the god you worship
shows up in your score.

A word of warning:  I couldn't make a conventional patch for this
because our code is modified enough from stock that the line numbers
would be way off, so where it's ambiguous as to where to insert the
code, I'll try and put lines before and after the insert. 

NOTE:  all the {B and {y and basically {x in anything that's printed is
Lope's colo(u)r code.  If you have it, great.  If you don't, just delete
all that stuff.  The colour codes are { and the _one_ character
following.

My comments on the code should be enclosed in < >.

Without further ado:

/* Jair's diety worship system, by implementing this code you are under
no obligation to credit myself for anything or notify me at all;
however, if you wish to give me credit, I'll be thrilled */

*** in comm.c ***
<This is the tail end of case CON_GET_ALIGNMENT, have to get rid of
this...>

group_add(ch,"rom basics",FALSE);
        group_add(ch,class_table[ch->class].base_group,FALSE);
        ch->pcdata->learned[gsn_recall] = 50;
        write_to_buffer(d,"Do you wish to customize this
character?\n\r",0);
        write_to_buffer(d,"Customization takes time, but allows a wider
range of skills and abilities.\n\r",0);
        write_to_buffer(d,"Customize (Y/N)? ",0);
        d->connected = CON_DEFAULT_CHOICE;
        break;

<...and replace it with this:>
       write_to_buffer(d,"The following gods are available:\n\r  ",0);
        for ( god = 0; god < MAX_GOD; god++ )
        {
          if ((god_table[god].pc_evil && ch->alignment == -750)
           || (god_table[god].pc_neutral && ch->alignment == 0)
           || (god_table[god].pc_good && ch->alignment == 750) )
            {
              if((god_table[god].pc_mage && ch->class == 0)
              || (god_table[god].pc_cleric && ch->class == 1)
              || (god_table[god].pc_thief && ch->class == 2)
              || (god_table[god].pc_warrior && ch->class == 3) )
              {
                write_to_buffer(d,god_table[god].name,0);
                write_to_buffer(d," ",1);
              }
            }
        }
        write_to_buffer(d,"\n\r",0);
        write_to_buffer(d,"Who do you want to worship (help for more
information)? ",0);
        d->connected = CON_GET_GOD;
        break;

    case CON_GET_GOD:
        one_argument(argument,arg);

        if (!strcmp(arg,"help"))
        {
            argument = one_argument(argument,arg);
            if (argument[0] == '\0')
                do_help(ch,"gods");
            else
                do_help(ch,argument);
                write_to_buffer(d,"Who do you want to worship (help for
more information)? ",0);
            break;
        }
        god = god_lookup(argument);

        if ( god == 0
            || (!god_table[god].pc_evil && ch->alignment == -750)
            || (!god_table[god].pc_neutral && ch->alignment == 0)
            || (!god_table[god].pc_good && ch->alignment == 750)
            || (!god_table[god].pc_mage && ch->class == 0)
            || (!god_table[god].pc_cleric && ch->class == 1)
            || (!god_table[god].pc_thief && ch->class == 2)
            || (!god_table[god].pc_warrior && ch->class == 3) )
        {
            write_to_buffer(d,"That is not a valid god.\n\r",0);
            write_to_buffer(d,"The following gods are
available:\n\r",0);
            for ( god = 0; god < MAX_GOD; god++ )
            {
              if ((god_table[god].pc_evil && ch->alignment == -750)
               || (god_table[god].pc_neutral && ch->alignment == 0)
               || (god_table[god].pc_good && ch->alignment == 750) )
                 {
                   if((god_table[god].pc_mage && ch->class == 0)
                   || (god_table[god].pc_cleric && ch->class == 1)
                   || (god_table[god].pc_thief && ch->class == 2)
                   || (god_table[god].pc_warrior && ch->class == 3) )
                   {
                     write_to_buffer(d,god_table[god].name,0);
                     write_to_buffer(d," ",1);
                   }
                 }
            }
            write_to_buffer(d,"\n\r",0);
            write_to_buffer(d,
                "Who do you want to worship (help for more information)?
",0);
            break;
         }

        ch->god = god;

        write_to_buffer(d,"\n\r",0);

        group_add(ch,"rom basics",FALSE);
        group_add(ch,class_table[ch->class].base_group,FALSE);
        ch->pcdata->learned[gsn_recall] = 50;
        write_to_buffer(d,"Do you wish to customize this
character?\n\r",0);
        write_to_buffer(d,"Customization takes time, but allows a wider
range of skills and
                 abilities.\n\r",0);
        write_to_buffer(d,"Customize (Y/N)? ",0);
        d->connected = CON_DEFAULT_CHOICE;
        break;

<obviously, if you don't want the gods that the player is able to
worship dependent on race or alignment, get rid of the appropriate if
statements in the previous code>

<Now, to aid us in replacing 'Mota' with the players appropriate god, I
just put another case into the $x statements.  I left in the surrounding
lines so you can see where it goes, the new line is indicated with a
'+'>

                case 'E': i = he_she  [URANGE(0, vch ->sex, 2)];       
break;
                case 'm': i = him_her [URANGE(0, ch  ->sex, 2)];       
break;
                case 'M': i = him_her [URANGE(0, vch ->sex, 2)];       
break;
                case 's': i = his_her [URANGE(0, ch  ->sex, 2)];       
break;
                case 'S': i = his_her [URANGE(0, vch ->sex, 2)];       
break;
           +    case 'g': i = god_table[ch->god].name;                 
break;

                case 'p':
                    i = can_see_obj( to, obj1 )
                            ? obj1->short_descr
                            : "something";
                    break;


*** in merc.h ***

#define MAX_GOD                    23    (or however many gods you have
+2)

<here, you'll have to increment all the numbers after CON_GET_GOD by one
(duh))

 #define CON_GET_GOD                     10
 #define CON_DEFAULT_CHOICE              11 
 #define CON_GEN_GROUPS                  12 
 #define CON_PICK_WEAPON                 13
 #define CON_READ_IMOTD                  14
 #define CON_READ_MOTD                   15
 #define CON_BREAK_CONNECT               16


<This slot (K) should be empty, if not, just pick another empty one>
 #define COMM_NOPRAY             (K)


<All the bool fields in the god_type are for setting and determing if
that god can be worshiped by pc's of that alignment and/or class.  If
you don't want to have these restrictions, you can simplify this and the
table of gods immensly by just taking out these fields>
 /*
  * Immortal table god fields.
  */
 struct god_type
 {
     char *      name;                   /* call name of the god */
     bool        pc_good;                /* can be chosen by good pcs */
     bool        pc_neutral;             /* can be chosen by neutral pcs
*/
     bool        pc_evil;                /* can be chosen by evil pcs */
     bool        pc_mage;                /* can be chosen by Mage pcs */
     bool        pc_thief;               /* can be chosen by Thief pcs
*/
     bool        pc_warrior;             /* can be chosen by Warrior pcs
*/
     bool        pc_cleric;              /* can be chosen by Cleric pcs
*/
 };
 
<This line goes into the: struct  char_data  (for PC's and NPC's)  I
didn't think this would be a problem, I just arbitrarily decided do put
it here instead of pc_data.>
     sh_int              god;

<Should be easy to find where the next two lines go.>
 extern  const   struct  god_type        god_table       [MAX_GOD];

 int     god_lookup      args( ( const char *name) );

*** in act_comm.c ***

<just add this function>
void do_pray( CHAR_DATA *ch, char *argument )
 {
     char buf[MAX_STRING_LENGTH];
     DESCRIPTOR_DATA *d;
 
     if ( argument[0] == '\0' )
     {
       if (IS_SET(ch->comm,COMM_NOPRAY))
       {
         send_to_char("Pray channel is now ON\n\r",ch);
         REMOVE_BIT(ch->comm,COMM_NOPRAY);
       }
       else
       {
         send_to_char("Pray channel is now OFF\n\r",ch);
         SET_BIT(ch->comm,COMM_NOPRAY);
       }
       return;
     }
 
     REMOVE_BIT(ch->comm,COMM_NOPRAY);
 
     sprintf( buf, "{y$n:{c %s{x", argument );
     act_new("$n prays {B$t{x",ch,argument,NULL,TO_CHAR,POS_DEAD);
     for ( d = descriptor_list; d != NULL; d = d->next )
     {
         if ( d->connected == CON_PLAYING
            && ( ch->god == d->character->god )
            && !IS_SET(d->character->comm,COMM_NOPRAY)
            && !IS_SET(d->character->comm,COMM_QUIET) )
         {
             act_new("$n prays
{B$t{x",ch,argument,d->character,TO_VICT,POS_DEAD);
         }
     }
 
     return;
 }
 
<and in the pose tables (if you still have those in) change the
following lines:>
 	    "The great god Mota gives you a staff.",
 	    "The great god Mota gives $n a staff.",

<to these lines:>
	    "The great god $g gives you a staff.",
 	    "The great god $g gives $n a staff.",

*** in act_obj.c ***

<for the following, < means put in, > means take out (they're just
replaces, no biggie)>

< 	act( "$n offers $mself to $g, who graciously declines.",
> 	act( "$n offers $mself to Mota, who graciously declines.",

< 	act( "$g appreciates your offer and may accept it later.", ch, NULL,
NULL, TO_CHAR );
> 	send_to_char( "Mota appreciates your offer and may accept it later.\n\r", ch );

<            act( "$g gives you one silver coin for your sacrifice.",
ch, NULL, NULL, TO_CHAR );
> 	send_to_char( "Mota gives you one silver coin for your sacrifice.\n\r", ch );
         
< 	sprintf(buf,"%s gives you %d silver coins for your sacrifice.\n\r",
< 		god_table[ch->god].name,silver);
> 	sprintf(buf,"Mota gives you %d silver coins for your sacrifice.\n\r",
> 		silver);

<     act( "$n sacrifices $p to $g.", ch, obj, NULL, TO_ROOM );
>     act( "$n sacrifices $p to Mota.", ch, obj, NULL, TO_ROOM );

<now, I might not have to had replaced the send_to_char with act
statements, but that's the only way I knew how to get that ch->god tag
in.  And, it also allows for easy future expansion>

*** in tables.c ***

     {   "nopray",               COMM_NOPRAY,            TRUE    },

*** in interp.c ***

     { "pray",           do_pray,        POS_SLEEPING,    0, 
LOG_NORMAL, 1 },

*** in interp.h ***

 DECLARE_DO_FUN( do_pray         ); 

*** in act_wiz.c ***

<on this line, it's the same as what's already there, just add the
'god'>

send_to_char( "    str int wis dex con sex class level god\n\r",ch );


<then, just add this bit somewhere under the /* Set something */>

if (!str_prefix(arg2,"god"))
    {
        int god;

        god = god_lookup(arg3);

        if( god == 0 )
        {
            send_to_char("That is not a valid god for that
character.\n\r",ch);
            return;
        }

        victim->god = god;
        return;
    }


*** in handler.c ***

/* returns god number */
 int god_lookup (const char *name)
 {
    int god;
 
    for ( god = 0; god_table[god].name != NULL; god++)
    {
         if (LOWER(name[0]) == LOWER(god_table[god].name[0])
         &&  !str_prefix( name,god_table[god].name))
             return god;
    }
 
    return 0;
 }
 

<this one is just added down where the other 'if(comm_flags &
COMM_EVERYTHING ELSE )etc... >

      if (comm_flags & COMM_NOPRAY        ) strcat(buf, " no_pray");


*** in const.c ***

<Ok, here is the god table, now obviously I'm not going to put up all 21
of my gods, there's enough here for you get an idea of what's going on. 
Just put in as many as you want, and don't forget to change MAX_GODS in
merc.h.  Again, if you don't want the alignment/class checks, this table
simplifies enormously.>

/* god table */
 const   struct  god_type       god_table      []           = 
 {
 /*
     {
         name,
         player_good?,   player_neutral?,   player_evil?,
         player_mage?,   player_thief?,     player_warrior?,  
player_cleric?
     },
 */
 
     { "Nobody", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE },
 
     { "God1",
       TRUE,	FALSE,	FALSE,
       TRUE,	FALSE,	TRUE,	FALSE
     },
 
     { "God2",
       FALSE,	FALSE,	TRUE,
       FALSE,	TRUE,	TRUE,	TRUE
     },
 
     { "God3",
       FALSE,	TRUE,	FALSE,
       TRUE,	TRUE,	TRUE,	FALSE
     },
  	.
	.
	.

     { "God21",
       FALSE,	TRUE,	FALSE,
       TRUE,	TRUE,	TRUE,	TRUE
     }
};
 
*** in act_info.c ***

<this is in here just to show the player whom they worship, it goes in
do_score, just wherever you want it to show up.  Or not at all if you
don't.>

sprintf( buf, "You worship %s \n\r",(god_table[ch->god].name));
    send_to_char( buf, ch);


Ok, that should be it.  The reason that I'm sending this to the mailing
list is because I looked around (pretty extensively) for a system like
this to use on my mud and didn't find one.   I know that plenty of other
people have coded something similar on their muds, I've played on a
couple, but I thought I'd throw this up for everyone to use.  If anyone
wants to put this on their web/ftp page of snippets, great!

Now, I know that I don't have a realy firm grasp on a lot of the things
that I'm coding, does anyone suggestions/ideas/flames/etc?

Jair

