.-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-. 
 |                                                                       | 
 |                                                                       | 
 |                                                                       | 
 |                         EXTRA IDENTIFY LINES                          | 
 |                                                                       | 
 !                                                                       ! 
 :                         A Snippet written by                          : 
 :                              Valcados                                 : 
 .                           for SMAUG 1.02                              . 
 .                                                                       . 
 :                                                                       : 
 :                                                                       : 
 !                                                                       ! 
 |                                                                       | 
 |                                                                       | 
 |                                                                       | 
 |                                                                       | 
 |                                                                       | 
 `-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-'

DESCRIPTION:
     This snippet allows builders to add extra lines to an item's
     diagnosis on "identify" and "auction".  This is quite nice for
     cases where a prog has been used to similate a flag which
     doesn't exist, for example, if an item is made to reject males
     from wearing it, you could add a line:
     "This item cannot be equipped by males."
     You can even use this to add fake stat lines:
     "Affects hitpoints by 25,000.  (Just Kidding!)"
     Another fun use is to add in-character notes on the item,
     "An old prophecy states this sword will slay the evil wizard."

TESTING:
     This has been in use at the Lands of Aethar (www.aethar.com)
     for a few years and has caused no problems that we know of
     so far.  However, in writing this snippet, I changed the way
     the extra id lines are saved in the area file, to be more
     agreeable with stock SMAUG, and that part is untested...

KNOWN PROBLEMS/BUGS:
     None to my knowledge, assuming the ad hoc area-saving
     changes mentioned above work correctly.

IN-GAME MECHANICS:
     Use oset to add extra idstrings:
     oset raft idstring Ahh, the raft of Captain Sparrow!

     You can optionally put color in the custom idstring
     using the usual color tokens.

     Uset "oset rmidstring (number)" to remove an idstring.

HOW TO INSTALL:

1.  In act_obj.c, in do_auction, declare the new variable:

    id_string *ids;

2.  Further down in do_auction, find something like this:

	    for ( paf = obj->pIndexData->first_affect; paf; paf = paf->next )
		showaffect( ch, paf );

Right above it, add this:

            for ( ids = obj->pIndexData->first_id_string; ids; ids = ids->next )
            {
              ch_printf_color( ch, "%s\n\r", ids->txt );
              set_char_color( AT_BLUE, ch );
            }

3.  In act_wiz.c, in do_ostat, add the following variable declaration:

     id_string *ids;

4.  Further down in do_ostat, find something like this:

    for ( paf = obj->pIndexData->first_affect; paf; paf = paf->next )
	ch_printf_color( ch, "&cAffects &w%s &cby &w%d.\n\r",
	    affect_loc_name( paf->location ), paf->modifier );

Below it, add this:

        for ( ids = obj->pIndexData->first_id_string; ids; ids = ids->next )
        ch_printf_color( ch, "&BExtra ID_STRING: %s\n\r", ids->txt );

5.  In build.c, in do_oset, find the block where the MUD lists
    the fields (when a builder types oset with no argument).
    It looks something like this...

	    send_to_char( "Syntax: oset <object> <field>  <value>\n\r",	ch );
	send_to_char( "\n\r",						ch );
	send_to_char( "Field being one of:\n\r",			ch );
	send_to_char( "  flags wear level weight cost rent timer\n\r",	ch );
	send_to_char( "  name short long ed rmed actiondesc\n\r",	ch );
	send_to_char( "  type value0 value1 value2 value3 value4 value5\n\r",	ch );
	send_to_char( "  affect rmaffect layers\n\r",				ch );

Wherever you think it looks it fits in best (for example after "layers"),
simply add "idstring" and "rmidstring" to the list.

6.  Further down in do_oset, find something like this:

    if ( !str_cmp( arg2, "ed" ) )

Right above it, add the following:

    if ( !str_cmp( arg2, "idstring" ) || !str_cmp( arg2, "id_string" ) )
    {
      id_string *ids;
      if ( !arg3 || !*arg3 )
      {
        send_to_char( "Syntax: oset <object> idstring <identify string>\n\r", ch );
        return;
      }
      if ( !can_omodify( ch, obj ) )
      {
        send_to_char( "You can't modify this object.\n\r", ch );
        return;
      }
      if ( !IS_OBJ_STAT(obj,ITEM_PROTOTYPE) )
      {
        send_to_char( "This item isn't a prototype!\n\r", ch );
        return;
      }
      CREATE( ids, id_string, 1 );
      ids->txt = str_alloc( arg3 );
      LINK( ids, obj->pIndexData->first_id_string,
                 obj->pIndexData->last_id_string, next, prev );
      send_to_char( "Done.\n\r", ch );
      return;
    }

    if ( !str_cmp( arg2, "rmidstring" )
    ||   !str_cmp( arg2, "rmid" ) )
    {
      int count = 0;
      id_string *ids;
      if ( !arg3 || !*arg3 || !is_number(arg3) )
      {
       send_to_char( "Syntax: oset <objext> rmid <# of idstring to remove>\n\r", ch );
       return;
      }
      if ( !can_omodify( ch, obj ))
      {
       send_to_char( "You can't modify this object.\n\r", ch );
       return;
      }
      if ( !IS_OBJ_STAT(obj,ITEM_PROTOTYPE) )
      {
        send_to_char( "This item isn't a prototype!\n\r", ch );
        return;
      }
      for ( ids = obj->pIndexData->first_id_string; ids; ids = ids->next)
      if ( ++count == atoi( arg3 ) )
      break;

      if ( ids )
      {
       UNLINK( ids, obj->pIndexData->first_id_string,
                    obj->pIndexData->last_id_string, next, prev );
       str_free( ids->txt );
       free( ids );
       send_to_char( "Removed.\n\r", ch );
       return;
      }
      ch_printf( ch, "Object doesn't have an idstring #%d", atoi(arg3));
      return;
    }

7.  Further down in do_oset, find something like this:

	if ( obj->item_type == ITEM_PAPER && get_trust(ch) < LEVEL_IMPLEMENTOR )
	{
	   send_to_char("You can not add an extra description to a note paper at the moment.\n\r", ch);
	   return;
	}

Below it, add this:

	if ( !str_cmp( arg3, "idstring" ) )
        {
           send_to_char( "Sorry, but that's an illegal extra description keyword.\n\r", ch );
           return;
        }

8.  In build.c, in function fold_area, find something like this:

	for ( ed = pObjIndex->first_extradesc; ed; ed = ed->next )
	   fprintf( fpout, "E\n%s~\n%s~\n",
			ed->keyword, strip_cr( ed->description )	);

Below it, add this:

	for ( ids = pObjIndex->first_id_string; ids; ids = ids->next )
           fprintf( fpout, "E\nidstring~\n%s~\n", strip_cr( ids->txt ) );

9.  In db.c, in load_objects, find something like this:

	pObjIndex->action_desc		= fread_string( fp );

Below it, add this:

        pObjIndex->first_id_string = NULL;
        pObjIndex->last_id_string = NULL;

10. In db.c, in load_objects, find something like this:

	    else if ( letter == 'E' )
	    {
		EXTRA_DESCR_DATA *ed;

		CREATE( ed, EXTRA_DESCR_DATA, 1 );
		ed->keyword		= fread_string( fp );
		ed->description		= fread_string( fp );
		LINK( ed, pObjIndex->first_extradesc, pObjIndex->last_extradesc,
			  next, prev );
		top_ed++;
	    }

Change it to the following:

	    else if ( letter == 'E' )
	    {
		EXTRA_DESCR_DATA *ed;
                char *ed_key = fread_string( fp );
                id_string *ids;

                if ( !str_cmp( ed_key, "idstring" ) )
                {
                  str_free( ed_key );
                  CREATE( ids, id_string, 1 );
                  ids->txt = fread_string( fp );
                  LINK( ids, pObjIndex->first_id_string, pObjIndex->last_id_string, next, prev );
                }   
                else
                {
		  CREATE( ed, EXTRA_DESCR_DATA, 1 );
		  ed->keyword		= ed_key;
		  ed->description		= fread_string( fp );
		  LINK( ed, pObjIndex->first_extradesc, pObjIndex->last_extradesc,
			  next, prev );
		  top_ed++;
                }
	    }

11. In db.c, in function delete_room, add this variable declaration:

  id_string *ids;

12. Further down in delete_room, find something like this;

  while ((mp = room->mudprogs) != NULL)
  {
    room->mudprogs = mp->next;
    STRFREE(mp->arglist);
    STRFREE(mp->comlist);
    DISPOSE(mp);
  }

Below it, add the following:

  while ((ids = obj->first_id_string) != NULL )
  {
    obj->first_id_string = ids->next;
    str_free( ids->txt );
    free( ids );
  }

13. In db.c, in function make_object, add this variable declaration:

        id_string *ids, *ids2;

14. Further down in make_object, find something like this:

	  pObjIndex->cost		= 0;

Below it, add this:

          pObjIndex->first_id_string = NULL;
          pObjIndex->last_id_string = NULL;

15. Further down in make_object, find something like this:

	  pObjIndex->cost		= cObjIndex->cost;

Below it, add this:

          pObjIndex->first_id_string = NULL;
          pObjIndex->last_id_string = NULL;
          if ( cObjIndex->first_id_string )
          {
            for ( ids = cObjIndex->first_id_string; ids; ids = ids->next )
            {
              CREATE( ids2, id_string, 1 );
              ids2->txt = quick_link(ids->txt);
              LINK(ids2, pObjIndex->first_id_string, pObjIndex->last_id_string,
                    next, prev );
            }
          }

16. In handler.c, in function clean_obj, add this variable declaration:

        id_string *ids, *ids_next;

17. Further down in clean_obj, find something like this:

	obj->first_extradesc	= NULL;
	obj->last_extradesc	= NULL;

Below that, add this:

        for ( ids = obj->first_id_string; ids; ids = ids_next )
        {
          ids_next = ids->next;
          UNLINK( ids, obj->first_id_string, obj->last_id_string, next, prev );
          str_free( ids->txt );
          free( ids );
        }

18. In magic.c, in function spell_identify, add this variable declaration:

    id_string *ids;

19. Further down in spell_identify, find something like this:

    for ( paf = obj->pIndexData->first_affect; paf; paf = paf->next )
	showaffect( ch, paf );

Just above that, add this:

    for ( ids = obj->pIndexData->first_id_string; ids; ids = ids->next )
    {
     ch_printf_color( ch, "%s\n\r", ids->txt );
     set_char_color( AT_MAGIC, ch );
    }

20. In mud.h, find something like this:

typedef	struct	lang_data		LANG_DATA;

Below that, add this:

typedef struct ID_STRING id_string;

21. In mud.h, find the obj_index_data structure and give it these two new elements:

        id_string *first_id_string;
        id_string *last_id_string;

22. In mud.h, find something like this:

struct tourney_data
{
    int    open;
    int    low_level;
    int    hi_level;
};

Below it, add this:

struct ID_STRING
{
  id_string *next;
  id_string *prev;
  char *txt;
};


23. Recompile, reboot, and have some fun!!! :)