/****************************************************************************
 * [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame      |   \\._.//   *
 * -----------------------------------------------------------|   (0...0)   *
 * SMAUG 1.4 (C) 1994, 1995, 1996, 1998  by Derek Snider      |    ).:.(    *
 * -----------------------------------------------------------|    {o o}    *
 * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus,      |   / ' ' \   *
 * Scryn, Rennard, Swordbearer, Gorog, Grishnakh, Nivek,      |~'~.VxvxV.~'~*
 * Tricops and Fireblade                                      |             *
 * ------------------------------------------------------------------------ *
 * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael        *
 * Chastain, Michael Quan, and Mitchell Tse.                                *
 * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,          *
 * Michael Seifert, Hans Henrik Starfeldt, Tom Madsen, and Katja Nyboe.     *
 * ------------------------------------------------------------------------ *
 *			 Package delivery module			    *
 *   Written by Aurora (EternalEmpress@LostProphecy.com) 'just because'     *
 ****************************************************************************/
/* need to add


  const char *gotmail = "<You've Got Mail!>\n\r";
to display_prompt in comm.c

add to mud.h:

>>>> #define PCFLAG_GOTMAIL                BV21 (inform they have mail)
needs to be: PLR_GOTMAIL, in other defines, not PCFLAG.



#define MAIL_DIR      "../mail/"/ (Player mail files, dont forget to actually create)
#define ACT_MAIL			 28		(Post Office Mob)
(be sure to add act_mail into an empty slot with the other ACT_'s in mud.h)

to comm.c add:
  const char *gotmail = "[MAIL]";

and:
  if ( !IS_NPC(ch) && xIS_SET(ch->act, PLR_GOTMAIL ) )
    send_to_char( gotmail, ch );
just above the check for helpstart

In Nanny Below:
    mail_count(ch);
Add:
    if (ch->level > 1)
    {
	char motdbuf[MAX_STRING_LENGTH];
        FILE *fp;

        sprintf( motdbuf, "%s%s", MAIL_DIR, capitalize( ch->name ) );
        if ( ( fp = fopen( motdbuf, "r" ) ) != NULL )
         {
         xSET_BIT(ch->act, PLR_GOTMAIL);
         fclose(fp);
         }
    }


*/



#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "mud.h"


