Code : Player Journals >From : amaron.mudservices.com:6001 Author : Felix Email : admins@amaron.mudservices.com July, 2000 The following code will allow you to add Player Journals to your mud. This will allow players to use a part of the ROM note system to "post" their own text to an objects extra descriptions. I use journals on Amaron to promote roleplaying, quests, promoting player histories, etc. The possibilities are endless. If you have any problems installing this code, you can reach me at the above information or on the ROM mailing list. The original idea for the journal code came from conversations between myself and one of my players, Khalad. I got the idea to use part of the ROM note system from the "SIGN" code that is out there on the snippet sites. A tip of the hat goes out to Kahlus Naester for assisting with a coding issue. Installing the code: ==================== **STEP 1** Open merc.h in your text editor. Locate the following code in merc.h: /* * Item types. * Used in #OBJECTS. */ #define ITEM_LIGHT 1 #define ITEM_SCROLL 2 Add the following code to the end of this list. You may have to change the numbers 36, 37 and 38 to fit your list. -- ADD THESE LINES -- #define ITEM_INK 36 #define ITEM_QUILL 37 #define ITEM_JOURNAL 38 The above objects are used to create the journal entries. ITEM_JOURNAL is the actual journal object. I have already added ITEM_INK and ITEM_QUILL to my mud to allow players to scribe scrolls. The journal code also checks to see if the player is holding a bottle of ink and a quill before allowing them to write a journal entry. If you don't want to use them, then don't add them. Locate the following code in merc.h: /* * Data structure for notes. */ #define NOTE_NOTE 0 #define NOTE_IDEA 1 #define NOTE_PENALTY 2 #define NOTE_NEWS 3 Add the following code to the end of this list. You may have to change the number 8 to fir your list. -- ADD THIS LINE -- #define NOTE_JOURNAL 8 Close and save merc.h **STEP 2** Open const.c with your text editor. Locate the following code in const.c: /* item type list */ const struct item_type item_table [] = { { ITEM_LIGHT, "light" }, { ITEM_SCROLL, "scroll" }, Add the following code to this list. -- ADD THESE LINES -- { ITEM_INK, "ink" }, /* Felix - Journal Code */ { ITEM_QUILL, "quill" }, /* Felix - Journal Code */ { ITEM_JOURNAL, "journal" }, /* Felix - Journal Code */ Save and close const.c **STEP 3** Open db.c with your text editor. Locate the following code in db.c: case ITEM_TREASURE: case ITEM_WARP_STONE: case ITEM_ROOM_KEY: case ITEM_GEM: Add the following code to this list. -- ADD THESE LINES -- case ITEM_INK: /* Felix - Journal Code */ case ITEM_QUILL: /* Felix - Journal Code */ case ITEM_JOURNAL: /* Felix - Journal Code */ Save and close db.c **STEP 4** Open limbo.are with your text editor. We are going to add the objects for the INK, QUILL and JOURNAL. Again, if you don't want to use the INK and QUILL then don't add the objects and don't add the above code for them to const.c and db.c - ADD THESE OBJECTS TO LIMBO.ARE -- #28 ink~ a small bottle of ink~ A small bottle of ink has been left here.~ glass~ ink 0 A 0 0 0 0 0 1 10 100 P #29 quill~ a quill~ A quill used for writing has been left here.~ feather~ quill 0 A 0 0 0 0 0 1 10 50 P #137 journal~ a journal~ A leather journal with many pages of writing.~ paper~ journal ORY A 0 0 0 0 0 1 10 10 P You may have to change the VNUMs of the above objects to fit your limbo.are file. At the very least, you'll have to change the journal object. The stock limbo.are file only goes to a VNUM of 99. Save and close limbo.are **STEP 5** Open interp.c with your text editor. Locate the following code: { "sleep", do_sleep, POS_SLEEPING, 0, LOG_NORMAL, 1 }, { "sneak", do_sneak, POS_STANDING, 0, LOG_NORMAL, 1 }, { "split", do_split, POS_RESTING, 0, LOG_NORMAL, 1 }, This is where you are going to add the journal command. You can add it to the bottom of the command list, or adding it aplabetically. Whatever floats your boat. -- ADD THIS LINE -- { "journal", do_journal, POS_STANDING, 0, LOG_NORMAL, 1 }, Save and close interp.c **STEP 6** Open interp.h with your text editor. Locate the following code: DECLARE_DO_FUN( do_invis ); DECLARE_DO_FUN( do_jail ); -- ADD THIS LINE -- DECLARE_DO_FUN( do_journal ); I added the aobve code right between do_jail and do_kick. If that works for you, good. If not, put it where you want. Save and close interp.h **STEP 7** Open act_obj.c with your text editor. Locate the following code at the very top of the act_obj.c file: #include #include #include #include "merc.h" #include "interp.h" Add the following line right after #include "interp.h" : -- ADD THIS LINE -- #include "recycle.h" Immediately following this code you will see the following lines of code: /* * Local functions. */ #define CD CHAR_DATA #define OD OBJ_DATA bool remove_obj args( (CHAR_DATA *ch, int iWear, bool fReplace ) ); void wear_obj args( (CHAR_DATA *ch, OBJ_DATA *obj, bool fReplace ) ); CD * find_keeper args( (CHAR_DATA *ch ) ); int get_cost args( (CHAR_DATA *keeper, OBJ_DATA *obj, bool fBuy ) ); void obj_to_keeper args( (OBJ_DATA *obj, CHAR_DATA *ch ) ); OD * get_obj_keeper args( (CHAR_DATA *ch,CHAR_DATA *keeper,char *argument)); #undef OD #undef CD Add the following line of code immediately after the above lines of code: -- ADD THIS LINE -- void parse_journal(CHAR_DATA *ch, char *argument, int type); Now scroll all the way to the bottom of act_obj.c add the following code: -- ADD THESE LINES OF CODE-- void do_journal(CHAR_DATA *ch,char *argument) { parse_journal(ch,argument,NOTE_JOURNAL); } void journal_attach( CHAR_DATA *ch, int type ) { NOTE_DATA *pnote; if ( ch->pnote != NULL ) return; pnote = new_note(); pnote->next = NULL; pnote->sender = str_dup( ch->name ); pnote->date = str_dup( "" ); pnote->to_list = str_dup( "" ); pnote->subject = str_dup( "" ); pnote->text = str_dup( "" ); pnote->type = type; ch->pnote = pnote; return; } void parse_journal( CHAR_DATA *ch, char *argument, int type ) { char arg[MAX_INPUT_LENGTH]; char buf[MAX_STRING_LENGTH]; EXTRA_DESCR_DATA *ed; BUFFER *buffer; BUFFER *keybuf; BUFFER *descbuf; OBJ_DATA *obj; int x = 0; /* Handle IMMs who are switched into MOBs */ if (IS_NPC(ch)) { send_to_char ( "MOBS can't make journals.\n\r", ch ); return; } /* Do we have any ink ? * If you decided to not use the INK object, remove this * FOR loop. */ for ( obj = ch->carrying; obj; obj = obj->next_content ) { if ( obj->item_type == ITEM_INK ) break; } /* Can't find any ink * If you decided to not use the INK object, remove this * IF statement. */ if ( !obj ) { send_to_char( "You do not have any ink in your inventory.\n\r", ch ); return; } /* Do we have a quill? * If you decided to not use the QUILL object, remove this * FOR loop. */ for ( obj = ch->carrying; obj; obj = obj->next_content ) { if ( obj->item_type == ITEM_QUILL ) break; } /* Can't find a quill * If you decided to not use the QUILL object, remove this * IF statement. */ if ( !obj ) { send_to_char( "You do not have a quill in your inventory.\n\r", ch ); return; } /* Do we have a journal ? * Make sure this FOR loop is always placed after the above two * FOR loops. Otherwise, the code will think the INK or QUILL * objects are the journal and all extra description info will be * added to the INK or QUILL. */ for ( obj = ch->carrying; obj; obj = obj->next_content ) { if ( obj->item_type == ITEM_JOURNAL ) break; } /* Can't find a journal */ if ( !obj ) { send_to_char( "You do not own a journal. Go purchase one.\n\r", ch ); return; } argument = one_argument( argument, arg ); smash_tilde( argument ); if ( arg[0] == '\0' ) { send_to_char( "{WSyntax:{x journal \n\r", ch ); send_to_char( "{WSyntax:{x journal + \n\r", ch ); send_to_char( "{WSyntax:{x journal - \n\r", ch ); send_to_char( "{WSyntax:{x journal \n\r", ch ); send_to_char( "{WSyntax:{x journal \n\r", ch ); send_to_char( "{WSyntax:{x journal \n\r", ch ); return; } if ( !str_prefix( arg, "add" ) ) { journal_attach( ch, type ); if (ch->pnote->type != type) { send_to_char("You already have a different note in progress.\n\r",ch); return; } /* Does the journal already have a journal entry (extra description) ? * If so, is the name of the journal entry being added the same as an * existing journal entry ? If so, stop and tell the player they can't * do that. * * This loop is also used to count the number of extra descriptions the * journal has. I set a limit of 10 journal entries per journal. Afterall, * the journal only has so much paper. Feel free to remove the limit or * change it to whatever you want. */ if ( obj->extra_descr != NULL ) { for ( ed = obj->extra_descr; ed != NULL; ed = ed->next ) { if ( (ed->keyword == str_dup( argument )) ) { send_to_char( "This journal already has an entry with that name.\n\r", ch ); return; } x += 1; } } if ( x > 9 ) { send_to_char( "You have run out of blank pages in your journal.\n\r", ch ); send_to_char( "Time to buy a new one.\n\r", ch ); return; } free_string( ch->pnote->to_list ); free_string( ch->pnote->subject ); ch->pnote->subject = str_dup( argument ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_cmp( arg, "+" ) ) { journal_attach( ch,type ); if (ch->pnote->type != type) { send_to_char("You already have a different note in progress.\n\r",ch); return; } if (strlen(ch->pnote->text)+strlen(argument) >= 4096) { send_to_char( "Journal entry too long.\n\r", ch ); return; } buffer = new_buf(); add_buf(buffer, ch->pnote->text); add_buf(buffer, argument); add_buf(buffer,"\n\r"); free_string( ch->pnote->text ); ch->pnote->text = str_dup( buf_string(buffer) ); free_buf(buffer); send_to_char( "Ok.\n\r", ch ); return; } if (!str_cmp(arg,"-")) { int len; bool found = FALSE; journal_attach(ch,type); if (ch->pnote->type != type) { send_to_char("You already have a different note in progress.\n\r",ch); return; } if (ch->pnote->text == NULL || ch->pnote->text[0] == '\0') { send_to_char("No lines left to remove.\n\r",ch); return; } strcpy(buf,ch->pnote->text); for (len = strlen(buf); len > 0; len--) { if (buf[len] == '\r') { if (!found) { if (len > 0) len--; found = TRUE; } else { buf[len + 1] = '\0'; free_string(ch->pnote->text); ch->pnote->text = str_dup(buf); return; } } } buf[0] = '\0'; free_string(ch->pnote->text); ch->pnote->text = str_dup(buf); return; } if ( !str_prefix( arg, "clear" ) ) { if ( ch->pnote != NULL ) { free_note(ch->pnote); ch->pnote = NULL; } send_to_char( "Ok.\n\r", ch ); return; } if ( !str_prefix( arg, "show" ) ) { if ( ch->pnote == NULL ) { send_to_char( "You have no journal entry in progress.\n\r", ch ); return; } if (ch->pnote->type != type) { send_to_char("You aren't working on that kind of note.\n\r",ch); return; } send_to_char( "Journal Entry: ", ch ); send_to_char( ch->pnote->subject, ch ); send_to_char( "\n\r\n\r", ch ); send_to_char( ch->pnote->text, ch ); return; } if ( !str_prefix( arg, "post" ) ) { if ( ch->pnote == NULL ) { send_to_char( "You have no journal entry in progress.\n\r", ch ); return; } if (ch->pnote->type != type) { send_to_char("You aren't working on that kind of note.\n\r",ch); return; } /* The following lines of code attach the name of the journal entry * to the extra description as the keyword and also adds all the text * entered by the player to the description of the keyword. */ ed = new_extra_descr(); keybuf = new_buf(); add_buf ( keybuf, ch->pnote->subject ); ed->keyword = str_dup( buf_string( keybuf ) ); buffer = new_buf(); sprintf( buf, "Author: %s\n\r\n\r", ch->name ); add_buf( buffer, buf ); add_buf( buffer, ch->pnote->text ); ed->description = str_dup( buf_string( buffer ) ); ed->next = obj->extra_descr; obj->extra_descr = ed; /* The following lines of code modify the journals long description. * It adds the name of the journal entry to the long description which * allows players to look at the journal and see what journal entries * have been made to the journal. */ descbuf = new_buf(); sprintf( buf, obj->description ); free_string( obj->description ); add_buf( descbuf, buf ); sprintf( buf, "\n\rJournal Entry: {c%s{x\n\r", ch->pnote->subject ); add_buf( descbuf, buf ); obj->description = str_dup( buf_string( descbuf ) ); free_buf( descbuf ); free_buf( buffer ); free_buf( keybuf ); ch->pnote = NULL; send_to_char("Your journal entry has been posted.\n\r",ch); return; } send_to_char( "{WSyntax:{x journal \n\r", ch ); send_to_char( "{WSyntax:{x journal + \n\r", ch ); send_to_char( "{WSyntax:{x journal - \n\r", ch ); send_to_char( "{WSyntax:{x journal \n\r", ch ); send_to_char( "{WSyntax:{x journal \n\r", ch ); send_to_char( "{WSyntax:{x journal \n\r", ch ); return; } Save and close act_obj.c Delete all of your .O files and a recompile. You're done. You will want to make the INK, QUILL and JOURNAL objects for sale by some of your shopkeeper mobs. If you have no idea how to add resets (Why not ??), get your builder to do it, or actually read the docs that come with ROM :). If you have any problems installing this code, you can reach me at information listed at the top of this file. The following is the associated help file entry for the journal code. -1 JOURNALS~ . Syntax: journal journal + journal - journal journal journal The journal command allows you to create you own personal journal entries and save them to a journal. You can purchase a journal and the necessary ink and quill from many stores in the three major cities of Amaron. The journal command functions very similar to the note system. Use the add command to add a new journal entry. Ex: {cjournal add Page1{x. To add lines of text to the journal entry "Page1", use the {cjournal +{x command. Ex: journal + It was a dark and stormy night. The {cjournal -{x command will remove the last line of text entered and {cjournal clear{x will remove and clear the entire journal entry and all lines of text that were entered. The {cjournal show{x command will display the name of the journal entry and the current text that has been entered. Ex: {cjournal show{x Journal Entry: Page1 It was a dark and stormy night. Once you are satisfied with your journal entry, use the {cjournal post{x command to save the journal entry into your journal. You can save a maximum of ten (10) journal entries to one journal. Also keep in mind you cannot add a journal entry if the same name already has been used in the journal. So, you cannot have to entries called "Page1". When you wish to read a journal entry, look at the journal. Ex: look journal. You will a description similar to the following: A leather journal with many pages of writing. Journal Entry: Page1 Journal Entry: Page2 This will tell you what journal entries are contained in this journal. To read them, look at a journal entries name. Ex: look Page1 Journal Code written by Felix of Amaron Mud. ~