/***************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* In order to use any part of this Merc Diku Mud, you must comply with *
* both the original Diku license in 'license.doc' as well the Merc *
* license in 'license.txt'. In particular, you may not remove either of *
* these copyright notices. *
* *
* Much time and thought has gone into this software and you are *
* benefitting. We hope that you share your changes too. What goes *
* around, comes around. *
**************************************************************************/
/***************************************************************************
* ROM 2.4 is copyright 1993-1996 Russ Taylor *
* ROM has been brought to you by the ROM consortium *
* Russ Taylor (rtaylor@efn.org) *
* Gabrielle Taylor *
* Brian Moore (zump@rom.org) *
* By using this code, you have agreed to follow the terms of the *
* ROM license, in the file Rom24/doc/rom.license *
***************************************************************************/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "include.h"
void mail_home args( ( CHAR_DATA *ch, CHAR_DATA *victim, MAIL_DATA *mAil,
OBJ_DATA *obj ) );
void mail_office args( ( CHAR_DATA *ch, CHAR_DATA *victim, MAIL_DATA *mail,
OBJ_DATA *obj ) );
#define MAX_NEST 100
#define MAX_RECIEVED 5
void save_mail args( ( void ) );
void fread_char args( ( CHAR_DATA *ch, FILE *fp ) );
int recieved_mail args( ( CHAR_DATA * victim) );
int get_mail_id args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
MAIL_DATA *mail_list;
static OBJ_DATA * rgObjNest [MAX_NEST];
#if defined(KEY)
#undef KEY
#endif
#if defined(KEY)
#undef KEY
#endif
#define KEY( literal, field, value ) if ( !str_cmp( word, literal ) ) { field = value; fMatch = TRUE; break; }
struct postal_type *postal_table;
int last_mail_id;
long last_mail_time;
int maxpostal;
void do_post( CHAR_DATA *ch, char *argument )
{
char arg[MSL];
char arg1[MSL];
char buf[MSL];
CHAR_DATA *victim;
OBJ_DATA *obj;
MAIL_DATA *mAil;
ROOM_INDEX_DATA *location;
if ( arg[0] == '\0' || arg1[0] == '\0' )
{
send_to_char( "Only objects may be posted at this time.\n\r", ch );
send_to_char( "Syntax: post <item> <player>\n\r", ch );
return;
}
location = get_room_index( hometown_table[ch->hometown].postal );
if ( ch->in_room != location )
{
send_to_char( "You must be in the post office to send mail.\n\r", ch );
return;
}
if ( IS_NPC( ch ) )
{
send_to_char( "Mobs don't need to send anyone anything.\n\r", ch );
return;
}
if ( ch->fighting != NULL )
{
send_to_char( "Not while your fighting!\n\r", ch );
return;
}
if ( ( obj = get_obj_list(ch, arg, ch->carrying) ) == NULL )
{
send_to_char( "You don't have that item.\n\r", ch );
return;
}
/*
* If person is on then see if they have a house. If they do send the item
* there. If not then we'll have to send it to the office.
*/
/*
* If they aren't on then we'll have to access their file, and see if they
* have a house.
*/
if ( ( victim = get_char_world( ch, arg1 ) ) != NULL )
{
if ( recieved_mail( victim ) > MAX_RECIEVED )
{
send_to_char( "They already have five items in their mailbox.\n\r", ch );
return;
}
for ( mAil = mail_list; mAil != NULL; mAil = mAil->next );
{
if ( HAS_HOME( victim ) )
{
mail_home( ch, victim, mAil, obj );
}
else
{
mail_office( ch, victim, mAil, obj );
}
}
return;
}
else
{
FILE *fp;
bool fOld;
victim = new_char();
victim->pcdata = new_pcdata();
fOld = FALSE;
sprintf( buf, "%s%s", PLAYER_DIR, capitalize( arg ) );
if (file_exists(buf))
{
int iNest;
fp = file_open(buf, "r");
for ( iNest = 0; iNest < MAX_NEST; iNest++ )
rgObjNest[iNest] = NULL;
fOld = TRUE;
for ( ; ; )
{
char letter;
char *word;
letter = fread_letter( fp );
if ( letter == '*' )
{
fread_to_eol( fp );
continue;
}
if ( letter != '#' )
{
bug( "Load_char_obj: # not found.", 0 );
break;
}
word = fread_word( fp );
if ( !str_cmp( word, "PLAYER" ) ) fread_char( victim, fp );
else if ( !str_cmp( word, "OBJECT" ) ) break;
else if ( !str_cmp( word, "O" ) ) break;
else if ( !str_cmp( word, "PET" ) ) break;
else if ( !str_cmp( word, "END" ) ) break;
else
{
bug( "Load_char_obj: bad section.", 0 );
break;
}
}
file_close( fp );
}
if ( !fOld )
{
send_to_char("No player by that name exists.\n\r",ch);
free_pcdata(victim->pcdata);
free_char(victim);
return;
}
if ( IS_NPC(victim) || victim->pcdata == NULL )
{
send_to_char( "Error in loading pcdata.\n\r", ch );
free_pcdata(victim->pcdata);
free_char(victim);
return;
}
if ( recieved_mail( victim ) > 5 )
{
send_to_char( "They already have five items in their mailbox.\n\r", ch );
return;
}
for ( mAil = mail_list; mAil != NULL; mAil = mAil->next );
{
if ( HAS_HOME( victim ) )
{
mail_home( ch, victim, mAil, obj );
}
else
{
mail_office( ch, victim, mAil, obj );
}
}
if ( victim == char_list )
{
char_list = victim->next;
}
else
{
CHAR_DATA *prev;
for ( prev = char_list; prev != NULL; prev = prev->next )
{
if ( prev->next == victim )
{
prev->next = victim->next;
break;
}
}
if ( prev == NULL )
{
bug( "Character not found.", 0 );
return;
}
}
free_pcdata(victim->pcdata);
free_char(victim);
return;
}
}
void mail_home( CHAR_DATA *ch, CHAR_DATA *victim, MAIL_DATA *mAil, OBJ_DATA *obj )
{
char *strtime;
int i;
int days = 5;
mAil = new_mail();
mAil->sender = str_dup( ch->name );
mAil->to_who = str_dup( victim->name );
mAil->item = obj;
for (i = 0; house_table[i].name != NULL; i++)
{
if ( is_name( "box", house_table[i].name ) && house_table[i].type == OBJ_VNUM )
{
mAil->box = house_table[i].vnum;
}
}
mAil->id = get_mail_id(ch, victim);
if (last_mail_time >= current_time)
mAil->date_stamp = ++last_mail_time;
else
{
mAil->date_stamp = current_time;
last_mail_time = current_time;
}
mAil->expire = days * 60 * 60 * 24;
strtime = ctime(¤t_time);
strtime[strlen(strtime) - 1] = '\0';
mAil->date = str_dup(strtime);
printf_to_char( ch, "The messenger rides up on their horse, you hand them %s, and they ride off again.\n\r", obj->name );
mAil->next = mail_list;
mail_list = mAil;
save_mail();
}
void mail_office( CHAR_DATA *ch, CHAR_DATA *victim, MAIL_DATA *mAil, OBJ_DATA *obj )
{
char *strtime;
int days = 5;
mAil = new_mail();
mAil->sender = str_dup( ch->name );
mAil->to_who = str_dup( victim->name );
mAil->box = hometown_table[victim->hometown].postal;
mAil->item = obj;
mAil->id = get_mail_id(ch, victim);
if (last_mail_time >= current_time)
mAil->date_stamp = ++last_mail_time;
else
{
mAil->date_stamp = current_time;
last_mail_time = current_time;
}
mAil->expire = days * 60 * 60 * 24;
strtime = ctime(¤t_time);
strtime[strlen(strtime) - 1] = '\0';
mAil->date = str_dup(strtime);
send_to_char( "You hand the messenger your item, and watch as he rides off to deliver it.\n\r", ch );
mAil->next = mail_list;
mail_list = mAil;
save_mail();
}
int get_mail_id(CHAR_DATA *ch, CHAR_DATA *victim)
{
MAIL_DATA *mail;
for (mail = mail_list; mail; mail = mail->next)
{
if (mail->id == last_mail_id || ( mail->id != ch->pcdata->mailid && mail->id != victim->pcdata->mailid ) )
last_mail_id++;
}
victim->pcdata->mailid = last_mail_id;
ch->pcdata->mailid = last_mail_id;
return last_mail_id;
}
int recieved_mail(CHAR_DATA * victim)
{
MAIL_DATA *mail;
int count;
for (count = 0, mail=mail_list ; mail; mail = mail->next)
{
if (!str_cmp( mail->to_who, victim->name ) )
count++;
}
return count;
}
MAIL_DATA *mail_free;
MAIL_DATA *new_mail(void)
{
static MAIL_DATA mail_zero;
MAIL_DATA *mAil;
if (mail_free == NULL)
mAil = (MAIL_DATA *)alloc_perm(sizeof(*mAil));
else
{
mAil = mail_free;
mail_free = mail_free->next;
}
*mAil = mail_zero;
VALIDATE(mAil);
return mAil;
}
void free_mail(MAIL_DATA *mAil)
{
if (!IS_VALID(mAil))
return;
free_string( mAil->sender );
free_string( mAil->to_who );
INVALIDATE(mAil);
mAil->next = mail_free;
mail_free = mAil;
}
void save_mail()
{
FILE *fp;
MAIL_DATA *mAil;
if ( ( fp = file_open( MAIL_FILE, "w" ) ) == NULL )
{
logf2("The mail file is gone!\n\r");
return;
}
for(mAil = mail_list ; mAil ; mAil = mAil->next )
{
fprintf(fp, "Sender %s~\n", mAil->sender );
fprintf(fp, "Reciever %s~\n", mAil->to_who );
/* I'd say here, you should fwrite_obj(), then on the load use fread_obj().
And I'm pretty sure I already made it so it can handle a NULL CHAR_DATA struct.
~Davion */
}
fprintf(fp, "$\n");
logf2("Mail saved.");
file_close(fp);
}
void do_chmail( CHAR_DATA *ch, char *argument )
{
ROOM_INDEX_DATA *location;
MAIL_DATA *mail;
bool found = FALSE;
location = get_room_index( hometown_table[ch->hometown].postal );
if ( IS_NPC( ch ) )
{
send_to_char( "Mobs can't recieve objects in the mail.\n\r", ch );
return;
}
if ( ch->in_room != location )
{
send_to_char( "You must be in the post office to check your mail.\n\r", ch );
return;
}
if ( argument[0] == '\0' )
{
send_to_char( "Chmail with no argument shows what is in the mail.\n\r", ch );
send_to_char( "Name Sender", ch );
send_to_char( "==================================================\n\r", ch );
for ( mail = mail_list; mail != NULL; mail = mail->next )
{
if( !str_cmp(ch->name,mail->to_who) )
{
printf_to_char( ch, "%-10s %-10s\n\r", mail->item->short_descr, mail->sender );
found = TRUE;
}
}
if ( !found )
send_to_char( "You have no object in your mail.\n\r", ch );
return;
}
}
void load_postal(FILE *fp, struct postal_type *postal)
{
const char *word;
bool fMatch;
for (;;)
{
word = feof (fp) ? "End" : fread_word (fp);
fMatch = FALSE;
switch (UPPER (word[0]))
{
case '*':
fMatch = TRUE;
fread_to_eol (fp);
break;
case 'P':
KEY("Pcount", postal->pcount, fread_number(fp) );
break;
case 'V':
KEY("Vnum", postal->vnum, fread_number(fp) );
break;
case 'E':
if (!str_cmp (word, "End"))
return;
}
}
return;
}
void load_postal_table()
{
FILE *fp;
int i;
fp = file_open (POSTAL_FILE, "r");
if (!fp)
{
bug ("Could not open " POSTAL_FILE " for reading.",0);
exit(1);
}
fscanf (fp, "%d\n", &maxpostal);
postal_table = (postal_type *)malloc (sizeof(struct postal_type) * (maxpostal+1));
for (i = 0; i < maxpostal; i++)
{
postal_table[i].pcount = 0;
postal_table[i].vnum = 0;
load_postal(fp,&postal_table[i]);
}
file_close (fp);
}
void save_postal(const struct postal_type *postal, FILE *fp)
{
fprintf(fp, "Vnum %d\n", postal->vnum);
fprintf(fp, "END\n\n" );
return;
}
void save_postal_table()
{
FILE *fp;
int i;
fp = file_open (POSTAL_FILE, "w");
fprintf (fp, "%d\n", maxpostal);
for ( i = 0 ; i < maxpostal ; i++)
save_postal(&postal_table[i], fp);
file_close (fp);
}
int postal_lookup (int vnum)
{
int i;
for (i = 0; i < maxpostal; i++)
{
if ( vnum == postal_table[i].vnum )
return i;
}
return -1;
}
void new_postal( CHAR_DATA *ch )
{
struct postal_type *new_table;
int ipostal;
if ( !IS_SET( ch->in_room->room_flags, ROOM_POSTAL ) )
{
;
if ( (ipostal = postal_lookup( ch->in_room->vnum ) ) != -1 )
{
send_to_char( "That post office already exist.\n\r", ch );
return;
}
ipostal = ch->in_room->vnum;
maxpostal++;
new_table = (postal_type *)realloc (postal_table, sizeof(struct postal_type) * maxpostal + 1);
if (!new_table)
{
send_to_char( "Memory allocation failed.\n\r", ch );
maxpostal--;
return;
}
SET_BIT( ch->in_room->room_flags, ROOM_POSTAL );
postal_table = new_table;
postal_table[maxpostal-1].pcount++;
postal_table[maxpostal-1].vnum = ipostal;
printf_to_char(ch, "A new post office has been added in room %d maxpostal is %d.\n\r", ipostal, maxpostal );
save_postal_table();
return;
}
else
{
int i,j;
struct postal_type *new_table = (postal_type *)malloc (sizeof(struct postal_type) * maxpostal);
if (!new_table)
{
send_to_char( "Memory allocation failed.\n\r", ch );
return;
}
ipostal = postal_lookup( ch->in_room->vnum );
if ( ipostal == -1 )
{
send_to_char( "That post office doesn't exist.\n\r", ch );
return;
}
REMOVE_BIT( ch->in_room->room_flags, ROOM_POSTAL );
for (i = 0, j = 0; i < maxpostal+1; i++)
{
if (i != ipostal)
{
new_table[j] = postal_table[i];
j++;
}
}
printf_to_char( ch, "You are deleting post office %d.\n\r", ipostal );
free(postal_table);
postal_table = new_table;
maxpostal--;
save_postal_table();
return;
}
return;
}
void do_pshow( CHAR_DATA *ch, char *argument )
{
int i;
bool found = FALSE;
send_to_char( "Vnum:\n\r", ch );
send_to_char( "{G====={x\n\r", ch );
for ( i = 0; i < maxpostal; i++ )
{
printf_to_char( ch, "[ %-5d ]\n\r", postal_table[i].vnum);
found = TRUE;
}
if (!found)
send_to_char("Ack their are no post offices have an imm make one.\n\r", ch );
return;
}
void load_mail(FILE *fp, MAIL_DATA *mail)
{
const char *word;
bool fMatch;
MAIL_DATA *mlist;
if (file_exists(MAIL_FILE) )
{
fp = file_open( MAIL_FILE, "r" );
mlist = NULL;
for (;;)
{
word = feof (fp) ? "End" : fread_word (fp);
fMatch = FALSE;
switch (UPPER (word[0]))
{
case '*':
fMatch = TRUE;
fread_to_eol (fp);
break;
case 'S':
mail = new_mail();
if (mail_list == NULL)
mail_list = mail;
else
mlist->next = mail;
mlist = mail;
KEY("Sender", mail->sender, fread_string(fp) );
case 'E':
if (!str_cmp (word, "End"))
return;
break;
case 'R':
KEY("Reciever", mail->to_who, fread_string(fp) );
break;
}
}
}
return;
}