/************************************************************************ 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__