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