/***************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* Ack 2.2 improvements copyright (C) 1994 by Stephen Dooley *
* *
* In order to use any part of this Merc Diku Mud, you must comply with *
* both the original Diku license in 'license.doc' as well the Merc *
* license in 'license.txt'. In particular, you may not remove either of *
* these copyright notices. *
* *
* _/ _/_/_/ _/ _/ _/ ACK! MUD is modified *
* _/_/ _/ _/ _/ _/ Merc2.0/2.1/2.2 code *
* _/ _/ _/ _/_/ _/ (c)Stephen Zepp 1998 *
* _/_/_/_/ _/ _/ _/ Version #: 4.3 *
* _/ _/ _/_/_/ _/ _/ _/ *
* *
* http://ackmud.nuc.net/ *
* zenithar@ackmud.nuc.net *
* Much time and thought has gone into this software and you are *
* benefitting. We hope that you share your changes too. What goes *
* around, comes around. *
***************************************************************************/
/*
* This program goes through each area. It checks all vnums to see if
* they are in the allowed range. If not it moves them, and updates all
* references.
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "globals.h"
#include "hash.h"
void swap_global_hash( char Tp, void *Ptr, int old_vnum, int new_vnum )
{
ROOM_INDEX_DATA *pRoomIndex, *prevRoomIndex;
OBJ_INDEX_DATA *pObjIndex, *prevObjIndex;
MOB_INDEX_DATA *pMobIndex, *prevMobIndex;
extern ROOM_INDEX_DATA *room_index_hash[];
extern OBJ_INDEX_DATA *obj_index_hash[];
extern MOB_INDEX_DATA *mob_index_hash[];
int iHash;
switch ( Tp )
{
case 'R':
/*
* Delete old hash table entry
*/
iHash = old_vnum % MAX_KEY_HASH;
prevRoomIndex = NULL;
for( pRoomIndex = room_index_hash[iHash]; pRoomIndex != NULL; pRoomIndex = pRoomIndex->next )
{
if( pRoomIndex == ( ROOM_INDEX_DATA * ) Ptr )
break;
prevRoomIndex = pRoomIndex;
}
if( pRoomIndex != NULL )
{
if( prevRoomIndex == NULL )
room_index_hash[iHash] = pRoomIndex->next;
else
prevRoomIndex->next = pRoomIndex->next;
}
/*
* Add another
*/
iHash = new_vnum % MAX_KEY_HASH;
pRoomIndex->next = room_index_hash[iHash];
room_index_hash[iHash] = pRoomIndex;
break;
case 'M':
/*
* Delete old hash table entry
*/
iHash = old_vnum % MAX_KEY_HASH;
prevMobIndex = NULL;
for( pMobIndex = mob_index_hash[iHash]; pMobIndex != NULL; pMobIndex = pMobIndex->next )
{
if( pMobIndex == ( MOB_INDEX_DATA * ) Ptr )
break;
prevMobIndex = pMobIndex;
}
if( pMobIndex != NULL )
{
if( prevMobIndex == NULL )
mob_index_hash[iHash] = pMobIndex->next;
else
prevMobIndex->next = pMobIndex->next;
}
/*
* Add another
*/
iHash = new_vnum % MAX_KEY_HASH;
pMobIndex->next = mob_index_hash[iHash];
mob_index_hash[iHash] = pMobIndex;
break;
case 'O':
/*
* Delete old hash table entry
*/
iHash = old_vnum % MAX_KEY_HASH;
prevObjIndex = NULL;
for( pObjIndex = obj_index_hash[iHash]; pObjIndex != NULL; pObjIndex = pObjIndex->next )
{
if( pObjIndex == ( OBJ_INDEX_DATA * ) Ptr )
break;
prevObjIndex = pObjIndex;
}
if( pObjIndex != NULL )
{
if( prevObjIndex == NULL )
obj_index_hash[iHash] = pObjIndex->next;
else
prevObjIndex->next = pObjIndex->next;
}
/*
* Add another
*/
iHash = new_vnum % MAX_KEY_HASH;
pObjIndex->next = obj_index_hash[iHash];
obj_index_hash[iHash] = pObjIndex;
break;
}
return;
}
void do_check_areas( CHAR_DATA * ch, char *argument )
{
hash_table *room_hash;
hash_table *obj_hash;
hash_table *mob_hash;
int min_vnum, max_vnum;
int new_vnum, old_vnum;
char buffer[MAX_INPUT_LENGTH];
FILE *out_file;
int a;
RESET_DATA *pReset;
AREA_DATA *CurArea;
BUILD_DATA_LIST *pList;
ROOM_INDEX_DATA *pRoomIndex;
OBJ_INDEX_DATA *pObjIndex;
MOB_INDEX_DATA *pMobIndex;
/*
* Create hash tables for rooms, mobiles, objects
*/
room_hash = create_hash_table( MAX_KEY_HASH );
obj_hash = create_hash_table( MAX_KEY_HASH );
mob_hash = create_hash_table( MAX_KEY_HASH );
out_file = file_open( "area_changes.txt", "a" );
for( CurArea = first_area; CurArea != NULL; CurArea = CurArea->next )
{
min_vnum = CurArea->min_vnum;
max_vnum = CurArea->max_vnum;
fprintf( out_file, "%s:\n", CurArea->name );
/*
* Go through rooms
*/
for( pList = CurArea->first_area_room; pList != NULL; pList = pList->next )
{
pRoomIndex = pList->data;
if( pRoomIndex->vnum < min_vnum || pRoomIndex->vnum > max_vnum )
{
old_vnum = pRoomIndex->vnum;
/*
* Find a free slot
*/
for( new_vnum = min_vnum; new_vnum <= max_vnum; new_vnum++ )
if( get_room_index( new_vnum ) == NULL )
break;
if( new_vnum > max_vnum )
{
xprintf( buffer, "Not enough vnums in area %s\n\r", CurArea->name );
send_to_char( buffer, ch );
}
else
{
fprintf( out_file, "Room: [%5i] -> [%5i] %s\n", old_vnum, new_vnum, pRoomIndex->name );
/*
* Delete from room hashing table, and put new vnum in.
*/
add_hash_entry( room_hash, old_vnum, ( void * )new_vnum );
swap_global_hash( 'R', pRoomIndex, old_vnum, new_vnum );
pRoomIndex->vnum = new_vnum;
area_modified( CurArea );
}
}
}
/*
* Go through objs
*/
for( pList = CurArea->first_area_object; pList != NULL; pList = pList->next )
{
pObjIndex = pList->data;
if( pObjIndex->vnum < min_vnum || pObjIndex->vnum > max_vnum )
{
old_vnum = pObjIndex->vnum;
/*
* Find a free slot
*/
for( new_vnum = min_vnum; new_vnum <= max_vnum; new_vnum++ )
if( get_obj_index( new_vnum ) == NULL )
break;
if( new_vnum > max_vnum )
{
xprintf( buffer, "Not enough vnums in area %s\n\r", CurArea->name );
send_to_char( buffer, ch );
}
else
{
fprintf( out_file, "Obj: [%5i] -> [%5i] %s\n", old_vnum, new_vnum, pObjIndex->short_descr );
/*
* Delete from obj hashing table, and put new vnum in.
*/
add_hash_entry( obj_hash, old_vnum, ( void * )new_vnum );
swap_global_hash( 'O', pObjIndex, old_vnum, new_vnum );
pObjIndex->vnum = new_vnum;
area_modified( CurArea );
}
}
}
/*
* Go through mobs
*/
for( pList = CurArea->first_area_mobile; pList != NULL; pList = pList->next )
{
pMobIndex = pList->data;
if( pMobIndex->vnum < min_vnum || pMobIndex->vnum > max_vnum )
{
old_vnum = pMobIndex->vnum;
/*
* Find a free slot
*/
for( new_vnum = min_vnum; new_vnum <= max_vnum; new_vnum++ )
if( get_mob_index( new_vnum ) == NULL )
break;
if( new_vnum > max_vnum )
{
xprintf( buffer, "Not enough vnums in area %s\n\r", CurArea->name );
send_to_char( buffer, ch );
}
else
{
fprintf( out_file, "Mob: [%5i] -> [%5i] %s\n", old_vnum, new_vnum, pMobIndex->short_descr );
/*
* Delete from mob hashing table, and put new vnum in.
*/
add_hash_entry( mob_hash, old_vnum, ( void * )new_vnum );
swap_global_hash( 'M', pMobIndex, old_vnum, new_vnum );
pMobIndex->vnum = new_vnum;
area_modified( CurArea );
/*
* Check for shops
*/
if( pMobIndex->pShop != NULL )
pMobIndex->pShop->keeper = new_vnum;
}
}
}
}
file_close( out_file );
/*
* Now go through all things referencing the changes
* *
* * Resets
* * exit->key
* *
*/
for( CurArea = first_area; CurArea != NULL; CurArea = CurArea->next )
{
for( pList = CurArea->first_area_room; pList != NULL; pList = pList->next )
{
/*
* Check keys and exits
*/
pRoomIndex = pList->data;
for( a = 0; a <= 5; a++ )
{
if( pRoomIndex->exit[a] != NULL )
{
if( pRoomIndex->exit[a]->key != 0
&& ( new_vnum = ( int )get_hash_entry( obj_hash, pRoomIndex->exit[a]->key ) ) != 0 )
{
pRoomIndex->exit[a]->key = new_vnum;
area_modified( CurArea );
}
if( ( new_vnum = ( int )get_hash_entry( room_hash, pRoomIndex->exit[a]->vnum ) ) != 0 )
{
pRoomIndex->exit[a]->vnum = new_vnum;
area_modified( CurArea );
}
}
}
}
/*
* Scan through resets
*/
for( pReset = CurArea->first_reset; pReset != NULL; pReset = pReset->next )
{
switch ( pReset->command )
{
case 'M':
if( ( new_vnum = ( int )get_hash_entry( mob_hash, pReset->arg1 ) ) != 0 )
{
area_modified( CurArea );
pReset->arg1 = new_vnum;
}
if( ( new_vnum = ( int )get_hash_entry( room_hash, pReset->arg3 ) ) != 0 )
{
area_modified( CurArea );
pReset->arg3 = new_vnum;
}
break;
case 'O':
if( ( new_vnum = ( int )get_hash_entry( obj_hash, pReset->arg1 ) ) != 0 )
{
area_modified( CurArea );
pReset->arg1 = new_vnum;
}
if( ( new_vnum = ( int )get_hash_entry( room_hash, pReset->arg3 ) ) != 0 )
{
area_modified( CurArea );
pReset->arg3 = new_vnum;
}
break;
case 'P':
if( ( new_vnum = ( int )get_hash_entry( obj_hash, pReset->arg1 ) ) != 0 )
{
area_modified( CurArea );
pReset->arg1 = new_vnum;
}
if( ( new_vnum = ( int )get_hash_entry( obj_hash, pReset->arg3 ) ) != 0 )
{
area_modified( CurArea );
pReset->arg3 = new_vnum;
}
break;
case 'G':
case 'E':
if( ( new_vnum = ( int )get_hash_entry( obj_hash, pReset->arg1 ) ) != 0 )
{
area_modified( CurArea );
pReset->arg1 = new_vnum;
}
break;
case 'D':
case 'R':
if( ( new_vnum = ( int )get_hash_entry( room_hash, pReset->arg1 ) ) != 0 )
{
area_modified( CurArea );
pReset->arg1 = new_vnum;
}
break;
}
}
}
/*
* FINISHED
*/
delete_hash_table( room_hash );
delete_hash_table( obj_hash );
delete_hash_table( mob_hash );
return;
}
void do_check_area( CHAR_DATA * ch, char *argument )
{
send_to_char( "You must say check_areas in full.\n\r", ch );
return;
}