/* * return values: * 0 - successful load, keep char in rent room. * 1 - load failure or load of crash items -- put char in temple. * 2 - rented equipment lost (no $) */ int Crash_load(struct char_data * ch) { FILE *fl; char fname[MAX_STRING_LENGTH]; struct obj_file_elem object; struct rent_info rent; int cost, orig_rent_code, num_objs = 0, j; float num_of_days; struct obj_data *obj, *obj2, *cont_row[MAX_BAG_ROWS]; int location; /* Empty all of the container lists (you never know ...) */ for (j = 0; j < MAX_BAG_ROWS; j++) cont_row[j] = NULL; if (!get_filename(GET_NAME(ch), fname, CRASH_FILE)) return 1; if (!(fl = fopen(fname, "r+b"))) { if (errno != ENOENT) { /* if it fails, NOT because of no file */ sprintf(buf1, "SYSERR: READING OBJECT FILE %s (5)", fname); perror(buf1); send_to_char("\r\n********************* NOTICE *********************\r\n" "There was a problem loading your objects from disk.\r\n" "Contact a God for assistance.\r\n", ch); } sprintf(buf, "%s entering game with NO equipment.", GET_NAME(ch)); mudlog(buf, NRM, MAX((int)LVL_IMMORT, (int)GET_INVIS_LEV(ch)), TRUE); return 1; } if (!feof(fl)) fread(&rent, sizeof(struct rent_info), 1, fl); else { plog("SYSERR: Crash_load: %s's rent file was empty!", GET_NAME(ch)); return 1; } if (rent.rentcode == RENT_RENTED || rent.rentcode == RENT_TIMEDOUT) { num_of_days = (float) (time(0) - rent.time) / SECS_PER_REAL_DAY; cost = (int) (rent.net_cost_per_diem * num_of_days); if (cost > GET_GOLD(ch) + GET_BANK_GOLD(ch)) { fclose(fl); sprintf(buf, "%s entering game, rented equipment lost (no $).", GET_NAME(ch)); mudlog(buf, BRF, MAX((int)LVL_IMMORT, (int)GET_INVIS_LEV(ch)), TRUE); Crash_crashsave(ch); return 2; } else { GET_BANK_GOLD(ch) -= MAX((long)cost - GET_GOLD(ch), 0L); GET_GOLD(ch) = MAX((long)GET_GOLD(ch) - cost, 0L); save_char(ch, NOWHERE); } } switch (orig_rent_code = rent.rentcode) { case RENT_RENTED: sprintf(buf, "%s un-renting and entering game.", GET_NAME(ch)); mudlog(buf, NRM, MAX((int)LVL_IMMORT, (int)GET_INVIS_LEV(ch)), TRUE); break; case RENT_CRASH: sprintf(buf, "%s retrieving crash-saved items and entering game.", GET_NAME(ch)); mudlog(buf, NRM, MAX((int)LVL_IMMORT, (int)GET_INVIS_LEV(ch)), TRUE); break; case RENT_CRYO: sprintf(buf, "%s un-cryo'ing and entering game.", GET_NAME(ch)); mudlog(buf, NRM, MAX((int)LVL_IMMORT, (int)GET_INVIS_LEV(ch)), TRUE); break; case RENT_FORCED: case RENT_TIMEDOUT: sprintf(buf, "%s retrieving force-saved items and entering game.", GET_NAME(ch)); mudlog(buf, NRM, MAX((int)LVL_IMMORT, (int)GET_INVIS_LEV(ch)), TRUE); break; default: sprintf(buf, "WARNING: %s entering game with undefined rent code.", GET_NAME(ch)); mudlog(buf, BRF, MAX((int)LVL_IMMORT, (int)GET_INVIS_LEV(ch)), TRUE); break; } while (!feof(fl)) { fread(&object, sizeof(struct obj_file_elem), 1, fl); if (ferror(fl)) { perror("Reading crash file: Crash_load."); fclose(fl); return 1; } if (feof(fl)) break; ++num_objs; if ( (obj = Obj_from_store(object, &location)) == NULL ) continue; auto_equip( ch, obj, location ); /* * What to do with a new loaded item: * * If there's a list with location less than 1 below this, then its * container has disappeared from the file so we put the list back into * the character's inventory. (Equipped items are 0 here.) * * If there's a list of contents with location of 1 below this, then we * check if it is a container: * - Yes: Get it from the character, fill it, and give it back so we * have the correct weight. * - No: The container is missing so we put everything back into the * character's inventory. * * For items with negative location, we check if there is already a list * of contents with the same location. If so, we put it there and if not, * we start a new list. * * Since location for contents is < 0, the list indices are switched to * non-negative. * * This looks ugly, but it works. */ if (location > 0) { /* Equipped */ for (j = MAX_BAG_ROWS - 1; j > 0; j--) { if (cont_row[j]) { /* No container, back to inventory. */ for (; cont_row[j]; cont_row[j] = obj2) { obj2 = cont_row[j]->next_content; obj_to_char(cont_row[j], ch); } cont_row[j] = NULL; } } if (cont_row[0]) { /* Content list existing. */ if (GET_OBJ_TYPE(obj) == ITEM_CONTAINER) { /* Remove object, fill it, equip again. */ obj = unequip_char(ch, location - 1); obj->contains = NULL; /* Should be NULL anyway, but just in case. */ for (; cont_row[0]; cont_row[0] = obj2) { obj2 = cont_row[0]->next_content; obj_to_obj(cont_row[0], obj); } equip_char(ch, obj, location - 1); } else { /* Object isn't container, empty the list. */ for (; cont_row[0]; cont_row[0] = obj2) { obj2 = cont_row[0]->next_content; obj_to_char(cont_row[0], ch); } cont_row[0] = NULL; } } } else { /* location <= 0 */ for (j = MAX_BAG_ROWS - 1; j > -location; j--) { if (cont_row[j]) { /* No container, back to inventory. */ for (; cont_row[j]; cont_row[j] = obj2) { obj2 = cont_row[j]->next_content; obj_to_char(cont_row[j], ch); } cont_row[j] = NULL; } } if (j == -location && cont_row[j]) { /* Content list exists. */ if (GET_OBJ_TYPE(obj) == ITEM_CONTAINER) { /* Take the item, fill it, and give it back. */ obj_from_char(obj); obj->contains = NULL; for (; cont_row[j]; cont_row[j] = obj2) { obj2 = cont_row[j]->next_content; obj_to_obj(cont_row[j], obj); } obj_to_char(obj, ch); /* Add to inventory first. */ } else { /* Object isn't container, empty content list. */ for (; cont_row[j]; cont_row[j] = obj2) { obj2 = cont_row[j]->next_content; obj_to_char(cont_row[j], ch); } cont_row[j] = NULL; } } if (location < 0 && location >= -MAX_BAG_ROWS) { /* * Let the object be part of the content list but put it at the * list's end. Thus having the items in the same order as before * the character rented. */ obj_from_char(obj); if ((obj2 = cont_row[-location - 1]) != NULL) { while (obj2->next_content) obj2 = obj2->next_content; obj2->next_content = obj; } else cont_row[-location - 1] = obj; } } } /* Little hoarding check. -gg 3/1/98 */ sprintf(fname, "%s (level %d) has %d object%s (max %d).", GET_NAME(ch), GET_LEVEL(ch), num_objs, num_objs != 1 ? "s" : "", max_obj_save); mudlog(fname, NRM, MAX(GET_INVIS_LEV(ch), LVL_GOD), TRUE); /* turn this into a crash file by re-writing the control block */ rent.rentcode = RENT_CRASH; rent.time = time(0); rewind(fl); Crash_write_rentcode(ch, fl, &rent); fclose(fl); if ((orig_rent_code == RENT_RENTED) || (orig_rent_code == RENT_CRYO)) return (0); else return (1); }
int handle_obj(struct obj_data *temp, struct char_data *ch, int locate, struct obj_data **cont_row) { int j; struct obj_data *obj1; if (!temp) /* this should never happen, but.... */ return (0); auto_equip(ch, temp, locate); /* what to do with a new loaded item: if there's a list with <locate> less than 1 below this: (equipped items are assumed to have <locate>==0 here) then its container has disappeared from the file *gasp* -> put all the list back to ch's inventory if there's a list of contents with <locate> 1 below this: check if it's a container - if so: get it from ch, fill it, and give it back to ch (this way the container has its correct weight before modifying ch) - if not: the container is missing -> put all the list to ch's inventory for items with negative <locate>: if there's already a list of contents with the same <locate> put obj to it if not, start a new list Confused? Well maybe you can think of some better text to be put here ... since <locate> for contents is < 0 the list indices are switched to non-negative */ if (locate > 0) { /* item equipped */ for (j = MAX_BAG_ROWS-1;j > 0;j--) if (cont_row[j]) { /* no container -> back to ch's inventory */ for (;cont_row[j];cont_row[j] = obj1) { obj1 = cont_row[j]->next_content; obj_to_char(cont_row[j], ch); } cont_row[j] = NULL; } if (cont_row[0]) { /* content list existing */ if (GET_OBJ_TYPE(temp) == ITEM_CONTAINER) { /* rem item ; fill ; equip again */ temp = unequip_char(ch, locate-1); temp->contains = NULL; /* should be empty - but who knows */ for (;cont_row[0];cont_row[0] = obj1) { obj1 = cont_row[0]->next_content; obj_to_obj(cont_row[0], temp); } equip_char(ch, temp, locate-1); } else { /* object isn't container -> empty content list */ for (;cont_row[0];cont_row[0] = obj1) { obj1 = cont_row[0]->next_content; obj_to_char(cont_row[0], ch); } cont_row[0] = NULL; } } } else { /* locate <= 0 */ for (j = MAX_BAG_ROWS-1;j > -locate;j--) if (cont_row[j]) { /* no container -> back to ch's inventory */ for (;cont_row[j];cont_row[j] = obj1) { obj1 = cont_row[j]->next_content; obj_to_char(cont_row[j], ch); } cont_row[j] = NULL; } if (j == -locate && cont_row[j]) { /* content list existing */ if (GET_OBJ_TYPE(temp) == ITEM_CONTAINER) { /* take item ; fill ; give to char again */ obj_from_char(temp); temp->contains = NULL; for (;cont_row[j];cont_row[j] = obj1) { obj1 = cont_row[j]->next_content; obj_to_obj(cont_row[j], temp); } obj_to_char(temp, ch); /* add to inv first ... */ } else { /* object isn't container -> empty content list */ for (;cont_row[j];cont_row[j] = obj1) { obj1 = cont_row[j]->next_content; obj_to_char(cont_row[j], ch); } cont_row[j] = NULL; } } if (locate < 0 && locate >= -MAX_BAG_ROWS) { /* let obj be part of content list but put it at the list's end thus having the items in the same order as before renting */ obj_from_char(temp); if ((obj1 = cont_row[-locate-1])) { while (obj1->next_content) obj1 = obj1->next_content; obj1->next_content = temp; } else cont_row[-locate-1] = temp; } } /* locate less than zero */ return (1); }