This code is designed for godwars-style muds where there is no renting system. If this does not sound like the MUD you'd like, DO NOT install this snippet. If you are updating a mud where you do not want to lose the existing object files, I suggest patching the saving part of the code in, then save everyone, then continue with the snippet. Perhaps later I'll support renting. Under the lib directory, create a new directory called "ofiles". open comm.c and change Crash_save_all() to ascii_save_all() and add this in limits.c: void ascii_save_all(void) { struct char_data *i, *next_char; for (i = character_list; i; i = next_char) { next_char = i->next; save_char(i, NOWHERE); } } add these in act.other.c (i put em just above do_save): (remember, if you get an error, 'obj_index': undeclared identifier that you must define obj_index as an extern at the top. (extern struct index_data *obj_index;) void write_ascii_obj(struct obj_data *obj, int locate, FILE *wofile) { struct obj_data *j, *next_thing; int i; if (obj->action_description) { strcpy(buf1, obj->action_description); strip_string(buf1); } else *buf1 = 0; fprintf(wofile, "#%d %d\n" "%s~\n" "%s~\n" "%s~\n" "%s~\n" "%d %d %d %d %d\n" "%d %d %d %d\n" "%d %d %d\n", GET_OBJ_VNUM(obj), locate, obj->name ? obj->name : "undefined", obj->short_description ? obj->short_description : "undefined", obj->description ? obj->description : "undefined", buf1, GET_OBJ_TYPE(obj), GET_OBJ_EXTRA(obj), GET_OBJ_WEAR(obj), GET_OBJ_TIMER(obj), obj->obj_flags.bitvector, GET_OBJ_VAL(obj, 0), GET_OBJ_VAL(obj, 1), GET_OBJ_VAL(obj, 2), GET_OBJ_VAL(obj, 3), GET_OBJ_WEIGHT(obj), GET_OBJ_COST(obj), GET_OBJ_RENT(obj) ); /* Do we have affects? */ for (i = 0; i < MAX_OBJ_AFFECT; i++) if (obj->affected[i].modifier) fprintf(wofile, "A\n" "%d %d\n", obj->affected[i].location,obj->affected[i].modifier); if (obj->contains) { if (locate>0) locate=0; for (j = obj->contains; j; j = next_thing) { next_thing = j->next_content; if (!IS_OBJ_STAT((j), ITEM_NORENT)) write_ascii_obj(j, locate-1, wofile); } } } void ascii_obj_save(struct char_data *ch) { int j; struct obj_data *obj; char filename[64]; FILE *wofile; sprintf(filename, "ofiles/%s.ofile", GET_NAME(ch)); if (!(wofile = fopen(filename, "w"))) { sprintf(buf, "Error saving %s's obj file", GET_NAME(ch)); mudlog(buf, NRM, LVL_GOD, TRUE); return; } for (j = 0; j < NUM_WEARS; j++) { if (GET_EQ(ch,j) && (!IS_OBJ_STAT(GET_EQ(ch, j), ITEM_NORENT))) write_ascii_obj(GET_EQ(ch,j), j+1, wofile); } for (obj = ch->carrying; obj; obj = obj->next_content) { if (!IS_OBJ_STAT((obj), ITEM_NORENT)) write_ascii_obj(obj, 0, wofile); } /* write final line, close */ fprintf(wofile, "$~\n"); fclose(wofile); } open handler.c and look for extract_char change these two: /* transfer objects to room, if any */ while (ch->carrying) { obj = ch->carrying; obj_from_char(obj); obj_to_room(obj, ch->in_room); } /* transfer equipment to room, if any */ for (i = 0; i < NUM_WEARS; i++) if (GET_EQ(ch, i)) obj_to_room(unequip_char(ch, i), ch->in_room); to this: /* transfer objects to room, if any */ while (ch->carrying) { obj = ch->carrying; obj_from_char(obj); extract_obj(obj); } /* transfer equipment to room, if any */ for (i = 0; i < NUM_WEARS; i++) if (GET_EQ(ch, i)) { obj = GET_EQ(ch, i); unequip_char(ch, i); extract_obj(obj); } and slightly lower.. if (!IS_NPC(ch)) { save_char(ch, NOWHERE); } else { if (GET_MOB_RNUM(ch) > -1) /* if mobile */ mob_index[GET_MOB_RNUM(ch)].number--; clearMemory(ch); /* Only NPC's can have memory */ free_char(ch); freed = 1; } to if (IS_NPC(ch)) { if (GET_MOB_RNUM(ch) > -1) /* if mobile */ mob_index[GET_MOB_RNUM(ch)].number--; clearMemory(ch); /* Only NPC's can have memory */ free_char(ch); freed = 1; } open db.c and add these functions (i put then after char_to_store): char *read_ascii_cont(struct obj_data *mobj, FILE *rofile, int vnum, int loc) { char line[256]; struct obj_data *obj; int rnum, i, t[10]; beginning: rnum = real_object(vnum); obj = read_object(rnum, REAL); obj->name = str_dup(fread_string(rofile, buf)); obj->short_description = str_dup(fread_string(rofile, buf)); obj->description = str_dup(fread_string(rofile, buf)); if ((obj->action_description = fread_string(rofile, buf)) == NULL) obj->action_description=0; get_line(rofile,line); sscanf(line,"%d %d %d %d %d\n",t,t+1,t+2,t+3,t+4); GET_OBJ_TYPE(obj) = t[0]; GET_OBJ_EXTRA(obj) = t[1]; GET_OBJ_WEAR(obj) = t[2]; GET_OBJ_TIMER(obj) = t[3]; obj->obj_flags.bitvector = t[4]; get_line(rofile,line); sscanf(line,"%d %d %d %d\n",t,t+1,t+2,t+3); GET_OBJ_VAL(obj, 0) = t[0]; GET_OBJ_VAL(obj, 1) = t[1]; GET_OBJ_VAL(obj, 2) = t[2]; GET_OBJ_VAL(obj, 3) = t[3]; get_line(rofile,line); sscanf(line,"%d %d %d\n",t,t+1,t+2); GET_OBJ_WEIGHT(obj) = t[0]; GET_OBJ_COST(obj) = t[1]; GET_OBJ_RENT(obj) = t[2]; t[0] = '\0'; for (i = 0; i < MAX_OBJ_AFFECT; i++) { if (!get_line(rofile,line)) { t[0] = '\0'; break; } if (sscanf(line,"A\n")) { get_line(rofile,line); sscanf(line,"%d %d\n", t, t+1); obj->affected[i].location = t[0]; obj->affected[i].modifier = t[1]; } else if (sscanf(line,"#%d %d\n",t,t+1)) break; } obj_to_obj(obj, mobj); ascobjlc: if (t[0] == '\0') { if (!get_line(rofile,line)) strcpy(buf, "EMPTY!"); return buf; } else if (!(sscanf(line,"#%d %d\n",t,t+1))) { t[0] = '\0'; goto ascobjlc; } else if (t[1] > loc) { strcpy(buf, line); return buf; } else if (t[1] == loc) goto beginning; else if (t[1] < loc) { strcpy(line, read_ascii_cont(obj, rofile, t[0], t[1])); if (sscanf(line, "EMPTY!\n")) { strcpy(buf, line); return buf; } else { t[0] = 1; goto ascobjlc; } } } void read_ascii_obj(struct char_data *ch, FILE *rofile, int vnum, int loc) { char line[256]; struct obj_data *obj; int rnum, i, t[10]; rnum = real_object(vnum); obj = read_object(rnum, REAL); obj->name = str_dup(fread_string(rofile, buf)); obj->short_description = str_dup(fread_string(rofile, buf)); obj->description = str_dup(fread_string(rofile, buf)); if ((obj->action_description = fread_string(rofile, buf)) == NULL) { obj->action_description=0; } get_line(rofile,line); sscanf(line,"%d %d %d %d %d\n",t,t+1,t+2,t+3,t+4); GET_OBJ_TYPE(obj) = t[0]; GET_OBJ_EXTRA(obj) = t[1]; GET_OBJ_WEAR(obj) = t[2]; GET_OBJ_TIMER(obj) = t[3]; obj->obj_flags.bitvector = t[4]; get_line(rofile,line); sscanf(line,"%d %d %d %d\n",t,t+1,t+2,t+3); GET_OBJ_VAL(obj, 0) = t[0]; GET_OBJ_VAL(obj, 1) = t[1]; GET_OBJ_VAL(obj, 2) = t[2]; GET_OBJ_VAL(obj, 3) = t[3]; get_line(rofile,line); sscanf(line,"%d %d %d %d\n",t,t+1,t+2); GET_OBJ_WEIGHT(obj) = t[0]; GET_OBJ_COST(obj) = t[1]; GET_OBJ_RENT(obj) = t[2]; t[0] = '\0'; for (i = 0; i < MAX_OBJ_AFFECT; i++) { if (!get_line(rofile,line)) { t[0] = '\0'; break; } if (sscanf(line,"A\n")) { get_line(rofile,line); sscanf(line,"%d %d\n", t, t+1); obj->affected[i].location = t[0]; obj->affected[i].modifier = t[1]; } else if (sscanf(line,"#%d %d\n",t,t+1)) break; } if (loc > 0) equip_char(ch, obj, loc-1); else if (loc == 0) obj_to_char(obj, ch); ascobjl: if (t[0] == '\0') { if (!get_line(rofile,line)) return; } else if (sscanf(line, "EMPTY!\n")) return; else if (!(sscanf(line,"#%d %d\n",t,t+1))) { t[0] = '\0'; goto ascobjl; } else if (t[1] >=0) read_ascii_obj(ch, rofile, t[0], t[1]); else if (t[1] < 0) { strcpy(line, read_ascii_cont(obj, rofile, t[0], t[1])); if (sscanf(line, "EMPTY!\n")) return; else { t[0] = 1; goto ascobjl; } } } void load_plr_objects(struct char_data *ch) { int vnum, loc, t[10]; char line[256]; char filename[64]; FILE *rofile; sprintf(filename, "ofiles/%s.ofile", GET_NAME(ch)); if (!(rofile = fopen(filename, "r"))) { sprintf(buf, "Error opening %s's obj file", GET_NAME(ch)); mudlog(buf, NRM, LVL_GOD, TRUE); return; } if (!get_line(rofile,line)) { fclose(rofile); return; } if (!(sscanf(line,"#%d %d\n",t,t+1))) { sprintf(buf, "Error reading %s's obj file", GET_NAME(ch)); mudlog(buf, NRM, LVL_GOD, TRUE); fclose(rofile); return; } vnum = t[0]; loc = t[1]; if (loc < 0) loc=0; read_ascii_obj(ch, rofile, vnum, loc); fclose(rofile); } and add ascii_obj_save(ch); to the very end of char_to_store, before the last bracket. open interpreter.c and find the line if ((load_result = Crash_load(d->character))) and replace it with load_plr_objects(d->character); and then delete these lines: if (load_result == 2) { /* rented items lost */ send_to_char("\r\n\007You could not afford your rent!\r\n" "Your possesions have been donated to the Salvation Army!\r\n", d->character); } and below, replace Crash_delete_file(GET_NAME(d->character)); with sprintf(buf, "ofiles/%s.ofile", GET_NAME(d->character)); if (ofile = fopen(buf, "w")) { fprintf(ofile, "Character has self-deleted\n"); fclose(ofile); } /* remember to define ofile at the beginning of nanny... FILE *ofile; */ delete objsave.c and open makefile under OBJFILES = , delete objsave.o (or objsave.obj in the case of windows) and delete: objsave.obj: objsave.c conf.h sysdep.h structs.h comm.h handler.h db.h \ interpreter.h utils.h spells.h $(CC) -c $(CFLAGS) objsave.c open spec_assign and delete and lines with receptionist or cryogenist in em. remove update_obj_file references along with obj_from_store, obj_to_store, crash_delete, crash_load, crash_rentsave, crash_listrent, update_obj_file, crash_crashsave, crash_idlesave, and crash_delete_crashfile. be absolutely sure to delete any brackets pertaining to the functions as well. To make things easier, here's a listing of the file locations: (please be careful deleting these.. if you don't delete the cases too, you'll get compile errors. Use your head for these!) crash_rentsave-> act.other.c, limits.c (4 occurances.. and watch the if cases!) crash_listrent-> act.wisard.c, handler.c (2 occ) update_obj_file-> db.c (2 occ) crash_delete_crashfile-> handler.c, handler.h (2 occ) obj_from_store-> house.c (3 occ) obj_to_store-> house.c (2 occ) crash_idlesave-> handler.h, limits.c (2 occ) crash_crashsave-> handler.h, limits.c (2 occ) If you get a compile error that says, 'unresolved external symbol _strip_string', then copy this into db.c: void strip_string(char *buffer) { register char *ptr, *str; ptr = buffer; str = ptr; while((*str = *ptr)) { str++; ptr++; if (*ptr == '\r') ptr++; } }