Hans Birkeland Apr 12 1995 This file contains modifications needed to db.c. ---- Among the local variables add: int top_shop; int top_vnum_room; /* OLC */ int top_vnum_mob; /* OLC */ int top_vnum_obj; /* OLC */ int mobile_count = 0; ---- Among the local booting procedures add: void load_area args( ( FILE *fp ) ); void new_load_area args( ( FILE *fp ) ); /* OLC */ void load_helps args( ( FILE *fp ) ); ---- boot_db() add: if ( word[0] == '$' ) break; else if ( !str_cmp( word, "AREA" ) ) load_area (fpArea); /* OLC */ else if ( !str_cmp( word, "AREADATA" ) ) new_load_area(fpArea); else if ( !str_cmp( word, "HELPS" ) ) load_helps (fpArea); At the end of boot_db: /* * Fix up exits. * Declare db booting over. * Convert all old_format objcets to new_format, ROM OLC * Reset all areas once. * Load up the notes file. */ { fix_exits( ); fBootDb = FALSE; convert_objects( ); /* ROM OLC */ area_update( ); load_notes( ); } The test below is not necesary for the OLC, but I had some nasty crashes when the help_greeting wasn't read (new_descriptor crashed...). If you want it, add it before boot_db() returns. if ( !help_greeting ) /* Hugin */ { bug( "boot_db: No help_greeting read.", 0 ); help_greeting = "By what name do you wish to be known ? "; } ---- load_area() Put in this instead: void load_area( FILE *fp ) { AREA_DATA *pArea; pArea = alloc_perm( sizeof( *pArea ) ); /* OLC-Removed pArea->reset_first = NULL; pArea->reset_last = NULL; */ pArea->name = fread_string( fp ); /* pArea->recall = ROOM_VNUM_TEMPLE; ROM OLC */ pArea->area_flags = AREA_LOADING; /* OLC */ pArea->security = 9; /* OLC */ /* 9 -- Hugin */ pArea->builders = str_dup( "None" ); /* OLC */ pArea->lvnum = 0; /* OLC */ pArea->uvnum = 0; /* OLC */ pArea->vnum = top_area; /* OLC */ pArea->filename = str_dup( strArea ); /* OLC */ pArea->age = 15; pArea->nplayer = 0; pArea->empty = FALSE; /* ROM OLC*/ if ( !area_first ) area_first = pArea; if ( area_last ) { area_last->next = pArea; REMOVE_BIT(area_last->area_flags, AREA_LOADING); /* OLC */ } area_last = pArea; pArea->next = NULL; top_area++; return; } ---- Drop this in after load_area(): /* * OLC * Use these macros to load any new area formats that you choose to * support on your MUD. See the new_load_area format below for * a short example. */ #if defined(KEY) #undef KEY #endif #define KEY( literal, field, value ) \ if ( !str_cmp( word, literal ) ) \ { \ field = value; \ fMatch = TRUE; \ break; \ } #define SKEY( string, field ) \ if ( !str_cmp( word, string ) ) \ { \ free_string( field ); \ field = fread_string( fp ); \ fMatch = TRUE; \ break; \ } /* OLC * Snarf an 'area' header line. Check this format. MUCH better. Add fields * too. * * #AREAFILE * Name { All } Locke Newbie School~ * Repop A teacher pops in the room and says, 'Repop coming!'~ * Recall 3001 * End */ void new_load_area( FILE *fp ) { AREA_DATA *pArea; char *word; bool fMatch; pArea = alloc_perm( sizeof(*pArea) ); pArea->age = 15; pArea->nplayer = 0; pArea->filename = str_dup( strArea ); pArea->vnum = top_area; pArea->name = str_dup( "New Area" ); pArea->builders = str_dup( "" ); pArea->security = 9; /* 9 -- Hugin */ pArea->lvnum = 0; pArea->uvnum = 0; pArea->area_flags = 0; /* pArea->recall = ROOM_VNUM_TEMPLE; ROM OLC */ for ( ; ; ) { word = feof( fp ) ? "End" : fread_word( fp ); fMatch = FALSE; switch ( UPPER(word[0]) ) { case 'N': SKEY( "Name", pArea->name ); break; case 'S': KEY( "Security", pArea->security, fread_number( fp ) ); break; case 'V': if ( !str_cmp( word, "VNUMs" ) ) { pArea->lvnum = fread_number( fp ); pArea->uvnum = fread_number( fp ); } break; case 'E': if ( !str_cmp( word, "End" ) ) { fMatch = TRUE; if ( area_first == NULL ) area_first = pArea; if ( area_last != NULL ) area_last->next = pArea; area_last = pArea; pArea->next = NULL; top_area++; return; } break; case 'B': SKEY( "Builders", pArea->builders ); break; /* removed for ROM OLC case 'R': KEY( "Recall", pArea->recall, fread_number( fp ) ); break; */ } } } /* * Sets vnum range for area using OLC protection features. */ void assign_area_vnum( int vnum ) { if ( area_last->lvnum == 0 || area_last->uvnum == 0 ) area_last->lvnum = area_last->uvnum = vnum; if ( vnum != URANGE( area_last->lvnum, vnum, area_last->uvnum ) ) if ( vnum < area_last->lvnum ) area_last->lvnum = vnum; else area_last->uvnum = vnum; return; } ---- load_old_mob() Before the loop, add: if ( !area_last ) /* OLC */ { bug( "Load_mobiles: no #AREA seen yet.", 0 ); exit( 1 ); } In the middle: pMobIndex->vnum = vnum; pMobIndex->area = area_last; /* OLC */ pMobIndex->new_format = FALSE; And at the end add: convert_mobile( pMobIndex ); /* ROM OLC */ iHash = vnum % MAX_KEY_HASH; pMobIndex->next = mob_index_hash[iHash]; mob_index_hash[iHash] = pMobIndex; top_mob_index++; top_vnum_mob = top_vnum_mob < vnum ? vnum : top_vnum_mob; /* OLC */ assign_area_vnum( vnum ); /* OLC */ kill_table[URANGE(0, pMobIndex->level, MAX_LEVEL-1)].number++; ---- load_old_obj() Before the loop, add: if ( !area_last ) /* OLC */ { bug( "Load_objects: no #AREA seen yet.", 0 ); exit( 1 ); } In the middle: pObjIndex->vnum = vnum; pObjIndex->area = area_last; /* OLC */ pObjIndex->new_format = FALSE; And at the end: top_obj_index++; top_vnum_obj = top_vnum_obj < vnum ? vnum : top_vnum_obj; /* OLC */ assign_area_vnum( vnum ); /* OLC */ ---- Replace load_resets() with (two functions): /* * Adds a reset to a room. OLC * Similar to add_reset in olc.c */ void new_reset( ROOM_INDEX_DATA *pR, RESET_DATA *pReset ) { RESET_DATA *pr; if ( !pR ) return; pr = pR->reset_last; if ( !pr ) { pR->reset_first = pReset; pR->reset_last = pReset; } else { pR->reset_last->next = pReset; pR->reset_last = pReset; pR->reset_last->next = NULL; } top_reset++; return; } /* * Snarf a reset section. Changed for OLC. */ void load_resets( FILE *fp ) { RESET_DATA *pReset; int iLastRoom = 0; int iLastObj = 0; if ( !area_last ) { bug( "Load_resets: no #AREA seen yet.", 0 ); exit( 1 ); } for ( ; ; ) { EXIT_DATA *pexit; ROOM_INDEX_DATA *pRoomIndex; char letter; if ( ( letter = fread_letter( fp ) ) == 'S' ) break; if ( letter == '*' ) { fread_to_eol( fp ); continue; } pReset = alloc_perm( sizeof( *pReset ) ); pReset->command = letter; /* if_flag */ fread_number( fp ); pReset->arg1 = fread_number( fp ); pReset->arg2 = fread_number( fp ); pReset->arg3 = ( letter == 'G' || letter == 'R' ) ? 0 : fread_number( fp ); fread_to_eol( fp ); /* * Validate parameters. * We're calling the index functions for the side effect. */ switch ( letter ) { default: bug( "Load_resets: bad command '%c'.", letter ); exit( 1 ); break; case 'M': get_mob_index ( pReset->arg1 ); if ( ( pRoomIndex = get_room_index ( pReset->arg3 ) ) ) { new_reset( pRoomIndex, pReset ); iLastRoom = pReset->arg3; } break; case 'O': get_obj_index ( pReset->arg1 ); if ( ( pRoomIndex = get_room_index ( pReset->arg3 ) ) ) { new_reset( pRoomIndex, pReset ); iLastObj = pReset->arg3; } break; case 'P': get_obj_index ( pReset->arg1 ); if ( ( pRoomIndex = get_room_index ( iLastObj ) ) ) { new_reset( pRoomIndex, pReset ); } break; case 'G': case 'E': get_obj_index ( pReset->arg1 ); if ( ( pRoomIndex = get_room_index ( iLastRoom ) ) ) { new_reset( pRoomIndex, pReset ); iLastObj = iLastRoom; } break; case 'D': pRoomIndex = get_room_index( pReset->arg1 ); if ( pReset->arg2 < 0 || pReset->arg2 > 5 || !pRoomIndex || !( pexit = pRoomIndex->exit[pReset->arg2] ) || !IS_SET( pexit->rs_flags, EX_ISDOOR ) ) { bug( "Load_resets: 'D': exit %d not door.", pReset->arg2 ); exit( 1 ); } switch ( pReset->arg3 ) { default: bug( "Load_resets: 'D': bad 'locks': %d." , pReset->arg3); case 0: break; case 1: SET_BIT( pexit->rs_flags, EX_LOCKED ); break; case 2: SET_BIT( pexit->rs_flags, EX_PICKPROOF ); break; } /* * By calling new_reset we are assigning reset data for doors. * This data is not used in updating the game any longer. But * displaying resets in this manner may be to your liking. * I have left the code here so you may do so. Uncomment data in * display_resets in olc.c if you wish to do this. * * new_reset( pRoomIndex, pReset ); * * End Resets Comment. */ break; case 'R': if ( pReset->arg2 < 0 || pReset->arg2 > 6 ) /* Last Door. */ { bug( "Load_resets: 'R': bad exit %d.", pReset->arg2 ); exit( 1 ); } if ( ( pRoomIndex = get_room_index( pReset->arg1 ) ) ) new_reset( pRoomIndex, pReset ); break; } } return; } ---- load_rooms() Add: pexit->exit_info = 0; pexit->rs_flags = 0; /* OLC */ locks = fread_number( fp ); pexit->key = fread_number( fp ); pexit->u1.vnum = fread_number( fp ); pexit->orig_door = door; /* OLC */ Replace the old switch with: switch ( locks ) /* OLC exit_info to rs_flags. */ { case 1: pexit->rs_flags = EX_ISDOOR; break; case 2: pexit->rs_flags = EX_ISDOOR | EX_PICKPROOF; break; } And at the end add: top_room++; top_vnum_room = top_vnum_room < vnum ? vnum : top_vnum_room; /* OLC */ assign_area_vnum( vnum ); /* OLC */ ---- After area_update() add this function: /* OLC * Reset one room. Called by reset_area and olc. */ void reset_room( ROOM_INDEX_DATA *pRoom ) { RESET_DATA *pReset; CHAR_DATA *pMob; OBJ_DATA *pObj; CHAR_DATA *LastMob = NULL; OBJ_DATA *LastObj = NULL; int iExit; int level = 0; bool last; if ( !pRoom ) return; pMob = NULL; last = FALSE; for ( iExit = 0; iExit < MAX_DIR; iExit++ ) { EXIT_DATA *pExit; if ( ( pExit = pRoom->exit[iExit] ) /* && !IS_SET( pExit->exit_info, EX_BASHED ) ROM OLC */ ) { pExit->exit_info = pExit->rs_flags; if ( ( pExit->u1.to_room != NULL ) && ( ( pExit = pExit->u1.to_room->exit[rev_dir[iExit]] ) ) ) { /* nail the other side */ pExit->exit_info = pExit->rs_flags; } } } for ( pReset = pRoom->reset_first; pReset != NULL; pReset = pReset->next ) { MOB_INDEX_DATA *pMobIndex; OBJ_INDEX_DATA *pObjIndex; OBJ_INDEX_DATA *pObjToIndex; ROOM_INDEX_DATA *pRoomIndex; switch ( pReset->command ) { default: bug( "Reset_room: bad command %c.", pReset->command ); break; case 'M': if ( !( pMobIndex = get_mob_index( pReset->arg1 ) ) ) { bug( "Reset_room: 'M': bad vnum %d.", pReset->arg1 ); continue; } #if 0 /* envy version, ROM doesn't use this */ /* * Some hard coding. */ if ( ( pMobIndex->spec_fun == spec_lookup( "spec_cast_ghost" ) && ( weather_info.sunlight != SUN_DARK ) ) ) continue; #endif /* envy version */ if ( pMobIndex->count >= pReset->arg2 ) { last = FALSE; break; } pMob = create_mobile( pMobIndex ); /* * Some more hard coding. */ if ( room_is_dark( pRoom ) ) SET_BIT(pMob->affected_by, AFF_INFRARED); /* * Pet shop mobiles get ACT_PET set. */ { ROOM_INDEX_DATA *pRoomIndexPrev; pRoomIndexPrev = get_room_index( pRoom->vnum - 1 ); if ( pRoomIndexPrev && IS_SET( pRoomIndexPrev->room_flags, ROOM_PET_SHOP ) ) SET_BIT( pMob->act, ACT_PET); } char_to_room( pMob, pRoom ); LastMob = pMob; level = URANGE( 0, pMob->level - 2, LEVEL_HERO - 1 ); /* -1 ROM */ last = TRUE; break; case 'O': if ( !( pObjIndex = get_obj_index( pReset->arg1 ) ) ) { bug( "Reset_room: 'O': bad vnum %d.", pReset->arg1 ); continue; } if ( !( pRoomIndex = get_room_index( pReset->arg3 ) ) ) { bug( "Reset_room: 'O': bad vnum %d.", pReset->arg3 ); continue; } if ( pRoom->area->nplayer > 0 || count_obj_list( pObjIndex, pRoom->contents ) > 0 ) break; pObj = create_object( pObjIndex, /* UMIN - ROM OLC */ UMIN(number_fuzzy( level ), LEVEL_HERO -1) ); pObj->cost = 0; obj_to_room( pObj, pRoom ); break; case 'P': if ( !( pObjIndex = get_obj_index( pReset->arg1 ) ) ) { bug( "Reset_room: 'P': bad vnum %d.", pReset->arg1 ); continue; } if ( !( pObjToIndex = get_obj_index( pReset->arg3 ) ) ) { bug( "Reset_room: 'P': bad vnum %d.", pReset->arg3 ); continue; } if ( pRoom->area->nplayer > 0 || !( LastObj = get_obj_type( pObjToIndex ) ) || count_obj_list( pObjIndex, LastObj->contains ) > 0 ) break; /* lastObj->level - ROM */ pObj = create_object( pObjIndex, number_fuzzy( LastObj->level ) ); obj_to_obj( pObj, LastObj ); break; case 'G': case 'E': if ( !( pObjIndex = get_obj_index( pReset->arg1 ) ) ) { bug( "Reset_room: 'E' or 'G': bad vnum %d.", pReset->arg1 ); continue; } if ( !last ) break; if ( !LastMob ) { bug( "Reset_room: 'E' or 'G': null mob for vnum %d.", pReset->arg1 ); last = FALSE; break; } if ( LastMob->pIndexData->pShop ) /* Shop-keeper? */ { int olevel; switch ( pObjIndex->item_type ) { default: olevel = 0; break; case ITEM_PILL: olevel = number_range( 0, 10 ); break; case ITEM_POTION: olevel = number_range( 0, 10 ); break; case ITEM_SCROLL: olevel = number_range( 5, 15 ); break; case ITEM_WAND: olevel = number_range( 10, 20 ); break; case ITEM_STAFF: olevel = number_range( 15, 25 ); break; case ITEM_ARMOR: olevel = number_range( 5, 15 ); break; /* ROM patch weapon, treasure */ case ITEM_WEAPON: olevel = number_range( 5, 15 ); break; case ITEM_TREASURE: olevel = number_range( 10, 20 ); break; #if 0 /* envy version */ case ITEM_WEAPON: if ( pReset->command == 'G' ) olevel = number_range( 5, 15 ); else olevel = number_fuzzy( level ); #endif /* envy version */ break; } pObj = create_object( pObjIndex, olevel ); SET_BIT( pObj->extra_flags, ITEM_INVENTORY ); /* ROM OLC */ #if 0 /* envy version */ if ( pReset->command == 'G' ) SET_BIT( pObj->extra_flags, ITEM_INVENTORY ); #endif /* envy version */ } else /* ROM OLC else version */ { int limit; if (pReset->arg2 > 50 ) /* old format */ limit = 6; else if ( pReset->arg2 == -1 ) /* no limit */ limit = 999; else limit = pReset->arg2; if ( pObjIndex->count < limit || number_range(0,4) == 0 ) pObj = create_object( pObjIndex, UMIN( number_fuzzy( level ), LEVEL_HERO - 1 ) ); else break; } #if 0 /* envy else version */ else { pObj = create_object( pObjIndex, number_fuzzy( level ) ); } #endif /* envy else version */ obj_to_char( pObj, LastMob ); if ( pReset->command == 'E' ) equip_char( LastMob, pObj, pReset->arg3 ); last = TRUE; break; case 'D': break; case 'R': if ( !( pRoomIndex = get_room_index( pReset->arg1 ) ) ) { bug( "Reset_room: 'R': bad vnum %d.", pReset->arg1 ); continue; } { EXIT_DATA *pExit; int d0; int d1; for ( d0 = 0; d0 < pReset->arg2 - 1; d0++ ) { d1 = number_range( d0, pReset->arg2-1 ); pExit = pRoomIndex->exit[d0]; pRoomIndex->exit[d0] = pRoomIndex->exit[d1]; pRoomIndex->exit[d1] = pExit; } } break; } } return; } ---- Replace reset_area() with: /* OLC * Reset one area. */ void reset_area( AREA_DATA *pArea ) { ROOM_INDEX_DATA *pRoom; int vnum; for ( vnum = pArea->lvnum; vnum <= pArea->uvnum; vnum++ ) { if ( ( pRoom = get_room_index(vnum) ) ) reset_room(pRoom); } return; } ---- create_mobile() Change: mob->pIndexData = pMobIndex; mob->name = str_dup( pMobIndex->player_name ); /* OLC */ mob->short_descr = str_dup( pMobIndex->short_descr ); /* OLC */ mob->long_descr = str_dup( pMobIndex->long_descr ); /* OLC */ mob->description = str_dup( pMobIndex->description ); /* OLC */ mob->spec_fun = pMobIndex->spec_fun; ---- create_objcet() Change: obj->wear_loc = -1; obj->name = str_dup( pObjIndex->name ); /* OLC */ obj->short_descr = str_dup( pObjIndex->short_descr ); /* OLC */ obj->description = str_dup( pObjIndex->description ); /* OLC */ obj->material = pObjIndex->material; ---- fread_flag() Right after number is set to 0 add/change: if (!isdigit(c) && c != '-' ) /* ROM OLC */ { while (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')) { number += flag_convert(c); c = getc(fp); } } if ( c == '-' ) /* ROM OLC */ { number = fread_number( fp ); return -number; } This is to teach fread_flag() to read negative numbers. It is a temporary solution, until I find out which item-types have negative values and how to step around it.