void fwrite_delivery( CHAR_DATA *ch, OBJ_DATA *obj )
{
    FILE *fp = NULL;
    char strsave[MAX_INPUT_LENGTH];
    EXTRA_DESCR_DATA *ed;
    AFFECT_DATA *paf;
    sh_int wear, wear_loc, x;

    if( !obj )
    {
	bug( "Fwrite_delivery: NULL object.", 0 );
	bug( ch->name, 0 );
        return;
    }

    sprintf( strsave, "%s%s", MAIL_DIR, capitalize( ch->name ) );
    
    if ( ( fp = fopen( strsave, "w" ) ) != NULL )
    {

    fprintf( fp, "#OBJECT\n");

    if ( obj->count > 1 )
	fprintf( fp, "Count        %d\n",	obj->count	     );
    if ( QUICKMATCH( obj->name, obj->pIndexData->name ) == 0 )
	fprintf( fp, "Name         %s~\n",	obj->name	     );
    if ( QUICKMATCH( obj->short_descr, obj->pIndexData->short_descr ) == 0 )
	fprintf( fp, "ShortDescr   %s~\n",	obj->short_descr     );
    if ( QUICKMATCH( obj->description, obj->pIndexData->description ) == 0 )
	fprintf( fp, "Description  %s~\n",	obj->description     );
    if ( QUICKMATCH( obj->action_desc, obj->pIndexData->action_desc ) == 0 )
	fprintf( fp, "ActionDesc   %s~\n",	obj->action_desc     );
    fprintf( fp, "Vnum         %d\n",	obj->pIndexData->vnum	     );
    if ( !xSAME_BITS(obj->extra_flags, obj->pIndexData->extra_flags) )
	fprintf( fp, "ExtraFlags   %s\n",	print_bitvector(&obj->extra_flags) );
    if ( obj->wear_flags != obj->pIndexData->wear_flags )
	fprintf( fp, "WearFlags    %d\n",	obj->wear_flags	     );
    wear_loc = -1;
    for ( wear = 0; wear < MAX_WEAR; wear++ )
	for ( x = 0; x < MAX_LAYERS; x++ )
	   if ( obj == save_equipment[wear][x] )
	   {
		wear_loc = wear;
		break;
	   }
	   else
	   if ( !save_equipment[wear][x] )
		break;
    if ( wear_loc != -1 )
	fprintf( fp, "WearLoc      %d\n",	wear_loc	     );
    if ( obj->item_type != obj->pIndexData->item_type )
	fprintf( fp, "ItemType     %d\n",	obj->item_type	     );
    if ( obj->weight != obj->pIndexData->weight )
      fprintf( fp, "Weight       %d\n",	obj->weight		     );
    if ( obj->level )
      fprintf( fp, "Level        %d\n",	obj->level		     );
    if ( obj->timer )
      fprintf( fp, "Timer        %d\n",	obj->timer		     );
    if ( obj->cost != obj->pIndexData->cost )
      fprintf( fp, "Cost         %d\n",	obj->cost		     );
    if ( obj->value[0] || obj->value[1] || obj->value[2]
    ||   obj->value[3] || obj->value[4] || obj->value[5] )
      fprintf( fp, "Values       %d %d %d %d %d %d\n",
	obj->value[0], obj->value[1], obj->value[2],
	obj->value[3], obj->value[4], obj->value[5]     );

    switch ( obj->item_type )
    {
    case ITEM_PILL: /* was down there with staff and wand, wrongly - Scryn */
    case ITEM_POTION:
    case ITEM_SCROLL:
	if ( IS_VALID_SN(obj->value[1]) )
	    fprintf( fp, "Spell 1      '%s'\n",
		skill_table[obj->value[1]]->name );

	if ( IS_VALID_SN(obj->value[2]) )
	    fprintf( fp, "Spell 2      '%s'\n",
		skill_table[obj->value[2]]->name );

	if ( IS_VALID_SN(obj->value[3]) )
	    fprintf( fp, "Spell 3      '%s'\n",
		skill_table[obj->value[3]]->name );

	break;

    case ITEM_STAFF:
    case ITEM_WAND:
	if ( IS_VALID_SN(obj->value[3]) )
	    fprintf( fp, "Spell 3      '%s'\n",
		skill_table[obj->value[3]]->name );

	break;
    case ITEM_SALVE:
	if ( IS_VALID_SN(obj->value[4]) )
	    fprintf( fp, "Spell 4      '%s'\n",
		skill_table[obj->value[4]]->name );

	break;
    }

    for ( paf = obj->first_affect; paf; paf = paf->next )
    {
	/*
	 * Save extra object affects				-Thoric
	 */
	if ( paf->type < 0 || paf->type >= top_sn )
	{
	  fprintf( fp, "Affect       %d %d %ld %d %s\n",
	    paf->type,
	    paf->duration,
	     ((paf->location == APPLY_WEAPONSPELL
	    || paf->location == APPLY_WEARSPELL
	    || paf->location == APPLY_REMOVESPELL
	    || paf->location == APPLY_STRIPSN
	    || paf->location == APPLY_RECURRINGSPELL)
	    && IS_VALID_SN(paf->modifier))
	    ? skill_table[paf->modifier]->slot : paf->modifier,
	    paf->location,
	    print_bitvector(&paf->bitvector)
	    );
	}
	else
	  fprintf( fp, "AffectData   '%s' %d %ld %d %s\n",
	    skill_table[paf->type]->name,
	    paf->duration,
	     ((paf->location == APPLY_WEAPONSPELL
	    || paf->location == APPLY_WEARSPELL
	    || paf->location == APPLY_REMOVESPELL
	    || paf->location == APPLY_STRIPSN
	    || paf->location == APPLY_RECURRINGSPELL)
	    && IS_VALID_SN(paf->modifier))
	    ? skill_table[paf->modifier]->slot : paf->modifier,
	    paf->location,
	    print_bitvector(&paf->bitvector)
	    );
    }

    for ( ed = obj->first_extradesc; ed; ed = ed->next )
	fprintf( fp, "ExtraDescr   %s~ %s~\n",
	    ed->keyword, ed->description );
    if ( obj->runenum )
      fprintf( fp, "Runenum   %d\n", obj->runenum      );
    if ( obj->runedesc )
      fprintf( fp, "Runedesc  %s~\n", obj->runedesc     );

    fprintf( fp, "End\n\n" );

    if ( obj->first_content )
	fwrite_obj( ch, obj->last_content, fp, 0, OS_CARRY );

}
        fprintf( fp, "#END \n\r" ); 
        fclose( fp );
    return;
}



