/************************************************************************
Realms of Aurealis James Rhone aka Vall of RoA
db.c Database code. Loading, saving and the
manipulation of the record keeping part
of the MUD. Direct involvement between
this code and the RoAOLC files.
******** Heavily modified and expanded ********
*** BE AWARE OF ALL RIGHTS AND RESERVATIONS ***
******** Heavily modified and expanded ********
All rights reserved henceforth.
Please note that no guarantees are associated with any code from
Realms of Aurealis. All code which has been released to the general
public has been done so with an 'as is' pretense. RoA is based on both
Diku and CircleMUD and ALL licenses from both *MUST* be adhered to as well
as the RoA license. *** Read, Learn, Understand, Improve ***
*************************************************************************/
#include "conf.h"
#include "sysdep.h"
#define __ROA_DB_C__
#include "structures.h"
#include "utils.h"
#include "db.h"
#include "comm.h"
#include "handler.h"
#include "mudlimits.h"
#include "magic.h"
#include "mail.h"
#include "interpreter.h"
#include "acmd.h"
#include "affect.h"
#include "house.h"
#include "plshop.h"
#include "shaman.h"
#include "boards.h"
#include "htown.h"
#include "exshell.h"
#include "thief.h"
#include "lists.h"
#include "global.h"
/* local functions */
void setup_new_dir(FILE *fl, int room, int dir);
void setup_existing_dir(FILE *fl, int room, int dir);
void index_boot(int mode);
void load_room_skeletons(FILE *fl, int file_nr);
void load_mobiles(FILE *mob_f, int file_nr);
void load_objects(FILE *obj_f, int file_nr);
void load_roazone(FILE *fl);
void assign_mobiles(void);
void assign_objects(void);
void assign_rooms(void);
void build_player_index(void);
void char_to_store(chdata *ch, struct char_file_u *st);
void store_to_char(struct char_file_u *st, chdata *ch);
int is_empty(int zone_nr);
void reset_roazone(int zone);
void check_start_rooms(void);
void renum_world(void);
void renum_zone_exits(int zone);
void clear_char(chdata *ch);
char *fread_string(FILE *fl, char *error);
BOOL fskip_string(FILE *fl, char *error);
void fread_to_eol( FILE *fp );
int idle_this_zone(int i);
int unidle_this_zone(int i);
int unidle_reset_zone(int zone);
void reload_zone(int i);
void clear_who_list(void);
/* external functions */
void load_messages(void);
void assign_command_pointers(void);
void assign_races(void);
void assign_classes(void);
void assign_skills(void);
void sort_commands(void);
void load_banned(void);
void Read_Invalid_List(void);
void load_assembly_table(void); /* assembly.c...assembly of objects */
void set_original_objects(int zone);
void update_goss_html(void);
void free_this_mob(int i);
void free_banned_list(void);
int free_this_zone(int i);
void free_the_boards(void);
void free_room_affects(struct room_affect_type *head);
int purge_zone(int zone);
void init_globals(void);
int alloc_skills(chdata *ch);
int save_skills(chdata *ch);
int alloc_gskills(chdata *ch);
int save_gskills(chdata *ch);
/*************************************************************************
* routines for booting the system *
*********************************************************************** */
// JTRhone - This whole autowiz system makes absolutely NO sense. If the
// MUD waits for autowiz to finish, why have it send a signal
// to us when it's done.... we'll KNOW when it's done, or if it
// failed... why bother setting up a signal handler and wasting
// a valueable signal ... ah well, I'll let it be... roa
// UPDATE: 2/4/98 -jtrhone... moved autowiz stuff into mud, we're waiting anyways
// replace system() with function call
void reboot_wizlists(void)
{
FREENULL(wizlist);
FREENULL(immlist);
if (file_to_string_alloc(WIZLIST_FILE, &wizlist) < 0)
mudlog("SYSERR: Unable to WIZLIST_FILE.", BRF, LEV_IMM, TRUE);
if (file_to_string_alloc(IMMLIST_FILE, &immlist) < 0)
mudlog("SYSERR: Unable to IMMLIST_FILE.", BRF, LEV_IMM, TRUE);
}
// not really external anymore -jtrhone
void external_autowiz(void)
{
extern BOOL main_wizlist_update(void);
mudlog("Recreating wizlists.", CMP, LEV_IMM, FALSE);
main_wizlist_update();
mudlog("Rereading wizlists.", CMP, LEV_IMM, TRUE);
reboot_wizlists();
}
// if character was advanced to IMM status, call autowiz outside to update the list
// and signal us to reread them
void check_autowiz(chdata *ch)
{
if (use_autowiz && GET_LEVEL(ch) >= LEV_IMM)
external_autowiz();
}
ACMD(do_reboot)
{
if (IS_NPC(ch)) return;
one_argument(argument, arg);
if (!str_cmp(arg, "all") || *arg == '*')
{
file_to_string_alloc(NEWS_FILE, &news);
file_to_string_alloc(CREDITS_FILE, &credits);
file_to_string_alloc(CREDIT_SEQ_FILE, &credit_sequence);
file_to_string_alloc(MOTD_FILE, &motd);
file_to_string_alloc(IMOTD_FILE, &imotd);
file_to_string_alloc(INFO_FILE, &info);
file_to_string_alloc(POLICIES_FILE, &policies);
file_to_string_alloc(HANDBOOK_FILE, &handbook);
file_to_string_alloc(BACKGROUND_FILE, &background);
file_to_string_alloc(WELCOME_FILE, &welcome);
file_to_string_alloc(START_FILE, &start);
// now do the wiz/imm list call
external_autowiz();
} else if (!str_cmp(arg, "wizlist") || !str_cmp(arg, "immlist"))
external_autowiz();
else if (!str_cmp(arg, "news"))
file_to_string_alloc(NEWS_FILE, &news);
else if (!str_cmp(arg, "credits"))
file_to_string_alloc(CREDITS_FILE, &credits);
else if (!str_cmp(arg, "credit_sequence"))
file_to_string_alloc(CREDIT_SEQ_FILE, &credit_sequence);
else if (!str_cmp(arg, "motd"))
file_to_string_alloc(MOTD_FILE, &motd);
else if (!str_cmp(arg, "imotd"))
file_to_string_alloc(IMOTD_FILE, &imotd);
else if (!str_cmp(arg, "info"))
file_to_string_alloc(INFO_FILE, &info);
else if (!str_cmp(arg, "policy"))
file_to_string_alloc(POLICIES_FILE, &policies);
else if (!str_cmp(arg, "handbook"))
file_to_string_alloc(HANDBOOK_FILE, &handbook);
else if (!str_cmp(arg, "background"))
file_to_string_alloc(BACKGROUND_FILE, &background);
else if (!str_cmp(arg, "welcome"))
file_to_string_alloc(WELCOME_FILE, &welcome);
else if (!str_cmp(arg, "start"))
file_to_string_alloc(START_FILE, &start);
else
{
send_to_char("Unknown reboot option.\n\r", ch);
return;
}
send_to_char("Okay.\n\r", ch);
}
/* body of the booting system */
void boot_db(void)
{
int i;
log("Boot db -- BEGIN.");
log("Init Global Structures.");
init_globals();
log("Reading greetings, news, credits, bground, info & motds.");
file_to_string_alloc(NEWS_FILE, &news);
file_to_string_alloc(RACES_FILE, &races);
file_to_string_alloc(TITLE_FILE0, &title0);
file_to_string_alloc(TITLE_FILE1, &title1);
file_to_string_alloc(TITLE_FILE2, &title2);
file_to_string_alloc(TITLE_FILE3, &title3);
file_to_string_alloc(TITLE_FILE4, &title4);
file_to_string_alloc(TITLE_FILE5, &title5);
file_to_string_alloc(CREDITS_FILE, &credits);
file_to_string_alloc(CREDIT_SEQ_FILE, &credit_sequence);
file_to_string_alloc(MOTD_FILE, &motd);
file_to_string_alloc(IMOTD_FILE, &imotd);
file_to_string_alloc(INFO_FILE, &info);
file_to_string_alloc(WIZLIST_FILE, &wizlist);
file_to_string_alloc(IMMLIST_FILE, &immlist);
file_to_string_alloc(POLICIES_FILE, &policies);
file_to_string_alloc(HANDBOOK_FILE, &handbook);
file_to_string_alloc(BACKGROUND_FILE, &background);
file_to_string_alloc(WELCOME_FILE, &welcome);
file_to_string_alloc(START_FILE, &start);
log("Loading zone table.");
index_boot(DB_BOOT_ZON);
log("Loading rooms.");
index_boot(DB_BOOT_WLD);
log("Converting Virtual Exits to Real Exits.");
renum_world();
log("Checking start rooms.");
check_start_rooms();
log("Loading mobs and generating index.");
index_boot(DB_BOOT_MOB);
log("Loading objs and generating index.");
index_boot(DB_BOOT_OBJ);
log("Generating player index.");
build_player_index();
log("Loading fight messages.");
load_messages();
log("Assigning hard-wired function pointers:");
log(" Mobiles.");
assign_mobiles();
log(" Objects.");
assign_objects();
log(" Rooms.");
assign_rooms();
log("Assigning runtime structures:");
log(" Races.");
assign_races();
log(" Classes.");
assign_classes();
log(" Commands.");
assign_command_pointers();
log(" Skills.");
assign_skills();
log("Sorting command list.");
sort_commands();
log("Booting mail system.");
if (!scan_file())
{
log(" Mail boot failed -- Mail system disabled");
no_mail = TRUE;
}
log("Initializing hometowns.");
init_htowns();
log("Initializing boards.");
init_boards();
log("Reading banned site and invalid-name list.");
load_banned();
Read_Invalid_List();
// from assem.c
log("Loading Assembly Table.");
load_assembly_table();
log("Setting system zones.");
SET_BIT(ZONE_FLAGS(LIMBO_ZONE), Z_SYSTEM);
SET_BIT(ZONE_FLAGS(1), Z_SYSTEM);
SET_BIT(ZONE_FLAGS(HOUSE_ZONE), Z_SYSTEM);
SET_BIT(ZONE_FLAGS(IMMORTAL_ZONE), Z_IMMORT);
SET_BIT(ZONE_FLAGS(DEF_HOMETOWN), Z_SYSTEM);
log("Setting zones freed."); // do not free zone 0, LIMBO_ZONE 2/5/98 -jtrhone
for (i = LIMBO_ZONE+1; i < NUM_ZONES; i++)
if (REAL_ZONE(i))
SET_ZONE_FREED(i);
// unidle and reset all system zones... 3/18/98 -jtrhone
log("Resetting system zones.");
for (i = 0; i < NUM_ZONES; i++)
if (REAL_ZONE(i) && ZONE_FLAGGED(i, Z_SYSTEM))
unidle_reset_zone(i);
// do not idle zone 0, LIMBO_ZONE 2/5/98 -jtrhone
// do not idle ANY system zones now 3/27/98 -jtrhone
log("Setting normal zones idle.");
for (i = LIMBO_ZONE+1; i < NUM_ZONES; i++)
if ((i != IMMORTAL_ZONE) && (i != DEF_HOMETOWN) && (i != HOUSE_ZONE) &&
!ZONE_FLAGGED(i, Z_SYSTEM))
idle_this_zone(i);
log("Calculating zone levels.");
do_calc_zones(0, 0, 0, 0);
reset_q.head = reset_q.tail = NULL;
set_original_objects(-1); /* (roa) in shop.c */
log("Object states set.");
boot_time = time(0);
if (!mini_mud)
{
log("Booting houses.");
boot_houses();
}
log("Boot db -- DONE.");
}
// build an index of the names and ips of players in the pfile
void build_player_index(void)
{
int nr = -1, i;
long size, recs;
struct char_file_u dummy;
if (!(player_fl = fopen(PLAYER_FILE, "r+b"))) {
perror("Error opening playerfile");
log("error opening playerfile db.c");
exit(1);
}
fseek(player_fl, 0L, SEEK_END);
size = ftell(player_fl);
rewind(player_fl);
if (size % sizeof(struct char_file_u))
fprintf(stderr, "WARNING: PLAYERFILE IS PROBABLY CORRUPT!\n");
recs = size / sizeof(struct char_file_u);
if (recs)
{
sprintf(buf, " %ld players in database.", recs);
log(buf);
CREATE(player_table, struct player_index_element, recs);
}
else
{
player_table = NULL;
top_of_p_file = top_of_p_table = -1;
return;
}
/* copy indexual data into player_index, for quick lookups of
player names and ips and idnums perhaps -roa */
for (; !feof(player_fl); )
{
fread(&dummy, sizeof(struct char_file_u), 1, player_fl);
if (!feof(player_fl)) /* new record */
{
nr++;
/* allocate space for player name */
CREATE(player_table[nr].name, char, strlen(dummy.name)+1);
/* copy char by char over, lowering each letter */
for (i = 0; (*(player_table[nr].name + i) = LOWER(*(dummy.name + i))); i++)
;
/* dupe idnums over */
player_table[nr].id = dummy.saved.idnum;
top_idnum = MAX(top_idnum, dummy.saved.idnum);
/* throw last ip in there -roa*/
strcpy(player_table[nr].last_ip, dummy.host);
}
}
top_of_p_file = top_of_p_table = nr;
}
/* function to count how many hash-mark delimited records exist in a file */
int count_hash_records(FILE *fl)
{
char buf[120];
int count = 0;
while (fgets(buf, 120, fl))
if (*buf == '#')
count++;
return (count - 1);
}
/* main booting procedure on bootup */
void index_boot(int mode)
{
char *index_filename, *prefix;
FILE *index, *db_file;
int rec_count = 0, i, file_nr;
switch (mode)
{
case DB_BOOT_WLD : prefix = WLD_PREFIX; break;
case DB_BOOT_MOB : prefix = MOB_PREFIX; break;
case DB_BOOT_OBJ : prefix = OBJ_PREFIX; break;
case DB_BOOT_ZON : prefix = ZON_PREFIX; break;
default:
log("SYSERR: Unknown subcommand to index_boot!");
exit(1);
break;
}
if (mini_mud)
index_filename = MINDEX_FILE;
else
index_filename = INDEX_FILE;
sprintf(buf2, "%s/%s", prefix, index_filename);
if (!(index = fopen(buf2, "r"))) {
sprintf(buf1, "Error opening index file '%s'", buf2);
log(buf1);
exit(1);
}
/* first, count the number of records in the file so we can malloc */
fscanf(index, "%s\n", buf1);
while (*buf1 != '$')
{
sprintf(buf2, "%s/%s", prefix, buf1);
if (mode == DB_BOOT_ZON) /* use the new zon format .zonroa -roa */
strcat(buf2, "roa");
if (!(db_file = fopen(buf2, "r")))
{
perror(buf2);
log(buf2);
exit(1);
}
else
{
if (mode == DB_BOOT_ZON)
rec_count++; /* just so it passed tests, dont use it for zones */
else
rec_count += count_hash_records(db_file);
}
fclose(db_file);
fscanf(index, "%s\n", buf1);
}
if (!rec_count) {
log("SYSERR: boot error - 0 records counted");
exit(1);
}
/* NOTE: in the allocations that follow, the way OLC is set up REQUIRES
that enough space is available for NEW prototypes to be tacked on to
the end of the proto lists. Using this array implementation is much
quicker for scanning, but this is the one area where it hurts,because
we are allocating XXX_PADDING on the end of each of these arrays to
account for any new protos during this boot. Though a list or tree
would be easier to add to in a situation like this, it would be FAR
slower to search through it as many times as we do. Thus the array
way is tolerated. Later on in mudlife, a proto list 'dupe' can be
added if the mud runs out of PADDING during a particular runtime, so
there will be no limit on how much builders can add per uptime, for
now, however, that's not the case. RoA uses 200 as an average uptime
limit on NEW protos created per obj/mob/wld. It seems very ample.
-jtrhone roa
*/
switch (mode) {
case DB_BOOT_WLD :
CREATE(world, rmdata, rec_count + WLD_PADDING); /* hash count + padding */
break;
case DB_BOOT_MOB :
CREATE(mob_proto, chdata, rec_count + MOB_PADDING);
CREATE(mob_index, indexdata, rec_count + MOB_PADDING);
sprintf(buf, "track: %d mobs allocated", rec_count + MOB_PADDING);
log(buf);
break;
case DB_BOOT_OBJ :
CREATE(obj_proto, obdata, rec_count + OBJ_PADDING);
CREATE(obj_index, indexdata, rec_count + OBJ_PADDING);
sprintf(buf, "track: %d objs allocated", rec_count + OBJ_PADDING);
log(buf);
break;
case DB_BOOT_ZON : /* ZONES are pre allocated, simply set stuff up */
for (i = 0; i < NUM_ZONES; i++)
{
zone_table[i].number = -1;
zone_table[i].comlist = NULL;
zone_table[i].bitvector = 0;
}
break;
} /* end of switch */
/* ok we allocated, now stuff it full of stuff -roa */
rewind(index);
fscanf(index, "%s\n", buf1);
while (*buf1 != '$')
{
/* check to see if new zon file is there */
sprintf(buf2, "%s/%s", prefix, buf1);
if (mode == DB_BOOT_ZON)
strcat(buf2, "roa");
if (!(db_file = fopen(buf2, "r")))
{
perror(buf2);
log(buf2);
exit(1);
}
file_nr = atoi(buf1);
switch (mode) {
case DB_BOOT_WLD : load_room_skeletons(db_file, file_nr); break;
case DB_BOOT_OBJ : load_objects(db_file, file_nr); break;
case DB_BOOT_MOB : load_mobiles(db_file, file_nr); break;
case DB_BOOT_ZON : load_roazone(db_file); break;
default:
log("SYSERR: Unknown sub_cmd to index_boot!");
exit(1);
break;
} /* end of switch */
fclose(db_file);
fscanf(index, "%s\n", buf1);
} /* end of while != $ */
fclose(index);
}
// clear out a room, reset to defaults if exists
void clear_room(int room_nr, BOOL exists)
{
int tmp;
if (room_nr <= NOWHERE)
{
log("SYSERR: invalid room to clear_room");
return;
}
world[room_nr].funct = NULL;
world[room_nr].max_contains = -1; /* no limit to start */
world[room_nr].drop_to = -1;
world[room_nr].float_to = -1;
world[room_nr].drift_to = -1;
world[room_nr].owner = -1;
world[room_nr].alter_type = 0;
world[room_nr].numdice = 0;
world[room_nr].sizedice = 0;
world[room_nr].room_flags2 = 0;
/* clear transport stuff */
world[room_nr].trans_present = -1;
world[room_nr].location = -1;
world[room_nr].to_port = 0; /* which port we pointing at? */
world[room_nr].wait_time = 0; /* we in a wait state? */
world[room_nr].dock_wait = 0;
world[room_nr].travel_wait = 0;
world[room_nr].ticket_num = -1;
for (tmp = 0; tmp < 4; tmp++)
world[room_nr].portals[tmp] = -1;
world[room_nr].exdesc = NULL;
// wax ptr to room affect list
world[room_nr].room_affects = NULL;
// zap the room snoopers -roa
wax_room_snoopers(&world[room_nr]);
// blank out rproc things 6/5/98 -jtrhone
world[room_nr].rproc = NULL;
world[room_nr].rproc_cur = NULL;
world[room_nr].target_char = NULL;
world[room_nr].target_obj = NULL;
if (!exists)
{
world[room_nr].contents = NULL;
world[room_nr].people = NULL;
world[room_nr].num_present = 0;
world[room_nr].light = 0;
for (tmp = 0; tmp < NUM_OF_DIRS; tmp++)
DIR(room_nr, tmp) = NULL;
}
}
void wax_room_snoopers(rmdata *r)
{
dsdata *temp, *s;
int rnum = -1;
while ((s = RSNOOPER(r)))
{
REMOVE_FROM_LIST(s, RSNOOPER(r), next_rsnooper);
}
rnum = real_room(r->number);
for (s = descriptor_list; s; s=s->next)
if (s->room_snooping == rnum)
s->room_snooping = 0;
}
void remove_room_snooper(rmdata *r, dsdata *d)
{
dsdata *temp, *s;
for (s = RSNOOPER(r); s; s = s->next_rsnooper)
if (s == d) break;
if (!s) return;
REMOVE_FROM_LIST(d, RSNOOPER(r), next_rsnooper);
d->room_snooping = 0;
}
void add_room_snooper(rmdata *r, dsdata *d)
{
d->room_snooping = real_room(r->number);
if (!RSNOOPER(r))
{
RSNOOPER(r) = d;
d->next_rsnooper = NULL;
}
else
{
d->next_rsnooper = RSNOOPER(r);
RSNOOPER(r) = d;
}
}
// dupe over an extra description list to a whole new one
// return ptr to new one
exdescdata *dupe_exdesc_over(exdescdata *src)
{
exdescdata *e_new, *tmp, *trg = NULL;
for (tmp = src; tmp; tmp = tmp->next)
{
CREATE(e_new, exdescdata, 1);
e_new->keyword = str_dup(tmp->keyword);
e_new->description = str_dup(tmp->description);
e_new->next = trg;
trg = e_new;
}
return trg;
}
/*
scans exdesc list and checks for valid ones...
if an invalid is found, its ejected from list and subsequently
freed :) -roa
returns ptr to corrected list
*/
exdescdata *correct_extra_descrips(exdescdata *ths)
{
exdescdata *temp = NULL; /* a temp ptr */
exdescdata *etemp = NULL; /* a temp ptr */
exdescdata *e = NULL; /* a temp ptr */
for (e = ths; e; e = etemp)
{
etemp = e->next;
/* if this is invalid, remove it and free it */
if ((!e->keyword || !*e->keyword || *e->keyword == '(' || *e->keyword == ' ') ||
(!e->description || !*e->description || *e->description == '(' || *e->keyword == ' '))
{
REMOVE_FROM_LIST(e, ths, next);
FREENULL(e->keyword);
FREENULL(e->description);
free(e);
mudlog("SYSERR: invalid ex_desc detected and removed", BRF, LEV_IMM, TRUE);
}
}
return ths;
}
// Change this procedure to not load entire room, just skeleton on bootup
// 8/27/97
void load_room_skeletons(FILE *fl, int file_nr)
{
static int room_nr = 0, virtual_nr, flag;
char *temp, chk[50];
int ctr = 0;
int tmp1, tmp2, tmp3;
do {
fscanf(fl, " #%d\n", &virtual_nr);
/* if for some reason the room has a NULL name */
/* substitute a default name in it */
if (!(temp = fread_string(fl, buf2)))
temp = str_dup("BLANK");
if ((flag = (*temp != '$')))
{
FREENULL(temp);
/* wax all the stuff in the room */
clear_room(room_nr, FALSE);
world[room_nr].zone = file_nr;
world[room_nr].number = virtual_nr;
fskip_string(fl, buf2);
world[room_nr].description = NULL;
fscanf(fl, " %*d ");
fscanf(fl, " %d ", &world[room_nr].room_flags);
fscanf(fl, " %d ", &tmp1);
world[room_nr].terrain_type = tmp1;
for (; ; )
{
fscanf(fl, " %s \n", chk);
if (*chk == 'D') /* direction field */
setup_new_dir(fl, room_nr, atoi(chk + 1));
else
if (*chk == 'r') /* room_flags2 field */
world[room_nr].room_flags2 = atoi(chk + 1);
else
if (*chk == 'E') /* extra description field */
{
fskip_string(fl, buf2);
fskip_string(fl, buf2);
}
else
if (*chk == 'R') /* ROOM RANDOMS RoA JRHONE */
for (ctr = 0; ctr < 5; ctr++)
{
fskip_string(fl, buf2);
world[room_nr].randoms[ctr] = NULL;
}
else
if (*chk == 'p') /* portals field */
{
fscanf(fl, "\n%d %d %d %d\n", &world[room_nr].portals[0],
&world[room_nr].portals[1],
&world[room_nr].portals[2],
&world[room_nr].portals[3]);
}
else
if (*chk == 'M') /* max contains field */
world[room_nr].max_contains = atoi(chk + 1);
else
if (*chk == 'F') /* float to field */
world[room_nr].float_to = atoi(chk + 1);
else
if (*chk == 'Q') /* drop_to field */
world[room_nr].drop_to = atoi(chk + 1);
else
if (*chk == 'd') /* drift_to field */
world[room_nr].drift_to = atoi(chk + 1);
else
if (*chk == 't') /* transport stuff */
{
fscanf(fl, "\n%d %d %d\n",&tmp1, &tmp2, &tmp3);
world[room_nr].dock_wait = tmp1;
world[room_nr].travel_wait = tmp2;
world[room_nr].ticket_num = tmp3;
}
else
if (*chk == 'z') /* dice field */
{
fscanf(fl, "\n%d %d %d\n", &tmp1, &tmp2, &tmp3);
world[room_nr].numdice = tmp1;
world[room_nr].sizedice = tmp2;
world[room_nr].alter_type = tmp3;
}
else
if (*chk == 'o') /* owner field for room owner */
{
fscanf(fl, " %d %d %d\n", &tmp1, &tmp2, &tmp3);
world[room_nr].owner = tmp1;
// tmp2 is a SPARE
// tmp3 is a SPARE
}
else
if (*chk == 'm') /* music file/timer */
{
fscanf(fl, " %d\n", &tmp1);
fskip_string(fl, buf2);
}
else
if (*chk == 'P') /* rproc 6/5/98 -jtrhone */
{
fskip_string(fl, buf2);
}
else
if (*chk == 'S') /* end of current room */
break;
}
world[room_nr].exdesc = NULL;
room_nr++;
} /* end if flag */
} while (flag);
/* cleanup the area containing the terminal $ */
FREENULL(temp);
top_of_sorted_world = top_of_world = room_nr;
}
// used when reading a fresh new direction from disk
// primarily on bootup, this one allocates everything
// UPDATE, this allocates the dir skeletons on bootup now... -roa 8/27/97
// added support of 4 more dir strs 3/24/98 -jtrhone
void setup_new_dir(FILE *fl, int room, int dir)
{
int tmp, tmp1, tmp2;
char letter;
if (room <= NOWHERE)
{
log("SYSERR: invalid room to setup_new_dir");
return;
}
CREATE(DIR(room, dir), rmdirdata, 1);
// wipe descs just in case...
DIR(room, dir)->exit_descr = NULL;
DIR(room, dir)->keyword = NULL;
DIR(room, dir)->enter = NULL;
DIR(room, dir)->oenter = NULL;
DIR(room, dir)->drop = NULL;
DIR(room, dir)->odrop = NULL;
DIR(room, dir)->traps = NULL;
fskip_string(fl, buf2);
fskip_string(fl, buf2);
letter=fread_letter(fl);
ungetc(letter, fl);
// if it has the new strings...
if (letter == '#')
{
fscanf(fl, "#\n");
fskip_string(fl, buf2);
fskip_string(fl, buf2);
fskip_string(fl, buf2);
fskip_string(fl, buf2);
letter=fread_letter(fl);
ungetc(letter, fl);
}
if (letter == 'V')
{
fscanf(fl, "V%d %d %d\n",&tmp, &tmp1, &tmp2);
DIR(room, dir)->exinfo = tmp;
DIR(room, dir)->key = tmp1;
DIR(room, dir)->to_room = tmp2;
}
else // do it the old way bleh
{
fscanf(fl, " %d ", &DIR(room, dir)->exit_type);
DIR(room, dir)->exinfo = 0; // clear out exit info bitvector
switch (DIR(room, dir)->exit_type) {
case 0: break;
case 1:
FLAG_EXIT(DIR(room, dir), EX_ISDOOR);
break;
case 2:
FLAG_EXIT(DIR(room, dir), EX_ISDOOR | EX_PICKPROOF);
break;
case 3:
FLAG_EXIT(DIR(room, dir), EX_ISDOOR | EX_PICKPROOF | EX_CLOSED | EX_LOCKED);
break;
default:
sprintf(buf2, "SYSERR: unknown exit type, rnum %d, dir %d.",room,dir);
log(buf2);
break;
}
fscanf(fl, " %d ", &tmp);
DIR(room, dir)->key = tmp;
fscanf(fl, " %d ", &tmp);
DIR(room, dir)->to_room = tmp;
}
}
// direction already exists, its allocated except strings
// reset it basically with strings from disk
void setup_existing_dir(FILE *fl, int room, int dir)
{
int tmp, tmp1, tmp2;
char letter;
int zone;
if (INVALID_ROOM(room))
{
mudlog("SYSERR: Invalid room to setup_existing_dir().", BRF, LEV_IMM, TRUE);
return;
}
// add check just in case dir doesn't exist... 6/6/98 -jtrhone
if (!DIR(room, dir))
{
mudlog("SYSERR: DIR() to setup_existing_dir() DNE.", BRF, LEV_IMM, TRUE);
return;
}
// only assign em if we arent auto generating them
zone = world[room].zone;
if (!ZONE_FLAGGED(zone, Z_EXITGENALL | Z_EXITGENLAT))
{
DIR(room, dir)->exit_descr = fread_string(fl, buf2);
DIR(room, dir)->keyword = fread_string(fl, buf2);
}
else
{
fskip_string(fl, buf2);
fskip_string(fl, buf2);
}
letter=fread_letter(fl);
ungetc(letter, fl);
// if it has the new strings...
if (letter == '#')
{
fscanf(fl, "#\n");
DIR(room, dir)->enter = fread_string(fl, buf2);
DIR(room, dir)->oenter = fread_string(fl, buf2);
DIR(room, dir)->drop = fread_string(fl, buf2);
DIR(room, dir)->odrop = fread_string(fl, buf2);
letter=fread_letter(fl);
ungetc(letter, fl);
}
if (letter == 'V')
fscanf(fl, "V%d %d %d\n",&tmp, &tmp1, &tmp2);
else // do it the old way bleh
fscanf(fl, " %d %d %d\n",&tmp, &tmp1, &tmp2);
}
/* go thru and check vital rooms in the mud, if not here, dont boot up */
void check_start_rooms(void)
{
if ((r_mortal_start_room = real_room(mortal_start_room)) < 0) {
log("SYSERR: Mortal start room does not exist. Change in config.c.");
exit(1);
}
if ((r_immort_start_room = real_room(immort_start_room)) < 0) {
if (!mini_mud)
log("SYSERR: Warning: Immort start room does not exist. Change in config.c.");
r_immort_start_room = r_mortal_start_room;
}
if ((r_frozen_start_room = real_room(frozen_start_room)) < 0) {
if (!mini_mud)
log("SYSERR: Warning: Frozen start room does not exist. Change in config.c.");
r_frozen_start_room = r_mortal_start_room;
}
if ((r_newbie_start_room = real_room(newbie_start_room)) < 0) {
if (!mini_mud)
log("SYSERR: Warning: Newbie start room does not exist. Change in config.c.");
r_newbie_start_room = r_mortal_start_room;
}
}
// go thru each exit and change the VNUM read from file to an rnum
void renum_world(void)
{
register int room, door;
for (room = 0; room < top_of_world; room++)
for (door = 0; door < NUM_OF_DIRS; door++)
if (DIR(room, door) && DIR(room, door)->to_room != NOWHERE)
DIR(room, door)->to_room = real_room(DIR(room, door)->to_room);
}
// basically renum_world on the rooms of a particular zone
void renum_zone_exits(int zone)
{
register int room, door;
for (room = 0; room < top_of_world; room++)
if (world[room].zone == zone)
for (door = 0; door < NUM_OF_DIRS; door++)
if (DIR(room, door) && DIR(room, door)->to_room != NOWHERE)
DIR(room, door)->to_room = real_room(DIR(room, door)->to_room);
}
// skip spaces in a file, read a letter
char fread_letter(FILE *fp)
{
char c;
do { c = getc(fp); } while (isspace(c));
return c;
}
// load up the zone information into zone_table from disk
// SKIP the strings, just load skeletons...
void load_roazone(FILE *fl)
{
int zon, i, j;
char clist[MAX_COMLIST_LENGTH], tmp[150];
char letter;
zndata *z;
int tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8;
fscanf(fl, "#%d\n", &zon);
zone_table[zon].number = zon;
zone_table[zon].name = fread_string(fl, buf2);
fscanf(fl, "%d %d %d\n", &tmp1, &tmp2, &tmp3);
zone_table[zon].top = tmp1;
zone_table[zon].lifespan = tmp2;
zone_table[zon].reset_mode = tmp3;
/* new, read the bitvector */
fscanf(fl, "%d\n",&zone_table[zon].bitvector);
REMOVE_BIT(ZONE_FLAGS(zon), Z_LOCKED);
REMOVE_BIT(ZONE_FLAGS(zon), Z_ON_Q);
/* CHECK FOR WEATHER DATA HERE -RoA */
/* set ignore trigger */
for (i=0; i < 4; i++)
zone_table[zon].seasons[i].avg_day_temp = -999;
// sound checks/adds 2/18/98 -jtrhone
letter=fread_letter(fl);
ungetc(letter, fl);
// check for sound stuff... denoted by -
if (letter == '@')
{
z = &zone_table[zon];
fscanf(fl, "@ %d %d\n", &z->music_timer, &z->wav_timer);
z->sound_file = fread_string(fl, buf2);
}
/* now get next char, if it's a W, we read in the weather stuff */
/* else we put the char back and continue */
letter=fread_letter(fl);
ungetc(letter, fl);
/* now we gotta read the zone weather -roa */
if (letter == 'W')
{
z = &zone_table[zon];
for (i = 0; i < 4; i++)
fscanf(fl, "W%d %d %d %d %d %d %d\n", &j,
&z->seasons[i].avg_day_temp,
&z->seasons[i].avg_day_temp_var,
&z->seasons[i].avg_night_temp,
&z->seasons[i].avg_night_temp_var,
&z->seasons[i].precip_percentage,
&z->seasons[i].atmosphere_type);
fscanf(fl, "W %d %d %d %d %d %d %d %d\n", &tmp1, &tmp2, &tmp3, &tmp4,
&tmp5, &tmp6, &tmp7, &tmp8);
z->current_status = tmp1;
z->previous_status = tmp2;
z->current_gtemp = tmp3;
z->previous_gtemp = tmp4;
z->current_atemp = tmp5;
z->previous_atemp = tmp6;
z->accum_type = tmp7;
z->accum = tmp8;
}
/* reset weather depending on time (just hit target temp ) -roa*/
if (zone_table[zon].seasons[0].avg_day_temp > -999)
{
zone_table[zon].current_gtemp = zone_table[zon].previous_gtemp =
(global_weather.sunlight == SUN_RISE ||
global_weather.sunlight == SUN_LIGHT) ?
zone_table[zon].seasons[global_weather.season].avg_day_temp:
zone_table[zon].seasons[global_weather.season].avg_night_temp;
}
zone_table[zon].has_rained = FALSE;
zone_table[zon].hour_to_rain = number(0, 23);
// check for sunrise/sunset messages, denoted by *
letter=fread_letter(fl);
ungetc(letter, fl);
if (letter == '*')
{
fscanf(fl, "*\n");
for (i = 0; i < 4; i++)
{
fskip_string(fl, buf2);
fskip_string(fl, buf2);
fskip_string(fl, buf2);
fskip_string(fl, buf2);
zone_table[zon].seasons[i].sunrise = NULL;
zone_table[zon].seasons[i].daytime = NULL;
zone_table[zon].seasons[i].sunset = NULL;
zone_table[zon].seasons[i].nighttime = NULL;
}
}
/* read the command list */
*tmp = ' ';
*clist = '\0';
while (*tmp != '~') /* while not at end of file babe */
{
fgets(tmp, 120, fl);
str_cat(clist, tmp, MAX_COMLIST_LENGTH, "load_roazone");
}
zone_table[zon].comlist = NULL;
}
// given a name of a mob, return the mob and vnum of all who match it
int vnum_mobile(char *searchname, chdata *ch)
{
int nr, found = 0;
char buf[20000];
char name1[MAX_INPUT_LENGTH], name2[MAX_INPUT_LENGTH];
// allow for honing in on mobs 2/5/98 -jtrhone
half_chop(searchname, name1, name2);
for (nr = 0, *buf = '\0'; nr < top_of_mobt; nr++)
if (isname(name1, mob_proto[nr].player.name) &&
(!*name2 || isname(name2, mob_proto[nr].player.name)))
{
sprintf(buf+strlen(buf), "%3d. [%5d] %-60.60s\n\r", ++found, mob_index[nr].vnum,
mob_proto[nr].player.short_descr);
}
if (*buf)
page_string(ch->desc, buf, 1);
return(found);
}
// do the same for objects
int vnum_object(char *searchname, chdata *ch)
{
int nr, found = 0;
char buf[20000];
char name1[MAX_INPUT_LENGTH], name2[MAX_INPUT_LENGTH];
// allow for honing in on objects 2/5/98 -jtrhone
half_chop(searchname, name1, name2);
for (nr = 0, *buf = '\0'; nr < top_of_objt; nr++)
if (isname(name1, obj_proto[nr].name) && (!*name2 || isname(name2, obj_proto[nr].name)))
{
sprintf(buf+strlen(buf), "%3d. [%5d] %-60.60s\n\r",
++found, obj_index[nr].vnum, obj_proto[nr].shdesc);
}
if (*buf)
page_string(ch->desc, buf, 1);
return(found);
}
/* create a new mobile from a prototype */
void init_mob(chdata *mob, int i)
{
// dupe ALL stuff from the prototype right here!
*mob = mob_proto[i];
// clear out our new mobs time stuff
mob->player.time.birth = time(0);
mob->player.time.played = 0;
mob->player.time.logon = time(0);
// roll the dice for new mobs hitp (mana and move to come soon)
GET_MAX_HIT(mob) = dice(mob->npc_specials.mob_num_hit, mob->npc_specials.mob_size_hit) +
mob->npc_specials.mob_add_hit;
GET_HIT(mob) = GET_MAX_HIT(mob);
GET_MAX_MANA(mob) = dice(mob->npc_specials.mob_num_mana, mob->npc_specials.mob_size_mana) +
mob->npc_specials.mob_add_mana;
GET_MANA(mob) = GET_MAX_MANA(mob);
GET_MAX_MOVE(mob) = dice(mob->npc_specials.mob_num_move, mob->npc_specials.mob_size_move) +
mob->npc_specials.mob_add_move;
GET_MOVE(mob) = GET_MAX_MOVE(mob);
// pick sex if its random
if (GET_SEX(mob) == SEX_RANDOM)
GET_SEX(mob) = number(SEX_MALE, SEX_FEMALE);
// set open if shopkeep
if (SPC_FLAGGED(mob, SPC_SHOPKEEP))
SET_BIT(CHAR_FLAGS(mob), CH_SHOP_OPEN);
else
REMOVE_BIT(CHAR_FLAGS(mob), CH_SHOP_OPEN);
/* if mob is a MOBPROC, set up the command list ptrs */
if (SPC_FLAGGED(mob, SPC_MOBPROC))
MPROC_CUR(mob) = MPROC_BEG(mob);
}
BOOL plshopkeep_loaded(int rnum)
{
chdata *mob;
for (mob = character_list; mob; mob=mob->next)
if (GET_MOB_RNUM(mob) == rnum)
return TRUE;
return FALSE;
}
// given a virtual or real number, return corresponding allocated
// structure, do the allocate here, along with initializing
chdata *read_mobile(int nr, int type)
{
int i;
chdata *mob;
i = (type == REAL ? nr : real_mobile(nr));
if (i >= top_of_mobt || i < 0)
{
sprintf(buf, "SYSERR: read_mob, invalid number (%d).", i);
mudlog(buf, BRF, LEV_IMM, TRUE);
return NULL;
}
// before we create, make sure we're not invoking multiple PLSHOPKEEPS -jtrhone
if ( MOB_FLAGGED(&mob_proto[i], MOB_PLSHOPKEEP) && plshopkeep_loaded(i))
{
sprintf(buf, "SYSERR: Multiple plshopkeep instance attempt (#%d).", GET_MOB_VNUM(&mob_proto[i]));
mudlog(buf, BRF, LEV_IMM, TRUE);
return NULL;
}
// allocate, clear/reset, and init the new mob
CREATE(mob, chdata, 1);
clear_char(mob);
init_mob(mob, i);
/* insert mob into character list */
mob->next = character_list;
character_list = mob;
mob_index[i].number++; // bump up our count of these mobs
// if the mob is a plshopkeep mob, give it it's inventory... 1/18/98 -jtrhone
if (MOB_FLAGGED(mob, MOB_PLSHOPKEEP))
load_plshopkeep_objs(mob);
// voila, send back our new mob
return mob;
}
// assign DEFAULT mob prototype values to protos about to be read in
void reset_mob_proto(int i)
{
int j;
mob_proto[i].nr = i;
mob_proto[i].player.title = NULL;
mob_proto[i].desc = NULL;
GET_NAME(mob_proto + i) = NULL;
mob_proto[i].player.short_descr = NULL;
mob_proto[i].player.long_descr = NULL;
mob_proto[i].player.description = NULL;
mob_proto[i].npc_specials.walkIn = NULL;
mob_proto[i].npc_specials.walkOut = NULL;
mob_proto[i].npc_specials.shop_data = NULL;
mob_proto[i].npc_specials.sound_file = NULL;
TRIGS(&mob_proto[i]) = NULL;
TRIG_WAITING(&mob_proto[i]) = FALSE;
TRIG_IGNORE(&mob_proto[i]) = FALSE;
for (j = 0; j < 6; j++)
mob_proto[i].npc_specials.strs[j] = NULL;
mob_proto[i].player.cls = 0;
mob_proto[i].player.weight = 200;
mob_proto[i].player.height = 198;
mob_proto[i].points.max_mana = 10;
mob_proto[i].points.max_move = 50;
mob_proto[i].npc_specials.mounter_id = -1;
mob_proto[i].specials.speaking = LANG_COMMON;
mob_proto[i].npc_specials.max_train_level = LEV_IMM - 1;
mob_proto[i].npc_specials.min_train_level = 1;
SUMMONER(&mob_proto[i]) = -1;
mob_proto[i].npc_specials.mob_num_hit = 1;
mob_proto[i].npc_specials.mob_size_hit = 1;
mob_proto[i].npc_specials.mob_add_hit = 1;
mob_proto[i].npc_specials.mob_num_mana = 1;
mob_proto[i].npc_specials.mob_size_mana = 1;
mob_proto[i].npc_specials.mob_add_mana = 1;
mob_proto[i].npc_specials.mob_num_move = 1;
mob_proto[i].npc_specials.mob_size_move = 1;
mob_proto[i].npc_specials.mob_add_move = 1;
for (j = 0; j < 5; j++)
mob_proto[i].npc_specials.saving_throws[j] = 0;
for (j = 0; j < MAX_WEAR; j++)
mob_proto[i].equipment[j] = NULL;
}
// load mobs from lib/world/mob/* in RoA mob file format, always changing :)
void load_mobiles(FILE *mob_f, int file_nr)
{
static int i = 0;
int nr, j;
long tmpl1, tmpl2;
int tmpi1, tmpi2, tmpi3, tmpi4, tmpi5, tmpi6;
char chk[10];
char letter;
BOOL skip = 0;
if (!fscanf(mob_f, "%s\n", chk))
{
perror("load_mobiles");
log("load_mobiles");
exit(1);
}
for (; ; )
{
if (*chk == '#')
{
sscanf(chk, "#%d\n", &nr);
if (nr >= 99999)
break;
mob_index[i].vnum = nr;
mob_index[i].number = 0;
mob_index[i].func = NULL;
clear_char(mob_proto + i);
reset_mob_proto(i);
if (!(mob_proto[i].player.name = fread_string(mob_f, buf2)))
{
sprintf(buf2, "mobile #%d", nr);
fprintf(stderr, "mobile with no name/descrip (%s)skipped\n", buf2);
log(buf2);
skip = TRUE;
}
mob_proto[i].player.short_descr = fread_string(mob_f, buf2);
mob_proto[i].player.long_descr = fread_string(mob_f, buf2);
mob_proto[i].player.description = fread_string(mob_f, buf2);
fscanf(mob_f, "%ld ", &MOB_FLAGS(mob_proto + i));
SET_BIT(MOB_FLAGS(mob_proto + i), MOB_ISNPC);
fscanf(mob_f, " %ld %d %c \n", &AFF_FLAGS(mob_proto + i),
&GET_ALIGNMENT(mob_proto + i), &letter);
if (letter == 'S')
{
fscanf(mob_f, " %d %d %d", &tmpi1, &tmpi2, &tmpi3);
GET_LEVEL(mob_proto + i) = MIN(75, tmpi1);
GET_HITROLL(mob_proto + i) = 20 - tmpi2;
GET_AC(mob_proto + i) = 10 * tmpi3;
fscanf(mob_f, " %dd%d+%d ", &tmpi1, &tmpi2, &tmpi3);
mob_proto[i].npc_specials.mob_num_hit = tmpi1;
mob_proto[i].npc_specials.mob_size_hit = tmpi2;
mob_proto[i].npc_specials.mob_add_hit = tmpi3;
fscanf(mob_f, " %dd%d+%d \n", &tmpi1, &tmpi2, &tmpi3);
mob_proto[i].npc_specials.damnodice = tmpi1;
mob_proto[i].npc_specials.damsizedice = tmpi2;
mob_proto[i].points.damroll = tmpi3;
fscanf(mob_f, " %ld %ld \n", &tmpl1, &tmpl2);
GET_GOLD(mob_proto + i) = tmpl1;
GET_EXP(mob_proto + i) = tmpl2;
fscanf(mob_f, " %d %d %d \n", &tmpi1, &tmpi2, &tmpi3);
mob_proto[i].specials.position = tmpi1;
mob_proto[i].npc_specials.default_pos = tmpi2;
mob_proto[i].player.sex = tmpi3;
}
else
if (letter == 'Z') // new file format RoA, easier quicker more
{
fscanf(mob_f, "%d %d %d %d %d\n",&tmpi1,&tmpi2,&tmpi3,&tmpi4,&tmpi5);
GET_LEVEL(mob_proto + i) = MIN(75, tmpi1);
GET_EXP(mob_proto + i) = tmpi2;
GET_HITROLL(mob_proto + i) = tmpi3;
GET_AC(mob_proto + i) = tmpi4;
GET_GOLD(mob_proto + i) = tmpi5;
fscanf(mob_f, "%d %d %d\n", &tmpi1, &tmpi2, &tmpi3);
mob_proto[i].npc_specials.damnodice = tmpi1;
mob_proto[i].npc_specials.damsizedice = tmpi2;
GET_DAMROLL(mob_proto + i) = tmpi3;
fscanf(mob_f, "%d %d %d\n", &tmpi1, &tmpi2, &tmpi3);
mob_proto[i].npc_specials.mob_num_hit = tmpi1;
mob_proto[i].npc_specials.mob_size_hit = tmpi2;
mob_proto[i].npc_specials.mob_add_hit = tmpi3;
fscanf(mob_f, "%d %d %d\n", &tmpi1, &tmpi2, &tmpi3);
mob_proto[i].npc_specials.mob_num_mana = tmpi1;
mob_proto[i].npc_specials.mob_size_mana = tmpi2;
mob_proto[i].npc_specials.mob_add_mana = tmpi3;
fscanf(mob_f, "%d %d %d\n", &tmpi1, &tmpi2, &tmpi3);
mob_proto[i].npc_specials.mob_num_move = tmpi1;
mob_proto[i].npc_specials.mob_size_move = tmpi2;
mob_proto[i].npc_specials.mob_add_move = tmpi3;
fscanf(mob_f, "%d %d %d\n", &tmpi1, &tmpi2, &tmpi3);
mob_proto[i].specials.position = tmpi1;
mob_proto[i].npc_specials.default_pos = tmpi2;
mob_proto[i].player.sex = tmpi3;
}
letter=fread_letter(mob_f);
if (letter == 's')
{
fscanf(mob_f, "%d\n", &tmpi1);
// range check needed due to conversion... 6/21/98 -jtrhone
// this will place value back between LANG_COMMON and LANG_DRAGON
if ((tmpi1 >= 240) && (tmpi1 <= 247))
tmpi1 -= 240;
mob_proto[i].specials.speaking = tmpi1;
letter=fread_letter(mob_f);
}
if (letter == 't') /* Mobile Strings RoA jtrhone */
{
fread_to_eol(mob_f);
// read 6 strings on mob (6th must ALWAYS be NULL!!)
for (j = 0; j < 6; j++)
mob_proto[i].npc_specials.strs[j] = fread_string(mob_f, buf2);
letter=fread_letter(mob_f);
}
if (letter == 'W')
{
fread_to_eol(mob_f);
mob_proto[i].npc_specials.walkIn = fread_string(mob_f, buf2);
mob_proto[i].npc_specials.walkOut = fread_string(mob_f, buf2);
letter=fread_letter(mob_f);
}
if (letter == 'P')
{
fscanf(mob_f, "%ld\n", &mob_proto[i].npc_specials.spc_bits);
letter=fread_letter(mob_f);
}
if (letter == 'p')
{
fscanf(mob_f, "%ld\n", &AFF2_FLAGS(mob_proto + i));
letter=fread_letter(mob_f);
}
if (letter == 'T') /* trainin levels for gmasters */
{
fscanf(mob_f, "%d %d\n", &tmpi1, &tmpi2);
mob_proto[i].npc_specials.min_train_level = tmpi1;
mob_proto[i].npc_specials.max_train_level = tmpi2;
letter=fread_letter(mob_f);
}
/* the numbers are written regardless on mobsave, but we wont
allocate a structure to the proto unless its a shopkeep ..
if its not flagged shopkeep, just scan past the numbers -roa*/
if (letter == 'H')
{
if (SPC_FLAGGED((mob_proto+i), SPC_SHOPKEEP))
{
CREATE((mob_proto+i)->npc_specials.shop_data, struct shop_data_type, 1);
fscanf(mob_f, "%d %d %d %d\n",
&(mob_proto+i)->npc_specials.shop_data->vhome,
&(mob_proto+i)->npc_specials.shop_data->vshop,
&(mob_proto+i)->npc_specials.shop_data->open,
&(mob_proto+i)->npc_specials.shop_data->close);
}
else
fscanf(mob_f, "%d %d %d %d\n",&tmpi1,&tmpi2,&tmpi3,&tmpi4);
letter=fread_letter(mob_f);
}
// read in saving throws
if (letter == 'V')
{
fscanf(mob_f, "%d %d %d %d %d\n",&tmpi1,&tmpi2,&tmpi3,&tmpi4, &tmpi5);
mob_proto[i].npc_specials.saving_throws[0] = tmpi1;
mob_proto[i].npc_specials.saving_throws[1] = tmpi2;
mob_proto[i].npc_specials.saving_throws[2] = tmpi3;
mob_proto[i].npc_specials.saving_throws[3] = tmpi4;
mob_proto[i].npc_specials.saving_throws[4] = tmpi5;
letter=fread_letter(mob_f);
}
// read in mob quest info
if (letter == 'Q')
{
fscanf(mob_f, "%d %d\n",&tmpi1,&tmpi2);
mob_proto[i].npc_specials.qnum = tmpi1;
mob_proto[i].npc_specials.hunt_quest = tmpi2;
letter=fread_letter(mob_f);
}
if (letter == 'm')
{
fscanf(mob_f, "%d\n", &mob_proto[i].npc_specials.music_timer);
mob_proto[i].npc_specials.sound_file = fread_string(mob_f, buf2);
letter=fread_letter(mob_f);
}
// put a bunch of spare ints here so i dont have to keep doin this...
if (letter == 'u')
{
fscanf(mob_f, "%d %d %d %d %d %d %d %d\n", &mob_proto[i].npc_specials.mob2_bits,
&tmpi1, &tmpi1, &tmpi1, &tmpi1, &tmpi1, &tmpi1, &tmpi1);
letter=fread_letter(mob_f);
}
if (letter == 'X')
{
int version;
fscanf(mob_f, "%d\n", &version);
fscanf(mob_f, "%d %d %d %d %d %d\n", &tmpi1, &tmpi2, &tmpi3, &tmpi4, &tmpi5, &tmpi6);
mob_proto[i].real_abils.str = tmpi1;
mob_proto[i].real_abils.str_add = tmpi2;
mob_proto[i].real_abils.intel = tmpi3;
mob_proto[i].real_abils.wis = tmpi4;
mob_proto[i].real_abils.dex = tmpi5;
mob_proto[i].real_abils.con = tmpi6;
mob_proto[i].aff_abils = mob_proto[i].real_abils;
fscanf(mob_f, "%d %d %ld", &tmpi1, &tmpi2, &tmpl1);
mob_proto[i].npc_specials.mob_size = tmpi2;
mob_proto[i].npc_specials.mob_class = tmpl1;
}
else
ungetc(letter, mob_f);
// read in the next line, prepare to go to top of loop
if (!fscanf(mob_f, "%s\n", chk))
{
sprintf(buf2, "SYSERR: Format error in mob file near mob #%d", nr);
log(buf2);
exit(1);
}
if (skip)
{
free_this_mob(i);
skip = FALSE;
}
else
{
/* fill it with dummy struct */
mob_proto[i].pc_specials = &dummy_mob;
/* if its a shopkeep and didnt load data from disk -roa*/
if (SPC_FLAGGED((mob_proto+i), SPC_SHOPKEEP) &&
!mob_proto[i].npc_specials.shop_data)
{
CREATE((mob_proto+i)->npc_specials.shop_data, struct shop_data_type, 1);
mob_proto[i].npc_specials.shop_data->vhome = -1;
mob_proto[i].npc_specials.shop_data->vshop = -1;
mob_proto[i].npc_specials.shop_data->open = -1;
mob_proto[i].npc_specials.shop_data->close = -1;
}
i++;
}
}
else
if (*chk == '$') /* EOF */
break;
else
{
sprintf(buf2, "SYSERR: Format error in mob file near mob #%d", nr);
log(buf2);
exit(1);
}
}
top_of_mobt = top_of_sorted_mobt = i;
}
// load/return an objects based on load probabilities
// zlock_reset and total_game_limits, uses RNUM as argument
obdata *reset_read_object(int nr)
{
obdata *obj;
int i;
if (nr < 0 || nr >= top_of_objt)
{
sprintf(buf, "SYSERR: invalid nr to reset_read_obj (%d) db.c.",nr);
log(buf);
return NULL;
}
// go thru 10 alternates if original doesnt load
for (i = 0; i < 10 && nr > 0; i++)
{
obj = &obj_proto[nr];
if (number(0,9999) < obj->percent_load || zlock_reset)
if (obj_index[GET_OBJ_RNUM(obj)].number < obj->total_game_limit ||
obj->total_game_limit == -1)
return read_object(nr, REAL);
if (!obj->alternate_load)
return NULL;
nr = real_object(obj->alternate_load);
}
return NULL;
}
// if obj spell data is somewhat off, reset to -1 on this object
void check_obj_spells(obdata *obj)
{
int i;
if (obj->type_flag == ITEM_POTION || obj->type_flag == ITEM_SCROLL)
for (i = 1; i <= 3; i++)
if (obj->value[i] <= 0 || obj->value[i] > MAX_SPELLS ||
!spell_info[obj->value[i]].spell_pointer)
obj->value[i] = -1;
if (obj->type_flag == ITEM_STAFF || obj->type_flag == ITEM_WAND)
if (obj->value[3] <= 0 || obj->value[3] > MAX_SPELLS ||
!spell_info[obj->value[3]].spell_pointer)
obj->value[3] = -1;
}
// get rnum/vnum with REAL or VIRTUAL flag sent along
// check bounds, then allocate memory
// copy from proto, update index, check spells, return obj
obdata *read_object(int nr, int type)
{
obdata *obj;
int i;
i = (type == REAL ? nr : real_object(nr));
if (i < 0 || i >= top_of_objt)
{
sprintf(buf, "SYSERR: invalid nr to read_obj (%d) db.c.",nr);
log(buf);
return NULL;
}
CREATE(obj, obdata, 1);
*obj = obj_proto[i];
obj->next = object_list;
object_list = obj;
obj_index[i].number++;
check_obj_spells(obj);
return (obj);
}
// blank out any unread object affects, starting with j
void check_obj_affs(int i, int j)
{
for (; j < MAX_OBJ_AFFECT; j++)
{
obj_proto[i].affected[j].location = APPLY_NONE;
obj_proto[i].affected[j].modifier = 0;
}
}
// fill a proto with default data
void reset_obj_proto(int i)
{
obj_proto[i].in_room = NOWHERE;
obj_proto[i].next_content = 0;
obj_proto[i].carried_by = 0;
obj_proto[i].in_obj = 0;
obj_proto[i].contains = 0;
obj_proto[i].item_number = i;
obj_proto[i].total_game_limit = -1;
obj_proto[i].percent_load = 10000;
obj_proto[i].alternate_load = 0;
obj_proto[i].min_level = 1;
obj_proto[i].obj_hits = 10000; /* obj_hits */
obj_proto[i].max_obj_hits = 10000; /* max_obj_hits */
obj_proto[i].extras2 = 0; /* extras2 */
obj_proto[i].made_of = OBJ_UNDEFINED; /* material unknown */
obj_proto[i].success_rate = 100; /* 100% default */
obj_proto[i].touched = FALSE;
obj_proto[i].lit = FALSE;
obj_proto[i].original = FALSE;
obj_proto[i].eqspell = -1;
obj_proto[i].eqaffbit = 0;
obj_proto[i].eqaff2bit = 0;
check_obj_affs(i, 0); // blank out all affects
}
/* read all objects from obj file; generate index and prototypes */
void load_objects(FILE *obj_f, int file_nr)
{
static int i = 0;
int tmp, tmp2, tmp3, tmp4, j, nr;
char chk[50];
exdescdata *new_descr = NULL;
BOOL breakout;
if (!fscanf(obj_f, "%s\n", chk)) {
perror("load_objects");
log("load_objects in db.c");
exit(1);
}
for (; ; )
{
if (*chk == '#')
{
sscanf(chk, "#%d\n", &nr);
if (nr >= 99999)
break;
obj_index[i].vnum = nr;
obj_index[i].number = 0;
obj_index[i].func = NULL;
clear_object(obj_proto + i);
reset_obj_proto(i);
if (!(obj_proto[i].name = fread_string(obj_f, buf2)))
obj_proto[i].name = str_dup("BLANK");
obj_proto[i].shdesc = fread_string(obj_f, buf2);
obj_proto[i].description = fread_string(obj_f, buf2);
if (!(obj_proto[i].actdesc = fread_string(obj_f, buf2)))
obj_proto[i].actdesc = STR_DUP(obj_proto[i].description);
fscanf(obj_f, " %d %d %d", &tmp, &tmp2, &tmp3);
obj_proto[i].type_flag = tmp;
obj_proto[i].extras = tmp2;
obj_proto[i].wear_flags = tmp3;
fscanf(obj_f, " %d %d %d %d", &tmp, &tmp2, &tmp3, &tmp4);
obj_proto[i].value[0] = tmp;
obj_proto[i].value[1] = tmp2;
obj_proto[i].value[2] = tmp3;
obj_proto[i].value[3] = tmp4;
fscanf(obj_f, " %d %d %d", &tmp, &tmp2, &tmp3);
obj_proto[i].weight = tmp;
obj_proto[i].cost = tmp2;
breakout = j = 0;
while (fscanf(obj_f, " %s \n", chk))
{
switch (*chk) {
case 'E':
CREATE(new_descr, exdescdata, 1);
new_descr->keyword = fread_string(obj_f, buf2);
new_descr->description = fread_string(obj_f, buf2);
new_descr->next = obj_proto[i].exdesc;
obj_proto[i].exdesc = new_descr;
break;
case 'A':
fscanf(obj_f, " %d %d ", &tmp, &tmp2);
if (j < MAX_OBJ_AFFECT)
{
obj_proto[i].affected[j].location = tmp;
obj_proto[i].affected[j].modifier = tmp2;
j++;
}
break;
case 'X':
fscanf(obj_f, " %d %d %d %d\n",
&obj_proto[i].total_game_limit,
&obj_proto[i].percent_load,
&obj_proto[i].alternate_load,
&tmp);
obj_proto[i].min_level = tmp;
break;
case 'Q':
fscanf(obj_f, " %d %ld\n", &obj_proto[i].eqspell,
&obj_proto[i].eqaffbit);
break;
case 'q':
fscanf(obj_f, " %ld\n", &obj_proto[i].eqaff2bit);
break;
case 'H':
fscanf(obj_f, " %d\n", &obj_proto[i].obj_hits);
break;
case 'M':
fscanf(obj_f, " %d\n", &obj_proto[i].max_obj_hits);
break;
case 'x':
fscanf(obj_f, " %d\n", &obj_proto[i].extras2);
break;
case 'm':
fscanf(obj_f, " %d\n", &obj_proto[i].made_of);
break;
case 'p':
fscanf(obj_f, " %d\n", &obj_proto[i].success_rate);
break;
case 'T':
fscanf(obj_f, " %d %d %d %d\n",
&obj_proto[i].throw_plushit,
&obj_proto[i].throw_numdam,
&obj_proto[i].throw_sizedam,
&obj_proto[i].throw_plusdam);
break;
case 'W':
obj_proto[i].wear_mesg = fread_string(obj_f, buf2);
obj_proto[i].rem_mesg = fread_string(obj_f, buf2);
obj_proto[i].weap_sing = fread_string(obj_f, buf2);
obj_proto[i].weap_plur = fread_string(obj_f, buf2);
break;
// added wvector 5/28/98 -jtrhone
case 'V':
fscanf(obj_f, " %d\n", &obj_proto[i].wvector);
break;
default:
breakout = TRUE;
break;
} // end of chk switch
if (breakout)
break;
} // end of while *chk
check_obj_affs(i, j);
i++;
}
else
if (*chk == '$') /* EOF */
break;
else
{
sprintf(buf2, "Format error in obj file at or near obj #%d", nr);
log(buf2);
exit(1);
}
}
/* objs loaded at boottime are sorted */
/* however, our obj proto list will be expanded during runtime by olc */
top_of_sorted_objt = top_of_objt = i; /* which is length of array */
}
// zone defines, to make it somewhat clearer to read and adjust as
// needed -roa
/* increment age if not idle, closed, locked, and reset_mode */
#define ZONE_CAN_AGE(i) \
(REAL_ZONE(i) && zone_table[i].age < zone_table[i].lifespan && \
zone_table[i].reset_mode && !ZONE_IDLE(i) && !ZONE_FREED(i) && \
!ZONE_CLOSED(i) && !ZONE_LOCKED(i) && !ZONE_FLAGGED(i, Z_IMMORT))
/* check for players in a zone, if not, we can inc IDLE time -RoA */
#define ZONE_CAN_IDLE_AGE(i) \
(REAL_ZONE(i) && !ZONE_FLAGGED(i, Z_SYSTEM) && !ZONE_IDLE(i) && \
!ZONE_FREED(i) && !ZONE_LOCKED(i) && !ZONE_FLAGGED(i, Z_IMMORT) && \
is_empty(i))
#define READY_TO_IDLE(i) (zone_table[i].idle_time >= zone_table[i].lifespan)
#define READY_TO_ENQUEUE(i) \
(!ZONE_FLAGGED(i, Z_ON_Q) && zone_table[i].reset_mode && \
(zone_table[i].age >= zone_table[i].lifespan) && !ZONE_IDLE(i) && \
!ZONE_FREED(i) && !ZONE_CLOSED(i) &&!ZONE_LOCKED(i))
// add a zone to the reset queue -roa (split up for readability)
void enqueue_zone(int zone)
{
struct reset_q_element *update_u;
CREATE(update_u, struct reset_q_element, 1);
update_u->zone = zone;
update_u->next = NULL;
if (!reset_q.head)
reset_q.head = reset_q.tail = update_u;
else
{
reset_q.tail->next = update_u;
reset_q.tail = update_u;
}
SET_BIT(ZONE_FLAGS(zone), Z_ON_Q);
}
// pluck a zone off the reset queue... reset_q is global ptr to it
void dequeue_zone(struct reset_q_element *uq)
{
struct reset_q_element *temp;
REMOVE_BIT(ZONE_FLAGS(uq->zone), Z_ON_Q);
// now to the actual dequeue
if (uq == reset_q.head)
reset_q.head = reset_q.head->next;
else
{
for (temp = reset_q.head; temp->next != uq; temp = temp->next)
;
if (!uq->next)
reset_q.tail = temp;
temp->next = uq->next;
}
FREENULL(uq);
}
/* update zone ages, queue for reset if necessary, and dequeue when possible */
void zone_update(void)
{
static int timer = 0;
int i;
struct reset_q_element *update_u;
/* jelson 10/22/92 4 comes from 4 passes/sec (enqueue every minute)*/
if (((++timer * PULSE_ZONE) / 4) >= 60)
{
timer = 0;
for (i = 0; i < NUM_ZONES; i++)
{
if (!REAL_ZONE(i)) continue;
if (ZONE_CAN_AGE(i))
zone_table[i].age++;
if (ZONE_CAN_IDLE_AGE(i))
{
zone_table[i].idle_time++;
if (READY_TO_IDLE(i))
{
idle_this_zone(i);
free_this_zone(i);
sprintf(buf, "Zone purged and freed: (#%d) %s", i, zone_table[i].name);
mudlog(buf, CMP, LEV_GOD, FALSE);
continue;
}
}
else
if (!is_empty(i)) /* its not empty, reset idle time */
unidle_this_zone(i);
if (READY_TO_ENQUEUE(i))
enqueue_zone(i);
} // end of zone scan
} // end of if it's been a minute
/* dequeue zones (if possible) and reset */
for (update_u = reset_q.head; update_u; update_u = update_u->next)
if ((zone_table[update_u->zone].reset_mode == 2 ||
is_empty(update_u->zone)) && !ZONE_CLOSED(update_u->zone) &&
!ZONE_IDLE(update_u->zone) && !ZONE_FREED(update_u->zone) &&
!ZONE_LOCKED(update_u->zone))
{
sprintf(buf, "Zone reset: (#%d) %s",update_u->zone,
zone_table[update_u->zone].name);
mudlog(buf, CMP, LEV_GOD, FALSE);
purge_zone(update_u->zone);
reset_roazone(update_u->zone);
dequeue_zone(update_u);
break; // we BREAK we only wanna do one per 10/secs, avoid lag
}
}
// go thru every room, yank transports from this zone
// and reset them
void reset_zone_transports(int zone)
{
int room, rm, trg;
int top = zone * 100 + 99;
extern void send_to_room_not_busy(char *txt, int room);
for (rm = 0; rm < top_of_world; rm++)
if (world[rm].trans_present / 100 == zone)
{
// send messg to the room the trannie is in
send_to_room_not_busy("%4Mystic energies engulf the area.%0",rm);
// send one to the ppl inside?
world[rm].trans_present = -1;
}
for (room = zone * 100; room <= top; room++)
if ((rm = real_room(room)) > 0)
if (ROOM_FLAGGED2(rm, TRANSPORT))
{
world[rm].wait_time = 0;
world[rm].location = world[rm].portals[0]; /* starting port! */
world[rm].to_port = 1; /* the second port -> 1st DESTINATION */
if ((trg = real_room(world[rm].location)) > 0)
world[trg].trans_present = room;
else
{
sprintf(buf, "SYSERR: invalid ports on transport reset, room #%d", room);
mudlog(buf, BRF, LEV_IMM, FALSE);
}
}
}
/* go one past eol in a string, used in comlist scanning */
/* RoA jtrhone
char *scan_past_eol(char **pt)
{
char *p = *pt;
while (*p && *p != '\n')
p++;
if (*p)
p++;
return p;
}
*/
/* skip an entire zone comlist block of reset commands */
/* used if target mob/obj is not loaded for whatever reason */
/* ASSUME we are pointing at { */
/* RoA jtrhone
char *skip_block(char **p)
{
int depth;
char *pt = *p;
pt++;
for (depth = 1; depth > 0; pt++)
{
if (*pt == '{')
depth++;
else
if (*pt == '}')
depth--;
}
pt++;
return pt;
}
*/
/* recursive in nature, loads objects into objects */
/* used in RoA zone comlist scanning */
/* RoA jtrhone */
char *load_obj_objects(obdata *ob, char *pt)
{
int ovnum = 0, robj = 0;
obdata *obj = 0;
pt = scan_past_eol(pt); /* bump past open brac */
while (*pt == 'P')
{
obj = NULL;
sscanf(pt, "P %d\n",&ovnum);
pt = scan_past_eol(pt);
if ((robj = real_object(ovnum))>=0)
if ((obj = reset_read_object(robj)))
obj_to_obj(obj, ob);
if (*pt == '{')
{
if (obj)
{
pt = load_obj_objects(obj, pt);
if (*pt == '}')
pt = scan_past_eol(pt);
} /* end if obj */
else
pt = skip_block(pt);
} /* end if open brack */
} /* end of while */
return pt;
}
void load_zone_rmobjs(int zone)
{
int i;
obdata *obj = NULL;
extern BOOL load_room_objects(int vnum);
for (i=0; i < top_of_world; i++)
if (world[i].zone == zone && ROOM_FLAGGED2(i, SAVE_ROOM))
{
while ((obj = world[i].contents))
extract_obj(obj);
load_room_objects(world[i].number);
}
}
/* execute the comlist of a given zone */
/* RoA jtrhone */
void reset_roazone(int zone)
{
chdata *mob = 0;
obdata *obj = 0;
char *cptr;
int mvnum, rvnum, ovnum, max;
int rmob, robj, rroom;
int dir, status, pos;
rmdirdata *d;
rmdata *r;
trap *t;
struct room_affect_type raf;
int tmp1, tmp2, tmp3, tmp4;
extern int generate_zone(int zone);
// if the zone is flagged Z_AUTOGEN, we have to regenerate it
if (ZONE_FLAGGED(zone, Z_EXITGENALL | Z_EXITGENLAT | Z_DESCGEN))
generate_zone(zone);
cptr = zone_table[zone].comlist;
if (!cptr || !*cptr)
{
sprintf(buf, "Zone #%d not reset - no comlist.",zone);
mudlog(buf, BRF, LEV_IMM, FALSE);
return;
}
while (*cptr && *cptr != '$')
{
switch(*cptr)
{
case '*': /* ignore command */
cptr = scan_past_eol(cptr);
break;
case 'M': /* read a mobile */
sscanf(cptr, "M %d %d %d\n", &mvnum, &rvnum, &max);
cptr = scan_past_eol(cptr);
mob = NULL;
if ((rmob = real_mobile(mvnum)) >= 0)
if ((mob_index[rmob].number < max || zlock_reset) &&
(rroom = real_room(rvnum)) >= 0)
{
mob = read_mobile(rmob, REAL);
mob->npc_specials.max_existing = max;
char_to_room(mob, rroom);
}
break;
case 'G': /* give object to last mob loaded */
if (!mob)
{
/* note: obj to mob not loaded */
cptr = scan_past_eol(cptr);
if (*cptr == '{')
cptr = skip_block(cptr);
break;
}
obj = NULL;
sscanf(cptr, "G %d\n",&ovnum);
cptr = scan_past_eol(cptr);
if ((robj = real_object(ovnum)) >= 0)
if ((obj = reset_read_object(robj)))
obj_to_char(obj, mob);
if (*cptr == '{')
{
if (obj)
{
cptr = load_obj_objects(obj, cptr);
cptr = scan_past_eol(cptr);
}
else
cptr = skip_block(cptr);
}
break;
case 'E': /* equip object on pos to last mob loaded */
if (!mob)
{
/* note: obj equip to mob not loaded */
cptr = scan_past_eol(cptr);
if (*cptr == '{')
cptr = skip_block(cptr);
break;
}
obj = NULL;
sscanf(cptr, "E %d %d\n", &ovnum, &pos);
cptr = scan_past_eol(cptr);
if ((robj = real_object(ovnum)) >= 0)
{
if (pos < 0 || pos >= MAX_WEAR)
{
sprintf(buf,"SYSERR: comlist error: invalid eq position (%s)", GET_NAME(mob));
mudlog(buf, BRF, LEV_IMM, FALSE);
}
else
if ((obj = reset_read_object(robj)))
equip_char(mob, obj, pos, FALSE);
}
if (*cptr == '{')
{
if (obj)
{
cptr = load_obj_objects(obj, cptr);
cptr = scan_past_eol(cptr);
}
else
cptr = skip_block(cptr);
}
break;
case 'O': /* read an object */
sscanf(cptr, "O %d %d\n", &ovnum, &rvnum);
cptr = scan_past_eol(cptr);
if ((rroom = real_room(rvnum)) >= 0)
if ((robj = real_object(ovnum)) >= 0)
if ((obj = reset_read_object(robj)))
obj_to_room(obj, rroom);
if (*cptr == '{')
{
if (obj)
{
cptr = load_obj_objects(obj, cptr);
cptr = scan_past_eol(cptr);
}
else
cptr = skip_block(cptr);
}
break;
case 'D': /* set state of door */
sscanf(cptr, "D %d %d %d\n", &rvnum, &dir, &status);
cptr = scan_past_eol(cptr);
if ((rroom = real_room(rvnum)) >= 0 && (d = DIR(rroom, dir)))
{
d->exinfo = status;
if ((EXIT_LOCKED(d) || EXIT_CLOSED(d)) && !EXIT_ISDOOR(d))
{
FLAG_EXIT(d, EX_ISDOOR);
sprintf(buf, "SYSUPD: Room: %d, exit: %d corrected.",rvnum, dir);
mudlog(buf, BUG, LEV_IMM, FALSE);
}
if (d->key > 0 && EXIT_ISDOOR(d) && EXIT_CLOSED(d))
FLAG_EXIT(d, EX_LOCKED);
}
else
if (!ZONE_FLAGGED(rvnum/100, Z_EXITGENALL | Z_EXITGENLAT))
{
sprintf(buf, "SYSERR: Room: #%d, exit: %d invalid.",rvnum, dir);
mudlog(buf, BRF, LEV_IMM, FALSE);
}
break;
case 'T': // we got traps now ... 4/26/98 -jtrhone
sscanf(cptr, "T %d %d %d %d %d %d\n", &rvnum, &dir, &tmp1, &tmp2, &tmp3, &tmp4);
cptr = scan_past_eol(cptr);
// make sure its valid before we allocate...
rroom = real_room(rvnum);
if (INVALID_ROOM(rroom))
{
sprintf(buf, "SYSERR: Room: #%d, trap invalid.",rvnum);
mudlog(buf, BRF, LEV_IMM, FALSE);
}
r = &world[rroom];
if (dir == -1) // trap on ROOM itself...
{
if (TRAPS(r))
{
sprintf(buf, "SYSERR: Room: #%d, multiple traps.",rvnum);
mudlog(buf, BRF, LEV_IMM, FALSE);
}
else
{
CREATE(t, trap, 1);
t->type = tmp1;
t->level = tmp2;
t->bitv = tmp3;
t->timer = tmp4;
trap_to_room(t, r);
}
}
else
{
if (dir >= NUM_OF_DIRS)
{
sprintf(buf, "SYSERR: Room: #%d, exit: %d invalid dir.",rvnum, dir);
mudlog(buf, BRF, LEV_IMM, FALSE);
}
else
if (!(d = DIR(rroom, dir)))
{
sprintf(buf, "SYSERR: Room: #%d, exit: %d invalid trap dir.",rvnum, dir);
mudlog(buf, BRF, LEV_IMM, FALSE);
}
else
if (TRAPS(d))
{
sprintf(buf, "SYSERR: Room: #%d, exit: %d, multiple traps.",rvnum, dir);
mudlog(buf, BRF, LEV_IMM, FALSE);
}
else
{
CREATE(t, trap, 1);
t->type = tmp1;
t->level = tmp2;
t->bitv = tmp3;
t->timer = tmp4;
trap_to_dir(t, d);
}
}
break;
case 'R': // we got room affs now ... 4/28/98 -jtrhone
sscanf(cptr, "R %d %d %d %d\n", &rvnum, &tmp1, &tmp2, &tmp3);
cptr = scan_past_eol(cptr);
// make sure its valid before we allocate...
rroom = real_room(rvnum);
if (INVALID_ROOM(rroom))
{
sprintf(buf, "SYSERR: Room: #%d, room affect invalid.",rvnum);
mudlog(buf, BRF, LEV_IMM, FALSE);
}
raf.spell = tmp1;
raf.duration = tmp2;
raf.bitvector = tmp3;
raf.caster = NULL;
affect_to_room(rroom, &raf);
break;
case '$': /* we've reached end!!! */
break;
default:
sprintf(buf, "SYSERR: COMLIST ERROR: zone %d.\n\r",zone);
mudlog(buf, CMP, LEV_AIMP, TRUE);
break;
}
}
set_original_objects(zone); /* reset shopkeepers stuff RoA */
load_zone_rmobjs(zone);
reset_zone_transports(zone);
zone_table[zone].age = 0;
zone_table[zone].idle_time = 0;
REMOVE_BIT(ZONE_FLAGS(zone), Z_IDLE);
// reset all rprocs to beginning... 6/5/98 -jtrhone
for (rroom = 0; rroom < top_of_world; rroom++)
if (world[rroom].zone == zone && ROOM_FLAGGED(rroom, RPROC))
RPROC_CUR(&world[rroom]) = RPROC_BEG(&world[rroom]);
}
/* for use in reset_roazone;
(and in ZARENA RoA James Rhone)
return TRUE if zone 'nr' is free of PC's */
int is_empty(int zone_nr)
{
dsdata *i;
for (i = descriptor_list; i; i = i->next)
if (D_CHECK(i) && i->character->in_room > NOWHERE)
if (world[i->character->in_room].zone == zone_nr)
return(FALSE);
return(TRUE);
}
/*************************************************************************
* stuff related to the save/load player system *
*********************************************************************** */
long get_id_by_name(char *name)
{
int i;
one_argument(name, arg);
for (i = 0; i <= top_of_p_table; i++)
if (!str_cmp((player_table + i)->name, arg))
return ((player_table + i)->id);
return -1;
}
char *get_name_by_id(long id)
{
int i;
if (id < 0) return NULL;
for (i = 0; i <= top_of_p_table; i++)
if ((player_table + i)->id == id)
return ((player_table + i)->name);
return NULL;
}
/* scan the current descriptor list for a particular idnum -roa */
chdata *get_char_by_id(long id)
{
dsdata *d = descriptor_list;
for ( ; d; d=d->next)
if (d->character && IS_PC(d->character) && GET_IDNUM(d->character) == id)
return(d->character);
return NULL;
}
/* Load a char, TRUE if loaded, FALSE if not */
int load_char(char *name, struct char_file_u *char_element)
{
int player_i;
int find_name(char *name);
if ((player_i = find_name(name)) >= 0)
{
fseek(player_fl, (long) (player_i * sizeof(struct char_file_u)), SEEK_SET);
fread(char_element, sizeof(struct char_file_u), 1, player_fl);
return(player_i);
} else
return(-1);
}
/* copy data from the file structure to a char struct */
void store_to_char(struct char_file_u *st, chdata *ch)
{
int i;
/* if not there already, give em a special struct */
if (!ch->pc_specials)
CREATE(ch->pc_specials, struct pc_special_data, 1);
GET_SEX(ch) = st->sex;
GET_CLASS(ch) = st->cls;
GET_LEVEL(ch) = st->level;
ch->player.short_descr = 0;
ch->player.long_descr = 0;
ch->player.name = str_dup(st->name);
if (*st->title)
ch->player.title = str_dup(st->title);
else
ch->player.title = str_dup("needs a new title.");
if (*st->description)
ch->player.description = str_dup(st->description);
else
ch->player.description = str_dup("<Insert Description Here>\n\r");
ch->player.hometown = st->hometown;
ch->player.time.birth = st->birth;
ch->player.time.played = st->played;
ch->player.time.logon = time(0);
ch->player.weight = st->weight;
ch->player.height = st->height;
ch->real_abils = st->real_abils;
ch->aff_abils = st->real_abils;
ch->points = st->points;
ch->pc_specials->saved.poofIn[0] = '\0';
ch->pc_specials->saved.poofOut[0] = '\0';
ch->pc_specials->saved.walkIn[0] = '\0';
ch->pc_specials->saved.walkOut[0] = '\0';
ch->pc_specials->saved = st->saved;
if (ch->points.max_mana < 100)
ch->points.max_mana = 100;
/* dynamic skill system: only PCs have a skill array allocated. */
// updated for new format 12/8/97 -jtrhone
// skill separation from char_file_u, 6/20/98 -jtrhone
if (!alloc_skills(ch))
{
sprintf(buf, "SYSWAR: Error in filling skills for %s.", GET_NAME(ch));
mudlog(buf, BRF, LEV_IMM, TRUE);
}
// dialect separation from char_file_u, 6/20/98 -jtrhone
if (!alloc_gskills(ch))
{
sprintf(buf, "SYSWAR: Error in filling gskills for %s.", GET_NAME(ch));
mudlog(buf, BRF, LEV_IMM, TRUE);
}
ch->specials.carry_weight = 0;
ch->specials.carry_items = 0;
ch->points.hitroll = 0;
ch->points.damroll = 0;
/* do ac calcs here, before affects are added -roa*/
ch->points.armor = 100;
if (IS_NAT_MONK(ch)) (ch->points.armor -= 2*GET_LEVEL(ch));
TELL_LEV(ch) = 0;
GET_ALIASES(ch) = NULL;
PLSHOPS(ch) = NULL;
/* Add all spell effects */
for (i = 0; i < MAX_AFFECT; i++)
if (st->affected[i].type)
affect_to_char(ch, &st->affected[i]);
ch->in_room = NOWHERE;
affect_total(ch);
/* If you're not poisoned and you've been away for more than
an hour, we'll set your HMV, rites... back to full */
if (!IS_AFFECTED(ch, AFF_POISON) && (((long) (time(0) - st->last_logon)) >= SECS_PER_REAL_HOUR))
{
GET_HIT(ch) = GET_MAX_HIT(ch);
GET_MOVE(ch) = GET_MAX_MOVE(ch);
GET_MANA(ch) = GET_MAX_MANA(ch);
RITES(ch) = 10;
}
} /* store_to_char */
/* copy vital data from a players char-structure to the file structure */
void char_to_store(chdata *ch, struct char_file_u *st)
{
int i;
struct affected_type *af;
obdata *char_eq[MAX_WEAR];
/* Unaffect everything a character can be affected by */
for (i = 0; i < MAX_WEAR; i++)
if ((char_eq[i] = EQ(ch, i)))
char_eq[i] = unequip_char(ch, i, FALSE);
for (af = ch->affected, i = 0; i < MAX_AFFECT; i++)
{
if (af)
{
st->affected[i] = *af;
st->affected[i].next = 0;
af = af->next;
}
else
{
st->affected[i].type = 0; /* Zero signifies not used */
st->affected[i].duration = 0;
st->affected[i].modifier = 0;
st->affected[i].location = 0;
st->affected[i].bitvector = 0;
st->affected[i].bitvector2 = 0;
st->affected[i].next = 0;
}
}
/* remove the affections so that the raw values are stored;
otherwise the effects are doubled when the char logs back in. */
while (ch->affected)
affect_remove(ch, ch->affected);
if ((i >= MAX_AFFECT) && af && af->next)
{
sprintf(buf, "SYSWAR: Out of aff storage room for %s.", GET_NAME(ch));
mudlog(buf, BRF, LEV_IMM, TRUE);
}
ch->aff_abils = ch->real_abils;
st->birth = ch->player.time.birth;
st->played = ch->player.time.played;
st->played += (long) (time(0) - ch->player.time.logon);
st->last_logon = time(0);
ch->player.time.played = st->played;
ch->player.time.logon = time(0);
st->hometown = ch->player.hometown;
st->weight = GET_WEIGHT(ch);
st->height = GET_HEIGHT(ch);
st->sex = GET_SEX(ch);
st->cls = GET_CLASS(ch);
st->level = GET_LEVEL(ch);
st->real_abils = ch->real_abils;
st->points = ch->points;
st->saved = ch->pc_specials->saved;
st->points.armor = 100;
st->points.hitroll = 0;
st->points.damroll = 0;
strncpy(st->name, GET_NAME(ch), NAME_LENGTH - 1);
if (GET_TITLE(ch))
strncpy(st->title, GET_TITLE(ch), TITLE_LENGTH - 1);
else
*st->title = '\0';
if (ch->player.description)
strncpy(st->description, ch->player.description, EXDESC_LENGTH - 1);
else
*st->description = '\0';
// separate skills from char_file_u 6/20/98 -jtrhone
if (!save_skills(ch))
{
sprintf(buf, "SYSWAR: Unable to save skills for %s.", GET_NAME(ch));
mudlog(buf, BRF, LEV_IMM, TRUE);
}
// separate gskills from char_file_u 6/20/98 -jtrhone
if (!save_gskills(ch))
{
sprintf(buf, "SYSWAR: Unable to save gskills for %s.", GET_NAME(ch));
mudlog(buf, BRF, LEV_IMM, TRUE);
}
/* add spell and eq affections back in now */
for (i = 0; i < MAX_AFFECT; i++)
if (st->affected[i].type)
affect_to_char(ch, &st->affected[i]);
for (i = 0; i < MAX_WEAR; i++)
if (char_eq[i])
equip_char(ch, char_eq[i], i, FALSE);
} /* Char to store */
/* create a new entry in the in-memory index table for the player file */
int create_entry(char *name)
{
int i;
if (top_of_p_table == -1)
{
CREATE(player_table, struct player_index_element, 1);
top_of_p_table = 0;
}
else
if (!(player_table = (struct player_index_element *)
realloc(player_table, sizeof(struct player_index_element) *
(++top_of_p_table + 1))))
{
perror("create entry");
log("REALLOC FAILURE: create entry in db.c");
exit(1);
}
CREATE(player_table[top_of_p_table].name, char , strlen(name) + 1);
/* copy lowercase equivalent of name to table field */
for (i = 0; (*(player_table[top_of_p_table].name + i) = LOWER(*(name + i)));
i++)
;
return (top_of_p_table);
}
/* UPDATE this slot of the player_table with this IDNUM and host...
NAME was already added in the create_entry function...
called from interpreter when a new char is created.. */
void update_p_index(int slot, long idnum, char *host)
{
player_table[slot].id = idnum;
strcpy(player_table[slot].last_ip, host);
}
/* write the vital data of a player to the player file */
void save_char(chdata *ch, sh_int load_room)
{
struct char_file_u st;
if (IS_NPC(ch) || !ch->desc)
return;
char_to_store(ch, &st);
strncpy(st.host, ch->desc->host, HOST_LEN);
st.host[HOST_LEN] = '\0';
st.saved.load_room = GET_LOADROOM(ch);
strcpy(st.pwd, ch->desc->pwd);
fseek(player_fl, ch->desc->pos * sizeof(struct char_file_u), SEEK_SET);
fwrite(&st, sizeof(struct char_file_u), 1, player_fl);
}
/************************************************************************
* procs of a (more or less) general utility nature *
********************************************************************** */
/* read and allocate space for a '~'-terminated string from a given file */
// do_fread
char *fread_string(FILE * fl, char *error)
{
char buf[MAX_STRING_LENGTH], tmp[512], *rslt;
register char *point;
int done = 0, length = 0, templength = 0;
*buf = '\0';
do {
if (!fgets(tmp, 512, fl)) {
fprintf(stderr, "SYSERR: fread_string: format error at or near %s\n",
error);
exit(1);
}
/* If there is a '~', end the string; else put an "\r\n" over the '\n'. */
if ((point = strchr(tmp, '~')) != NULL) {
*point = '\0';
done = 1;
} else {
point = tmp + strlen(tmp) - 1;
*(point++) = '\r';
*(point++) = '\n';
*point = '\0';
}
templength = strlen(tmp);
if (length + templength >= MAX_STRING_LENGTH) {
log("SYSERR: fread_string: string too large (db.c)");
log(error);
sprintf(buf, "length = %d",length + templength);
log(buf);
exit(1);
} else {
strcat(buf + length, tmp);
length += templength;
}
} while (!done);
/* allocate space for the new string and copy it */
if (strlen(buf) > 0) {
CREATE(rslt, char, length + 1);
strcpy(rslt, buf);
} else
rslt = NULL;
return rslt;
}
/* read and SKIP a '~'-terminated string from a given file */
// do_fskip
BOOL fskip_string(FILE *fl, char *error)
{
char buf[MAX_STRING_LENGTH], tmp[512];
register char *point;
int done = 0, length = 0, templength = 0;
*buf = '\0';
do {
if (!fgets(tmp, 512, fl)) {
fprintf(stderr, "SYSERR: fskip_string: format error at or near %s\n",
error);
exit(1);
}
/* If there is a '~', end the string; else put an "\r\n" over the '\n'. */
if ((point = strchr(tmp, '~')) != NULL) {
*point = '\0';
done = 1;
} else {
point = tmp + strlen(tmp) - 1;
*(point++) = '\r';
*(point++) = '\n';
*point = '\0';
}
templength = strlen(tmp);
if (length + templength >= MAX_STRING_LENGTH) {
log("SYSERR: fskip_string: string too large (db.c)");
log(error);
sprintf(buf, "length = %d",length + templength);
log(buf);
exit(1);
} else {
strcat(buf + length, tmp);
length += templength;
}
} while (!done);
/* allocate space for the new string and copy it */
if (strlen(buf) > 0)
return TRUE;
else
return FALSE;
}
// no freeing here, just set all times to 0, and flag it Z_IDLE
// purge everything in the zone as well,
// without the global variable .zlock_reset. so it's a normal purge -roa
int idle_this_zone(int i)
{
SET_ZONE_IDLE(i);
zone_table[i].idle_time = 0;
zone_table[i].age = 0;
purge_zone(i);
return(1);
}
// remove the IDLE flag and reset the idle time to 0 -roa
// may add things to this process later on
int unidle_this_zone(int i)
{
UNSET_ZONE_IDLE(i);
zone_table[i].idle_time = 0;
return(1);
}
int unidle_reset_zone(int zone)
{
if (ZONE_FREED(zone))
reload_zone(zone);
zlock_reset = 1;
purge_zone(zone);
zlock_reset = 0;
reset_roazone(zone);
sprintf(buf, "Idle zone activated: (#%d) %s",zone, zone_table[zone].name);
mudlog(buf, CMP, LEV_IMM, TRUE);
return 1;
}
/* reads in the string comlist from .zonroa file on disk */
void load_zone_comlist(int zone)
{
int zon, i;
char clist[MAX_COMLIST_LENGTH], tmp[150];
FILE *fl;
char letter;
sprintf(buf, "world/zon/%d.zonroa", zone);
if (!(fl = fopen(buf, "r"))) {
sprintf(tmp, "Error reading %s", buf);
perror(tmp);
return;
}
fscanf(fl, "#%d\n", &zon);
FREENULL(zone_table[zone].name);
zone_table[zone].name = fread_string(fl, buf2);
// discard the followig data on a zone reload during runtime...
fscanf(fl, "%d %d %d\n%d\n", &zon, &zon, &zon, &zon);
// sound checks/adds 2/18/98 -jtrhone
letter=fread_letter(fl);
ungetc(letter, fl);
// check for sound stuff... denoted by @
if (letter == '@')
{
fscanf(fl, "@ %d %d\n", &zon, &zon);
fskip_string(fl, buf2);
}
/* CHECK FOR WEATHER DATA HERE so we can ignore it -RoA */
/* now get next char, if it's a W, we read in the weather stuff */
/* else we put the char back and continue */
letter=fread_letter(fl);
ungetc(letter, fl);
/* now we gotta read the zone weather -roa */
if (letter == 'W')
{
for (i = 0; i < 4; i++)
fscanf(fl, "W%d %d %d %d %d %d %d\n",
&zon, &zon, &zon, &zon, &zon, &zon, &zon);
fscanf(fl, "W %d %d %d %d %d %d %d %d\n",
&zon, &zon, &zon, &zon, &zon, &zon, &zon, &zon);
}
// check for sunrise/sunset messages, denoted by *
letter=fread_letter(fl);
ungetc(letter, fl);
if (letter == '*')
{
fscanf(fl, "*\n");
for (i = 0; i < 4; i++)
{
zone_table[zon].seasons[i].sunrise = fread_string(fl, buf2);
zone_table[zon].seasons[i].daytime = fread_string(fl, buf2);
zone_table[zon].seasons[i].sunset = fread_string(fl, buf2);
zone_table[zon].seasons[i].nighttime = fread_string(fl, buf2);
}
}
*tmp = ' ';
*clist = '\0';
while (*tmp != '~') /* while not at end of file babe */
{
fgets(tmp, 120, fl);
str_cat(clist, tmp, MAX_COMLIST_LENGTH, "load_zone_comlist");
}
fclose(fl);
if (*clist)
zone_table[zone].comlist = str_dup(clist);
else
zone_table[zone].comlist = NULL;
}
// load the rooms of a zone when returning from FREE/IDLE state
void load_zone_rooms(int zone)
{
int room_nr = 0, virtual_nr, flag = 0;
char *temp, chk[50];
exdescdata *new_descr;
BOOL skip = 0;
int ctr = 0;
int tmpi1, tmpi2, tmpi3;
FILE *fl;
sprintf(buf, "world/wld/%d.wld", zone);
if (!(fl = fopen(buf, "r"))) {
sprintf(buf2, "Error reading %s", buf);
perror(buf2);
return;
}
do {
fscanf(fl, " #%d\n", &virtual_nr);
/* make sure room is in world list if nt at end*/
if (virtual_nr != 99999)
if ((room_nr = real_room(virtual_nr)) < 0)
{
sprintf(buf, "SYSERR: reload room #%d not in dbase.",virtual_nr);
mudlog(buf, BRF, LEV_IMM, TRUE);
skip = TRUE;
}
/* if for some reason the room has a NULL name */
/* substitute a default name in it */
if (!(temp = fread_string(fl, buf2)))
temp = str_dup("BLANK");
if ((flag = (*temp != '$')))
{
world[room_nr].name = temp;
if (!(world[room_nr].description = fread_string(fl, buf2)))
world[room_nr].description = str_dup("BLANK\n\r");
clear_room(room_nr, TRUE);
fscanf(fl, " %*d ");
fscanf(fl, " %d ", &world[room_nr].room_flags);
fscanf(fl, " %d ", &tmpi1);
world[room_nr].terrain_type = tmpi1;
for (; ; )
{
fscanf(fl, " %s \n", chk);
if (*chk == 'D') /* direction field */
setup_existing_dir(fl, room_nr, atoi(chk + 1));
else
if (*chk == 'r') /* room_flags2 field */
world[room_nr].room_flags2 = atoi(chk + 1);
else
if (*chk == 'E') /* extra description field */
{
CREATE(new_descr, exdescdata, 1);
new_descr->keyword = fread_string(fl, buf2);
new_descr->description = fread_string(fl, buf2);
// insert into room exdesc list...
new_descr->next = world[room_nr].exdesc;
world[room_nr].exdesc = new_descr;
}
else
if (*chk == 'R') /* ROOM RANDOMS RoA JRHONE */
for (ctr = 0; ctr < 5; ctr++)
world[room_nr].randoms[ctr] = fread_string(fl, buf2);
else
if (*chk == 'p') /* portals field */
{
fscanf(fl, "\n%d %d %d %d\n", &world[room_nr].portals[0],
&world[room_nr].portals[1],
&world[room_nr].portals[2],
&world[room_nr].portals[3]);
}
else if (*chk == 'M') /* max contains field */
{
world[room_nr].max_contains = atoi(chk + 1);
}
else if (*chk == 'F') /* float to field */
{
world[room_nr].float_to = atoi(chk + 1);
}
else if (*chk == 'Q') /* drop_to field */
{
world[room_nr].drop_to = atoi(chk + 1);
}
else if (*chk == 'd') /* drift_to field */
{
world[room_nr].drift_to = atoi(chk + 1);
}
else if (*chk == 't') /* transport stuff */
{
fscanf(fl, "\n%d %d %d\n", &tmpi1, &tmpi2, &tmpi3);
world[room_nr].dock_wait = tmpi1;
world[room_nr].travel_wait = tmpi2;
world[room_nr].ticket_num = tmpi3;
}
else if (*chk == 'z') /* dice field */
{
fscanf(fl, "\n%d %d %d\n", &tmpi1, &tmpi2, &tmpi3);
world[room_nr].numdice = tmpi1;
world[room_nr].sizedice = tmpi2;
world[room_nr].alter_type = tmpi3;
}
else
if (*chk == 'o') /* owner field for room owner */
{
fscanf(fl, " %d %d %d\n", &tmpi1, &tmpi2, &tmpi3);
world[room_nr].owner = tmpi1;
// tmp2 is a SPARE
// tmp3 is a SPARE
}
else
if (*chk == 'm') /* music file/timer */
{
fscanf(fl, " %d\n", &tmpi1);
world[room_nr].music_timer = tmpi1;
world[room_nr].sound_file = fread_string(fl, buf2);
}
else
if (*chk == 'P') /* rproc 6/5/98 -jtrhone */
{
world[room_nr].rproc = fread_string(fl, buf2);
world[room_nr].rproc_cur = world[room_nr].rproc;
}
else if (*chk == 'S') /* end of current room */
break;
}
world[room_nr].exdesc = correct_extra_descrips(world[room_nr].exdesc);
if (skip)
skip = FALSE;
else
room_nr++;
}
} while (flag);
fclose(fl);
/* cleanup the area containing the terminal $ */
if (temp)
free(temp);
}
/* go thru, 1. load up the comlist from disk
2. load up the .wld file into the world list */
void reload_zone(int i)
{
if (!ZONE_FREED(i))
{
sprintf(buf, "SYSERR: Attempted reload of unfreed zone (%d).",i);
mudlog(buf, BRF, LEV_IMM, TRUE);
return;
}
UNSET_ZONE_FREED(i);
load_zone_rooms(i);
load_zone_comlist(i);
reset_zone_transports(i);
}
/* read contets of a text file, alloc space, point buf to it */
int file_to_string_alloc(char *name, char **buf)
{
char temp[10000];
if (file_to_string(name, temp) < 0)
return -1;
if (*buf) free(*buf);
*buf = str_dup(temp);
return 0;
}
/* read contents of a text file, and place in buf */
int file_to_string(char *name, char *buf)
{
FILE * fl;
char tmp[100];
*buf = '\0';
if (!(fl = fopen(name, "r"))) {
sprintf(tmp, "Error reading %s", name);
perror(tmp);
*buf = '\0';
return(-1);
}
do
{
// clear out tmp before every line... 5/23/98 -jtrhone
*tmp = '\0';
fgets(tmp, 99, fl);
// add *tmp check, could be feof(fl) and still have chars to place! 5/23/98 -jtrhone
if (*tmp || !feof(fl))
{
if (strlen(buf) + strlen(tmp) + 1 >= MAX_STRING_LENGTH)
{
mudlog("SYSERR: fl->strng: string too big (db.c, file_to_string)", BRF, LEV_IMM, TRUE);
*buf = '\0';
return(-1);
}
strcat(buf, tmp);
*(buf + strlen(buf) + 1) = '\0';
*(buf + strlen(buf)) = '\r';
}
} while (!feof(fl));
fclose(fl);
return(0);
}
/* read contents of a text file, and place in buf */
int huge_file_to_string(char *name, char *buf)
{
FILE * fl;
char tmp[100];
*buf = '\0';
if (!(fl = fopen(name, "r"))) {
sprintf(tmp, "Error reading %s", name);
perror(tmp);
*buf = '\0';
return(-1);
}
do
{
fgets(tmp, 99, fl);
if (!feof(fl))
{
if (strlen(buf) + strlen(tmp) + 1 >= 85000)
{
mudlog("SYSERR: fl->strng: string too big (db.c, huge_file_to_string)", BRF, LEV_IMM, TRUE);
*buf = '\0';
return(-1);
}
strcat(buf, tmp);
*(buf + strlen(buf) + 1) = '\0';
}
} while (!feof(fl));
fclose(fl);
return(0);
}
/* clear some of the the working variables of a char */
void reset_char(chdata *ch)
{
int i;
ch->in_room = NOWHERE;
for (i = 0; i < MAX_WEAR; i++) /* Initializing */
EQ(ch, i) = NULL;
ch->carrying = 0;
ch->specials.carry_weight = 0;
ch->specials.carry_items = 0;
ch->next = 0;
ch->next_in_room = 0;
ch->next_fighting = 0;
ch->followers = 0;
ch->master = 0;
DELAY_TYPE(ch) = CHAR_FLAGS(ch) = 0;
FIGHTING(ch) = HUNTING(ch) = 0;
ch->specials.position = POS_STANDING;
ch->npc_specials.default_pos = POS_STANDING;
for (i = 0; i < 6; i++)
ch->npc_specials.strs[i] = NULL;
ch->pc_specials->saved.zone_locked = FALSE;
if (GET_HIT(ch) <= 0)
GET_HIT(ch) = 1;
if (GET_MOVE(ch) <= 0)
GET_MOVE(ch) = 1;
if (GET_MANA(ch) <= 0)
GET_MANA(ch) = 1;
ch->pc_specials->prehit = GET_HIT(ch);
ch->pc_specials->premana = GET_MANA(ch);
ch->pc_specials->premove = GET_MOVE(ch);
if (PAGE_LENGTH(ch) <= 15 || PAGE_LENGTH(ch) > 40)
PAGE_LENGTH(ch) = 22;
}
/* clear ALL the working variables of a char and
do NOT free any space alloc'ed*/
void clear_char(chdata *ch)
{
int j;
memset((char *)ch, (char)'\0', (int)sizeof(chdata));
ch->in_room = NOWHERE;
ch->specials.was_in_room = NOWHERE;
ch->specials.position = POS_STANDING;
ch->npc_specials.sound_file= NULL;
ch->npc_specials.shop_data = NULL;
for (j = 0; j < 6; j++)
ch->npc_specials.strs[j] = NULL;
GET_AC(ch) = 100; /* Basic Armor */
if (ch->points.max_mana < 100)
ch->points.max_mana = 100;
}
void clear_object(obdata *obj)
{
memset((char *)obj, (char)'\0', (int)sizeof(obdata));
obj->item_number = -1;
obj->objsave_self = -1;
obj->objsave_parent = -1;
obj->objsave_where = -1;
obj->in_room = NOWHERE;
obj->tmp1 = -1;
obj->tmp2 = -1;
}
/* initialize a new character only if class is set */
void init_char(chdata *ch)
{
int i;
/* if not there already, give em a special struct */
if (!ch->pc_specials)
CREATE(ch->pc_specials, struct pc_special_data, 1);
/* *** if this is our first player --- he be God *** */
// first char no longer has ID == 0
if (top_of_p_table <= 0)
{
GET_EXP(ch) = 7000000;
GET_LEVEL(ch) = LEV_IMPL;
ch->points.max_hit = 500;
ch->points.max_mana = 100;
ch->points.max_move = 82;
}
set_title(ch);
ch->player.short_descr = 0;
ch->player.long_descr = 0;
ch->player.description = 0;
ch->player.time.birth = time(0);
ch->player.time.played = 0;
ch->player.time.logon = time(0);
ch->pc_specials->saved.changed_password = TRUE;
ch->real_abils.str = 25;
ch->real_abils.str_add = 100;
ch->real_abils.intel = 25;
ch->real_abils.wis = 25;
ch->real_abils.con = 25;
ch->real_abils.dex = 25;
ch->real_abils.cha = 25;
/* make favors for sex */
if (ch->player.sex == SEX_MALE)
{
ch->player.weight = number(120, 180);
ch->player.height = number(160, 200);
}
else
{
ch->player.weight = number(100, 160);
ch->player.height = number(150, 180);
}
ch->points.max_mana = 100;
ch->points.mana = GET_MAX_MANA(ch);
ch->points.hit = GET_MAX_HIT(ch);
ch->points.max_move = 82;
ch->points.move = GET_MAX_MOVE(ch);
ch->points.armor = 100;
/* assign this character the highest IDNUM available, and bump it up*/
/* NOTE: this does not update the player index! shall we? -roa */
ch->pc_specials->saved.idnum = ++top_idnum;
if (!ch->skills)
CREATE(ch->skills, skl_info, MAX_SKILLS);
if (!ch->gskills)
CREATE(ch->gskills, skl_info, MAX_GSKILLS);
for (i = 1; i < MAX_SKILLS; i++)
if (GET_LEVEL(ch) < LEV_IMPL)
{
set_skill(ch, i, 0);
ch->skills[i].learned = 0;
}
else
{
set_skill(ch, i, 100);
ch->skills[i].learned = 1;
}
for (i = 0; i < MAX_GSKILLS; i++)
if (GET_LEVEL(ch) < LEV_IMPL)
{
ch->gskills[i].perc = 0;
ch->gskills[i].learned = 1;
}
else
{
ch->gskills[i].perc = 100;
ch->gskills[i].learned = 1;
}
if (!save_skills(ch))
{
sprintf(buf, "SYSWAR: Unable to save skills for %s.", GET_NAME(ch));
mudlog(buf, BRF, LEV_IMM, TRUE);
}
if (!save_gskills(ch))
{
sprintf(buf, "SYSWAR: Unable to save gskills for %s.", GET_NAME(ch));
mudlog(buf, BRF, LEV_IMM, TRUE);
}
AFF_FLAGS(ch) = AFF2_FLAGS(ch) = 0;
for (i = 0; i < MAX_WEAR; i++) /* Initializing */
{
if (EQ(ch, i))
{
sprintf(buf, "SYSUPD: %s eq slot %d failed NULL check.",GET_NAME(ch), i);
mudlog(buf, BUG, LEV_IMM, TRUE);
}
EQ(ch, i) = NULL;
}
for (i = 0; i < 5; i++)
SAVING_THROW(ch, i) = 0;
for (i = 0; i < 3; i++)
GET_COND(ch, i) = (GET_LEVEL(ch) == LEV_IMPL ? -1 : 24);
/* Set up a default prompt - the standard one is too confusing */
strcpy(ch->pc_specials->saved.saved_prompt, "<%h/%H %v/%V %m/%M> ");
strcpy(ch->pc_specials->saved.walkIn, "enters");
strcpy(ch->pc_specials->saved.walkOut, "leaves");
strcpy(ch->pc_specials->saved.prename, "");
// set up screen for newbie
VTSPLIT(ch) = 21;
PAGE_LENGTH(ch) = 22;
// give em some default flags
SET_BIT(PRF_FLAGS(ch), PRF_AUTOX);
SET_BIT(PLR_FLAGS(ch), PLR_INFOCH);
}
/* returns the real number of the room with given virtual number */
int real_room(int vnum)
{
int bot, top, mid;
bot = 0;
top = top_of_sorted_world - 1;
/* perform binary search on world-table */
for (; ; ) {
mid = (bot + top) / 2;
if ((world + mid)->number == vnum)
return(mid);
if (bot >= top) {
break;
}
if ((world + mid)->number > vnum)
top = mid - 1;
else
bot = mid + 1;
}
for (mid = top_of_sorted_world; mid < top_of_world; mid++)
if ((world + mid)->number == vnum)
return(mid);
return -1;
}
/* returns the real number of the monster with given virtual number */
int real_mobile(int vnum)
{
int bot, top, mid;
bot = 0;
top = top_of_sorted_mobt - 1;
/* perform binary search on mob-table */
for (; ; ) {
mid = (bot + top) / 2;
if ((mob_index + mid)->vnum == vnum)
return(mid);
if (bot >= top)
break;
if ((mob_index + mid)->vnum > vnum)
top = mid - 1;
else
bot = mid + 1;
}
for (mid = top_of_sorted_mobt; mid < top_of_mobt; mid++)
if ((mob_index + mid)->vnum == vnum)
return(mid);
return -1;
}
/* returns the real number of the object with given virtual number */
int real_object(int vnum)
{
int bot, top, mid;
bot = 0;
top = top_of_sorted_objt - 1;
/* perform binary search on obj-table */
for (; ; ) {
mid = (bot + top) / 2;
if ((obj_index + mid)->vnum == vnum)
return(mid);
if (bot >= top)
break;
if ((obj_index + mid)->vnum > vnum)
top = mid - 1;
else
bot = mid + 1;
}
for (mid = top_of_sorted_objt; mid < top_of_objt; mid++)
if ((obj_index + mid)->vnum == vnum)
return(mid);
return -1;
}
/* kinda dumb check for real zone, well dumb now cause all zones are
of same length, so just check table number - RoA jtrhone */
int real_zone(int target_zone)
{
if (target_zone < 0 || target_zone >= NUM_ZONES)
return -1;
if (zone_table[target_zone].number >= 0)
return target_zone;
return -1;
}
/*
* Read a number from a file.
*/
int fread_number( FILE *fp )
{
int number;
BOOL sign;
char c;
do {
c = getc( fp );
} while ( isspace(c) );
number = 0;
sign = FALSE;
if ( c == '+' ) {
c = getc( fp );
} else if ( c == '-' ) {
sign = TRUE;
c = getc( fp );
}
if ( !isdigit(c) ) {
log("fread_number : bad format in db.c");
exit( 1 );
}
while ( isdigit(c) ) {
number = number * 10 + c - '0';
c = getc( fp );
}
if ( sign )
number = 0 - number;
if ( c == '|' )
number += fread_number( fp );
else if ( c != ' ' )
ungetc( c, fp );
return number;
}
/*
* Read to end of line (for comments).
*/
void fread_to_eol( FILE *fp )
{
char c;
do {
c = getc( fp );
} while ( c != '\n' && c != '\r' );
do {
c = getc( fp );
} while ( c == '\n' || c == '\r' );
ungetc( c, fp );
return;
}
/*
* Read one word (into static buffer).
*/
char *fread_word(FILE *fp)
{
static char word[MAX_INPUT_LENGTH];
char *pword;
char cEnd;
do
{
cEnd = getc( fp );
}
while ( isspace( cEnd ) );
if ( cEnd == '\'' || cEnd == '"' )
{
pword = word;
}
else
{
word[0] = cEnd;
pword = word+1;
cEnd = ' ';
}
for ( ; pword < word + MAX_INPUT_LENGTH; pword++ )
{
*pword = getc( fp );
if ( cEnd == ' ' ? isspace(*pword) || *pword == '~' : *pword == cEnd )
{
if ( cEnd == ' ' || cEnd == '~' )
ungetc( *pword, fp );
*pword = '\0';
return word;
}
}
log("SYSERR: Fread_word: word too long.");
exit( 1 );
return NULL;
}
/*************************************************************************/
/* The following mob,obj,wldsave procs completely update the files */
/* without having to do it by hand...as of now it is RoA standard 0.06 */
/* ... easy changes for any flags */
/* that each mud may have..or different file formats...NOTE: these procs*/
/* change the ORIGINAL files in world dir...be sure to backup regularly*/
/* JTRHONE 4/95 */
/*************************************************************************/
/* this procedure waxes all the \r chars in a string */
/* warning, call with preallocated string to avoid leaking */
/* NOTE: str is a pre allocated string */
/* NOTE THIS ALSO replaces the ~ char with - so fread string can work */
char *killr(char *str)
{
char *tmp1, *tmp2;
for (tmp1 = str; *tmp1; tmp1++)
{
// we must not have ~ in the text data files
if (*tmp1 == '~')
*tmp1 = '-';
else
while (*tmp1 == '\r')
{
for (tmp2 = tmp1 + 1; *tmp2; tmp2++)
*(tmp2 - 1) = *tmp2;
*(tmp2 - 1) = '\0';
}
}
return str;
}
// caller must free the string returned from this function
char *winkillr(char *str)
{
int len;
char *t1, *t2, *new;
// first, wax the \r's
killr(str);
// get current length
len = strlen(str)+1;
// allocate enough buffer
CREATE(t2, char, len*2);
new = t2;
// now, scan thru str, change each \n into \r\n
for (t1 = str; *t1; t1++)
if (*t1 == '\n')
{
*t2 = '\r'; t2++;
*t2 = '\n'; t2++;
}
else
{
*t2 = *t1; t2++;
}
*t2 = '\0';
return new;
}
ACMD(do_mobsave)
{
void save_mobindex(chdata *ch, BOOL show);
int znum;
chdata *m;
int i, top, j;
FILE *fptr;
if (IS_NPC(ch))
return;
one_argument(argument, arg);
if (!*arg) {
send_to_char("Usage: mobsave <zone#>.\n\r",ch);
return;
}
if (is_number(arg)) {
znum = atoi(arg);
}
else {
send_to_char("Usage: mobsave <zone#>.\n\r",ch);
return;
}
if (!REAL_ZONE(znum))
{
send_to_char("mobsave: That zone doesn't exist.\n\r",ch);
return;
}
sprintf(buf2, "world/mob/%d.mob",znum);
if ( !(fptr = fopen(buf2, "wt")) )
{
sprintf(buf, "SYSERR: Unable to open %d.mob for writing.", znum);
mudlog(buf, BRF, LEV_IMM, TRUE);
return;
}
i = znum * 100;
top = i + 99;
while ( i <= top)
{
if ((real_mobile(i)) < 0)
{
i++;
continue;
}
m = &mob_proto[real_mobile(i)];
fprintf(fptr, "#%d\n", i);
if (m->player.name)
str_cpy(buf, m->player.name, MAX_STRING_LENGTH, "do_mobsave");
else
strcpy(buf, "BLANK");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_mobsave"), fptr);
if(m->player.short_descr)
str_cpy(buf, m->player.short_descr, MAX_STRING_LENGTH, "do_mobsave");
else
strcpy(buf, "BLANK");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_mobsave"), fptr);
if(m->player.long_descr)
str_cpy(buf, m->player.long_descr, MAX_STRING_LENGTH, "do_mobsave");
else
strcpy(buf, "BLANK");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_mobsave"), fptr);
if(m->player.description)
str_cpy(buf, m->player.description, MAX_STRING_LENGTH, "do_mobsave");
else
strcpy(buf, "BLANK");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_mobsave"), fptr);
fprintf(fptr, "%ld %ld %d Z\n", MOB_FLAGS(m), AFF_FLAGS(m),
GET_ALIGNMENT(m));
fprintf(fptr, "%d %d %d %d %d\n", GET_LEVEL(m), GET_EXP(m),
GET_HITROLL(m), GET_AC(m), GET_GOLD(m));
fprintf(fptr, "%d %d %d\n", m->npc_specials.damnodice,
m->npc_specials.damsizedice, GET_DAMROLL(m));
fprintf(fptr, "%d %d %d\n",m->npc_specials.mob_num_hit,
m->npc_specials.mob_size_hit,m->npc_specials.mob_add_hit);
fprintf(fptr, "%d %d %d\n",m->npc_specials.mob_num_mana,
m->npc_specials.mob_size_mana, m->npc_specials.mob_add_mana);
fprintf(fptr, "%d %d %d\n",m->npc_specials.mob_num_move,
m->npc_specials.mob_size_move,m->npc_specials.mob_add_move);
fprintf(fptr, "%d %d %d\n",m->specials.position,
m->npc_specials.default_pos, m->player.sex);
fprintf(fptr, "s%d\n", SPEAKING(m));
fprintf(fptr, "t\n"); /* mobile strings RoA jtrhone */
// got 5 strings to write here 0 - 4
for (j = 0; j < 5; j++)
if (m->npc_specials.strs[j])
{
str_cpy(buf, m->npc_specials.strs[j], MAX_STRING_LENGTH, "do_mobsave");
str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_mobsave");
fputs(buf, fptr);
}
else
fprintf(fptr, "~\n");
// WE MUST WRITE MPROC_CUR as NULL -jtrhone 1/5/97
fprintf(fptr, "~\n");
fprintf(fptr, "W\n"); /* mobile walkin/out strings RoA jtrhone */
if (MWALKIN(m))
{
str_cpy(buf, MWALKIN(m), MAX_STRING_LENGTH, "do_mobsave");
str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_mobsave");
fputs(buf, fptr);
}
else
fprintf(fptr, "~\n");
if (MWALKOUT(m))
{
str_cpy(buf, MWALKOUT(m), MAX_STRING_LENGTH, "do_mobsave");
str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_mobsave");
fputs(buf, fptr);
}
else
fprintf(fptr, "~\n");
fprintf(fptr, "P%ld\n", m->npc_specials.spc_bits);
fprintf(fptr, "p%ld\n", AFF2_FLAGS(m));
fprintf(fptr, "T%d %d\n", m->npc_specials.min_train_level, m->npc_specials.max_train_level);
/* if a shopkeep and defined hours, writem -roa*/
if (SPC_FLAGGED(m, SPC_SHOPKEEP) && m->npc_specials.shop_data)
fprintf(fptr, "H%d %d %d %d\n",
m->npc_specials.shop_data->vhome,
m->npc_specials.shop_data->vshop,
m->npc_specials.shop_data->open,
m->npc_specials.shop_data->close);
fprintf(fptr, "V%d %d %d %d %d\n",
m->npc_specials.saving_throws[0],
m->npc_specials.saving_throws[1],
m->npc_specials.saving_throws[2],
m->npc_specials.saving_throws[3],
m->npc_specials.saving_throws[4]);
fprintf(fptr, "Q%d %d\n", m->npc_specials.qnum, m->npc_specials.hunt_quest);
fprintf(fptr, "m %d\n", m->npc_specials.music_timer);
if (m->npc_specials.sound_file)
{
str_cpy(buf, m->npc_specials.sound_file, MAX_STRING_LENGTH, "do_mobsave");
strcat(killr(buf), "~\n");
fputs(buf, fptr);
}
else
fprintf(fptr, "~\n");
// note the spares....
fprintf(fptr, "u%d %d %d %d %d %d %d %d\n", MOB2_FLAGS(m),0,0,0,0,0,0,0);
fprintf(fptr, "X2\n");
fprintf(fptr, "%d %d %d %d %d %d\n-1 %d %ld\n",
m->real_abils.str,
m->real_abils.str_add,
m->real_abils.intel,
m->real_abils.wis,
m->real_abils.dex,
m->real_abils.con,
m->npc_specials.mob_size,
m->npc_specials.mob_class);
i++;
}
fprintf(fptr, "#99999\n$~");
fclose(fptr);
save_mobindex(ch, subcmd);
if (subcmd)
send_to_char("Mob file rewritten.\n\r",ch);
return;
}
ACMD(do_objsave)
{
void save_objindex (chdata *ch, BOOL show);
int znum;
obdata *o;
int i, j, top;
FILE *fp;
char fname[MAX_INPUT_LENGTH];
exdescdata *e;
if (IS_NPC(ch))
return;
one_argument(argument, arg);
if (!*arg) {
send_to_char("Usage: objsave <zone#>.\n\r",ch);
return;
}
if (is_number(arg)) {
znum = atoi(arg);
}
else {
send_to_char("Usage: objsave <zone#>.\n\r",ch);
return;
}
if (!REAL_ZONE(znum))
{
send_to_char("objsave: That zone doesn't exist.\n\r",ch);
return;
}
sprintf(fname, "world/obj/%d.obj",znum);
if ( !(fp = fopen(fname, "wt")) )
{
sprintf(buf, "SYSERR: Unable to open %d.obj for writing.", znum);
mudlog(buf, BRF, LEV_IMM, TRUE);
return;
}
i = znum * 100;
top = i + 99;
while ( i <= top)
{
if (real_object(i) < 0)
{
i++;
continue;
}
o = &obj_proto[real_object(i)];
/* make sure they are written correctly to disk */
o->exdesc = correct_extra_descrips(o->exdesc);
fprintf(fp, "#%d\n", i);
if (o->name)
{
str_cpy(buf, o->name, MAX_STRING_LENGTH, "do_objsave");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_objsave"), fp);
}
else
fputs(strcpy(buf, "BLANK~\n"), fp);
if (o->shdesc)
{
str_cpy(buf, o->shdesc, MAX_STRING_LENGTH, "do_objsave");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_objsave"), fp);
}
else
fputs(strcpy(buf, "BLANK~\n"), fp);
if (o->description)
{
str_cpy(buf, o->description, MAX_STRING_LENGTH, "do_objsave");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_objsave"), fp);
}
else
fputs(strcpy(buf, "BLANK~\n"), fp);
if (o->actdesc)
{
str_cpy(buf, o->actdesc, MAX_STRING_LENGTH, "do_objsave");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_objsave"), fp);
}
else
fputs(strcpy(buf, "BLANK~\n"), fp);
fprintf(fp, "%d %d %d\n", o->type_flag,OBJ_EXTRAS(o), OBJ_WEARS(o));
fprintf(fp, "%d %d %d %d\n", o->value[0],o->value[1], o->value[2], o->value[3]);
fprintf(fp, "%d %d 0\n", o->weight,o->cost);
for (e = o->exdesc; e; e = e->next)
{
sprintf(buf, "E\n%s", e->keyword);
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_objsave"), fp);
str_cpy(buf, e->description, MAX_STRING_LENGTH, "do_objsave");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_objsave"), fp);
}
for (j = 0; j < MAX_OBJ_AFFECT; j++)
{
if (o->affected[j].location)
{
fprintf(fp, "A\n%d %d\n", o->affected[j].location,
o->affected[j].modifier);
}
}
fprintf(fp, "H %d\n",OBJ_HITS(o));
fprintf(fp, "M %d\n",MAX_OBJ_HITS(o));
fprintf(fp, "x %d\n",OBJ_EXTRAS2(o));
fprintf(fp, "m %d\n",MADE_OF(o));
fprintf(fp, "p %d\n",SUCCESS_RATE(o));
fprintf(fp, "X %d %d %d %d\n", o->total_game_limit, o->percent_load,
o->alternate_load, o->min_level);
fprintf(fp, "Q %d %ld\n", o->eqspell, o->eqaffbit);
fprintf(fp, "q %ld\n", o->eqaff2bit);
fprintf(fp, "T %d %d %d %d\n", o->throw_plushit, o->throw_numdam,
o->throw_sizedam, o->throw_plusdam);
if (o->wear_mesg)
{
fputs("W\n",fp);
str_cpy(buf, o->wear_mesg, MAX_STRING_LENGTH, "do_objsave");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_objsave"), fp);
}
else
fputs(strcpy(buf, "W\n~\n"), fp);
if (o->rem_mesg)
{
str_cpy(buf, o->rem_mesg, MAX_STRING_LENGTH, "do_objsave");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_objsave"), fp);
}
else
fputs(strcpy(buf, "~\n"), fp);
if (o->weap_sing)
{
str_cpy(buf, o->weap_sing, MAX_STRING_LENGTH, "do_objsave");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_objsave"), fp);
}
else
fputs(strcpy(buf, "BLANK~\n"), fp);
if (o->weap_plur)
{
str_cpy(buf, o->weap_plur, MAX_STRING_LENGTH, "do_objsave");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_objsave"), fp);
}
else
fputs(strcpy(buf, "BLANK~\n"), fp);
// added wvector 5/28/98 -jtrhone
fprintf(fp, "V %d\n", WV_FLAGS(o));
i++;
}
fprintf(fp, "#99999\n$~");
fclose(fp);
save_objindex(ch, subcmd);
if (subcmd)
send_to_char("Object file rewritten.\n\r",ch);
return;
}
/* JTRHONE .. umm 4/95...completely updates wld file */
/* note: ch may be NULL */
ACMD(do_wldsave)
{
void save_wldindex (chdata *ch, BOOL show);
int ctr, znum;
rmdata *r;
int i, j, top;
FILE *fp;
char fname[MAX_INPUT_LENGTH];
exdescdata *e;
one_argument(argument, arg);
if (ch)
{
if (IS_NPC(ch))
return;
if (!*arg) {
send_to_char("Usage: wldsave <zone#>.\n\r",ch);
return;
}
}
if (is_number(arg))
znum = atoi(arg);
else
{
if (ch)
send_to_char("Usage: wldsave <zone#>.\n\r",ch);
return;
}
if (!REAL_ZONE(znum))
{
if (ch)
send_to_char("wldsave: That zone doesn't exist.\n\r",ch);
return;
}
if (ZONE_FREED(znum))
{
sprintf(buf, "SYSERR: Attempt to wldsave a FREED zone (%d).",znum);
mudlog(buf, BRF, LEV_IMM, TRUE);
if (ch)
send_to_char("Cannot %Bwldsave%0 a %B%6freed%0 zone.\n\r",ch);
return;
}
sprintf(fname, "world/wld/%d.wld",znum);
if ( !(fp = fopen(fname, "wt")) )
{
sprintf(buf, "SYSERR: Unable to open %d.wld for writing.", znum);
mudlog(buf, BRF, LEV_IMM, TRUE);
return;
}
i = znum * 100;
top = i + 99;
while ( i <= top)
{
if (real_room(i) < 0)
{
i++;
continue;
}
r = &world[real_room(i)];
/* make sure they are written correctly to disk */
r->exdesc = correct_extra_descrips(r->exdesc);
sprintf(buf, "#%d\n", i);
fputs(buf, fp);
if (r->name)
{
str_cpy(buf, r->name, MAX_STRING_LENGTH, "do_wldsave");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_objsave"), fp);
}
else
fputs(strcpy(buf, "BLANK~\n"), fp);
if (r->description)
{
str_cpy(buf, r->description, MAX_STRING_LENGTH, "do_wldsave");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_wldsave"), fp);
}
else
fputs(strcpy(buf, "BLANK~\n"), fp);
fprintf(fp, "%d %d %d\n", r->zone, r->room_flags,
r->terrain_type);
fprintf(fp, "r%d\n",r->room_flags2);
for (e = r->exdesc; e; e = e->next)
{
sprintf(buf, "E\n%s", e->keyword);
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_wldsave"), fp);
str_cpy(buf, e->description, MAX_STRING_LENGTH, "do_wldsave");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_wldsave"), fp);
}
for (j = 0; j < NUM_OF_DIRS; j++)
{
if (r->dir_option[j])
{
fprintf(fp, "D%d\n", j);
if (r->dir_option[j]->exit_descr)
{
str_cpy(buf, r->dir_option[j]->exit_descr, MAX_STRING_LENGTH, "do_wldsave");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_wldsave"), fp);
}
else
fputs("~\n", fp);
if (r->dir_option[j]->keyword)
{
str_cpy(buf, r->dir_option[j]->keyword, MAX_STRING_LENGTH, "do_wldsave");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_wldsave"), fp);
}
else
fputs("~\n", fp);
// add support for 4 new exit strs 3/24/98 -jtrhone
fprintf(fp, "#\n");
if (r->dir_option[j]->enter)
{
str_cpy(buf, r->dir_option[j]->enter, MAX_STRING_LENGTH, "do_wldsave");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_wldsave"), fp);
}
else
fputs("~\n", fp);
if (r->dir_option[j]->oenter)
{
str_cpy(buf, r->dir_option[j]->oenter, MAX_STRING_LENGTH, "do_wldsave");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_wldsave"), fp);
}
else
fputs("~\n", fp);
if (r->dir_option[j]->drop)
{
str_cpy(buf, r->dir_option[j]->drop, MAX_STRING_LENGTH, "do_wldsave");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_wldsave"), fp);
}
else
fputs("~\n", fp);
if (r->dir_option[j]->odrop)
{
str_cpy(buf, r->dir_option[j]->odrop, MAX_STRING_LENGTH, "do_wldsave");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_wldsave"), fp);
}
else
fputs("~\n", fp);
// save the BITVECTOR not the type anymore -roa
fprintf(fp, "V%d %d %d\n",
r->dir_option[j]->exinfo, r->dir_option[j]->key,
world[r->dir_option[j]->to_room].number);
}
}
fprintf(fp, "R\n"); /* room randoms */
for (ctr = 0; ctr < 5; ctr++)
if (r->randoms[ctr])
{
str_cpy(buf, r->randoms[ctr], MAX_STRING_LENGTH, "do_wldsave");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_wldsave"), fp);
}
else
fprintf(fp, "~\n");
fprintf(fp, "p\n%d %d %d %d\n", r->portals[0], r->portals[1],
r->portals[2], r->portals[3]);
fprintf(fp, "M%d\n", r->max_contains);
fprintf(fp, "F%d\n", r->float_to);
fprintf(fp, "Q%d\n", r->drop_to);
fprintf(fp, "d%d\n", r->drift_to);
fprintf(fp, "t\n%d %d %d\n", r->dock_wait, r->travel_wait, r->ticket_num);
fprintf(fp, "z\n%d %d %d\n", r->numdice, r->sizedice, r->alter_type);
fprintf(fp, "o %d -1 -1\n", r->owner); // <-- SPARES, last two
fprintf(fp, "m %d\n", r->music_timer);
if (r->sound_file)
{
str_cpy(buf, r->sound_file, MAX_STRING_LENGTH, "do_wldsave");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_wldsave"), fp);
}
else
fprintf(fp, "~\n");
// write the room proc 6/5/98 -jtrhone
fprintf(fp, "P\n");
if (r->rproc)
{
str_cpy(buf, r->rproc, MAX_STRING_LENGTH, "do_wldsave");
fputs(str_cat(killr(buf), "~\n", MAX_STRING_LENGTH, "do_wldsave"), fp);
}
else
fprintf(fp, "~\n");
fprintf(fp, "S\n"); // That's all folks
i++;
}
fprintf(fp, "#99999\n$~\n");
fclose(fp);
if (ch)
{
save_wldindex(ch, subcmd);
if (subcmd)
send_to_char("World(rooms) file rewritten.\n\r",ch);
}
return;
}
void save_mobindex (chdata *ch, BOOL show)
{
int i;
FILE *fp;
char fname[MAX_INPUT_LENGTH];
if (mini_mud)
sprintf(fname, "world/mob/index.mini");
else
sprintf(fname, "world/mob/index");
if ( !(fp = fopen(fname, "wt"))) {
mudlog("SYSERR: Opening mob index for writing.", BUG, LEV_IMM, TRUE);
return;
}
for (i = 0; i < NUM_ZONES; i++)
if (REAL_ZONE(i))
fprintf(fp, "%d.mob\n", i);
fprintf(fp, "$\n");
fclose(fp);
if (show)
send_to_char("MobIndex updated.\n\r",ch);
}
void save_objindex (chdata *ch, BOOL show)
{
int i;
FILE *fp;
char fname[MAX_INPUT_LENGTH];
if (mini_mud)
sprintf(fname, "world/obj/index.mini");
else
sprintf(fname, "world/obj/index");
if ( !(fp = fopen(fname, "wt"))) {
mudlog("SYSERR: Opening obj index for writing.", BUG, LEV_IMM, TRUE);
return;
}
for (i = 0; i < NUM_ZONES; i++)
if (REAL_ZONE(i))
fprintf(fp, "%d.obj\n", i);
fprintf(fp, "$\n");
fclose(fp);
if (show)
send_to_char("ObjIndex updated.\n\r",ch);
}
void save_wldindex (chdata *ch, BOOL show)
{
int i;
FILE *fp;
char fname[MAX_INPUT_LENGTH];
if (mini_mud)
sprintf(fname, "world/wld/index.mini");
else
sprintf(fname, "world/wld/index");
if ( !(fp = fopen(fname, "wt")))
{
mudlog("SYSERR: Opening wld index for writing.", BUG, LEV_IMM, TRUE);
return;
}
for (i = 0; i < NUM_ZONES; i++)
if (REAL_ZONE(i))
fprintf(fp, "%d.wld\n", i);
fprintf(fp, "$\n");
fclose(fp);
if (show)
send_to_char("WldIndex updated.\n\r",ch);
}
// updated, use is_abbrev() now 6/14/98 -jtrhone
ACMD(do_view)
{
if (IS_NPC(ch))
return;
one_argument(argument, arg);
if (!*arg) {
send_to_char("Usage: view <ideas | bugs | typos>.\n\r",ch);
return;
}
if (is_abbrev(arg, "stats"))
{
sprintf(buf, "%s memory statistics...\n\r", shortmudname);
S2C();
underline(buf);
S2C();
send_to_char("Unavailable.\n\r",ch);
}
else
if (is_abbrev(arg, "ideas"))
{
sprintf(buf, "tail -n 25 %s >> ideas_temp", IDEA_FILE);
roa_system(buf);
file_to_string("ideas_temp", buf2);
unlink("ideas_temp");
sprintf(buf, "%s IDEA listing...\n\r", shortmudname);
S2C();
underline(buf);
S2C();
page_string(ch->desc, buf2, 1);
}
else
if (is_abbrev(arg, "bugs"))
{
sprintf(buf, "tail -n 25 %s >> bugs_temp", BUG_FILE);
roa_system(buf);
file_to_string("bugs_temp", buf2);
unlink("bugs_temp");
sprintf(buf, "%s BUG listing...\n\r", shortmudname);
S2C();
underline(buf);
S2C();
page_string(ch->desc, buf2, 1);
}
else
if (is_abbrev(arg, "typos"))
{
sprintf(buf, "tail -n 25 %s >> typos_temp", TYPO_FILE);
roa_system(buf);
file_to_string("typos_temp", buf2);
unlink("typos_temp");
sprintf(buf, "%s TYPO listing...\n\r", shortmudname);
S2C();
underline(buf);
S2C();
page_string(ch->desc, buf2, 1);
}
else
send_to_char("Usage: view < ideas | bugs | typos >.\n\r",ch);
}
#undef __ROA_DB_C__