Wear Template Code by Justice (Kwon J. Ekstrom) Updated: June 14, 2006 In mud.h: Add: (command declaration) DECLARE_DO_FUN( do_wtemplate ); // Wear Template Snippet Add: (preferably before struct area_data) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Wear Template Snippet * Allow a mob to be easily equipped. * -- Justice (05-29-2003) * Cleaned up and updated for SmaugFUSS * -- Justice (06-14-2006) */ // Typedefs typedef struct wear_template_data WEAR_TEMPLATE_DATA; typedef struct wear_template_item WEAR_TEMPLATE_ITEM; // Global list extern WEAR_TEMPLATE_DATA *first_wear_template; // global list extern WEAR_TEMPLATE_DATA *last_wear_template; // global list // Maximum container nest #define MAX_WEAR_TEMPLATE_NEST 10 // Template filename #define WEAR_TEMPLATE_FILE SYSTEM_DIR "template.dat" // Template data struct wear_template_data { WEAR_TEMPLATE_DATA *next; WEAR_TEMPLATE_DATA *prev; WEAR_TEMPLATE_ITEM *data; char *name; }; // Single template record struct wear_template_item { WEAR_TEMPLATE_ITEM *next; WEAR_TEMPLATE_ITEM *prev; WEAR_TEMPLATE_ITEM *first_child; WEAR_TEMPLATE_ITEM *last_child; OBJ_INDEX_DATA *obj; int wear_loc; int nest; }; In db.c: Add: (near top) // Wear Template Snippet // Function Prototypes void load_wear_template(); In db.c: After: /* * Initialize area weather data */ load_weatherdata( ); init_area_weather( ); Add: // Wear Template Snippet // Load wear templates log_string("Loading wear templates."); load_wear_template(); In act_wiz.c: Add: (near top) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Wear Template Snippet * Declarations */ // Command function prototypes void do_wear_template_create(CHAR_DATA *ch, char *argument); void do_wear_template_apply(CHAR_DATA *ch, char *argument); // Util function prototypes void create_wear_template(char *name, CHAR_DATA *ch); void create_wear_template2(WEAR_TEMPLATE_ITEM *root, OBJ_DATA *first, OBJ_DATA *last, int level); void list_wear_template(CHAR_DATA *ch, WEAR_TEMPLATE_DATA *templ); int list_wear_template2(CHAR_DATA *ch, WEAR_TEMPLATE_ITEM *first, WEAR_TEMPLATE_ITEM *last, bool header, int level); void apply_wear_template(CHAR_DATA *ch, OBJ_DATA *con, WEAR_TEMPLATE_ITEM *root, int obj_level); // Load/Write function prototypes void save_wear_template(); void load_wear_template(); void fwrite_wear_template(FILE *fp, WEAR_TEMPLATE_ITEM *root, int level); void fread_wear_template(FILE *fp); void fread_wear_template2(FILE *fp, WEAR_TEMPLATE_ITEM *root); // List declarations WEAR_TEMPLATE_DATA *first_wear_template; WEAR_TEMPLATE_DATA *last_wear_template; In act_wiz.c: Add: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Wear Template Snippet * Implementation */ void do_wtemplate(CHAR_DATA *ch, char *argument) { char arg[MAX_INPUT_LENGTH]; // No argument.... if (argument[0] == '\0') { send_to_char("Syntax: wtemplate create <name> <victim>\n\r", ch); send_to_char("Syntax: wtemplate list\n\r", ch); send_to_char("Syntax: wtemplate stat <name>\n\r", ch); send_to_char("Syntax: wtemplate apply <name> <victim>\n\r", ch); send_to_char("Syntax: wtemplate save\n\r", ch); return; } // Get the first argument. argument = one_argument(argument, arg); // Create a new template. if (!str_cmp(arg, "create")) { do_wear_template_create(ch, argument); return; } if (!str_cmp(arg, "save")) { save_wear_template(); send_to_char("Saved.\n\r", ch); return; } if (!str_cmp(arg, "load")) { first_wear_template = NULL; last_wear_template = NULL; load_wear_template(); send_to_char("Loaded... this load doesn't cleanup old wear templates!", ch); send_to_char("Please only use for testing purposes.", ch); return; } // List existing templates. if (!str_cmp(arg, "list")) { WEAR_TEMPLATE_DATA *templ; int cnt = 0; if (!first_wear_template) { send_to_char("There aren't any wear templates.\n\r", ch); return; } send_to_char("| # | Name\n\r", ch); send_to_char("|-----+--------------------\n\r", ch); for (templ = first_wear_template; templ; templ = templ->next) ch_printf(ch, "| %-3d | %s\n\r", ++cnt, templ->name); send_to_char("|-----+--------------------\n\r", ch); ch_printf(ch, "There %s %d wear template%s.\n\r", (cnt == 1 ? "is" : "are"), cnt, (cnt == 1 ? "" : "s")); return; } if (!str_cmp(arg, "stat")) { WEAR_TEMPLATE_DATA *templ; for (templ = first_wear_template; templ; templ = templ->next) if (!str_cmp(templ->name, argument)) break; if (!templ) { ch_printf(ch, "There isn't a wear template named '%s'\n\r", argument); return; } list_wear_template(ch, templ); return; } if (!str_cmp(arg, "apply")) { do_wear_template_apply(ch, argument); return; } // Default action do_wtemplate(ch, ""); return; } void do_wear_template_create(CHAR_DATA *ch, char *argument) { WEAR_TEMPLATE_DATA *templ; CHAR_DATA *vict; char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; set_char_color(AT_IMMORT, ch); if (argument[0] == '\0') { do_wtemplate(ch, ""); return; } argument = one_argument(argument, arg1); argument = one_argument(argument, arg2); if ( arg1[0] == '\0') { do_wtemplate(ch, ""); send_to_char("What should the wear template be named?\n\r", ch); return; } if (arg2[0] == '\0') { do_wtemplate(ch, ""); send_to_char("Who should be used as the wear template's target?\n\r", ch); return; } for (templ = first_wear_template; templ; templ = templ->next) { ch_printf(ch, " %s / ", templ->name); if (!str_cmp(templ->name, arg1)) break; ch_printf(ch, "%s\n\r", templ->name); } if (templ) { send_to_char("There is already a wear template with that name.\n\r", ch); return; } if ((vict = get_char_room(ch, arg2)) == NULL) { send_to_char("Who do you want to make a wear template of?\n\r", ch); return; } create_wear_template(arg1, vict); send_to_char("Created.\n\r", ch); return; } void do_wear_template_apply(CHAR_DATA *ch, char *argument) { WEAR_TEMPLATE_DATA *templ; CHAR_DATA *vict; char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; set_char_color(AT_IMMORT, ch); if (argument[0] == '\0') { do_wtemplate(ch, ""); return; } argument = one_argument(argument, arg1); argument = one_argument(argument, arg2); if (arg1[0] == '\0') { do_wtemplate(ch, ""); send_to_char("What wear template should be applied?\n\r", ch); return; } if (arg2[0] == '\0' || (vict = get_char_room(ch, arg2)) == NULL) { do_wtemplate(ch, ""); send_to_char("Who should be used as the wear template's target?\n\r", ch); return; } for (templ = first_wear_template; templ; templ = templ->next) if (!str_cmp(templ->name, arg1)) break; if (!templ) { send_to_char("There isn't a wear template with that name.\n\r", ch); return; } apply_wear_template(vict, NULL, templ->data, get_trust(ch)); send_to_char("Applied.\n\r", ch); return; } void create_wear_template(char *name, CHAR_DATA *ch) { WEAR_TEMPLATE_DATA *templ; WEAR_TEMPLATE_ITEM *root; // need to check if one exists. CREATE(templ, WEAR_TEMPLATE_DATA, 1); LINK(templ, first_wear_template, last_wear_template, next, prev); CREATE(root, WEAR_TEMPLATE_ITEM, 1); templ->name = str_dup(name); templ->data = root; // Setup the root's defaults. root->nest = -1; root->wear_loc = WEAR_NONE; root->obj = NULL; // Start building the item list. create_wear_template2(root, ch->first_carrying, ch->last_carrying, 0); } void create_wear_template2(WEAR_TEMPLATE_ITEM *root, OBJ_DATA *first, OBJ_DATA *last, int nest) { WEAR_TEMPLATE_ITEM *cur; OBJ_DATA *obj; for (obj=first; obj; obj=obj->next_content) { // Instantiate and link CREATE(cur, WEAR_TEMPLATE_ITEM, 1); LINK(cur, root->first_child, root->last_child, next, prev); // Get the wear loc, only "top" nest items can have a wear location. cur->wear_loc = (nest == 0 ? obj->wear_loc : WEAR_NONE); // Reference the index and the nest. cur->obj = obj->pIndexData; cur->nest = nest; // Recursively build the item list. if (obj->first_content && nest <= MAX_WEAR_TEMPLATE_NEST) create_wear_template2(cur, obj->first_content, obj->last_content, nest+1); // Usable defaults. else { cur->first_child = NULL; cur->last_child = NULL; } } } void list_wear_template(CHAR_DATA *ch, WEAR_TEMPLATE_DATA *templ) { int count = 0; ch_printf(ch, "Wear Template: %s\n\r", templ->name); if (templ->data->first_child) { count = list_wear_template2(ch, templ->data->first_child, templ->data->last_child, TRUE, 0); ch_printf(ch, "There %s %d item%s.\n\r", (count == 1 ? "is" : "are"), count, (count == 1 ? "" : "s") ); } } int list_wear_template2(CHAR_DATA *ch, WEAR_TEMPLATE_ITEM *first, WEAR_TEMPLATE_ITEM *last, bool header, int nest) { WEAR_TEMPLATE_ITEM *cur; int cnt = 0; if (header) send_to_char("| Wear | Vnum | Item (nest)\n\r", ch); for (cur = first; cur; cur = cur->next) { cnt++; // Output data. ch_printf(ch, "| %-13.13s | %-6d | %s (%d)\n\r", (cur->wear_loc == WEAR_NONE ? "none" : wear_locs[cur->wear_loc]), cur->obj->vnum, cur->obj->short_descr, nest ); // Recursive Call to build the tree. if (cur->first_child && nest <= MAX_WEAR_TEMPLATE_NEST) cnt += list_wear_template2(ch, cur->first_child, cur->last_child, FALSE, nest+1); } return cnt; } void apply_wear_template(CHAR_DATA *ch, OBJ_DATA *con, WEAR_TEMPLATE_ITEM *root, int obj_level) { WEAR_TEMPLATE_ITEM *cur = NULL; OBJ_DATA *obj = NULL; int nest; // Invalid data checks. if (!ch || !root) return; // Handle nesting. nest = root->nest; obj_level = URANGE(0, obj_level, LEVEL_AVATAR); // The "root" has a nest of -1, which means it doesn't have an obj. if (nest != -1) { if (!root->obj) return; obj = create_object(root->obj, obj_level); obj->level = obj_level; if (nest == 0) { obj = obj_to_char(obj, ch); if (root->wear_loc != WEAR_NONE) equip_char(ch, obj, root->wear_loc); } else if (con) { obj = obj_to_obj(obj, con); } else return; } // Check for recursive apply. if (root->first_child && nest < MAX_WEAR_TEMPLATE_NEST) for (cur=root->first_child; cur; cur=cur->next) apply_wear_template(ch, obj, cur, obj_level); } void save_wear_template() { FILE *fp; WEAR_TEMPLATE_DATA *templ; if (!(fp = fopen(WEAR_TEMPLATE_FILE, "w"))) { bug("save_wear_template: Unable to open file for writing."); return; } for (templ=first_wear_template; templ; templ=templ->next) { fprintf(fp, "#WEARTEMPLATE\n"); fprintf(fp, "%s~\n", templ->name); fwrite_wear_template(fp, templ->data, 0); fprintf(fp, "End\n"); } fprintf(fp, "#END\n"); fclose(fp); } void fwrite_wear_template(FILE *fp, WEAR_TEMPLATE_ITEM *root, int nest) { WEAR_TEMPLATE_ITEM *cur; for (cur = root->first_child; cur; cur=cur->next) { fprintf(fp, "Item %d %d %d\n", cur->obj->vnum, cur->wear_loc, nest ); // Recursive save. if (cur->first_child && nest < MAX_WEAR_TEMPLATE_NEST) fwrite_wear_template(fp, cur, nest+1); } } void load_wear_template() { FILE *fp; char *word; char letter; if (!(fp = fopen(WEAR_TEMPLATE_FILE, "r"))) { bug("load_wear_template: Unable to open file for reading."); return; } while(TRUE) { letter = fread_letter( fp ); if (letter == '*') { fread_to_eol(fp); continue; } if (letter != '#') { bug("load_wear_template: # not found."); break; } word = fread_word(fp); if (!strcmp(word, "WEARTEMPLATE")) { fread_wear_template(fp); return; } } } void fread_wear_template(FILE *fp) { WEAR_TEMPLATE_DATA *templ; CREATE(templ, WEAR_TEMPLATE_DATA, 1); CREATE(templ->data, WEAR_TEMPLATE_ITEM, 1); LINK(templ, first_wear_template, last_wear_template, next, prev); templ->name = fread_string_nohash(fp); templ->data->nest = -1; templ->data->wear_loc = WEAR_NONE; templ->data->obj = NULL; fread_wear_template2(fp, templ->data); } void fread_wear_template2(FILE *fp, WEAR_TEMPLATE_ITEM *root) { char *word; char *line; int vnum; int wear; int nest; int last_nest = -1; int i; OBJ_INDEX_DATA *obj; WEAR_TEMPLATE_ITEM *hist[MAX_WEAR_TEMPLATE_NEST]; WEAR_TEMPLATE_ITEM *cur; WEAR_TEMPLATE_ITEM *tmp; while(TRUE) { obj = NULL; vnum = -1; wear = WEAR_NONE; nest = -2; if (feof(fp)) return; word = fread_word(fp); if (!str_cmp(word, "End")) return; if (str_cmp(word, "Item")) { bug("Unrecognized word in wear template file."); continue; } line = fread_line(fp); sscanf(line, "%d %d %d", &vnum, &wear, &nest); // Object check. if (!(obj = get_obj_index(vnum))) continue; // Nest consistency check. if (nest < 0 || nest >= MAX_WEAR_TEMPLATE_NEST) continue; // Valid data should only allow the "nest" to increase by 1 at a time. if (nest > last_nest+1) continue; // 0 is root, otherwise use "nest-1" if (nest == 0) tmp = root; else tmp = hist[nest-1]; // Make sure we have a "parent" if (!tmp) continue; // Finally, read in the data. CREATE(cur, WEAR_TEMPLATE_ITEM, 1); cur->obj = obj; cur->wear_loc = wear; cur->nest = nest; // Link it to it's parent. LINK(cur, tmp->first_child, tmp->last_child, next, prev); // Update history data. hist[nest] = cur; last_nest = nest; // Clear all "post" nest data from the history. for (i=nest+1; i<MAX_WEAR_TEMPLATE_NEST; i++) hist[i] = NULL; } }