ILAB OLC Beta 1.1 Jason Dinkel May. 15 1995 DB.C This file contains modifications needed to stock Envy 1.0 db.c. Only the lines commented with /* OLC */ need to be added. The surrounding code is for getting ones bearings. ---- After top_shop int top_room; int top_shop; int top_vnum_room; /* OLC */ int top_vnum_mob; /* OLC */ int top_vnum_obj; /* OLC */ ---- Before boot_db /* * Non-Envy Loading procedures. * Put any new loading function in this section. */ void new_load_area args( ( FILE *fp ) ); /* OLC */ void new_load_rooms args( ( FILE *fp ) ); /* OLC 1.1b */ ---- In boot_db else if ( !str_cmp( word, "SPECIALS" ) ) load_specials( fpArea ); else if ( !str_cmp( word, "AREADATA" ) ) /* OLC */ new_load_area( fpArea ); else if ( !str_cmp( word, "ROOMDATA" ) ) /* OLC 1.1b */ new_load_rooms( fpArea ); ---- FUNCTION: load_area DESC: This is a replacement function for the Envy load_area function. Just copy it over the old one. void load_area( FILE *fp ) { AREA_DATA *pArea; pArea = alloc_perm( sizeof( *pArea ) ); /* pArea->reset_first = NULL; * OLC-Removed pArea->reset_last = NULL; */ pArea->name = fread_string( fp ); pArea->recall = ROOM_VNUM_TEMPLE; pArea->area_flags = AREA_LOADING; /* OLC */ pArea->security = 1; /* OLC */ 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; 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 in code right after load_area() (2 functions and 2 macros) /* * 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 = 1; pArea->lvnum = 0; pArea->uvnum = 0; pArea->area_flags = 0; pArea->recall = ROOM_VNUM_TEMPLE; 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; 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; } ---- FUNCTION: load_mobiles DESC: Before entering the for loop add this code. It is for the vnum counting procedure, so you don't have to manually set vnums of the areas. It ensures that an area file has been loaded and expands the vnum range of the file as mobiles are loaded. if ( !area_last ) /* OLC */ { bug( "Load_mobiles: no #AREA seen yet.", 0 ); exit( 1 ); } DESC: Inside the for loop. Just insert the OLC commented lines. pMobIndex->vnum = vnum; pMobIndex->area = area_last; /* OLC */ pMobIndex->player_name = fread_string( fp ); DESC: End of the for loop. Just insert the OLC commented lines. 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++; ---- FUNCTION: load_objects DESC: Same as for mobiles above but now is for objects. Before entering the for loop, this is for the vnum counting procedure. if ( !area_last ) /* OLC */ { bug( "Load_objects: no #AREA seen yet.", 0 ); exit( 1 ); } DESC: Inside the for loop. Just insert the OLC commented lines. pObjIndex->vnum = vnum; pObjIndex->area = area_last; /* OLC */ pObjIndex->name = fread_string( fp ); DESC: End of the for loop. Just insert the OLC commented lines. iHash = vnum % MAX_KEY_HASH; pObjIndex->next = obj_index_hash[iHash]; obj_index_hash[iHash] = pObjIndex; top_obj_index++; top_vnum_obj = top_vnum_obj < vnum ? vnum : top_vnum_obj; /* OLC */ assign_area_vnum( vnum ); /* OLC */ ---- DROP in code right before load_resets. /* * 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; } ---- REPLACEment code for load_resets. /* * 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 ) /* OLC 1.1b */ { default: bug( "Load_resets: 'D': bad 'locks': %d." , pReset->arg3); case 0: break; case 1: SET_BIT( pexit->rs_flags, EX_CLOSED ); break; case 2: SET_BIT( pexit->rs_flags, EX_CLOSED | EX_LOCKED ); break; } 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; } ---- FUNCTION: load_rooms DESC: Once again, just add the OLC comments. pexit->exit_info = 0; pexit->rs_flags = 0; /* OLC */ locks = fread_number( fp ); pexit->key = fread_number( fp ); pexit->vnum = fread_number( fp ); DESC: Replace exit_info with rs_flags, exit_info will get set in the resets. I appologize for this, but I blame this exit code on the Envy team. It is their fault this is so bulky. 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; case 3: pexit->rs_flags = EX_ISDOOR | EX_BASHPROOF; break; case 4: pexit->rs_flags = EX_ISDOOR | EX_PICKPROOF | EX_BASHPROOF; break; case 5: pexit->rs_flags = EX_ISDOOR | EX_PASSPROOF; break; case 6: pexit->rs_flags = EX_ISDOOR | EX_PICKPROOF | EX_PASSPROOF; break; case 7: pexit->rs_flags = EX_ISDOOR | EX_BASHPROOF | EX_PASSPROOF; break; case 8: pexit->rs_flags = EX_ISDOOR | EX_PICKPROOF | EX_BASHPROOF | EX_PASSPROOF; break; } DESC: End of the for loop. Just insert the OLC commented lines. iHash = vnum % MAX_KEY_HASH; pRoomIndex->next = room_index_hash[iHash]; room_index_hash[iHash] = pRoomIndex; top_room++; top_vnum_room = top_vnum_room < vnum ? vnum : top_vnum_room; /* OLC */ assign_area_vnum( vnum ); /* OLC */ ---- DROP in right after load_rooms /* OLC 1.1b */ void new_load_rooms( FILE *fp ) { ROOM_INDEX_DATA *pRoomIndex; if ( !area_last ) { bug( "Load_rooms: no #AREA seen yet.", 0 ); exit( 1 ); } for ( ; ; ) { char letter; int vnum; int door; int iHash; letter = fread_letter( fp ); if ( letter != '#' ) { bug( "Load_rooms: # not found.", 0 ); exit( 1 ); } vnum = fread_number( fp ); if ( vnum == 0 ) break; fBootDb = FALSE; if ( get_room_index( vnum ) ) { bug( "Load_rooms: vnum %d duplicated.", vnum ); exit( 1 ); } fBootDb = TRUE; pRoomIndex = alloc_perm( sizeof( *pRoomIndex ) ); pRoomIndex->people = NULL; pRoomIndex->contents = NULL; pRoomIndex->extra_descr = NULL; pRoomIndex->area = area_last; pRoomIndex->vnum = vnum; pRoomIndex->name = fread_string( fp ); pRoomIndex->description = fread_string( fp ); /* Area number */ fread_number( fp ); /* Unused */ pRoomIndex->room_flags = fread_number( fp ); pRoomIndex->sector_type = fread_number( fp ); pRoomIndex->light = 0; for ( door = 0; door <= 5; door++ ) pRoomIndex->exit[door] = NULL; for ( ; ; ) { letter = fread_letter( fp ); if ( letter == 'S' || letter == 's' ) { if ( letter == 's' ) bug( "Load_rooms: vnum %d has lowercase 's'", vnum ); break; } if ( letter == 'D' ) { EXIT_DATA *pexit; int locks; door = fread_number( fp ); if ( door < 0 || door > 5 ) { bug( "Fread_rooms: vnum %d has bad door number.", vnum ); exit( 1 ); } pexit = alloc_perm( sizeof( *pexit ) ); pexit->description = fread_string( fp ); pexit->keyword = fread_string( fp ); locks = fread_number( fp ); pexit->exit_info = locks; pexit->rs_flags = locks; pexit->key = fread_number( fp ); pexit->vnum = fread_number( fp ); pRoomIndex->exit[door] = pexit; top_exit++; } else if ( letter == 'E' ) { EXTRA_DESCR_DATA *ed; ed = alloc_perm( sizeof( *ed ) ); ed->keyword = fread_string( fp ); ed->description = fread_string( fp ); ed->next = pRoomIndex->extra_descr; pRoomIndex->extra_descr = ed; top_ed++; } else { bug( "Load_rooms: vnum %d has flag not 'DES'.", vnum ); exit( 1 ); } } iHash = vnum % MAX_KEY_HASH; pRoomIndex->next = room_index_hash[iHash]; room_index_hash[iHash] = pRoomIndex; top_room++; top_vnum_room = top_vnum_room < vnum ? vnum : top_vnum_room; assign_area_vnum( vnum ); } return; } ---- DROP in before reset_area /* 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 ) ) /* Skip Bashed. */ { pExit->exit_info = pExit->rs_flags; if ( ( pExit->to_room != NULL ) && ( ( pExit = pExit->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; } /* * Some hard coding. */ if ( ( pMobIndex->spec_fun == spec_lookup( "spec_cast_ghost" ) && ( weather_info.sunlight != SUN_DARK ) ) ) continue; 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 ); 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, number_fuzzy( level ) ); 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; pObj = create_object( pObjIndex, number_fuzzy( level ) ); obj_to_obj( pObj, LastObj ); /* * Ensure that the container gets reset. OLC 1.1b */ if ( LastObj->item_type == ITEM_CONTAINER ) { LastObj->value[1] = LastObj->pIndexData->value[1]; } else { /* THIS SPACE INTENTIONALLY LEFT BLANK */ } 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; case ITEM_WEAPON: if ( pReset->command == 'G' ) olevel = number_range( 5, 15 ); else olevel = number_fuzzy( level ); break; } pObj = create_object( pObjIndex, olevel ); if ( pReset->command == 'G' ) SET_BIT( pObj->extra_flags, ITEM_INVENTORY ); } else { pObj = create_object( pObjIndex, number_fuzzy( level ) ); } obj_to_char( pObj, LastMob ); if ( pReset->command == 'E' ) equip_char( LastMob, pObj, pReset->arg3 ); last = TRUE; break; case 'D': break; case 'R': /* OLC 1.1b 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; } ---- REPLACEment for reset_area /* 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; } ---- FUNCTION: create_mobile DESC: These corrections ensure correct memory management. They are new since the first version I released. Change the following: 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 */ ---- FUNCTION: create_object DESC: Change the following: obj->name = str_dup( pObjIndex->name ); /* OLC */ obj->short_descr = str_dup( pObjIndex->short_descr ); /* OLC */ obj->description = str_dup( pObjIndex->description ); /* OLC */ END OF FILE DB.C