/**************************************************************************/ // 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; } /**************************************************************************/ /**************************************************************************/ /**************************************************************************/