New mail system, with inbox OLC, index rebuilder and initial mail

This commit is contained in:
JamDog 2010-12-06 18:40:28 +00:00
parent d257dc0c75
commit e068bfd5c0
28 changed files with 4085 additions and 588 deletions

View file

@ -35,6 +35,8 @@ export (QQ's a zone into a tarball)
Xlist (mlist, olist, rlist, zlist, slist, tlist, qlist)
(lots of major bugfixes too)
@
[Dec 06 2010] - Jamdog
Added new mail system, with inbox OLC, index rebuilder and first mail (to ID 1)
[Dec 05 2010] - Jamdog
Bug-Fix: 'Did you mean' now only shows commands you have access to (thanks Welcor)
Bug-Fix: Fixed crash bug introduced by new house system when saving house contents

20
lib/mudmail/0/0.ml Normal file
View file

@ -0,0 +1,20 @@
MlID: 0
Send: -1
Reci: 1
Sent: 1283977700
Subj: Welcome to Trigun Mail
Body:
@GWelcome to Trigun MUD Mail System
@W---------------------------------
@y
This is an automatic mail sent to the MUD owner. This new tbaMUD
Mail system allows for much greater flexibility than the old circle
MUDmail.
A manual on usage is available at:
@Chttp://www.stefancole.com/mudmail.pdf@n
~
Gold: 10
Flag: f 0 0 0
$~

5
lib/mudmail/index Normal file
View file

@ -0,0 +1,5 @@
# tbaMUD Mail Index
# Format: <ID> <flags> <sender ID/vnum> <recipient ID> <time> <subject>
# For 'No Subject', use (null)
0 f -1 4 1283977700 Welcome to tbaMUD Mail
~

View file

@ -51,12 +51,21 @@ ACMD(do_write);
* Begin Functions and defines for act.informative.c
****************************************************************************/
/* Utility Functions */
/* do_look, do_inventory utility functions */
void show_obj_to_char(struct obj_data *obj, struct char_data *ch, int mode);
void list_obj_to_char(struct obj_data *list, struct char_data *ch, int mode, int show);
/** @todo Move to a utility library */
char *find_exdesc(char *word, struct extra_descr_data *list);
/** @todo Move to a mud centric string utility library */
void space_to_minus(char *str);
/** @todo Move to a help module? */
int search_help(const char *argument, int level);
/* Used by show_obj_to_char */
#define SHOW_OBJ_LONG 0
#define SHOW_OBJ_SHORT 1
#define SHOW_OBJ_ACTION 2
/* functions with subcommands */
/* do_commands */
ACMD(do_commands);

View file

@ -38,23 +38,14 @@ static void look_at_char(struct char_data *i, struct char_data *ch);
static void look_at_target(struct char_data *ch, char *arg);
static void look_in_direction(struct char_data *ch, int dir);
static void look_in_obj(struct char_data *ch, char *arg);
/* do_look, do_inventory utility functions */
static void list_obj_to_char(struct obj_data *list, struct char_data *ch, int mode, int show);
/* do_look, do_equipment, do_examine, do_inventory */
static void show_obj_to_char(struct obj_data *obj, struct char_data *ch, int mode);
static void show_obj_modifiers(struct obj_data *obj, struct char_data *ch);
/* do_where utility functions */
static void perform_immort_where(struct char_data *ch, char *arg);
static void perform_mortal_where(struct char_data *ch, char *arg);
static void print_object_location(int num, struct obj_data *obj, struct char_data *ch, int recur);
/* Subcommands */
/* For show_obj_to_char 'mode'. /-- arbitrary */
#define SHOW_OBJ_LONG 0
#define SHOW_OBJ_SHORT 1
#define SHOW_OBJ_ACTION 2
static void show_obj_to_char(struct obj_data *obj, struct char_data *ch, int mode)
void show_obj_to_char(struct obj_data *obj, struct char_data *ch, int mode)
{
int found = 0;
struct char_data *temp;
@ -170,7 +161,7 @@ static void show_obj_modifiers(struct obj_data *obj, struct char_data *ch)
send_to_char(ch, " ..It emits a faint humming sound!");
}
static void list_obj_to_char(struct obj_data *list, struct char_data *ch, int mode, int show)
void list_obj_to_char(struct obj_data *list, struct char_data *ch, int mode, int show)
{
struct obj_data *i, *j, *display;
bool found;
@ -829,8 +820,8 @@ ACMD(do_score)
send_to_char(ch, "Your armor class is %d/10, and your alignment is %d.\r\n",
compute_armor_class(vict), GET_ALIGNMENT(vict));
send_to_char(ch, "You have %d exp, %d gold coins, and %d questpoints.\r\n",
GET_EXP(vict), GET_GOLD(vict), GET_QUESTPOINTS(vict));
send_to_char(ch, "You have %s exp, %s gold coins, and %d questpoints.\r\n",
add_commas(GET_EXP(vict)), add_commas(GET_GOLD(vict)), GET_QUESTPOINTS(vict));
if (GET_LEVEL(vict) < CONFIG_MAX_LEVEL)
send_to_char(ch, "You need %d exp to reach your next level.\r\n",
@ -2154,7 +2145,7 @@ ACMD(do_toggle)
act("$n is now away from $s keyboard.", TRUE, ch, 0, 0, TO_ROOM);
else {
act("$n has returned to $s keyboard.", TRUE, ch, 0, 0, TO_ROOM);
if (has_mail(GET_IDNUM(ch)))
if (has_mail(ch))
send_to_char(ch, "You have mail waiting.\r\n");
}
break;
@ -2494,7 +2485,7 @@ ACMD(do_whois)
}
}
if (has_mail(GET_IDNUM(victim)))
if (has_mail(victim))
send_to_char (ch, "They have mail waiting.\r\n");
else
send_to_char (ch, "They have no mail waiting.\r\n");

View file

@ -819,7 +819,7 @@ ACMD(do_gen_tog)
act("$n has gone AFK.", TRUE, ch, 0, 0, TO_ROOM);
else {
act("$n has come back from AFK.", TRUE, ch, 0, 0, TO_ROOM);
if (has_mail(GET_IDNUM(ch)))
if (has_mail(ch))
send_to_char(ch, "You have mail waiting.\r\n");
}
break;

View file

@ -139,6 +139,18 @@ static void cedit_setup(struct descriptor_data *d)
OLC_CONFIG(d)->autowiz.use_autowiz = CONFIG_USE_AUTOWIZ;
OLC_CONFIG(d)->autowiz.min_wizlist_lev = CONFIG_MIN_WIZLIST_LEV;
/* Mudmail */
OLC_CONFIG(d)->mail.mail_allowed = CONFIG_CAN_MAIL;
OLC_CONFIG(d)->mail.objects_allowed = CONFIG_CAN_MAIL_OBJ;
OLC_CONFIG(d)->mail.gold_allowed = CONFIG_CAN_MAIL_GOLD;
OLC_CONFIG(d)->mail.stamp_cost = CONFIG_STAMP_COST;
OLC_CONFIG(d)->mail.min_level = CONFIG_MIN_MAIL_LEVEL;
OLC_CONFIG(d)->mail.min_free_level = CONFIG_FREE_MAIL_LEVEL;
OLC_CONFIG(d)->mail.allow_drafts = CONFIG_DRAFTS_ALLOWED;
OLC_CONFIG(d)->mail.draft_timeout = CONFIG_DRAFT_TIMEOUT;
OLC_CONFIG(d)->mail.safe_mailing = CONFIG_SAFE_MAILING;
OLC_CONFIG(d)->mail.min_mail_anywhere = CONFIG_MIN_MAIL_ANYWHERE;
OLC_CONFIG(d)->mail.min_send_to_all = CONFIG_MIN_SEND_TO_ALL;
/* Allocate space for the strings. */
OLC_CONFIG(d)->play.OK = str_udup(CONFIG_OK);
@ -239,6 +251,20 @@ static void cedit_save_internally(struct descriptor_data *d)
CONFIG_USE_AUTOWIZ = OLC_CONFIG(d)->autowiz.use_autowiz;
CONFIG_MIN_WIZLIST_LEV = OLC_CONFIG(d)->autowiz.min_wizlist_lev;
/* Mudmail */
CONFIG_CAN_MAIL = OLC_CONFIG(d)->mail.mail_allowed;
CONFIG_CAN_MAIL_OBJ = OLC_CONFIG(d)->mail.objects_allowed;
CONFIG_CAN_MAIL_GOLD = OLC_CONFIG(d)->mail.gold_allowed;
CONFIG_STAMP_COST = OLC_CONFIG(d)->mail.stamp_cost;
CONFIG_OBJECT_COST = OLC_CONFIG(d)->mail.object_cost;
CONFIG_MIN_MAIL_LEVEL = OLC_CONFIG(d)->mail.min_level;
CONFIG_FREE_MAIL_LEVEL = OLC_CONFIG(d)->mail.min_free_level;
CONFIG_DRAFTS_ALLOWED = OLC_CONFIG(d)->mail.allow_drafts;
CONFIG_DRAFT_TIMEOUT = OLC_CONFIG(d)->mail.draft_timeout;
CONFIG_SAFE_MAILING = OLC_CONFIG(d)->mail.safe_mailing;
CONFIG_MIN_MAIL_ANYWHERE = OLC_CONFIG(d)->mail.min_mail_anywhere;
CONFIG_MIN_SEND_TO_ALL = OLC_CONFIG(d)->mail.min_send_to_all;
/* Allocate space for the strings. */
if (CONFIG_OK)
free(CONFIG_OK);
@ -542,6 +568,56 @@ int save_config( IDXTYPE nowhere )
"min_wizlist_lev = %d\n\n",
CONFIG_MIN_WIZLIST_LEV);
/* MUDMAIL OPTIONS */
fprintf(fl, "\n\n\n* [ Mudmail Options ]\n");
fprintf(fl, "* Enable/Disable the whole mudmail system\n"
"can_mail = %d\n\n",
CONFIG_CAN_MAIL);
fprintf(fl, "* Can objects be sent via mudmail?\n"
"mail_objects_allowed = %d\n\n",
CONFIG_CAN_MAIL_OBJ);
fprintf(fl, "* Can gold coins be sent via mudmail?\n"
"mail_gold_allowed = %d\n\n",
CONFIG_CAN_MAIL_GOLD);
fprintf(fl, "* How much does it cost to send mudmails\n"
"mail_stamp_cost = %d\n\n",
CONFIG_STAMP_COST);
fprintf(fl, "* How much extra does it cost to add each object mudmails\n"
"mail_object_cost = %d\n\n",
CONFIG_OBJECT_COST);
fprintf(fl, "* The minimum player level that's allowed to send mudmails\n"
"mail_min_level = %d\n\n",
CONFIG_MIN_MAIL_LEVEL);
fprintf(fl, "* The minimum level that can send mudmails for free\n"
"mail_min_free_level = %d\n\n",
CONFIG_FREE_MAIL_LEVEL);
fprintf(fl, "* Are players allowed to create draft mails for sending later?\n"
"mail_drafts_allowed = %d\n\n",
CONFIG_DRAFTS_ALLOWED);
fprintf(fl, "* Number of days before a draft mail is autoremoved (0 for never) \n"
"mail_draft_timeout = %d\n\n",
CONFIG_DRAFT_TIMEOUT);
fprintf(fl, "* When on, the player cannot be attacked or stolen from while mailing. \n"
"mail_safe_mailing = %d\n\n",
CONFIG_SAFE_MAILING);
fprintf(fl, "* This is the minimum level that can send mail from any location (not just at postmaster). \n"
"mail_min_mail_anywhere = %d\n\n",
CONFIG_MIN_MAIL_ANYWHERE);
fprintf(fl, "* This is the minimum level that can send mail to all players. \n"
"mail_min_send_to_all = %d\n\n",
CONFIG_MIN_SEND_TO_ALL);
fclose(fl);
@ -566,6 +642,7 @@ static void cedit_disp_menu(struct descriptor_data *d)
"%sR%s) Room Numbers\r\n"
"%sO%s) Operation Options\r\n"
"%sA%s) Autowiz Options\r\n"
"%sM%s) Mudmail Options\r\n"
"%sQ%s) Quit\r\n"
"Enter your choice : ",
@ -574,6 +651,7 @@ static void cedit_disp_menu(struct descriptor_data *d)
grn, nrm,
grn, nrm,
grn, nrm,
grn, nrm,
grn, nrm
);
@ -781,6 +859,50 @@ static void cedit_disp_autowiz_options(struct descriptor_data *d)
OLC_MODE(d) = CEDIT_AUTOWIZ_OPTIONS_MENU;
}
void cedit_disp_mudmail_options(struct descriptor_data *d)
{
char timeout[MAX_INPUT_LENGTH];
get_char_colors(d->character);
clear_screen(d);
if (OLC_CONFIG(d)->mail.draft_timeout > 0)
sprintf(timeout, "%d days", OLC_CONFIG(d)->mail.draft_timeout);
else
sprintf(timeout, "%s<Never!>", cyn);
write_to_output(d, "\r\n\r\n"
"%sA%s) Use mudmail system : %s%s\r\n"
"%sB%s) Allow object attachments : %s%s\r\n"
"%sC%s) Allow gold attachments : %s%s\r\n"
"%sD%s) Stamp Cost (Normal Mails) : %s%d coins\r\n"
"%sE%s) Cost per object attached : %s%d coins\r\n"
"%sF%s) Allow draft mudmails : %s%s\r\n"
"%sG%s) Draft mail timeout : %s%s\r\n"
"%sH%s) Min. level that can mail : %s%d\r\n"
"%sI%s) Min. level for free mail : %s%d\r\n"
"%sJ%s) Safe while mailing? : %s%s\r\n"
"%sK%s) Min level to mail anywhere : %s%d\r\n"
"%sL%s) Min level to send to all : %s%d\r\n"
"%sQ%s) Exit To The Main Menu\r\n"
"Enter your choice : ",
grn, nrm, cyn, CHECK_VAR(OLC_CONFIG(d)->mail.mail_allowed),
grn, nrm, cyn, CHECK_VAR(OLC_CONFIG(d)->mail.objects_allowed),
grn, nrm, cyn, CHECK_VAR(OLC_CONFIG(d)->mail.gold_allowed),
grn, nrm, yel, OLC_CONFIG(d)->mail.stamp_cost,
grn, nrm, yel, OLC_CONFIG(d)->mail.object_cost,
grn, nrm, cyn, CHECK_VAR(OLC_CONFIG(d)->mail.allow_drafts),
grn, nrm, yel, timeout,
grn, nrm, yel, OLC_CONFIG(d)->mail.min_level,
grn, nrm, yel, OLC_CONFIG(d)->mail.min_free_level,
grn, nrm, cyn, CHECK_VAR(OLC_CONFIG(d)->mail.safe_mailing),
grn, nrm, yel, OLC_CONFIG(d)->mail.min_mail_anywhere,
grn, nrm, yel, OLC_CONFIG(d)->mail.min_send_to_all,
grn, nrm
);
OLC_MODE(d) = CEDIT_MUDMAIL_OPTIONS_MENU;
}
/* The event handler. */
void cedit_parse(struct descriptor_data *d, char *arg)
{
@ -844,6 +966,12 @@ void cedit_parse(struct descriptor_data *d, char *arg)
OLC_MODE(d) = CEDIT_AUTOWIZ_OPTIONS_MENU;
break;
case 'm':
case 'M':
cedit_disp_mudmail_options(d);
OLC_MODE(d) = CEDIT_MUDMAIL_OPTIONS_MENU;
break;
case 'q':
case 'Q':
write_to_output(d, "Do you wish to save your changes? : ");
@ -1270,6 +1398,87 @@ void cedit_parse(struct descriptor_data *d, char *arg)
cedit_disp_autowiz_options(d);
return;
case CEDIT_MUDMAIL_OPTIONS_MENU:
switch (*arg) {
case 'a':
case 'A':
TOGGLE_VAR(OLC_CONFIG(d)->mail.mail_allowed);
break;
case 'b':
case 'B':
TOGGLE_VAR(OLC_CONFIG(d)->mail.objects_allowed);
break;
case 'c':
case 'C':
TOGGLE_VAR(OLC_CONFIG(d)->mail.gold_allowed);
break;
case 'd':
case 'D':
write_to_output(d, "Enter the cost per mail (without attachments) : ");
OLC_MODE(d) = CEDIT_STAMP_COST;
return;
case 'e':
case 'E':
write_to_output(d, "Enter the cost per object attachment : ");
OLC_MODE(d) = CEDIT_OBJECT_COST;
return;
case 'f':
case 'F':
TOGGLE_VAR(OLC_CONFIG(d)->mail.allow_drafts);
break;
case 'g':
case 'G':
write_to_output(d, "Enter the timeout (in days) before draft mails are auto-removed (0=off) : ");
OLC_MODE(d) = CEDIT_DRAFT_TIMEOUT;
return;
case 'h':
case 'H':
write_to_output(d, "Enter the minimum admin level that can send mudmails : ");
OLC_MODE(d) = CEDIT_MIN_MAIL_LEVEL;
return;
case 'i':
case 'I':
write_to_output(d, "Enter the minimum admin level for free mudmails : ");
OLC_MODE(d) = CEDIT_MIN_FREE_LEVEL;
return;
case 'j':
case 'J':
TOGGLE_VAR(OLC_CONFIG(d)->mail.safe_mailing);
break;
case 'k':
case 'K':
write_to_output(d, "Enter the minimum admin level that can send mail from anywhere : ");
OLC_MODE(d) = CEDIT_MAIL_ANYWHERE;
return;
case 'l':
case 'L':
write_to_output(d, "Enter the minimum admin level that can send to all players : ");
OLC_MODE(d) = CEDIT_MAIL_ALL_PLAYERS;
return;
case 'q':
case 'Q':
cedit_disp_menu(d);
return;
default:
write_to_output(d, "\r\nThat is an invalid choice!\r\n");
}
cedit_disp_mudmail_options(d);
return;
case CEDIT_LEVEL_CAN_SHOUT:
if (!*arg) {
write_to_output(d,
@ -1666,6 +1875,41 @@ void cedit_parse(struct descriptor_data *d, char *arg)
}
break;
case CEDIT_STAMP_COST:
OLC_CONFIG(d)->mail.stamp_cost = MIN(MAX(atoi(arg), 0), 1000);
cedit_disp_mudmail_options(d);
break;
case CEDIT_OBJECT_COST:
OLC_CONFIG(d)->mail.object_cost = MIN(MAX(atoi(arg), 0), 1000);
cedit_disp_mudmail_options(d);
break;
case CEDIT_DRAFT_TIMEOUT:
OLC_CONFIG(d)->mail.draft_timeout = MIN(MAX(atoi(arg), 0), 3653); /* up to 10 years */
cedit_disp_mudmail_options(d);
break;
case CEDIT_MIN_MAIL_LEVEL:
OLC_CONFIG(d)->mail.min_level = MIN(MAX(atoi(arg), 0), ADMLVL_IMPL);
cedit_disp_mudmail_options(d);
break;
case CEDIT_MIN_FREE_LEVEL:
OLC_CONFIG(d)->mail.min_free_level = MIN(MAX(atoi(arg), 0), ADMLVL_IMPL);
cedit_disp_mudmail_options(d);
break;
case CEDIT_MAIL_ANYWHERE:
OLC_CONFIG(d)->mail.min_mail_anywhere = MIN(MAX(atoi(arg), 0), ADMLVL_IMPL);
cedit_disp_mudmail_options(d);
break;
case CEDIT_MAIL_ALL_PLAYERS:
OLC_CONFIG(d)->mail.min_send_to_all = MIN(MAX(atoi(arg), 0), ADMLVL_IMPL);
cedit_disp_mudmail_options(d);
break;
default: /* We should never get here, but just in case... */
cleanup_olc(d, CLEANUP_CONFIG);
mudlog(BRF, ADMLVL_BUILDER, TRUE, "SYSERR: OLC: cedit_parse(): Reached default case!");

View file

@ -80,7 +80,7 @@ qst_rnum total_quests = 0; /* top of autoquest table */
struct shop_data *shop_index; /* index table for shops */
int top_shop = -1; /* top of shop table */
int no_mail = 0; /* mail disabled? */
int can_mail = 1; /* mail enabled? */
int mini_mud = 0; /* mini-mud mode? */
int no_rent_check = 0; /* skip rent check on boot? */
time_t boot_time = 0; /* time of mud boot */
@ -704,10 +704,11 @@ void boot_db(void)
sort_spells();
log("Booting mail system.");
if (!scan_file()) {
if (!build_mail_index()) {
log(" Mail boot failed -- Mail system disabled");
no_mail = 1;
can_mail = 0;
}
log("Reading banned site and invalid-name list.");
load_banned();
read_invalid_list();

View file

@ -34,6 +34,7 @@
#define LIB_PLROBJS ":plrobjs:"
#define LIB_PLRVARS ":plrvars:"
#define LIB_PLRFILES ":plrfiles:"
#define LIB_MLFILES ":mudmail:"
#define LIB_HOUSE ":house:"
#define SLASH ":"
#elif defined(CIRCLE_AMIGA) || defined(CIRCLE_UNIX) || defined(CIRCLE_WINDOWS) || defined(CIRCLE_ACORN) || defined(CIRCLE_VMS)
@ -47,6 +48,7 @@
#define LIB_PLRVARS "plrvars/"
#define LIB_HOUSE "house/"
#define LIB_PLRFILES "plrfiles/"
#define LIB_MLFILES "mudmail/"
#define SLASH "/"
#else
#error "Unknown path components."
@ -56,6 +58,7 @@
#define SUF_TEXT "text"
#define SUF_MEM "mem"
#define SUF_PLR "plr"
#define SUF_MAIL "ml"
#if defined(CIRCLE_AMIGA)
#define EXE_FILE "/bin/circle" /* maybe use argv[0] but it's not reliable */
@ -351,7 +354,7 @@ extern int top_of_helpt;
extern struct help_index_element *help_table;
/* Mud configurable variables */
extern int no_mail;
extern int can_mail;
extern int mini_mud;
extern int no_rent_check;
extern time_t boot_time;

View file

@ -22,14 +22,13 @@
#include "genzon.h" /* for real_zone_by_thing */
#include "act.h"
#include "fight.h"
#include "mail.h"
/* Local file scope functions. */
static void mob_log(char_data *mob, const char *format, ...);
/* attaches mob's name and vnum to msg and sends it to script_log */
static void mob_log(char_data *mob, const char *format, ...)
void mob_log(char_data *mob, const char *format, ...)
{
va_list args;
char output[MAX_STRING_LENGTH];
@ -1155,3 +1154,101 @@ ACMD(do_mrecho)
else
send_to_range(atoi(start), atoi(finish), "%s\r\n", msg);
}
/* Mailing functions */
ACMD(do_mmail)
{
char arg[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH], *arg3;
char buf[MAX_STRING_LENGTH];
char_data *victim;
long recipient = MAIL_TO_NOBODY;
obj_vnum o_num;
struct obj_data *obj;
if (!MOB_OR_IMPL(ch)) {
send_to_char(ch, "Huh?!?\r\n");
return;
}
arg3 = two_arguments(argument, arg, arg2);
if (!*arg) {
mob_log(ch, "mmail called with no argument");
return;
} else if (!strcmp(arg, "recipient")) {
create_mob_mail(ch);
if (*arg2 == UID_CHAR) {
if (!(victim = get_char(arg2))) {
mob_log(ch, "mmail: recipient (%s) not found",arg2);
return;
}
} else if (!(victim = get_char_vis(ch, arg2, NULL, FIND_CHAR_WORLD))) {
/* Check special cases and mail groups */
if ((recipient = get_mail_group_by_name(arg2)) == MAIL_TO_NOBODY) {
mob_log(ch,"mmail: victim (%s) does not exist", arg2);
return;
}
} else if (victim == ch) {
mob_log(ch, "mmail: victim is self");
return;
} else if (IS_NPC(victim)) {
mob_log(ch, "mmail: victim is another mob");
return;
} else {
/* all name checks passed - get the recipient ID */
recipient = GET_ID(victim);
}
if (!add_recipient(MOB_MAIL(ch), recipient)) {
mob_log(ch, "mmail failed to add recipient");
return;
}
} else if (!strcmp(arg, "object")) {
create_mob_mail(ch);
o_num = atoi(arg2);
if (!real_object(o_num)) {
mob_log(ch, "mmail: invalid object vnum");
return;
}
if ((obj = read_object(o_num, VIRTUAL)) == NULL) {
mob_log(ch, "mmail: invalid object to load");
return;
}
obj_to_mail(obj, MOB_MAIL(ch)->mail);
} else if (!strcmp(arg, "subject")) {
create_mob_mail(ch);
sprintf(buf, "%s%s", arg2, arg3);
if ((MOB_MAIL(ch)->mail)->subject)
free((MOB_MAIL(ch)->mail)->subject);
(MOB_MAIL(ch)->mail)->subject = strdup(buf);
} else if (!strcmp(arg, "body")) {
create_mob_mail(ch);
if ((MOB_MAIL(ch)->mail)->body)
free((MOB_MAIL(ch)->mail)->body);
(MOB_MAIL(ch)->mail)->body = strdup(buf);
} else if (!strcmp(arg, "gold")) {
create_mob_mail(ch);
(MOB_MAIL(ch)->mail)->coins = atol(arg2);
} else if (!strcmp(arg, "urgent")) {
create_mob_mail(ch);
TOGGLE_BIT_AR((MOB_MAIL(ch)->mail)->mail_flags, MAIL_URGENT);
} else if (!strcmp(arg, "cod")) {
create_mob_mail(ch);
TOGGLE_BIT_AR((MOB_MAIL(ch)->mail)->mail_flags, MAIL_COD);
} else if (!strcmp(arg, "send")) {
if (mail_from_mobile(ch)== FALSE)
mob_log(ch, "mmail: send failed.");
} else if (!strcmp(arg, "new")) {
create_mob_mail(ch);
clear_mail_data(MOB_MAIL(ch)->mail);
} else if ((!strcmp(arg, "view")) ||
(!strcmp(arg, "show")) ||
(!strcmp(arg, "echo")) ||
(!strcmp(arg, "list")) ) {
create_mob_mail(ch);
send_to_room(IN_ROOM(ch), "%s\r\n", get_mail_text(MOB_MAIL(ch)->mail) );
send_to_room(IN_ROOM(ch), "Recipients: %s\r\n", recipient_list(MOB_MAIL(ch)) );
} else {
mob_log(ch, "mmail: unknown %mail% command (%s).", arg);
}
return;
}

View file

@ -363,6 +363,7 @@ int valid_dg_target(char_data *ch, int bitvector);
void script_damage(char_data *vict, int dam);
/* from dg_mobcmd.c */
void mob_log(char_data *mob, const char *format, ...);
ACMD(do_masound);
ACMD(do_mat);
ACMD(do_mdamage);
@ -377,6 +378,7 @@ ACMD(do_mhunt);
ACMD(do_mjunk);
ACMD(do_mkill);
ACMD(do_mload);
ACMD(do_mmail);
ACMD(do_mpurge);
ACMD(do_mrecho);
ACMD(do_mremember);

View file

@ -232,6 +232,7 @@ void find_replacement(void *go, struct script_data *sc, trig_data *trig,
char *recho[] = {"mrecho ", "orecho ", "wrecho " };
/* there is no such thing as mmove, thus the mecho below */
char *omove[] = {"mecho ", "omove ", "wmove " };
char *mail[] = {"mmail ", "oecho ", "wecho " };
*str = '\0';
@ -300,6 +301,8 @@ void find_replacement(void *go, struct script_data *sc, trig_data *trig,
snprintf(str, slen, "%s", recho[type]);
else if (!str_cmp(var, "move"))
snprintf(str, slen, "%s", omove[type]);
else if (!str_cmp(var, "mail"))
snprintf(str, slen, "%s", mail[type]);
else
*str = '\0';
}

View file

@ -22,6 +22,7 @@
#include "class.h"
#include "fight.h"
#include "quest.h"
#include "mail.h"
/* local file scope variables */
static int extractions_pending = 0;
@ -765,6 +766,37 @@ void obj_from_obj(struct obj_data *obj)
obj->next_content = NULL;
}
/* Attach an object into a mudmail */
void obj_to_mail(struct obj_data *object, struct mail_data *mail)
{
if (!object || !mail)
log("SYSERR: Illegal value(s) passed to obj_to_mail. (Mail ID %ld, obj %p)", mail ? mail->mail_id : 0, object);
else {
object->next_content = mail->attachment;
mail->attachment = object;
IN_MAIL(object) = mail;
IN_ROOM(object) = NOWHERE;
object->carried_by = NULL;
}
}
/* Take an object from a mudmail */
void obj_from_mail(struct obj_data *object)
{
struct obj_data *temp;
if (!object || IN_ROOM(object) != NOWHERE || object->carried_by) {
log("SYSERR: NULL object (%p) or obj not attached to a mail passed to obj_from_mail", object);
return;
}
REMOVE_FROM_LIST(object, (IN_MAIL(object))->attachment, next_content);
IN_MAIL(object) = NULL;
IN_ROOM(object) = NOWHERE;
object->next_content = NULL;
}
/* Set all carried_by to point to new owner */
void object_list_new_owner(struct obj_data *list, struct char_data *ch)
{

View file

@ -41,6 +41,8 @@ void obj_to_room(struct obj_data *object, room_rnum room);
void obj_from_room(struct obj_data *object);
void obj_to_obj(struct obj_data *obj, struct obj_data *obj_to);
void obj_from_obj(struct obj_data *obj);
void obj_to_mail(struct obj_data *object, struct mail_data *mail);
void obj_from_mail(struct obj_data *object);
void object_list_new_owner(struct obj_data *list, struct char_data *ch);
void extract_obj(struct obj_data *obj);

View file

@ -221,7 +221,7 @@ cpp_extern const struct command_info cmd_info[] = {
{ "motd" , "motd" , POS_DEAD , do_gen_ps , 0, ADMLVL_MORTAL, ADM_NONE, SCMD_MOTD },
{ "mortal" , "mort" , POS_DEAD , do_mortal , 0, ADMLVL_MORTAL, ADM_NONE, 0 },
{ "mail" , "mail" , POS_STANDING, do_not_here , 1, ADMLVL_MORTAL, ADM_NONE, 0 },
{ "mail" , "mail" , POS_STANDING, do_mail , 1, ADMLVL_MORTAL, ADM_NONE, 0 },
{ "map" , "map" , POS_STANDING, do_map , 1, ADMLVL_MORTAL, ADM_NONE, 0 },
{ "medit" , "med" , POS_DEAD , do_oasis_medit,0, ADMLVL_BUILDER, ADM_NONE, 0 },
{ "mlist" , "mlist" , POS_DEAD , do_oasis_list, 0, ADMLVL_BUILDER, ADM_BUILD, SCMD_OASIS_MLIST },
@ -406,6 +406,7 @@ cpp_extern const struct command_info cmd_info[] = {
{ "mtransform", do_mtransform , 0 },
{ "mzoneecho", do_mzoneecho, 0 },
{ "mfollow" , do_mfollow , 0 },
{ "mmail" , do_mmail , 0 },
{ "\n" , do_not_here , 0 } };
int script_command_interpreter(struct char_data *ch, char *arg) {
@ -1194,7 +1195,7 @@ static int perform_dupe_check(struct descriptor_data *d)
write_to_output(d, "Reconnecting.\r\n");
act("$n has reconnected.", TRUE, d->character, 0, 0, TO_ROOM);
mudlog(NRM, MAX(ADMLVL_IMMORT, GET_INVIS_LEV(d->character)), TRUE, "%s [%s] has reconnected.", GET_NAME(d->character), d->host);
if (has_mail(GET_IDNUM(d->character)))
if (has_mail(d->character))
write_to_output(d, "You have mail waiting.\r\n");
break;
case USURP:
@ -1341,6 +1342,7 @@ void nanny(struct descriptor_data *d, char *arg)
{ CON_PREFEDIT, prefedit_parse },
{ CON_IBTEDIT, ibtedit_parse },
{ CON_HSEDIT, hsedit_parse },
{ CON_MAILEDIT, mailedit_parse },
{ -1, NULL }
};
@ -1675,8 +1677,8 @@ void nanny(struct descriptor_data *d, char *arg)
send_to_char(d->character, "%s", CONFIG_START_MESSG);
}
look_at_room(d->character, 0);
if (has_mail(GET_IDNUM(d->character)))
send_to_char(d->character, "You have mail waiting.\r\n");
if (has_mail(d->character))
notify_on_login(d->character);
if (load_result == 2) { /* rented items lost */
send_to_char(d->character, "\r\n\007You could not afford your rent!\r\n"
"Your possesions have been donated to the Salvation Army!\r\n");

2238
src/mail.c

File diff suppressed because it is too large Load diff

View file

@ -1,108 +1,212 @@
/**
* @file mail.h
* Public procs, macro defs, subcommand defines mudmail system.
*
* Part of the core tbaMUD source code distribution, which is a derivative
* of, and continuation of, CircleMUD.
*
* All rights reserved. See license for complete information.
* Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University
* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.
* By Jeremy Elson.
*/
#ifndef _MAIL_H_
#define _MAIL_H_
/***************************************************************************
* @file mail.h *
* Public procs, macro defs, subcommand defines mudmail system. *
* *
* Part of the core tbaMUD source code distribution, which is a derivative *
* of, and continuation of, CircleMUD. *
* *
* All rights reserved. See license for complete information. *
* Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. *
* By Jeremy Elson. *
**************************************************************************/
/* You can modify the following constants to fit your own MUD. */
/* minimum level a player must be to send mail */
#define MIN_MAIL_LEVEL 1
/* # of gold coins required to send mail */
#define STAMP_PRICE 150
/* A handy 'flag' define - probably better in utils.h? */
#define FLAG(n) (1 << (n))
/* Maximum size of mail in bytes (arbitrary) */
#define MAX_MAIL_SIZE 8192
#define MAX_MAIL_ID 2000000000
/* size of mail file allocation blocks */
#define BLOCK_SIZE 100
/* For mail anywhere to work, we need to know which room to find the immortal mailman in */
#define MAIL_IMMORTAL_ROOM 1205
/* General, publicly available functions */
SPECIAL(postmaster);
/* Mail index flags - mostly essential info that should be known before reading mails */
#define MINDEX_DELETED FLAG(0) /* Mail has been marked for deletion */
#define MINDEX_URGENT FLAG(1) /* Mail is flagged as urgent by sender */
#define MINDEX_HAS_OBJ FLAG(2) /* Mail has an attached object */
#define MINDEX_HAS_GOLD FLAG(3) /* Mail contains some gold coins */
#define MINDEX_IS_COD FLAG(4) /* Mail requires some gold coins */
#define MINDEX_FROM_MOB FLAG(5) /* Mail has been sent by using scripts */
#define MINDEX_READ FLAG(6) /* Mail has been viewed but not received */
#define MINDEX_DRAFT FLAG(7) /* Mail is an unsent draft copy */
/* NOTE: Make sure that your block size is big enough. If not, HEADER_BLOCK_
* DATASIZE will end up negative. This is a bad thing. Check the define below
* to make sure it is >0 when choosing values for NAME_SIZE and BLOCK_SIZE.
* 100 is a nice round number for BLOCK_SIZE and is the default. The mail system
* will always allocate disk space in chunks of size BLOCK_SIZE. */
/* Mail Flags */
#define MAIL_DELETED 1 /* Marks mail for deletion with next purge */
#define MAIL_URGENT 2 /* This mail is flagged as urgent? */
#define MAIL_COD 3 /* Means coins amount is required payment */
#define MAIL_FROM_MOB 4 /* Specifies that 'sender' is a mob vnum */
#define MAIL_READ 5 /* Mail has been read by recipient */
#define MAIL_DRAFT 6 /* Mail is a draft (not yet sent) */
/* DON'T TOUCH DEFINES BELOW. */
int scan_file(void);
int has_mail(long recipient);
void store_mail(long to, long from, char *message_pointer);
char *read_delete(long recipient);
void notify_if_playing(struct char_data *from, int recipient_id);
#define IS_MAIL_DELETED(i) (IS_SET(mail_table[(i)].flags, MINDEX_DELETED))
#define IS_MAIL_URGENT(i) (IS_SET(mail_table[(i)].flags, MINDEX_URGENT))
#define IS_MAIL_DRAFT(i) (IS_SET(mail_table[(i)].flags, MINDEX_DRAFT))
#define IS_MAIL_READ(i) (IS_SET(mail_table[(i)].flags, MINDEX_READ))
#define IS_MAIL_COD(i) (IS_SET(mail_table[(i)].flags, MINDEX_IS_COD))
#define MAIL_HAS_OBJECT(i) (IS_SET(mail_table[(i)].flags, MINDEX_HAS_OBJ))
#define MAIL_HAS_GOLD(i) (IS_SET(mail_table[(i)].flags, MINDEX_HAS_GOLD))
struct mail_t {
long recipient;
long sender;
time_t sent_time;
char *body;
#define MAIL_URGENT_COLOR(i) (IS_MAIL_URGENT(i) ? QBRED : QNRM)
/* Mail editor submodes */
#define MAILEDIT_INBOX 0
#define MAILEDIT_OUTBOX 1
#define MAILEDIT_MAILEDIT 2
#define MAILEDIT_VIEW 3
#define MAILEDIT_REPLY 4
#define MAILEDIT_FORWARD 5
#define MAILEDIT_RECEIVE 6
#define MAILEDIT_DELETE 7
#define MAILEDIT_BACK_TO_MENU 8
#define MAILEDIT_ATTACHMENTS 9
#define MAILEDIT_ASK_DRAFT 10
#define MAILEDIT_ASK_QUIT 11
#define MAILEDIT_OUTEDIT 12
#define MAILEDIT_OUTVIEW 13
#define MAILEDIT_OUTDELETE 14
#define MAILEDIT_RECIP_MENU 15
#define MAILEDIT_ADD_RECIP 16
#define MAILEDIT_DEL_RECIP 17
#define MAILEDIT_CLR_RECIP 18
#define MAILEDIT_ATTACH_MENU 19
#define MAILEDIT_ADD_ATTACH 20
#define MAILEDIT_DEL_ATTACH 21
#define MAILEDIT_CLR_ATTACH 22
#define MAILEDIT_GET_SUBJECT 23
#define MAILEDIT_GET_GOLD 24
#define MAILEDIT_GET_BODYTEXT 25
#define MAILEDIT_PURGE_N_QUIT 26
/* Mail Editor handy defines */
#define MAILEDIT_SUBJECT ((OLC_MAIL(d)->mail)->subject)
#define MAILEDIT_BODYTEXT ((OLC_MAIL(d)->mail)->body)
#define MAILEDIT_GOLD ((OLC_MAIL(d)->mail)->coins)
#define MAILEDIT_URGENT (IS_SET_AR((OLC_MAIL(d)->mail)->mail_flags, MAIL_URGENT))
#define MAILEDIT_COD (IS_SET_AR((OLC_MAIL(d)->mail)->mail_flags, MAIL_COD))
/* Copy modes for mail_copy */
#define MAIL_COPY_NORMAL 0
#define MAIL_COPY_FORWARD 1
#define MAIL_COPY_REPLY 2
/* Special-case sender/recipient ID's for get_sender_name, should be below zero (above zero = player id) */
#define MAIL_TO_NOBODY 0 /* Used internally - do not change this one! */
#define MAIL_FROM_MAIL -1 /* (sender) Mail from the tbaMUD mail system */
#define MAIL_TO_IMMS -2 /* (recipient) Mail to all the MUD's immortals */
#define MAIL_TO_ALL -3 /* (recipient) Mail to all players (usually Imp-only) */
/* Note - changing the list above needs changing the list at the top of mail.c too */
/* This number should match the mail_groups list at the top of mail.c */
#define NUM_MAIL_GROUPS 2
#define ML_ARRAY_MAX 4
#define NO_MAIL -1
struct recipient_list {
long recipient;
struct recipient_list *next;
};
/* old stuff below */
#define HEADER_BLOCK (-1)
#define LAST_BLOCK (-2)
#define DELETED_BLOCK (-3)
/* Note: next_block is part of header_blk in a data block; we can't combine them
* here because we have to be able to differentiate a data block from a header
* block when booting mail system. */
struct header_data_type {
long next_block; /* if header block, link to next block */
long from; /* idnum of the mail's sender */
long to; /* idnum of mail's recipient */
time_t mail_time; /* when was the letter mailed? */
struct mail_data {
long mail_id;
long recipient;
long sender;
time_t sent_time;
char *subject;
char *body;
struct obj_data *attachment;
int coins;
int mail_flags[ML_ARRAY_MAX];
};
/* size of the data part of a header block */
#define HEADER_BLOCK_DATASIZE \
(BLOCK_SIZE - sizeof(long) - sizeof(struct header_data_type) - sizeof(char))
/* size of the data part of a data block */
#define DATA_BLOCK_DATASIZE (BLOCK_SIZE - sizeof(long) - sizeof(char))
/* note that an extra space is allowed in all string fields for the
terminating null character. */
struct header_block_type_d {
long block_type; /* is this a header or data block? */
struct header_data_type header_data; /* other header data */
char txt[HEADER_BLOCK_DATASIZE+1]; /* actual text plus 1 for null */
struct mail_edit_data {
struct mail_data *mail;
struct recipient_list *recipients;
};
struct data_block_type_d {
long block_type; /* -1 if header block, -2 if last data block
in mail, otherwise a link to the next */
char txt[DATA_BLOCK_DATASIZE+1]; /* actual text plus 1 for null */
struct mail_index {
long mail_id;
long recipient;
long sender;
time_t sent_time;
char *subject;
int flags;
};
typedef struct header_block_type_d header_block_type;
typedef struct data_block_type_d data_block_type;
struct position_list_type_d {
long position;
struct position_list_type_d *next;
struct mail_group {
char name[MAX_NAME_LENGTH+1]; /* name entered by player */
long recipient; /* The special recipient ID (below zero) */
};
typedef struct position_list_type_d position_list_type;
/* Functions in mail.c (in the order they appear) */
bool build_mail_index(void); /* Load the mudmail index file on MUD startup */
long new_mail_id(void); /* Get a unique ID for a new mudmail */
void free_mail_index(void); /* Erase the entire mudmail index from memory */
void free_mail(struct mail_data *mail); /* Free memory used by one mail_data structure */
void extract_mail(struct mail_data *mail); /* Free memory used by one mail_data structure */
int find_mail_by_id(long mail_id); /* Get the mail index rnum from the mail id */
void copy_mail_index_entry(struct mail_index *to, struct mail_index *from); /* Make a copy of an index entry */
void copy_mail(struct mail_data *to, struct mail_data *from, int copy_mode); /* Copy the mail data to a new mail */
int create_mail_index_entry(struct mail_data *mail); /* Add a mail to the mudmail index list */
bool delete_mail_index_entry(int mail_id); /* Delete one mudmail from the index (by id) */
bool save_mail_index(void); /* Save the mail index, returns TRUE on success */
int handle_mail_obj(struct obj_data *temp, struct mail_data *ml);/* Put loaded objects into the actual mail */
bool check_mail_dir(long mail_id); /* Check that a mail folder exists or create it */
bool save_as_draft(struct char_data *ch, struct mail_data *ml); /* Save mail as a draft for sending later */
bool save_mail(struct mail_data *ml); /* Save the actual mail for the mudmail file */
bool load_mail(long mail_id, struct mail_data *ml); /* Load mail by id - put data into ml */
void draft_timeout(void); /* Perform a timeout on old draft mails */
bool mail_recip_ok(const char *name); /* Validate a player name for recipients */
struct char_data *find_mailman(struct char_data *ch); /* returns a mailman in the same room as player */
struct char_data *find_immortal_mailman(void); /* returns a mailman in immortal mail room */
int show_inbox_to_char(struct char_data *ch); /* Displays the player's inbox */
int show_outbox_to_char(struct char_data *ch); /* Displays the player's outbox */
void give_mail_attachments(struct char_data *ch, struct mail_data *ml); /* give all mail attachments to a player */
int count_recipients(struct mail_edit_data *ml_list); /* Count the number of recipients in edited mail */
void clear_mail_data(struct mail_data *ml); /* Set all values in struct to zero or NULL */
int purge_marked_mail(struct char_data *ch); /* purges all marked mail for one player */
struct mail_data *create_mail(void); /* Create a new blank mail_data structure */
bool add_recipient(struct mail_edit_data *ml, long player_id); /* Add a recipient to list for mailing */
bool remove_recipient(struct mail_edit_data *ml, long player_id); /* Remove a recipient from the list for mailing */
void clear_recipients(struct mail_edit_data *ml); /* Clear a whole recipient list */
char *recipient_list(struct mail_edit_data *ml); /* Get a list of all recipients */
long get_mail_group_by_name(char *name); /* Get the recipient id from the group name */
void list_attachments_numbered(struct obj_data *list, struct char_data *ch); /* Stacked list of attachments */
struct obj_data *get_attachment_numbered(struct char_data *ch, struct obj_data *list, int find_num); /* Return obj by stacked list line */
bool mail_from_player(long to, long from, char *message_pointer); /* Send a mail from a player to another player */
bool mail_from_mobile(struct char_data *mob); /* Send a mail from a mob using scripts */
void make_cod_payment_mail(struct mail_data *orig); /* Send an auto-COD reply back to mail sender */
bool perform_send_edited(struct char_data *ch, struct mail_edit_data *ml_list); /* Send to multiple recipients */
bool perform_mob_send_edited(struct char_data *mob); /* Send a scripted mob mudmail */
void create_mob_mail(struct char_data *mob); /* Create a blank mail structure if needed */
bool has_mail(struct char_data *ch); /* returns TRUE is player has mail waiting */
int count_deleted(struct char_data *ch); /* Returns the number of mails marked as deleted */
void notify_if_playing(struct char_data *from, int recipient_id); /* Inform a player of a new mail arrival */
void notify_on_login(struct char_data *ch); /* Tell player how many new mails they have */
char *get_sender_name(struct mail_data *ml); /* Get the name of the mail sender by mail_data */
char *get_sender_name_by_id(long mail_id); /* Get the name of the mail sender by mail_id */
char *get_recipient_name(struct mail_data *ml); /* Get the name of the mail recip by mail_data */
char *get_recipient_name_by_id(long mail_id); /* Get the name of the mail recipient by mail_id */
int attachment_count(struct mail_data *ml); /* Count the number of mail attachments */
char *get_mail_text(struct mail_data *ml); /* Create the text string thats shown to players */
void show_mail_to_char(struct char_data *ch, struct mail_data *ml); /* Display full mail details to player */
void mail_view(struct char_data *ch, long mail_id); /* Show a mail to a player (by mail id) */
bool mail_receive(struct char_data *ch, long mail_id); /* Convert a mail into an actual object in inv */
bool mail_delmark(struct char_data *ch, long mail_id); /* Mark a mail for deletion at next purge */
bool mail_forward(struct char_data *ch, long mail_id, long recipient); /* Forward a mail without changing any text */
long get_id_by_inbox_num(struct char_data *ch, int num); /* Work out which mail_id player wants to use */
long get_id_by_outbox_num(struct char_data *ch, int num); /* Work out which mail_id player wants to use */
void mail_view_by_num(struct char_data *ch, int num); /* Show a mail to player by inbox entry number */
bool mail_receive_by_num(struct char_data *ch, int num); /* Receive a mail by inbox entry number */
bool mail_delmark_by_num(struct char_data *ch, int num); /* Mark as deleted by inbox entry number */
ACMD(do_mail);
struct mail_index_type_d {
long recipient; /* who is this mail for? */
position_list_type *list_start; /* list of mail positions */
struct mail_index_type_d *next; /* link to next one */
};
/* Functions in mailedit.c */
ACMD(do_mailedit); /* The mail edit command, called from do_mail */
void mailedit_setup(struct descriptor_data *d); /* Setup a blank structure ready for editing */
void mailedit_cleanup(struct descriptor_data *d); /* Free up the actual OLC structure for exiting */
void mailedit_disp_menu(struct descriptor_data *d); /* Display inbox menu view */
void mailedit_disp_mail(struct descriptor_data *d); /* Display main mail editor (for edit/reply/etc) */
void mailedit_parse(struct descriptor_data *d, char *arg); /* The mail mailedit parser */
typedef struct mail_index_type_d mail_index_type;
#endif /* _MAIL_H_ */

898
src/mailedit.c Executable file
View file

@ -0,0 +1,898 @@
/**************************************************************************
* File: mailedit.c Part of tbaMUD *
* Usage: Oasis OLC - Mudmail. *
* *
* Copyright 1996 Harvey Gilpin. 1997-2001 George Greer. 2010 Stefan Cole. *
**************************************************************************/
#include "conf.h"
#include "sysdep.h"
#include "structs.h"
#include "utils.h"
#include "interpreter.h"
#include "db.h"
#include "comm.h"
#include "handler.h"
#include "modify.h"
#include "mail.h"
#include "oasis.h"
#include "improved-edit.h"
/* External functions */
void list_obj_to_char(struct obj_data *list, struct char_data *ch, int mode, int show);
/* external global variables */
extern const struct mail_group mail_groups[];
/* utility functions */
ACMD(do_mailedit)
{
struct descriptor_data *d;
d = ch->desc;
/* Give descriptor an OLC structure. */
if (d->olc) {
mudlog(BRF, ADMLVL_IMMORT, TRUE,
"SYSERR: do_oasis_medit: Player already had olc structure.");
free(d->olc);
}
CREATE(d->olc, struct oasis_olc_data, 1);
OLC_ZNUM(d) = NOWHERE;
OLC_NUM(d) = 0;
mailedit_setup(d);
mailedit_disp_menu(d);
/* Display messages to the players in the same room as the
player and also log it. */
act("$n starts editing mail.", TRUE, ch, 0, 0, TO_ROOM);
SET_BIT_AR(PLR_FLAGS(ch), PLR_MAILING);
SET_BIT_AR(PLR_FLAGS(ch), PLR_WRITING);
STATE(d) = CON_MAILEDIT;
mudlog(CMP, ADMLVL_IMMORT, TRUE,"MAIL: %s starts editing mudmail in room %d",
GET_NAME(ch), world[IN_ROOM(d->character)].number);
}
/* No 'new' or 'existing' to edit - just set up the mudmail structures */
void mailedit_setup(struct descriptor_data *d)
{
struct mail_edit_data *mail_info;
/* Allocate a scratch mudmails structure. */
CREATE(mail_info, struct mail_edit_data, 1);
mail_info->mail = create_mail();
mail_info->recipients = NULL;
OLC_MAIL(d) = mail_info;
/* Has changed flag. (It hasn't so far, we just made it.) */
OLC_VAL(d) = FALSE;
}
/* clear up memory used by the mudmail structures */
void mailedit_cleanup(struct descriptor_data *d)
{
struct mail_edit_data *mail_info;
struct mail_data *single_mail;
struct obj_data *obj;
mail_info = OLC_MAIL(d);
single_mail = mail_info->mail;
if (single_mail) {
/* Any leftover attachments should be passed back to the owner */
while (single_mail->attachment) {
obj = single_mail->attachment;
obj_from_mail(obj);
obj_to_char(obj, d->character);
}
/* Any leftover gold is returned too */
if ((single_mail->coins > 0) && !IS_SET_AR(single_mail->mail_flags, MAIL_COD)) {
GET_GOLD(d->character) += single_mail->coins;
single_mail->coins = 0;
}
if (single_mail->subject) free(single_mail->subject);
if (single_mail->body) free(single_mail->body);
single_mail = NULL;
free (mail_info->mail);
}
clear_recipients(mail_info);
mail_info = NULL;
free(OLC_MAIL(d));
OLC_MAIL(d) = NULL;
}
/* Menu functions */
/* The 'main menu' - displays inbox, with options */
void mailedit_disp_menu(struct descriptor_data *d)
{
get_char_colors(d->character);
clear_screen(d);
write_to_output(d, "tbaMUD Mail Editor\r\n");
show_inbox_to_char(d->character);
if (CONFIG_DRAFTS_ALLOWED)
write_to_output(d, "%s(%sC%s)%s Create %s(%sV%s)%s View %s(%sR%s)%s Reply %s(%sF%s)%s Forward \r\n"
"%s(%sE%s)%s Receive %s(%sD%s)%s Delete %s(%sO%s)%s Outbox %s(%sQ%s)%s Quit \r\n",
cyn, yel, cyn, nrm,
cyn, yel, cyn, nrm,
cyn, yel, cyn, nrm,
cyn, yel, cyn, nrm,
cyn, yel, cyn, nrm,
cyn, yel, cyn, nrm,
cyn, yel, cyn, nrm,
cyn, yel, cyn, nrm );
else
write_to_output(d, "%s(%sC%s)%s Create %s(%sV%s)%s View %s(%sR%s)%s Reply %s(%sF%s)%s Forward \r\n"
"%s(%sE%s)%s Receive %s(%sD%s)%s Delete %s(%sQ%s)%s Quit \r\n",
cyn, yel, cyn, nrm,
cyn, yel, cyn, nrm,
cyn, yel, cyn, nrm,
cyn, yel, cyn, nrm,
cyn, yel, cyn, nrm,
cyn, yel, cyn, nrm,
cyn, yel, cyn, nrm );
write_to_output(d, "Enter Selection: ");
OLC_MODE(d) = MAILEDIT_INBOX;
}
void mailedit_disp_outbox(struct descriptor_data *d)
{
get_char_colors(d->character);
clear_screen(d);
write_to_output(d, "tbaMUD Mail Editor\r\n");
show_outbox_to_char(d->character);
write_to_output(d, "%s(%sE%s)%s Edit %s(%sV%s)%s View %s(%sD%s)%s Delete %s(%sI%s)%s Inbox %s(%sQ%s)%s Quit\r\n",
cyn, yel, cyn, nrm,
cyn, yel, cyn, nrm,
cyn, yel, cyn, nrm,
cyn, yel, cyn, nrm,
cyn, yel, cyn, nrm );
write_to_output(d, "Enter Selection: ");
OLC_MODE(d) = MAILEDIT_OUTBOX;
}
void mailedit_disp_mail(struct descriptor_data *d)
{
char att[15], gold[25];
int gold_amt;
get_char_colors(d->character);
clear_screen(d);
bool can_attach = TRUE;
if (count_recipients(OLC_MAIL(d)) > 1) can_attach = FALSE;
if (attachment_count(OLC_MAIL(d)->mail) > 0)
sprintf(att, "%s%d object%s", can_attach ? "@r" : "@y", attachment_count(OLC_MAIL(d)->mail), attachment_count(OLC_MAIL(d)->mail) > 1 ? "s" : "");
else
sprintf(att, "<None>");
if (MAILEDIT_GOLD > 0) {
sprintf(gold, "%s%s coins", can_attach ? "@r" : "@y", add_commas(MAILEDIT_GOLD));
} else {
sprintf(gold, "<None>");
}
gold_amt = CONFIG_STAMP_COST + (attachment_count(OLC_MAIL(d)->mail) * CONFIG_OBJECT_COST);
write_to_output(d, "tbaMUD Mail Editor\r\n");
if (GET_LEVEL(d->character) < CONFIG_FREE_MAIL_LEVEL) {
write_to_output(d, "Current cost to send this mail: %s%d%s coins\r\n", yel, gold_amt, nrm);
} else {
write_to_output(d, "Current cost to send this mail: %sFree!%s\r\n", yel, nrm);
}
write_to_output(d, "%sA%s)%s Recipients : %s%s\r\n"
"%sB%s)%s Subject : %s%s\r\n"
"%sC%s)%s Urgency : %s%s\r\n"
"%sD%s)%s Attachments : %s%s\r\n"
"%sE%s)%s Gold : %s%s\r\n"
"%sF%s)%s Gold Mode : %s%s\r\n"
"%sG%s)%s Body Text : \r\n%s%s\r\n"
"%sS%s)%s Send Mail\r\n"
"%sX%s)%s Clear Mail data\r\n"
"%sQ%s)%s Quit without sending\r\n",
yel, cyn, nrm, yel, OLC_MAIL(d)->recipients ? recipient_list(OLC_MAIL(d)) : "<None!>",
yel, cyn, nrm, yel, MAILEDIT_SUBJECT == NULL ? "- No Subject -" : MAILEDIT_SUBJECT,
yel, cyn, nrm, yel, MAILEDIT_URGENT ? "@RUrgent!" : "Normal",
yel, cyn, CONFIG_CAN_MAIL_OBJ ? nrm : gry, CONFIG_CAN_MAIL_OBJ ? yel : gry, att,
yel, cyn, CONFIG_CAN_MAIL_GOLD ? nrm : gry, CONFIG_CAN_MAIL_GOLD ? yel : gry, gold,
yel, cyn, nrm, yel, MAILEDIT_COD ? "Cash-on-Delivery (COD)" : "Send Gold",
yel, cyn, nrm, yel, MAILEDIT_BODYTEXT == NULL ? "No Text" : MAILEDIT_BODYTEXT,
yel, cyn, nrm,
yel, cyn, nrm,
yel, cyn, nrm);
write_to_output(d, "Enter Selection: ");
OLC_MODE(d) = MAILEDIT_MAILEDIT;
}
void mailedit_disp_recipients(struct descriptor_data *d)
{
get_char_colors(d->character);
clear_screen(d);
write_to_output(d, "tbaMUD Mail Recipient Editor\r\n");
write_to_output(d, "Current Recipient List:\r\n");
write_to_output(d, "%s%s%s\r\n", yel, OLC_MAIL(d)->recipients ? recipient_list(OLC_MAIL(d)) : "<None!>", nrm);
write_to_output(d, "%sA%s)%s Add a Recipient\r\n"
"%sB%s)%s Delete a Recipient\r\n"
"%sC%s)%s Clear all Recipients\r\n"
"%sQ%s)%s Quit (back to Editor)\r\n",
yel, cyn, nrm,
yel, cyn, nrm,
yel, cyn, nrm,
yel, cyn, nrm);
write_to_output(d, "Enter Selection: ");
OLC_MODE(d) = MAILEDIT_RECIP_MENU;
}
void mailedit_disp_attachments(struct descriptor_data *d)
{
get_char_colors(d->character);
clear_screen(d);
write_to_output(d, "tbaMUD Mail Attachment Editor\r\n");
write_to_output(d, "Current Attached Objects:\r\n");
list_obj_to_char((OLC_MAIL(d)->mail)->attachment, d->character, 1, TRUE);
write_to_output(d, "\r\n");
write_to_output(d, "%sA%s)%s Add an Object\r\n"
"%sB%s)%s Remove an Object\r\n"
"%sC%s)%s Remove all Objects\r\n"
"%sQ%s)%s Quit (back to Editor)\r\n",
yel, cyn, nrm,
yel, cyn, nrm,
yel, cyn, nrm,
yel, cyn, nrm);
write_to_output(d, "Enter Selection: ");
OLC_MODE(d) = MAILEDIT_ATTACH_MENU;
}
void mailedit_parse(struct descriptor_data *d, char *arg)
{
int i, num;
long mail_id, diff, gold;
struct mail_data *ml;
struct obj_data *obj;
char *oldtext = NULL;
switch (OLC_MODE(d)) {
case MAILEDIT_ASK_DRAFT:
switch (*arg) {
case 'y':
case 'Y':
/* Save the mail as a draft. */
save_as_draft(d->character, OLC_MAIL(d)->mail);
clear_mail_data(OLC_MAIL(d)->mail);
mailedit_disp_outbox(d);
return;
case 'n':
case 'N':
clear_mail_data(OLC_MAIL(d)->mail);
mailedit_disp_menu(d);
return;
default:
write_to_output(d, "Invalid choice!\r\n");
write_to_output(d, "Do you wish to save this mail as a draft? (Y/N): ");
return;
}
break;
case MAILEDIT_ASK_QUIT:
switch (*arg) {
case 'y':
case 'Y':
clear_mail_data(OLC_MAIL(d)->mail);
mailedit_disp_outbox(d);
return;
case 'n':
case 'N':
mailedit_disp_mail(d);
return;
default:
write_to_output(d, "Invalid choice!\r\n");
write_to_output(d, "Do you wish to quit and lose your changes? (Y/N): ");
return;
}
break;
case MAILEDIT_INBOX:
switch (*arg) {
case 'q':
case 'Q':
if (count_deleted(d->character) > 0) {
write_to_output(d, "You have mail marked for deletion.\r\n");
write_to_output(d, "Do you wish to purge all marked mails now? (Y/N)\r\n");
OLC_MODE(d) = MAILEDIT_PURGE_N_QUIT;
REMOVE_BIT_AR(PLR_FLAGS(d->character), PLR_MAILING);
return;
}
REMOVE_BIT_AR(PLR_FLAGS(d->character), PLR_MAILING);
cleanup_olc(d, CLEANUP_ALL);
return;
case 'c':
case 'C':
if ((GET_LEVEL(d->character) < CONFIG_FREE_MAIL_LEVEL) && (GET_GOLD(d->character) < CONFIG_STAMP_COST)) {
write_to_output(d, "Mails cost %d coins, and you can't afford that!\r\n", CONFIG_STAMP_COST);
mailedit_disp_menu(d);
return;
}
clear_mail_data(OLC_MAIL(d)->mail);
mailedit_disp_mail(d);
break;
case 'v':
case 'V':
write_to_output(d, "Which mail do you wish to view? : ");
OLC_MODE(d) = MAILEDIT_VIEW;
break;
case 'r':
case 'R':
if ((GET_LEVEL(d->character) < CONFIG_FREE_MAIL_LEVEL) && (GET_GOLD(d->character) < CONFIG_STAMP_COST)) {
write_to_output(d, "Mails cost %d coins, and you can't afford that!\r\n", CONFIG_STAMP_COST);
mailedit_disp_menu(d);
return;
}
write_to_output(d, "Which mail do you wish to reply to? : ");
OLC_MODE(d) = MAILEDIT_REPLY;
break;
case 'f':
case 'F':
if ((GET_LEVEL(d->character) < CONFIG_FREE_MAIL_LEVEL) && (GET_GOLD(d->character) < CONFIG_STAMP_COST)) {
write_to_output(d, "Mails cost %d coins, and you can't afford that!\r\n", CONFIG_STAMP_COST);
mailedit_disp_menu(d);
return;
}
write_to_output(d, "Which mail do you wish to forward? : ");
OLC_MODE(d) = MAILEDIT_FORWARD;
break;
case 'd':
case 'D':
write_to_output(d, "Which mail do you wish to delete? : ");
OLC_MODE(d) = MAILEDIT_DELETE;
break;
case 'e':
case 'E':
write_to_output(d, "Which mail do you wish to receive? : ");
OLC_MODE(d) = MAILEDIT_RECEIVE;
break;
case 'o':
case 'O':
mailedit_disp_outbox(d);
break;
default:
write_to_output(d, "Invalid Choice!\r\nEnter Selection : ");
break;
}
break;
case MAILEDIT_OUTBOX:
switch (*arg) {
case 'q':
case 'Q':
cleanup_olc(d, CLEANUP_ALL);
return;
case 'e':
case 'E':
if ((GET_LEVEL(d->character) < CONFIG_FREE_MAIL_LEVEL) && (GET_GOLD(d->character) < CONFIG_STAMP_COST)) {
write_to_output(d, "Mails cost %d coins, and you can't afford that!\r\n", CONFIG_STAMP_COST);
mailedit_disp_menu(d);
return;
}
write_to_output(d, "Which mail do you wish to edit? : ");
OLC_MODE(d) = MAILEDIT_OUTEDIT;
break;
case 'v':
case 'V':
write_to_output(d, "Which mail do you wish to view? : ");
OLC_MODE(d) = MAILEDIT_OUTVIEW;
break;
case 'i':
case 'I':
mailedit_disp_menu(d);
break;
case 'd':
case 'D':
write_to_output(d, "Which mail do you wish to delete? : ");
OLC_MODE(d) = MAILEDIT_OUTDELETE;
break;
default:
write_to_output(d, "Invalid Choice!\r\nEnter Selection : ");
break;
}
break;
case MAILEDIT_VIEW:
num = atoi(arg);
if (num == 0) {
mailedit_disp_menu(d);
return;
}
mail_id = get_id_by_inbox_num(d->character, num);
if (mail_id == NO_MAIL) {
write_to_output(d, "Invalid mail number.\r\n");
mailedit_disp_menu(d);
return;
}
mail_view(d->character, mail_id);
write_to_output(d, "-- Press Enter to Continue! --\r\n");
OLC_MODE(d) = MAILEDIT_BACK_TO_MENU;
break;
case MAILEDIT_REPLY:
num = atoi(arg);
if (num == 0) {
mailedit_disp_menu(d);
return;
}
mail_id = get_id_by_inbox_num(d->character, num);
if (mail_id == NO_MAIL) {
write_to_output(d, "Invalid mail number.\r\n");
mailedit_disp_menu(d);
return;
}
if ((ml = create_mail()) != NULL) {
load_mail(mail_id, ml);
copy_mail(OLC_MAIL(d)->mail, ml, MAIL_COPY_REPLY);
for (i=0; i<ML_ARRAY_MAX; i++)
ml->mail_flags[i] = 0;
(OLC_MAIL(d)->mail)->mail_id = NO_MAIL;
(OLC_MAIL(d)->mail)->sender = GET_ID(d->character);
add_recipient(OLC_MAIL(d), ml->sender);
mailedit_disp_mail(d);
}
break;
case MAILEDIT_FORWARD:
num = atoi(arg);
if (num == 0) {
mailedit_disp_menu(d);
return;
}
mail_id = get_id_by_inbox_num(d->character, num);
if (mail_id == NO_MAIL) {
write_to_output(d, "Invalid mail number.\r\n");
mailedit_disp_menu(d);
return;
}
if ((ml = create_mail()) != NULL) {
load_mail(mail_id, ml);
copy_mail(OLC_MAIL(d)->mail, ml, MAIL_COPY_FORWARD);
for (i=0; i<ML_ARRAY_MAX; i++)
ml->mail_flags[i] = 0;
(OLC_MAIL(d)->mail)->mail_id = NO_MAIL;
(OLC_MAIL(d)->mail)->sender = GET_ID(d->character);
mailedit_disp_mail(d);
}
break;
case MAILEDIT_DELETE:
num = atoi(arg);
if (num == 0) {
mailedit_disp_menu(d);
return;
}
mail_id = get_id_by_inbox_num(d->character, num);
if (mail_id == NO_MAIL) {
write_to_output(d, "Invalid mail number.\r\n");
mailedit_disp_menu(d);
return;
}
mail_delmark(d->character, mail_id);
mailedit_disp_mail(d);
break;
case MAILEDIT_RECEIVE:
num = atoi(arg);
if (num == 0) {
mailedit_disp_menu(d);
return;
}
mail_id = get_id_by_inbox_num(d->character, num);
if (mail_id == NO_MAIL) {
write_to_output(d, "Invalid mail number.\r\n");
mailedit_disp_menu(d);
return;
}
if (mail_receive(d->character, mail_id))
write_to_output(d, "Mail received into your inventory.\r\n");
mailedit_disp_menu(d);
break;
case MAILEDIT_OUTEDIT:
num = atoi(arg);
if (num == 0) {
mailedit_disp_outbox(d);
return;
}
mail_id = get_id_by_outbox_num(d->character, num);
if (mail_id == NO_MAIL) {
write_to_output(d, "Invalid mail number.\r\n");
mailedit_disp_outbox(d);
return;
}
if ((ml = create_mail()) != NULL) {
load_mail(mail_id, ml);
copy_mail(OLC_MAIL(d)->mail, ml, MAIL_COPY_NORMAL);
(OLC_MAIL(d)->mail)->sender = GET_ID(d->character);
mailedit_disp_mail(d);
}
break;
case MAILEDIT_OUTVIEW:
num = atoi(arg);
if (num == 0) {
mailedit_disp_menu(d);
return;
}
mail_id = get_id_by_outbox_num(d->character, num);
if (mail_id == NO_MAIL) {
write_to_output(d, "Invalid mail number.\r\n");
mailedit_disp_outbox(d);
return;
}
mail_view(d->character, mail_id);
write_to_output(d, "-- Press Enter to Continue! --\r\n");
OLC_MODE(d) = MAILEDIT_BACK_TO_MENU;
break;
case MAILEDIT_OUTDELETE:
num = atoi(arg);
if (num == 0) {
mailedit_disp_menu(d);
return;
}
mail_id = get_id_by_outbox_num(d->character, num);
if (mail_id == NO_MAIL) {
write_to_output(d, "Invalid mail number.\r\n");
mailedit_disp_outbox(d);
return;
}
mail_delmark(d->character, mail_id);
mailedit_disp_mail(d);
break;
case MAILEDIT_BACK_TO_MENU:
mailedit_disp_menu(d);
break;
case MAILEDIT_RECIP_MENU:
switch (*arg) {
case 'a':
case 'A':
/* Mail with attachments can only have one recipient */
if (count_recipients(OLC_MAIL(d)) > 0) {
if (((OLC_MAIL(d)->mail)->attachment) || ((OLC_MAIL(d)->mail)->coins > 0 && !IS_SET_AR((OLC_MAIL(d)->mail)->mail_flags, MAIL_COD))) {
write_to_output(d, "Sorry, mail with attachments cannot be sent to more than one person!\r\n");
mailedit_disp_recipients(d);
return;
}
}
write_to_output(d, "Enter a player name to add: ");
OLC_MODE(d) = MAILEDIT_ADD_RECIP;
break;
case 'b':
case 'B':
write_to_output(d, "Enter a player name to remove: ");
OLC_MODE(d) = MAILEDIT_DEL_RECIP;
break;
case 'c':
case 'C':
write_to_output(d, "Are you sure you wish to remove ALL recipients? (Y/N): ");
OLC_MODE(d) = MAILEDIT_CLR_RECIP;
break;
case 'q':
case 'Q':
mailedit_disp_mail(d);
break;
}
break;
case MAILEDIT_ADD_RECIP:
/* check 'special cases' (mail groups) */
if ((mail_id = get_mail_group_by_name(arg)) == MAIL_TO_NOBODY) {
if ((mail_id = get_id_by_name(arg)) < 0 || !mail_recip_ok(arg)) {
write_to_output(d, "No one by that name is registered here!\r\n");
mailedit_disp_recipients(d);
return;
}
}
if (mail_id == MAIL_TO_ALL && GET_LEVEL(d->character) < CONFIG_MIN_SEND_TO_ALL) {
write_to_output(d, "Sorry, you don't have sufficient access to send to 'all'\r\n");
mailedit_disp_recipients(d);
return;
}
add_recipient(OLC_MAIL(d), mail_id);
mailedit_disp_recipients(d);
break;
case MAILEDIT_DEL_RECIP:
if ((mail_id = get_id_by_name(arg)) < 0 || !mail_recip_ok(arg)) {
write_to_output(d, "No one by that name is registered here!\r\n");
mailedit_disp_recipients(d);
return;
}
remove_recipient(OLC_MAIL(d), mail_id);
mailedit_disp_recipients(d);
break;
case MAILEDIT_CLR_RECIP:
switch (*arg) {
case 'y':
case 'Y':
clear_recipients(OLC_MAIL(d));
mailedit_disp_recipients(d);
break;
case 'n':
case 'N':
mailedit_disp_recipients(d);
break;
default : write_to_output(d, "Invalid choice!\r\nAre you sure you wish to remove ALL recipients? (Y/N): ");
break;
}
break;
case MAILEDIT_ATTACH_MENU:
switch (*arg) {
case 'a':
case 'A':
/* Mail with attachments can only have one recipient */
if (count_recipients(OLC_MAIL(d)) > 1) {
write_to_output(d, "Sorry, mail with multiple recipients cannot have attachments!\r\n");
mailedit_disp_attachments(d);
return;
}
if ((d->character)->carrying == NULL) {
write_to_output(d, "Your inventory seems to be empty - you cannot attach anything.\r\n");
mailedit_disp_attachments(d);
return;
}
list_attachments_numbered((d->character)->carrying, d->character);
write_to_output(d, "Enter a object to add: ");
OLC_MODE(d) = MAILEDIT_ADD_ATTACH;
break;
case 'b':
case 'B':
if ((OLC_MAIL(d)->mail)->attachment == NULL) {
write_to_output(d, "There are no attachments - you cannot remove anything.\r\n");
mailedit_disp_attachments(d);
return;
}
list_attachments_numbered((OLC_MAIL(d)->mail)->attachment, d->character);
write_to_output(d, "Enter an object to remove: ");
OLC_MODE(d) = MAILEDIT_DEL_ATTACH;
break;
case 'c':
case 'C':
write_to_output(d, "Are you sure you wish to remove ALL objects? (Y/N): ");
OLC_MODE(d) = MAILEDIT_CLR_ATTACH;
break;
case 'q':
case 'Q':
mailedit_disp_mail(d);
break;
}
break;
case MAILEDIT_ADD_ATTACH:
num = atoi(arg);
if ((obj = get_attachment_numbered(d->character, (d->character)->carrying, num)) == NULL) {
write_to_output(d, "That object number is not in your inventory\r\n");
mailedit_disp_attachments(d);
return;
}
obj_from_char(obj);
obj_to_mail(obj, OLC_MAIL(d)->mail);
mailedit_disp_attachments(d);
break;
case MAILEDIT_DEL_ATTACH:
num = atoi(arg);
if ((obj = get_attachment_numbered(d->character, (OLC_MAIL(d)->mail)->attachment, num)) == NULL) {
write_to_output(d, "That object number is not attached.\r\n");
mailedit_disp_attachments(d);
return;
}
obj_from_mail(obj);
obj_to_char(obj, d->character);
mailedit_disp_attachments(d);
break;
case MAILEDIT_CLR_ATTACH:
switch (*arg) {
case 'y':
case 'Y':
while ((OLC_MAIL(d)->mail)->attachment) {
obj = (OLC_MAIL(d)->mail)->attachment;
obj_from_mail(obj);
obj_to_char(obj, d->character);
}
mailedit_disp_attachments(d);
break;
case 'n':
case 'N':
mailedit_disp_attachments(d);
break;
default : write_to_output(d, "Invalid choice!\r\nAre you sure you wish to remove ALL attachments? (Y/N): ");
break;
}
break;
case MAILEDIT_GET_GOLD:
gold = atol(arg);
diff = (gold - (OLC_MAIL(d)->mail)->coins);
if (diff > GET_GOLD(d->character)) {
write_to_output(d, "@RYou don't have that much gold!@n\r\n");
mailedit_disp_mail(d);
return;
}
GET_GOLD(d->character) -= diff;
(OLC_MAIL(d)->mail)->coins = gold;
mailedit_disp_mail(d);
break;
case MAILEDIT_GET_SUBJECT:
if ((OLC_MAIL(d)->mail)->subject)
free ((OLC_MAIL(d)->mail)->subject);
(OLC_MAIL(d)->mail)->subject = strdup(arg);
mailedit_disp_mail(d);
break;
case MAILEDIT_MAILEDIT:
switch (*arg) {
case 'q':
case 'Q':
if (CONFIG_DRAFTS_ALLOWED) {
write_to_output(d, "Do you wish to save this mail as a draft? (Y/N): ");
OLC_MODE(d) = MAILEDIT_ASK_DRAFT;
} else {
write_to_output(d, "Do you wish to quit and lose your changes? (Y/N): ");
OLC_MODE(d) = MAILEDIT_ASK_QUIT;
}
break;
case 'a':
case 'A':
mailedit_disp_recipients(d);
break;
case 'b':
case 'B':
write_to_output(d, "Enter a subject for this mail: ");
OLC_MODE(d) = MAILEDIT_GET_SUBJECT;
break;
case 'c':
case 'C':
TOGGLE_BIT_AR((OLC_MAIL(d)->mail)->mail_flags, MAIL_URGENT);
mailedit_disp_mail(d);
break;
case 'd':
case 'D':
if (CONFIG_CAN_MAIL_OBJ) {
mailedit_disp_attachments(d);
} else {
write_to_output(d, "@RSorry, object attachments are disabled!@n\r\n");
mailedit_disp_mail(d);
}
break;
case 'e':
case 'E':
if (CONFIG_CAN_MAIL_GOLD) {
write_to_output(d, "Enter a number of gold coins: ");
OLC_MODE(d) = MAILEDIT_GET_GOLD;
} else {
write_to_output(d, "@RSorry, gold attachments are disabled!@n\r\n");
mailedit_disp_mail(d);
}
break;
case 'f':
case 'F':
/* Flicking between COD and 'send money', we need to give/take gold from the player */
if (IS_SET_AR((OLC_MAIL(d)->mail)->mail_flags, MAIL_COD) && ((OLC_MAIL(d)->mail)->coins > 0)) {
diff = (OLC_MAIL(d)->mail)->coins;
if (diff > GET_GOLD(d->character)) {
write_to_output(d, "@RYou don't have enough gold to do that!@n\r\n");
mailedit_disp_mail(d);
return;
}
GET_GOLD(d->character) -= diff;
} else if (!IS_SET_AR((OLC_MAIL(d)->mail)->mail_flags, MAIL_COD) && ((OLC_MAIL(d)->mail)->coins > 0)) {
diff = (OLC_MAIL(d)->mail)->coins;
GET_GOLD(d->character) += diff;
}
TOGGLE_BIT_AR((OLC_MAIL(d)->mail)->mail_flags, MAIL_COD);
mailedit_disp_mail(d);
break;
case 'g':
case 'G':
OLC_MODE(d) = MAILEDIT_GET_BODYTEXT;
send_editor_help(d);
write_to_output(d, "Enter the main body text for this mail:\r\n\r\n");
if ((OLC_MAIL(d)->mail)->body) {
write_to_output(d, "%s", (OLC_MAIL(d)->mail)->body);
oldtext = strdup((OLC_MAIL(d)->mail)->body);
}
string_write(d, &(OLC_MAIL(d)->mail)->body, MAX_MAIL_SIZE, 0, oldtext);
break;
case 's':
case 'S':
if (GET_LEVEL(d->character) < CONFIG_FREE_MAIL_LEVEL) {
gold = CONFIG_STAMP_COST + (attachment_count(OLC_MAIL(d)->mail) * CONFIG_OBJECT_COST);
} else {
gold = 0;
}
if (gold > 0 && GET_GOLD(d->character) < gold ) {
write_to_output(d, "This mail costs %ld coins, and you can't afford that!\r\n", gold );
mailedit_disp_mail(d);
return;
}
(OLC_MAIL(d)->mail)->sender = GET_ID(d->character);
if (perform_send_edited(d->character, OLC_MAIL(d)) == FALSE) {
write_to_output(d, "@RERROR: Unable to send Mail: Please tell an Imm!@n\r\n");
/* Sending failed - return to editor, so they can choose to save as draft */
mailedit_disp_mail(d);
return;
}
/* Sending was successful - clean up */
if (gold) GET_GOLD(d->character) -= gold;
clear_mail_data(OLC_MAIL(d)->mail);
clear_recipients(OLC_MAIL(d));
write_to_output(d, "Sending of mail successful! Press Enter to continue.\r\n");
OLC_MODE(d) = MAILEDIT_BACK_TO_MENU;
break;
case 'x':
case 'X':
clear_mail_data(OLC_MAIL(d)->mail);
mailedit_disp_mail(d);
break;
default:
write_to_output(d, "Invalid Choice!\r\nEnter Selection : ");
break;
}
break;
case MAILEDIT_PURGE_N_QUIT:
switch (*arg) {
case 'y':
case 'Y':
num = purge_marked_mail(d->character);
if (num > 0) {
write_to_output(d, "%d deleted mail%s ha%s been purged.", num, num == 1 ? "" : "s", num == 1 ? "s" : "ve");
}
cleanup_olc(d, CLEANUP_ALL);
break;
case 'n':
case 'N':
cleanup_olc(d, CLEANUP_ALL);
break;
default : write_to_output(d, "Invalid choice!\r\nDo you wish to purge all marked mails now? (Y/N): ");
break;
}
break;
default:
write_to_output(d, "Sorry - There appears to be a problem, returning to inbox.\r\n");
log("SYSERR: mailedit: Invalid submode (%d)", OLC_MODE(d));
mailedit_disp_menu(d);
break;
}
}
void mailedit_string_cleanup(struct descriptor_data *d, int terminator)
{
switch (OLC_MODE(d)) {
case MAILEDIT_GET_BODYTEXT:
mailedit_disp_mail(d);
break;
}
}

View file

@ -196,6 +196,7 @@ void string_add(struct descriptor_data *d, char *str)
{ CON_HEDIT, hedit_string_cleanup },
{ CON_QEDIT , qedit_string_cleanup },
{ CON_IBTEDIT, ibtedit_string_cleanup },
{ CON_MAILEDIT , mailedit_string_cleanup },
{ -1, NULL }
};
@ -222,9 +223,12 @@ static void playing_string_cleanup(struct descriptor_data *d, int action)
{
if (PLR_FLAGGED(d->character, PLR_MAILING)) {
if (action == STRINGADD_SAVE && *d->str) {
store_mail(d->mail_to, GET_IDNUM(d->character), *d->str);
write_to_output(d, "Message sent!\r\n");
notify_if_playing(d->character, d->mail_to);
if (mail_from_player(d->mail_to, GET_IDNUM(d->character), *d->str)) {
write_to_output(d, "Message sent!\r\n");
notify_if_playing(d->character, d->mail_to);
} else {
write_to_output(d, "Error: Mail could not be sent. Please tell an Imm\r\n");
}
} else
write_to_output(d, "Mail aborted.\r\n");
free(*d->str);

View file

@ -48,7 +48,7 @@ static struct olc_scmd_info_t {
*/
/* Global variables defined here, used elsewhere */
const char *nrm, *grn, *cyn, *yel;
const char *nrm, *grn, *cyn, *yel, *gry;
/* Internal Function prototypes */
static void free_config(struct config_data *data);
@ -70,6 +70,7 @@ void get_char_colors(struct char_data *ch)
grn = CCGRN(ch, C_NRM);
cyn = CCCYN(ch, C_NRM);
yel = CCYEL(ch, C_NRM);
gry = CBBLK(ch, C_NRM);
}
/* This procedure frees up the strings and/or the structures attatched to a

View file

@ -98,6 +98,7 @@ struct oasis_olc_data {
struct prefs_data *prefs; /* used for 'prefedit' */
struct ibt_data *ibt; /* used for 'ibtedit' */
struct house_control_data *house; /* used for 'hsedit' */
struct mail_edit_data *mail; /* used for Mudmail editor */
int script_mode;
int trigger_position;
int item_type;
@ -106,7 +107,7 @@ struct oasis_olc_data {
};
/* Exported globals. */
extern const char *nrm, *grn, *cyn, *yel;
extern const char *nrm, *grn, *cyn, *yel, *gry;
/* Descriptor access macros. */
#define OLC(d) ((d)->olc)
@ -131,6 +132,7 @@ extern const char *nrm, *grn, *cyn, *yel;
#define OLC_PREFS(d) (OLC(d)->prefs) /**< Preferences structure */
#define OLC_IBT(d) (OLC(d)->ibt) /**< IBT (idea/bug/typo) structure */
#define OLC_HOUSE(d) (OLC(d)->house) /**< Player-Owned House/Shop structure */
#define OLC_MAIL(d) (OLC(d)->mail) /**< Mudmail structure. */
/* Other macros. */
#define OLC_EXIT(d) (OLC_ROOM(d)->dir_option[OLC_VAL(d)])
@ -333,6 +335,7 @@ extern const char *nrm, *grn, *cyn, *yel;
#define CEDIT_MENU 14
#define CEDIT_WELC_MESSG 15
#define CEDIT_START_MESSG 16
#define CEDIT_MUDMAIL_OPTIONS_MENU 17
/* Numerical responses. */
#define CEDIT_NUMERICAL_RESPONSE 20
@ -373,6 +376,13 @@ extern const char *nrm, *grn, *cyn, *yel;
#define CEDIT_MAP_OPTION 55
#define CEDIT_MAP_SIZE 56
#define CEDIT_MINIMAP_SIZE 57
#define CEDIT_STAMP_COST 58
#define CEDIT_OBJECT_COST 59
#define CEDIT_DRAFT_TIMEOUT 60
#define CEDIT_MIN_MAIL_LEVEL 61
#define CEDIT_MIN_FREE_LEVEL 62
#define CEDIT_MAIL_ANYWHERE 63
#define CEDIT_MAIL_ALL_PLAYERS 64
/* Hedit Submodes of connectedness. */
#define HEDIT_CONFIRM_SAVESTRING 0
@ -416,6 +426,12 @@ void clear_screen(struct descriptor_data *);
int can_edit_zone(struct char_data *ch, zone_rnum rnum);
ACMD(do_oasis);
/* public functions from mailedit.c */
ACMD(do_mail);
ACMD(do_mailedit);
void mailedit_string_cleanup(struct descriptor_data *d, int terminator);
void mailedit_parse(struct descriptor_data *d, char *arg);
/* public functions from medit.c */
void medit_setup_existing(struct descriptor_data *d, int rnum);
void medit_save_internally(struct descriptor_data *d);

View file

@ -109,16 +109,6 @@ void assign_mobiles(void)
ASSIGNMOB(3105, mayor);
ASSIGNMOB(110, postmaster);
ASSIGNMOB(1201, postmaster);
ASSIGNMOB(3010, postmaster);
ASSIGNMOB(10412, postmaster);
ASSIGNMOB(10719, postmaster);
ASSIGNMOB(25710, postmaster);
ASSIGNMOB(27164, postmaster);
ASSIGNMOB(30128, postmaster);
ASSIGNMOB(31510, postmaster);
ASSIGNMOB(1200, receptionist);
ASSIGNMOB(3005, receptionist);
ASSIGNMOB(5404, receptionist);
@ -181,7 +171,6 @@ struct spec_func_data spec_func_list[] = {
{"Fido", fido },
{"Janitor", janitor },
{"Cityguard", cityguard },
{"Postmaster", postmaster },
{"Receptionist", receptionist },
{"Cryogenicist", cryogenicist},
{"Bulletin Board", gen_board },

View file

@ -92,8 +92,9 @@
#define ROOM_OLC 14 /**< (R) Modifyable/!compress */
#define ROOM_BFS_MARK 15 /**< (R) breath-first srch mrk */
#define ROOM_WORLDMAP 16 /**< World-map style maps here */
#define ROOM_MAIL 17 /**< Mudmail can be sent from here */
/** The total number of Room Flags */
#define NUM_ROOM_FLAGS 17
#define NUM_ROOM_FLAGS 18
/* Zone info: Used in zone_data.zone_flags */
#define ZONE_CLOSED 0 /**< Zone is closed - players cannot enter */
@ -222,9 +223,10 @@
#define MOB_NOBASH 16 /**< Mob can't be bashed (e.g. trees) */
#define MOB_NOBLIND 17 /**< Mob can't be blinded */
#define MOB_NOKILL 18 /**< Mob can't be attacked */
#define MOB_NOTDEADYET 19 /**< (R) Mob being extracted */
#define MOB_MAILMAN 19 /**< Mob stands in room with MAIL flag */
#define MOB_NOTDEADYET 20 /**< (R) Mob being extracted */
#define NUM_MOB_FLAGS 19
#define NUM_MOB_FLAGS 20
/* Preference flags: used by char_data.player_specials.pref */
#define PRF_BRIEF 0 /**< Room descs won't normally be shown */
@ -358,10 +360,11 @@
#define CON_PREFEDIT 29 /**< OLC mode - preference edit */
#define CON_IBTEDIT 30 /**< OLC mode - idea/bug/typo edit */
#define CON_HSEDIT 31 /**< OLC mode - house editor */
#define CON_MAILEDIT 32 /**< OLC mode - Mudmail editor */
/* OLC States range - used by IS_IN_OLC and IS_PLAYING */
#define FIRST_OLC_STATE CON_OEDIT /**< The first CON_ state that is an OLC */
#define LAST_OLC_STATE CON_HSEDIT /**< The last CON_ state that is an OLC */
#define LAST_OLC_STATE CON_MAILEDIT /**< The last CON_ state that is an OLC */
/* Character equipment positions: used as index for char_data.equipment[] */
/* NOTE: Don't confuse these constants with the ITEM_ bitvectors
@ -758,6 +761,7 @@ struct obj_data
struct obj_data *next_content; /**< For 'contains' lists */
struct obj_data *next; /**< For the object list */
struct char_data *sitting_here; /**< For furniture, who is sitting in it */
struct mail_data *in_mail; /**< Which mail object is attached to */
};
/** Instance info for an object that gets saved to disk.
@ -1010,6 +1014,8 @@ struct mob_special_data
byte default_pos; /**< Default position (standing, sleeping, etc.) */
byte damnodice; /**< The number of dice to roll for damage */
byte damsizedice; /**< The size of each die rolled for damage. */
struct mail_edit_data *ml_list; /**< Mail info for sending from mobs by script */
};
/** An affect structure. */
@ -1385,6 +1391,22 @@ struct autowiz_data
int min_wizlist_lev; /**< Minimun level to show on wizlist. */
};
/** The Mail System options. */
struct mail_config {
int mail_allowed; /* Is mudmail allowed? (to disable whole mudmail system) Yes */
int objects_allowed; /* object mailing allowed Yes */
int gold_allowed; /* gold mailing allowed? Yes */
int stamp_cost; /* Stamp Cost 150 coins */
int object_cost; /* Cost per object for each attachment 30 coins */
int min_level; /* Min level that can mail 1 */
int min_free_level; /* Min level for free mail Immortal */
int allow_drafts; /* Can players save draft mudmails? Yes */
int draft_timeout; /* No. of days a draft mail can stay in the outbox 28 days */
int safe_mailing; /* Can players be attacked or stolen from while mailing? Yes */
int min_mail_anywhere; /* Min level that can send mail from anywhere? Immortal */
int min_send_to_all; /* Min level that can send mail to all players? Implementor */
};
/**
Main Game Configuration Structure.
Global variables that can be changed within the game are held within this
@ -1408,6 +1430,8 @@ struct config_data
struct game_operation operation;
/** Autowiz specific settings, like turning it on and minimum level */
struct autowiz_data autowiz;
/** Mudmail configuration */
struct mail_config mail;
};
#ifdef MEMORY_DEBUG

View file

@ -26,10 +26,11 @@ default: all
all: $(BINDIR)/asciipasswd \
$(BINDIR)/autowiz \
$(BINDIR)/plrtoascii \
$(BINDIR)/rebuildIndex \
$(BINDIR)/rebuildMailIndex \
$(BINDIR)/shopconv \
$(BINDIR)/sign \
$(BINDIR)/split \
$(BINDIR)/rebuildIndex \
$(BINDIR)/wld2html \
$(BINDIR)/webster
@ -39,6 +40,10 @@ autowiz: $(BINDIR)/autowiz
plrtoascii: $(BINDIR)/plrtoascii
rebuildIndex: $(BINDIR)/rebuildIndex
rebuildMailIndex: $(BINDIR)/rebuildMailIndex
shopconv: $(BINDIR)/shopconv
sign: $(BINDIR)/sign
@ -49,11 +54,6 @@ wld2html: $(BINDIR)/wld2html
webster: $(BINDIR)/webster
rebuildIndex: $(BINDIR)/rebuildIndex
$(BINDIR)/rebuildIndex: rebuildAsciiIndex.c
$(CC) $(CFLAGS) -o $(BINDIR)/rebuildIndex rebuildAsciiIndex.c
$(BINDIR)/asciipasswd: asciipasswd.c
$(CC) $(CFLAGS) -o $(BINDIR)/asciipasswd asciipasswd.c @CRYPTLIB@
@ -63,6 +63,12 @@ $(BINDIR)/autowiz: autowiz.c
$(BINDIR)/plrtoascii: plrtoascii.c
$(CC) $(CFLAGS) -o $(BINDIR)/plrtoascii plrtoascii.c
$(BINDIR)/rebuildIndex: rebuildAsciiIndex.c
$(CC) $(CFLAGS) -o $(BINDIR)/rebuildIndex rebuildAsciiIndex.c
$(BINDIR)/rebuildMailIndex: rebuildMailIndex.c
$(CC) $(CFLAGS) -o $(BINDIR)/rebuildMailIndex rebuildMailIndex.c
$(BINDIR)/shopconv: shopconv.c
$(CC) $(CFLAGS) -o $(BINDIR)/shopconv shopconv.c

299
src/util/rebuildMailIndex.c Executable file
View file

@ -0,0 +1,299 @@
/* ************************************************************************
* file: rebuildMailIndex.c Part of tbaMUD *
* Copyright (C) 1990, 2010 - see 'license.doc' for complete information. *
* All Rights Reserved *
************************************************************************* */
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <ctype.h>
#include <string.h>
#define READ_SIZE 256
#define FLAG(n) (1 << (n))
#ifndef FALSE
typedef enum _boolean_type {
FALSE=0, TRUE
} bool;
#endif
/* 128-bit flag defines (from utils.h) */
#define Q_FIELD(x) ((int) (x) / 32)
#define Q_BIT(x) (1 << ((x) % 32))
#define IS_SET_AR(var, bit) ((var)[Q_FIELD(bit)] & Q_BIT(bit))
#define SET_BIT_AR(var, bit) ((var)[Q_FIELD(bit)] |= Q_BIT(bit))
/* 32-bit flag defines (from utils.h) */
#define IS_SET(flag,bit) ((flag) & (bit))
#define SET_BIT(var,bit) ((var) |= (bit))
int atoi(const char *str);
long atol(const char *str);
/* Mail index flags - taken from mail.h */
#define MINDEX_DELETED FLAG(0) /* Mail has been marked for deletion */
#define MINDEX_URGENT FLAG(1) /* Mail is flagged as urgent by sender */
#define MINDEX_HAS_OBJ FLAG(2) /* Mail has an attached object */
#define MINDEX_HAS_GOLD FLAG(3) /* Mail contains some gold coins */
#define MINDEX_IS_COD FLAG(4) /* Mail requires some gold coins */
#define MINDEX_FROM_MOB FLAG(5) /* Mail has been sent by using scripts */
#define MINDEX_READ FLAG(6) /* Mail has been viewed but not received */
#define MINDEX_DRAFT FLAG(7) /* Mail is an unsent draft copy */
/* Mail Flags - taken from mail.h */
#define MAIL_DELETED 1 /* Marks mail for deletion with next purge */
#define MAIL_URGENT 2 /* This mail is flagged as urgent? */
#define MAIL_COD 3 /* Means coins amount is required payment */
#define MAIL_FROM_MOB 4 /* Specifies that 'sender' is a mob vnum */
#define MAIL_READ 5 /* Mail has been read by recipient */
#define MAIL_DRAFT 6 /* Mail is a draft (not yet sent) */
void walkdir(FILE* index_file, char *dir);
int get_line(FILE *fl, char *buf);
long asciiflag_conv(char *flag);
int sprintascii(char *out, long bits);
int main(int argc, char** argv)
{
FILE *index_file;
if ( argc == 1 ) {
printf("Usage: %s indexfile\n",argv[0]);
return 0;
}
if (!(index_file = fopen(argv[1], "w"))) {
perror("error opening index file");
return 1;
}
fprintf(index_file, "# tbaMUD mail index\n");
fprintf(index_file, "# Format: <ID> <flags> <sender ID/vnum> <recipient ID> <time> <subject>\n");
fprintf(index_file, "# For 'No Subject', use (null)\n");
walkdir(index_file, ".");
fprintf(index_file, "~\n");
fclose(index_file);
return 0;
}
/* check that filename is a valid mail file, else return NULL */
char *parsefilename(char *filename) {
static char copy[1024];
char *extension;
strcpy(copy, filename);
extension = strchr(copy, '.');
if (extension == NULL) {
return NULL;
}
if (strcmp(".ml", extension)) {
return NULL;
}
*extension = '\0';
return copy;
}
/* Search file for a specific tag line, return text after tag, or NULL if not found */
char *findLine(FILE *plr_file, char *tag) {
static char line[5000];
rewind(plr_file);
while (get_line(plr_file, line)) {
if(!strncmp(tag, line, strlen(tag))) {
return line+strlen(tag);
}
}
return NULL;
}
/* Search file for mail ID and convert to long */
long parse_mailid(FILE *plr_file) {
return atol(findLine(plr_file, "MlID:"));
}
/* Search file for sender ID and convert to long */
long parse_sender(FILE *plr_file) {
return atol(findLine(plr_file, "Send:"));
}
/* Search file for recipient ID and convert to long */
long parse_recipient(FILE *plr_file) {
return atoi(findLine(plr_file, "Reci:"));
}
/* Search file for date/time mail was sent and convert to long */
long parse_send_time(FILE *plr_file) {
return atoi(findLine(plr_file, "Sent:"));
}
/* Search file for mail subject and return as string */
char *parse_subject(FILE *plr_file) {
static char subj[1000];
char *txt = findLine(plr_file, "Subj:");
sprintf(subj, "%s", (txt == NULL) ? "(null)" : txt);
return (subj);
}
/* Search file for mail flags and return as bitvector */
int parse_mail_flags(FILE *plr_file) {
int fl[4], ret=0;
char *txt, f1[33], f2[33], f3[33], f4[33];
if ((txt = findLine(plr_file, "Flag:")) != NULL) {
/* Read the flags */
if (sscanf(txt, "%s %s %s %s", f1, f2, f3, f4) == 4) {
fl[0] = asciiflag_conv(f1);
fl[1] = asciiflag_conv(f2);
fl[2] = asciiflag_conv(f3);
fl[3] = asciiflag_conv(f4);
/* convert from mail flags to mail index flags */
if (IS_SET_AR(fl, MAIL_DELETED)) SET_BIT(ret, MINDEX_DELETED);
if (IS_SET_AR(fl, MAIL_URGENT)) SET_BIT(ret, MINDEX_URGENT);
if (IS_SET_AR(fl, MAIL_COD)) SET_BIT(ret, MINDEX_IS_COD);
if (IS_SET_AR(fl, MAIL_FROM_MOB)) SET_BIT(ret, MINDEX_FROM_MOB);
if (IS_SET_AR(fl, MAIL_READ)) SET_BIT(ret, MINDEX_READ);
if (IS_SET_AR(fl, MAIL_DRAFT)) SET_BIT(ret, MINDEX_DRAFT);
}
}
if ((txt = findLine(plr_file, "Gold:")) != NULL) {
if (atol(txt) > 0) SET_BIT(ret, MINDEX_HAS_GOLD);
}
if ((txt = findLine(plr_file, "Objs:")) != NULL) {
SET_BIT(ret, MINDEX_HAS_OBJ);
}
return (ret);
}
int parseadminlevel(FILE *plr_file, int level) {
char *fromFile = findLine(plr_file, "Admn:");
if (fromFile != NULL)
return atoi(fromFile);
if (level >= 30)
return level-30;
else
return 0;
}
long parselast(FILE *plr_file) {
return atol(findLine(plr_file, "Last:"));
}
void walkdir(FILE *index_file, char *dir) {
char filename_qfd[1000], *subject, bits[65];
struct dirent *dp;
long id, sender, recipient, sent_time;
int flags;
DIR *dfd;
FILE *mail_file;
if ((dfd = opendir(dir)) == NULL)
{
fprintf(stderr, "Can't open %s\n", dir);
return;
}
while ((dp = readdir(dfd)) != NULL)
{
struct stat stbuf ;
sprintf( filename_qfd , "%s/%s",dir,dp->d_name) ;
if( stat(filename_qfd,&stbuf ) == -1 ) {
fprintf(stdout, "Unable to stat file: %s\n",filename_qfd) ;
continue ;
}
if ( ( stbuf.st_mode & S_IFMT ) == S_IFDIR ) {
if (!strcmp(".", dp->d_name) || !strcmp("..", dp->d_name))
continue;
walkdir(index_file, filename_qfd);
} else {
char *name = parsefilename(dp->d_name);
if (name != NULL) {
/* Grab the data from the mail file and throw it in the index */
mail_file = fopen(filename_qfd, "r");
id = parse_mailid(mail_file);
sender = parse_sender(mail_file);
recipient = parse_recipient(mail_file);
sent_time = parse_send_time(mail_file);
flags = parse_mail_flags(mail_file);
subject = parse_subject(mail_file);
sprintascii(bits, flags);
fprintf(index_file, "%ld %s %ld %ld %ld %s\n", id, *bits ? bits : "0", sender, recipient, sent_time, subject);
fclose(mail_file);
}
}
}
}
int get_line(FILE *fl, char *buf)
{
char temp[READ_SIZE];
int lines = 0;
int sl;
do {
if (!fgets(temp, READ_SIZE, fl))
return (0);
lines++;
} while (*temp == '*' || *temp == '\n' || *temp == '\r');
/* Last line of file doesn't always have a \n, but it should. */
sl = strlen(temp);
while (sl > 0 && (temp[sl - 1] == '\n' || temp[sl - 1] == '\r'))
temp[--sl] = '\0';
strcpy(buf, temp); /* strcpy: OK, if buf >= READ_SIZE (256) */
return (lines);
}
long asciiflag_conv(char *flag)
{
long flags = 0;
int is_num = TRUE;
char *p;
for (p = flag; *p; p++) {
if (islower(*p))
flags |= 1 << (*p - 'a');
else if (isupper(*p))
flags |= 1 << (26 + (*p - 'A'));
/* Allow the first character to be a minus sign */
if (!isdigit(*p) && (*p != '-' || p != flag))
is_num = FALSE;
}
if (is_num)
flags = atol(flag);
return (flags);
}
int sprintascii(char *out, long bits)
{
int i, j = 0;
/* 32 bits, don't just add letters to try to get more unless your bitvector_t is also as large. */
char *flags = "abcdefghijklmnopqrstuvwxyzABCDEF";
for (i = 0; flags[i] != '\0'; i++)
if (bits & (1 << i))
out[j++] = flags[i];
if (j == 0) /* Didn't write anything. */
out[j++] = '0';
/* NUL terminate the output string. */
out[j++] = '\0';
return j;
}

View file

@ -1516,3 +1516,24 @@ bool set_admin_level(struct char_data *ch, int admlvl)
return TRUE;
}
/* add_commas takes a numeric value, and adds commas to it, returning a string */
char *add_commas(long num)
{
int i, j = 0, len;
int negative = (num < 0);
char num_string[MAX_INPUT_LENGTH];
static char commastring[MAX_INPUT_LENGTH];
sprintf(num_string, "%ld", num);
len = strlen(num_string);
for (i = 0; num_string[i]; i++) {
if ((len - i) % 3 == 0 && i && i - negative)
commastring[j++] = ',';
commastring[j++] = num_string[i];
}
commastring[j] = '\0';
return commastring;
}

View file

@ -69,6 +69,7 @@ char *strpaste(char *str1, char *str2, char *joiner);
void new_affect(struct affected_type *af);
int get_class_by_name(char *classname);
bool set_admin_level(struct char_data *ch, int admlvl);
char *add_commas(long num);
/* Public functions made available form weather.c */
void weather_and_time(int mode);
@ -647,6 +648,8 @@ do \
#define GET_DEFAULT_POS(ch) ((ch)->mob_specials.default_pos)
/** Return the memory of ch. */
#define MEMORY(ch) ((ch)->mob_specials.memory)
/** Return the structure used for creating mudmail from mobs */
#define MOB_MAIL(ch) ((ch)->mob_specials.ml_list)
/** Return the equivalent strength of ch if ch has level 18 strength. */
#define STRENGTH_APPLY_INDEX(ch) \
@ -749,6 +752,8 @@ do \
#define CAN_WEAR(obj, part) OBJWEAR_FLAGGED((obj), (part))
/** Return short description of obj. */
#define GET_OBJ_SHORT(obj) ((obj)->short_description)
/** Return the mudmail that the object is attached to */
#define IN_MAIL(obj) ((obj)->in_mail)
/* Compound utilities and other macros. */
/** Used to compute version. To see if the code running is newer than 3.0pl13,
@ -1067,4 +1072,31 @@ do \
/** What is the minimum level character to put on the wizlist? */
#define CONFIG_MIN_WIZLIST_LEV config_info.autowiz.min_wizlist_lev
/* Mudmail Configuraton */
/** Mail system enabled or not? */
#define CONFIG_CAN_MAIL config_info.mail.mail_allowed
/** Able to attach objects to mails? */
#define CONFIG_CAN_MAIL_OBJ config_info.mail.objects_allowed
/** Able to attach gold to mails? */
#define CONFIG_CAN_MAIL_GOLD config_info.mail.gold_allowed
/** Cost of stamps per mail for mortals */
#define CONFIG_STAMP_COST config_info.mail.stamp_cost
/** Extra Cost per object attachment for mortals */
#define CONFIG_OBJECT_COST config_info.mail.object_cost
/** Minimum level that can send mails */
#define CONFIG_MIN_MAIL_LEVEL config_info.mail.min_level
/** Lowest admin level that can always send free mails */
#define CONFIG_FREE_MAIL_LEVEL config_info.mail.min_free_level
/** Can mails be saved as drafts for later sending? */
#define CONFIG_DRAFTS_ALLOWED config_info.mail.allow_drafts
/** How long (in days) should draft mails be kept? */
#define CONFIG_DRAFT_TIMEOUT config_info.mail.draft_timeout
/** While mailing, are players safe from attack or stealing? */
#define CONFIG_SAFE_MAILING config_info.mail.safe_mailing
/** Minimum admin level at which a post office isn't required */
#define CONFIG_MIN_MAIL_ANYWHERE config_info.mail.min_mail_anywhere
/** Minimum admin level that can send to groups/all */
#define CONFIG_MIN_SEND_TO_ALL config_info.mail.min_send_to_all
#endif /* _UTILS_H_ */