/**************************************************************************/
// areas.cpp - reading/writing of NAFF area files (New Area File Format)
/***************************************************************************
* The Dawn of Time v1.69r (c)1997-2004 Michael Garratt *
* >> A number of people have contributed to the Dawn codebase, with the *
* majority of code written by Michael Garratt - www.dawnoftime.org *
* >> To use this source code, you must fully comply with the dawn license *
* in licenses.txt... In particular, you may not remove this copyright *
* notice. *
**************************************************************************/
//
// The concept of NAFF is based the following principles:
// * Never use a hard coded number in the area file.
// * Always use word representation of flags in areafiles.
// * As a general rule each line should stand alone and have a meaningful
// header, If multiple lines worth of information are needed to be stored
// but not necessarily stored in every situation (e.g. room exit flags),
// then reference something that was previously read in.
// * Put every string thru pack_string when writing, and unpack_string when
// loading. (These functions add a leading . if necessary + other things).
// * Put everything that will be read in with fread_word() thru pack_word
// when writing (this adds the ' 's if necessary).
// NOTE: pack_string() is not multibuffered!!!
// (This means do NOT call it more than once within a single fprintf()!)
//
#include "include.h"
#include "areas.h"
#include "db.h"
#include "olc.h"
#include "lockers.h"
#include "shop.h"
// mob_cmds.cpp
char *mprog_type_to_name( int type );
// gamble.cpp
char *gamble_name( GAMBLE_FUN *function);
GAMBLE_FUN *gamble_lookup( const char *name );
// db.cpp
/**************************************************************************/
// local prototypes
void fread_mob_NAFF( MOB_INDEX_DATA *pMob, FILE *fp );
/**************************************************************************/
// will change the vnum if it is only inside the untranslated vnum range
// of the area - needed to find the new reset values of mobs etc
void apply_area_vnum_offset(int *old_vnum)
{
if(!area_last){
bug("apply_area_offset called when area_last==NULL!");
}
// do the translation if necessary
if( area_last->vnum_offset
&& *old_vnum <= area_last->max_vnum
&& *old_vnum >= area_last->min_vnum)
{
*old_vnum+=area_last->vnum_offset;
}
}
/**************************************************************************/
// Prepare a word to be written to file by putting it in 's if necessary
// Also convert ''s to `'s
// Multibuffered :)
const char *pack_word(const char *word)
{
static int i;
static char buf[5][512];
++i%=5;
buf[i][0] = '\0';
if(IS_NULLSTR(word)){
return "''";
}
int j=1;
bool quote=false;
for(const char *p=word; *p; p++)
{
if(is_space(*p)){
quote=true;
buf[i][j]=*p;
}else if(*p=='\''){
buf[i][j]='`';
}else{
buf[i][j]=*p;
}
j++;
}
buf[i][j]='\0';
if(quote){
buf[i][0]='\'';
buf[i][j]='\'';
buf[i][j+1]='\0';
return buf[i];
}
return &buf[i][1];
}
/**************************************************************************/
// Prepare a string to be written to file - Kal Jan 2001
// - Removing all \r's
// - Converting ~'s into {-
// - Prefixing the string with a . if the string begins with a . or space
char *pack_string(const char *str)
{
if(IS_NULLSTR(str)){
return "";
}
const char *p=str;
char *result=&temp_HSL_workspace[1];
// process the input string
while(*p){
if(*p=='\r'){ // ignore \r's
p++;
}else if(*p=='~'){ // convert ~ into `-
*result++='`';
*result++='-';
p++;
}else{
*result++=*p++;
}
}
*result='\0';
if(is_space(temp_HSL_workspace[1]) || temp_HSL_workspace[1]=='.'){
temp_HSL_workspace[0]='.';
return temp_HSL_workspace;
}
return &temp_HSL_workspace[1];
}
/**************************************************************************/
// Remove a leading . from a string if it has one - Kal Jan 2001
char *unpack_string(char *str)
{
if(IS_NULLSTR(str)){
return str_dup("");
}
if(*str=='.'){
char *result=str_dup(str+1);
free_string(str);
return result;
}
return str;
}
/**************************************************************************/
void fwrite_roomecho(room_echo_data *pRe, FILE *fp)
{
fprintf(fp, "RoomEcho %2d %2d %3d %s~\n", pRe->firsthour, pRe->lasthour,
pRe->percentage,pack_string(pRe->echotext));
}
/**************************************************************************/
void fwrite_roomecho_recursive(room_echo_data *pRe, FILE *fp)
{
if(!pRe){ // no more? descripts to write
return;
}
fwrite_roomecho_recursive(pRe->next, fp);
fwrite_roomecho(pRe, fp);
}
/**************************************************************************/
void fwrite_extradesc(EXTRA_DESCR_DATA *pEd, FILE *fp)
{
fprintf( fp, "ExtraDesc %s~\n", pack_string(pEd->keyword));
fprintf( fp, "%s~\n",pack_string(pEd->description));
}
/**************************************************************************/
// extra description saving recursive loop in order to save the descripts
// in reverse order as loaded - Kal Jan 01
void fwrite_extradesc_recursive(EXTRA_DESCR_DATA *pEd, FILE *fp)
{
if(!pEd){ // no more? descripts to write
return;
}
fwrite_extradesc_recursive(pEd->next, fp);
fwrite_extradesc(pEd, fp);
}
/**************************************************************************/
// save one room in New Area File Format
// - Kal, based on what Kerenos started
void save_rooms_NAFF( FILE *fp, AREA_DATA *pArea )
{
ROOM_INDEX_DATA *pRoomIndex;
EXIT_DATA *pExit;
int i;
int exit;
fprintf( fp, "#ROOMS\n" );
for( i = pArea->min_vnum; i <= pArea->max_vnum; i++ ){
pRoomIndex=get_room_index(i);
if(pRoomIndex)
{
fprintf( fp, "#%d\n", pRoomIndex->vnum );
fprintf( fp, "Name %s~\n", pack_string(pRoomIndex->name));
fprintf( fp, "Desc %s~\n", pack_string(pRoomIndex->description));
fwrite_wordflag( room_flags, pRoomIndex->room_flags, "RoomFlags ", fp);
fwrite_wordflag( room2_flags, pRoomIndex->room2_flags, "Room2Flags ", fp);
fwrite_wordflag( sector_types, pRoomIndex->sector_type, "Sector ", fp);
if ( pRoomIndex->mana_rate != 100 ){
fprintf( fp, "Mana %d\n", pRoomIndex->mana_rate );
}
if ( pRoomIndex->heal_rate != 100 ){
fprintf( fp, "Heal %d\n", pRoomIndex->heal_rate );
}
if(pRoomIndex->lockers){
locker_room_data *rl=pRoomIndex->lockers;
if ( rl->quantity){
fprintf( fp, "LockerQuant %d\n", rl->quantity);
}
if(rl->initial_rent){
fprintf( fp, "LockerInitRent %d\n", rl->initial_rent);
}
if ( rl->ongoing_rent){
fprintf( fp, "LockerOngoRent %d\n", rl->ongoing_rent);
}
if ( rl->weight){
fprintf( fp, "LockerWeight %d\n", rl->weight);
}
if ( rl->capacity){
fprintf( fp, "LockerCapacity %d\n", rl->capacity);
}
if ( rl->pick_proof){
fprintf( fp, "LockerPickProof %d\n", rl->pick_proof);
}
}
if(!IS_NULLSTR(pRoomIndex->msp_sound)){
fprintf( fp, "MSP %s~\n", pack_string(pRoomIndex->msp_sound));
}
if(pRoomIndex->clan){
fprintf( fp, "Clan %s\n", pack_word(pRoomIndex->clan->savename()));
}
if(!IS_NULLSTR(pRoomIndex->owner)){
fprintf( fp, "Owner %s~\n", pack_string(pRoomIndex->owner));
}
// save any room echos
fwrite_roomecho_recursive(pRoomIndex->echoes, fp);
// save any extra descriptions
fwrite_extradesc_recursive(pRoomIndex->extra_descr, fp);
// Exits leading out of the room
for( exit= 0; exit<MAX_DIR; exit++)
{
if (( pExit = pRoomIndex->exit[exit] )
&& pExit->u1.to_room )
{
fprintf( fp, "Exit %s %d\n", pack_word(flag_string(direction_types, exit)),
pExit->u1.to_room->vnum);
fwrite_wordflag(exit_flags, pExit->rs_flags, "EFlags ", fp);
if(pExit->key){
fprintf( fp, "EKeyvnum %d\n", pExit->key);
}
if(!IS_NULLSTR(pExit->keyword)){
fprintf( fp, "EKeywords %s~\n", pack_string(pExit->keyword));
}
if(!IS_NULLSTR(pExit->description)){
fprintf( fp, "EDesc %s~\n", pack_string(pExit->description));
}
}
}
fprintf( fp, "End\n\n\n" );
}
}
fprintf( fp, "#0\n\n\n\n" );
return;
}
/**************************************************************************/
// - Kal, based on what Kerenos started
void load_rooms_NAFF( FILE *fp, int version)
{
ROOM_INDEX_DATA *pRoomIndex;
char *word=NULL;
char *previousword;
bool fMatch, done = false;
if ( area_last == NULL )
{
bug("Load_rooms_NAFF(): no #AREA seen yet.");
exit_error( 1 , "load_rooms_NAFF", "no #AREA seen yet");
}
for ( ; ; )
{
EXIT_DATA *last_exit;
vn_int vnum;
char letter;
int door;
int iHash;
letter = fread_letter( fp );
if ( letter != '#' )
{
bug("Load_rooms_NAFF: # not found.");
exit_error( 1 , "load_rooms_NAFF", "# not found");
}
vnum = fread_number( fp );
if ( vnum == 0 )
break;
vnum+= area_last->vnum_offset;
fBootDb = false;
ROOM_INDEX_DATA *dup_room_index=get_room_index( vnum );
if ( dup_room_index)
{
bugf( "Load_rooms_NAFF: vnum %d duplicated with room from areafile '%s'.",
vnum, dup_room_index->area?dup_room_index->area->file_name:"unknown");
exit_error( 1 , "load_rooms_NAFF", "duplicate vnum");
}
fBootDb = true;
last_vnum = vnum; // backup the last vnum for gdb use
last_exit=NULL;
pRoomIndex = new_room_index();
pRoomIndex->area = area_last;
pRoomIndex->vnum = vnum;
// check vnum fits in area vnum range
if ( vnum < pRoomIndex->area->min_vnum + pRoomIndex->area->vnum_offset)
{
bugf("Room with Vnum %d is less than area %s <%s> vnum %d!",
vnum,
pRoomIndex->area->name,
pRoomIndex->area->file_name,
pRoomIndex->area->min_vnum );
}
if ( vnum > pRoomIndex->area->max_vnum + pRoomIndex->area->vnum_offset)
{
bugf("Room with Vnum %d is greater than area %s <%s> vnum %d!",
vnum,
pRoomIndex->area->name,
pRoomIndex->area->file_name,
pRoomIndex->area->max_vnum );
}
for ( ; ; )
{
previousword = word;
word = feof( fp ) ? (char*)"End" : fread_word( fp );
fMatch = false;
switch ( UPPER(word[0]) )
{
case '*':
fMatch = true;
fread_to_eol( fp );
break;
case 'C':
KEY( "Clan", pRoomIndex->clan, clan_slookup(fread_word( fp )));
break;
case 'D':
KEY( "Desc", pRoomIndex->description, unpack_string(fread_string( fp )));
break;
case 'E':
if ( !str_cmp( word, "ExtraDesc" ))
{
EXTRA_DESCR_DATA *ed=new_extra_descr();
ed->keyword = unpack_string(fread_string( fp ));
ed->description = unpack_string(fread_string( fp ));
ed->next = pRoomIndex->extra_descr;
pRoomIndex->extra_descr = ed;
top_ed++;
fMatch = true;
break;
}
if ( !str_cmp( word, "Exit" ))
{
EXIT_DATA *pexit;
door = wordflag_to_value( direction_types, fread_word( fp ));
if ( door < 0 || door>=MAX_DIR )
{
bugf("load_rooms_NAFF: room vnum %d '%s' has bad door number.",
vnum, pRoomIndex->name);
exit_error( 1 , "load_rooms_NAFF", "room with bad doors");
}
pexit = new_exit();
pexit->u1.vnum = fread_number( fp );
apply_area_vnum_offset(&pexit->u1.vnum);
last_exit=pexit;
pRoomIndex->exit[door] = pexit;
top_exit++;
fMatch = true;
break;
}
KEY( "EFlags", last_exit->rs_flags, fread_wordflag( exit_flags, fp ));
KEY( "EKeyvnum", last_exit->key, fread_number(fp) );
KEY( "EKeywords", last_exit->keyword, unpack_string(fread_string(fp)));
KEY( "EDesc", last_exit->description, unpack_string(fread_string(fp)));
if ( !str_cmp( word, "End" ))
{
done = true;
fMatch = true;
break;
}
break;
case 'H':
KEY( "Heal", pRoomIndex->heal_rate, fread_number( fp ));
break;
case 'L':
{
if(!str_prefix("Locker", word)){
// allocate memory for lockers on a just in time basis
if(!pRoomIndex->lockers){
pRoomIndex->lockers=new locker_room_data;
pRoomIndex->lockers->quantity=0;
pRoomIndex->lockers->initial_rent=0;
pRoomIndex->lockers->ongoing_rent=0;
pRoomIndex->lockers->weight=0;
pRoomIndex->lockers->capacity=0;
pRoomIndex->lockers->pick_proof=0;
}
}
KEY( "LockerQuant", pRoomIndex->lockers->quantity, fread_number( fp ));
KEY( "LockerInitRent", pRoomIndex->lockers->initial_rent, fread_number( fp ));
KEY( "LockerOngoRent", pRoomIndex->lockers->ongoing_rent, fread_number( fp ));
KEY( "LockerWeight", pRoomIndex->lockers->weight, fread_number( fp ));
KEY( "LockerCapacity", pRoomIndex->lockers->capacity, fread_number( fp ));
KEY( "LockerPickProof", pRoomIndex->lockers->pick_proof, fread_number( fp ));
}
break;
case 'M':
KEY( "Mana", pRoomIndex->mana_rate, fread_number( fp ));
KEY( "MSP", pRoomIndex->msp_sound, unpack_string(fread_string( fp )));
break;
case 'N':
KEY( "Name", pRoomIndex->name, unpack_string(fread_string( fp )));
break;
case 'O':
KEY( "Owner", pRoomIndex->owner, unpack_string(fread_string( fp )));
break;
case 'R':
KEY( "RoomFlags", pRoomIndex->room_flags, fread_wordflag( room_flags, fp ));
KEY( "Room2Flags", pRoomIndex->room2_flags, fread_wordflag( room2_flags, fp ));
if(!str_cmp( word, "RoomEcho"))
{
room_echo_data *re=new_room_echo();
re->firsthour =fread_number(fp);
re->lasthour =fread_number(fp);
re->percentage =fread_number(fp);
re->echotext =unpack_string(fread_string(fp));
re->next =pRoomIndex->echoes;
pRoomIndex->echoes= re;
fMatch = true;
break;
}
break;
case 'S':
KEY( "Sector", pRoomIndex->sector_type, fread_wordflag( sector_types, fp ));
break;
}
if ( !fMatch )
{
bugf( "load_rooms_NAFF: no match for '%s', word before that = '%s'.",
word, previousword);
fread_to_eol( fp );
}
if ( done )
{
done = false;
break;
}
}
iHash = vnum % MAX_KEY_HASH;
pRoomIndex->next = room_index_hash[iHash];
room_index_hash[iHash] = pRoomIndex;
top_vnum_room = top_vnum_room < vnum ? vnum : top_vnum_room;
assign_area_vnum( vnum );
}
return;
}
/**************************************************************************/
// save one object in New Area File Format
// - Kal, based on what Kerenos started
void save_object_NAFF( FILE *fp, OBJ_INDEX_DATA *pObjIndex )
{
fprintf( fp, "#%d\n", pObjIndex->vnum );
fprintf( fp, "Name %s~\n", pack_string(pObjIndex->name));
fprintf( fp, "Short %s~\n", pack_string(pObjIndex->short_descr));
fprintf( fp, "Desc %s~\n", pack_string(pObjIndex->description));
fprintf( fp, "Level %d\n", pObjIndex->level );
// ItemType must be saved early, so loading knows how to handle values
fwrite_wordflag( item_types, pObjIndex->item_type, "ItemType ", fp);
if ( IS_TRAPPED( pObjIndex ))
{
fprintf( fp, "Trap %ld %d %d %d\n",
(long)pObjIndex->trap_trig,
pObjIndex->trap_dtype,
pObjIndex->trap_charge,
pObjIndex->trap_modifier );
}
fprintf( fp, "Cost %d\n", pObjIndex->cost );
if(pObjIndex->condition!=100){
fprintf( fp, "Condition %d\n", URANGE(1,pObjIndex->condition, 100));
}
fprintf( fp, "Asize %d\n", pObjIndex->absolute_size );
fprintf( fp, "Rsize %d\n", pObjIndex->relative_size );
fprintf( fp, "Values " ); save_object_values( fp, pObjIndex );
fprintf( fp, "Weight %d\n", pObjIndex->weight );
if(IS_NULLSTR(pObjIndex->material)){
fprintf( fp, "Material unknown~\n");
}else{
fprintf( fp, "Material %s~\n", pack_string(pObjIndex->material));
}
fwrite_wordflag( objextra_flags, pObjIndex->extra_flags, "Extra ", fp);
fwrite_wordflag( objextra2_flags, pObjIndex->extra2_flags,"Extra2 ", fp);
fwrite_wordflag( wear_flags, pObjIndex->wear_flags, "Wear ", fp);
fwrite_wordflag(classnames_flags, pObjIndex->class_allowances,"ClassAllowances ", fp );
fwrite_wordflag(attune_flags, pObjIndex->attune_flags,"AttuneFlags ", fp );
// save all the affects on an object
fwrite_affect_recursive(pObjIndex->affected, fp);
// save classgroup object restrictions - system not really finished
{
OBJRESTRICT_LIST_DATA *pr;
for( pr = pObjIndex->restrict; pr; pr = pr->next )
{
fprintf( fp, "Restrict %d %s %s\n",
pr->priority,
pack_word(pr->classgroup->name),
pack_word(pr->affectprofile->name));
}
}
// extra descriptions
fwrite_extradesc_recursive(pObjIndex->extra_descr, fp);
fprintf(fp, "End\n\n");
return;
}
/**************************************************************************/
// - Kal, based on what Kerenos started
void load_objects_NAFF( FILE *fp, int version)
{
OBJ_INDEX_DATA *pObjIndex;
char *word=NULL;
char *previousword;
bool fMatch, done = false;
if ( !area_last ) // OLC
{
bug("Load_objects: no #AREA seen yet.");
exit_error( 1 , "load_objects_NAFF", "no #AREA seen yet");
}
for ( ; ; )
{
vn_int vnum;
char letter;
int iHash;
letter = fread_letter( fp );
if ( letter != '#' )
{
bug("Load_objects_NAFF: # not found.");
exit_error( 1 , "load_objects_NAFF", "# not found");
}
vnum = fread_number( fp );
if ( vnum == 0 )
break;
vnum+= area_last->vnum_offset;
fBootDb = false;
if ( get_obj_index( vnum ) != NULL )
{
char *aname="an unknown area.";
if( get_obj_index( vnum )->area
&& get_obj_index( vnum )->area->file_name){
aname=get_obj_index( vnum )->area->file_name;
}
bugf( "Load_objects_NAFF: vnum %d duplicated.", vnum );
logf("with %s (%s) from %s",
get_obj_index( vnum )->short_descr,
get_obj_index( vnum )->name,
aname);
exit_error( 1 , "load_objects_NAFF", "duplicate vnum");
}
fBootDb = true;
last_vnum = vnum; // backup the last vnum for gdb use
pObjIndex = (OBJ_INDEX_DATA *)alloc_perm( sizeof(*pObjIndex) );
pObjIndex->vnum = vnum;
pObjIndex->area = area_last;
// check object vnum fits in areas vnum range
if ( vnum < pObjIndex->area->min_vnum + pObjIndex->area->vnum_offset)
{
bugf("Object with Vnum %d is less than area %s <%s> vnum %d!",
vnum,
pObjIndex->area->name,
pObjIndex->area->file_name,
pObjIndex->area->min_vnum
);
}
if ( vnum > pObjIndex->area->max_vnum + pObjIndex->area->vnum_offset)
{
bugf("Object with Vnum %d is greater than area %s <%s> vnum %d!",
vnum,
pObjIndex->area->name,
pObjIndex->area->file_name,
pObjIndex->area->max_vnum
);
}
pObjIndex->trap_trig = 0;
pObjIndex->trap_dtype = 0;
pObjIndex->trap_charge = 0;
pObjIndex->trap_modifier= 0;
pObjIndex->condition = 100;
pObjIndex->reset_num = 0;
for ( ; ; )
{
previousword = word;
word = feof( fp ) ? (char*)"End" : fread_word( fp );
fMatch = false;
switch ( UPPER(word[0]) )
{
case '*':
fMatch = true;
fread_to_eol( fp );
break;
case 'A':
KEY( "Asize", pObjIndex->absolute_size, fread_number( fp ));
KEY( "AttuneFlags", pObjIndex->attune_flags, fread_wordflag( attune_flags, fp ));
if ( !str_cmp( word, "Affect" ))
{
AFFECT_DATA *paf=fread_affect(fp);
paf->next = pObjIndex->affected;
pObjIndex->affected = paf;
top_affect++;
fMatch = true;
break;
}
break;
case 'C':
KEY( "Cost", pObjIndex->cost, fread_number( fp ));
KEY( "Condition", pObjIndex->condition, fread_number( fp ));
KEY( "ClassAllowances", pObjIndex->class_allowances,fread_wordflag( classnames_flags, fp ));
break;
case 'D':
KEY( "Desc", pObjIndex->description, unpack_string(fread_string( fp )));
break;
case 'E':
KEY( "Extra", pObjIndex->extra_flags, fread_wordflag( objextra_flags, fp ));
KEY( "Extra2", pObjIndex->extra2_flags, fread_wordflag( objextra2_flags, fp ));
if ( !str_cmp( word, "ExtraDesc" ))
{
EXTRA_DESCR_DATA *ed=new_extra_descr();
ed->keyword = unpack_string(fread_string( fp ));
ed->description = unpack_string(fread_string( fp ));
ed->next = pObjIndex->extra_descr;
pObjIndex->extra_descr = ed;
top_ed++;
fMatch = true;
if (str_len(ed->description)>MSL-4 || str_len(ed->keyword)>MSL-4 )
{
bugf("load_objects_NAFF: Extended description in object "
"%d is %d characters!!! (more than %d)",
(int)last_vnum, str_len(ed->description), MSL-4);
exit_error( 1 , "load_objects_NAFF", "extended description too long.");
}
break;
}
if ( !str_cmp( word, "End" ))
{
if(pObjIndex->item_type==0){
bugf("undefined item type for object %d... can not load area file!",
pObjIndex->vnum);
exit_error( 1 , "load_objects_NAFF", "undefined item type");
}
done = true;
fMatch = true;
break;
}
break;
case 'I':
KEY( "ItemType", pObjIndex->item_type, fread_wordflag( item_types, fp ));
break;
case 'L':
KEY( "Level", pObjIndex->level, fread_number( fp ));
break;
case 'M':
KEY( "Material", pObjIndex->material, unpack_string(fread_string(fp)));
break;
case 'N':
KEY( "Name", pObjIndex->name, unpack_string(fread_string(fp)));
break;
case 'R':
KEY( "Rsize", pObjIndex->relative_size, fread_number( fp ));
if ( !str_cmp( word, "Restrict" ))
{
OBJRESTRICT_LIST_DATA *pr;
classgroup_type * cg;
affectprofile_type *ap;
int priority = fread_number( fp );
char * classgroup = fread_word ( fp );
char * affectprofile = fread_word ( fp );
cg=classgroup_lookup(classgroup);
ap=affectprofile_lookup(affectprofile);
if(!cg || !ap){
if(!cg){
bugf("Unknown classgroup '%s' for object vnum %d restriction, IGNORING!",
classgroup, vnum);
}
if(!ap){
bugf("Unknown affectprofile '%s' for object vnum %d restriction, IGNORING!",
affectprofile, vnum);
}
}else{
pr=new OBJRESTRICT_LIST_DATA;
pr->affectprofile=ap;
pr->classgroup=cg;
pr->priority=priority;
// can't have positive affect modifiers
if(ap->wear_amount>0){
bugf("positive ap->wear_amount for %s, inverted.", ap->name);
ap->wear_amount=0-ap->wear_amount;
}
// Add it to the restricts list
pr->next = pObjIndex->restrict;
pObjIndex->restrict = pr;
SET_BIT(pObjIndex->objrestrict,(1<<cg->bitindex)); // create bit quick lookup
}
fMatch = true;
break;
}
break;
case 'S':
KEY( "Short", pObjIndex->short_descr, unpack_string(fread_string( fp )));
break;
case 'T':
if ( !str_cmp( word, "Trap" ))
{
pObjIndex->trap_trig = fread_number( fp );
pObjIndex->trap_dtype = fread_number( fp );
pObjIndex->trap_charge = fread_number( fp );
pObjIndex->trap_modifier= fread_number( fp );
fMatch = true;
break;
}
break;
case 'V':
if ( !str_cmp( word, "Values" )){
load_object_values( fp, version, pObjIndex );
fMatch = true;
break;
}
break;
case 'W':
KEY( "Wear", pObjIndex->wear_flags, fread_wordflag( wear_flags, fp ));
KEY( "Weight", pObjIndex->weight, fread_number( fp ));
break;
}
if ( !fMatch )
{
bugf( "load_objects_NAFF: no match for '%s', word before that = '%s'.",
word, previousword);
fread_to_eol( fp );
}
if ( done )
{
done = false;
break;
}
}
iHash = vnum % MAX_KEY_HASH;
pObjIndex->next = obj_index_hash[iHash];
obj_index_hash[iHash] = pObjIndex;
top_obj_index++;
}
return;
}
/**************************************************************************/
void fwrite_mobprog(MPROG_LIST *pMprog, FILE *fp)
{
if(pMprog->pos_flags){
// A '=' directly after the mprog word means the end of
// the line has the positions for the prog
fprintf(fp, "MProg = %s %d %s~%s~\n",
mprog_type_to_name(pMprog->trig_type),
pMprog->prog->vnum,
pack_string(pMprog->trig_phrase),
flag_string(position_flags, pMprog->pos_flags));
}else{
fprintf(fp, "MProg %s %d %s~\n",
mprog_type_to_name(pMprog->trig_type),
pMprog->prog->vnum,
pack_string(pMprog->trig_phrase));
}
}
/**************************************************************************/
// mobprog saving recursive loop in order to save the mobprogs in
// reverse order as loaded - Kal Jan 01
void fwrite_mobprog_recursive(MPROG_LIST *pMprog, FILE *fp)
{
if(!pMprog){ // no more? mobprogs to write
return;
}
fwrite_mobprog_recursive(pMprog->next, fp);
fwrite_mobprog(pMprog, fp);
}
/**************************************************************************/
// save one mobile in New Area File Format
// - Kal, based on what Kerenos started
void save_mobile_NAFF( FILE *fp, MOB_INDEX_DATA *pMobIndex )
{
fprintf( fp, "#%d\n", pMobIndex->vnum);
fprintf( fp, "Name %s~\n", pack_string( pMobIndex->player_name));
fprintf( fp, "ShortD %s~\n", pack_string( pMobIndex->short_descr));
fprintf( fp, "LongD %s~\n", pack_string( pMobIndex->long_descr ));
fprintf( fp, "Desc %s~\n", pack_string( pMobIndex->description));
fprintf( fp, "Race %s~\n", pack_string(race_table[pMobIndex->race]->name));
fprintf( fp, "Align %d %d\n", pMobIndex->tendency, pMobIndex->alliance );
if(pMobIndex->xp_mod!=100){
fprintf( fp, "XPMod %d\n", pMobIndex->xp_mod );
}
fprintf( fp, "Level %d\n", pMobIndex->level );
fprintf( fp, "Hitroll %d\n", pMobIndex->hitroll );
fprintf( fp, "HitDice %dd%d+%d\n", pMobIndex->hit[DICE_NUMBER],
pMobIndex->hit[DICE_TYPE],
pMobIndex->hit[DICE_BONUS] );
fprintf( fp, "ManaDice %dd%d+%d\n", pMobIndex->mana[DICE_NUMBER],
pMobIndex->mana[DICE_TYPE],
pMobIndex->mana[DICE_BONUS] );
fprintf( fp, "DamDice %dd%d+%d\n", pMobIndex->damage[DICE_NUMBER],
pMobIndex->damage[DICE_TYPE],
pMobIndex->damage[DICE_BONUS] );
fprintf( fp, "DamType %s\n", pack_word(attack_table[pMobIndex->dam_type].name));
fprintf( fp, "AC %d %d %d %d\n", pMobIndex->ac[AC_PIERCE],
pMobIndex->ac[AC_BASH],
pMobIndex->ac[AC_SLASH],
pMobIndex->ac[AC_EXOTIC]);
fprintf( fp, "Wealth %ld\n", pMobIndex->wealth );
fwrite_wordflag( act_flags, pMobIndex->act, "Act ", fp);
fwrite_wordflag( act2_flags, pMobIndex->act2, "Act2 ", fp);
fwrite_wordflag( affect_flags, pMobIndex->affected_by, "AffBy ", fp);
fwrite_wordflag( affect2_flags, pMobIndex->affected_by2,"AffBy2 ", fp);
fwrite_wordflag( off_flags, pMobIndex->off_flags, "Off ", fp);
fwrite_wordflag( imm_flags, pMobIndex->imm_flags, "Imm ", fp);
fwrite_wordflag( res_flags, pMobIndex->res_flags, "Res ", fp);
fwrite_wordflag( vuln_flags, pMobIndex->vuln_flags, "Vuln ", fp);
fwrite_wordflag( form_flags, pMobIndex->form, "Form ", fp);
fwrite_wordflag( part_flags, pMobIndex->parts, "Part ", fp);
fwrite_wordflag( position_types, pMobIndex->start_pos, "StartP ", fp);
fwrite_wordflag( position_types, pMobIndex->default_pos, "DefPos ", fp);
fwrite_wordflag( size_types, pMobIndex->size, "Size ", fp);
fwrite_wordflag( sex_types, pMobIndex->sex, "Sex ", fp);
if(pMobIndex->gamble_fun){
fprintf(fp,"Gamble %s\n", pack_word(gamble_name(pMobIndex->gamble_fun)));
}
if(pMobIndex->pInnData){
fprintf(fp,"InnBuy %d\n", pMobIndex->pInnData->profit_buy);
fprintf(fp,"InnSell %d\n", pMobIndex->pInnData->profit_sell);
fprintf(fp,"InnOpen %d\n", pMobIndex->pInnData->open_hour);
fprintf(fp,"InnClose %d\n", pMobIndex->pInnData->close_hour);
for(int i=0;i<MAX_INN; i++){
if(pMobIndex->pInnData->vnRoom[i]){
fprintf(fp,"InnRoom %d %d\n", pMobIndex->pInnData->vnRoom[i], pMobIndex->pInnData->shRate[i]);
}
}
}
if(IS_NULLSTR(pMobIndex->material)){
fprintf( fp, "Material unknown\n");
}else{
fprintf( fp, "Material %s\n" , pack_word(pMobIndex->material));
}
if (pMobIndex->group){
fprintf( fp, "Group %d\n", pMobIndex->group);
}
if (pMobIndex->helpgroup){
fprintf( fp, "Helpgroup %d\n", pMobIndex->helpgroup);
}
fwrite_mobprog_recursive(pMobIndex->mprogs, fp);
fprintf(fp, "END\n\n");
return;
}
/**************************************************************************/
// - Kal, based on what Kerenos started
void load_mobiles_NAFF( FILE *fp, int)
{
MOB_INDEX_DATA *pMobIndex;
if ( !area_last ) // OLC
{
bug("Load_mobiles: no #AREA seen yet.");
exit_error( 1 , "load_mobiles_NAFF", "no #AREA seen yet");
}
for ( ; ; )
{
vn_int vnum;
char letter;
int iHash;
letter = fread_letter( fp );
if ( letter != '#' )
{
bug("load_mobiles_NAFF(): # not found.");
exit_error( 1 , "load_mobiles_NAFF", "# not found");
}
vnum = fread_number( fp );
if ( vnum == 0 )// end of mobiles section
break;
// apply our vnum offset
vnum+= area_last->vnum_offset;
fBootDb = false; // Must be outside the get_mob_index() check as with fBootDb
// set to false get_mob_index() doesn't log the lookup
if ( get_mob_index( vnum ) != NULL )
{
char *aname="an unknown area.";
if( get_mob_index( vnum )->area
&& get_mob_index( vnum )->area->file_name){
aname=get_mob_index( vnum )->area->file_name;
}
bugf( "load_mobiles_NAFF(): vnum %d duplicated.", vnum );
logf("with %s (%s) from %s",
get_mob_index( vnum )->short_descr,
get_mob_index( vnum )->player_name,
aname);
exit_error( 1 , "load_mobiles_NAFF", "duplicate vnum");
}
fBootDb = true;
last_vnum = vnum; // backup the last vnum for gdb use
pMobIndex= (MOB_INDEX_DATA *)alloc_perm( sizeof(*pMobIndex) );
pMobIndex->vnum = vnum;
pMobIndex->area = area_last;
// check mob vnum fits in areas vnum range
if ( vnum < pMobIndex->area->min_vnum + pMobIndex->area->vnum_offset)
{
bugf("Mob with Vnum %d is less than area %s <%s> vnum %d!",
vnum,
pMobIndex->area->name,
pMobIndex->area->file_name,
pMobIndex->area->min_vnum
);
}
if ( vnum > pMobIndex->area->max_vnum + pMobIndex->area->vnum_offset)
{
bugf("Mob with Vnum %d is greater than area %s <%s> vnum %d!",
vnum,
pMobIndex->area->name,
pMobIndex->area->file_name,
pMobIndex->area->max_vnum
);
}
pMobIndex->pShop = NULL;
pMobIndex->xp_mod = 100; // default to normal xp
fread_mob_NAFF( pMobIndex, fp );
iHash = vnum % MAX_KEY_HASH;
pMobIndex->next = mob_index_hash[iHash];
mob_index_hash[iHash] = pMobIndex;
top_mob_index++;
kill_table[URANGE(0, pMobIndex->level, MAX_LEVEL-1)].number++;
// linked list of all pMobIndex records
pMobIndex->listnext=pMobIndexlist;
pMobIndexlist=pMobIndex;
}
return;
}
/**************************************************************************/
// - Kal, based on what Kerenos started
void fread_mob_NAFF( MOB_INDEX_DATA *pMob, FILE *fp )
{
char *word=NULL;
char *previousword;
bool fMatch;
for ( ; ; )
{
previousword=word;
word = feof( fp ) ? (char*)"End" : fread_word( fp );
fMatch = false;
switch ( UPPER(word[0]) )
{
case '*':
fMatch = true;
fread_to_eol( fp );
break;
case 'A':
KEY( "Act", pMob->act, fread_wordflag( act_flags, fp ));
KEY( "Act2", pMob->act2, fread_wordflag( act2_flags, fp ));
KEY( "AffBy", pMob->affected_by, fread_wordflag( affect_flags, fp ));
KEY( "AffBy2", pMob->affected_by2, fread_wordflag( affect2_flags, fp ));
if (!str_cmp( word, "Align"))
{
pMob->tendency=fread_number( fp );
pMob->alliance=fread_number( fp );
fMatch=true;
break;
}
if (!str_cmp(word,"AC"))
{
for(int i = 0; i < 4; i++){
pMob->ac[i] = fread_number(fp);
}
fMatch = true;
break;
}
break;
case 'D':
KEY( "Desc", pMob->description, unpack_string(fread_string( fp )));
KEY( "DamType", pMob->dam_type, attack_lookup(fread_word(fp)));
KEY( "DefPos", pMob->default_pos, fread_wordflag( position_types, fp ));
if ( !str_cmp( word, "DamDice" )) // 5 d 10 + 50
{
pMob->damage[DICE_NUMBER] = fread_number( fp ); // 5
fread_letter( fp ); // d
pMob->damage[DICE_TYPE] = fread_number( fp ); // 10
fread_letter( fp ); // +
pMob->damage[DICE_BONUS] = fread_number( fp ); // 50
fMatch = true;
break;
}
break;
case 'E':
if ( !str_cmp( word, "End" ) )
{
// Last spot in which to default mob settings and such
// count all the usage stats while loading
race_table[pMob->race]->inuse++;
total_npcracescount++;
if (race_table[pMob->race]->lastarea!=area_last){
race_table[pMob->race]->areacount++;
total_npcareacount++;
}
race_table[pMob->race]->lastarea=area_last;
// Capitalize
pMob->long_descr[0] = UPPER(pMob->long_descr[0]);
pMob->description[0] = UPPER(pMob->description[0]);
pMob->short_descr[0] = LOWER(pMob->short_descr[0]);
SET_BIT(pMob->act, ACT_IS_NPC); // all mobs are NPC's :)
return;
}
break;
case 'F':
KEY( "Form", pMob->form, fread_wordflag( form_flags, fp ));
break;
case 'G':
KEY( "Group", pMob->group, fread_number( fp ));
KEY( "Gamble", pMob->gamble_fun, gamble_lookup(fread_word(fp)));
break;
case 'H':
KEY( "HelpGroup", pMob->helpgroup, fread_number( fp ))
KEY( "Hitroll", pMob->hitroll, fread_number( fp ));
if ( !str_cmp( word, "HitDice" )) // 5 d 10 + 50
{
pMob->hit[DICE_NUMBER] = fread_number( fp ); // 5
fread_letter( fp ); // d (discarded)
pMob->hit[DICE_TYPE] = fread_number( fp ); // 10
fread_letter( fp ); // + (discarded)
pMob->hit[DICE_BONUS] = fread_number( fp ); // 50
if(pMob->hit[DICE_NUMBER]<0 || pMob->hit[DICE_TYPE]<0 || pMob->hit[DICE_BONUS]<0){
char *aname="an unknown area.";
if(pMob->area && !IS_NULLSTR(pMob->area->file_name)){
aname=pMob->area->file_name;
}
bugf("Mob %d has an invalid hitdice of %dd%d+%d... manually edit %s and fix the area.",
pMob->vnum, pMob->hit[DICE_NUMBER], pMob->hit[DICE_TYPE],
pMob->hit[DICE_BONUS], aname);
exit_error( 1 , "fread_mob_NAFF", "invalid hitdice");
}
fMatch = true;
break;
}
break;
case 'I':
KEY( "Imm", pMob->imm_flags, fread_wordflag( imm_flags, fp ));
{ // handle reading in the inns
// if a mob has something that starts with the word Inn,
// confirm we have allocated memory for the inn
// if we haven't then we do it now
if(!str_prefix("inn", word)){
if(!pMob->pInnData){
pMob->pInnData= new cInnData;
top_inn++;
if ( !pFirstInn ) {
pFirstInn=pMob->pInnData;
}
if ( pLastInn ) {
pLastInn->pNextInn = pMob->pInnData;
}
pLastInn = pMob->pInnData;
pLastInn->pNextInn = NULL;
pMob->pInnData->vnKeeper = pMob->vnum;
}
}
KEY( "InnBuy", pMob->pInnData->profit_buy, fread_number(fp ));
KEY( "InnSell", pMob->pInnData->profit_sell,fread_number(fp ));
KEY( "InnOpen", pMob->pInnData->open_hour, fread_number(fp ));
KEY( "InnClose",pMob->pInnData->close_hour, fread_number(fp ));
if(!str_cmp(word, "InnRoom")){
int i;
// first read the data
int roomvnum=fread_number(fp);
int roomrate=fread_number(fp);
// now add them as the first unused inn
for(i=0; i<MAX_INN; i++){
if(!pMob->pInnData->vnRoom[i]){
pMob->pInnData->vnRoom[i]=roomvnum;
pMob->pInnData->shRate[i]=roomrate;
break;
}
}
if(i==MAX_INN){
bugf("No room to store InnRoom %d %d for mob %d, discarding.",
roomvnum, roomrate, pMob->vnum);
}
fMatch = true;
}
}
break;
case 'L':
KEY( "Level", pMob->level, fread_number( fp ));
KEY( "LongD", pMob->long_descr,
trim_trailing_carriage_return_line_feed(unpack_string(fread_string( fp ))));
break;
case 'M':
KEY( "Material", pMob->material, str_dup(fread_word( fp )));
if ( !str_cmp( word, "ManaDice" )) // 5 d 10 + 50
{
pMob->mana[DICE_NUMBER] = fread_number( fp ); // 5
fread_letter( fp ); // d
pMob->mana[DICE_TYPE] = fread_number( fp ); // 10
fread_letter( fp ); // +
pMob->mana[DICE_BONUS] = fread_number( fp ); // 50
fMatch = true;
break;
}
if ( !str_cmp( word, "MProg" ))
{
MPROG_LIST *pMprog;
char *wod;
int trigger = 0;
bool positions=false;
pMprog = (MPROG_LIST *)alloc_perm(sizeof(*pMprog));
wod = fread_word( fp );
// support position flags
if(wod[0]=='='){
positions=true;
wod= fread_word( fp );
}
if ( !(trigger = flag_lookup( wod, mprog_flags )) )
{
bugf("MOBprogs: Invalid trigger '%s' on mob %d.", wod, pMob->vnum);
exit_error( 1 , "fread_mob_NAFF", "invalid trigger");
}
SET_BIT( pMob->mprog_flags, trigger );
pMprog->trig_type = trigger;
// get the mobprog number, with vnum translation support
int mpvnum=fread_number( fp );
apply_area_vnum_offset( &mpvnum); // this system only works within a particular area
assert(mpvnum!=0);
pMprog->temp_mpvnum= mpvnum; // hack for loading - fixed up in fix_mobprogs
pMprog->trig_phrase = unpack_string(fread_string( fp ));
if(positions){
pMprog->pos_flags=fread_wordflag(position_flags, fp);
}else{
pMprog->pos_flags=0;
}
pMprog->next = pMob->mprogs;
pMob->mprogs = pMprog;
fMatch = true;
break;
}
break;
case 'N':
KEY( "Name", pMob->player_name, unpack_string(fread_string( fp )));
break;
case 'O':
KEY( "Off", pMob->off_flags, fread_wordflag( off_flags, fp ));
break;
case 'P':
KEY( "Part", pMob->parts, fread_wordflag( part_flags, fp ));
break;
case 'R':
KEY( "Res", pMob->res_flags, fread_wordflag( res_flags, fp ));
if ( !str_cmp( word, "Race" ) )
{
char *racename=unpack_string(fread_string( fp ));
pMob->race = race_lookup(racename);
if(pMob->race == -1)
{
logf("Mob %d has an unrecognised race '%s', "
"dynamically creating race.", pMob->vnum, racename);
pMob->race= race_generate_race_adding_to_race_table(racename);
}
free_string(racename);
fMatch = true;
break;
}
break;
case 'S':
KEY( "ShortD", pMob->short_descr, unpack_string(fread_string( fp )));
KEY( "StartP", pMob->start_pos, fread_wordflag( position_types, fp ));
KEY( "Size", pMob->size, fread_wordflag( size_types, fp ));
KEY( "Sex", pMob->sex, fread_wordflag( sex_types, fp ));
break;
case 'V':
KEY( "Vuln", pMob->vuln_flags, fread_wordflag( vuln_flags, fp ));
break;
case 'W':
if ( !str_cmp( word, "Wealth" ))
{
pMob->wealth = fread_number( fp );
if ( pMob->wealth > pMob->level*MAX_MOB_WEALTH_MULTIPLIER){
bugf("Mob %d read in with wealth greater than Mob->level*%d (%d), reduced wealth to max",
pMob->vnum, pMob->level*MAX_MOB_WEALTH_MULTIPLIER, (int)pMob->wealth);
pMob->wealth = pMob->level*MAX_MOB_WEALTH_MULTIPLIER;
}
if( pMob->wealth < 0 ){
pMob->wealth = 0;
}
fMatch = true;
break;
}
break;
case 'X':
if ( !str_cmp( word, "XPMod" ))
{
pMob->xp_mod = fread_number( fp );
if( pMob->xp_mod < 0 ){
bugf("Mob %d read in with xpmod of %d, increased it to 0", pMob->vnum, pMob->xp_mod);
pMob->xp_mod = 0;
}
if( pMob->xp_mod > 200 ){
bugf("Mob %d read in with xpmod of %d, reduced it to 200", pMob->vnum, pMob->xp_mod);
pMob->xp_mod = 200;
}
fMatch = true;
break;
}
break;
}
if ( !fMatch )
{
bugf( "Fread_char: no match for '%s', word before that = '%s'.",
word, previousword);
fread_to_eol( fp );
}
}
}
/**************************************************************************/
#define OLDAPPLY_NONE 0
#define OLDAPPLY_ST 1
#define OLDAPPLY_QU 2
#define OLDAPPLY_PR 3
#define OLDAPPLY_EM 4
#define OLDAPPLY_IN 5
#define OLDAPPLY_SEX 6
#define OLDAPPLY_CLASS 7
#define OLDAPPLY_LEVEL 8
#define OLDAPPLY_AGE 9
#define OLDAPPLY_HEIGHT 10
#define OLDAPPLY_WEIGHT 11
#define OLDAPPLY_MANA 12
#define OLDAPPLY_HIT 13
#define OLDAPPLY_MOVE 14
#define OLDAPPLY_GOLD 15
#define OLDAPPLY_EXP 16
#define OLDAPPLY_AC 17
#define OLDAPPLY_HITROLL 18
#define OLDAPPLY_DAMROLL 19
#define OLDAPPLY_SAVES 20
#define OLDAPPLY_SAVING_PARA 20
#define OLDAPPLY_SAVING_ROD 21
#define OLDAPPLY_SAVING_PETRI 22
#define OLDAPPLY_SAVING_BREATH 23
#define OLDAPPLY_SAVING_SPELL 24
#define OLDAPPLY_SPELL_AFFECT 25 // set to saves, unused in theory though.
#define OLDAPPLY_CO 26
#define OLDAPPLY_AG 27
#define OLDAPPLY_SD 28
#define OLDAPPLY_ME 29
#define OLDAPPLY_RE 30
#define OLDAPPLY_COPY_TO_CHAR 31
struct old_apply_translate_table_type { int oldval; APPLOC apploc_value; };
old_apply_translate_table_type old_apply_translate_table[]=
{
{OLDAPPLY_NONE, APPLY_NONE},
{OLDAPPLY_ST, APPLY_ST},
{OLDAPPLY_QU, APPLY_QU},
{OLDAPPLY_PR, APPLY_PR},
{OLDAPPLY_EM, APPLY_EM},
{OLDAPPLY_IN, APPLY_IN},
{OLDAPPLY_SEX, APPLY_SEX},
{OLDAPPLY_CLASS, APPLY_CLASS},
{OLDAPPLY_LEVEL, APPLY_LEVEL},
{OLDAPPLY_AGE, APPLY_AGE},
{OLDAPPLY_HEIGHT, APPLY_HEIGHT},
{OLDAPPLY_WEIGHT, APPLY_WEIGHT},
{OLDAPPLY_MANA, APPLY_MANA},
{OLDAPPLY_HIT, APPLY_HIT},
{OLDAPPLY_MOVE, APPLY_MOVE},
{OLDAPPLY_GOLD, APPLY_GOLD},
{OLDAPPLY_EXP, APPLY_EXP},
{OLDAPPLY_AC, APPLY_AC},
{OLDAPPLY_HITROLL, APPLY_HITROLL},
{OLDAPPLY_DAMROLL, APPLY_DAMROLL},
{OLDAPPLY_SAVES, APPLY_SAVES},
{OLDAPPLY_SAVING_PARA, APPLY_SAVES},
{OLDAPPLY_SAVING_ROD, APPLY_SAVES},
{OLDAPPLY_SAVING_PETRI, APPLY_SAVES},
{OLDAPPLY_SAVING_BREATH, APPLY_SAVES},
{OLDAPPLY_SAVING_SPELL, APPLY_SAVES},
{OLDAPPLY_SPELL_AFFECT, APPLY_SAVES}, // mapped to a saves...
{OLDAPPLY_CO, APPLY_CO},
{OLDAPPLY_AG, APPLY_AG},
{OLDAPPLY_SD, APPLY_SD},
{OLDAPPLY_ME, APPLY_ME},
{OLDAPPLY_RE, APPLY_RE},
{OLDAPPLY_COPY_TO_CHAR, APPLY_NONE},
{-1, APPLY_NONE} // mark end of table with -1 oldloc
};
/**************************************************************************/
// Convert numeric values stored in files (old file formats) to enumerated
// values - Kal
APPLOC translate_old_apply_number(int oldvalue)
{
for(int i=0; old_apply_translate_table[i].oldval!=-1; i++){
if(oldvalue==old_apply_translate_table[i].oldval){
APPLOC val=old_apply_translate_table[i].apploc_value;
// logf("Translating apply number %2d to %s (%d)",
// oldvalue, flag_string(apply_types,val), val);
return val;
}
}
bugf("translate_old_apply_number(): Unsupported old APPLY_VALUE '%d'... "
"manually remove where it came from?", oldvalue);
do_abort();
return APPLY_NONE; // no compiler area
}
/**************************************************************************/
// reverse the affect of translate_old_apply_number() - Kal
int reverse_translate_old_apply_number(APPLOC newvalue)
{
for(int i=0; old_apply_translate_table[i].oldval!=-1; i++){
if(newvalue==old_apply_translate_table[i].apploc_value){
return old_apply_translate_table[i].oldval;
}
}
bug("reverse_translate_old_apply_number(): Couldn't find number to reverse to!");
do_abort();
return 0;
}
/**************************************************************************/
// write the buy types - Kal
void shopdata_write_buy_types(gio_type *gio_table, int tableIndex,
void *data, FILE *fp)
{
shop_data * psd;
psd= (shop_data*) data;
for(int i=0; i<MAX_TRADE; i++){
if(psd->buy_type[i]){
char heading[MIL];
strcpy(heading, gio_table[tableIndex].heading);
fwrite_wordflag(item_types, psd->buy_type[i], heading, fp);
}
}
}
/**************************************************************************/
// read the buy types - Kal
void shopdata_read_buy_types(gio_type *, int, void *data, FILE *fp)
{
shop_data * psd;
psd= (shop_data*) data;
int bt=fread_wordflag(item_types,fp);
// find the next free buy type slot to put it in.
for(int i=0; i<MAX_TRADE; i++){
if(!psd->buy_type[i]){
psd->buy_type[i]=bt;
return;
}
}
bugf("shopdata_read_buy_types(): Too many buy types for reading in "
"shop that is applied to mob %d", psd->keeper);
exit_error( 1 , "shopdata_read_buy_types", "Too many buy types");
}
/**************************************************************************/
GIO_START(shop_data)
GIO_CUSTOM_WRITEH(buy_type, "buy_type ", shopdata_write_buy_types)
GIO_CUSTOM_READH(buy_type, "buy_type ", shopdata_read_buy_types)
GIO_SHINT(profit_buy)
GIO_SHINT(profit_sell)
GIO_SHINT(open_hour)
GIO_SHINT(close_hour)
GIO_FINISH
/**************************************************************************/
// Save shops in NAFF format - Kal
void save_shops_NAFF( FILE *fp, AREA_DATA *pArea )
{
SHOP_DATA *pShopIndex;
MOB_INDEX_DATA *pMobIndex;
int iHash;
fprintf( fp, "#SHOPS\n" );
for( iHash = 0; iHash < MAX_KEY_HASH; iHash++ )
{
for( pMobIndex = mob_index_hash[iHash]; pMobIndex; pMobIndex = pMobIndex->next )
{
if ( pMobIndex && pMobIndex->area == pArea && pMobIndex->pShop )
{
pShopIndex = pMobIndex->pShop;
fprintf(fp, "#%d\n", pShopIndex->keeper);
GIO_SAVE_RECORD(shop_data, pShopIndex, fp, NULL);
}
}
}
fprintf( fp, "#0\n\n\n" );
return;
}
/**************************************************************************/
// Kal
void load_shops_NAFF( FILE *fp )
{
SHOP_DATA *pShop;
for ( ; ; )
{
char letter = fread_letter( fp );
if ( letter != '#' )
{
bugf("load_shops_NAFF: # not found, letter='%c'.", letter);
exit_error( 1 , "load_shops_NAFF", "# not found");
}
int mobnum=fread_number ( fp );
if ( mobnum == 0 ){
return;
}
apply_area_vnum_offset( &mobnum);
// read in the shop keeper data using GIO
pShop= (SHOP_DATA *)alloc_perm( sizeof(*pShop) );
GIO_LOAD_RECORD(shop_data, pShop, fp);
pShop->keeper= mobnum;
MOB_INDEX_DATA *pMobIndex= get_mob_index( pShop->keeper );
if(!pMobIndex){
bugf("load_shops: Can't find shop keeper with Vnum %d!", pShop->keeper);
}else{
pMobIndex->pShop = pShop;
if ( shop_first == NULL ){
shop_first = pShop;
}
if ( shop_last != NULL ){
shop_last->next = pShop;
}
shop_last = pShop;
pShop->next = NULL;
top_shop++;
}
}
return;
}
/**************************************************************************/
GIO_START(mprog_code)
GIO_STR(title)
GIO_STR(author)
GIO_STR(code)
GIO_BOOL(disabled)
GIO_STR(disabled_text)
GIO_STR(last_editor)
GIO_LONG(last_editdate)
GIO_FINISH_STRDUP_EMPTY
/**************************************************************************/
// Kal
void save_mobprogs_NAFF( FILE *fp, AREA_DATA *pArea )
{
MPROG_CODE *pMprog;
int i;
fprintf(fp, "#MOBPROGS\n");
for( i = pArea->max_vnum; i>=pArea->min_vnum; i-- )
{
if ( (pMprog = get_mprog_index(i) ) != NULL)
{
if(GAMESETTING2(GAMESET2_DONT_SAVE_MOBPROG_AUTHORS)){
replace_string(pMprog->author,"");
}
if(GAMESETTING2(GAMESET2_DONT_SAVE_LASTEDITORS)){
replace_string(pMprog->last_editor,"");
pMprog->last_editdate=0;
}
fprintf(fp, "#%d\n", i);
GIO_SAVE_RECORD(mprog_code, pMprog, fp, NULL);
}
}
fprintf(fp,"#0\n\n\n");
return;
}
/**************************************************************************/
// Kal
void load_mobprogs_NAFF( FILE *fp )
{
for ( ; ; )
{
char letter = fread_letter( fp );
if ( letter != '#' )
{
bugf("load_mobprogs_NAFF: # not found, letter='%c'.", letter);
exit_error( 1 , "load_mobprogs_NAFF", "# not found");
}
int vnum=fread_number ( fp );
if ( vnum== 0 ){
return;
}
apply_area_vnum_offset( &vnum);
fBootDb = false;
if ( get_mprog_index( vnum ) != NULL )
{
bugf( "Load_mobprogs: vnum %d duplicated.", vnum );
exit_error( 1 , "load_mobprogs_NAFF", "duplicate vnum");
}
fBootDb = true;
MPROG_CODE *pMprog=(MPROG_CODE*)alloc_perm( sizeof(*pMprog) );
// read in the mobprog code using GIO
GIO_LOAD_RECORD(mprog_code, pMprog, fp);
mobprog_count++;
pMprog->vnum = vnum;
pMprog->area = area_last;
// add our prog to the list of progs
if ( !mprog_list ){
mprog_list = pMprog;
}else{
pMprog->next = mprog_list;
mprog_list = pMprog;
}
}
return;
}
/**************************************************************************/
// generic affect saving recursive loop in order to save the affects in
// reverse order as loaded - Kal Jan 01
void fwrite_affect_recursive(AFFECT_DATA *paf, FILE *fp)
{
if(!paf){ // we got the short end of the stick
return;
}
fwrite_affect_recursive(paf->next, fp);
fwrite_affect(paf, fp);
}
/**************************************************************************/
// generic affect saving - Kal Jan 01
void fwrite_affect(AFFECT_DATA *paf, FILE *fp)
{
char skillname_text[MIL];
const flag_type *bv_flags=affect_get_bitvector_table_for_where(paf->where);
if(paf->type>=0 && paf->type<MAX_SKILL){
strcpy(skillname_text,skill_table[paf->type].name);
}else{
sprintf(skillname_text,"%d", paf->type);
}
if(!bv_flags && paf->bitvector){
// prevent future developers using the bitvectors without
// adding a wordflag table.
bugf("Affect bitvectors for %d dont have a matching table and are non NULL!",
paf->where);
logf( "Affect %s %s %d %d %s %d %s <<<<<< the last value needs to be non 0!",
pack_word(flag_string(to_types, paf->where)),
pack_word(skillname_text),
paf->level,
paf->duration,
pack_word(flag_string(apply_types, paf->location)),
paf->modifier,
pack_word(bv_flags?flag_string(bv_flags, paf->bitvector):"0"));
do_abort();
}
// generic affect saving
fprintf( fp, "Affect %s %s %d %d %s %d %s\n",
pack_word(flag_string(to_types, paf->where)),
pack_word(skillname_text),
paf->level,
paf->duration,
pack_word(flag_string(apply_types, paf->location)),
paf->modifier,
pack_word(bv_flags && paf->bitvector?flag_string(bv_flags, paf->bitvector):"0"));
}
/**************************************************************************/
// generic affect loading - Kal Jan 01
AFFECT_DATA *fread_affect(FILE *fp)
{
AFFECT_DATA *paf;
paf=(AFFECT_DATA *)alloc_perm( sizeof(*paf) );
char *where_word=fread_word(fp);
paf->where=wordflag_to_value(to_types, where_word);
const flag_type *bv_flags=affect_get_bitvector_table_for_where(paf->where);
char *skillname = fread_word(fp);
if(is_number(skillname)){
paf->type=atoi(skillname);
}else{
paf->type = skill_lookup(skillname);
if(paf->type<0)
{
bugf("fread_affect(): Unfound non numeric skillname '%s' when reading in affect.", skillname);
paf->type=-1;
{ // autonote it and move on.
char body[MSL];
sprintf(body, "fread_affect(): Unfound unrecognised skillname '%s' "
"when reading in affect. This may or maynot be on a pfile... "
"You can get more details in the mud main log by searching for"
"log entries around this date and time.", skillname);
autonote(NOTE_SNOTE, "fread_affect()",
"Unfound non numeric skillname.",
"admin code", body, true);
}
}
}
paf->level = fread_number(fp);
paf->duration = fread_number(fp);
char *location_word=fread_word(fp);
paf->location=(APPLOC)wordflag_to_value(apply_types, location_word);
if(paf->location==NO_FLAG){
bugf("fread_affect(): Unfound recognised affect location '%s' when reading in affect.",
location_word);
exit_error( 1 , "fread_affect", "unfound recognised affect location");
}
paf->modifier = fread_number( fp );
char *bitvector_word=fread_word(fp);
if(bv_flags && !(bitvector_word[0]=='0' && bitvector_word[1]=='\0') ){
paf->bitvector=wordflag_to_value(bv_flags, bitvector_word);
if(paf->bitvector==NO_FLAG){
bugf("fread_affect(): Unfound recognised affect location '%s' when reading in affect.",
location_word);
exit_error( 1 , "fread_affect", "unfound recognised affect location2");
}
}else{
assert(!str_cmp(bitvector_word,"0")); // safety check
paf->bitvector=0;
}
// convert to WHERE_MODIFIER if appropriate
if(paf->where == WHERE_OBJEXTRA && paf->bitvector==0 && paf->location!=APPLY_NONE){
paf->where=WHERE_MODIFIER;
};
return paf;
}
/**************************************************************************/
// Read in a mobiles affects and possible affects two, from an area file
// - Kal, July 01
void areaimport_mobile_affects_stock( FILE *fp, int version, MOB_INDEX_DATA *pMobIndex)
{
if(version<3){
pMobIndex->affected_by = fread_flag( fp ) | race_table[pMobIndex->race]->aff;
pMobIndex->affected_by2 = race_table[pMobIndex->race]->aff2;
return;
}
if ( version > 3 ){
pMobIndex->act2 = fread_flag( fp );
}
if ( version > 4 ){
fread_to_eol(fp);
}
pMobIndex->affected_by = fread_flag( fp )| race_table[pMobIndex->race]->aff;
if ( version > 3 ){
pMobIndex->affected_by2 = fread_flag( fp )| race_table[pMobIndex->race]->aff2;
}
if ( version > 4 || AREA_IMPORT_FLAG(AREAIMPORTFLAG_READ_TO_EOL_ON_ACT_AFF_LINE)){
fread_to_eol(fp);
}
}
/**************************************************************************/
void areaimport_mobile_affects_format2( FILE *fp, int version, MOB_INDEX_DATA *pMobIndex)
{
// in this format, mobile affects are stored in the format
// 16bitnumber 16bitnumber 16bitnumber .... -1
// to translate to dawn the first two 16 bits must be concatenated,
// put thru the rom affect flag to dawn affect flag converter
// then the remainder discarded or translated
// any remaining numbers need to be translated/ignored
// read the first two numbers
int num=fread_number(fp);
int num2=fread_number(fp);
// merge them
num+=num2<<16;
pMobIndex->affected_by=num;
// remove any flags we dont support
// - can be changed to a translation using the example code here:
// *** example translation code ***
//if(IS_SET(pMobIndex->affected_by, ee)){
// REMOVE_BIT(pMobIndex->affected_by, ee);
// SET_BIT(pMobIndex->affected_by2, AFF2_MUTE);
//}
REMOVE_BIT(pMobIndex->affected_by, L);
REMOVE_BIT(pMobIndex->affected_by, ee);
// read the next 16 bits
num=fread_number(fp);
pMobIndex->affected_by2=0;
// translate the affect bits over to dawn positions
REMOVE_BIT(pMobIndex->affected_by, L);
if(IS_SET(pMobIndex->affected_by, ee)){ // AFF_FIRESHIELD (old bit 31)
REMOVE_BIT(pMobIndex->affected_by, ee);
SET_BIT(pMobIndex->affected_by2, AFF2_FIRE_SHIELD);
}
if(IS_SET(pMobIndex->affected_by, 1<<31)){ // AFF_ICESHIELD (old bit 32)
REMOVE_BIT(pMobIndex->affected_by, 1<<31);
SET_BIT(pMobIndex->affected_by2, AFF2_ICE_SHIELD);
}
// bits higher than 33 have moved into num, starting from bit position A
if(IS_SET(num, A)){// AFF_SHOCKSHIELD (old bit 33) -> A
SET_BIT(pMobIndex->affected_by2, AFF2_SHOCK_SHIELD);
}
if(IS_SET(num, B)){// AFF_HALLUCINATE (old bit 34) -> B
SET_BIT(pMobIndex->affected_by2, AFF2_HALLUCINATE);
}
// keep reading until we get a -1 (we aren't interested in any more of the numbers)
while (num!=-1){
num=fread_number(fp);
}
}
/**************************************************************************/
void areaimport_object_translate_flags_stock( FILE *fp, int version, OBJ_INDEX_DATA *pObjIndex)
{
if(version<4){
// TRANSLATE mud WEAR FORMAT TO DAWN FORMAT
// stock rom defines up to Q
REMOVE_BIT(pObjIndex->wear_flags, R | S | T | U | V | W | X | Y | Z | aa | bb | cc | dd | ee);
/*
// fix this up on a per mud basis !?!
// - wear flags
if(IS_SET(pObjIndex->wear_flags, R)){
REMOVE_BIT(pObjIndex->wear_flags, R);
SET_BIT(pObjIndex->wear_flags, OBJWEAR_EYES);
}
if(IS_SET(pObjIndex->wear_flags, S)){
REMOVE_BIT(pObjIndex->wear_flags, S);
SET_BIT(pObjIndex->wear_flags, OBJWEAR_EAR);
}
if(IS_SET(pObjIndex->wear_flags, T)){
REMOVE_BIT(pObjIndex->wear_flags, T);
SET_BIT(pObjIndex->wear_flags, OBJWEAR_FACE);
}
if(IS_SET(pObjIndex->wear_flags, U)){
REMOVE_BIT(pObjIndex->wear_flags, U);
SET_BIT(pObjIndex->wear_flags, OBJWEAR_ANKLE);
}
*/
// extra flags
// stock rom defines up to Z less R
REMOVE_BIT(pObjIndex->extra_flags, R | aa | bb | cc | dd | ee);
/* if(IS_SET(pObjIndex->extra_flags, bb)){
REMOVE_BIT(pObjIndex->extra_flags, bb);
SET_BIT(pObjIndex->extra2_flags, OBJEXTRA2_QUEST);
}
if(IS_SET(pObjIndex->extra_flags, cc)){
REMOVE_BIT(pObjIndex->extra_flags, cc);
SET_BIT(pObjIndex->extra2_flags, OBJEXTRA2_HOLY);
}
if(IS_SET(pObjIndex->extra_flags, dd)){
REMOVE_BIT(pObjIndex->extra_flags, dd);
SET_BIT(pObjIndex->extra2_flags, OBJEXTRA2_REMORT);
}
if(IS_SET(pObjIndex->extra_flags, ee)){
REMOVE_BIT(pObjIndex->extra_flags, ee);
SET_BIT(pObjIndex->extra2_flags, OBJEXTRA2_VAMPIRE_BANE);
}
*/
}
}
/**************************************************************************/
void areaimport_object_translate_flags_format2( FILE *fp, int version, OBJ_INDEX_DATA *pObjIndex)
{
int wear_flags=pObjIndex->wear_flags;
pObjIndex->wear_flags=0;
// TRANSLATE mud WEAR FORMAT TO DAWN FORMAT
// - wear flags
if(IS_SET(wear_flags, A)){
SET_BIT(pObjIndex->wear_flags, OBJWEAR_TAKE);
}
if(IS_SET(wear_flags, B)){
SET_BIT(pObjIndex->wear_flags, OBJWEAR_FLOAT);
}
if(IS_SET(wear_flags, C)){
SET_BIT(pObjIndex->wear_flags, OBJWEAR_HEAD);
}
if(IS_SET(wear_flags, D)){
SET_BIT(pObjIndex->wear_flags, OBJWEAR_FACE);
}
if(IS_SET(wear_flags, E)){
SET_BIT(pObjIndex->wear_flags, OBJWEAR_EAR);
}
if(IS_SET(wear_flags, F)){
SET_BIT(pObjIndex->wear_flags, OBJWEAR_NECK);
}
if(IS_SET(wear_flags, G)){
SET_BIT(pObjIndex->wear_flags, OBJWEAR_ABOUT);
}
if(IS_SET(wear_flags, H)){
SET_BIT(pObjIndex->wear_flags, OBJWEAR_TORSO);
}
if(IS_SET(wear_flags, I)){
SET_BIT(pObjIndex->wear_flags, OBJWEAR_BACK);
}
if(IS_SET(wear_flags, J)){
SET_BIT(pObjIndex->wear_flags, OBJWEAR_ARMS);
}
if(IS_SET(wear_flags, K)){
SET_BIT(pObjIndex->wear_flags, OBJWEAR_WRIST);
}
if(IS_SET(wear_flags, L)){
SET_BIT(pObjIndex->wear_flags, OBJWEAR_HANDS);
}
if(IS_SET(wear_flags, M)){
SET_BIT(pObjIndex->wear_flags, OBJWEAR_FINGER);
}
if(IS_SET(wear_flags, N)){
SET_BIT(pObjIndex->wear_flags, OBJWEAR_WIELD);
}
if(IS_SET(wear_flags, O)){
SET_BIT(pObjIndex->wear_flags, OBJWEAR_HOLD);
}
if(IS_SET(wear_flags, P)){
SET_BIT(pObjIndex->wear_flags, OBJWEAR_SHIELD);
}
if(IS_SET(wear_flags, Q)){
SET_BIT(pObjIndex->wear_flags, OBJWEAR_WAIST);
}
if(IS_SET(wear_flags, R)){
SET_BIT(pObjIndex->wear_flags, OBJWEAR_LEGS);
}
if(IS_SET(wear_flags, S)){
SET_BIT(pObjIndex->wear_flags, OBJWEAR_ANKLE);
}
if(IS_SET(wear_flags, T)){
SET_BIT(pObjIndex->wear_flags, OBJWEAR_FEET);
}
// extra flags
if(IS_SET(pObjIndex->extra_flags, bb)){
REMOVE_BIT(pObjIndex->extra_flags, bb);
SET_BIT(pObjIndex->extra2_flags, OBJEXTRA2_QUEST);
}
if(IS_SET(pObjIndex->extra_flags, cc)){
REMOVE_BIT(pObjIndex->extra_flags, cc);
SET_BIT(pObjIndex->extra2_flags, OBJEXTRA2_HOLY);
}
if(IS_SET(pObjIndex->extra_flags, dd)){
REMOVE_BIT(pObjIndex->extra_flags, dd);
SET_BIT(pObjIndex->extra2_flags, OBJEXTRA2_REMORT);
}
if(IS_SET(pObjIndex->extra_flags, ee)){
REMOVE_BIT(pObjIndex->extra_flags, ee);
SET_BIT(pObjIndex->extra2_flags, OBJEXTRA2_VAMPIRE_BANE);
}
}
/**************************************************************************/
void areaimport_object_translate_flags_format3( FILE *fp, int version, OBJ_INDEX_DATA *pObjIndex)
{
if(version<4){
// TRANSLATE format3 WEAR FORMAT TO DAWN FORMAT
// format3 defines bits up to T, R,S & T are different
// - wear flags
if(IS_SET(pObjIndex->wear_flags, R)){
REMOVE_BIT(pObjIndex->wear_flags, R);
SET_BIT(pObjIndex->wear_flags, OBJWEAR_EAR);
}
if(IS_SET(pObjIndex->wear_flags, S)){
REMOVE_BIT(pObjIndex->wear_flags, S);
SET_BIT(pObjIndex->wear_flags, OBJWEAR_FACE);
}
if(IS_SET(pObjIndex->wear_flags, T)){
REMOVE_BIT(pObjIndex->wear_flags, T);
SET_BIT(pObjIndex->wear_flags, OBJWEAR_BACK);
}
// remove any other bits we don't know about
REMOVE_BIT(pObjIndex->wear_flags, U | V | W | X | Y | Z | aa | bb | cc | dd | ee);
// extra flags
// format3 defines up to bb less R (aa and bb are different)
REMOVE_BIT(pObjIndex->extra_flags, R | cc | dd | ee);
if(IS_SET(pObjIndex->extra_flags, aa)){
REMOVE_BIT(pObjIndex->extra_flags, aa);
SET_BIT(pObjIndex->extra2_flags, OBJEXTRA2_NOSELL);
}
if(IS_SET(pObjIndex->extra_flags, bb)){
REMOVE_BIT(pObjIndex->extra_flags, cc);
SET_BIT(pObjIndex->extra2_flags, OBJEXTRA2_NOQUEST);
}
}
}
/**************************************************************************/
void areaimport_room_flags_stock( FILE *fp, int version, ROOM_INDEX_DATA *pRoomIndex)
{
if(version<4){ // remove any room flags that dawn didn't use before version 4
REMOVE_BIT(pRoomIndex->room_flags, U|V|X|Y|Z);
}
if(version<11){
// flag was allocated to class restriction, since removed
REMOVE_BIT(pRoomIndex->room_flags, V);
}
}
/**************************************************************************/
void areaimport_room_flags_format2( FILE *fp, int version, ROOM_INDEX_DATA *pRoomIndex)
{
if(IS_SET(pRoomIndex->room_flags, U)){ // BANK
REMOVE_BIT(pRoomIndex->room_flags, U);
SET_BIT(pRoomIndex->room_flags, ROOM_BANK);
}
if(IS_SET(pRoomIndex->room_flags, V)){ // ARENA
REMOVE_BIT(pRoomIndex->room_flags, V);
SET_BIT(pRoomIndex->room_flags, ROOM_ARENA);
}
if(IS_SET(pRoomIndex->room_flags, Y)){ // NO_MAGIC
REMOVE_BIT(pRoomIndex->room_flags, Y);
SET_BIT(pRoomIndex->room_flags, ROOM_ANTIMAGIC);
}
if(IS_SET(pRoomIndex->room_flags, W)){ // NO_SUMMON
REMOVE_BIT(pRoomIndex->room_flags, W);
SET_BIT(pRoomIndex->room_flags, ROOM_NO_SUMMON);
}
if(IS_SET(pRoomIndex->room_flags, X)){ // NO_PORTAL
REMOVE_BIT(pRoomIndex->room_flags, X);
SET_BIT(pRoomIndex->room_flags, ROOM_NO_PORTAL);
}
}
/**************************************************************************/
/*
// RESETS VERSION 1 AND 2 FORMATS
M 0 <mnum> <global mob limit> <rnum> <room mob limit>
O 0 <onum> <global limit> <rnum> 0
P 0 <contents_onum> <global limit> <container_onum> <container_limit>
(v2 the P RESET MUST directly follow the container onum)
G 0 <onum> <global limit> 0 0
E 0 <onum> <global limit> <wear_location> 0
(v1 wear_loc= numeric, v2 wear_loc is a wordflag from wear_location_types)
D 0 <rnum> <direction> <door flags> 0
(v2 D is not valid in a version 2 - currently silently ignored)
R 0 <rnum> <direction> 0 0
S
NOTES:
// mob to room reset
M loads mobile mnum into room rnum, up to the max world_limit
of mobs.
// object related resets
//to room
O puts object onum into room rnum.
//to object
P puts contents_onum into container_onum.
Technically the container_onum, doesn't have to be an object
and can be nested - i.e. objects within other objects, within
other objects - can be an object carried by a mob also?
//to mob inventory
G puts onum into a mob's inventory. This MUST follow the M of
the mob you wish to give the item to!
//to mob equip
E equips mob with onum on wear_location. This MUST follow the
M of the mob you wish to give the item to!
// exit related resets
D sets the door facing "direction" in rnum to door_state
R randomizes rnums exits. Put total number of exits into
total_exits. (This reset is not documented, probably because
all right-thinking people realize this is a major annoyance)
// reset list terminator S
S Denotes the end of the #RESETS section
*/
/**************************************************************************/
extern RESET_DATA *complete_resets_list;
void new_reset( ROOM_INDEX_DATA *pR, RESET_DATA *pReset );
/**************************************************************************/
// attaches all the resets to the rooms
// - Kal, July 01
void attach_resets()
{
logf("Attaching resets to rooms...");
char bad_resets[MSL*4];
char buf[MIL];
bad_resets[0]='\0';
ROOM_INDEX_DATA *pRoom;
MOB_INDEX_DATA *pMob;
OBJ_INDEX_DATA *pObj;
ROOM_INDEX_DATA *pRoomOfLastMob=NULL; // room which the last mob was reset into
ROOM_INDEX_DATA *pRoomOfLastObj=NULL; // room which the last obj was reset into
RESET_DATA *r=complete_resets_list;
RESET_DATA *r_next;
pRoomOfLastMob=NULL;
for ( ; r; r=r_next)
{
r_next=r->next;
// Validate parameters.
// We're calling the index functions for the side effect.
switch ( r->command) // checks moved into fix_resets
{
default:
// should never get here
bugf( "attach_resets(): bad command '%c'.", r->command);
do_abort();
break;
case 'M': // M 0 <mnum> <global mob limit> <rnum> <room mob limit>
{
// check the mob exists
pMob=get_mob_index( r->arg1);
if(!pMob){
sprintf(buf, "attach_resets(): unfound mob %d for reset M 0 %d %d %d %d (removed)",
r->arg1, r->arg1, r->arg2, r->arg3, r->arg4);
bug(buf);
strcat(bad_resets, buf);
strcat(bad_resets, "`1");
pRoomOfLastMob=NULL;
free_reset_data(r);
continue;
}
// check the room exists
pRoom = get_room_index ( r->arg3 );
if(!pRoom){
sprintf(buf, "attach_resets(): unfound room %d for reset M 0 %d %d %d %d (removed)",
r->arg3, r->arg1, r->arg2, r->arg3, r->arg4);
bug(buf);
strcat(bad_resets, buf);
strcat(bad_resets, "`1");
pRoomOfLastMob=NULL;
free_reset_data(r);
continue;
}
// put the M reset into the room
new_reset( pRoom, r );
pRoomOfLastMob=pRoom;
continue;
}
break;
case 'O': // O 0 <onum> <global limit> <rnum>
{
// check the object exists
pObj=get_obj_index( r->arg1);
if(!pObj){
sprintf(buf, "attach_resets(): unfound object %d for reset O 0 %d %d %d (removed)",
r->arg2, r->arg2, r->arg3, r->arg4);
bug(buf);
strcat(bad_resets, buf);
strcat(bad_resets, "`1");
pRoomOfLastObj=NULL;
free_reset_data(r);
continue;
}
// check the room exists
pRoom = get_room_index ( r->arg3 );
if(!pRoom){
sprintf(buf, "attach_resets(): unfound room %d for reset O 0 %d %d %d %d (removed)",
r->arg3, r->arg1, r->arg2, r->arg3, r->arg4);
bug(buf);
strcat(bad_resets, buf);
strcat(bad_resets, "`1");
pRoomOfLastObj=NULL;
free_reset_data(r);
continue;
}
// put the O reset into the room
new_reset( pRoom, r );
pRoomOfLastObj=pRoom;
continue;
}
break; // case O
case 'P': // P 0 <contents_onum> <global limit> <container_onum> <max_in_container>
{ // NOTE: Because the code in load_resets() moves the P resets to appear
// directly after the object they load into, we know that pRoomOfLastObj
// relates to the room which the correct <container_onum> is being loaded into.
if( !pRoomOfLastObj ){
sprintf(buf, "attach_resets(): unfound room resetting container object %d for reset P 0 %d %d %d %d (removed)",
r->arg3, r->arg1, r->arg2, r->arg3, r->arg4);
bug(buf);
strcat(bad_resets, buf);
strcat(bad_resets, "`1");
free_reset_data(r);
continue;
}
new_reset( pRoomOfLastObj, r );
}
break; // case P
case 'G':
case 'E':
{
if(!pRoomOfLastMob){
sprintf(buf, "attach_resets(): unfound room resetting mob for reset %c 0 %d %d %d %d (removed)",
r->command, r->arg1, r->arg2, r->arg3, r->arg4);
bug(buf);
strcat(bad_resets, buf);
strcat(bad_resets, "`1");
free_reset_data(r);
pRoomOfLastObj=NULL;
continue;
}
new_reset( pRoomOfLastMob, r );
pRoomOfLastObj=pRoomOfLastMob;
}
break; // case G and E
case 'D': // D's are converted then removed by load_resets()
{
bugf("attach_resets(): A 'D' reset was encounted!!!... these should be converted/removed by load_resets().");
do_abort();
}
break;
case 'R':
{
ROOM_INDEX_DATA *pRoomIndex;
if ( r->arg2 < 0 || r->arg2 >=MAX_DIR) // Last Door.
{
bugf( "attach_resets: 'R': bad exit %d.", r->arg2 );
exit_error( 1 , "attach_resets", "bad exit");
}
if ( ( pRoomIndex = get_room_index( r->arg1 ) ) ){
new_reset( pRoomIndex, r );
}
}
break;
}
}
logf("All resets have been attached.");
return;
}
/**************************************************************************/
int areaimport_translate_wear_locations_stock( int old_wear_location, int area_version)
{
if(area_version>3){ // dawn versions of the wear locations don't need converting
return old_wear_location;
}
// old, new
int wear_translate_table[][2]={
{ 0, WEAR_LIGHT},
{ 1, WEAR_FINGER_L},
{ 2, WEAR_FINGER_R},
{ 3, WEAR_NECK_1},
{ 4, WEAR_NECK_2},
{ 5, WEAR_TORSO},
{ 6, WEAR_HEAD},
{ 7, WEAR_LEGS},
{ 8, WEAR_FEET},
{ 9, WEAR_HANDS},
{ 10, WEAR_ARMS},
{ 11, WEAR_SHIELD},
{ 12, WEAR_ABOUT},
{ 13, WEAR_WAIST},
{ 14, WEAR_WRIST_L},
{ 15, WEAR_WRIST_R},
{ 16, WEAR_WIELD},
{ 17, WEAR_HOLD},
{ 18, WEAR_FLOAT},
/*
// stock rom only goes this far
{ 19, WEAR_SECONDARY},
{ 20, WEAR_LODGED_ARM},
{ 21, WEAR_LODGED_LEG},
{ 22, WEAR_LODGED_RIB},
{ 23, WEAR_SHEATHED},
{ 24, WEAR_CONCEALED},
{ 25, WEAR_EYES},
{ 26, WEAR_EAR_L},
{ 27, WEAR_EAR_R},
{ 28, WEAR_FACE},
{ 29, WEAR_ANKLE_L},
{ 30, WEAR_ANKLE_R},
{ 31, WEAR_BACK},
*/
{ -1, -1} // -1 terminate the list
};
int new_value;
for(int i=0; wear_translate_table[i][0]!=-1; i++){
if(old_wear_location==wear_translate_table[i][0]){
new_value=wear_translate_table[i][1];
if(new_value==WEAR_NONE){
logf("areaimport_translate_wear_locations_stock(): converting wear location '%d', "
"to WEAR_NONE.", old_wear_location);
}
return new_value;
}
}
logf("areaimport_translate_wear_locations_stock(): unrecognised wear location '%d', "
"converting it to WEAR_NONE.", old_wear_location);
return WEAR_NONE; // translating it to WEAR_NONE
}
/**************************************************************************/
int areaimport_translate_wear_locations_format2( int old_wear_location, int area_version)
{
if(area_version>3){ // dawn versions of the wear locations don't need converting
return old_wear_location;
}
// old, new
int wear_translate_table[][2]={
{ 0, WEAR_LIGHT},
{ 15, WEAR_FINGER_L},
{ 16, WEAR_FINGER_R},
{ 6, WEAR_NECK_1},
{ 7, WEAR_NECK_2},
{ 9, WEAR_TORSO},
{ 2, WEAR_HEAD},
{ 22, WEAR_LEGS},
{ 24, WEAR_FEET},
{ 14, WEAR_HANDS},
// { , WEAR_ARMS},
{ 20, WEAR_SHIELD},
{ 8, WEAR_ABOUT},
{ 21, WEAR_WAIST},
{ 12, WEAR_WRIST_L},
{ 13, WEAR_WRIST_R},
{ 17, WEAR_WIELD},
{ 19, WEAR_HOLD},
{ 1, WEAR_FLOAT},
{ 18, WEAR_SECONDARY},
{ 11, WEAR_LODGED_ARM},
// { , WEAR_LODGED_LEG},
// { , WEAR_LODGED_RIB},
// { , WEAR_SHEATHED},
// { , WEAR_CONCEALED},
// { , WEAR_EYES},
{ 4, WEAR_EAR_L},
{ 5, WEAR_EAR_R},
{ 3, WEAR_FACE},
{ 23, WEAR_ANKLE_L},
{ 23, WEAR_ANKLE_R},
{ 10, WEAR_BACK},
{ -1, -1} // -1 terminate the list
};
int new_value;
for(int i=0; wear_translate_table[i][0]!=-1; i++){
if(old_wear_location==wear_translate_table[i][0]){
new_value=wear_translate_table[i][1];
if(new_value==WEAR_NONE){
logf("areaimport_translate_wear_locations_stock(): converting wear location '%d', "
"to WEAR_NONE.", old_wear_location);
}
return new_value;
}
}
logf("areaimport_translate_wear_locations_stock(): unrecognised wear location '%d', "
"converting it to WEAR_NONE.", old_wear_location);
return WEAR_NONE; // translating it to WEAR_NONE
}
/**************************************************************************/
int areaimport_translate_wear_locations_format3( int old_wear_location, int area_version)
{
if(area_version>3){ // dawn versions of the wear locations don't need converting
return old_wear_location;
}
// old, new
int wear_translate_table[][2]={
{ 0, WEAR_LIGHT},
{ 1, WEAR_FINGER_L},
{ 2, WEAR_FINGER_R},
{ 3, WEAR_NECK_1},
{ 4, WEAR_NECK_2},
{ 5, WEAR_TORSO},
{ 6, WEAR_HEAD},
{ 7, WEAR_LEGS},
{ 8, WEAR_FEET},
{ 9, WEAR_HANDS},
{ 10, WEAR_ARMS},
{ 11, WEAR_SHIELD},
{ 12, WEAR_ABOUT},
{ 13, WEAR_WAIST},
{ 14, WEAR_WRIST_L},
{ 15, WEAR_WRIST_R},
{ 16, WEAR_WIELD},
{ 17, WEAR_HOLD},
{ 18, WEAR_FLOAT},
// additional positions which rom doesn't have in format3
{ 19, WEAR_SECONDARY},
{ 20, WEAR_FACE},
{ 21, WEAR_EAR_L},
{ 22, WEAR_EAR_R},
{ 23, WEAR_BACK},
{ -1, -1} // -1 terminate the list
};
int new_value;
for(int i=0; wear_translate_table[i][0]!=-1; i++){
if(old_wear_location==wear_translate_table[i][0]){
new_value=wear_translate_table[i][1];
if(new_value==WEAR_NONE){
logf("areaimport_translate_wear_locations_stock(): converting wear location '%d', "
"to WEAR_NONE.", old_wear_location);
}
return new_value;
}
}
logf("areaimport_translate_wear_locations_stock(): unrecognised wear location '%d', "
"converting it to WEAR_NONE.", old_wear_location);
return WEAR_NONE; // translating it to WEAR_NONE
}
/**************************************************************************/
// break up the area credits into dawns format
void areaimport_convert_credits(AREA_DATA *pArea)
{
char nbuf[MSL];
char nword[MSL];
char *name;
strcpy(nbuf,pArea->credits);
name=nbuf;
// area must be below version 4 and credits must
// have { and } in them to be considered convertible
if( pArea->version>3
|| count_char(nbuf, '{')<1
|| count_char(nbuf, '}')<1 ){
return;
}
// ignore the leading {'s
while (*name=='{'){
name++;
}
// the first number - lower level
name=one_argument(name,nword);
if(is_number(nword)){
pArea->low_level=atoi(nword);
// the second number - upper level
name=one_argument(name,nword);
// chop off the trailing '}'
if(nword[str_len(nword)-1]=='}'){
nword[str_len(nword)-1]='\0';
}
if(is_number(nword)){ // first number
pArea->high_level=atoi(nword);
// next word becomes the credits
name=one_argument(name,nword);
pArea->credits=str_dup(nword);
}else{
pArea->low_level=-1;
}
}else{ // prob an { all } section
char lcomment[MSL];
lcomment[0]='\0';
// copy all the text up till the }
while(!IS_NULLSTR(nword) && nword[0]!='}'){
strcat(lcomment, " ");
strcat(lcomment, nword);
name=one_argument(name,nword);
}
replace_string(pArea->lcomment, &lcomment[1]);
// next word becomes the credits
name=one_argument(name,nword);
replace_string(pArea->credits, nword);
}
}
/**************************************************************************/
void save_area_roominvitelist( AREA_DATA *pArea )
{
FILE *fp;
ROOM_INDEX_DATA *room;
fclose( fpReserve );
char newfilename[MIL];
sprintf(newfilename, "%s%s.ril.save", BACKUP_AREA_RIL_DIR, pArea->file_name);
// trim out the '.are' bit
{
char *are=strstr(newfilename, ".are.ril.save");
if(are && are[13]==0){
strcpy(are, ".ril.save");
}
}
logf("save_area_roominvitelist(): saving ril to %s...", newfilename);
if ( !( fp = fopen( newfilename, "w" ) ) )
{
bugf("save_area_roominvitelist(): fopen for write '%s' - error %d (%s)",
newfilename, errno, strerror( errno));
exit_error( 1 , "save_area_roominvitelist", "fopen for write error");
}
int count=0;
fprintf( fp, "#DAWNAREA_RoomInviteList\n" );
for( int i = pArea->min_vnum; i <= pArea->max_vnum; i++ ){
room=get_room_index(i);
if(room && !IS_NULLSTR(room->owner) && !IS_NULLSTR(room->invite_list)){
char *txt=ltrim_string(rtrim_string(room->invite_list));
if(!IS_NULLSTR(txt)){
count++;
fprintf(fp, "RIL %d %s~\n", room->vnum, txt); // Room Invite List
}
}
}
fprintf( fp, "#$\n" );
fclose( fp );
fpReserve = fopen( NULL_FILE, "r" );
// rename area/*.are.ril to bak_area/*.are.old.ril,
// then bak_area/*.are.ril.save to area/invitelist/*.are.ril
{
char old_areafilename[MIL];
sprintf(old_areafilename, "%s%s.ril.old", BACKUP_AREA_RIL_DIR, pArea->file_name);
char areafilename[MIL];
sprintf(areafilename, "%s%s.ril", AREA_RIL_DIR, pArea->file_name);
// trim out the '.are' bit
{
char *are=strstr(areafilename, ".are.ril");
if(are && are[8]==0){
strcpy(are, ".ril");
}
}
#ifdef WIN32
unlink(old_areafilename);
#endif
if(file_exists(areafilename)){
if(rename(areafilename,old_areafilename)!=0){
bugf("Error %d occured renaming '%s' to '%s'!.. exiting to avoid area file corruption.",
errno, areafilename, old_areafilename);
exit_error( 1 , "save_area_roominvitelist", "rename error - file exists");
}
}
if(count>0){
if(rename(newfilename, areafilename)!=0){
bugf("Error %d occured renaming '%s' to '%s'!.. exiting to avoid area file corruption.",
errno, newfilename, areafilename);
exit_error( 1 , "save_area_roominvitelist", "rename failed");
}
}else{
logf("No room invite list text for area, removing %s file.", areafilename);
unlink(areafilename);
}
}
logf("save_area_roominvitelist(): save complete.");
}
/**************************************************************************/
// these are used so bug() will report the correct filename and line number.
extern FILE *fpArea;
extern char strArea[MIL];
/**************************************************************************/
void load_area_roominvitelist( AREA_DATA *pArea )
{
ROOM_INDEX_DATA *room;
sprintf(strArea, "%s%s.ril", AREA_RIL_DIR, pArea->file_name);
// trim out the '.are' bit
char *are=strstr(strArea, ".are.ril");
if(are && are[8]==0){
strcpy(are, ".ril");
}
if(!file_exists(strArea)){
return;
}
if ( ( fpArea= fopen( strArea, "r" ) ) == NULL )
{
bugf("load_area_roominvitelist(): fopen for read '%s' - error %d (%s)",
strArea, errno, strerror( errno));
exit_error( 1 , "load_area_roominvitelist", "fopen for read failed");
}
logf(" Reading in RIL %s",strArea);
char *word=fread_word(fpArea);
if(str_cmp(word, "#DAWNAREA_RoomInviteList")){
logf("load_area_roominvitelist(): reading in file %s, "
"unexpected start of file '%s'- ignoring list.", strArea, word);
fclose(fpArea);
fpArea=NULL;
return;
}
word=fread_word(fpArea); // read the 'RIL' keyword or eof marker '#$'
while(str_cmp(word, "#$")){
// the RIL keyword has just been read
if(str_cmp(word, "RIL")){
bugf("load_area_roominvitelist(): reading in file %s, "
"expecting 'RIL' keyword but found '%s' - ignoring rest of file.", strArea, word);
fclose(fpArea);
fpArea=NULL;
return;
}
// read the room vnum
word=fread_word(fpArea);
if(!is_number(word)){
bugf("load_area_roominvitelist(): reading in file %s, "
"expecting room vnum directly after 'RIL' keyword but "
"found '%s' - ignoring rest of file.", strArea, word);
fclose(fpArea);
fpArea=NULL;
return;
}
int roomvnum=atoi(word);
// apply the vnum offet to the room vnum
apply_area_vnum_offset(&roomvnum);
// read the invite list string
word=fread_string(fpArea);
// find the room
room=get_room_index(roomvnum);
if(room){
replace_string(room->invite_list, FORMATF(" %s ",word));
}else{
logf("ignoring room invite list '%s' for room %d - unfound room.", word, roomvnum);
}
free_string(word);
word=fread_word(fpArea); // read the next 'RIL' keyword or eof marker '#$'
}
fclose(fpArea);
fpArea=NULL;
}
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/