/*************************************************************************** * Mud20 1.0 by Todd H. Johnson (Kregor) a derivative of the Open Gaming * * License by Wizards of the Coast. All comments referring to D20, OGL, * * and SRD refer to the System Reference Document for the Open Gaming * * system. Any inclusion of these derivatives must include credit to the * * Mud20 system, the full and complete Open Gaming LIcense, and credit to * * the respective authors. See ../doc/srd.txt for more information. * * * * Emud 2.2 by Igor van den Hoven, Michiel Lange, and Martin Bethlehem. * * * * MrMud 1.4 by David Bills, Dug Michael and Martin Gallwey * * * * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * Original Diku Mud copyright (C) 1990 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeld, Tom Madsen, and Katje Nyboe. * ***************************************************************************/ /*************************************************************************** * db.c: Server load, loop and event functions * ***************************************************************************/ #include <sys/time.h> #include <stdarg.h> #include "mud.h" /* Locals. */ AREA_DATA *area_load; int tot_memory_warning = 0; CHAR_DATA *supermob; OBJ_DATA *supermob_obj; ROOM_INDEX_DATA *supermob_room; void create_menu_tree(); /* Cpu management */ lg_int timers[TIMER_MAXTIMER][5]; const char timer_strings[TIMER_MAXTIMER][40] = { "Area Save Time:", "Update Shops:", "Update Character:", "Update Areas:", "Update Weather:", "Update Objects:", "Char Save Time:", "Update Violence:", "Update Obj Progs:", "Update Mob Progs:", "Update Mobiles:", "Update Aggressive:", "Update Purger:", "Update Tactical:", "Scan Descriptor:", "Process Input:", "Process Output:", "Update Time:", }; /* Memory management */ #define MAX_PERM_BLOCK 1000000 #define MAX_MEM_LIST 48 const int rgSizeList [MAX_MEM_LIST] = { 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 288, 320, 352, 384, 416, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1088, 1216, 1344, 1472, 1728, 1984, 2240, 2496, 3072, 4096, 6144, 8192, 16384, 32768, 65536, 72016 }; void * alloc_perm ( bool iList ); typedef struct perm_block_list PERM_BLOCK_LIST; struct perm_block_list { int iMemPerm; }; PERM_BLOCK_LIST *perm_block_index[ 255 ]; /* Maximum perm blocks of 256 */ typedef struct free_mem_list FREE_MEM_LIST; struct free_mem_list { FREE_MEM_LIST * next; }; FREE_MEM_LIST *rgFreeList [MAX_MEM_LIST]; int rgFreeCount[MAX_MEM_LIST]; /* count of freed memory */ int rgUsedCount[MAX_MEM_LIST]; /* count of used memory */ /* Semi-locals. */ FILE * fpArea; char strArea[MAX_INPUT_LENGTH]; /* Local booting procedures. */ void load_auth_list args( ( void ) ); /* New Auth Code */ void save_auth_list args( ( void ) ); void save_style args( (int num) ); void save_styles args( ( void ) ); void load_style args( (int num) ); void load_styles args( ( void ) ); void save_races args( ( void ) ); void load_races args( ( void ) ); void save_domain args( (int num) ); void save_domains args( ( void ) ); void load_domain args( (int num) ); void load_domains args( ( void ) ); void save_god args( (int num) ); void save_gods args( ( void ) ); void load_god args( (int num) ); void load_gods args( ( void ) ); void fread_components args( ( void ) ); void fread_bloodlines args( ( void ) ); void save_class args( (int num) ); void save_classes args( ( void ) ); void load_classes args( ( void ) ); void load_area args( ( FILE *fp, int segment ) ); void load_helps args( ( FILE *fp ) ); void load_mobiles args( ( FILE *fp ) ); void load_objects args( ( FILE *fp ) ); void load_resets args( ( FILE *fp ) ); void load_rooms args( ( FILE *fp ) ); void load_shops args( ( FILE *fp ) ); void load_inns args( ( FILE *fp ) ); void load_stables args( ( FILE *fp ) ); void load_specials args( ( FILE *fp ) ); void load_ranges args( ( FILE *fp ) ); void load_version args( ( FILE *fp ) ); void load_olc_ranges args( ( FILE *fp ) ); void load_resetmsg args( ( FILE *fp ) ); void load_justice args( ( FILE *fp ) ); void load_authors args( ( FILE *fp ) ); void load_flags args( ( FILE *fp ) ); void load_temperature args( ( FILE *fp ) ); void load_weather args( ( FILE *fp ) ); void load_repairs args( ( FILE *fp ) ); void load_fk_mobiles args( ( FILE *fp ) ); void load_fk_objects args( ( FILE *fp ) ); void load_fk_rooms args( ( FILE *fp ) ); void load_fk_weather args( ( FILE *fp ) ); void load_fk_weather args( ( FILE *fp ) ); OBJ_PROG * load_object_program args( ( FILE *fp ) ); void obj_prog_if_dest args( ( OBJ_INDEX_DATA * ) ); void expand_mob_prog args( ( MOB_INDEX_DATA * , OBJ_INDEX_DATA *, ROOM_INDEX_DATA *, MPROG_DATA * ) ); char expand_line_mprog args( ( MOB_INDEX_DATA * , OBJ_INDEX_DATA *, ROOM_INDEX_DATA *, MPROG_DATA *, char *, bool, char ) ); RESET_DATA * get_reset_from_obj args( ( RESET_DATA *lReset ) ); RESET_DATA * get_reset_from_mob args( ( RESET_DATA *lReset ) ); RESET_DATA * get_reset_from_trap args( ( RESET_DATA *lReset ) ); /* MOBprogram locals */ void mprog_read_programs args ( ( FILE* fp, MOB_INDEX_DATA *pMobIndex ) ); void init_supermob( void ) { supermob = create_mobile( get_mob_index( 3 ) ); char_to_room( supermob, 3, FALSE ); } /* * convert a bitvector to a string - Kregor */ char *bits_to_str(lg_int number, char *vector) { char *buf; lg_int cnt; push_call("bits_to_str(%p,%p)",number,vector); for (cnt = 0 ; *bitvector_table[cnt].name != '\0' ; cnt++) { if (!str_prefix(vector, bitvector_table[cnt].name)) { if (number == bitvector_table[cnt].value) { pop_call(); return (bitvector_table[cnt].name); } } } sprintf(buf, "%lld", number ); pop_call(); return buf; } /* * convert a string to a bitvector * if no value found, return 0 - Kregor */ lg_int str_to_bits(char *vector) { lg_int cnt; push_call("str_to_bits(%p)",vector); for (cnt = 0 ; *bitvector_table[cnt].name != '\0' ; cnt++) { if (!strcasecmp(vector, bitvector_table[cnt].name)) { pop_call(); return (bitvector_table[cnt].value); } } pop_call(); return 0; } /* * Return a string of bitvectors - Kregor */ char *broken_bits( lg_int number, char *vector, bool linear ) { lg_int bit, cnt; bool found; static char broken_string[MAX_INPUT_LENGTH]; push_call("broken_bits(%p,%p,%p)",number,vector,linear); if (IS_SET(mud->flags, MUD_STRAIGHTNUMBERS)) { sprintf(broken_string, "%lld" , number); pop_call(); return broken_string; } found = FALSE; bit = 0; broken_string[0] = '\0'; if (!linear) { while (bit <= number && number >= 0) { if (IS_SET(number, bit)) { for (cnt = mud->bitvector_ref[*vector - 'A'] ; *bitvector_table[cnt].name != '\0' ; cnt++) { if (bit == bitvector_table[cnt].value) { if (!str_prefix(vector, bitvector_table[cnt].name)) { if (found) { strcat( broken_string, "|" ); } strcat(broken_string, bitvector_table[cnt].name); found = TRUE; break; } } } if (*bitvector_table[cnt].name == '\0') { if (found) { strcat(broken_string, "|" ); } log_printf("broken_bits: %s not found %lld", vector, bit); cat_sprintf(broken_string, "%lld", bit); found = TRUE; } } if (bit != 0) { bit *= 2; } else { bit++; } } } else { for (cnt = mud->bitvector_ref[*vector - 'A'] ; *bitvector_table[cnt].name != '\0' ; cnt++) { if (number == bitvector_table[cnt].value) { if (vector[0] == bitvector_table[cnt].name[0] && !str_prefix(vector, bitvector_table[cnt].name)) { strcat(broken_string, bitvector_table[cnt].name); found = TRUE; break; } } } } if (!found) { sprintf(broken_string, "%lld", number); } pop_call(); return( broken_string); } /* * for use in load_mobiles in db.c to * advance simple mobiles by hit dice - Kregor * * Compares hard set level to hit dice in race file, * advances mobile based on difference. */ void advance_mobile( MOB_INDEX_DATA *mob ) { int lvl, cnt; push_call("resize_mobile(%p)", mob); // do not run on custom non-raced mobiles if (mob->race == RACE_NONE) { pop_call(); return; } // if classed, levels are class levels if (mob->class != CLASS_MONSTER) { pop_call(); return; } // humanoids and fey advance by class levels switch (race_table[mob->race].type) { default: break; case RTYPE_HUMANOID: case RTYPE_MONSTROUS: case RTYPE_FEY: pop_call(); return; } if (race_table[mob->race].hit_dice >= mob->level) { pop_call(); return; } /* can't get any bigger than this... */ if (race_table[mob->race].size >= SIZE_COLOSSAL) { pop_call(); return; } lvl = race_table[mob->race].hit_dice; // dragons get special advancement rules if (race_table[mob->race].type == RTYPE_DRAGON) { int sizeplus; lvl = UMAX(0, mob->level - lvl); switch(lvl / 2) { default: sizeplus = 5; mob->perm_dex = UMAX(1, mob->perm_dex - 8); break; case 0: sizeplus = 0; break; case 1: sizeplus = 1; mob->perm_dex = UMAX(1, mob->perm_dex - 2); break; case 2: case 3: sizeplus = 2; mob->perm_dex = UMAX(1, mob->perm_dex - 4); break; case 4: case 5: case 6: sizeplus = 3; mob->perm_dex = UMAX(1, mob->perm_dex - 6); break; case 7: case 8: case 9: case 10: sizeplus = 4; mob->perm_dex = UMAX(1, mob->perm_dex - 8); break; } if (sizeplus) { mob->size = UMIN(mob->size + sizeplus, SIZE_COLOSSAL); mob->nat_armor += lvl * 3 / 2; mob->perm_str += lvl + 2; if (lvl >= 4) mob->perm_str += 2; mob->perm_con += sizeplus * 2; mob->perm_int += lvl / 2 + 1; mob->perm_wis += lvl / 2 + 1; mob->perm_cha += lvl / 2 + 1; } } else if (mob->level >= ROUNDUP(lvl * 3 / 2)) { // size up & add stat mods for size for (cnt = mob->size ; cnt <= SIZE_COLOSSAL ; cnt++) { if (mob->level < ROUNDUP(lvl * 3 / 2)) // mob level is less than 50% more, no resize break; if (mob->size == SIZE_COLOSSAL) break; lvl *= 3; lvl = ROUNDUP(lvl/2); if (mob->size > SIZE_FINE) mob->perm_str += mob->size; if (mob->size < SIZE_GARGANTUAN) mob->perm_dex = UMAX(3, mob->perm_dex - 2); if (mob->size > SIZE_TINY) { mob->perm_con += mob->size / 2; mob->nat_armor += mob->size - 3; } mob->size++; } } // add points to racial skills for advancement for (cnt = 0 ; is_string(skill_table[cnt].name) ; cnt++) { if (skill_table[cnt].skilltype != FSKILL_SKILL) continue; if (skill_table[cnt].race_skill[mob->race]) mob->learned[cnt] += UMAX(0, mob->level - race_table[mob->race].hit_dice); } pop_call(); return; } /* Big mama top level function. */ void boot_db( bool fCopyOver ) { lg_int boot_start, boot_end; int index, cnt; push_call("boot_db(%p)",fCopyOver); boot_start = get_game_usec(); SET_BIT(mud->flags, MUD_EMUD_BOOTING); SET_BIT(mud->flags, MUD_EMUD_BOOTDB); srand48(mud->current_time); log_string("Loading Bitvector Table..."); for (index = 0 ; index < 26 ; index++) { for (cnt = 0 ; *bitvector_table[cnt].name != '\0' ; cnt++) { if (bitvector_table[cnt].name[0] == 'A' + index) { /* log_printf("bitvector_ref[%c] = %d", 'A' + index, cnt); */ mud->bitvector_ref[index] = cnt; break; } } } load_sites(); load_nsites(); load_usage(); load_players(); load_timeinfo(); load_bounties(); load_victors(); load_hiscores(); load_classes(); load_domains(); load_styles(); load_races(); load_gods(); fread_components(); fread_bloodlines(); /* Assign table indexes - Scandum */ for (index = 0 ; index < 26 ; index++) { for (cnt = 0 ; *cmd_table[cnt].name != '\0' ; cnt++) { if (*cmd_table[cnt].name == 'a' + index) { /* log_printf("command_ref[%c] = %d", 'a' + index, cnt); */ mud->command_ref[index] = cnt; break; } } } for (index = 0 ; index < 26 ; index++) { for (cnt = 0 ; *social_table[cnt].name != '\0' ; cnt++) { if (*social_table[cnt].name == 'a' + index) { /* log_printf("social_ref[%c] = %d", 'a' + index, cnt); */ mud->social_ref[index] = cnt; break; } } } /* removed dependency on MAX_SKILL changing, * MAX_REAL_SKILL advances until a skill with no * name is reached in skill table - Kregor */ for (cnt = MAX_REAL_SKILL = 0 ; *skill_table[cnt].name != '\0' ; cnt++) { if (skill_table[cnt].pgsn != NULL) { /* log_printf("skill_table[%03d].name = %s", cnt, skill_table[cnt].name); */ *skill_table[cnt].pgsn = cnt; } MAX_REAL_SKILL++; } /* Read in all the area files. */ { FILE *fpList; log_printf("Loading Areas"); if ((fpList = my_fopen(AREA_LIST, "r", FALSE)) == NULL) { perror( AREA_LIST ); abort(); } while (TRUE) { strcpy(strArea, fread_word(fpList)); log_string(strArea); if (strArea[0] == '$') { break; } if ((fpArea = my_fopen(strArea, "r", FALSE)) == NULL) { perror( strArea ); abort( ); } fread_area(fpArea, 0); my_fclose(fpArea); fpArea = NULL; } if (fpList) { my_fclose( fpList ); } } if (mud->time_info->hour < 5) { mud->sunlight = SUN_DARK; } else if (mud->time_info->hour < 6) { mud->sunlight = SUN_RISE; } else if ( mud->time_info->hour < 11 ) { mud->sunlight = SUN_LIGHT; } else if ( mud->time_info->hour < 15 ) { mud->sunlight = SUN_NOON; } else if ( mud->time_info->hour < 19 ) { mud->sunlight = SUN_LIGHT; } else if ( mud->time_info->hour < 20 ) { mud->sunlight = SUN_SET; } else { mud->sunlight = SUN_DARK; } SET_BIT(mud->flags, MUD_EMUD_BOOTDB); log_string("Loading the SuperMob"); init_supermob(); log_string("Updating Areas"); area_update(); REMOVE_BIT(mud->flags, MUD_EMUD_BOOTDB); log_string("Loading Notes"); load_notes(); log_string("Creating Menu Tree"); create_menu_tree(); log_string("Loading Saved Storerooms"); load_lockers(); log_string( "Loading Clans" ); load_clans(); log_string( "Loading Auth Name list" ); load_auth_list( ); save_auth_list( ); REMOVE_BIT(mud->flags, MUD_EMUD_BOOTING); { /* Clear out timers */ int cnt; for (cnt = 0 ; cnt < TIMER_MAXTIMER ; cnt++) { timers[cnt][0] = 0; timers[cnt][1] = 0; timers[cnt][2] = 0; timers[cnt][3] = 0; timers[cnt][4] = 0; } } if (fCopyOver) { copyover_recover(); } boot_end = get_game_usec(); log_printf("Database booted in %lld usec!", boot_end - boot_start); pop_call(); return; } void fread_area(FILE *fp, int segment) { char *word; push_call("fread_area(%p,%p)",fp, segment); while (TRUE) { if (fread_letter(fp) != '#') { bug( "Boot_db: # not found.", 0 ); abort( ); } word = fread_word(fp); switch (word[0]) { case '$': pop_call(); return; case 'A': if (!strcmp(word, "AREA")) { load_area(fp, segment); break; } if (!strcmp(word, "AUTHORS") || !strcmp(word, "AUTHOR") ) { load_authors(fp); break; } case 'F': if (!strcmp(word, "FLAGS")) { load_flags(fp); break; } case 'E': if (!strcmp(word, "ECONOMY")) // For loading FKMud areas with stupid economy - Kregor { break; } case 'H': if (!strcmp(word, "HELPS")) { load_helps(fp); break; } case 'I': if (!strcmp(word, "INNS")) { load_inns(fp); break; } case 'J': if (!strcmp(word, "JUSTICE")) { load_justice(fp); break; } case 'M': if (!strcmp(word, "MOBILES")) { if (area_load->version == 99) load_fk_mobiles(fp); else load_mobiles(fp); break; } case 'O': if (!strcmp(word, "OLC_RANGES")) { load_olc_ranges(fp); break; } if (!strcmp(word, "OBJECTS")) { if (area_load->version == 99) load_fk_objects(fp); else load_objects (fp); break; } case 'Q': if (!strcmp(word, "QUESTS")) // here til I can reverse engineer it - Kregor { break; } case 'R': if (!strcmp(word, "RANGES")) { load_ranges(fp); break; } if (!strcmp(word, "REPAIRS")) // Because FKMud uses the silly Smaug way - Kregor { load_resetmsg(fp); break; } if (!strcmp(word, "RESETMSG")) { load_resetmsg(fp); break; } if (!strcmp(word, "RESETS")) { load_resets(fp); break; } if (!strcmp(word, "ROOMS")) { if (area_load->version == 99) load_fk_rooms(fp); else load_rooms(fp); break; } case 'S': if (!strcmp(word, "SHOPS")) { load_shops(fp); break; } if (!strcmp(word, "SPECIALS")) { load_specials(fp); break; } if (!strcmp(word, "STABLES")) { load_stables(fp); break; } case 'T': if (!strcmp(word, "TEMPERATURE")) { load_temperature(fp); break; } case 'V': if (!strcmp(word, "VERSION")) { load_version(fp); break; } case 'W': if (!strcmp(word, "WEATHER")) { if (area_load->version == 99) load_fk_weather(fp); else load_weather(fp); break; } default: bug("boot_db: bad section name: %s", word); abort( ); } } } /* Snarf an 'area' header line. */ void load_area ( FILE *fp, int segment ) { AREA_DATA *pArea, *temp_area; int cnt; push_call("load_area(%p,%p)",fp,segment); ALLOCMEM(pArea, AREA_DATA, 1); pArea->name = fread_string( fp ); pArea->age = 99; pArea->version = 0; pArea->low_r_vnum = MAX_VNUM-1; pArea->low_o_vnum = MAX_VNUM-1; pArea->low_m_vnum = MAX_VNUM-1; pArea->olc_range_lo = MAX_VNUM-1; pArea->resetmsg = STRDUPE(str_empty); pArea->hi_soft_range = MAX_LEVEL; pArea->hi_hard_range = MAX_LEVEL; pArea->authors = STRDUPE(str_empty); for (cnt = 0 ; cnt < CRIME_MAX ; cnt++) { pArea->punishment[cnt] = 0; } pArea->courtroom = 0; pArea->dungeon = 0; pArea->judge = 0; pArea->guard = 0; ALLOCMEM(pArea->weather_info, WEATHER_DATA, 1); pArea->weather_info->temp_winter = -10; pArea->weather_info->temp_summer = 20; pArea->weather_info->temp_daily = 10; pArea->weather_info->wind_scale = 4; pArea->weather_info->wet_scale = 4; { for (temp_area = mud->f_area ; temp_area ; temp_area = temp_area->next) { if (strcmp(pArea->name, temp_area->name) < 0) { INSERT_LEFT(pArea, temp_area, mud->f_area, next, prev); break; } } if (!temp_area) { LINK(pArea, mud->f_area, mud->l_area, next, prev); } mud->top_area++; } pArea->filename = STRALLOC(strArea); area_load = pArea; pop_call(); return; } void load_temperature( FILE * fp ) { push_call("load_temperature(%p)",fp); fread_number(fp); fread_number(fp); fread_number(fp); fread_number(fp); pop_call(); return; } void load_weather( FILE * fp ) { push_call("load_weather(%p)",fp); area_load->weather_info->temp_winter = fread_number(fp); area_load->weather_info->temp_summer = fread_number(fp); area_load->weather_info->temp_daily = fread_number(fp); area_load->weather_info->wet_scale = fread_number(fp); area_load->weather_info->wind_scale = fread_number(fp); pop_call(); return; } void load_flags( FILE *fp ) { if (area_load->version < 2 || area_load->version == 99) { fread_number(fp); fread_number(fp); } else { area_load->flags = fread_number(fp); } } void load_authors( FILE *fp ) { push_call("load_authors(%p)",fp); STRFREE(area_load->authors); area_load->authors = fread_string(fp); pop_call(); return; } void load_ranges( FILE *fp ) { push_call("load_ranges(%p)",fp); area_load->low_soft_range = fread_number( fp ); area_load->hi_soft_range = fread_number( fp ); area_load->low_hard_range = fread_number( fp ); area_load->hi_hard_range = fread_number( fp ); if (area_load->low_soft_range > area_load->hi_soft_range) { log_printf("Low soft range is greater than high soft range."); } if (area_load->low_hard_range > area_load->hi_hard_range) { log_printf("Low hard range is greater than high hard range."); } pop_call(); return; } void load_version( FILE *fp ) { push_call("load_version(%p)",fp); area_load->version = fread_number(fp); pop_call(); return; } void load_olc_ranges( FILE *fp ) { push_call("load_olc_ranges(%p)",fp); area_load->olc_range_lo = fread_number( fp ); area_load->olc_range_hi = fread_number( fp ); pop_call(); return; } void load_resetmsg( FILE *fp ) { push_call("load_resetmsg(%p)",fp); STRFREE( area_load->resetmsg ); area_load->resetmsg = fread_string( fp ); pop_call(); return; } void load_justice( FILE *fp ) { char *word; push_call("load_justice(%p)",fp); while (TRUE) { word = fread_word(fp); switch (word[0]) { case '$': pop_call(); return; case 'C': if (!strcmp(word, "Courtroom")) { area_load->courtroom = fread_number(fp); break; } if (!strcmp(word, "Crime")) { area_load->punishment[fread_number(fp)] = fread_number(fp); break; } case 'D': if (!strcmp(word, "Dungeon")) { area_load->dungeon = fread_number(fp); break; } case 'G': if (!strcmp(word, "Guard")) { area_load->guard = fread_number(fp); break; } case 'J': if (!strcmp(word, "Judge")) { area_load->judge = fread_number(fp); break; } case 'S': if (!strcmp(word, "Storeroom")) { area_load->storeroom = fread_number(fp); break; } default: bug("load_justice: bad section name: %s", word); abort( ); } } pop_call(); return; } /* Snarf a help section. */ void load_helps( FILE *fp ) { HELP_DATA *pHelp; push_call("load_helps(%p)",fp); while (TRUE) { ALLOCMEM(pHelp, HELP_DATA, 1); pHelp->level = fread_number( fp ); pHelp->keyword = fread_string( fp ); if (pHelp->keyword[0] == '$') { FREEMEM(pHelp); break; } if (IS_SET(area_load->flags, AFLAG_NEWHELPS)) { pHelp->title = fread_string( fp ); } pHelp->text = fread_string( fp ); pHelp->area = area_load; LINK( pHelp, area_load->first_help, area_load->last_help, next, prev ); mud->top_help++; } pop_call(); return; } /* Add a character to the list of all characters */ void add_char( CHAR_DATA *ch ) { push_call("add_char(%p)",ch); if (!IS_NPC(ch)) { LINK(ch, mud->f_char, mud->l_char, next, prev); } else { LINK(ch, mud->f_char, mud->l_char, next, prev); LINK(ch, ch->pIndexData->first_instance, ch->pIndexData->last_instance, next_instance, prev_instance); } pop_call(); return; } /* Snarf a mob section. */ void load_mobiles( FILE *fp ) { MOB_INDEX_DATA *pMobIndex; EXTRA_DESCR_DATA *ed; AFFECT_DATA *paf; char buf[256], *pt; int vnum, sn, value; char letter; push_call("load_mobiles(%p)",fp); while (TRUE) { letter = fread_letter( fp ); if (letter != '#') { bug( "Load_mobiles: # not found.", 0 ); abort( ); } vnum = fread_number( fp ); if (vnum == 0) { break; } if (vnum < 1 || vnum >= MAX_VNUM) { bug("load_mobiles: vnum %u out of range.", vnum); abort( ); } if (get_mob_index(vnum) != NULL) { bug("load_mobiles: vnum %u duplicated.", vnum); abort( ); } ALLOCMEM(pMobIndex, MOB_INDEX_DATA, 1); pMobIndex->vnum = vnum; mob_index[vnum] = pMobIndex; pMobIndex->area = area_load; if (IS_SET(mud->flags, MUD_EMUD_BOOTDB)) { if (area_load->low_m_vnum > vnum) { area_load->low_m_vnum = vnum; } if (vnum > area_load->hi_m_vnum) { area_load->hi_m_vnum = vnum; } } pt = fread_string( fp ); /* Add M### system to names */ sprintf( buf, "m%u", vnum ); if (strstr(pt, buf) == NULL) { sprintf( buf, "%s m%u", pt, vnum ); } else { strcpy( buf, pt ); } STRFREE (pt); pMobIndex->player_name = STRALLOC(buf); /* pMobIndex->player_name = fread_string( fp ); */ pMobIndex->short_descr = fread_string( fp ); pMobIndex->long_descr = fread_string( fp ); pMobIndex->description = fread_string( fp ); pMobIndex->unique = FALSE; /* The read section for the new mob format starts HERE - Kregor 3/13/07 */ if (area_load->version >= 4) { letter = fread_letter( fp ); if (letter == 'U') pMobIndex->unique = TRUE; else if (letter == 'S') pMobIndex->unique = FALSE; else { bug( "Load_mobiles: vnum %u not U or S.", vnum ); abort( ); } pMobIndex->level = fread_number( fp ); pMobIndex->class = fread_number( fp ); pMobIndex->race = fread_number( fp ); pMobIndex->sex = fread_number( fp ); pMobIndex->position = fread_number( fp ); pMobIndex->god = fread_number( fp ); pMobIndex->act = fread_number( fp ); // Adjust old area levels to Mud20 standard - Kregor if (!IS_SET(pMobIndex->act, ACT_MOBINVIS)) pMobIndex->level = URANGE(1, pMobIndex->level, 30); if (!pMobIndex->unique) { if (pMobIndex->race <= RACE_NONE) { bug( "Load_mobiles: no race set on S mobile.", vnum ); pMobIndex->race = RACE_HUMAN; } if (pMobIndex->class != CLASS_MONSTER && pMobIndex->class < MAX_CLASS) pMobIndex->hitsizedice = class_table[pMobIndex->class].hp_max; else if (pMobIndex->race > RACE_NONE) pMobIndex->hitsizedice = race_type_table[race_table[pMobIndex->race].type].hit_die; else { bug( "Load_mobiles: neither class nor race hit die.", vnum ); pMobIndex->hitsizedice = 8; } pMobIndex->alignment = race_table[pMobIndex->race].alignment; pMobIndex->ethos = race_table[pMobIndex->race].ethos; pMobIndex->gold = 0; // need to add means to determine standard random gold /* * assign stats based on class pri and sec stats * These routines effectively gives standard NPCs * an elite array of abilities - Kregor */ if (pMobIndex->class > CLASS_MONSTER) { int class = pMobIndex->class; if (class_table[class].attr_prime == APPLY_STR) pMobIndex->perm_str = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[0]; else if (class_table[class].attr_second == APPLY_STR) pMobIndex->perm_str = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[0]; else pMobIndex->perm_str = best_three_of_four() + race_table[pMobIndex->race].race_mod[0]; if (class_table[class].attr_prime == APPLY_DEX) pMobIndex->perm_dex = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[1]; else if (class_table[class].attr_second == APPLY_DEX) pMobIndex->perm_dex = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[1]; else pMobIndex->perm_dex = best_three_of_four() + race_table[pMobIndex->race].race_mod[1]; if (class_table[class].attr_prime == APPLY_CON) pMobIndex->perm_con = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[2]; else if (class_table[class].attr_second == APPLY_CON) pMobIndex->perm_con = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[2]; else pMobIndex->perm_con = best_three_of_four() + race_table[pMobIndex->race].race_mod[2]; if (class_table[class].attr_prime == APPLY_INT) pMobIndex->perm_int = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[3]; else if (class_table[class].attr_second == APPLY_INT) pMobIndex->perm_int = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[3]; else pMobIndex->perm_int = best_three_of_four() + race_table[pMobIndex->race].race_mod[3]; if (class_table[class].attr_prime == APPLY_WIS) pMobIndex->perm_wis = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[4]; else if (class_table[class].attr_second == APPLY_WIS) pMobIndex->perm_wis = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[4]; else pMobIndex->perm_wis = best_three_of_four() + race_table[pMobIndex->race].race_mod[4]; if (class_table[class].attr_prime == APPLY_CHA) pMobIndex->perm_cha = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[5]; else if (class_table[class].attr_second == APPLY_CHA) pMobIndex->perm_cha = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[5]; else pMobIndex->perm_cha = best_three_of_four() + race_table[pMobIndex->race].race_mod[5]; } else { pMobIndex->perm_str = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[0]; pMobIndex->perm_int = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[1]; pMobIndex->perm_wis = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[2]; pMobIndex->perm_dex = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[3]; pMobIndex->perm_con = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[4]; pMobIndex->perm_cha = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[5]; } // zero out nonabilities by race if (race_table[pMobIndex->race].nonability[STAT_STR]) pMobIndex->perm_str = 0; if (race_table[pMobIndex->race].nonability[STAT_DEX]) pMobIndex->perm_dex = 0; if (race_table[pMobIndex->race].nonability[STAT_CON]) pMobIndex->perm_con = 0; if (race_table[pMobIndex->race].nonability[STAT_INT]) pMobIndex->perm_int = 0; if (race_table[pMobIndex->race].nonability[STAT_WIS]) pMobIndex->perm_wis = 0; if (race_table[pMobIndex->race].nonability[STAT_CHA]) pMobIndex->perm_cha = 0; pMobIndex->nat_armor = race_table[pMobIndex->race].nat_armor; pMobIndex->wear_locs = race_table[pMobIndex->race].wear_locs; pMobIndex->size = race_table[pMobIndex->race].size; pMobIndex->understands = race_table[pMobIndex->race].understands; pMobIndex->speaks = race_table[pMobIndex->race].speaks; } else { pMobIndex->affected_by = fread_number( fp ); pMobIndex->nat_armor = fread_number( fp ); pMobIndex->armor_type = fread_number( fp ); /* 'd' */ fread_letter( fp ); if (pMobIndex->class > CLASS_MONSTER && pMobIndex->class < MAX_CLASS) { fread_number( fp ); pMobIndex->hitsizedice = class_table[pMobIndex->class].hp_max; } else if (pMobIndex->race > RACE_NONE) { fread_number( fp ); pMobIndex->hitsizedice = race_type_table[race_table[pMobIndex->race].type].hit_die; } else { pMobIndex->hitsizedice = fread_number( fp ); } /* '+' */ fread_letter( fp ); pMobIndex->hitplus = fread_number( fp ); // damage stats no longer used in Mud20, but keeping in file fread_number( fp ); /* 'd' */ fread_letter( fp ); fread_number( fp ); /* '+' */ fread_letter( fp ); fread_number( fp ); pMobIndex->alignment = fread_number( fp ); pMobIndex->ethos = fread_number( fp ); pMobIndex->gold = fread_number( fp ); pMobIndex->perm_str = fread_number( fp ); pMobIndex->perm_int = fread_number( fp ); pMobIndex->perm_wis = fread_number( fp ); pMobIndex->perm_dex = fread_number( fp ); pMobIndex->perm_con = fread_number( fp ); pMobIndex->perm_cha = fread_number( fp ); if (!pMobIndex->race) { pMobIndex->body_type = fread_number( fp ); pMobIndex->wear_locs = fread_number( fp ); pMobIndex->size = fread_number( fp ); pMobIndex->race_type = fread_number( fp ); pMobIndex->rspecs = fread_number( fp ); } else { /* Unused */ fread_number( fp ); pMobIndex->wear_locs = race_table[pMobIndex->race].wear_locs; /* Unused */ fread_number( fp ); pMobIndex->size = fread_number( fp ); /* Unused */ fread_number( fp ); /* Unused */ fread_number( fp ); } pMobIndex->understands = fread_number( fp ); pMobIndex->speaks = fread_number( fp ); /* Unused */ fread_number( fp ); /* Unused */ fread_number( fp ); /* Unused */ fread_number( fp ); } } else { pMobIndex->act = fread_number( fp ); pMobIndex->affected_by = fread_number( fp ); pMobIndex->alignment = fread_number( fp ); letter = fread_letter( fp ); if (letter != 'S') { bug( "Load_mobiles: vnum %u non-S.", vnum ); abort( ); } pMobIndex->level = fread_number( fp ); pMobIndex->level = URANGE(1, pMobIndex->level, 40); /* unused */ fread_number( fp ); pMobIndex->wear_locs = fread_number( fp ); pMobIndex->hitnodice = fread_number( fp ); fread_letter( fp ); /* 'd' */ pMobIndex->hitsizedice = fread_number( fp ); fread_letter( fp ); /* '+' */ pMobIndex->hitplus = fread_number( fp ); fread_number( fp ); fread_letter( fp ); /* 'd' */ fread_number( fp ); fread_letter( fp ); /* '+' */ fread_number( fp ); pMobIndex->gold = fread_number( fp ); pMobIndex->race = fread_number( fp ); pMobIndex->position = fread_number( fp ); fread_number( fp ); /* Unused */ pMobIndex->sex = fread_number( fp ); pMobIndex->perm_str = 10; pMobIndex->perm_dex = 10; pMobIndex->perm_int = 10; pMobIndex->perm_wis = 10; pMobIndex->perm_cha = 10; pMobIndex->perm_con = 10; if (pMobIndex->race > RACE_NONE) { if (race_table[pMobIndex->race].nonability[STAT_STR]) pMobIndex->perm_str = 0; else pMobIndex->perm_str += race_table[pMobIndex->race].race_mod[0]; if (race_table[pMobIndex->race].nonability[STAT_DEX]) pMobIndex->perm_dex = 0; else pMobIndex->perm_dex += race_table[pMobIndex->race].race_mod[1]; if (race_table[pMobIndex->race].nonability[STAT_CON]) pMobIndex->perm_con = 0; else pMobIndex->perm_con += race_table[pMobIndex->race].race_mod[2]; if (race_table[pMobIndex->race].nonability[STAT_INT]) pMobIndex->perm_int = 0; else pMobIndex->perm_int += race_table[pMobIndex->race].race_mod[3]; if (race_table[pMobIndex->race].nonability[STAT_WIS]) pMobIndex->perm_wis = 0; else pMobIndex->perm_wis += race_table[pMobIndex->race].race_mod[4]; if (race_table[pMobIndex->race].nonability[STAT_CHA]) pMobIndex->perm_cha = 0; else pMobIndex->perm_cha += race_table[pMobIndex->race].race_mod[5]; } } if (pMobIndex->size == 0) pMobIndex->size = race_table[pMobIndex->race].size; pMobIndex->mclass[pMobIndex->class] = pMobIndex->level; if (IS_SET(pMobIndex->affected_by, AFF_ETHEREAL)) { SET_BIT(pMobIndex->act, ACT_MOBINVIS); REMOVE_BIT(pMobIndex->affected_by, AFF_ETHEREAL); } while (letter) { switch (letter = fread_letter(fp)) { case 'A': ALLOCMEM(paf, AFFECT_DATA, 1); paf->type = 0; paf->duration = -1; paf->location = fread_number( fp ); paf->modifier = fread_number( fp ); paf->bitvector = fread_number( fp ); paf->bittype = paf->bitvector ? AFFECT_TO_CHAR : AFFECT_TO_NONE; paf->level = pMobIndex->level; paf->caster = STRALLOC("None"); LINK(paf, pMobIndex->first_affect, pMobIndex->last_affect, next, prev); mud->top_affect++; break; case 'C': pMobIndex->mclass[fread_number( fp )] = fread_number( fp ); break; case 'E': ALLOCMEM(ed, EXTRA_DESCR_DATA, 1); ed->keyword = fread_string( fp ); ed->description = fread_string( fp ); LINK(ed, pMobIndex->first_extradesc, pMobIndex->last_extradesc, next, prev); mud->top_ed++; break; case 'M': pMobIndex->reset_msg = fread_string( fp ); break; case 'O': pMobIndex->load_eq[fread_number( fp )] = fread_number( fp ); break; case 'X': pMobIndex->attacks[fread_number( fp )] = fread_number( fp ); break; case '%': value = fread_number( fp ); value = URANGE(0, value, 99); sn = skill_lookup( fread_string( fp ) ); if (sn < 0) { bug("load_mobiles: %d - unknown skill.", vnum); break; } pMobIndex->learned[sn] = value; break; case '>': ungetc(letter, fp); mprog_read_programs(fp, pMobIndex); letter = FALSE; break; default: ungetc(letter, fp); letter = FALSE; break; } } // Add sorcerer "multiclass" to dragon race if (race_table[pMobIndex->race].parent_race == RACE_DRAGON && pMobIndex->mclass[CLASS_SORCERER] == 0) pMobIndex->mclass[CLASS_SORCERER] = dragon_caster_level(pMobIndex->level); if (!pMobIndex->unique && pMobIndex->race && pMobIndex->level > race_table[pMobIndex->race].hit_dice) advance_mobile(pMobIndex); mud->top_mob_index++; } pop_call(); return; } /* Snarf an obj section. */ void load_objects( FILE *fp ) { OBJ_PROG *prg; OBJ_INDEX_DATA *pObjIndex; EXTRA_DESCR_DATA *ed; AFFECT_DATA *paf; char buf[256], *pt; int vnum, val, sn; char letter; push_call("load_object(%p)",fp); while (TRUE) { letter = fread_letter( fp ); if ( letter != '#' ) { bug( "Load_objects: # not found.", 0 ); abort( ); } vnum = fread_number( fp ); if ( vnum == 0 ) { break; } if (vnum < 1 || vnum >= MAX_VNUM) { bug("load_objects: vnum %u out of range.", vnum); abort( ); } if (get_obj_index(vnum) != NULL) { bug("load_objects: vnum %u duplicated.", vnum); abort(); } ALLOCMEM(pObjIndex, OBJ_INDEX_DATA, 1); pObjIndex->vnum = vnum; if (area_load->low_o_vnum > vnum) { area_load->low_o_vnum = vnum; } if (vnum > area_load->hi_o_vnum) { area_load->hi_o_vnum = vnum; } obj_index[ vnum ] = pObjIndex; pObjIndex->area = area_load; pt = fread_string( fp ); /* Add I### system to names */ sprintf( buf, "i%u", vnum ); if (strstr(pt, buf) == NULL) { sprintf( buf, "%s i%u", pt, vnum ); } else { strcpy( buf, pt ); } STRFREE (pt ); pObjIndex->name = STRALLOC(buf); pObjIndex->short_descr = fread_string( fp ); pObjIndex->long_descr = fread_string( fp ); pObjIndex->description = fread_string( fp ); pObjIndex->item_type = fread_number( fp ); pObjIndex->extra_flags = fread_number( fp ); pObjIndex->wear_flags = fread_number( fp ); if (area_load->version >= 4) { /* unused */ fread_number( fp ); pObjIndex->material = fread_number( fp ); pObjIndex->hit_points = fread_number( fp ); pObjIndex->size = fread_number( fp ); } pObjIndex->value[0] = fread_number( fp ); pObjIndex->value[1] = fread_number( fp ); pObjIndex->value[2] = fread_number( fp ); pObjIndex->value[3] = fread_number( fp ); if (area_load->version > 2) { pObjIndex->value[4] = fread_number( fp ); pObjIndex->value[5] = fread_number( fp ); pObjIndex->value[6] = fread_number( fp ); pObjIndex->value[7] = fread_number( fp ); } pObjIndex->weight = fread_number(fp); pObjIndex->cost = abs(fread_number( fp )); pObjIndex->level = fread_number( fp ); pObjIndex->attack_string = STRDUPE(str_empty); pObjIndex->id_name = STRDUPE(str_empty); pObjIndex->id_descr = STRDUPE(str_empty); /* added to fix new wear size value for armor */ if (pObjIndex->item_type == ITEM_ARMOR && pObjIndex->value[3] <= 0) pObjIndex->value[3] = SIZE_MEDIUM; while (letter) { switch (letter = fread_letter(fp)) { case 'A': ALLOCMEM(paf, AFFECT_DATA, 1); paf->type = 0; paf->duration = -1; paf->location = fread_number( fp ); paf->modifier = fread_number( fp ); if (area_load->version != 2) paf->bitvector = fread_number( fp ); paf->bittype = paf->bitvector ? AFFECT_TO_CHAR : AFFECT_TO_NONE; paf->level = pObjIndex->level; paf->caster = STRALLOC("None"); LINK(paf, pObjIndex->first_affect, pObjIndex->last_affect, next, prev); SET_BIT(pObjIndex->extra_flags, ITEM_MAGIC); mud->top_affect++; break; case 'C': STRFREE(pObjIndex->attack_string); pObjIndex->attack_string = fread_string( fp ); pObjIndex->class_flags = fread_number( fp ); break; case 'E': ALLOCMEM(ed, EXTRA_DESCR_DATA, 1); ed->keyword = fread_string( fp ); ed->description = fread_string( fp ); LINK(ed, pObjIndex->first_extradesc, pObjIndex->last_extradesc, next, prev); mud->top_ed++; break; case 'I': STRFREE(pObjIndex->id_name); pObjIndex->id_name = fread_string( fp ); STRFREE(pObjIndex->id_descr); pObjIndex->id_descr = fread_string( fp ); break; // this remnant of MRMud left to simply allow loading of old areas case 'P': prg = load_object_program(fp); break; case '>': ungetc(letter, fp); oprog_read_programs(fp, pObjIndex); letter = FALSE; break; // added to deprecate skill bitvectors for scrolls etc. - Kregor case 'V': val = fread_number( fp ); if ((sn = skill_lookup(fread_word( fp ))) == -1) { bug("load_objects: %u bad skill for value %d.", vnum, val); } pObjIndex->value[val] = sn; break; default: ungetc(letter, fp); letter = FALSE; break; } } if (obj_index_cost(pObjIndex) != -1) pObjIndex->cost = obj_index_cost(pObjIndex); fix_materials(pObjIndex); fix_sizes(pObjIndex); if (load_obj_weight(pObjIndex) != -1) pObjIndex->weight = load_obj_weight(pObjIndex); load_obj_hit(pObjIndex); mud->top_obj_index++; } pop_call(); return; } /* Snarf a reset section. */ void load_resets( FILE *fp ) { RESET_DATA *pReset; char letter; push_call("load_resets(%p)",fp); if (area_load == NULL) { bug( "Load_resets: no #AREA seen yet.", 0 ); abort( ); } while (TRUE) { if ((letter = fread_letter(fp)) == 'S') { break; } ALLOCMEM(pReset, RESET_DATA, 1); pReset->command = letter; if (area_load->version <= 2 || area_load->version == 99) // Get rid of MERC extraneous number - Kregor fread_number( fp ); pReset->arg1 = fread_number( fp ); pReset->arg2 = fread_number( fp ); if ((area_load->version < 4 || area_load->version == 99) && letter != 'D') // pre Mud20 1.0 used as a repop limit, not percentage - Kregor pReset->arg2 = 100; if ((area_load->version <= 2 || area_load->version == 99) && letter == 'G') // Other bases leave this number out - Kregor pReset->arg3 = 0; else pReset->arg3 = fread_number( fp ); fread_to_eol( fp ); LINK(pReset, area_load->first_reset, area_load->last_reset, next, prev); mud->top_reset++; /* Add container references while at it - Scandum */ switch ( letter ) { case 'P': pReset->container = get_reset_from_obj(pReset); break; case 'T': pReset->container = get_reset_from_trap(pReset); break; case 'G': case 'E': pReset->container = get_reset_from_mob(pReset); break; } } pop_call(); return; } /* Snarf a room section. And counting occurances of things. */ void load_rooms( FILE *fp ) { ROOM_INDEX_DATA *pRoomIndex; EXIT_DATA *pExit; EXTRA_DESCR_DATA *ed; int vnum; bool door; char letter; push_call("load_rooms(%p)",fp); if (area_load == NULL) { bug( "Load_resets: no #AREA seen yet.", 0 ); abort( ); } while (TRUE) { letter = fread_letter( fp ); if (letter != '#') { bug( "Load_rooms: # not found.", 0 ); abort( ); } vnum = fread_number(fp); if (vnum == 0) { break; } if (vnum < 0 || vnum >= MAX_VNUM) { bug("load_rooms: vnum %u out of range.", vnum); abort( ); } if (room_index[vnum] != NULL && vnum < MAX_VNUM) { bug("load_rooms: vnum %u duplicated.", vnum); abort( ); } ALLOCMEM(pRoomIndex, ROOM_INDEX_DATA, 1); if (vnum < area_load->low_r_vnum) { area_load->low_r_vnum = vnum; } if (vnum > area_load->hi_r_vnum) { area_load->hi_r_vnum = vnum; } pRoomIndex->area = area_load; pRoomIndex->vnum = vnum; room_index[vnum] = pRoomIndex; pRoomIndex->name = fread_string( fp ); pRoomIndex->description = fread_string( fp ); pRoomIndex->listen_desc = STRDUPE( str_empty ); pRoomIndex->night_desc = STRDUPE( str_empty ); pRoomIndex->creator_pvnum = fread_number( fp ); pRoomIndex->room_flags = fread_number( fp ); pRoomIndex->sector_type = fread_number( fp ); if (area_load->version >= 4) { /* not used */ fread_number( fp ); /* not used */ fread_number( fp ); /* not used */ fread_number( fp ); } for (door = 0 ; door < MAX_LAST_LEFT ; door++) { pRoomIndex->last_left[door] = STRDUPE(str_empty); } while (letter) { switch (letter = fread_letter(fp)) { case 'S': letter = FALSE; break; case 'D': door = fread_number( fp ); if (door > 5) { bug("fread_rooms: vnum %u has bad door number.", vnum); abort( ); } ALLOCMEM(pExit, EXIT_DATA, 1); pExit->description = fread_string( fp ); pExit->keyword = fread_string( fp ); pExit->exit_info = fread_number( fp ); pExit->key = fread_number( fp ); pExit->vnum = fread_number( fp ); if (area_load->version >= 4) { pExit->exit_size = fread_number( fp ); pExit->climb_dc = fread_number( fp ); pExit->fall_dist = fread_number( fp ); } pExit->to_room = pExit->vnum; pRoomIndex->exit[door] = pExit; mud->top_exit++; break; case 'E': ALLOCMEM(ed, EXTRA_DESCR_DATA, 1); ed->keyword = fread_string( fp ); ed->description = fread_string( fp ); LINK(ed, pRoomIndex->first_extradesc, pRoomIndex->last_extradesc, next, prev); mud->top_ed++; break; case 'L': /* listen desc - Kregor */ pRoomIndex->listen_desc = fread_string( fp ); break; case 'N': /* night desc - Kregor */ pRoomIndex->night_desc = fread_string( fp ); break; case '>': ungetc(letter, fp); rprog_read_programs(fp, pRoomIndex); // letter = FALSE; break; default: bug("Load_rooms: vnum %u uses bad flag '%c'.", vnum, letter); abort(); } } mud->top_room++; } pop_call(); return; } /* Snarf a shop section. */ void load_shops( FILE *fp ) { SHOP_DATA *pShop; MOB_INDEX_DATA *pMobIndex; bool iTrade; push_call("load_shops(%p)",fp); while (TRUE) { ALLOCMEM( pShop, SHOP_DATA, 1); pShop->keeper = fread_number( fp ); if (pShop->keeper == 0) { FREEMEM(pShop); break; } if (get_mob_index(pShop->keeper) == NULL) { bug("load_shop: Mobile %d does not exist", pShop->keeper); abort(); } for (iTrade = 0 ; iTrade < MAX_TRADE ; iTrade++) { pShop->buy_type[iTrade] = fread_number( fp ); } pShop->shop_flags = fread_number( fp ); if (area_load->version < 4 || area_load->version == 99) pShop->shop_flags = 0; pShop->profit_buy = fread_number( fp ); pShop->profit_buy = UMAX(pShop->profit_buy, 100); pShop->profit_sell = fread_number( fp ); pShop->profit_sell = UMIN(pShop->profit_sell, 50); pShop->open_hour = fread_number( fp ); pShop->close_hour = fread_number( fp ); fread_to_eol( fp ); pMobIndex = get_mob_index( pShop->keeper ); pMobIndex->pShop = pShop; LINK(pShop, mud->f_shop, mud->l_shop, next, prev); mud->top_shop++; } pop_call(); return; } /* Snarf a inn section. */ void load_inns( FILE *fp ) { INN_DATA *pInn; MOB_INDEX_DATA *pMobIndex; int iRoom; push_call("load_inns(%p)",fp); while (TRUE) { ALLOCMEM( pInn, INN_DATA, 1); pInn->keeper = fread_number( fp ); if (pInn->keeper == 0) { FREEMEM(pInn); break; } if (get_mob_index(pInn->keeper) == NULL) { bug("load_inn: Mobile %d does not exist", pInn->keeper); abort(); } for (iRoom = 0 ; iRoom < MAX_INN_ROOMS ; iRoom++) { pInn->room[iRoom] = fread_number( fp ); if (pInn->room[iRoom] > 0 && room_index[pInn->room[iRoom]] == NULL) { bug("load_inn: Room %d does not exist", pInn->room); abort(); } } for (iRoom = 0 ; iRoom < MAX_INN_ROOMS ; iRoom++) { pInn->rent[iRoom] = fread_number( fp ); } fread_number( fp ); pInn->open_hour = fread_number( fp ); pInn->close_hour = fread_number( fp ); pInn->shop_flags = fread_number( fp ); fread_to_eol( fp ); pMobIndex = get_mob_index( pInn->keeper ); pMobIndex->pInn = pInn; LINK(pInn, mud->f_inn, mud->l_inn, next, prev); mud->top_inn++; } pop_call(); return; } /* Snarf a stable section. */ void load_stables( FILE *fp ) { STABLE_DATA *pStable; MOB_INDEX_DATA *pMobIndex; push_call("load_stables(%p)",fp); while (TRUE) { ALLOCMEM( pStable, STABLE_DATA, 1); pStable->keeper = fread_number( fp ); if (pStable->keeper == 0) { FREEMEM(pStable); break; } if (get_mob_index(pStable->keeper) == NULL) { bug("load_stable: Mobile %d does not exist", pStable->keeper); abort(); } pStable->room = fread_number( fp ); if (room_index[pStable->room] == NULL) { bug("load_stable: Room %d does not exist", pStable->room); abort(); } pStable->shop_flags = fread_number( fp ); pStable->rent = fread_number( fp ); pStable->open_hour = fread_number( fp ); pStable->close_hour = fread_number( fp ); fread_to_eol( fp ); pMobIndex = get_mob_index( pStable->keeper ); pMobIndex->pStable = pStable; LINK(pStable, mud->f_stable, mud->l_stable, next, prev); mud->top_stable++; } pop_call(); return; } /* Snarf spec proc declarations. */ void load_specials( FILE *fp ) { int vnum; MOB_INDEX_DATA *pMobIndex; char letter; push_call("load_special(%p)",fp); while (TRUE) { switch (letter = fread_letter(fp)) { default: bug("load_specials: letter '%c' not MSO.", letter); abort( ); case 'S': pop_call(); return; case 'M': vnum = fread_number ( fp ); pMobIndex = get_mob_index ( vnum ); pMobIndex->spec_fun = spec_lookup ( fread_word ( fp ) ); if (pMobIndex->spec_fun == NULL) { log_printf("load_specials: 'M': vnum %u.", pMobIndex->vnum ); } break; } fread_to_eol( fp ); } pop_call(); return; } /* Conversion for FKMud/Smaug repair shops. */ void load_repairs( FILE *fp ) { int vnum, skill; MOB_INDEX_DATA *pMobIndex; push_call("load_shops(%p)",fp); while (TRUE) { if ((vnum = fread_number( fp )) == 0) { break; } if ((pMobIndex = get_mob_index(vnum)) == NULL) { bug("load_shop: Mobile %d does not exist", vnum); abort(); } // grabs each item type repair and converts to Mud20 skill switch (fread_number( fp )) { case ITEM_ARMOR: skill = gsn_craft_armor; break; case ITEM_WEAPON: skill = gsn_craft_weapons; break; case ITEM_TREASURE: skill = gsn_craft_jewelry; break; case ITEM_CONTAINER: skill = gsn_craft_leather; break; default: skill = -1; break; } if (skill != -1) { pMobIndex->learned[skill] = pMobIndex->level + 3; } switch (fread_number( fp )) { case ITEM_ARMOR: skill = gsn_craft_armor; break; case ITEM_WEAPON: skill = gsn_craft_weapons; break; case ITEM_TREASURE: skill = gsn_craft_jewelry; break; case ITEM_CONTAINER: skill = gsn_craft_leather; break; default: skill = -1; break; } if (skill != -1) { pMobIndex->learned[skill] = pMobIndex->level + 3; } // just get rid of substance type because it's assumed in Mud20 skill fread_number( fp ); // and the rest don't matter fread_to_eol( fp ); } pop_call(); return; } /* * Written to covert areas from my * previous server FKMud - Kregor */ void load_fk_mobiles( FILE *fp ) { MOB_INDEX_DATA *pMobIndex; EXTRA_DESCR_DATA *ed; AFFECT_DATA *paf; char buf[256], *pt; int vnum, sn, value; char letter; push_call("load_mobiles(%p)",fp); while (TRUE) { letter = fread_letter( fp ); if (letter != '#') { bug( "Load_mobiles: # not found.", 0 ); abort( ); } vnum = fread_number( fp ); if (vnum == 0) { break; } if (vnum < 1 || vnum >= MAX_VNUM) { bug("load_mobiles: vnum %u out of range.", vnum); abort( ); } if (get_mob_index(vnum) != NULL) { bug("load_mobiles: vnum %u duplicated.", vnum); abort( ); } ALLOCMEM(pMobIndex, MOB_INDEX_DATA, 1); pMobIndex->vnum = vnum; mob_index[vnum] = pMobIndex; pMobIndex->area = area_load; if (IS_SET(mud->flags, MUD_EMUD_BOOTDB)) { if (area_load->low_m_vnum > vnum) { area_load->low_m_vnum = vnum; } if (vnum > area_load->hi_m_vnum) { area_load->hi_m_vnum = vnum; } } pt = fread_string( fp ); /* Add M### system to names */ sprintf( buf, "m%u", vnum ); if (strstr(pt, buf) == NULL) { sprintf( buf, "%s m%u", pt, vnum ); } else { strcpy( buf, pt ); } STRFREE (pt); pMobIndex->player_name = STRALLOC(buf); pMobIndex->short_descr = fread_string( fp ); pMobIndex->long_descr = fread_string( fp ); pMobIndex->description = fread_string( fp ); pMobIndex->unique = FALSE; letter = fread_letter( fp ); if (letter == 'U') pMobIndex->unique = TRUE; else if (letter == 'S') pMobIndex->unique = FALSE; else { bug( "Load_mobiles: vnum %u not U or S.", vnum ); abort( ); } pMobIndex->level = fread_number( fp ); pMobIndex->class = fread_number( fp ); pMobIndex->race = fread_number( fp ); pMobIndex->sex = fread_number( fp ); pMobIndex->position = fread_number( fp ); pMobIndex->god = fread_number( fp ); pMobIndex->act = fread_number( fp ); // Convert 50 level scale to 20 - Kregor if (!IS_SET(pMobIndex->act, ACT_MOBINVIS)) pMobIndex->level = UMAX(1, pMobIndex->level / 2); if (!pMobIndex->unique) { if (pMobIndex->race <= RACE_NONE) { bug( "Load_mobiles: no race set on S mobile.", vnum ); pMobIndex->race = RACE_HUMAN; } if (pMobIndex->class != CLASS_MONSTER && pMobIndex->class < MAX_CLASS) pMobIndex->hitsizedice = class_table[pMobIndex->class].hp_max; else if (pMobIndex->race > RACE_NONE) pMobIndex->hitsizedice = race_type_table[race_table[pMobIndex->race].type].hit_die; else { bug( "Load_mobiles: neither class nor race hit die.", vnum ); pMobIndex->hitsizedice = 8; } pMobIndex->alignment = race_table[pMobIndex->race].alignment; pMobIndex->ethos = race_table[pMobIndex->race].ethos; pMobIndex->gold = 0; // need to add means to determine standard random gold /* * assign stats based on class pri and sec stats * These routines effectively gives standard NPCs * an elite array of abilities - Kregor */ if (pMobIndex->class > CLASS_MONSTER) { int class = pMobIndex->class; if (class_table[class].attr_prime == APPLY_STR) pMobIndex->perm_str = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[0]; else if (class_table[class].attr_second == APPLY_STR) pMobIndex->perm_str = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[0]; else pMobIndex->perm_str = best_three_of_four() + race_table[pMobIndex->race].race_mod[0]; if (class_table[class].attr_prime == APPLY_DEX) pMobIndex->perm_dex = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[1]; else if (class_table[class].attr_second == APPLY_DEX) pMobIndex->perm_dex = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[1]; else pMobIndex->perm_dex = best_three_of_four() + race_table[pMobIndex->race].race_mod[1]; if (class_table[class].attr_prime == APPLY_CON) pMobIndex->perm_con = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[2]; else if (class_table[class].attr_second == APPLY_CON) pMobIndex->perm_con = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[2]; else pMobIndex->perm_con = best_three_of_four() + race_table[pMobIndex->race].race_mod[2]; if (class_table[class].attr_prime == APPLY_INT) pMobIndex->perm_int = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[3]; else if (class_table[class].attr_second == APPLY_INT) pMobIndex->perm_int = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[3]; else pMobIndex->perm_int = best_three_of_four() + race_table[pMobIndex->race].race_mod[3]; if (class_table[class].attr_prime == APPLY_WIS) pMobIndex->perm_wis = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[4]; else if (class_table[class].attr_second == APPLY_WIS) pMobIndex->perm_wis = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[4]; else pMobIndex->perm_wis = best_three_of_four() + race_table[pMobIndex->race].race_mod[4]; if (class_table[class].attr_prime == APPLY_CHA) pMobIndex->perm_cha = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[5]; else if (class_table[class].attr_second == APPLY_CHA) pMobIndex->perm_cha = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[5]; else pMobIndex->perm_cha = best_three_of_four() + race_table[pMobIndex->race].race_mod[5]; } else { pMobIndex->perm_str = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[0]; pMobIndex->perm_int = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[1]; pMobIndex->perm_wis = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[2]; pMobIndex->perm_dex = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[3]; pMobIndex->perm_con = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[4]; pMobIndex->perm_cha = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[5]; } // zero out nonabilities by race if (race_table[pMobIndex->race].nonability[STAT_STR]) pMobIndex->perm_str = 0; if (race_table[pMobIndex->race].nonability[STAT_DEX]) pMobIndex->perm_dex = 0; if (race_table[pMobIndex->race].nonability[STAT_CON]) pMobIndex->perm_con = 0; if (race_table[pMobIndex->race].nonability[STAT_INT]) pMobIndex->perm_int = 0; if (race_table[pMobIndex->race].nonability[STAT_WIS]) pMobIndex->perm_wis = 0; if (race_table[pMobIndex->race].nonability[STAT_CHA]) pMobIndex->perm_cha = 0; pMobIndex->nat_armor = race_table[pMobIndex->race].nat_armor; pMobIndex->wear_locs = race_table[pMobIndex->race].wear_locs; pMobIndex->size = race_table[pMobIndex->race].size; pMobIndex->understands = race_table[pMobIndex->race].understands; pMobIndex->speaks = race_table[pMobIndex->race].speaks; } else { pMobIndex->affected_by = fread_number( fp ); pMobIndex->armor_type = fread_number( fp ); /*unused*/ fread_number( fp ); /* 'd' */ fread_letter( fp ); if (pMobIndex->class > CLASS_MONSTER && pMobIndex->class < MAX_CLASS) { fread_number( fp ); pMobIndex->hitsizedice = class_table[pMobIndex->class].hp_max; } else if (pMobIndex->race > RACE_NONE) { fread_number( fp ); pMobIndex->hitsizedice = race_type_table[race_table[pMobIndex->race].type].hit_die; } else { pMobIndex->hitsizedice = fread_number( fp ); } /* '+' */ fread_letter( fp ); pMobIndex->hitplus = fread_number( fp ); pMobIndex->alignment = fread_number( fp ); pMobIndex->perm_str = fread_number( fp ); pMobIndex->perm_int = fread_number( fp ); pMobIndex->perm_wis = fread_number( fp ); pMobIndex->perm_dex = fread_number( fp ); pMobIndex->perm_con = fread_number( fp ); pMobIndex->perm_cha = fread_number( fp ); fread_number( fp ); // read and discard LUCK stat fread_number( fp ); // unused field fread_number( fp ); // unused field fread_number( fp ); // unused field fread_number( fp ); // unused field fread_number( fp ); // unused field pMobIndex->speaks = fread_number( fp ); pMobIndex->understands = fread_number( fp ); /* Unused */ fread_number( fp ); /* Unused */ fread_number( fp ); /* Unused */ fread_number( fp ); } if (pMobIndex->size == 0) pMobIndex->size = race_table[pMobIndex->race].size; pMobIndex->mclass[pMobIndex->class] = pMobIndex->level; while (letter) { switch (letter = fread_letter(fp)) { case 'A': ALLOCMEM(paf, AFFECT_DATA, 1); paf->type = 0; paf->duration = -1; paf->location = fread_number( fp ); paf->modifier = fread_number( fp ); paf->bittype = AFFECT_TO_NONE; paf->level = pMobIndex->level; paf->caster = STRALLOC("None"); LINK(paf, pMobIndex->first_affect, pMobIndex->last_affect, next, prev); mud->top_affect++; break; case 'E': ALLOCMEM(ed, EXTRA_DESCR_DATA, 1); ed->keyword = fread_string( fp ); ed->description = fread_string( fp ); LINK(ed, pMobIndex->first_extradesc, pMobIndex->last_extradesc, next, prev); mud->top_ed++; break; case '%': value = fread_number( fp ); value = URANGE(0, value, 99); fread_number( fp ); // unused sn = skill_lookup( fread_string( fp ) ); if (sn < 0) { break; } if (skill_table[sn].skilltype != FSKILL_FEAT && skill_table[sn].skilltype != FSKILL_SKILL && skill_table[sn].skilltype != FSKILL_SPELL && skill_table[sn].skilltype != FSKILL_CRAFT && skill_table[sn].skilltype != FSKILL_KNOWLEDGE) { break; } pMobIndex->learned[sn] = value; break; case '>': ungetc(letter, fp); mprog_read_programs(fp, pMobIndex); letter = FALSE; break; default: ungetc(letter, fp); letter = FALSE; break; } } // Add sorcerer "multiclass" to dragon race if (race_table[pMobIndex->race].parent_race == RACE_DRAGON && pMobIndex->mclass[CLASS_SORCERER] == 0) pMobIndex->mclass[CLASS_SORCERER] = dragon_caster_level(pMobIndex->level); if (!pMobIndex->unique && pMobIndex->race && pMobIndex->level > race_table[pMobIndex->race].hit_dice) advance_mobile(pMobIndex); mud->top_mob_index++; } pop_call(); return; } void load_fk_objects( FILE *fp ) { OBJ_INDEX_DATA *pObjIndex; EXTRA_DESCR_DATA *ed; AFFECT_DATA *paf; char buf[256], *pt; int vnum; char letter; push_call("load_object(%p)",fp); while (TRUE) { letter = fread_letter( fp ); if ( letter != '#' ) { bug( "Load_objects: # not found.", 0 ); abort( ); } vnum = fread_number( fp ); if ( vnum == 0 ) { break; } if (vnum < 1 || vnum >= MAX_VNUM) { bug("load_objects: vnum %u out of range.", vnum); abort( ); } if (get_obj_index(vnum) != NULL) { bug("load_objects: vnum %u duplicated.", vnum); abort(); } ALLOCMEM(pObjIndex, OBJ_INDEX_DATA, 1); pObjIndex->vnum = vnum; if (area_load->low_o_vnum > vnum) { area_load->low_o_vnum = vnum; } if (vnum > area_load->hi_o_vnum) { area_load->hi_o_vnum = vnum; } obj_index[ vnum ] = pObjIndex; pObjIndex->area = area_load; pt = fread_string( fp ); /* Add i### system to names */ sprintf( buf, "i%u", vnum ); if (strstr(pt, buf) == NULL) { sprintf( buf, "%s i%u", pt, vnum ); } else { strcpy( buf, pt ); } STRFREE (pt); pObjIndex->name = STRALLOC(buf); pObjIndex->short_descr = fread_string( fp ); pObjIndex->long_descr = fread_string( fp ); pObjIndex->description = fread_string( fp ); pObjIndex->item_type = fread_number( fp ); pObjIndex->extra_flags = fread_number( fp ); pObjIndex->wear_flags = fread_number( fp ); /* unused */ fread_number( fp ); // was quality in FKMud pObjIndex->material = fread_number( fp ); pObjIndex->hit_points = fread_number( fp ); pObjIndex->size = fread_number( fp ); pObjIndex->value[0] = fread_number( fp ); pObjIndex->value[1] = fread_number( fp ); pObjIndex->value[2] = fread_number( fp ); pObjIndex->value[3] = fread_number( fp ); pObjIndex->value[4] = fread_number( fp ); pObjIndex->value[5] = fread_number( fp ); pObjIndex->attack_string = STRDUPE(str_empty); pObjIndex->id_name = STRDUPE(str_empty); pObjIndex->id_descr = STRDUPE(str_empty); /* added to fix new wear size value for armor */ if (pObjIndex->item_type == ITEM_ARMOR && pObjIndex->value[3] <= 0) pObjIndex->value[3] = SIZE_MEDIUM; while (letter) { switch (letter = fread_letter(fp)) { case 'A': ALLOCMEM(paf, AFFECT_DATA, 1); paf->type = 0; paf->duration = -1; paf->location = fread_number( fp ); paf->modifier = fread_number( fp ); paf->bittype = AFFECT_TO_NONE; paf->level = obj_level_estimate(pObjIndex); paf->caster = STRALLOC("None"); LINK(paf, pObjIndex->first_affect, pObjIndex->last_affect, next, prev); SET_BIT(pObjIndex->extra_flags, ITEM_MAGIC); mud->top_affect++; break; case 'E': ALLOCMEM(ed, EXTRA_DESCR_DATA, 1); ed->keyword = fread_string( fp ); ed->description = fread_string( fp ); LINK(ed, pObjIndex->first_extradesc, pObjIndex->last_extradesc, next, prev); mud->top_ed++; break; case 'I': STRFREE(pObjIndex->id_name); pObjIndex->id_name = fread_line( fp ); STRFREE(pObjIndex->id_descr); pObjIndex->id_descr = fread_string( fp ); break; // this remnant of MRMud left to simply allow loading of old areas case '>': ungetc(letter, fp); oprog_read_programs(fp, pObjIndex); letter = FALSE; break; default: ungetc(letter, fp); letter = FALSE; break; } } if (obj_index_cost(pObjIndex) != -1) pObjIndex->cost = obj_index_cost(pObjIndex); fix_materials(pObjIndex); fix_sizes(pObjIndex); if (load_obj_weight(pObjIndex) != -1) pObjIndex->weight = load_obj_weight(pObjIndex); load_obj_hit(pObjIndex); mud->top_obj_index++; } pop_call(); return; } /* * Read in FKMud/Smaug weather stat, * convert into Mud20 stats - Kregor */ void load_fk_weather( FILE * fp ) { push_call("load_weather(%p)",fp); area_load->weather_info->temp_summer = fread_number(fp) * 12; area_load->weather_info->temp_winter = area_load->weather_info->temp_summer / 2; area_load->weather_info->temp_daily = (area_load->weather_info->temp_summer - area_load->weather_info->temp_summer) / 2; area_load->weather_info->wet_scale = fread_number(fp); pop_call(); return; } void load_fk_rooms( FILE *fp ) { ROOM_INDEX_DATA *pRoomIndex; EXIT_DATA *pExit; EXTRA_DESCR_DATA *ed; int vnum; bool door; char letter; push_call("load_rooms(%p)",fp); if (area_load == NULL) { bug( "Load_resets: no #AREA seen yet.", 0 ); abort( ); } while (TRUE) { letter = fread_letter( fp ); if (letter != '#') { bug( "Load_rooms: # not found.", 0 ); abort( ); } vnum = fread_number(fp); if (vnum == 0) { break; } if (vnum < 0 || vnum >= MAX_VNUM) { bug("load_rooms: vnum %u out of range.", vnum); abort( ); } if (room_index[vnum] != NULL && vnum < MAX_VNUM) { bug("load_rooms: vnum %u duplicated.", vnum); abort( ); } ALLOCMEM(pRoomIndex, ROOM_INDEX_DATA, 1); if (vnum < area_load->low_r_vnum) { area_load->low_r_vnum = vnum; } if (vnum > area_load->hi_r_vnum) { area_load->hi_r_vnum = vnum; } pRoomIndex->area = area_load; pRoomIndex->vnum = vnum; room_index[vnum] = pRoomIndex; pRoomIndex->name = fread_string( fp ); pRoomIndex->description = fread_string( fp ); pRoomIndex->listen_desc = STRDUPE( str_empty ); pRoomIndex->night_desc = STRDUPE( str_empty ); /* not used */ fread_number( fp ); pRoomIndex->room_flags = fread_number( fp ); pRoomIndex->sector_type = fread_number( fp ); /* not used */ fread_number( fp ); /* not used */ fread_number( fp ); /* not used */ fread_number( fp ); for (door = 0 ; door < MAX_LAST_LEFT ; door++) { pRoomIndex->last_left[door] = STRDUPE(str_empty); } while (letter) { switch (letter = fread_letter(fp)) { case 'S': letter = FALSE; break; case 'D': door = fread_number( fp ); if (door > 5) { bug("fread_rooms: vnum %u has bad door number.", vnum); abort( ); } ALLOCMEM(pExit, EXIT_DATA, 1); pExit->description = fread_string( fp ); pExit->keyword = fread_string( fp ); pExit->exit_info = fread_number( fp ); pExit->key = fread_number( fp ); pExit->vnum = fread_number( fp ); /* not used */ fread_number( fp ); pExit->to_room = pExit->vnum; pRoomIndex->exit[door] = pExit; mud->top_exit++; break; case 'E': ALLOCMEM(ed, EXTRA_DESCR_DATA, 1); ed->keyword = fread_string( fp ); ed->description = fread_string( fp ); LINK(ed, pRoomIndex->first_extradesc, pRoomIndex->last_extradesc, next, prev); mud->top_ed++; break; case '>': ungetc(letter, fp); rprog_read_programs(fp, pRoomIndex); // letter = FALSE; break; default: bug("Load_rooms: vnum %u uses bad flag '%c'.", vnum, letter); abort(); } } mud->top_room++; } pop_call(); return; } /* This procedure is responsible for reading any in_file MOBprograms. */ void mprog_read_programs( FILE *fp, MOB_INDEX_DATA *pMobIndex) { MPROG_DATA *mprg; bool done = FALSE; push_call("mprog_read_programs(%p,%p)",fp,pMobIndex); if (fread_letter(fp) != '>') { bug("load_mobiles: vnum %d MOBPROG char", pMobIndex->vnum); abort( ); } ALLOCMEM(mprg, MPROG_DATA, 1); while (!done) { mprg->type = mprog_name_to_type(fread_word(fp)); switch ( mprg->type ) { case ERROR_PROG: bug("load_mobiles: vnum %u ERROR_PROG type.", pMobIndex->vnum); abort( ); break; default: SET_BIT(pMobIndex->progtypes, mprg->type); mprg->arglist = fread_string( fp ); fread_to_eol( fp ); mprg->comlist = fread_string( fp ); fread_to_eol( fp ); if (strstr(mprg->comlist, "$r") != NULL) { SET_BIT(mprg->flags, MPTRIGGER_RAND_PLR); } expand_mob_prog( pMobIndex, NULL, NULL, mprg ); /* Tokenize Mobprog */ LINK(mprg, pMobIndex->first_prog, pMobIndex->last_prog, next, prev); switch (fread_letter( fp ) ) { case '>': ALLOCMEM(mprg, MPROG_DATA, 1); break; case '|': fread_to_eol( fp ); done = TRUE; break; default: bug( "Load_mobiles: vnum %u bad MOBPROG.", pMobIndex->vnum ); abort(); break; } break; } } pop_call(); return; } /* This procedure is responsible for reading any in_file OBJprograms. */ void oprog_read_programs( FILE *fp, OBJ_INDEX_DATA *pObjIndex) { MPROG_DATA *mprg; bool done = FALSE; char letter; push_call("oprog_read_programs(%p,%p)",fp,pObjIndex); if ((letter = fread_letter(fp)) != '>') { bug("load_objects: vnum %d MOBPROG obj, letter is '%c'", pObjIndex->vnum, letter); abort( ); } ALLOCMEM(mprg, MPROG_DATA, 1); while (!done) { mprg->type = mprog_name_to_type(fread_word(fp)); switch ( mprg->type ) { case ERROR_PROG: bug("load_objects: vnum %u ERROR_PROG type.", pObjIndex->vnum); abort( ); break; default: SET_BIT(pObjIndex->progtypes, mprg->type); mprg->arglist = fread_string( fp ); fread_to_eol( fp ); mprg->comlist = fread_string( fp ); fread_to_eol( fp ); if (strstr(mprg->comlist, "$r") != NULL) { SET_BIT(mprg->flags, MPTRIGGER_RAND_PLR); } expand_mob_prog( NULL, pObjIndex, NULL, mprg ); /* Tokenize Mobprog */ LINK(mprg, pObjIndex->first_prog, pObjIndex->last_prog, next, prev); switch (fread_letter( fp ) ) { case '>': ALLOCMEM(mprg, MPROG_DATA, 1); break; case '|': fread_to_eol( fp ); done = TRUE; break; default: bug( "Load_objects: vnum %u bad MOBPROG obj.", pObjIndex->vnum ); abort(); break; } break; } } pop_call(); return; } /* This procedure is responsible for reading any in_file ROOMprograms. */ void rprog_read_programs( FILE *fp, ROOM_INDEX_DATA *pRoomIndex) { MPROG_DATA *mprg; bool done = FALSE; push_call("rprog_read_programs(%p,%p)",fp,pRoomIndex); if (fread_letter(fp) != '>') { bug("load_rooms: vnum %d MOBPROG obj", pRoomIndex->vnum); abort( ); } ALLOCMEM(mprg, MPROG_DATA, 1); while (!done) { mprg->type = mprog_name_to_type(fread_word(fp)); switch ( mprg->type ) { case ERROR_PROG: bug("load_mobiles: vnum %u ERROR_PROG type.", pRoomIndex->vnum); abort( ); break; default: SET_BIT(pRoomIndex->progtypes, mprg->type); mprg->arglist = fread_string( fp ); fread_to_eol( fp ); mprg->comlist = fread_string( fp ); fread_to_eol( fp ); if (strstr(mprg->comlist, "$r") != NULL) { SET_BIT(mprg->flags, MPTRIGGER_RAND_PLR); } expand_mob_prog( NULL, NULL, pRoomIndex, mprg ); /* Tokenize Mobprog */ LINK(mprg, pRoomIndex->first_prog, pRoomIndex->last_prog, next, prev); switch (fread_letter( fp ) ) { case '>': ALLOCMEM(mprg, MPROG_DATA, 1); break; case '|': fread_to_eol( fp ); done = TRUE; break; default: bug( "load_rooms: vnum %u bad MOBPROG room.", pRoomIndex->vnum ); abort(); break; } break; } } pop_call(); return; } void expand_mob_prog( MOB_INDEX_DATA *mind, OBJ_INDEX_DATA *obj, ROOM_INDEX_DATA *room, MPROG_DATA *mprog ) { char buf[MAX_INPUT_LENGTH]; char *pti, *pto; char level; push_call("expand_mob_prog(%p,%p,%p,%p)",mind,obj,room,mprog); pti = mprog->comlist; level = 0; while (*pti != '\0') { while (*pti == '\n' || *pti == '\r') { pti++; } if (*pti != '\0') { for (pto = buf ; *pti != '\r' && *pti != '\n' && *pti != '\0' ; pti++, pto++) { *pto = *pti; } *pto = '\0'; level = expand_line_mprog( mind, obj, room, mprog, buf, FALSE, level ); } } /* fixer_mprog will rebuild the old comlist - Scandum */ STRFREE(mprog->comlist); pop_call(); return; } char expand_line_mprog( MOB_INDEX_DATA *mind, OBJ_INDEX_DATA *obj, ROOM_INDEX_DATA *room, MPROG_DATA *mprog, char *line, bool iForce, char level ) { char *pti, *pto; char buf[MAX_INPUT_LENGTH]; char string[MAX_INPUT_LENGTH]; int type; void *func; int value; NPC_TOKEN *token; char achange, bchange; push_call("expand_line_mprog(%p,%p,%p,%p,%p,%p,%p)",mind,obj,room,mprog,line,iForce,level); func = NULL; for (pti = line ; *pti == ' ' ; pti++); for (pto = buf ; isalnum(*pti) ; pti++, pto++) { *pto = *pti; } *pto = '\0'; if (*buf == '\0') { pop_call(); return(level); } type = 0; /* Error type */ value = 0; achange = 0; bchange = 0; switch (buf[0]) { case 'b': if (!strcmp(buf, "break")) { type = MPTOKEN_BREAK; } break; case 'c': if (!strcmp(buf, "case")) { type = MPTOKEN_CASE; bchange = -1; achange = 1; } break; case 'd': if (!strcmp(buf, "default")) { type = MPTOKEN_DEFAULT; bchange = -1; achange = 1; } break; case 'e': if (!strcmp(buf, "else")) { type = MPTOKEN_ELSE; bchange =-1; achange = 1; } else if (!strcmp(buf, "endif")) { type = MPTOKEN_ENDIF; bchange =-1; } else if (!strcmp(buf, "endswitch")) { type = MPTOKEN_ENDSWITCH; bchange = -2; } break; case 'i': if (!strcmp(buf, "if")) { type = MPTOKEN_IF; achange = 1; } else if (!strcmp(buf, "ifnot")) { type = MPTOKEN_IFNOT; achange = 1; } break; case 'o': if (!strcmp(buf, "or")) { type = MPTOKEN_OR; bchange = -1; achange = 1; } else if (!strcmp(buf, "ornot")) { type = MPTOKEN_ORNOT; bchange = -1; achange = 1; } break; case 's': if (!strcmp(buf, "switch")) { type = MPTOKEN_SWITCH; achange = 2; } break; } if (type == 0) { if ((value = find_command(buf, MAX_LEVEL - 1)) >= 0) { func = (void *) cmd_table[value].do_fun; type = 2; } else if ((value = find_social(buf)) >= 0) { func = (void *) social_table[value].name; type = 1; } if (func == NULL) { log_printf("expand_line_mprog: unknown command: %s", buf); value = 0; type = 0; } } ALLOCMEM(token, NPC_TOKEN, 1); token->type = type; token->function = func; token->value = value; mud->top_mprog++; LINK(token, mprog->first_token, mprog->last_token, next, prev); level += bchange; /* before change */ if (level < 0) { level = 0; } token->level = level; level += achange; /* after change */ while (*pti == ' ') { pti++; } if (type == MPTOKEN_IF || type == MPTOKEN_OR || type == MPTOKEN_SWITCH) { pto = string; while (*pti != '(') { if (*pti == '\0') { if (mind) log_build_printf(mind->vnum, "ifchck syntax error"); else if (obj) log_build_printf(obj->vnum, "ifchck syntax error"); else if (room) log_build_printf(room->vnum, "ifchck syntax error"); token->type = 0; break; } else if (*pti == ' ') { pti++; } else { *pto++ = *pti++; } } *pto++ = ' '; while (*pti != ')') { if (*pti == '\0') { if (mind) log_build_printf(mind->vnum, "ifchck syntax error"); else if (obj) log_build_printf(obj->vnum, "ifchck syntax error"); else if (room) log_build_printf(room->vnum, "ifchck syntax error"); token->type = 0; break; } // else if (*pti == ' ') // { // pti++; // } else { *pto++ = *pti++; } } *pto++ = *pti++; while (*pti == ' ') { pti++; } if (*pti == '\0') { *pto = '\0'; token->string = STRALLOC(string); pop_call(); return level; } else { *pto++ = ' '; while (*pti != ' ' && !isalnum(*pti)) { if (*pti == '\0') { if (mind) log_build_printf(mind->vnum, "ifchck operator without value"); else if (obj) log_build_printf(obj->vnum, "ifchck operator without value"); else if (room) log_build_printf(room->vnum, "ifchck operator without value"); token->string = STRDUPE(str_empty); pop_call(); return level; } else { *pto++ = *pti++; } } while (*pti == ' ') { pti++; } *pto++ = ' '; while (*pti != '\0') /* took out *pto++ != ' ' right here */ { *pto++ = *pti++; } *pto = '\0'; token->string = STRALLOC(string); pop_call(); return level; } } for (pto = string ; *pti != '\0' && *pti != '\r' && *pti != '\n' ; pti++, pto++) { *pto = *pti; } *pto = '\0'; token->string = STRALLOC(string); pop_call(); return(level); } /* Repopulate areas periodically. */ void repop_area ( AREA_DATA *pArea ) { PLAYER_GAME *gpl; push_call("repop_area(%p)",pArea); pArea->age++; if (pArea->nplayer > 0 && pArea->age == 39 && (!pArea->resetmsg || strcasecmp(pArea->resetmsg, "off"))) { int rnd = number_range(1, 4); for (gpl = mud->f_player ; gpl ; gpl = gpl->next) { if (IS_AWAKE(gpl->ch) && gpl->ch->in_room && gpl->ch->in_room->area == pArea) { if (pArea->resetmsg && pArea->resetmsg[0] != '\0') { ch_printf_color(gpl->ch, "%s\n\r", pArea->resetmsg); } else { switch (gpl->ch->in_room->sector_type) { case SECT_INSIDE: switch (rnd) { case 1: ch_printf_color(gpl->ch, "You hear the boards creaking.\n\r"); break; case 2: ch_printf_color(gpl->ch, "You hear growling echoing in the distance.\n\r"); break; case 3: ch_printf_color(gpl->ch, "You hear wax dripping off a candle.\n\r" ); break; case 4: ch_printf_color(gpl->ch, "You hear foot steps in the distance.\n\r"); break; } break; case SECT_CITY: switch (rnd) { case 1: ch_printf_color(gpl->ch, "You hear the shuffle of feet upon the street.\n\r"); break; case 2: ch_printf_color(gpl->ch, "You hear the idle chatter of passers by.\n\r"); break; case 3: ch_printf_color(gpl->ch, "You hear shopkeepers announcing their wares.\n\r"); break; case 4: ch_printf_color(gpl->ch, "Patrons and merchants roam about the streets.\n\r"); break; } break; case SECT_FIELD: switch (rnd) { case 1: ch_printf_color(gpl->ch, "%sYou hear small creatures rustling the grass.\n\r", ansi_translate("{128}")); break; case 2: ch_printf_color(gpl->ch, "%sYou hear large creatures rustling the grass.\n\r", ansi_translate("{128}")); break; case 3: ch_printf_color(gpl->ch, "%sField mice scurrying about in the brush.\n\r", ansi_translate("{128}")); break; case 4: ch_printf_color(gpl->ch, "%sThe wind whispers softly through the grasses.\n\r", ansi_translate("{128}")); break; } break; case SECT_FOREST: switch (rnd) { case 1: ch_printf_color(gpl->ch, "%sYou hear the trees creaking in the wind.\n\r", ansi_translate("{028}")); break; case 2: ch_printf_color(gpl->ch, "%sThe sound of forest creatures echoes around the trees.\n\r", ansi_translate("{028}")); break; case 3: ch_printf_color(gpl->ch, "%sThe wind carries the scent of evergreens through the trees.\n\r", ansi_translate("{028}")); break; case 4: ch_printf_color(gpl->ch, "%sYou hear the distinct sound of trees grooming one another in the wind.\n\r", ansi_translate("{028}")); break; } break; case SECT_HILLS: switch (rnd) { case 1: ch_printf_color(gpl->ch, "%sThe wind causes the grass to sway along the rolling hills.\n\r", ansi_translate("{038}")); break; case 2: ch_printf_color(gpl->ch, "%sYou hear nothing but a peaceful, easy calm.\n\r", ansi_translate("{038}")); break; case 3: ch_printf_color(gpl->ch, "%sWildflowers dance with the grass in the wind.\n\r", ansi_translate("{038}")); break; case 4: ch_printf_color(gpl->ch, "%sThe bleating of a goat carries far across the hillside.\n\r", ansi_translate("{038}")); break; } break; case SECT_MOUNTAIN: switch (rnd) { case 1: ch_printf_color(gpl->ch, "%sYou hear a rockslide off in the distance.\n\r", ansi_translate("{038}")); break; case 2: ch_printf_color(gpl->ch, "%sYou hear echos of large hooved animals wandering across the rocks.\n\r", ansi_translate("{038}")); break; case 3: ch_printf_color(gpl->ch, "%sThe sound of rams' horns clashing echoes in the distance.\n\r", ansi_translate("{038}")); break; case 4: ch_printf_color(gpl->ch, "%sThe wind whips briskly along the side of the mountain.\n\r", ansi_translate("{038}")); break; } break; case SECT_LAKE: switch (rnd) { case 1: ch_printf_color(gpl->ch, "%sYou hear fish splashing in the water.\n\r", ansi_translate("{168}")); break; case 2: ch_printf_color(gpl->ch, "%sBubbles gently rise to the surface of the water.\n\r", ansi_translate("{168}")); break; case 3: ch_printf_color(gpl->ch, "%sThe water ripples gently around you.\n\r", ansi_translate("{168}")); break; case 4: ch_printf_color(gpl->ch, "%sWater laps lightly against the shoreline.\n\r", ansi_translate("{168}")); break; } break; case SECT_RIVER: switch (rnd) { case 1: ch_printf_color(gpl->ch, "%sThe river's waters gurgle softly as they flow.\n\r", ansi_translate("{168}")); break; case 2: ch_printf_color(gpl->ch, "%sWater splashes as it runs over the rocks.\n\r", ansi_translate("{168}")); break; case 3: ch_printf_color(gpl->ch, "%sSmall fishes splash about in the water.\n\r", ansi_translate("{168}")); break; case 4: ch_printf_color(gpl->ch, "%sThe flow of the water continues its way downstream.\n\r", ansi_translate("{168}")); break; } break; case SECT_OCEAN: switch (rnd) { case 1: ch_printf_color(gpl->ch, "%sThe waves crest around you loudly.\n\r", ansi_translate("{148}")); break; case 2: ch_printf_color(gpl->ch, "%sLarge fishes splash in the water around you.\n\r", ansi_translate("{148}")); break; case 3: ch_printf_color(gpl->ch, "%sYou hear a fog horn echoing through the darkness.\n\r", ansi_translate("{148}")); break; case 4: ch_printf_color(gpl->ch, "%sYou hear the echoes of sea creatures deep below.\n\r", ansi_translate("{148}")); break; } break; case SECT_AIR: switch (rnd) { case 1: ch_printf_color(gpl->ch, "The wind blows harshly around you.\n\r"); break; case 2: ch_printf_color(gpl->ch, "You hear birds of prey screeching nearby.\n\r"); break; case 3: ch_printf_color(gpl->ch, "The clouds roll and whisp around you.\n\r"); break; case 4: ch_printf_color(gpl->ch, "The air rushes at you from all directions at once.\n\r"); break; } break; case SECT_DESERT: switch (rnd) { case 1: ch_printf_color(gpl->ch, "%sThe desert wind whips the sand fiercely.\n\r", ansi_translate("{138}")); break; case 2: ch_printf_color(gpl->ch, "%sThe desert heat radiates off of the sands.\n\r", ansi_translate("{138}")); break; case 3: ch_printf_color(gpl->ch, "%sYou hear a sandstorm growing in the distance.\n\r", ansi_translate("{138}")); break; case 4: ch_printf_color(gpl->ch, "%sAn oasis appears and fades as a mirage in the distance.\n\r", ansi_translate("{138}")); break; } break; case SECT_LAVA: switch (rnd) { case 1: ch_printf_color(gpl->ch, "%sYou hear the bubbling of molten stone.\n\r", ansi_translate("{118}")); break; case 2: ch_printf_color(gpl->ch, "%sYou hear grinding of rocks.\n\r", ansi_translate("{118}")); break; case 3: ch_printf_color(gpl->ch, "%sLava steams and sizzles as it bubbles onto cold stone.\n\r", ansi_translate("{118}")); break; case 4: ch_printf_color(gpl->ch, "%scraters of molten earth groan and bubble around you.\n\r", ansi_translate("{118}")); break; } break; case SECT_ETHEREAL: switch (rnd) { case 1: ch_printf_color(gpl->ch, "You hear echos of an unknown creature.\n\r"); break; case 2: ch_printf_color(gpl->ch, "You hear the distant explosions of power.\n\r"); break; case 3: ch_printf_color(gpl->ch, "You hear an indescribable sound.\n\r"); break; case 4: ch_printf_color(gpl->ch, "You feel a transparent mist appear and thicken about you momentarily.\n\r"); break; } break; case SECT_ASTRAL: switch (rnd) { case 1: ch_printf_color(gpl->ch, "You hear silence echoing in your head.\n\r"); break; case 2: ch_printf_color(gpl->ch, "You hear the pain of a lost soul.\n\r"); break; case 3: ch_printf_color(gpl->ch, "You hear the beating of your own heart.\n\r"); break; case 4: ch_printf_color(gpl->ch, "You hear high pitched voices whispering quietly around you.\n\r"); break; } break; case SECT_UNDER_WATER: switch (rnd) { case 1: ch_printf_color(gpl->ch, "%sYou hear the gurgling of the water.\n\r", ansi_translate("{048}")); break; case 2: ch_printf_color(gpl->ch, "%sYou hear the clicking of a large marine animal.\n\r", ansi_translate("{048}")); break; case 3: ch_printf_color(gpl->ch, "%sSmall fish dart back and forth before your eyes.\n\r", ansi_translate("{048}")); break; case 4: ch_printf_color(gpl->ch, "%sYou hear the echoing roar of a giant sea creature.\n\r", ansi_translate("{048}")); break; } break; case SECT_UNDER_GROUND: switch (rnd) { case 1: ch_printf_color(gpl->ch, "You hear a loud crash!\n\r"); break; case 2: ch_printf_color(gpl->ch, "Some cracks appear in the rock above your head.\n\r"); break; case 3: ch_printf_color(gpl->ch, "The echo of dripping water echoes against the walls.\n\r"); break; case 4: ch_printf_color(gpl->ch, "You hear nothing but the sound of your own breathing.\n\r"); break; } break; case SECT_DEEP_EARTH: switch (rnd) { case 1: ch_printf_color(gpl->ch, "%sYou hear a distant cry echoing all around you.\n\r", ansi_translate("{108}")); break; case 2: ch_printf_color(gpl->ch, "%sYou hear the groan of the immense weight above you.\n\r", ansi_translate("{108}")); break; case 3: ch_printf_color(gpl->ch, "%sYou smell ozone in the air around you.\n\r", ansi_translate("{108}")); break; case 4: ch_printf_color(gpl->ch, "%sYou hear the rocks around you shifting and settling.\n\r", ansi_translate("{108}")); break; } break; case SECT_ROAD: switch (rnd) { case 1: ch_printf_color(gpl->ch, "%sA trading caravan rolls by.\n\r", ansi_translate("{038}")); break; case 2: ch_printf_color(gpl->ch, "%sYou hear clop of trotting hooves in the distance.\n\r", ansi_translate("{038}")); break; case 3: ch_printf_color(gpl->ch, "%sYou hear crickets hidden alongside the road.\n\r", ansi_translate("{038}")); break; case 4: ch_printf_color(gpl->ch, "%sYou feel a gust of wind and dust blown from the road.\n\r", ansi_translate("{038}")); break; } break; case SECT_SWAMP: switch (rnd) { case 1: ch_printf_color(gpl->ch, "%sGurgling bubbles belch forth from the calm surface of the water.\n\r", ansi_translate("{028}")); break; case 2: ch_printf_color(gpl->ch, "%sYou hear frogs croaking in the distance.\n\r", ansi_translate("{028}")); break; case 3: ch_printf_color(gpl->ch, "%sYou hear mosquitos buzzing around you.\n\r", ansi_translate("{028}")); break; case 4: ch_printf_color(gpl->ch, "%sThe sounds of marsh life echo all around you.\n\r", ansi_translate("{028}")); break; } break; case SECT_BEACH: switch (rnd) { case 1: ch_printf_color(gpl->ch, "%sA cool salty spray blows in the air.\n\r", ansi_translate("{168}")); break; case 2: ch_printf_color(gpl->ch, "%sThe grating squawk of a seabirds echoes overhead.\n\r", ansi_translate("{168}")); break; case 3: ch_printf_color(gpl->ch, "%sThe soft roar of waves crashing echoes across the beach.\n\r", ansi_translate("{168}")); break; case 4: ch_printf_color(gpl->ch, "%sThe clean scent of seaweed fills the air as it washes up on the beach.\n\r", ansi_translate("{168}")); break; } break; case SECT_TUNDRA: switch (rnd) { case 1: ch_printf_color(gpl->ch, "%sThe faint sound of arctic creatures can be heard in the distance.\n\r", ansi_translate("{178}")); break; case 2: ch_printf_color(gpl->ch, "%sThe wind whistles as snows dance and spiral over the tundra.\n\r", ansi_translate("{178}")); break; case 3: ch_printf_color(gpl->ch, "%sThe icy silence is broken by the sound of a distant snowslide.\n\r", ansi_translate("{178}")); break; case 4: ch_printf_color(gpl->ch, "%sThe icy chill of the wind stabs at you like daggers.\n\r", ansi_translate("{178}")); break; } break; case SECT_BARREN: switch (rnd) { case 1: ch_printf_color(gpl->ch, "%sA tumbleweed rolls by, driven by an eerily quiet breeze.\n\r", ansi_translate("{038}")); break; case 2: ch_printf_color(gpl->ch, "%sThe sound of a lone cyote calls in the distance.\n\r", ansi_translate("{038}")); break; case 3: ch_printf_color(gpl->ch, "%sA flock of buzzards circles in the distance over some unknown quarry.\n\r", ansi_translate("{038}")); break; case 4: ch_printf_color(gpl->ch, "%sA light arid breeze offers only momentary reprieve from the dry air.\n\r", ansi_translate("{038}")); break; } break; default: ch_printf_color(gpl->ch, "You hear the patter of little feet.\n\r"); break; } } } } } /* Check age and reset. */ if (pArea->age >= 40) { reset_area( pArea ); } pop_call(); return; } void area_update( void ) { AREA_DATA *pArea; push_call("area_update(void)"); for (pArea = mud->f_area ; pArea ; pArea = pArea->next) { repop_area(pArea); } pop_call(); return; } /* Locate last instance of obj reset */ RESET_DATA *get_reset_from_obj(RESET_DATA *lReset) { RESET_DATA *pReset; push_call("get_reset_from_obj(%p)",lReset); for (pReset = lReset ; pReset ; pReset = pReset->prev) { if (pReset->arg1 == lReset->arg3) { if (pReset->command == 'O' || pReset->command == 'G' || pReset->command == 'E') { pop_call(); return pReset; } } } log_printf("get_reset_from_obj: bad '%c' reset", lReset->command); pop_call(); return NULL; } /* Locate last instance of mobile reset */ RESET_DATA *get_reset_from_mob( RESET_DATA *lReset ) { RESET_DATA *pReset; push_call("get_reset_from_mob(%p)",lReset); for (pReset = lReset->prev ; pReset ; pReset = pReset->prev) { if (pReset->command == 'M') { pop_call(); return pReset; } } log_printf("get_reset_from_mob: bad '%c' reset", lReset->command); pop_call(); return NULL; } /* Locate last instance of door reset */ RESET_DATA *get_reset_from_trap( RESET_DATA *lReset ) { RESET_DATA *pReset; push_call("get_reset_from_trap(%p)",lReset); for (pReset = lReset->prev ; pReset ; pReset = pReset->prev) { if (pReset->arg1 == lReset->arg2) { if (pReset->command == 'O' || pReset->command == 'G' || pReset->command == 'E' || pReset->command == 'D') { pop_call(); return pReset; } } } log_printf("get_reset_from_trap: bad '%c' reset", lReset->command); pop_call(); return NULL; } void do_resetarea( CHAR_DATA *ch, char *arg) { push_call("do_resetarea(%p,%p)",ch,arg); if (IS_NPC(ch)) { log_printf("mob using area reset."); dump_stack(); pop_call(); return; } if (!can_olc_modify(ch, ch->in_room->vnum)) { ch_printf_color(ch, "This area is not in your allocated range.\n\r"); pop_call(); return; } SET_BIT(mud->flags, MUD_EMUD_BOOTDB); if (IS_SET(mud->flags, MUD_EMUD_REALGAME)) { log_printf("%s resetted area %s", get_name(ch), ch->in_room->area->name); } send_to_char("Resetting area.\n\r", ch); reset_area(ch->in_room->area); REMOVE_BIT(mud->flags, MUD_EMUD_BOOTDB); pop_call(); return; } /* Create an instance of a mobile. */ CHAR_DATA *create_mobile( MOB_INDEX_DATA *pMobIndex ) { CHAR_DATA *mob; AFFECT_DATA *paf; NPC_DATA *np; int cnt; push_call("create_mobile(%p)",pMobIndex); if (pMobIndex == NULL) { bug("create_mobile: NULL pMobIndex."); abort( ); } if (pMobIndex->total_mobiles > 1000) { log_build_printf(pMobIndex->vnum, "More than 1000 mobs created: %d.\n\r", pMobIndex->total_mobiles); } mud->total_mob++; ALLOCMEM(mob, CHAR_DATA, 1); ALLOCMEM(np, NPC_DATA, 1); mob->level = URANGE(1, pMobIndex->level, 45); clear_char( mob ); mob->npcdata = np; mob->pIndexData = pMobIndex; mob->name = STRDUPE(pMobIndex->player_name); mob->short_descr = STRDUPE(pMobIndex->short_descr); mob->long_descr = STRDUPE(pMobIndex->long_descr); mob->description = STRDUPE(pMobIndex->description); mob->act = pMobIndex->act; mob->spec_fun = pMobIndex->spec_fun; mob->affected_by = pMobIndex->affected_by; mob->alignment = pMobIndex->alignment; mob->ethos = pMobIndex->ethos; mob->sex = pMobIndex->sex; mob->size = pMobIndex->size; mob->max_hit = UMAX(pMobIndex->level, dice(pMobIndex->level, pMobIndex->hitsizedice)) + pMobIndex->hitplus; mob->gold = number_fuzzy(pMobIndex->gold); mob->perm_str = pMobIndex->perm_str; mob->perm_dex = pMobIndex->perm_dex; mob->perm_int = pMobIndex->perm_int; mob->perm_wis = pMobIndex->perm_wis; mob->perm_con = pMobIndex->perm_con; mob->perm_cha = pMobIndex->perm_cha; mob->npcdata->remember = STRDUPE(str_empty); mob->npcdata->hate_fear = 0; mob->npcdata->sac_timer = -1; mob->npcdata->sac_string = STRDUPE(str_empty); mob->npcdata->prog_cmd = STRDUPE(str_empty); mob->race = pMobIndex->race; mob->class = pMobIndex->class; height_weight(mob); if (IS_CLASSED(mob)) { mob->max_hit = 0; for (cnt = 1 ; cnt < MAX_CLASS ; cnt++) { if (mob->class == cnt && pMobIndex->mclass[cnt] == 0) mob->mclass[cnt] = mob->level; if (pMobIndex->mclass[cnt] > 0) { mob->mclass[cnt] = pMobIndex->mclass[cnt]; if (cnt == CLASS_MONSTER) mob->max_hit += dice(pMobIndex->mclass[cnt], race_type_table[race_type(mob)].hit_die); else mob->max_hit += dice(pMobIndex->mclass[cnt], class_table[cnt].hp_max); } } } else if (!mob->race) { mob->max_hit = dice(mob->level, race_type_table[race_table[mob->race].type].hit_die); mob->speak = race_table[mob->race].speaks; mob->language = race_table[mob->race].understands; } else { mob->max_hit = dice(mob->level, pMobIndex->hitsizedice); } if (pMobIndex->speaks > 0) mob->speak = pMobIndex->speaks; SET_BIT(mob->language, pMobIndex->understands); for (cnt = 0 ; *skill_table[cnt].name != '\0' ; cnt++) { if (pMobIndex->learned[cnt] > 0) { mob->learned[cnt] = pMobIndex->learned[cnt]; continue; } if (skill_table[cnt].flags != FSKILL_SKILL) continue; mob->learned[cnt] = learned(mob, cnt); } restore_mana(mob); mob->speed = 1; mob->position = pMobIndex->position; mob->hit = get_max_hit(mob); mob->move = get_max_move(mob); //transfer MobIndex effects to local effects for (paf = mob->pIndexData->first_affect ; paf != NULL ; paf = paf->next) { affect_to_char(NULL, mob, paf); } /* Insert in list. */ add_char( mob ); pMobIndex->total_mobiles++; /* add objects from load_eq */ OBJ_DATA *obj; int vnum; for (cnt = 0 ; cnt < MAX_WEAR ; cnt++) { if ((vnum = pMobIndex->load_eq[cnt]) > 0) { if ((obj = create_object(obj_index[vnum], 0)) == NULL) { log_printf("create_mobile: NULL obj in load_eq %d.", vnum); continue; } obj_to_char(obj, mob); equip_char(mob, obj, cnt); } } char_reset(mob); //clean up and load applies and resists pop_call(); return mob; } /* Create an instance of an object. */ OBJ_DATA *create_object( OBJ_INDEX_DATA *pObjIndex, bool hashed ) { OBJ_DATA *obj; AFFECT_DATA *paf; push_call("create_object(%p,%p)",pObjIndex,hashed); if (pObjIndex == NULL) { log_string("Create_object: NULL pObjIndex."); pop_call(); return NULL; } ALLOCMEM(obj, OBJ_DATA, 1); obj->pIndexData = pObjIndex; obj->level = pObjIndex->level; obj->wear_loc = WEAR_NONE; if (!hashed) { add_obj_ref_hash(obj); } obj->name = STRDUPE(pObjIndex->name); obj->short_descr = STRDUPE(pObjIndex->short_descr); obj->long_descr = STRDUPE(pObjIndex->long_descr); obj->description = STRDUPE(pObjIndex->description); obj->id_name = STRDUPE(pObjIndex->id_name); obj->id_descr = STRDUPE(pObjIndex->id_descr); obj->item_type = pObjIndex->item_type; obj->extra_flags = pObjIndex->extra_flags; obj->wear_flags = pObjIndex->wear_flags; obj->material = pObjIndex->material; obj->hit_points = pObjIndex->hit_points; obj->size = pObjIndex->size; obj->value[0] = pObjIndex->value[0]; obj->value[1] = pObjIndex->value[1]; obj->value[2] = pObjIndex->value[2]; obj->value[3] = pObjIndex->value[3]; obj->value[4] = pObjIndex->value[4]; obj->value[5] = pObjIndex->value[5]; obj->value[6] = pObjIndex->value[6]; obj->value[7] = pObjIndex->value[7]; obj->weight = pObjIndex->weight; obj->cost = pObjIndex->cost; obj->level = pObjIndex->level; obj->identified = FALSE; //transfer ObjIndex effects to local effects for (paf = obj->pIndexData->first_affect ; paf != NULL ; paf = paf->next) { affect_to_obj(NULL, obj, paf); } /* Mess with object properties. */ switch (obj->item_type) { default: log_printf("create_object: vnum %u has bad item_type", pObjIndex->vnum); break; case ITEM_FIRE: case ITEM_LIGHT: case ITEM_SYMBOL: case ITEM_SPELLBOOK: case ITEM_TREASURE: case ITEM_FURNITURE: case ITEM_TRASH: case ITEM_SPELLPOUCH: case ITEM_CONTAINER: case ITEM_CART: case ITEM_SHEATH: case ITEM_QUIVER: case ITEM_DRINK_CON: case ITEM_KEY: case ITEM_CRAFT: case ITEM_PIECE: case ITEM_FOOD: case ITEM_BOAT: case ITEM_CORPSE_NPC: case ITEM_CORPSE_PC: case ITEM_FOUNTAIN: case ITEM_PORTAL: case ITEM_WINDOW: case ITEM_PAPER: case ITEM_TRAP: case ITEM_TOTEM: case ITEM_BOOK: break; case ITEM_TOOLS: obj->value[1] = number_fuzzy(obj->value[1]); break; case ITEM_SCROLL: case ITEM_POTION: case ITEM_PILL: case ITEM_COMPONENT: obj->value[0] = number_fuzzy(obj->value[0]); break; case ITEM_WAND: case ITEM_STAFF: obj->value[0] = number_fuzzy(obj->value[0]); obj->value[1] = number_fuzzy(obj->value[1]); break; case ITEM_WEAPON: obj->weight = weapon_table[obj->value[0]].weight; obj->apply[APPLY_HITROLL] = get_obj_apply(obj, APPLY_HITROLL); obj->apply[APPLY_DAMROLL] = get_obj_apply(obj, APPLY_DAMROLL); break; case ITEM_ARMOR: obj->weight = armor_table[obj->value[0]].weight; obj->apply[APPLY_ENHANCE_AC] = get_obj_apply(obj, APPLY_ENHANCE_AC); break; case ITEM_MONEY: obj->cost = obj->value[0] * 100; obj->cost += obj->value[1] * 10; obj->cost += obj->value[2]; break; case ITEM_AMMO: obj->value[1] = number_fuzzy(obj->value[1]); obj->apply[APPLY_HITROLL] = get_obj_apply(obj, APPLY_HITROLL); obj->apply[APPLY_DAMROLL] = get_obj_apply(obj, APPLY_DAMROLL); break; } LINK(obj, mud->f_obj, mud->l_obj, next, prev); LINK(obj, obj->pIndexData->first_instance, obj->pIndexData->last_instance, next_instance, prev_instance); mud->total_obj++; pObjIndex->total_objects++; pop_call(); return obj; } /* Clear a new character. */ void clear_char( CHAR_DATA *ch ) { push_call("clear_char(%p)",ch); ch->position = POS_STANDING; ch->hit = 0; ch->max_hit = 0; ch->move = 0; ch->max_move = 0; pop_call(); return; } /* Free a character. */ void free_char( CHAR_DATA *ch ) { POISON_DATA *pd; CRIME_DATA *crime; int cnt; push_call("free_char(%p)",ch); while (ch->first_carrying) { extract_obj(ch->first_carrying); } while (ch->first_affect) { affect_from_char(ch, ch->first_affect); } while (ch->first_disease) { disease_from_char(ch, ch->first_disease); } while ((pd = ch->poison) != NULL) { ch->poison = ch->poison->next; FREEMEM(pd); } STRFREE(ch->name); STRFREE(ch->short_descr); STRFREE(ch->long_descr); STRFREE(ch->description); if (in_combat(ch) || ch->in_battle != NULL) { char_from_combat(ch); } if (ch->last_attacked) { ch->last_attacked = NULL; } if (ch->last_attacker) { ch->last_attacker = NULL; } if (ch->pcdata) { STRFREE(ch->pcdata->host ); STRFREE(ch->pcdata->account ); STRFREE(ch->pcdata->mail_address ); STRFREE(ch->pcdata->html_address ); STRFREE(ch->pcdata->block_list ); STRFREE(ch->pcdata->title ); STRFREE(ch->pcdata->auto_command ); STRFREE(ch->pcdata->adjective ); STRFREE(ch->pcdata->authed_by ); STRFREE(ch->pcdata->bamfin ); STRFREE(ch->pcdata->bamfout ); STRFREE(ch->pcdata->pwd ); STRFREE(ch->pcdata->page_buf ); STRFREE(ch->pcdata->edit_buf ); STRFREE(ch->pcdata->prompt_layout ); STRFREE(ch->pcdata->subprompt ); STRFREE(ch->pcdata->clan_name ); STRFREE(ch->pcdata->clan_pledge ); STRFREE(ch->pcdata->last_command ); STRFREE(ch->pcdata->bio ); STRFREE(ch->pcdata->pose ); STRFREE(ch->pcdata->disguise ); STRFREE(ch->pcdata->disguise_descr ); ch->pcdata->tracking = NULL; while ((crime = ch->pcdata->first_record) != NULL) { ch->pcdata->first_record = crime->next; STRFREE(crime->crime_record); STRFREE(crime->arrester); STRFREE(crime->releaser); FREEMEM(crime); } if (ch->pcdata->pnote != NULL) { STRFREE(ch->pcdata->pnote->text); STRFREE(ch->pcdata->pnote->subject); STRFREE(ch->pcdata->pnote->to_list); STRFREE(ch->pcdata->pnote->date); STRFREE(ch->pcdata->pnote->sender); FREEMEM(ch->pcdata->pnote); } if (ch->pcdata->editor) { stop_editing(ch); } for (cnt = 0 ; cnt < MAX_PK_ATTACKS ; cnt++) { STRFREE(ch->pcdata->last_pk_attack_name[cnt]); } for (cnt = 0 ; cnt < MAX_ALIAS ; cnt++) { STRFREE (ch->pcdata->alias[cnt] ); STRFREE (ch->pcdata->alias_c[cnt] ); } for (cnt = 0 ; cnt < 26 ; cnt++) { STRFREE(ch->pcdata->back_buf[cnt] ); } for (cnt = 0 ; cnt < MAX_AREA ; cnt++) { if (ch->pcdata->quest[cnt] != NULL) { FREEMEM(ch->pcdata->quest[cnt]); } } if (ch->pcdata->tactical) { FREEMEM(ch->pcdata->tactical); } FREEMEM(ch->pcdata); } if (ch->npcdata) { if (ch->npcdata->mob_quest) { FREEMEM(ch->npcdata->mob_quest); } STRFREE(ch->npcdata->remember); STRFREE(ch->npcdata->sac_string); ch->npcdata->hate_fear = 0; FREEMEM(ch->npcdata); } FREEMEM(ch); pop_call(); return; } /* Get an extra description from a list. */ char *get_extra_descr( const char *name, EXTRA_DESCR_DATA *ed ) { push_call("get_extra_descr(%p,%p)",name,ed); for ( ; ed ; ed = ed->next) { if (is_name(name, ed->keyword)) { pop_call(); return ed->description; } } pop_call(); return NULL; } /* Read a letter from a file. */ char fread_letter( FILE *fp ) { char c; push_call("fread_letter(%p)",fp); do { if (feof(fp)) { bug("fread_letter: EOF encountered on read.\n\r"); if (IS_SET(mud->flags, MUD_EMUD_BOOTDB)) { exit(1); } pop_call(); return '\0'; } c = getc(fp); } while (isspace(c)); pop_call(); return c; } /* Read a number from a file. */ lg_int fread_number( FILE *fp ) { int cnt; lg_int number; bool sign; char c; char buf[100]; push_call("fread_number(%p)",fp); buf[0] = '\0'; do { if (feof(fp)) { bug("fread_number: EOF encountered on read.\n\r"); if (IS_SET(mud->flags, MUD_EMUD_BOOTDB)) { exit(1); } pop_call(); return 0; } c = getc(fp); } while (isspace(c)); number = 0; sign = (c == '-'); if (c == '+' || c == '-') { c = getc(fp); } for (cnt = 0 ; isdigit(c) || isupper(c) || c == '_' ; cnt++) { buf[cnt] = c; c = getc(fp); } buf[cnt] = '\0'; if (isupper(buf[0])) { for (cnt = mud->bitvector_ref[*buf - 'A'] ; *bitvector_table[cnt].name != '\0' ; cnt++) { if (!strcmp(bitvector_table[cnt].name, buf)) { number = bitvector_table[cnt].value; break; } } if (*bitvector_table[cnt].name == '\0') { log_printf("fread_number: bad format1 '%s'.", buf); dump_stack(); } } else { if (!isdigit(buf[0])) { log_printf("fread_number: bad format2 '%c%s'", c, fread_word(fp)); pop_call(); return number; } number = atoll(buf); } if (sign) { number = 0 - number; } if (c == '|') { number += fread_number( fp ); } else if (c != ' ') { ungetc( c, fp ); } pop_call(); return number; } /* Read and allocate space for a string from a file. Strings are created and placed in Dynamic Memory. */ char *fread_string( FILE *fp ) { char buf[MAX_STRING_LENGTH]; char *plast; char c; int ln; push_call("fread_string(%p)",fp); plast = buf; buf[0] = '\0'; ln = 0; /* Skip blanks. Read first char. */ do { if (feof(fp)) { bug("fread_string: EOF encountered on read.\n\r"); if (IS_SET(mud->flags, MUD_EMUD_BOOTDB)) { exit(1); } pop_call(); return STRDUPE(str_empty); } c = getc( fp ); } while (isspace(c)); if ((*plast++ = c) == '~') { pop_call(); return STRDUPE(str_empty); } for (ln = 0 ; ln < MAX_STRING_LENGTH ; ln++, plast++) { switch (*plast = getc(fp)) { case EOF: bug( "Fread_string: EOF" ); if (IS_SET(mud->flags, MUD_EMUD_BOOTDB)) { exit( 1 ); } *plast = '\0'; pop_call(); return STRALLOC(buf); case '\n': plast++; ln++; *plast = '\r'; break; case '\r': plast--; ln--; break; case '~': *plast = '\0'; pop_call(); return STRALLOC( buf ); } } bug("fread_string: string too long" ); if (IS_SET(mud->flags, MUD_EMUD_BOOTDB)) { abort(); } *plast = '\0'; pop_call(); return STRALLOC(buf); } /* Read to end of line (for comments). */ void fread_to_eol( FILE *fp ) { char c; push_call("fread_to_eol(%p)",fp); do { if (feof(fp)) { bug("fread_to_eol: EOF encountered on read.\n\r", 0); if (IS_SET(mud->flags, MUD_EMUD_BOOTDB)) { abort(); } pop_call(); return; } c = getc( fp ); } while (c != '\n' && c != '\r'); do { c = getc( fp ); } while (c == '\n' || c == '\r'); ungetc(c, fp); pop_call(); return; } char *fread_line( FILE *fp ) { static char line[MAX_STRING_LENGTH]; char *pline; char c; int ln; push_call("fread_line(%p)",fp); pline = line; line[0] = '\0'; ln = 0; /* Skip blanks. Read first char. */ do { if (feof(fp)) { bug("fread_line: EOF encountered on read.\n\r",0); if (IS_SET(mud->flags, MUD_EMUD_BOOTDB)) { abort(); } strcpy(line, ""); pop_call(); return line; } c = getc( fp ); } while (isspace(c)); ungetc(c, fp); do { if (feof(fp)) { bug("fread_line: EOF encountered on read.\n\r",0); if (IS_SET(mud->flags, MUD_EMUD_BOOTDB)) { abort(); } *pline = '\0'; pop_call(); return line; } c = getc( fp ); *pline++ = c; ln++; if (ln >= (MAX_STRING_LENGTH - 1)) { bug( "fread_line: line too long",0 ); if (IS_SET(mud->flags, MUD_EMUD_BOOTDB)) { abort(); } break; } } while (c != '\n' && c != '\r'); do { c = getc( fp ); } while (c == '\n' || c == '\r'); ungetc( c, fp ); *pline = '\0'; pop_call(); return line; } /* Read one word (into static buffer). */ char *fread_word( FILE *fp ) { static char word[MAX_INPUT_LENGTH]; char *pword; char cEnd; int cnt; push_call("fread_word(%p)",fp); do { if (feof(fp)) { bug("fread_word: EOF encountered on read.\n\r", 0); if (IS_SET(mud->flags, MUD_EMUD_BOOTDB)) { abort(); } word[0] = '\0'; pop_call(); return word; } cEnd = getc( fp ); } while ( isspace(cEnd) ); if (cEnd == '\'' || cEnd == '"') { pword = word; } else { word[0] = cEnd; pword = word+1; cEnd = ' '; } for (cnt = 0 ; cnt < MAX_INPUT_LENGTH ; cnt++, pword++) { if (feof(fp)) { bug("fread_word: EOF encountered on read.\n\r", 0); if (IS_SET(mud->flags, MUD_EMUD_BOOTDB)) { abort(); } *pword = '\0'; pop_call(); return word; } *pword = getc(fp); if (*pword == cEnd || *pword == EOF || *pword == '\n') { if (*pword == EOF || cEnd == ' ') { ungetc( *pword, fp ); } *pword = '\0'; pop_call(); return word; } } word[10] = '\0'; bug("fread_word: word '%s' too long.", word); abort( ); } /* Returns 1000 times normal percentage value */ lg_int display_timer( CHAR_DATA *ch, int timer ) { lg_int tot_usage, ind_usage; push_call("display_timer(%p,%p)",ch,timer); tot_usage = mud->total_io_exec + mud->total_io_delay; if (tot_usage == 0) { pop_call(); return(0); } if (timers[timer][1] == 0 || timers[timer][4] == 0) { pop_call(); return(0); } ind_usage = timers[timer][0] / timers[timer][1] * timers[timer][4]; ch_printf_color(ch, "%-30s%8lld %8lld %8.2f %8.2f\n\r", timer_strings[timer], timers[timer][0] / timers[timer][1], timers[timer][3] / timers[timer][4] / 1000, 100.0 * (double) ind_usage / (double) mud->total_io_exec, 100.0 * (double) ind_usage / (double) tot_usage); pop_call(); return ind_usage; } void start_timer( int timer ) { struct timeval last_time; lg_int cur_time; gettimeofday(&last_time, NULL); cur_time = (lg_int) last_time.tv_usec + 1000000LL * (lg_int) last_time.tv_sec; if (timers[timer][2] == 0) { timers[timer][2] = cur_time ; return; } timers[timer][3] += cur_time - timers[timer][2]; timers[timer][2] = cur_time; timers[timer][4] ++; return; } void close_timer( int timer ) { struct timeval last_time; lg_int cur_time; gettimeofday(&last_time, NULL); cur_time = (lg_int) last_time.tv_usec + 1000000LL * (lg_int) last_time.tv_sec; /* if (cur_time - timers[timer][2] > 1000000 / PULSE_PER_SECOND) { bug("%s heartbeat violation of %lld usec", timer_strings[timer], cur_time - timers[timer][2] - (1000000LL / PULSE_PER_SECOND)); } */ timers[timer][0] += (cur_time - timers[timer][2]); timers[timer][1] ++; return; } /* randomize number by -10 to 10 percent */ int number_fuzzy( int number ) { return (number - number/10 + number_range(0, number/10*2)); } /* randomize each digit in number by -1 to +1 */ int big_number_fuzzy( int number ) { char numbuf[MAX_STRING_LENGTH]; sh_int i; sprintf(numbuf, "%d", number); for ( i = 0; numbuf[i] != '\0'; i++ ) numbuf[i] = number_fuzzy(numbuf[i]); number = atoi(numbuf); return UMAX( 1, number ); } float what_percent(float current, float max) { float percent; push_call("what_percent(%p,%p)",current,max); percent = 100 * UMAX(0, current) / UMAX(1, max); pop_call(); return percent; } /* Generate a random number. */ int number_range( int from, int to ) { int val; push_call("number_range(%p,%p)",from,to); if (from > to || from < 0 || to < 0) { log_printf("number_range: invalid range (%d,%d)", from, to); dump_stack(); if (from > to) { val = from; from = to; to = val; } } pop_call(); return (lrand48() % (to - from + 1)) + from; } /* Roll some dice. */ int dice( int number, int size ) { int idice, sum; push_call("dice(%p,%p)",number,size); if (size <= 0) { pop_call(); return 0; } for (idice = sum = 0 ; idice < number ; idice++) { sum += (lrand48() % size) + 1; } pop_call(); return sum; } /* Return a value between 1 and 100 */ int number_percent( void ) { return ((lrand48() % 100) + 1); } /* Generate a random door. */ int number_door( void ) { return (lrand48() % 6); } /* return a value between 0 and given power of 2 */ int number_bits( int width ) { return (lrand48() % (1 << width)); } /* Append a string to a file. */ void append_file( CHAR_DATA *ch, char *fname, FILE *fp, char *str ) { push_call("append_file(%p,%p,%p,%p)",ch,fname,fp,str); if ((ch != NULL && IS_NPC(ch)) || str == NULL || str[0] == '\0') { pop_call(); return; } if (fpAppend) { my_fclose( fpAppend ); } if (fp == NULL) { fp = my_fopen( fname, "a",FALSE); } if (fp == NULL) { perror( fname ); fpAppend = my_fopen( NULL_FILE, "r",FALSE); pop_call(); return; } if (ch == NULL) { fprintf( fp, "%s\n", str ); fflush( fp ); fpAppend = my_fopen( NULL_FILE, "r",FALSE); pop_call(); return; } fprintf( fp, "[%s] %s: %s\n", get_time_string(mud->current_time), ch->name, str ); fflush( fp ); fpAppend = my_fopen( NULL_FILE, "r",FALSE); pop_call(); return; } /* Reports a bug. -1 param does not put in logs. */ void bug( const char *str, ... ) { char buf[MAX_STRING_LENGTH]; push_call("bug(%p)",str); if (fpArea != NULL) { int iLine; int iChar; if (fpArea == stdin) { iLine = 0; } else { iChar = ftell(fpArea); fseek(fpArea, 0, 0); for (iLine = 0 ; ftell(fpArea) < iChar ; iLine++) { while (getc(fpArea) != '\n') { ; } } fseek(fpArea, iChar, 0); } log_printf("[*****] FILE: %s LINE: %d", strArea, iLine); } strcpy(buf, "[+++++] "); { va_list param; va_start(param, str); vsprintf( buf + strlen(buf), str, param ); va_end(param); } log_string( buf ); log_printf("[+++++] %s", mud->last_player_cmd); pop_call(); return; } /* * Dump a text file to a player, a line at a time * originally by Thoric */ void show_file( CHAR_DATA * ch, char *filename ) { FILE *fp; char buf[MAX_STRING_LENGTH]; int c; int num = 0; if( ( fp = my_fopen( filename, "r", FALSE ) ) != NULL ) { while( !feof( fp ) ) { while( ( buf[num] = fgetc( fp ) ) != EOF && buf[num] != '\n' && buf[num] != '\r' && num < ( MAX_STRING_LENGTH - 2 ) ) num++; c = fgetc( fp ); if( ( c != '\n' && c != '\r' ) || c == buf[num] ) ungetc( c, fp ); buf[num++] = '\n'; buf[num++] = '\r'; buf[num] = '\0'; send_to_char_color( buf, ch ); num = 0; } my_fclose( fp ); } } /* Writes a string to the log. */ void log_string( char *str ) { char *strtime; struct timeval log_time; CHAR_DATA *fch; PLAYER_GAME *fpl; push_call("log_string(%p)",str); for (fpl = mud->f_player ; fpl ; fpl = fpl->next) { fch = fpl->ch; if (IS_NPC(fch)) { continue; } if (!IS_SET(fch->act, PLR_HEARLOG) || !IS_IMMORTAL(fch)) { continue; } ch_printf_color(fch, "{058}Log: %s\n\r", justify(str, get_page_width(fch))); } gettimeofday(&log_time, NULL); strtime = ctime(&log_time.tv_sec); strtime[strlen(strtime)-6] = '\0'; fprintf( stderr, "%s- %s\n", strtime, str ); pop_call(); return; } void log_build_string(int vnum, char *str ) { struct timeval log_time; char *strtime; CHAR_DATA *fch; PLAYER_GAME *fpl; push_call("log_build_string(%p)",str); for (fpl = mud->f_player ; fpl ; fpl = fpl->next) { fch = fpl->ch; if (!IS_SET(fpl->ch->act, PLR_HEARLOG) || !can_olc_modify(fpl->ch, vnum)) { continue; } ch_printf_color(fch, "{058}Log: [%u] %s\n\r", vnum, str); } gettimeofday(&log_time, NULL); strtime = ctime(&log_time.tv_sec); strtime[strlen(strtime)-6] = '\0'; fprintf( stderr, "%s- [%u] %s\n", strtime, vnum, str ); pop_call(); return; } void log_wiz_string( char *str ) { CHAR_DATA *fch; PLAYER_GAME *fpl; push_call("log_wiz_string(%p)",str); for (fpl = mud->f_player ; fpl ; fpl = fpl->next) { fch = fpl->ch; if (IS_NPC(fch)) continue; if (!IS_SET(fpl->ch->act, PLR_WIZTIME)) continue; ch_printf_color(fch, "{058}DEBUG: %s\n\r", str); } pop_call(); return; } void log_god_string( char *str ) { char *strtime; struct timeval log_time; CHAR_DATA *fch; PLAYER_GAME *fpl; push_call("log_god_string(%p)",str); for (fpl = mud->f_player ; fpl ; fpl = fpl->next) { fch = fpl->ch; if (IS_NPC(fch)) { continue; } if (!IS_SET(fch->act, PLR_HEARLOG) || !IS_GOD(fch)) { continue; } ch_printf_color(fch, "{058}Log: %s\n\r", justify(str, get_page_width(fch))); } gettimeofday(&log_time, NULL); strtime = ctime(&log_time.tv_sec); strtime[strlen(strtime)-6] = '\0'; fprintf( stderr, "%s- %s\n", strtime, str ); pop_call(); return; } void create_menu_tree() { char *pt; int cnt; char line[200]; AREA_DATA *pArea, *tArea; HELP_DATA *pHelp, *tHelp; HELP_MENU_DATA *menu; char buf[MAX_STRING_LENGTH]; push_call("create_menu_tree()"); for (pArea = mud->f_area ; pArea ; pArea = pArea->next) { for (pHelp = pArea->first_help ; pHelp ; pHelp = pHelp->next) { strcpy(buf, pHelp->text); pt = buf; pt += strlen(buf) / 4; while (*pt != '\0') { if (*(pt+1) != '{' || *(pt+2) == '\0' || *(pt+3) != '}') { pt++; continue; } pt++; *pt = '\0'; if (pHelp->first_menu == NULL) { STRFREE(pHelp->text); pHelp->text = STRALLOC(buf); } *pt = '{'; /* find menu items here */ cnt = 0; while (*pt != '\r' && *pt != '\n' && *pt != '\0') { line[cnt] = *pt; cnt++; pt++; } line[cnt] = '\0'; for (tHelp = pHelp->area->first_help ; tHelp ; tHelp = tHelp->next) { if (line[3] == tHelp->keyword[0] && line[4] == tHelp->keyword[1] && !strcmp(&line[3], tHelp->keyword)) { ALLOCMEM(menu, HELP_MENU_DATA, 1); menu->option = tolower(line[1]); menu->help = tHelp; LINK(menu, pHelp->first_menu, pHelp->last_menu, next, prev); goto end_of_loop; } } /* log_printf("create_menu: inter area help menu: %s", line); */ for (tArea = mud->f_area ; tArea ; tArea = tArea->next) { for (tHelp = tArea->first_help ; tHelp ; tHelp = tHelp->next) { if (line[3] == tHelp->keyword[0] && line[4] == tHelp->keyword[1] && !strcmp(&line[3], tHelp->keyword)) { ALLOCMEM(menu, HELP_MENU_DATA, 1); menu->option = tolower(line[1]); menu->help = tHelp; LINK(menu, pHelp->first_menu, pHelp->last_menu, next, prev); goto end_of_loop; } } } log_printf("create_menu: failed perfect match: %s", line); for (tArea = mud->f_area ; tArea ; tArea = tArea->next) { for (tHelp = tArea->first_help ; tHelp ; tHelp = tHelp->next) { if (is_name(&line[3], tHelp->keyword)) { ALLOCMEM(menu, HELP_MENU_DATA, 1); menu->option = tolower(line[1]); menu->help = tHelp; LINK(menu, pHelp->first_menu, pHelp->last_menu, next, prev); goto end_of_loop; } } } end_of_loop: continue; } } } pop_call(); return; } int find_command( char *cmd_str, int trust ) { int cmd; push_call("find_command(%p)",cmd_str); if (isalpha(*cmd_str)) { for (cmd = mud->command_ref[tolower(*cmd_str) - 'a'] ; *cmd_table[cmd].name == *cmd_str ; cmd++) { if (IS_SET(cmd_table[cmd].flags, CMD_BUILDER|CMD_TESTER) && !str_prefix(cmd_str, cmd_table[cmd].name)) { pop_call(); return cmd; } if (cmd_table[cmd].level <= trust && !str_prefix(cmd_str, cmd_table[cmd].name)) { pop_call(); return cmd; } } } else { for (cmd = 0 ; !isalpha(*cmd_table[cmd].name) ; cmd++) { if (IS_SET(cmd_table[cmd].flags, CMD_BUILDER|CMD_TESTER) && !str_prefix(cmd_str, cmd_table[cmd].name)) { pop_call(); return cmd; } if (cmd_table[cmd].level <= trust && !str_prefix(cmd_str, cmd_table[cmd].name)) { pop_call(); return cmd; } } } pop_call(); return -1; } int find_social( char *social_str ) { int cmd; push_call("find_social(%p)",social_str); if (isalpha(*social_str)) { for (cmd = mud->social_ref[tolower(*social_str) - 'a'] ; *social_table[cmd].name == *social_str ; cmd++) { if (!str_prefix(social_str, social_table[cmd].name)) { pop_call(); return cmd; } } } pop_call(); return -1; } OBJ_PROG * load_object_program( FILE *fp) { OBJ_PROG *prg; char buf[MAX_INPUT_LENGTH]; push_call("load_object_program(%p)",fp); ALLOCMEM(prg, OBJ_PROG, 1); prg->unknown = STRDUPE(str_empty); prg->if_symbol = '='; prg->argument = STRDUPE(str_empty); prg->index = fread_number( fp ); /* get index number */ prg->trigger = fread_number( fp ); /* get trigger command type */ mud->top_oprog++; switch (prg->trigger) { case TRIG_VOID: break; case TRIG_COMMAND: case TRIG_ROOM_COMMAND: case TRIG_WEAR_COMMAND: prg->percentage = fread_number( fp ); if ((prg->cmd = find_command(fread_word(fp), MAX_LEVEL - 1)) == -1) { bug("Bad obj_command command name: %s", buf); abort(); } break; case TRIG_UNKNOWN: case TRIG_ROOM_UNKNOWN: case TRIG_WEAR_UNKNOWN: prg->percentage = fread_number( fp ); STRFREE(prg->unknown); prg->unknown = STRALLOC(fread_word( fp )) ; break; case TRIG_TICK: case TRIG_DAMAGE: case TRIG_HIT: case TRIG_WEAR: case TRIG_REMOVE: case TRIG_SACRIFICE: prg->percentage = fread_number( fp ); break; default: log_string( "Bad obj_command type"); } prg->obj_command = fread_number( fp ); switch (prg->obj_command) { case OPROG_ECHO: case OPROG_GOD_COMMAND: case OPROG_GOD_ARGUMENT: case OPROG_COMMAND: case OPROG_ARGUMENT: STRFREE(prg->argument); prg->argument = fread_string( fp ) ; break; case OPROG_QUEST_SET: prg->quest_offset = fread_number( fp ); prg->quest_bits = fread_number( fp ); prg->if_value = fread_number( fp ); break; case OPROG_QUEST_ADD: prg->quest_offset = fread_number( fp ); prg->quest_bits = fread_number( fp ); prg->if_value = fread_number( fp ); break; case OPROG_PLAYER_QUEST_IF: prg->quest_offset = fread_number( fp ); prg->quest_bits = fread_number( fp ); prg->if_symbol = fread_letter( fp ); prg->if_value = fread_number( fp ); prg->if_true = fread_number( fp ); prg->if_false = fread_number( fp ); break; case OPROG_OBJECT_QUEST_IF: prg->quest_offset = fread_number( fp ); prg->quest_bits = fread_number( fp ); prg->if_symbol = fread_letter( fp ); prg->if_value = fread_number( fp ); prg->if_true = fread_number( fp ); prg->if_false = fread_number( fp ); break; case OPROG_IF_HAS_OBJECT: prg->if_value = fread_number( fp ); prg->if_true = fread_number( fp ); prg->if_false = fread_number( fp ); break; case OPROG_IF: prg->if_check = fread_number( fp ); prg->if_symbol = fread_letter( fp ); prg->if_value = fread_number( fp ); prg->if_true = fread_number( fp ); prg->if_false = fread_number( fp ); break; case OPROG_APPLY: prg->if_check = fread_number( fp ); prg->if_value = fread_number( fp ); break; case OPROG_JUNK: break; default: log_string( "Bad obj_command reaction type"); } pop_call(); return( prg ); } void obj_prog_if_dest( OBJ_INDEX_DATA *obj ) { push_call("obj_prog_if_dest(%p)",obj); pop_call(); return; } /* Load default weight of an object from index data. */ int load_obj_weight( OBJ_INDEX_DATA *obj ) { int weight; push_call("load_obj_weight(%p)",obj); switch (obj->item_type) { default: bug("load_obj_weight(%d): unknown item type %d!", obj->vnum, obj->item_type); pop_call(); return 0; case ITEM_WAND: weight = 5; break; case ITEM_STAFF: weight = 40; break; case ITEM_FURNITURE: case ITEM_TOTEM: weight = obj->size/SIZE_MEDIUM * 500; break; case ITEM_TRASH: weight = obj->size/SIZE_MEDIUM * 50; break; case ITEM_LIGHT: weight = 10; break; case ITEM_POTION: weight = 10; if (obj->value[0] == 0) weight /= 3; break; case ITEM_SPELLBOOK: weight = obj->value[0]; break; case ITEM_BOOK: weight = 30; break; case ITEM_FOOD: case ITEM_DRINK_CON: weight = UMAX(1, obj->value[0] * 2); break; case ITEM_SCROLL: case ITEM_COMPONENT: case ITEM_KEY: case ITEM_PILL: case ITEM_PAPER: case ITEM_FIRE: weight = 0; break; case ITEM_TRAP: case ITEM_PORTAL: case ITEM_WINDOW: case ITEM_CRAFT: case ITEM_PIECE: weight = -1; break; case ITEM_TOOLS: weight = tool_table[obj->value[0]].weight; break; case ITEM_WEAPON: weight = weapon_table[obj->value[0]].weight; break; case ITEM_AMMO: weight = 1; break; case ITEM_ARMOR: weight = armor_weight(obj); break; case ITEM_QUIVER: case ITEM_SHEATH: case ITEM_CART: case ITEM_CONTAINER: case ITEM_SPELLPOUCH: if (IS_SET(obj->value[1], CONT_HOLDING)) weight = ROUNDUP(obj->value[0]/160); else weight = obj->size * 10; break; case ITEM_SYMBOL: case ITEM_FOUNTAIN: case ITEM_TREASURE: weight = obj->size << obj->size; break; case ITEM_MONEY: weight = obj->value[0]; weight += obj->value[1]; weight += obj->value[2]; break; case ITEM_BOAT: weight = 100; break; case ITEM_CORPSE_NPC: case ITEM_CORPSE_PC: weight = 1; break; } pop_call(); return(weight); } /* * Used in load_objects to fix objects that * load with no material data. */ void fix_materials( OBJ_INDEX_DATA *obj ) { int material; push_call("fix_materials(%p)", obj); if ((material = obj->material) <= 0 || material >= MATERIAL_MAX) { switch (obj->item_type) { case ITEM_WEAPON: if (IS_SET(weapon_table[obj->value[0]].weap_spec, WSPEC_MISSILE)) material = MATERIAL_SOFTWOOD; else if (IS_SET(weapon_table[obj->value[0]].weap_spec, WSPEC_WOODEN_HAFTED)) material = MATERIAL_HARDWOOD; else material = MATERIAL_STEEL; break; case ITEM_ARMOR: if (obj->value[0] <= ARMOR_TYPE_PADDED) material = MATERIAL_CLOTH; else if (obj->value[0] <= ARMOR_TYPE_STUDDED_LEATHER) material = MATERIAL_LEATHER; else if (obj->value[0] <= ARMOR_TYPE_HIDE) material = MATERIAL_HIDE; else if (obj->value[0] <= ARMOR_TYPE_FULL_PLATE) material = MATERIAL_STEEL; else if (obj->value[0] <= ARMOR_TYPE_LIGHT_SHIELD) material = MATERIAL_HARDWOOD; else material = MATERIAL_STEEL; break; case ITEM_SCROLL: case ITEM_PAPER: case ITEM_BOOK: case ITEM_MAP: case ITEM_SPELLBOOK: material = MATERIAL_PAPER; break; case ITEM_WAND: case ITEM_STAFF: case ITEM_FURNITURE: case ITEM_TRASH: case ITEM_BOAT: case ITEM_TOTEM: case ITEM_AMMO: case ITEM_CART: material = MATERIAL_HARDWOOD; break; case ITEM_POTION: case ITEM_WINDOW: case ITEM_DRINK_CON: material = MATERIAL_GLASS; break; case ITEM_SPELLPOUCH: case ITEM_SHEATH: case ITEM_CONTAINER: case ITEM_QUIVER: material = MATERIAL_LEATHER; break; case ITEM_KEY: material = MATERIAL_BRONZE; break; case ITEM_TOOLS: material = MATERIAL_STEEL; break; case ITEM_FOUNTAIN: material = MATERIAL_STONE; break; case ITEM_FOOD: case ITEM_CORPSE_PC: case ITEM_CORPSE_NPC: material = MATERIAL_FLESH; break; case ITEM_MONEY: case ITEM_TREASURE: case ITEM_SYMBOL: material = MATERIAL_SILVER; break; default: material = -1; // need a control for irrelevant item types break; } if (material != -1) { obj->material = material; bug("fix_materials: obj vnum %d with bad material, fixed.", obj->vnum); } } pop_call(); return; } /* * Used in load_objects to fix objects that * load with no size data. */ void fix_sizes( OBJ_INDEX_DATA *obj ) { int size; push_call("fix_sizes(%p)", obj); if ((size = obj->size) <= 0 || size > SIZE_COLOSSAL) { switch (obj->item_type) { case ITEM_WEAPON: size = weapon_table[obj->value[0]].size; break; case ITEM_SYMBOL: case ITEM_KEY: size = SIZE_FINE; break; case ITEM_LIGHT: case ITEM_POTION: case ITEM_TREASURE: case ITEM_SPELLPOUCH: case ITEM_FOOD: case ITEM_AMMO: case ITEM_MAP: size = SIZE_DIMINUTIVE; break; case ITEM_PAPER: case ITEM_WAND: case ITEM_SCROLL: case ITEM_DRINK_CON: case ITEM_TRASH: case ITEM_SPELLBOOK: case ITEM_BOOK: case ITEM_TOOLS: case ITEM_PIECE: size = SIZE_TINY; break; case ITEM_FIRE: case ITEM_TRAP: case ITEM_CRAFT: case ITEM_CONTAINER: case ITEM_SHEATH: case ITEM_QUIVER: size = SIZE_SMALL; break; case ITEM_ARMOR: case ITEM_CORPSE_NPC: case ITEM_CORPSE_PC: case ITEM_WINDOW: case ITEM_FURNITURE: size = SIZE_MEDIUM; break; case ITEM_STAFF: case ITEM_PORTAL: case ITEM_TOTEM: case ITEM_CART: size = SIZE_LARGE; break; case ITEM_BOAT: case ITEM_FOUNTAIN: size = SIZE_HUGE; break; default: size = SIZE_FINE; break; } if (size > 0) { obj->size = size; // bug("fix_sizes: obj vnum %d with bad size, fixed.", obj->vnum); } } pop_call(); return; } /* * calculate obj hit points in edit and loading. */ void load_obj_hit( OBJ_INDEX_DATA *obj ) { int hit; push_call("load_obj_hit(%p)", obj); switch (obj->item_type) { default: hit = obj->size * material_table[obj->material].hit; break; case ITEM_WEAPON: hit = weapon_table[obj->value[0]].weight / 10; break; case ITEM_ARMOR: hit = armor_table[obj->value[0]].ac_bonus * 5; break; case ITEM_SYMBOL: case ITEM_KEY: case ITEM_SCROLL: case ITEM_SPELLPOUCH: case ITEM_AMMO: case ITEM_PAPER: case ITEM_MAP: case ITEM_POTION: case ITEM_DRINK_CON: case ITEM_TOOLS: case ITEM_PIECE: case ITEM_TRAP: case ITEM_SHEATH: case ITEM_QUIVER: hit = ROUNDUP(obj->size / 2) * material_table[obj->material].hit; break; case ITEM_SPELLBOOK: case ITEM_BOOK: case ITEM_BOAT: case ITEM_FOUNTAIN: hit = obj->size * obj->size * material_table[obj->material].hit; break; } if (hit > 0) { obj->hit_points = hit; } pop_call(); return; } /* creation and deletion for OLC - Scandum 22-06-2002 */ void create_shop( MOB_INDEX_DATA *mob ) { SHOP_DATA *pShop; int iTrade; push_call("create_shop(%p)",mob); ALLOCMEM(pShop, SHOP_DATA, 1); pShop->keeper = mob->vnum; for (iTrade = 0 ; iTrade < MAX_TRADE ; iTrade++) { pShop->buy_type[iTrade] = ITEM_NOTHING; } pShop->profit_buy = 100; pShop->profit_sell = 50; pShop->open_hour = 0; pShop->close_hour = 23; mob->pShop = pShop; LINK(pShop, mud->f_shop, mud->l_shop, next, prev); mud->top_shop++; pop_call(); return; } void delete_shop( MOB_INDEX_DATA *mob ) { push_call("delete_shop(%p)",mob); if (mob->pShop) { UNLINK(mob->pShop, mud->f_shop, mud->l_shop, next, prev); FREEMEM(mob->pShop); mob->pShop = NULL; --mud->top_shop; } pop_call(); return; } void create_stable( MOB_INDEX_DATA *mob ) { STABLE_DATA *pStable; push_call("create_stable(%p)",mob); ALLOCMEM(pStable, STABLE_DATA, 1); pStable->keeper = mob->vnum; pStable->room = 0; pStable->shop_flags = 0; pStable->rent = 50; pStable->open_hour = 0; pStable->close_hour = 23; mob->pStable = pStable; LINK(pStable, mud->f_stable, mud->l_stable, next, prev); mud->top_stable++; pop_call(); return; } void delete_stable( MOB_INDEX_DATA *mob ) { push_call("delete_stable(%p)",mob); if (mob->pStable) { UNLINK(mob->pStable, mud->f_stable, mud->l_stable, next, prev); FREEMEM(mob->pStable); mob->pStable = NULL; --mud->top_stable; } pop_call(); return; } void create_inn( MOB_INDEX_DATA *mob ) { INN_DATA *pInn; int iRoom; push_call("create_inn(%p)",mob); ALLOCMEM(pInn, INN_DATA, 1); pInn->keeper = mob->vnum; for (iRoom = 0 ; iRoom < MAX_INN_ROOMS ; iRoom++) { pInn->room[iRoom] = -1; } for (iRoom = 0 ; iRoom < MAX_INN_ROOMS ; iRoom++) { pInn->rent[iRoom] = 50; } pInn->shop_flags = 0; pInn->open_hour = 0; pInn->close_hour = 23; mob->pInn = pInn; LINK(pInn, mud->f_inn, mud->l_inn, next, prev); mud->top_inn++; pop_call(); return; } void delete_inn( MOB_INDEX_DATA *mob ) { push_call("delete_inn(%p)",mob); if (mob->pInn) { UNLINK(mob->pInn, mud->f_inn, mud->l_inn, next, prev); FREEMEM(mob->pInn); mob->pInn = NULL; --mud->top_inn; } pop_call(); return; } void create_exit( ROOM_INDEX_DATA *room, int door) { EXIT_DATA *pExit; push_call("create_exit(%p,%d)",room,door); if (room->exit[door] != NULL) { pop_call(); return; } ALLOCMEM(pExit, EXIT_DATA, 1); pExit->description = STRDUPE(str_empty); pExit->keyword = STRDUPE(str_empty); pExit->pvnum = -1; pExit->vnum = -1; pExit->key = -1; room->exit[door] = pExit; mud->top_exit++; pop_call(); return; } void delete_exit( ROOM_INDEX_DATA *room, int door) { EXIT_DATA *pExit; push_call("delete_exit(%p,%d)",room,door); if ((pExit = room->exit[door]) == NULL) { pop_call(); return; } STRFREE(pExit->keyword); STRFREE(pExit->description); FREEMEM(pExit); mud->top_exit--; room->exit[door] = NULL; pop_call(); return; } void create_room( int vnum ) { ROOM_INDEX_DATA *room; push_call("create_room(%d)",vnum); ALLOCMEM(room, ROOM_INDEX_DATA, 1); room_index[vnum] = room; mud->top_room++; pop_call(); return; } bool delete_room( ROOM_INDEX_DATA *room ) { bool door; int vnum; ROOM_INDEX_DATA *prev; OBJ_DATA *o; CHAR_DATA *ch; EXTRA_DESCR_DATA *ed; RESET_DATA *pReset; push_call("delete_room(%p)",room); switch (room->vnum) { case ROOM_VNUM_LIMBO: case ROOM_VNUM_JUNK: case ROOM_VNUM_TEMPLE: case ROOM_VNUM_SCHOOL: case ROOM_VNUM_ARENA: case ROOM_VNUM_CLANHALLS: log_printf("Refusing to delete hardcore vnum: %d", room->vnum); dump_stack(); pop_call(); return FALSE; } del_room_timer(room->vnum, -1); while ((ch = room->first_person) != NULL) { if (!IS_NPC(ch)) { char_from_room(ch); char_to_room(ch, ROOM_VNUM_TEMPLE, TRUE); } else { log_printf("junking mob %s", ch->name); junk_mob(ch); } } while ((o = room->first_content) != NULL) { junk_obj(o); } while ((ed = room->first_extradesc) != NULL) { room->first_extradesc = ed->next; STRFREE(ed->keyword); STRFREE(ed->description); FREEMEM(ed ); --mud->top_ed; } if (!IS_SET(room->room_flags, ROOM_HASH)) { for (pReset = room->area->first_reset ; pReset ; ) { if (is_room_reset(pReset, room)) { delete_reset(room->area, pReset); pReset = room->area->first_reset; } else { pReset = pReset->next; } } for (vnum = 0 ; vnum < MAX_VNUM ; vnum++) { if ((prev = room_index[vnum]) == NULL) { continue; } for (door = 0 ; door <= 5 ; door++) { if (prev->exit[door] == NULL) { continue; } if (prev->exit[door]->vnum != room->vnum) { continue; } log_printf("[%u] Deleting connection to room [%u]", prev->vnum, prev->exit[door]->vnum); delete_exit(prev, door); } } if (room->vnum == room->area->low_r_vnum) { vnum = room->area->low_r_vnum + 1; for (room->area->low_r_vnum = MAX_VNUM-1 ; vnum <= room->area->hi_r_vnum ; vnum++) { if ((prev = get_room_index(vnum)) == NULL) { continue; } if (prev->area != room->area) { continue; } room->area->low_r_vnum = prev->vnum; break; } } if (room->vnum == room->area->hi_r_vnum) { vnum = room->area->hi_r_vnum - 1; for (room->area->hi_r_vnum = 0 ; vnum >= room->area->low_r_vnum ; vnum--) { if ((prev = get_room_index(vnum)) == NULL) { continue; } if (prev->area != room->area) { continue; } room->area->hi_r_vnum = prev->vnum; break; } } } for (door = 0 ; door <= 5 ; door++) { if (room->exit[door] == NULL) { continue; } /* log_printf("[%u] Deleting connection to room [%u]", room->vnum, room->exit[door]->vnum); */ delete_exit(room, door); } for (door = 0 ; door < MAX_LAST_LEFT ; door++) { STRFREE(room->last_left[door]); } STRFREE (room->name); STRFREE (room->description); if (room->vnum >= ROOM_VNUM_WILDERNESS) { room_index[room->vnum] = room_index[ROOM_VNUM_WILDERNESS + room->sector_type]; } else { room_index[room->vnum] = NULL; } FREEMEM(room ); --mud->top_room; pop_call(); return TRUE; } bool delete_obj( OBJ_INDEX_DATA *obj ) { EXTRA_DESCR_DATA *ed; AFFECT_DATA *af; RESET_DATA *pReset; push_call("delete_obj(%p)",obj); if (obj->vnum < 100) { log_printf("Refusing to delete hardcore vnum: %d", obj->vnum); dump_stack(); pop_call(); return FALSE; } while (obj->first_instance) { extract_obj(obj->first_instance); } for (pReset = obj->area->first_reset ; pReset ; ) { if (is_obj_reset(pReset, obj)) { delete_reset(obj->area, pReset); pReset = obj->area->first_reset; } else { pReset = pReset->next; } } /* Remove references to object index */ while ((ed = obj->first_extradesc) != NULL) { obj->first_extradesc = ed->next; STRFREE (ed->keyword); STRFREE (ed->description); FREEMEM(ed); --mud->top_ed; } while ((af = obj->first_affect) != NULL) { obj->first_affect = af->next; FREEMEM(af); --mud->top_affect; } if (obj->vnum == obj->area->low_o_vnum && obj->vnum == obj->area->hi_o_vnum) { obj->area->low_o_vnum = MAX_VNUM - 1; obj->area->hi_o_vnum = 0; } else if (obj->vnum == obj->area->low_o_vnum) { for (obj->area->low_o_vnum++ ; obj->area->low_o_vnum <= obj->area->hi_o_vnum ; obj->area->low_o_vnum++) { if (obj_index[obj->area->low_o_vnum] != NULL) { break; } } } else if (obj->vnum == obj->area->hi_o_vnum) { for (obj->area->hi_o_vnum-- ; obj->area->hi_o_vnum >= obj->area->low_o_vnum ; obj->area->hi_o_vnum--) { if (obj_index[obj->area->hi_o_vnum] != NULL) { break; } } } STRFREE (obj->name); STRFREE (obj->short_descr); STRFREE (obj->long_descr); STRFREE (obj->description); STRFREE (obj->attack_string); obj_index[obj->vnum] = NULL; FREEMEM(obj); --mud->top_obj_index; pop_call(); return TRUE; } /* Scandum 28-04-2002 */ bool delete_mob( MOB_INDEX_DATA *mob ) { int vnum; MOB_INDEX_DATA *prev; RESET_DATA *pReset; push_call("delete_mob(%p)",mob); if (mob->vnum >= 9900 && mob->vnum < 10000) { log_printf("Refusing to delete hardcore vnum: %d", mob->vnum); dump_stack(); pop_call(); return FALSE; } while (mob_index[mob->vnum]->first_instance) { extract_char(mob_index[mob->vnum]->first_instance); } for (pReset = mob->area->first_reset ; pReset ; ) { if (is_mob_reset(pReset, mob)) { delete_reset(mob->area, pReset); pReset = mob->area->first_reset; } else { pReset = pReset->next; } } if (mob->pShop) { delete_shop(mob); } if (mob->pStable) { delete_shop(mob); } if (mob->pInn) { delete_inn(mob); } if (mob->vnum == mob->area->low_m_vnum) { vnum = mob->area->low_m_vnum+1; for (mob->area->low_m_vnum = MAX_VNUM-1 ; vnum <= mob->area->hi_m_vnum ; vnum++) { if ((prev = get_mob_index(vnum)) == NULL) { continue; } if (prev->area != mob->area) { continue; } mob->area->low_m_vnum = prev->vnum; break; } } if (mob->vnum == mob->area->hi_m_vnum) { vnum = mob->area->hi_m_vnum-1; for (mob->area->hi_m_vnum = 0 ; vnum > mob->area->low_m_vnum ; vnum--) { if ((prev = get_mob_index(vnum)) == NULL) { continue; } if (prev->area != mob->area) { continue; } mob->area->hi_m_vnum = prev->vnum; break; } } STRFREE (mob->player_name); STRFREE (mob->short_descr); STRFREE (mob->long_descr); STRFREE (mob->description); STRFREE (mob->reset_msg); mob_index[mob->vnum] = NULL; FREEMEM(mob); --mud->top_mob_index; pop_call(); return TRUE; } bool delete_help( HELP_DATA *help ) { HELP_MENU_DATA *menu; push_call("delete_help(%p)",help); while ((menu = help->first_menu) != NULL) { help->first_menu = menu->next; FREEMEM(menu); } STRFREE (help->keyword); STRFREE (help->title); STRFREE (help->text); UNLINK(help, help->area->first_help, help->area->last_help, next, prev); FREEMEM(help); --mud->top_help; pop_call(); return TRUE; } int get_alloc_size( unsigned char *str ) { push_call("get_alloc_size(%p)",str); if (str == NULL) { log_printf("get_alloc_size: null pointer"); pop_call(); return -1; } if (*(str-1) != *(str-2) + *(str-3) + *(str-4)) { log_printf("get_alloc_size: failed check sum"); pop_call(); return -1; } switch (*(str-3)) { case 'F': case 'D': case 'S': pop_call(); return rgSizeList[*(str-2)]; } log_printf("get_alloc_size: bad block type"); pop_call(); return -1; } unsigned char *set_block_header( bool iBlock, bool typ, bool iList, bool *pMem ) { push_call("set_block_header(%p,%p,%p,%p)",iBlock,typ,iList,pMem); *pMem = iBlock; /* Index for perm_block_index */ pMem++; *pMem = typ; /* D dynamic, P perm, F Free */ pMem++; *pMem = iList; /* Index for rgSizeList */ pMem++; *pMem = iList + typ + iBlock; /* Checksum */ pMem++; pop_call(); return( pMem ); } void set_block_type( bool typ, bool *pMem ) { push_call("set_block_type(%p,%p)",typ,pMem); *(pMem-3) = typ; *(pMem-1) = *(pMem-2) + *(pMem-3) + *(pMem-4); pop_call(); return; } /* Allocate some ordinary memory, with the expectation of freeing it someday. */ void *alloc_mem( int sMem ) { PERM_BLOCK_LIST *pBlock; bool iList, *pMem; push_call("alloc_mem(%d)",sMem); for (iList = 0 ; iList < MAX_MEM_LIST ; iList++) { if (sMem <= rgSizeList[iList]) { break; } } if (iList == MAX_MEM_LIST) { log_printf("alloc_mem: size %d too large.", sMem); dump_stack(); abort(); } if (rgFreeList[iList] == NULL) { pMem = (bool *) alloc_perm(iList); rgUsedCount[iList]++; } else { pMem = (bool *) rgFreeList[iList]; rgFreeList[iList] = rgFreeList[iList]->next; rgFreeCount[iList]--; pBlock = perm_block_index[*(pMem-4)]; if (get_alloc_size(pMem) != rgSizeList[iList]) { log_string("alloc_mem: allocating a free with wrong size"); dump_stack(); pMem = (bool *) alloc_perm(iList); rgUsedCount[iList]++; tot_memory_warning++; } else if (pBlock == NULL || (bool *) pBlock > pMem || (bool *) pBlock + MAX_PERM_BLOCK < pMem) { log_printf("free_mem: bad header: block index out of range"); dump_stack(); pMem = (bool *) alloc_perm(iList); rgUsedCount[iList]++; tot_memory_warning++; } else { rgUsedCount[iList]++; } } memset(pMem, 0, sMem); set_block_type('D', pMem); pop_call(); return ((void *) pMem); } /* Free some memory. Recycle it back onto the free list for blocks of that size. The pAdd is the pointer to the pointer of the memory. */ void free_mem( bool *pMem ) { FREE_MEM_LIST *fm; PERM_BLOCK_LIST *pBlock; bool iBlock, iList; push_call("free_mem(%p)",pMem); if (pMem == NULL) { log_printf("free_mem: null pointer"); dump_stack(); pop_call(); return; } iList = *(pMem-2); iBlock = *(pMem-4); if (get_alloc_size(pMem) < 0) { dump_stack(); tot_memory_warning++; pop_call(); return; } pBlock = perm_block_index[iBlock]; if (pBlock == NULL || (bool *) pBlock > pMem || (bool *) pBlock + MAX_PERM_BLOCK < pMem) { log_printf("free_mem: bad header: block index out of range"); dump_stack(); tot_memory_warning++; pop_call(); return; } fm = (FREE_MEM_LIST *) pMem; fm->next = rgFreeList[iList]; rgFreeList[iList] = fm; rgFreeCount[iList]++; rgUsedCount[iList]--; set_block_type( 'F', pMem ); pop_call(); return; } /* Allocate some permanent memory. Permanent memory is never freed, pointers into it may be copied safely. */ void *alloc_perm( bool iList ) { int sMem; PERM_BLOCK_LIST *pBlock; bool block_index, *pMem; push_call("alloc_perm(%p)", iList); sMem = rgSizeList[iList]; sMem += 4; /* Add 4 bytes for header */ for (block_index = 0 ; block_index < 255 && perm_block_index[block_index] ; block_index++) { if (perm_block_index[block_index]->iMemPerm + sMem < MAX_PERM_BLOCK) { break; } } if (block_index == 255) { log_string( "alloc_perm: no free blocks left" ); abort(); } pBlock = perm_block_index[block_index]; if (pBlock == NULL) { if ((pBlock = calloc(1, MAX_PERM_BLOCK)) == NULL) { perror("alloc_perm"); abort(); } pBlock->iMemPerm = sizeof( *pBlock ); perm_block_index[block_index] = pBlock; } pMem = (bool *) pBlock + pBlock->iMemPerm; pBlock->iMemPerm += sMem; set_block_header(block_index, 'P', iList, pMem); pop_call(); return (void *) (pMem+4); } void do_memory( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; int cnt, Ftotal, Utotal, Ptotal; push_call("do_memory(%p,%p)",ch,argument); buf[0] = '\0'; cat_sprintf(buf, "{078}Players: {178}%6d ", mud->total_plr); cat_sprintf(buf, "{078}Descs: {178}%6d ", mud->total_desc); cat_sprintf(buf, "{078}Areas: {178}%6d ", mud->top_area); cat_sprintf(buf, "{078}Helps: {178}%6d\n\r", mud->top_help); cat_sprintf(buf, "{078}Rooms: {178}%6d ", mud->top_room); cat_sprintf(buf, "{078}MobsIn: {178}%6d ", mud->top_mob_index); cat_sprintf(buf, "{078}ObjsIn: {178}%6d ", mud->top_obj_index); cat_sprintf(buf, "{078}Resets: {178}%6d\n\r", mud->top_reset); cat_sprintf(buf, "{078}Exits: {178}%6d ", mud->top_exit); cat_sprintf(buf, "{078}Mobs: {178}%6d ", mud->total_mob); cat_sprintf(buf, "{078}Objs: {178}%6d ", mud->total_obj); cat_sprintf(buf, "{078}Affects: {178}%6d\n\r", mud->top_affect); cat_sprintf(buf, "{078}Shops: {178}%6d ", mud->top_shop); cat_sprintf(buf, "{078}Stables: {178}%6d ", mud->top_stable); cat_sprintf(buf, "{078}Inns: {178}%6d ", mud->top_inn); cat_sprintf(buf, "{078}Skills: {178}%6d\n\r", MAX_REAL_SKILL); cat_sprintf(buf, "{078}Mprog: {178}%6d ", mud->top_mprog); cat_sprintf(buf, "{078}Oprog: {178}%6d ", mud->top_oprog); cat_sprintf(buf, "{078}Extra: {178}%6d\n\r", mud->top_ed); Utotal = Ftotal = 0; for (cnt = 0 ; cnt < MAX_MEM_LIST ; cnt++) { Utotal += (4 + rgSizeList[cnt]) * rgUsedCount[cnt]; Ftotal += (4 + rgSizeList[cnt]) * rgFreeCount[cnt]; } for (Ptotal = 0 ; Ptotal < 255 ; Ptotal++) { if (perm_block_index[Ptotal] == NULL) { Ptotal *= MAX_PERM_BLOCK; break; } } cat_sprintf(buf, "\n\r"); cat_sprintf(buf, "{078}Perm Mem: {178}%8d ", Ptotal); cat_sprintf(buf, "{078}Used Mem: {178}%8d ", Utotal); cat_sprintf(buf, "{078}Free Mem: {178}%8d ", Ftotal); cat_sprintf(buf, "\n\r\n\r"); for (cnt = 0 ; cnt < MAX_MEM_LIST ; cnt++) { cat_sprintf(buf, "{178}%6d {118}%6d {128}%5d ", rgSizeList[cnt], rgUsedCount[cnt], rgFreeCount[cnt]); if (cnt % 4 == 3) { strcat(buf, "\n\r"); } } if (str_suffix("\n\r", buf)) { strcat(buf, "\n\r"); } if (tot_memory_warning) { cat_sprintf(buf, "\n\r{018}Total Memory Warnings: {178}%8d\n\r", tot_memory_warning); } send_to_char_color(buf, ch); pop_call(); return; } /* Create new stuff (OLC) - Scandum 10-07-2002 */ ROOM_INDEX_DATA *make_room( int vnum ) { ROOM_INDEX_DATA *pRoomIndex; bool door; push_call("make_room(%p)",vnum); if (get_area_from_vnum(vnum) == NULL) { log_printf("make_room: failed to add area data."); pop_call(); return NULL; } ALLOCMEM( pRoomIndex, ROOM_INDEX_DATA, 1 ); pRoomIndex->vnum = vnum; pRoomIndex->area = get_area_from_vnum(vnum); if (vnum < pRoomIndex->area->low_r_vnum) { pRoomIndex->area->low_r_vnum = vnum; } if (vnum > pRoomIndex->area->hi_r_vnum) { pRoomIndex->area->hi_r_vnum = vnum; } pRoomIndex->name = STRALLOC("Floating in a void"); pRoomIndex->description = STRDUPE(str_empty); pRoomIndex->listen_desc = STRDUPE(str_empty); pRoomIndex->night_desc = STRDUPE(str_empty); for (door = 0 ; door < MAX_LAST_LEFT ; door++) { pRoomIndex->last_left[door] = STRDUPE(str_empty); } room_index[vnum] = pRoomIndex; mud->top_room++; pop_call(); return pRoomIndex; } OBJ_INDEX_DATA *make_object(int vnum) { OBJ_INDEX_DATA *pObjIndex; push_call("make_object(%p)",vnum); if (get_area_from_vnum(vnum) == NULL) { log_printf("Make_object: Failed to add area data to object."); pop_call(); return NULL; } ALLOCMEM( pObjIndex, OBJ_INDEX_DATA, 1 ); pObjIndex->vnum = vnum; pObjIndex->area = get_area_from_vnum(vnum); if (vnum < pObjIndex->area->low_o_vnum) { pObjIndex->area->low_o_vnum = vnum; } if (vnum > pObjIndex->area->hi_o_vnum) { pObjIndex->area->hi_o_vnum = vnum; } obj_index[vnum] = pObjIndex; pObjIndex->name = STRDUPE(str_empty); pObjIndex->short_descr = STRDUPE(str_empty); pObjIndex->long_descr = STRDUPE(str_empty); pObjIndex->description = STRDUPE(str_empty); pObjIndex->attack_string = STRDUPE(str_empty); pObjIndex->id_name = STRDUPE(str_empty); pObjIndex->id_descr = STRDUPE(str_empty); pObjIndex->item_type = ITEM_TRASH; pObjIndex->extra_flags = 0; pObjIndex->wear_flags = 0; pObjIndex->value[0] = 0; pObjIndex->value[1] = 0; pObjIndex->value[2] = 0; pObjIndex->value[3] = 0; pObjIndex->value[4] = 0; pObjIndex->value[5] = 0; pObjIndex->value[6] = 0; pObjIndex->value[7] = 0; pObjIndex->weight = 1; pObjIndex->cost = 10; pObjIndex->level = 1; pObjIndex->level = 1; pObjIndex->progtypes = 0; mud->top_obj_index++; pop_call(); return pObjIndex; } HELP_DATA * make_helpfile( char *argument, AREA_DATA *area ) { HELP_DATA *help; push_call("make_helpfile(%p,%p)",argument,area); ALLOCMEM(help, HELP_DATA, 1); help->level = 0; help->keyword = STRALLOC(argument); help->text = STRDUPE(str_empty); help->area = area; LINK (help, area->first_help, area->last_help, next, prev ); mud->top_help++; pop_call(); return help; } AREA_DATA * get_area_from_vnum (int vnum) { AREA_DATA * pArea; push_call("get_area_from_vnum(%p)",vnum); for (pArea = mud->f_area ; pArea ; pArea = pArea->next) { if (pArea->olc_range_lo <= vnum && pArea->olc_range_hi >= vnum) { break; } if (pArea->low_r_vnum <= vnum && pArea->hi_r_vnum >= vnum) { break; } if (pArea->low_m_vnum <= vnum && pArea->hi_m_vnum >= vnum) { break; } if (pArea->low_o_vnum <= vnum && pArea->hi_o_vnum >= vnum) { break; } } pop_call(); return pArea; } /* Create a new INDEX mobile (OLC) */ MOB_INDEX_DATA *make_mobile( int vnum ) { MOB_INDEX_DATA *pMobIndex; push_call("make_mobile(%p)",vnum); if (get_area_from_vnum(vnum) == NULL) { log_printf("make_mobile: couldn't find area.\n\r"); pop_call(); return NULL; } ALLOCMEM( pMobIndex, MOB_INDEX_DATA, 1 ); pMobIndex->vnum = vnum; pMobIndex->player_name = STRALLOC("newly created mobile"); pMobIndex->short_descr = STRALLOC("a newly created mobile"); pMobIndex->long_descr = STRALLOC("a newly created mobile stands here"); pMobIndex->description = STRALLOC(""); pMobIndex->act = ACT_SENTINEL; pMobIndex->level = 1; pMobIndex->hitplus = 0; pMobIndex->position = POS_STANDING; pMobIndex->area = get_area_from_vnum (vnum); if (vnum < pMobIndex->area->low_m_vnum) { pMobIndex->area->low_m_vnum = vnum; } if (vnum > pMobIndex->area->hi_m_vnum) { pMobIndex->area->hi_m_vnum = vnum; } mob_index[vnum] = pMobIndex; mud->top_mob_index++; pop_call(); return pMobIndex; } EXIT_DATA *make_exit( ROOM_INDEX_DATA *pRoomIndex, ROOM_INDEX_DATA *to_room, bool door ) { EXIT_DATA *pExit; push_call("make_exit(%p,%p,%p)",pRoomIndex,to_room,door); ALLOCMEM(pExit, EXIT_DATA, 1); pExit->exit_info = 0; pExit->pvnum = 0; pExit->key = -1; pExit->exit_size = 0; pExit->climb_dc = 0; pExit->fall_dist = 0; if (to_room) { pExit->to_room = to_room->vnum; pExit->vnum = to_room->vnum; } room_index[pRoomIndex->vnum]->exit[door] = pExit; mud->top_exit++; pop_call(); return pExit; } /* This routine makes sure that files are not cross linked or chopped Chaos - 4/26/99 */ bool is_valid_save( char *file_name , char *text_crc) { char buf[MAX_INPUT_LENGTH]; sh_int cnt, cf; FILE *fp; push_call("is_valid_save(%p,%p)",file_name,text_crc); if ((fp = my_fopen(file_name, "r", FALSE)) == NULL) { pop_call(); return( FALSE ); } fseek(fp, 0, SEEK_END); if (ftell(fp) < 10) { my_fclose(fp); log_printf("Oops, file system full! %s failed.", file_name); pop_call(); return( FALSE ); } cf = ' '; cnt = 0; while (cf != '#' && cnt > -25) { cnt--; fseek(fp, cnt, SEEK_END); cf = fgetc( fp ); } if (cnt < -25) { my_fclose(fp); log_printf("Didn't find an #%s on %s", text_crc, file_name); pop_call(); return( FALSE ); } cf = fgetc(fp); for (cnt = 0 ; cf != '\n' && cf != EOF ; cnt++) { buf[cnt] = cf; cf = fgetc(fp); } buf[cnt] = '\0'; if (!strcmp(buf, text_crc)) { my_fclose( fp ); pop_call(); return( TRUE ); } my_fclose( fp ); log_printf("Cross linked file %s on %s", buf, file_name); pop_call(); return( FALSE ); } /* Save this class */ /* * Thanks for Erwin's MERC tips on dynamically * loading class tables - Kregor */ void fwrite_class (int num) { FILE *fp; char buf[MAX_STRING_LENGTH]; int sn; sprintf (buf, "%s/%s.txt", CLASSES_DIR, bits_to_str(num, "CLASS_")); close_reserve(); if ((fp = my_fopen(buf, "w", FALSE)) == NULL) { log_printf("Could not open file %s in order to save class.", buf); } fprintf( fp, "Name %s~\n", !is_string(class_table[num].who_name_long) ? strlower(bits_to_str(num, "CLASS_")) : class_table[num].who_name_long); fprintf( fp, "WhoName %s~\n", !is_string(class_table[num].who_name) ? "???" : class_table[num].who_name); fprintf( fp, "HitDice %d\n", class_table[num].hp_max ); fprintf( fp, "FORTSave %d\n", class_table[num].fort_save ); fprintf( fp, "REFLSave %d\n", class_table[num].refl_save ); fprintf( fp, "WILLSave %d\n", class_table[num].will_save ); fprintf( fp, "EntryLvl %d\n", class_table[num].pc_class ); fprintf( fp, "Mana %d\n", class_table[num].mana_table ); fprintf( fp, "BAB %d\n", class_table[num].base_attack ); fprintf( fp, "AttrPrime %d\n", class_table[num].attr_prime ); fprintf( fp, "AttrSecond %d\n", class_table[num].attr_second ); fprintf( fp, "PriMod %d\n", class_table[num].prime_mod ); fprintf( fp, "SecMod %d\n", class_table[num].sec_mod ); fprintf( fp, "SkillPts %d\n", class_table[num].skill_pts ); fprintf( fp, "MaxLevel %d\n", class_table[num].max_level ); fprintf( fp, "FirstFeat %d\n", class_table[num].first_bonus ); fprintf( fp, "FeatLevel %d\n", class_table[num].bonus_lvl ); for (sn = 0; *skill_table[sn].name != '\0' ; sn++) { if (skill_table[sn].name == NULL) continue; if (skill_table[sn].skill_level[num] < LEVEL_IMMORTAL) fprintf (fp, "Skill %d '%s'\n", skill_table[sn].skill_level[num], skill_table[sn].name); if (skill_table[sn].skilltype == FSKILL_FEAT && skill_table[sn].bonus_feat[num] < LEVEL_IMMORTAL) fprintf (fp, "BonusFeat %d '%s'\n", skill_table[sn].bonus_feat[num], skill_table[sn].name); } fprintf( fp, "%s", "EndClass\n\n" ); my_fclose (fp); open_reserve(); } void save_classes() { int i; for (i = 0; i < MAX_CLASS; i++) { fwrite_class(i); } } /* Load a class */ void fread_class (int num) { char buf[MAX_STRING_LENGTH]; char *word; bool fMatch; FILE *fp; sprintf (buf, "%s/%s.txt", CLASSES_DIR, bits_to_str(num, "CLASS_")); close_reserve(); if ((fp = my_fopen(buf, "r", FALSE)) == NULL) { fwrite_class(num); fread_class(num); return; } for ( ; ; ) { word = feof(fp) ? "EndClass" : fread_word(fp); fMatch = FALSE; switch (word[0]) { case 'A': NKEY("AttrPrime", class_table[num].attr_prime, fread_number(fp)); NKEY("AttrSecond", class_table[num].attr_second, fread_number(fp)); break; case 'B': if ( !strcasecmp( word, "BonusFeat" ) ) { int sn; int value; value = fread_number( fp ); sn = skill_lookup( fread_word( fp ) ); if (sn < 0) { bug("fread_class: %s - unknown skill.", class_table[num].who_name_long); } else if (skill_table[sn].skilltype == FSKILL_FEAT) { skill_table[sn].bonus_feat[num] = value; } fMatch = TRUE; break; } NKEY("BAB", class_table[num].base_attack, fread_number(fp)); break; case 'E': NKEY( "EntryLvl", class_table[num].pc_class, fread_number(fp)); if (!strcmp(word, "EndClass")) return; break; case 'F': NKEY( "FORTSave", class_table[num].fort_save, fread_number(fp)); NKEY( "FirstFeat", class_table[num].first_bonus, fread_number(fp)); NKEY( "FeatLevel", class_table[num].bonus_lvl, fread_number(fp)); break; case 'H': NKEY( "HitDice", class_table[num].hp_max, fread_number(fp)); break; case 'M': NKEY( "Mana", class_table[num].mana_table, fread_number(fp)); NKEY( "MaxLevel", class_table[num].max_level, fread_number(fp)); break; case 'N': if ( !strcasecmp( word, "Name" ) ) { char *name = STRALLOC(fread_string(fp)); if (!is_string(name)) sprintf(class_table[num].who_name_long, "%s", strlower(bits_to_str(num, "CLASS_"))); else sprintf(class_table[num].who_name_long, "%s", name); fMatch = TRUE; break; } break; case 'P': NKEY( "PriMod", class_table[num].prime_mod, fread_number(fp)); case 'R': NKEY( "REFLSave", class_table[num].refl_save, fread_number(fp)); case 'S': if ( !strcasecmp( word, "Skill" ) ) { int sn; int value; value = fread_number( fp ); sn = skill_lookup( fread_word( fp ) ); if (sn < 0) { bug("fread_class: %s - unknown skill.", class_table[num].who_name_long); } else { skill_table[sn].skill_level[num] = value; } fMatch = TRUE; break; } NKEY( "SecMod", class_table[num].sec_mod, fread_number(fp)); NKEY( "SkillPts", class_table[num].skill_pts, fread_number(fp)); break; case 'W': if ( !strcasecmp( word, "WhoName" ) ) { char *name = STRALLOC(fread_string(fp)); if (!is_string(name)) sprintf(class_table[num].who_name, "???"); else sprintf(class_table[num].who_name, "%s", name); fMatch = TRUE; break; } NKEY( "WILLSave", class_table[num].will_save, fread_number(fp)); break; } if (fMatch == FALSE) { log_printf("fread_class: no match: %s %s", word, fread_line(fp)); } } my_fclose (fp); open_reserve(); } void load_classes () { int cls,sn; log_string("Loading Class Table..."); for (cls = 0; cls < MAX_CLASS; cls++) { for (sn = 0; *skill_table[sn].name != '\0' ; sn++) { skill_table[sn].skill_level[cls] = LEVEL_IMMORTAL; skill_table[sn].bonus_feat[cls] = LEVEL_IMMORTAL; } fread_class(cls); } // for (sn = 0; *skill_table[sn].name != '\0' ; sn++) // { // if (skill_table[sn].skilltype != FSKILL_FEAT) // continue; // if (IS_SET(skill_table[sn].spell_school, FEAT_ROGUE)) // { // skill_table[sn].bonus_feat[CLASS_ROGUE] = IS_SET(skill_table[sn].spell_school, FEAT_ADVANCED) ? 10 : 1; // } // if (IS_SET(skill_table[sn].spell_school, FEAT_METAMAGIC|FEAT_CREATION|FEAT_WIZARD)) // { // skill_table[sn].bonus_feat[CLASS_WIZARD] = 1; // skill_table[sn].bonus_feat[CLASS_LOREMASTER] = 1; // } // if (IS_SET(skill_table[sn].spell_school, FEAT_FIGHTER)) // { // skill_table[sn].bonus_feat[CLASS_FIGHTER] = 1; // skill_table[sn].bonus_feat[CLASS_ELDRITCH_KNIGHT] = 1; // } // if (IS_SET(skill_table[sn].spell_school, FEAT_PALADIN)) // { // skill_table[sn].bonus_feat[CLASS_PALADIN] = 1; // skill_table[sn].bonus_feat[CLASS_BLACKGUARD] = 1; // } // } } /* Save this domain skill table */ void save_domain (int num) { FILE *fp; char buf[MAX_STRING_LENGTH]; int lev, i; sprintf (buf, "%s/%s.txt", DOMAIN_DIR, domain_types[num]); close_reserve(); if ((fp = my_fopen(buf, "w", FALSE)) == NULL) { log_printf("Could not open file %s in order to save domain %s.", buf, domain_types[num]); return; } for (lev = 0; lev < LEVEL_IMMORTAL; lev++) { for (i = 0; *skill_table[i].name != '\0'; i++) { if (!skill_table[i].name || !skill_table[i].name[0]) continue; if (skill_table[i].domains[num] == lev) fprintf (fp, "%d %s\n", lev, skill_table[i].name); } } fprintf (fp, "-1"); /* EOF -1 */ my_fclose (fp); open_reserve(); } void save_domains() { int i; for (i = 0; i < MAX_DOMAIN; i++) save_domain (i); } /* Load a domain skill table */ void load_domain (int num) { char buf[MAX_STRING_LENGTH]; int level,n; FILE *fp; sprintf (buf, "%s/%s.txt", DOMAIN_DIR, domain_types[num]); close_reserve(); if ((fp = my_fopen(buf, "r", FALSE)) == NULL) { log_printf ("Could not open file %s in order to load domain %s.", buf, domain_types[num]); return; } fscanf (fp, "%d", &level); while (level != -1) { fscanf (fp, " %[^\n]\n", buf); /* read name of skill into buf */ n = skill_lookup (buf); /* find index */ if (n == -1) { char buf2[200]; sprintf (buf2, "Domain %s: unknown skill/spell %s", domain_types[num], buf); log_printf (buf2, 0); } else skill_table[n].domains[num] = level; fscanf (fp, "%d", &level); } my_fclose (fp); open_reserve(); } void load_domains () { int i,j; log_string("Skill Table: Domains..."); for (i = 0; i < MAX_DOMAIN; i++) { for (j = 0; *skill_table[j].name != '\0'; j++) { skill_table[j].domains[i] = LEVEL_IMMORTAL; } load_domain (i); } } /* Save this style */ void save_style (int num) { FILE *fp; char buf[MAX_STRING_LENGTH]; int lev, i; sprintf (buf, "%s/%s.txt", STYLE_DIR, combat_styles[num]); close_reserve(); if ((fp = my_fopen(buf, "w", FALSE)) == NULL) { log_printf("Could not open file %s in order to save style %s.", buf, combat_styles[num]); return; } for (lev = 0; lev < LEVEL_IMMORTAL; lev++) { for (i = 0; *skill_table[i].name != '\0' ; i++) { if (!skill_table[i].name || !skill_table[i].name[0]) continue; if (skill_table[i].styles[num] == lev) fprintf (fp, "%d %s\n", lev, skill_table[i].name); } } fprintf (fp, "-1"); /* EOF -1 */ my_fclose (fp); open_reserve(); } void save_styles() { int i; for (i = 0; i < STYLE_MAX; i++) save_style (i); } /* Load a style */ void load_style (int num) { char buf[MAX_STRING_LENGTH]; int level,n; FILE *fp; sprintf (buf, "%s/%s.txt", STYLE_DIR, combat_styles[num]); close_reserve(); if ((fp = my_fopen(buf, "r", FALSE)) == NULL) { log_printf ("Could not open file %s in order to load style %s.", buf, combat_styles[num]); return; } fscanf (fp, "%d", &level); while (level != -1) { fscanf (fp, " %[^\n]\n", buf); /* read name of skill into buf */ n = skill_lookup (buf); /* find index */ if (n == -1) { char buf2[200]; sprintf (buf2, "Style %s: unknown skill/spell %s", combat_styles[num], buf); log_printf (buf2, 0); } else skill_table[n].styles[num] = level; fscanf (fp, "%d", &level); } my_fclose (fp); open_reserve(); } void load_styles () { int i,j; log_string("Skill Table: Combat Styles..."); for (i = 0; i < STYLE_MAX; i++) { for (j = 0; *skill_table[j].name != '\0' ; j++) { skill_table[j].styles[i] = LEVEL_IMMORTAL; } load_style (i); } } /* Save this race */ void fwrite_race (int num) { FILE *fp; char buf[MAX_STRING_LENGTH]; int sn; sprintf (buf, "%s/%s.txt", RACE_DIR, bits_to_str(num, "RACE_")); close_reserve(); if ((fp = my_fopen(buf, "w", FALSE)) == NULL) { log_printf("Could not open file %s in order to save race.", buf); } fprintf( fp, "Name %s~\n", !is_string(race_table[num].race_name) ? strlower(bits_to_str(num, "RACE_")) : race_table[num].race_name); fprintf( fp, "Size "); break_bits( fp, race_table[num].size, "SIZE_", TRUE); fprintf( fp, "\n" ); fprintf( fp, "RaceType "); break_bits( fp, race_table[num].type, "RTYPE_", TRUE); fprintf( fp, "\n" ); fprintf( fp, "BodyType "); break_bits( fp, race_table[num].body_type, "BTYPE_", TRUE); fprintf( fp, "\n" ); fprintf( fp, "HitDice %d\n", race_table[num].hit_dice ); fprintf( fp, "SpeedLand %d\n", race_table[num].land_speed ); fprintf( fp, "SpeedBurrow %d\n", race_table[num].burrow_speed ); fprintf( fp, "SpeedClimb %d\n", race_table[num].climb_speed ); fprintf( fp, "SpeedFly %d\n", race_table[num].fly_speed ); fprintf( fp, "SpeedSwim %d\n", race_table[num].swim_speed ); fprintf( fp, "NaturalAC %d\n", race_table[num].nat_armor ); fprintf( fp, "DeflectAC %d\n", race_table[num].deflection ); fprintf( fp, "PCRace %d\n", race_table[num].pcrace ); fprintf( fp, "Align %d\n", race_table[num].alignment ); fprintf( fp, "Ethos %d\n", race_table[num].ethos ); fprintf( fp, "AttrMod %d %d %d %d %d %d\n", race_table[num].race_mod[0], race_table[num].race_mod[1], race_table[num].race_mod[2], race_table[num].race_mod[3], race_table[num].race_mod[4], race_table[num].race_mod[5] ); fprintf( fp, "Nonabil %d %d %d %d %d %d\n", race_table[num].nonability[0], race_table[num].nonability[1], race_table[num].nonability[2], race_table[num].nonability[3], race_table[num].nonability[4], race_table[num].nonability[5] ); fprintf( fp, "Weight %d\n", race_table[num].weight ); fprintf( fp, "Height %d\n", race_table[num].height ); fprintf( fp, "ParentRace "); break_bits( fp, race_table[num].parent_race, "RACE_", TRUE); fprintf( fp, "\n" ); fprintf( fp, "Material "); break_bits( fp, race_table[num].material, "MATERIAL_", TRUE); fprintf( fp, "\n" ); fprintf( fp, "Vulnerable "); break_bits( fp, race_table[num].vulnerability, "DAM_", FALSE); fprintf( fp, "\n" ); fprintf( fp, "AffectedBy "); break_bits( fp, race_table[num].affected_by, "AFF_", FALSE); fprintf( fp, "\n" ); fprintf( fp, "Speaks "); break_bits( fp, race_table[num].speaks, "LANG_", FALSE); fprintf( fp, "\n" ); fprintf( fp, "Understands "); break_bits( fp, race_table[num].understands, "LANG_", FALSE); fprintf( fp, "\n" ); fprintf( fp, "BonusLangs "); break_bits( fp, race_table[num].bonus_langs, "LANG_", FALSE); fprintf( fp, "\n" ); fprintf( fp, "Specials "); break_bits( fp, race_table[num].flags, "RSPEC_", FALSE); fprintf( fp, "\n" ); fprintf( fp, "Sectors "); break_bits( fp, race_table[num].sectors, "RACESECT_", FALSE); fprintf( fp, "\n" ); fprintf( fp, "WearLocs "); break_bits( fp, race_table[num].wear_locs, "CAN_WEAR", FALSE); fprintf( fp, "\n" ); if (race_table[num].poison) { fprintf( fp, "Poison "); break_bits( fp, race_table[num].poison_part, "ATTK_", TRUE); fprintf( fp, " " ); break_bits( fp, race_table[num].poison, "POISON_", TRUE); fprintf( fp, "\n" ); } if (race_table[num].disease) { fprintf( fp, "Disease "); break_bits( fp, race_table[num].disease_part, "ATTK_", TRUE); fprintf( fp, " " ); break_bits( fp, race_table[num].disease, "DIS_", TRUE); fprintf( fp, "\n" ); } fprintf( fp, "FavoredCls "); break_bits( fp, race_table[num].favored_class, "CLASS_", TRUE); fprintf( fp, "\n" ); fprintf( fp, "LevelAdj %d\n", race_table[num].lvl_adj ); fprintf( fp, "Align %d\n", race_table[num].alignment ); fprintf( fp, "Ethos %d\n", race_table[num].ethos ); for (sn = 0; *skill_table[sn].name != '\0' ; sn++) { if (skill_table[sn].name == NULL) continue; if (skill_table[sn].race_skill[num]) fprintf (fp, "Skill %d '%s'\n", skill_table[sn].race_skill[num], skill_table[sn].name); } for (sn = 0; sn < MAX_APPLY; sn++) { if (race_table[num].apply[sn]) { fprintf (fp, "Apply "); break_bits( fp, sn, "APPLY_", TRUE); fprintf( fp, " %d\n", race_table[num].apply[sn] ); } } for (sn = 0; sn < ATTK_MAX; sn++) { if (race_table[num].attacks[sn]) { fprintf (fp, "Attack "); break_bits( fp, sn, "ATTK_", TRUE); fprintf( fp, " %d\n", race_table[num].attacks[sn] ); } } fprintf( fp, "%s", "EndRace\n\n" ); my_fclose (fp); open_reserve(); } void save_races() { int i; for (i = 0; i < MAX_RACE; i++) { fwrite_race(i); } } /* Load a race */ void fread_race (int num) { char buf[MAX_STRING_LENGTH]; char *word; char *line; bool fMatch; int x1,x2,x3,x4,x5,x6; int cnt; FILE *fp; sprintf (buf, "%s/%s.txt", RACE_DIR, bits_to_str(num, "RACE_")); close_reserve(); if ((fp = my_fopen(buf, "r", FALSE)) == NULL) { fwrite_race(num); fread_race(num); return; } for ( ; ; ) { word = feof(fp) ? "EndRace" : fread_word(fp); fMatch = FALSE; // if (!is_string(race_table[num].race_name)) // sprintf(race_table[num].race_name, strlower(bits_to_str(num, "RACE"))); // switch (word[0]) { case 'A': if ( !strcasecmp( word, "AttParts" ) ) { fMatch = TRUE; break; } NKEY("Align", race_table[num].alignment, fread_number(fp)); AKEY("Apply", race_table[num].apply, fread_number(fp)); AKEY("Attack", race_table[num].attacks, fread_number(fp)); NKEY("AffectedBy",race_table[num].affected_by, fread_number(fp)); if ( !strcasecmp( word, "AttrMod" ) ) { line = fread_line( fp ); x1=x2=x3=x4=x5=x6=0; sscanf( line, "%d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6 ); race_table[num].race_mod[0] = x1; race_table[num].race_mod[1] = x2; race_table[num].race_mod[2] = x3; race_table[num].race_mod[3] = x4; race_table[num].race_mod[4] = x5; race_table[num].race_mod[5] = x6; fMatch = TRUE; break; } break; case 'B': NKEY("BonusLangs", race_table[num].bonus_langs, fread_number(fp)); NKEY("BodyType", race_table[num].body_type, fread_number(fp)); break; case 'D': if ( !strcasecmp( word, "Disease" ) ) { int body; int value; body = fread_number( fp ); value = fread_number( fp ); if (!race_table[num].attacks) { bug("fread_race: %s - poisoned part not set in attack parts.", race_table[num].race_name); break; } if (disease_table[value].name == NULL) { bug("fread_race: %s - unknown disease type.", race_table[num].race_name); break; } race_table[num].disease_part = body; race_table[num].disease = value; fMatch = TRUE; break; } NKEY( "DeflectAC", race_table[num].deflection, fread_number(fp)); break; case 'E': NKEY( "Ethos", race_table[num].ethos, fread_number(fp)); if (!strcmp(word, "EndRace")) return; break; case 'F': NKEY( "FavoredCls", race_table[num].favored_class, fread_number(fp)); break; case 'H': NKEY( "Height", race_table[num].height, fread_number(fp)); NKEY( "HitDice", race_table[num].hit_dice, fread_number(fp)); break; case 'L': NKEY( "LevelAdj", race_table[num].lvl_adj, fread_number(fp)); break; case 'M': NKEY( "Material", race_table[num].material, fread_number(fp)); break; case 'N': NKEY( "NaturalAC", race_table[num].nat_armor, fread_number(fp)); if ( !strcasecmp( word, "Name" ) ) { char *name = STRALLOC(fread_string(fp)); if (!is_string(name)) sprintf(race_table[num].race_name, "%s", strlower(bits_to_str(num, "RACE_"))); else sprintf(race_table[num].race_name, "%s", name); fMatch = TRUE; break; } if ( !strcasecmp( word, "Nonabil" ) ) { line = fread_line( fp ); x1=x2=x3=x4=x5=x6=0; sscanf( line, "%d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6 ); race_table[num].nonability[0] = x1; race_table[num].nonability[1] = x2; race_table[num].nonability[2] = x3; race_table[num].nonability[3] = x4; race_table[num].nonability[4] = x5; race_table[num].nonability[5] = x6; fMatch = TRUE; break; } break; case 'P': if ( !strcasecmp( word, "PriPart" ) ) { fMatch = TRUE; break; } NKEY( "PCRace", race_table[num].pcrace, fread_number(fp)); NKEY( "ParentRace", race_table[num].parent_race, fread_number(fp)); if ( !strcasecmp( word, "Poison" ) ) { int body; int value; body = fread_number( fp ); value = fread_number( fp ); if (!race_table[num].attacks) { bug("fread_race: %s - poisoned part not set in attack parts.", race_table[num].race_name); break; } if (poison_table[value].name == NULL) { bug("fread_race: %s - unknown poison type.", race_table[num].race_name); break; } race_table[num].poison_part = body; race_table[num].poison = value; fMatch = TRUE; break; } break; case 'R': NKEY( "RaceType", race_table[num].type, fread_number(fp)); break; case 'S': NKEY( "Size", race_table[num].size, fread_number(fp)); NKEY( "Speaks", race_table[num].speaks, fread_number(fp)); NKEY( "Specials", race_table[num].flags, fread_number(fp)); NKEY( "SpeedBurrow", race_table[num].burrow_speed, fread_number(fp)); NKEY( "SpeedClimb", race_table[num].climb_speed, fread_number(fp)); NKEY( "SpeedFly", race_table[num].fly_speed, fread_number(fp)); NKEY( "SpeedLand", race_table[num].land_speed, fread_number(fp)); NKEY( "SpeedSwim", race_table[num].swim_speed, fread_number(fp)); NKEY( "Sectors", race_table[num].sectors, fread_number(fp)); if ( !strcasecmp( word, "Skill" ) ) { int sn; int value; value = fread_number( fp ); sn = skill_lookup( fread_word( fp ) ); if (sn < 0) { bug("fread_race: %s - unknown skill.", race_table[num].race_name); } else { skill_table[sn].race_skill[num] = value; } fMatch = TRUE; break; } break; case 'U': NKEY("Understands", race_table[num].understands, fread_number(fp)); break; case 'V': NKEY("Vulnerable", race_table[num].vulnerability, fread_number(fp)); break; case 'W': NKEY("WearLocs", race_table[num].wear_locs, fread_number(fp)); NKEY("Weight", race_table[num].weight, fread_number(fp)); break; } if (fMatch == FALSE) { log_printf("fread_race: no match: %s %s", word, fread_line(fp)); } } my_fclose (fp); open_reserve(); } void load_races () { int i; // int j; log_string("Loading Races..."); for (i = 0; i < MAX_RACE; i++) { // for (j = 0; *skill_table[j].name != '\0' ; j++) // { // skill_table[j].race_skill[i] = 0; // } fread_race(i); } } /* Save this god */ void fwrite_god (int num) { FILE *fp; char buf[MAX_STRING_LENGTH]; int cnt; sprintf (buf, "%s/%s.txt", GOD_DIR, bits_to_str(num, "GOD_")); close_reserve(); if ((fp = my_fopen(buf, "w", FALSE)) == NULL) { log_printf("Could not open file %s in order to save god.", buf); return; } fprintf( fp, "Name %s~\n", !is_string(god_table[num].god_name) ? strlower(bits_to_str(num, "GOD_")) : god_table[num].god_name); fprintf( fp, "LogMsg %s~\n", god_table[num].logout_msg ); for (cnt = 0; cnt < MAX_DOMAIN; cnt++) { if (!god_table[num].domain[cnt]) continue; fprintf (fp, "Domain "); break_bits( fp, cnt, "DOMAIN_", TRUE); fprintf( fp, " 1\n" ); } fprintf( fp, "Domain1 %d\n", god_table[num].domain1 ); fprintf( fp, "Domain2 %d\n", god_table[num].domain2 ); fprintf( fp, "FaveWeapon "); break_bits( fp, god_table[num].favored_weapon, "WEAPON_TYPE_", TRUE); fprintf( fp, "\n" ); fprintf( fp, "Align %d\n", god_table[num].align ); fprintf( fp, "Ethos %d\n", god_table[num].ethos ); fprintf( fp, "AlignHi %d\n", god_table[num].align_hi ); fprintf( fp, "AlignLo %d\n", god_table[num].align_lo ); fprintf( fp, "EthosHi %d\n", god_table[num].ethos_hi ); fprintf( fp, "EthosLo %d\n", god_table[num].ethos_lo ); fprintf( fp, "Race "); break_bits( fp, god_table[num].race, "RSPEC_", FALSE); fprintf( fp, "\n" ); fprintf( fp, "PaladinMulti "); break_bits( fp, god_table[num].paladin_multi, "FLAG_CLASS", FALSE); fprintf( fp, "\n" ); fprintf( fp, "MonkMulti "); break_bits( fp, god_table[num].monk_multi, "FLAG_CLASS", FALSE); fprintf( fp, "\n" ); for (cnt = 0; cnt < MAX_GOD; cnt++) { if (god_table[cnt].god_name == NULL) continue; if (god_table[num].faith_enemy[cnt] > 0) { fprintf (fp, "FaithEnemy "); break_bits( fp, cnt, "GOD_", TRUE); fprintf( fp, " 1\n" ); } } for (cnt = 0; cnt < MAX_GOD; cnt++) { if (god_table[cnt].god_name == NULL) continue; if (god_table[num].faith_ally[cnt]) { fprintf (fp, "FaithAlly "); break_bits( fp, cnt, "GOD_", TRUE); fprintf( fp, " 1\n" ); } } fprintf( fp, "%s", "EndGod\n\n" ); my_fclose (fp); open_reserve(); } void save_gods() { int i; for (i = 0; i < MAX_GOD; i++) { fwrite_god(i); } } /* Load a god */ void fread_god (int num) { char buf[MAX_STRING_LENGTH]; char *word; bool fMatch; int cnt; FILE *fp; sprintf (buf, "%s/%s.txt", GOD_DIR, bits_to_str(num, "GOD_")); close_reserve(); if ((fp = my_fopen(buf, "r", FALSE)) == NULL) { fwrite_god(num); fread_god(num); return; } for (cnt = 0 ; cnt < 5 ; cnt++) RESTRING(god_table[num].ranking[cnt], str_empty); for ( ; ; ) { word = feof(fp) ? "EndGod" : fread_word(fp); fMatch = FALSE; // if (!is_string(god_table[num].god_name)) // sprintf(god_table[num].god_name, strlower(bits_to_str(num, "GOD_"))); // switch (word[0]) { case 'A': NKEY("Align", god_table[num].align, fread_number(fp)); NKEY("AlignHi", god_table[num].align_hi, fread_number(fp)); NKEY("AlignLo", god_table[num].align_lo, fread_number(fp)); break; case 'D': NKEY( "Domain1", god_table[num].domain1, fread_number(fp)); NKEY( "Domain2", god_table[num].domain2, fread_number(fp)); AKEY( "Domain", god_table[num].domain, fread_number(fp)); break; case 'E': NKEY( "Ethos", god_table[num].ethos, fread_number(fp)); NKEY( "EthosHi", god_table[num].ethos_hi, fread_number(fp)); NKEY( "EthosLo", god_table[num].ethos_lo, fread_number(fp)); if (!strcmp(word, "EndGod")) { return; } break; case 'F': NKEY( "FaveWeapon", god_table[num].favored_weapon, fread_number(fp)); AKEY( "FaithEnemy", god_table[num].faith_enemy, fread_number(fp)); AKEY( "FaithAlly", god_table[num].faith_ally, fread_number(fp)); break; case 'L': if ( !strcasecmp( word, "LogMsg" ) ) { char *msg = STRALLOC(fread_string(fp)); sprintf(god_table[num].logout_msg, "%s", msg); fMatch = TRUE; } break; case 'M': NKEY( "MonkMulti", god_table[num].monk_multi, fread_number(fp)); break; case 'N': if ( !strcasecmp( word, "Name" ) ) { char *name = STRALLOC(fread_string(fp)); if (!is_string(name)) sprintf(god_table[num].god_name, "%s", strlower(bits_to_str(num, "GOD_"))); else sprintf(god_table[num].god_name, "%s", name); fMatch = TRUE; } break; case 'P': NKEY( "PaladinMulti", god_table[num].paladin_multi, fread_number(fp)); break; case 'R': NKEY( "Race", god_table[num].race, fread_number(fp)); break; } if (fMatch == FALSE) { log_printf("fread_god: no match: %s %s", word, fread_line(fp)); } } my_fclose (fp); open_reserve(); } void load_gods () { int i; log_string("Loading Gods..."); for (i = 0; i < MAX_GOD; i++) { fread_god(i); } } /* Save the components table */ void fwrite_components (void) { FILE *fp; char buf[MAX_STRING_LENGTH]; int i, j; sprintf (buf, "../skilltables/components.txt"); close_reserve(); if ((fp = my_fopen(buf, "w", FALSE)) == NULL) { log_printf("Could not open file %s in order to save components table.", buf); return; } for (i = 0; *skill_table[i].name != '\0'; i++) { if (!skill_table[i].name || !skill_table[i].name[0]) continue; if (skill_table[i].components[0] == 0) continue; fprintf (fp, "'%s'", skill_table[i].name); for (j = 0 ; j < 5 ;j++) { fprintf (fp, " "); break_bits( fp, skill_table[i].components[j], "COMP_", TRUE); } fprintf (fp, "\n\r"); } fprintf (fp, "End\n\r"); /* EOF */ my_fclose (fp); open_reserve(); } /* Load the components table */ void fread_components (void) { char buf[MAX_STRING_LENGTH]; char *word; int sn; FILE *fp; sprintf (buf, "../skilltables/components.txt"); close_reserve(); if ((fp = my_fopen(buf, "r", FALSE)) == NULL) { log_printf ("Could not open file %s in order to load components.", buf); // abort(); return; } log_printf ("Loading components..."); for ( ; ; ) { word = feof(fp) ? "End" : fread_word(fp); if (!strcmp(word, "End")) return; if ((sn = skill_lookup(word)) == -1) { log_printf("fread_components: no such skill: %s %s", word, fread_line(fp)); continue; } skill_table[sn].components[0] = fread_number(fp); skill_table[sn].components[1] = fread_number(fp); skill_table[sn].components[2] = fread_number(fp); skill_table[sn].components[3] = fread_number(fp); skill_table[sn].components[4] = fread_number(fp); } my_fclose (fp); open_reserve(); } /* Save the bloodline table */ void fwrite_bloodlines (void) { FILE *fp; char buf[MAX_STRING_LENGTH]; int i, j; sprintf (buf, "../skilltables/bloodline.txt"); close_reserve(); if ((fp = my_fopen(buf, "w", FALSE)) == NULL) { log_printf("Could not open file %s in order to save bloodline table.", buf); return; } for (i = 0; *skill_table[i].name != '\0'; i++) { if (!skill_table[i].name || !skill_table[i].name[0]) continue; for (j = 0 ; j < BLOODLINE_MAX ;j++) { if (skill_table[i].bloodline[j] >= 75) continue; fprintf (fp, "'%s'", skill_table[i].name); fprintf (fp, " "); break_bits( fp, j, "BLOODLINE_", TRUE); fprintf (fp, " %d \n", skill_table[i].bloodline[j]); } } fprintf (fp, "End\n\r"); /* EOF */ my_fclose (fp); open_reserve(); } /* Load the bloodline table */ void fread_bloodlines (void) { char buf[MAX_STRING_LENGTH]; char *word; int sn, i, j; FILE *fp; // initialize all skills to immortal first. for (i = 0; *skill_table[i].name != '\0'; i++) { if (!skill_table[i].name || !skill_table[i].name[0]) continue; for (j = 0 ; j < BLOODLINE_MAX ;j++) { skill_table[i].bloodline[j] = LEVEL_IMMORTAL; } } sprintf (buf, "../skilltables/bloodline.txt"); close_reserve(); if ((fp = my_fopen(buf, "r", FALSE)) == NULL) { log_printf ("Could not open file %s in order to load bloodline.", buf); // abort(); return; } log_printf ("Loading bloodline skill table..."); for ( ; ; ) { word = feof(fp) ? "End" : fread_word(fp); if (!strcmp(word, "End")) return; if ((sn = skill_lookup(word)) == -1) { log_printf("fread_bloodline: no such skill: %s %s", word, fread_line(fp)); continue; } skill_table[sn].bloodline[fread_number(fp)] = fread_number(fp); } my_fclose (fp); open_reserve(); }