void do_deliver( CHAR_DATA *ch, char *argument )
{ 
   OBJ_DATA * obj;
   char arg[MAX_INPUT_LENGTH];  
   char arg2[MAX_INPUT_LENGTH];
   char arg3[MAX_INPUT_LENGTH];
   char strsave[MAX_INPUT_LENGTH];
   char mobbuf[MAX_INPUT_LENGTH];
   CHAR_DATA * victim;
   CHAR_DATA * mob;
   FILE *fp = NULL;
   int cost;
  
   argument = one_argument( argument, arg );
   argument = one_argument( argument, arg2 );
   argument = one_argument( argument, arg3 );

   if (IS_NPC(ch))
    return;

   for ( mob = ch->in_room->first_person; mob; mob = mob->next_in_room )
	    if ( IS_NPC(mob) && xIS_SET(mob->act, ACT_MAIL) )
		break;
   if ( !mob )
   {
	    send_to_char( "You need to visit the post office.\n\r", ch );
	    return;
   }


   if ( arg[0] == '\0' )
   {
     send_to_char( "Deliver what to who?\n\r", ch );
     send_to_char( "Syntax: deliver <object> <player>\n\r", ch );
     return;
   }
   if ( !str_cmp( arg, "pickup" ))
   {
        sprintf( strsave, "%s%s", MAIL_DIR, capitalize( ch->name ) );
    
        if ( ( fp = fopen( strsave, "r" ) ) != NULL )
        {
          for ( ; ; )
          {
            char letter;
            char *word;
            
            letter = fread_letter( fp );
            if ( letter == '#')
            {
              word = fread_word( fp );
  
              if (!strcmp(word,"END" ))
                   break;
                             
              if (!strcmp(word,"OBJECT"))
                fread_obj( ch, fp, OS_CARRY );
            }
          }    
          fclose( fp );
          if ( !remove( strsave ) )
          {
           send_to_char( "You retrive your delivery.\n\r", ch );
           xREMOVE_BIT(ch->act, PLR_GOTMAIL);
          }
          else if ( errno != ENOENT )
           bug( "Delivery unable to delete mailbox.\n\r", 0 );
         return;
        }
        else
        {
         send_to_char( "You currently have no deliveries.\n\r", ch );
         return;
        }
   }
   if ( ms_find_obj(ch) )
     return;
	
   if ( !( obj = get_obj_carry( ch, arg ) ) )
   {
     send_to_char( "You do not have that item.\n\r", ch );
     return;
   }
   separate_obj(obj); 
   if ( IS_OBJ_STAT( obj, ITEM_NODROP ) || IS_OBJ_STAT( obj, ITEM_PROTOTYPE))
   {
    sprintf( mobbuf, "I'm sorry we dont handle objects of that nature.");
    do_say(mob, mobbuf);
     return;
   }

    if ( ( victim = get_char_world( ch, arg2 ) ) == NULL || IS_NPC(victim))
   {
    sprintf( mobbuf, "They're not here right now... let me check their mailbox.");
    do_say(mob, mobbuf);
    sprintf( strsave, "%s%c/%s", PLAYER_DIR, tolower(arg2[0]), capitalize( arg2 ) );
    if ( ( fp = fopen( strsave, "r" ) ) != NULL ) ;
    else
    {
     sprintf( mobbuf, "I dont have a mailbox for %s... Are you sure thats the correct name?", capitalize( arg2) );
     do_say(mob, mobbuf);
     return;
    }
    sprintf( strsave, "%s%s", MAIL_DIR, capitalize( arg2 ) );
    if ( ( fp = fopen( strsave, "r" ) ) != NULL )
    {
          fclose( fp );
     sprintf( mobbuf, "Oh... I'm sorry, But that mailbox is already full. Anything else i can do for you?");
     do_say(mob, mobbuf);
     return;
    }
    else
    {
    cost= obj->level*300; 

    if ( ch->gold - cost < 0)
   {
     send_to_char( "You cant afford to send that to them.\n\r", ch );
     return;
   }
    ch->gold -= cost;
    if ( ( fp = fopen( strsave, "w" ) ) != NULL )
    {
	    EXTRA_DESCR_DATA *ed;
 	    AFFECT_DATA *paf;
	    sh_int wear, wear_loc, x;

            /* Yes its redundant... But it works */
	    fprintf( fp, "#OBJECT\n");

	    if ( obj->count > 1 )
		fprintf( fp, "Count        %d\n",	obj->count	     );
	    if ( QUICKMATCH( obj->name, obj->pIndexData->name ) == 0 )
		fprintf( fp, "Name         %s~\n",	obj->name	     );
	    if ( QUICKMATCH( obj->short_descr, obj->pIndexData->short_descr ) == 0 )
		fprintf( fp, "ShortDescr   %s~\n",	obj->short_descr     );
	    if ( QUICKMATCH( obj->description, obj->pIndexData->description ) == 0 )
		fprintf( fp, "Description  %s~\n",	obj->description     );
	    if ( QUICKMATCH( obj->action_desc, obj->pIndexData->action_desc ) == 0 )
		fprintf( fp, "ActionDesc   %s~\n",	obj->action_desc     );
	    fprintf( fp, "Vnum         %d\n",	obj->pIndexData->vnum	     );
	    if ( !xSAME_BITS(obj->extra_flags, obj->pIndexData->extra_flags) )
		fprintf( fp, "ExtraFlags   %s\n",	print_bitvector(&obj->extra_flags) );
	    if ( obj->wear_flags != obj->pIndexData->wear_flags )
		fprintf( fp, "WearFlags    %d\n",	obj->wear_flags	     );
	    wear_loc = -1;
	    for ( wear = 0; wear < MAX_WEAR; wear++ )
		for ( x = 0; x < MAX_LAYERS; x++ )
		   if ( obj == save_equipment[wear][x] )
		   {
			wear_loc = wear;
			break;
		   }
		   else
		   if ( !save_equipment[wear][x] )
			break;
	    if ( wear_loc != -1 )
		fprintf( fp, "WearLoc      %d\n",	wear_loc	     );
	    if ( obj->item_type != obj->pIndexData->item_type )
		fprintf( fp, "ItemType     %d\n",	obj->item_type	     );
 	   if ( obj->weight != obj->pIndexData->weight )
	      fprintf( fp, "Weight       %d\n",	obj->weight		     );
	    if ( obj->level )
	      fprintf( fp, "Level        %d\n",	obj->level		     );
	    if ( obj->timer )
	      fprintf( fp, "Timer        %d\n",	obj->timer		     );
	    if ( obj->cost != obj->pIndexData->cost )
	      fprintf( fp, "Cost         %d\n",	obj->cost		     );
	    if ( obj->value[0] || obj->value[1] || obj->value[2]
	    ||   obj->value[3] || obj->value[4] || obj->value[5] )
	      fprintf( fp, "Values       %d %d %d %d %d %d\n",
		obj->value[0], obj->value[1], obj->value[2],
		obj->value[3], obj->value[4], obj->value[5]     );

	    switch ( obj->item_type )
	    {
	    case ITEM_PILL: /* was down there with staff and wand, wrongly - Scryn */
	    case ITEM_POTION:
	    case ITEM_SCROLL:
		if ( IS_VALID_SN(obj->value[1]) )
		    fprintf( fp, "Spell 1      '%s'\n",
			skill_table[obj->value[1]]->name );

		if ( IS_VALID_SN(obj->value[2]) )
		    fprintf( fp, "Spell 2      '%s'\n",
			skill_table[obj->value[2]]->name );

		if ( IS_VALID_SN(obj->value[3]) )
		    fprintf( fp, "Spell 3      '%s'\n",
			skill_table[obj->value[3]]->name );

		break;

	    case ITEM_STAFF:
	    case ITEM_WAND:
		if ( IS_VALID_SN(obj->value[3]) )
		    fprintf( fp, "Spell 3      '%s'\n",
			skill_table[obj->value[3]]->name );

		break;
	    case ITEM_SALVE:
		if ( IS_VALID_SN(obj->value[4]) )
		    fprintf( fp, "Spell 4      '%s'\n",
			skill_table[obj->value[4]]->name );

		break;
	    }

	    for ( paf = obj->first_affect; paf; paf = paf->next )
   	 {
		/*
		 * Save extra object affects				-Thoric
		 */
		if ( paf->type < 0 || paf->type >= top_sn )
		{
		  fprintf( fp, "Affect       %d %d %ld %d %s\n",
		    paf->type,
		    paf->duration,
		     ((paf->location == APPLY_WEAPONSPELL
		    || paf->location == APPLY_WEARSPELL
		    || paf->location == APPLY_REMOVESPELL
		    || paf->location == APPLY_STRIPSN
		    || paf->location == APPLY_RECURRINGSPELL)
		    && IS_VALID_SN(paf->modifier))
		    ? skill_table[paf->modifier]->slot : paf->modifier,
		    paf->location,
		    print_bitvector(&paf->bitvector)
		    );
		}
		else
		  fprintf( fp, "AffectData   '%s' %d %ld %d %s\n",
	    	skill_table[paf->type]->name,
	    	paf->duration,
		     ((paf->location == APPLY_WEAPONSPELL
		    || paf->location == APPLY_WEARSPELL
		    || paf->location == APPLY_REMOVESPELL
		    || paf->location == APPLY_STRIPSN
		    || paf->location == APPLY_RECURRINGSPELL)
		    && IS_VALID_SN(paf->modifier))
		    ? skill_table[paf->modifier]->slot : paf->modifier,
		    paf->location,
		    print_bitvector(&paf->bitvector)
		    );
	    }

	    for ( ed = obj->first_extradesc; ed; ed = ed->next )
		fprintf( fp, "ExtraDescr   %s~ %s~\n",
		    ed->keyword, ed->description );
	    if ( obj->runenum )
	      fprintf( fp, "Runenum   %d\n", obj->runenum      );
	    if ( obj->runedesc )
	      fprintf( fp, "Runedesc  %s~\n", obj->runedesc     );

	    fprintf( fp, "End\n\n" );

	    if ( obj->first_content )
		fwrite_obj( ch, obj->last_content, fp, 0, OS_CARRY );

	}
        fprintf( fp, "#END \n\r" ); 
        fclose( fp );
    }
     sprintf( mobbuf, "Ok, I've put it in their mailbox for them. Thanks and may I assist you further %s?.", ch->name );
     do_say(mob, mobbuf);
     extract_obj(obj);
    return;

    }
   if ( !str_cmp( arg3, "express" ))
   {
    cost= obj->level*400; 

    if (victim == ch)
    {
     sprintf( mobbuf, "I'm not gonna waste my time delivering to you FROM you %s!", ch->name );
     do_say(mob, mobbuf);
     return;
    }

    if (IS_SET(victim->in_room->room_flags, ROOM_ARENA))
    {
     sprintf( mobbuf, "They're in the Arena. My couriers can't go there, so you'll have to wait until they get out.");
     do_say(mob, mobbuf);
     return;
    }
    if (!IS_PKILL(ch) && IS_PKILL(victim))
    {
     sprintf( mobbuf, "I'm not about to send an item from a Peaceful to a Deadly. Thats forbidden!");
     do_say(mob, mobbuf);
     return;
    }
    if ( ch->gold - cost < 0)
   {
     send_to_char( "You cant afford to send that to them.\n\r", ch );
     return;
   }
    ch->gold -= cost;
    separate_obj(obj); 
    obj_from_char( obj );
    obj_to_char( obj, victim );
    act( AT_MAGIC, "You give the postmaster $p to express deliver to $N", ch, obj, victim, TO_CHAR );
    sprintf( mobbuf, "Thanks %s! It's on its way to %s.", ch->name, victim->name );
    do_say(mob, mobbuf);
    act( AT_MAGIC, "A courier materliazes and hands you $p from $n.", ch, obj, victim, TO_VICT );
    save_char_obj(victim);
    save_char_obj(ch);
    return;
   }
    cost= obj->level*200; 

    if ( ch->gold - cost < 0)
   {
     send_to_char( "You cant afford to send that to them.\n\r", ch );
     return;
   }
    sprintf( strsave, "%s%s", MAIL_DIR, capitalize( victim->name ) );
    if ( ( fp = fopen( strsave, "r" ) ) != NULL )
   {
     send_to_char( "Their mailbox is already full.\n\r", ch );
          fclose( fp );
     return;
   }

    ch->gold -= cost;
    act( AT_MAGIC, "You give the postmaster $p to deliver to $N", ch, obj, victim, TO_CHAR );
    fwrite_delivery( victim, obj );
    extract_obj(obj);
    sprintf( mobbuf, "Thanks %s! I've put your package in %s's box and sent a memo to them to pickup.", ch->name, victim->name );
    do_say(mob, mobbuf);
    act( AT_MAGIC, "$n has sent you $p in the mail, and it is awaiting your pickup at the nearest post office.", ch, obj, victim, TO_VICT );
    xSET_BIT(victim->act, PLR_GOTMAIL);
    return; 
}


