/************************************************************** * Locker Code * * * * /|\ Life always travels forward. * * /-|-\ Always look ahead, never back. * * /--|--\ To do so is to loose sight of the future, * * /---|---\ while travelling on the highways of life. * * Code by Aidan 5/4/2006 * * * * This code has been written as freeware * * and may be used without any limitations * * of any sort whatsoever. Contact me at * * immortal@chaos-ascending.com if you * * need help or have questions. --Aidan * * * **************************************************************/ /* * Just an addendum for use in a helpfile if you wish. * * The Locker system has been designed and setup to * save items that have not been setup on a reset * in rooms that have been flagged as a "locker" room. * Just a side note on this. To minimize the amount of * objects being saved over reboots in every locker room * the max objects has been limited to 20. * * This can be adjusted by changing MAX_ITEM_SAVE which * is defined below. * * Player corpses will be saved throughout the world, * no matter where they are or how many items are in * the room. This is helpful if you are in development * and suffer a crash, etc. * I suggest putting a call to save_lockers( ) in the * raw_kill function located in fight.c for Merc/Rom * derivitives. * * An important thing to remember. A call to save_lockers( ) * should be included in copyover, reboot, shutdown, etc, to * insure proper saving of locker things on normal game resets. * * You have to call load_lockers in int boot_db located in db.c * so that these items are re-loaded when you start the game up. * This should optimally be done near the end when the function * is starting to finish up the last minute boot up items and * before copyover_recover. The reason for this is we can't sit * and load a lot of items that don't exist yet into rooms that * don't exist yet. */ #include "merc.h" #define MAX_NEST 100 #define MAX_ITEM_SAVE 20 #define LOCKER_FILE "../area/lockers.txt" void do_save_lockers(CHAR_DATA *ch, char *argument) { save_lockers(); send_to_char("Lockers have been saved.\n\r",ch); return; } void save_lockers( ) { FILE *LockerFile; ROOM_INDEX_DATA *room; RESET_DATA *reset; /* Close the reserve file */ fclose(fpReserve); /* Open the Locker File for saving */ LockerFile = fopen(LOCKER_FILE,"w"); /* Okay, lets loop through all of the rooms on the game */ for(vnum = 0; vnum < 32768; vnum++) { if((room = get_room_index(vnum)) != NULL) { OBJ_DATA *obj = NULL; int count = 0; for(obj = room->contents; obj; obj = obj->next_content) { bool hasReset = FALSE; /* Are we being carried? Are we in a valid room? */ if(obj->carried_by) continue; /* Is this a Locker Room? Is it a player corpse? */ if(!IS_SET(room->room_flags, ROOM_LOCKER) && obj->item_type != ITME_CORPSE_PC) continue; /* Okay, so now let's see if the item is on a reset */ for(reset = room->reset_first; reset; reset = reset->next) { if(((reset->command == 'O' || reset->command == 'P') && reset->vnum == obj->pIndexData->vnum) || (reset->command == 'E' && reset->vnum == obj->pIndexData->vnum)) { hasReset = TRUE; break; } } /* No saving items on reset */ if(hasReset) continue; /* No saving items above MAX_ITEM_SAVE */ if(++count > MAX_ITEM_SAVE && obj->item_type != ITEM_CORPSE_PC) continue; /* Write the obj to file */ fwrite_locker(obj,LockerFile,0); } } } /* Print the end statement */ fprintf(LockerFile,"#END\n"); /* Close the LockerFile */ fclose(LockerFile); /* Re-Open the reserve file */ fpReserve = fopen(NULL_FILE,"r"); return; } /* * fwrite_locker is used to write the locker * data out to file. This file is called on * boot to replace stored items. */ void fwrite_locker(OBJ_DATA *obj, FILE *fp, int iNest) { EXTRA_DESCR_DATA *ed; AFFECT_DATA *af; if(obj->next_content && iNet > 0) fwrite_locker(obj->next_content,fp,iNest); fprintf(fp,"#O\n"); // Object ID fprintf(fp,"Vnum %d\n", obj->pIndexData->vnum); // Object Vnum if(obj->enchanged) // Enchanted? fprintf(fp,"Enchanged\n"); fprintf(fp,"Nest %d\n",iNest); // Nest if(obj->name != obj->pIndexData->name) // Name fprintf(fp,"Name %s~\n",obj->name); if(obj->short_descr != obj->pIndexData->short_descr) // Short Desc fprintf(fp,"ShD %s~\n",obj->short_descr); if(obj->description != obj->pIndexData->description) // Long Desc fprintf(fp,"Desc %s~\n",obj->description); fprintf(fp,"Wear %lld\n",obj->wear_loc); // Wear Locations fprintf(fp,"Lev %d\n",obj->level); // Level if(obj->timer != 0) fprintf(fp,"Time %d\n",obj->timer); // Timer if(obj->in_room) fprintf(fp,"InRm %d\n",obj->in_room->vnum); // room vnum if(obj->value[0] != obj->pIndexData->value[0] // V Slots || obj->value[1] != obj->pIndexData->value[1] || obj->value[2] != obj->pIndexData->value[2] || obj->value[3] != obj->pIndexData->value[3] || obj->value[4] != obj->pIndexData->value[4] ) fprintf(fp,"Val %d %d %d %d %d\n", obj->value[0], obj->value[1], obj->value[2], obj->value[3], obj->value[4]); for(af = obj->affected; af; af = af->next) // Affects { if(!skill_table[af->type].name) continue; fprintf(fp,"AffD '%s' %d %d %d %d %d\n", skill_table[af->type].name, af->level, af->duration, af->modifier, af->location, af->bitvector); } for(ed = obj->extra_descr; ed; ed = ed->next) // Extended Descs fprintf(fp,"ExDe %s~ %s~\n",ed->keyword, ed->description); fprintf(fp,"End\n\n"); if(obj->contains) fwrite_locker(obj->contains,fp,iNest+1); return; } void load_lockers( ) { FILE *LockerFile; fclose(fpReserve); if((LockerFile = fopen(LOCKER_FILE,"r")) == NULL) { log_string("No locker file found."); fclose(LockerFile); fpReserve = fopen(NULL_FILE,"r"); return; } for( ; ; ) { char *letter; char letter = fread_letter(LockerFile); if(letter != '#') { bug("Load_Lockers: # not found.",0); break; } word = fread_word(LockerFile); if(!str_cmp(word,"O")) fread_locker_obj(LockerFile); else if(!str_cmp(word,"END")) break; else { bug("Load_Lockers: bad section.",0); break; } } fclose(LockerFile); fpReserve = fopen(NULL_FILE,"r"); return; } void fread_locker_obj(FILE *fp); { OBJ_DATA *obj = NULL; char *word = NULL; int iNest = 0; bool fMatch = FALSE; bool fNest = FALSE; bool fVnum = FALSE; bool first = TRUE; bool new_format = FALSE; bool make_new = FALSE; word = feof(fp) ? (char *)"End" : fread_word(fp); if(!str_cmp(word,"Vnum")) { int vnum = fread_number(fp); first = FALSE; if(get_obj_index(vnum) == NULL) bug("Fread_obj: bad vnum %d.",vnum); else { obj = create_object(get_obj_index(vnum),-1); new_format = TRUE; } } if(!obj) { obj = new_obj( ); obj->name = str_dup(""); obj->short_descr = str_dup(""); obj->description = str_dup(""); } fVnum = TRUE; for( ; ; ) { fMatch = FALSE; if(first) first = FALSE; else word = feof(fp) ? (char *)"End" : fread_word(fp); switch(UPPER(word[0])) { case 'A': if(!str_cmp(word,"AffD")) { AFFECT_DATA *af; char *skill; int sn; af = new_affect( ); skill = fread_word(fp); sn = skill_lookup(skill); if(sn < 0) bug("Fread_obj: unknown skill.",0); else { paf->type = sn; paf->level = fread_number(fp); paf->duration = fread_number(fp); paf->modifier = fread_number(fp); paf->location = fread_number(fp); paf->bitvector = fread_number(fp); paf->next = obj->affected; obj->affected = af; fMatch = TRUE; break; } } break; case 'E': if(!str_cmp(word,"Enchanged")) { obj->enchanted = TRUE; fMatch = TRUE; break; } if(!str_cmp(word,"ExDe")) { EXTRA_DESCR_DATA *ed; ed = new_extra_descr( ); ed->keyword = fread_string(fp); ed->description = fread_string(fp); ed->next = obj->extra_descr; obj->extra_descr = ed; fMatch = TRUE; break; } if(!str_cmp(word,"End")) { if(!fNest || !fVnum || !obj->pIndexData) { bug("Fread_obj: incomplete object.",0); free_obj(obj); return; } else { if(!new_format) { obj->next = object_list; object_list = obj; obj->pIndexData->count++; } if(make_new) { int wear = obj->wear_loc; extract_obj(obj); obj = create_object(obj->pIndexData,0); obj->wear_loc = wear; } if(iNest == 0 || rgObjNest[iNest] == NULL) obj_to_room(obj,obj->in_room); else obj_to_obj(obj,rgObjNest[iNest-1]); return; } } break; case 'D': KEY("Desc", obj->description, fread_string(fp)); break; case 'I': KEY("InRm", obj->in_room, fread_number(fp)); break; case 'L': KEY("Lev", obj->level, fread_number(fp)); break; case 'N': KEY("Name", obj->name, fread_string(fp); if(!str_cmp(word,"Nest")) { iNest = fread_number(fp); if(iNest < 0 || iNest >= MAX_NEST) bug("Fread_obj: bad nest %d.",iNest); else { rgObjiNest[iNest] = obj; fNest = TRUE; } fMatch = TRUE; break; } break; case 'S': KEY("ShD", obj->short_descr, fread_string(fp); break; case 'T': KEY("Time", obj->timer, fread_number(fp)); break; case 'V': if(!str_cmp(word,"Val")) { int i; for(i = 0; i < 5; i++) obj->value[i] = fread_number(fp); fMatch = TRUE; break; } break; if(!str_cmp(word,"Vnum")) { int vnum = fread_number(fp); if((obj->pIndexData = get_obj_index(vnum)) == NULL) bug("Fread_obj: bad vnum %d.",vnum); else fVnum = TRUE; fMatch = TRUE; break; } break; case 'W': KEY("Wear", obj->wear_loc, fread_number(fp)); break; } if(!fMatch) { bug("Fread_obj: no match.",0); fread_to_eol(fp); } } return; }