Snippet by Edward Felch (yay another one) dustlos@hotmail.com 7-2-2001 Disclaimer: Use of this snippet on your part requires me to do nothing (unless you ask nicely) and since I have no responsibility whatsoever for what you do, I am entitled to laugh at your problems (if you don't ask nicely). Purpose: allows the saving of items given/sold to shopkeepers who normally do not load or "produce" the items. Example: a shopkeeper only loads and sells a long sword (vnum 400), but a player sells him two clubs. If for some reason the MUD crashs, or someone purges the shopkeeper then resets him, the keeper will still have the two clubs in his inventory. Platform/Etc: Worked on FreeBSD 4.2, used CircleMUD bpl17, ASCII pfiles, Oasis, etc. Shouldn't matter since it hardly uses anything. Warning: I expect you to be able to figure out if you need to prototype a function or variable (like top_shop for example), or figure out that you might need to include a file for things to work. Signs that some is wrong includes: compiler whining about functions or variables it can't find within a file. Code follows: # In shell or whatever, go inside lib/ and make the directory called # shop_item, should be like this: circle/lib/shop_item # Open up shop.c: # Find this part: sprintf(buf, shop_index[shop_nr].message_buy, GET_NAME(ch), goldamt); do_tell(keeper, buf, cmd_tell, 0); sprintf(buf, "You now have %s.\r\n", tempstr); send_to_char(buf, ch); # Add this below: save_shop_nonnative(shop_nr, keeper); save_char(ch, NOWHERE); # Find this part: sprintf(buf, shop_index[shop_nr].message_sell, GET_NAME(ch), goldamt); do_tell(keeper, buf, cmd_tell, 0); sprintf(buf, "The shopkeeper now has %s.\r\n", item_name); send_to_char(buf, ch); # Add this below: save_shop_nonnative(shop_nr, keeper); save_char(ch, NOWHERE); # At the top of shop.c, before other functions begin, add these two: /* Function to take a shop and mob and save any non-unique items to it * It saves any object vnums which aren't native producing, good for crashs */ void save_shop_nonnative(shop_vnum shop_num, struct char_data *keeper) { FILE *cfile = NULL; struct obj_data *obj, *next_obj; sprintf(buf, "shop_item/%ld", shop_num); if ((cfile = fopen(buf, "w")) == NULL) { /* Create the File Then */ sprintf(buf2, "shop_item/%ld", shop_num); if (!(cfile = fopen(buf2, "w"))) { mudlog("SYSERR: SHP: Can't write new shop_item file.", BRF, LVL_IMPL, TRUE); exit(0); } } /* Loops through the keeper's item list, checks if its native or not * if it isnt, it writes the item's VNUM to the file */ *buf = '\0'; *buf2 = '\0'; sprintf(buf2, "#%ld\n" "%s\n", shop_num, GET_NAME(keeper)); for (obj = keeper->carrying; obj; obj = next_obj) { next_obj = obj->next_content; if (!shop_producing(obj, shop_num)) sprintf(buf2+strlen(buf2), "%ld\n", GET_OBJ_VNUM(obj)); if (!next_obj) break; } fprintf(cfile, buf2); fprintf(cfile, "$\n"); fclose(cfile); return; } void load_shop_nonnative(shop_vnum shop_num, struct char_data *keeper) { FILE *cfile = NULL; struct obj_data *obj; int line_num = 0, placer = 0; obj_vnum v_this; sprintf(buf, "shop_item/%ld", shop_num); /* Check to see if we have a file for this shop number */ if ((cfile = fopen(buf, "r")) == NULL) return; // Shop number line_num += get_line(cfile, buf); if (sscanf(buf, "#%d", &placer) != 1) { fprintf(stderr, "Format error in shop_item %ld, line %d.\n", shop_num, line_num); exit(0); } // Name of shopkeeper line_num += get_line(cfile, buf); // Item list while (buf && *buf != '$') { line_num += get_line(cfile, buf); if (!buf || !*buf || *buf == '$') break; if (sscanf(buf, "%d", &placer) != 1) { fprintf(stderr, "Format error in shop_item %ld, line %d.\n", shop_num, line_num); exit(0); } v_this = placer; obj = read_object(v_this, VIRTUAL); slide_obj(obj, keeper, shop_num); } return; } # Open up db.c: # In function reset_zone add in these variables: shop_vnum shop_nr; # Find something like this part: mob = read_mobile(ZCMD.arg1, REAL); char_to_room(mob, ZCMD.arg3); load_mtrigger(mob); tmob = mob; last_cmd = 1; mob_load = TRUE; # Add this below: /* Parts for loading non-native items in shops, if mob * load was true, see if this mob is a shopkeeper, if it * is then we should try the load function */ for (shop_nr = 0; shop_nr <= top_shop; shop_nr++) { if (SHOP_KEEPER(shop_nr) == mob->nr) break; } if (shop_nr < top_shop) load_shop_nonnative(shop_nr, mob); # Contact me for any help.