/* ************************************************************************** * File: craft.c Part of tbaMUD * * Version: 1.2 (March 2009) Written for tbaMUD 3.58 by Jamdog * * Purpose: To provide player crafting with OLC for creating new crafts * * Copyright: tbaMUD and Jamdog 2009 * * tbaMUD is a derivative of, and the continuation of, CircleMUD since v3.5 * * CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. * ************************************************************************** */ #ifndef __CRAFT_C__ #define __CRAFT_C__ #include "conf.h" #include "sysdep.h" #include "structs.h" #include "utils.h" #include "comm.h" #include "handler.h" #include "db.h" #include "interpreter.h" #include "genolc.h" #include "genzon.h" #include "spells.h" #include "oasis.h" #include "class.h" #include "screen.h" #include "craft.h" /* local static functions */ static void craftedit_save_internally(struct descriptor_data *d); static void craftedit_save_to_disk(void); static void craftedit_setup_new(struct descriptor_data *d); static void craftedit_setup_existing(struct descriptor_data *d, struct craft_data *cr); static void craftedit_disp_menu(struct descriptor_data *d); static void craftedit_req_menu(struct descriptor_data *d); static void craftedit_class_menu(struct descriptor_data *d); static void craftedit_flag_menu(struct descriptor_data *d); static void craftedit_skill_menu(struct descriptor_data *d); const char *craft_req_flags[] = { "NON-EXPEND", "IN-ROOM", "\n" }; /* Global variables used for crafting system */ struct craft_data *craft_list = NULL; /* Global variable as placeholder for OLC system */ struct craft_requirement temp_req; struct craft_data *new_craft(void) { struct craft_data *new_data; CREATE(new_data, struct craft_data, 1); new_data->result = NOTHING; new_data->craft_name = strdup("New Craft"); new_data->obj_reqs = NULL; new_data->num_reqs = 0; new_data->class_req = 0; new_data->skill_req = 0; new_data->min_skill = 0; new_data->min_level = 0; new_data->next = NULL; return (new_data); } struct craft_data *get_craft_by_vnum(craft_vnum c_num) { struct craft_data *this_craft; if (!craft_list) return NULL; for (this_craft=craft_list; this_craft; this_craft = this_craft->next) { if (this_craft->vnum == c_num) return this_craft; } return NULL; } void remove_craft_from_list(struct craft_data *rem_craft) { struct craft_data *this_craft = NULL; if (!craft_list) return; /* Check the main craft list */ for (this_craft=craft_list; this_craft && this_craft != rem_craft; this_craft = this_craft->next); if (this_craft == NULL) return; /* We found the craft in the list, remove it */ if (this_craft == craft_list) { craft_list = craft_list->next; /* 1st item - move the main craft_list pointer */ this_craft->vnum = NOTHING; free_craft(this_craft); } else { for (this_craft=craft_list; this_craft && this_craft->next != rem_craft; this_craft = this_craft->next); this_craft->next = rem_craft->next; rem_craft->vnum = NOTHING; free_craft(rem_craft); } } void free_craft(struct craft_data *this_craft) { if (this_craft) { free_craft_requirements(this_craft); if (this_craft->craft_name) free(this_craft->craft_name); if (get_craft_by_vnum(this_craft->vnum) != NULL) remove_craft_from_list(this_craft); free(this_craft); } } void free_craft_requirements(struct craft_data *this_craft) { if (this_craft->obj_reqs) free(this_craft->obj_reqs); this_craft->obj_reqs = NULL; this_craft->num_reqs = 0; } void free_craft_list(void) { struct craft_data *this_craft; for (this_craft=craft_list; this_craft; this_craft=craft_list) { craft_list = this_craft->next; this_craft->next = NULL; if (this_craft->craft_name) free(this_craft->craft_name); free_craft_requirements(this_craft); } craft_list = NULL; } void copy_craft(struct craft_data *to_craft, struct craft_data *from_craft) { int i; if (!to_craft || !from_craft) return; if (to_craft->craft_name) free(to_craft->craft_name); if (to_craft->obj_reqs) free_craft_requirements(to_craft); *to_craft = *from_craft; if (from_craft->craft_name) to_craft->craft_name = strdup(from_craft->craft_name); else to_craft->craft_name = NULL; to_craft->obj_reqs = NULL; to_craft->num_reqs = 0; for (i=0; i<from_craft->num_reqs; i++) { add_craft_requirement(to_craft, from_craft->obj_reqs[i].onum, from_craft->obj_reqs[i].num_required, from_craft->obj_reqs[i].req_flags); } } void add_craft(struct craft_data *toadd) { struct craft_data *this_craft=NULL, *i=NULL, *j=NULL; if (craft_list == NULL) { craft_list = new_craft(); this_craft = craft_list; } else { this_craft = new_craft(); /* Sort numerically at add-time */ for (i=craft_list; i && (CRAFT_VNUM(i) < CRAFT_VNUM(toadd)); i=i->next) j = i; if (j) { this_craft->next = j->next; j->next = this_craft; } } copy_craft(this_craft, toadd); } void add_craft_requirement(struct craft_data *this_craft, obj_vnum o_num, int num_objs, int *rq_flags) { int i; if (!this_craft) { log("SYSERR: Invalid craft (NULL) passed to add_craft_requirement"); return; } if (real_object(o_num) == NOTHING) { log("SYSERR: Invalid object vnum (%d) passed to add_craft_requirement", o_num); return; } if (num_objs < 1) { log("SYSERR: Invalid number of objects (%d) passed to add_craft_requirement", num_objs); return; } this_craft->num_reqs++; if (this_craft->obj_reqs && this_craft->num_reqs > 1) RECREATE(this_craft->obj_reqs, struct craft_requirement, this_craft->num_reqs); else CREATE(this_craft->obj_reqs, struct craft_requirement, this_craft->num_reqs); this_craft->obj_reqs[(this_craft->num_reqs-1)].onum = o_num; this_craft->obj_reqs[(this_craft->num_reqs-1)].num_required = num_objs; for (i=0; i<RQ_ARRAY_MAX; i++) this_craft->obj_reqs[(this_craft->num_reqs-1)].req_flags[i] = rq_flags[i]; } void delete_craft_requirement(struct craft_data *this_craft, int req_id) { int i, how_many; struct craft_requirement *new_list; /* Validate the variables */ if (!this_craft) return; how_many = this_craft->num_reqs; if (how_many == 0 || this_craft->obj_reqs == NULL) return; if (req_id < 0 || req_id >= how_many) return; /* We know which requirement in the list, make a new list */ CREATE(new_list, struct craft_requirement, how_many-1); /* Copy to the new list, ignoring the one to be removed */ for (i=0; i<how_many; i++) { if (i < req_id) { new_list[i] = this_craft->obj_reqs[i]; } else if (i > req_id) { new_list[(i-1)] = this_craft->obj_reqs[i]; } } /* All the data is copied to the new list - kill the old one */ free(this_craft->obj_reqs); this_craft->obj_reqs = new_list; this_craft->num_reqs--; } int load_crafts(void) { FILE *fl; int gl = 0, num_found=0, i, j, line_no = 0, v[2], b_flags[RQ_ARRAY_MAX]; char tag[6], line[MAX_INPUT_LENGTH + 1], buf[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH], buf3[MAX_STRING_LENGTH], buf4[MAX_STRING_LENGTH]; struct craft_data *this_craft=NULL; log("Loading Crafts file..."); if (!(fl = fopen(CRAFT_FILE, "r"))) { log(" Crafts file (%s) does not exist. Will create a new one", CRAFT_FILE); save_crafts(); return FALSE; } else { /* Ensure the craft_list is empty before loading */ free_craft_list(); while ((gl = get_line(fl, line)) && *line != '$') { line_no++; while (*line == '*') {gl = get_line(fl, line); line_no++;} if (*line == '#') { num_found++; if (num_found > MAX_CRAFTS) { log("SYSERR: Too many crafts found in crafts file (Max: %d)", MAX_CRAFTS); return FALSE; } /* Put the previous craft into the list */ if (this_craft) { add_craft(this_craft); free_craft(this_craft); this_craft = NULL; } /* Create a new craft ctructure to hold the data being loaded */ this_craft = new_craft(); this_craft->vnum = atoi(line+1); gl = 0; } if (gl) { tag_argument(line, tag); switch (*tag) { case 'C': if (!strcmp(tag, "Clas")) this_craft->class_req = asciiflag_conv(line); else log("SYSERR: Unknown tag %s in craft file %s, line %d", tag, CRAFT_FILE, line_no); break; case 'M': if (!strcmp(tag, "MSkl")) this_craft->min_skill = MIN(MAX(atoi(line), 0), 100); else if (!strcmp(tag, "MLvl")) this_craft->min_level = MIN(MAX(atoi(line), 0), LVL_IMMORT); else log("SYSERR: Unknown tag %s in craft file %s, line %d", tag, CRAFT_FILE, line_no); break; case 'N': if (!strcmp(tag, "Name")) { if (this_craft->craft_name) free (this_craft->craft_name); this_craft->craft_name = strdup(line); } else log("SYSERR: Unknown tag %s in craft file %s, line %d", tag, CRAFT_FILE, line_no); break; case 'O': if (!strcmp(tag, "ORes")) this_craft->result = real_object(atoi(line)) != NOTHING ? atoi(line) : NOTHING; else log("SYSERR: Unknown tag %s in craft file %s, line %d", tag, CRAFT_FILE, line_no); break; case 'R': if (!strcmp(tag, "Reqs")) { j=0; get_line(fl, line); line_no++; while (*line && *line != '~') { if (++j >= MAX_REQUIREMENTS) { log("SYSERR: Too many requirements in craft file (craft VNUM: %d, line %d, requirement %d)", this_craft->vnum, line_no, j+1); } else { if ((i = sscanf(line, "%d %d %s %s %s %s", v, v+1, buf, buf2, buf3, buf4)) != 6) { log("SYSERR: Invalid requirement in craft file (craft VNUM: %d, line %d, requirement %d)", this_craft->vnum, line_no, j+1); } else { b_flags[0] = asciiflag_conv(buf); b_flags[1] = asciiflag_conv(buf2); b_flags[2] = asciiflag_conv(buf3); b_flags[3] = asciiflag_conv(buf4); add_craft_requirement(this_craft, v[0], v[1], b_flags); } } get_line(fl, line); line_no++; } } else log("SYSERR: Unknown tag %s in craft file %s, line %d", tag, CRAFT_FILE, line_no); break; case 'S': if (!strcmp(tag, "Skil")) this_craft->skill_req = atoi(line); else log("SYSERR: Unknown tag %s in craft file %s, line %d", tag, CRAFT_FILE, line_no); break; default: log("SYSERR: Unknown tag %s in craft file %s, line %d", tag, CRAFT_FILE, line_no); break; } /* end switch tag */ } /* end if (gl) */ } /* end while get_line */ /* Put the final craft into the list (if one was found) */ if (this_craft) { add_craft(this_craft); free_craft(this_craft); this_craft = NULL; } log("- %d crafts loaded successfully", num_found); fclose(fl); } /* end else */ return TRUE; } int save_crafts(void) { FILE *fl; int j; char bits[127], bits2[127], bits3[127], bits4[127]; struct craft_data *this_craft; if (!(fl = fopen(CRAFT_FILE, "w"))) { mudlog(CMP, LVL_IMPL, TRUE, "SYSERR: Unable to open craft file for writing!"); return FALSE; } fprintf(fl, "* ASCII Craft File\n"); fprintf(fl, "* Part of tbaMUD\n"); for(this_craft=craft_list; this_craft; this_craft = this_craft->next) { fprintf(fl, "#%d\n", this_craft->vnum); if (this_craft->craft_name) fprintf(fl, "Name: %s\n", this_craft->craft_name); if (this_craft->result) fprintf(fl, "ORes: %d\n", this_craft->result); if (this_craft->class_req) fprintf(fl, "Clas: %d\n", this_craft->class_req); if (this_craft->skill_req) fprintf(fl, "Skil: %d\n", this_craft->skill_req); if (this_craft->min_skill) fprintf(fl, "MSkl: %d\n", this_craft->min_skill); if (this_craft->min_level) fprintf(fl, "MLvl: %d\n", this_craft->min_level); if (this_craft->num_reqs > 0) { fprintf(fl, "Reqs:\n"); for (j=0; j<this_craft->num_reqs; j++) { sprintascii(bits, CRAFT_REQ_FLAGS(this_craft,j)[0]); sprintascii(bits2, CRAFT_REQ_FLAGS(this_craft,j)[1]); sprintascii(bits3, CRAFT_REQ_FLAGS(this_craft,j)[2]); sprintascii(bits4, CRAFT_REQ_FLAGS(this_craft,j)[3]); fprintf(fl, "%d %d %s %s %s %s\n", CRAFT_REQ_OBJ(this_craft,j), CRAFT_REQ_NUM(this_craft,j), bits, bits2, bits3, bits4); } fprintf(fl, "~\n"); } } fprintf(fl, "$\n"); fclose(fl); return TRUE; } void show_crafts(struct char_data *ch, char *arg) { int j; obj_rnum o_num; char buf[MAX_STRING_LENGTH]; struct craft_data *i; get_char_colors(ch); if (!craft_list) { send_to_char(ch, "There are no crafts currently available.\r\n"); return; } if (arg && *arg) { /* List a single craft's details */ if ((i = get_craft_by_vnum(atoi(arg))) == NULL) { send_to_char(ch, "Invalid craft number.\r\n"); return; } sprintbit(CRAFT_CLASS_FLAGS(i), pc_class_types, buf, sizeof(buf)); send_to_char(ch, "Craft VNUM : %s[%s%d%s]%s\r\n" "Craft Name : %s%s%s\r\n" "Result Object : %s%d %s(%s)%s\r\n" "Allowed Classes: %s%s%s\r\n" "Required Skill : %s%d %s(%s)%s\r\n" "Minimum Skill : %s%d%s\r\n" "Minimum Level : %s%d%s\r\n", cyn, yel, CRAFT_VNUM(i), cyn, nrm, CRAFT_NAME(i) != NULL ? yel : cyn, CRAFT_NAME(i) != NULL ? CRAFT_NAME(i) : "<Not Set!>", nrm, yel, CRAFT_RESULT(i) != NOTHING ? CRAFT_RESULT(i) : 0, cyn, real_object(CRAFT_RESULT(i)) != NOTHING ? obj_proto[real_object(CRAFT_RESULT(i))].short_description : "<Not Set!>", nrm, cyn, buf, nrm, yel, CRAFT_SKILL_REQ(i), cyn, CRAFT_SKILL_REQ(i) != 0 ? spell_info[CRAFT_SKILL_REQ(i)].name : "<None>", nrm, yel, CRAFT_MIN_SKILL(i), nrm, yel, CRAFT_MIN_LEVEL(i), nrm); if (CRAFT_NUM_REQS(i) > 0) { send_to_char(ch, "Requirements :\r\n"); for (j=0; j<CRAFT_NUM_REQS(i); j++) { sprintbitarray(CRAFT_REQ_FLAGS(i,j), craft_req_flags, RQ_ARRAY_MAX, buf); o_num = real_object(CRAFT_REQ_OBJ(i,j)); send_to_char(ch, "(%d) %s[%s%5d%s]%s %-30s %s%s%s\r\n", CRAFT_REQ_NUM(i,j), cyn, yel, CRAFT_REQ_OBJ(i,j) != NOTHING ? CRAFT_REQ_OBJ(i,j) : 0, cyn, yel, o_num != NOTHING ? obj_proto[o_num].short_description: "<Invalid Obj VNUM>", cyn, buf, nrm ); } } else { send_to_char(ch, "Requirements : %s<None Set!>%s\r\n", cyn, nrm); } } else /* List all crafts */ { send_to_char(ch, "VNUM Object Name Lvl Skill\r\n"); for (i=craft_list; i; i=i->next) { send_to_char(ch, "%s[%s%5d%s] [%s%5d%s]%s %-30s %s%-3d %s%s\r\n", cyn, yel, CRAFT_VNUM(i), cyn, yel, CRAFT_RESULT(i) != NOTHING ? CRAFT_RESULT(i) : 0, cyn, CRAFT_NAME(i) != NULL ? yel : cyn, CRAFT_NAME(i) != NULL ? CRAFT_NAME(i) : "<Not Set!>", yel, CRAFT_MIN_LEVEL(i), CRAFT_SKILL_REQ(i) != 0 ? spell_info[CRAFT_SKILL_REQ(i)].name : "<None>", nrm); } } } struct obj_data *check_obj_in_inventory(struct char_data *ch, obj_rnum item_rnum) { struct obj_data *obj; for (obj = ch->carrying;obj;obj=obj->next_content) if(GET_OBJ_RNUM(obj)==item_rnum) return obj; return NULL; } int count_objs_in_inventory(struct char_data *ch, obj_rnum item_rnum) { struct obj_data *obj; int count=0; for (obj = ch->carrying;obj;obj=obj->next_content) if(GET_OBJ_RNUM(obj)==item_rnum) count++; return count; } struct obj_data *check_obj_in_inv_or_room(struct char_data *ch, obj_rnum item_rnum) { struct obj_data *obj; for (obj = ch->carrying;obj;obj=obj->next_content) if(GET_OBJ_RNUM(obj)==item_rnum) return obj; for (obj = world[IN_ROOM(ch)].contents;obj;obj=obj->next_content) if(GET_OBJ_RNUM(obj)==item_rnum) return obj; return NULL; } int count_objs_in_inv_or_room(struct char_data *ch, obj_rnum item_rnum) { struct obj_data *obj; int count=0; for (obj = ch->carrying;obj;obj=obj->next_content) if(GET_OBJ_RNUM(obj)==item_rnum) count++; for (obj = world[IN_ROOM(ch)].contents;obj;obj=obj->next_content) if(GET_OBJ_RNUM(obj)==item_rnum) count++; return count; } /* Player command: lists known crafts */ ACMD(do_crafts) { int j, count=0; struct char_data *vict = ch; struct craft_data *i; char arg[MAX_STRING_LENGTH]; obj_rnum o_num=NOTHING; bool fail=FALSE; argument = one_argument(argument, arg); if (GET_LEVEL(ch) >= LVL_GRGOD) { if (*arg) if (!(vict = get_player_vis(ch, arg, NULL, FIND_CHAR_WORLD))) vict = ch; if (vict != ch) { send_to_char(ch, "%sCraft details for %s%s\r\n", CCCYN(ch, C_NRM), GET_NAME(vict), CCNRM(ch, C_NRM)); argument = one_argument(argument, arg); /* Check for another arg */ } } if (*arg) { if ((i = get_craft_by_name(arg)) != NULL) { /* Show details for an individual craft */ if (!known_craft(vict, CRAFT_VNUM(i))) { send_to_char(ch, "You do not know that craft!\r\n"); return; } send_to_char(ch, "%sCraft Details for '%s'%s\r\n", CCYEL(ch, C_NRM), CRAFT_NAME(i), CCNRM(ch, C_NRM)); send_to_char(ch, "Skill Required: %s%s%s\r\n", CCCYN(ch, C_NRM), spell_info[CRAFT_SKILL_REQ(i)].name, CCNRM(ch, C_NRM)); send_to_char(ch, "Requirements :\r\n"); for (j=0; j<CRAFT_NUM_REQS(i); j++) { o_num = real_object(CRAFT_REQ_OBJ(i,j)); send_to_char(ch, "%s%d%s x %s%-30s%s\r\n", CCYEL(ch, C_NRM), CRAFT_REQ_NUM(i,j), CCNRM(ch, C_NRM), CCCYN(ch, C_NRM), o_num != NOTHING ? obj_proto[o_num].short_description : "<Invalid Obj VNUM>", CCNRM(ch, C_NRM) ); } return; } } for( i=craft_list; i; i=i->next) { if (CRAFT_SKILL_REQ(i) == 0) /* No known skill (craft err) */ continue; if (GET_SKILL(vict, CRAFT_SKILL_REQ(i)) < CRAFT_MIN_SKILL(i)) /* Player doesn't know skill */ continue; if (GET_LEVEL(vict) < CRAFT_MIN_LEVEL(i)) /* Player too low level */ continue; if (real_object(CRAFT_RESULT(i)) == NOTHING) /* Invalid result object */ continue; /* Check Class restriction flags */ if (!CRAFT_CLASS_FLAGGED(i, GET_CLASS(vict))) continue; fail=FALSE; /* Check all requirements are real objects */ for(j=0; j<CRAFT_NUM_REQS(i); j++) if ((o_num = real_object(CRAFT_REQ_OBJ(i,j))) == NOTHING) /* Valid result object */ fail=TRUE; if (fail == TRUE) continue; /* All checks passed - show this line of the list */ if (count == 0) send_to_char(ch, "Craft Name Skill Creates\r\n"); count++; o_num = real_object(CRAFT_RESULT(i)); send_to_char(ch, "%s%-20s%s %-15s%s %s\r\n", CCYEL(ch, C_NRM), CRAFT_NAME(i), CCCYN(ch, C_NRM), spell_info[CRAFT_SKILL_REQ(i)].name, CCNRM(ch, C_NRM), obj_proto[o_num].short_description); } if (count == 0) { if (vict == ch) { send_to_char(ch, "You do not know any crafts!\r\n"); } else { send_to_char(ch, "%s does not know any crafts!\r\n", GET_NAME(vict)); } } else { if (vict == ch) { send_to_char(ch, "You know %s%d%s craft%s!\r\n", CCYEL(ch, C_NRM), count, CCNRM(ch, C_NRM), count == 1 ? "" : "s"); } else { send_to_char(ch, "%s knows %s%d%s craft%s!\r\n", GET_NAME(vict), CCYEL(ch, C_NRM), count, CCNRM(ch, C_NRM), count == 1 ? "" : "s"); } } } /* Returns TRUE if the craft is valid and if ch should know it */ bool known_craft(struct char_data *ch, craft_rnum c_num) { int i; struct craft_data *this_craft; /* Perform checks - if any fail, return FALSE */ if ((this_craft = get_craft_by_vnum(c_num)) == NULL) return FALSE; if (CRAFT_SKILL_REQ(this_craft) == 0) /* No known skill (craft err) */ return FALSE; if (GET_SKILL(ch, CRAFT_SKILL_REQ(this_craft) < CRAFT_MIN_SKILL(this_craft))) /* Player doesn't know skill */ return FALSE; if (GET_LEVEL(ch) < CRAFT_MIN_LEVEL(this_craft)) /* Player too low level */ return FALSE; if (real_object(CRAFT_RESULT(this_craft)) == NOTHING) /* Invalid result object */ return FALSE; /* Check Class restriction flags */ if (!CRAFT_CLASS_FLAGGED(this_craft, GET_CLASS(ch))) return FALSE; /* Check all requirements are real objects */ for(i=0; i<CRAFT_NUM_REQS(this_craft); i++) if ((real_object(CRAFT_REQ_OBJ(this_craft,i))) == NOTHING) /* Valid result object */ return FALSE; /* All checks passed - return TRUE */ return TRUE; } bool check_craft_kit(struct obj_data *kit, int num) { /* Kit is infinite */ if (GET_OBJ_VAL(kit, 0) == -1) return TRUE; /* Yes, removal would be successful */ if (GET_OBJ_VAL(kit, 1) < num) return FALSE; /* No, there are not enough kit parts */ return TRUE; /* Yes, removal would be successful */ } bool reduce_craft_kit(struct obj_data *kit, int num) { /* Kit is infinite */ if (GET_OBJ_VAL(kit, 0) == -1) return TRUE; if (GET_OBJ_VAL(kit, 1) < num) return FALSE; /* No, there are not enough kit parts */ GET_OBJ_VAL(kit, 1) = MIN(MAX((GET_OBJ_VAL(kit, 1) - num), 0), GET_OBJ_VAL(kit, 0)); return TRUE; } /* Checks all requirements, telling player everything they are missing */ bool has_craft_requirements(struct char_data *ch, craft_vnum c_id) { int i; obj_rnum o_rnum; struct obj_data *obj; struct craft_data *cr; bool success = TRUE; if ((cr = get_craft_by_vnum(c_id)) == NULL) { log("SYSERR: Invalid craft VNUM (%d) passed to has_craft_requirements", c_id); return FALSE; } for (i=0; i<CRAFT_NUM_REQS(cr); i++) { if ((o_rnum = real_object(CRAFT_REQ_OBJ(cr,i))) != NOTHING) { /* Only check if valid */ if (CRAFT_REQ_FLAGGED(cr,i,C_REQ_IN_ROOM)) { if ((obj = check_obj_in_inv_or_room(ch, o_rnum)) != NULL) { /* Is this a kit? */ if (GET_OBJ_TYPE(obj) == ITEM_CRAFTKIT) { if (!check_craft_kit(obj, CRAFT_REQ_NUM(cr,i))) { success = FALSE; send_to_char(ch, "%s is too empty.\r\n", GET_OBJ_SHORT(obj)); } } else { /* Not a craftkit */ if (count_objs_in_inv_or_room(ch, o_rnum) < CRAFT_REQ_NUM(cr,i)) { success = FALSE; send_to_char(ch, "You don't have enough of %s.\r\n", GET_OBJ_SHORT(obj)); } } } else { success = FALSE; send_to_char(ch, "You don't have %s.\r\n", obj_proto[o_rnum].short_description); } } else { if ((obj = check_obj_in_inventory(ch, o_rnum)) != NULL) { /* Is this a kit? */ if (GET_OBJ_TYPE(obj) == ITEM_CRAFTKIT) { if (!check_craft_kit(obj, CRAFT_REQ_NUM(cr,i))) { success = FALSE; send_to_char(ch, "%s is too empty.\r\n", GET_OBJ_SHORT(obj)); } } else { /* Not a craftkit */ if (count_objs_in_inventory(ch, o_rnum) < CRAFT_REQ_NUM(cr,i)) { success = FALSE; send_to_char(ch, "You don't have enough of %s.\r\n", GET_OBJ_SHORT(obj)); } } } else { success = FALSE; send_to_char(ch, "You don't have %s.\r\n", obj_proto[o_rnum].short_description); } } } } return(success); } void remove_all_craft_requirements(struct char_data *ch, craft_vnum c_id) { int i, j; obj_rnum o_rnum; struct obj_data *obj; struct craft_data *cr; if ((cr = get_craft_by_vnum(c_id)) == NULL) { log("SYSERR: Invalid craft VNUM (%d) passed to remove_all_craft_requirements", c_id); return; } for (i=0; i<CRAFT_NUM_REQS(cr); i++) { if (CRAFT_REQ_FLAGGED(cr, i, C_REQ_NON_EXPEND)) /* Flagged 'do not expend' */ continue; if ((o_rnum = real_object(CRAFT_REQ_OBJ(cr,i))) != NOTHING) { if (CRAFT_REQ_FLAGGED(cr,i,C_REQ_IN_ROOM)) { /* IN-ROOM is flagged, so check both room and inventory */ if ((obj = check_obj_in_inv_or_room(ch, o_rnum)) != NULL) { if (GET_OBJ_TYPE(obj) == ITEM_CRAFTKIT) { reduce_craft_kit(obj, CRAFT_REQ_NUM(cr,i)); } else { /* Repeat as many times as necessary */ for(j=0; j<CRAFT_REQ_NUM(cr,i); j++) { if (obj) { obj_from_char(obj); extract_obj(obj); } obj = check_obj_in_inv_or_room(ch, o_rnum); } } } } else if ((obj = check_obj_in_inventory(ch, o_rnum)) != NULL) { /* IN-ROOM isn't flagged, so only check inventory */ if (GET_OBJ_TYPE(obj) == ITEM_CRAFTKIT) { reduce_craft_kit(obj, CRAFT_REQ_NUM(cr,i)); } else { /* Repeat as many times as necessary */ for(j=0; j<CRAFT_REQ_NUM(cr,i); j++) { if (obj) { obj_from_char(obj); extract_obj(obj); } obj = check_obj_in_inventory(ch, o_rnum); } } } } } } struct craft_data *get_craft_by_name(char *cr_name) { struct craft_data *i; if (!cr_name || !*cr_name) return NULL; /* Check for perfect match first */ for (i=craft_list; i; i=i->next) { if (i->craft_name && str_cmp(cr_name, i->craft_name) == 0) return i; } /* Not found - check for abbreviated match */ for (i=craft_list; i; i=i->next) { if ( is_abbrev(cr_name, CRAFT_NAME(i)) ) return i; } /* Still not found - return NOTHING */ return NULL; } /* General crafting function - used for all crafts, regardless of command */ ACMD(do_gen_craft) { int skill_id=0, i; struct obj_data *obj; struct craft_data *cr; obj_rnum o_num; char to_ch[MAX_STRING_LENGTH], to_rm[MAX_STRING_LENGTH]; switch(subcmd) { case SCMD_BREW: skill_id = SKILL_BREW; sprintf(to_ch, "You carefully brew the ingredients and create $p."); sprintf(to_rm, "$n brews up $p."); break; case SCMD_SCRIBE: skill_id = SKILL_SCRIBE; sprintf(to_ch, "You carefully scribe to create $p."); sprintf(to_rm, "$n scribes $p."); break; case SCMD_CONSTRUCT: skill_id = SKILL_CONSTRUCT; sprintf(to_ch, "You carefully put the pieces together to contruct $p."); sprintf(to_rm, "$n constructs $p."); break; default: /* Check all crafts, to see if it's been missed in the list */ for (i=0; i<MAX_SKILLS; i++) if (spell_info[i].routines == SK_CRAFT) if (is_abbrev(complete_cmd_info[cmd].command, spell_info[i].name)) skill_id = i; if (skill_id == 0) { log("SYSERR: Invalid scmd in do_gen_craft"); return; } sprintf(to_ch, "You carefully craft $p."); sprintf(to_rm, "$N crafts $p."); break; } skip_spaces(&argument); if (!*argument) { send_to_char(ch, "%s what? Type crafts to see your available crafts.", spell_info[(skill_id)].name); return; } /* Is the 'name' a valid craft? */ if ((cr = get_craft_by_name(argument)) == NULL) { send_to_char(ch, "You have no idea how to %s that!", spell_info[(skill_id)].name); return; } /* Does the player know this craft? */ if (!known_craft(ch, CRAFT_VNUM(cr))) { send_to_char(ch, "You don't know how to %s that!", spell_info[(skill_id)].name); return; } /* Is player using the correct required skill */ if (skill_id != CRAFT_SKILL_REQ(cr)) { send_to_char(ch, "You can't %s that! Try %s instead!", spell_info[(skill_id)].name, spell_info[(CRAFT_SKILL_REQ(cr))].name); return; } if (!has_craft_requirements(ch, CRAFT_VNUM(cr))) { /* has_craft_requirements shows messages, so just return */ return; } /* Check probability of success */ if (rand_number(0,101) > GET_SKILL(ch, skill_id)) { send_to_char(ch, "You fail, miserably!"); return; } if ((o_num = real_object(CRAFT_RESULT(cr))) == NOTHING) { send_to_char(ch, "Your attempts result in a gelatinous mess that oozes into the earth."); return; } /* All checks passed, let's craft! */ remove_all_craft_requirements(ch, CRAFT_VNUM(cr)); obj = read_object(o_num, REAL); obj_to_char(obj, ch); act(to_ch, TRUE, ch, obj, NULL, TO_CHAR); act(to_rm, TRUE, ch, obj, NULL, TO_ROOM); } /****************************************************************************/ /** All craftedit functions are below this point **/ /****************************************************************************/ static void craftedit_save_internally(struct descriptor_data *d) { struct craft_data *r_craft; if ((r_craft = get_craft_by_vnum(OLC_CRAFT(d)->vnum)) != NULL) { copy_craft(r_craft, OLC_CRAFT(d)); } else { add_craft(OLC_CRAFT(d)); } } static void craftedit_save_to_disk(void) { save_crafts(); } static void craftedit_setup_new(struct descriptor_data *d) { OLC_CRAFT(d) = new_craft(); OLC_CRAFT(d)->vnum = OLC_NUM(d); /* Show the main craft edit menu */ craftedit_disp_menu(d); } static void craftedit_setup_existing(struct descriptor_data *d, struct craft_data *cr) { OLC_CRAFT(d) = new_craft(); copy_craft(OLC_CRAFT(d), cr); OLC_CRAFT(d)->vnum = OLC_NUM(d); /* Show the main craft edit menu */ craftedit_disp_menu(d); } ACMD(do_oasis_craftedit) { int save = 0; craft_vnum number = NOTHING; struct descriptor_data *d; struct craft_data *cr; char *buf3; char buf1[MAX_INPUT_LENGTH]; char buf2[MAX_INPUT_LENGTH]; /****************************************************************************/ /** Parse any arguments. **/ /****************************************************************************/ buf3 = two_arguments(argument, buf1, buf2); if (!*buf1) { send_to_char(ch, "Specify a craft VNUM to edit.\r\n"); return; } else if (!isdigit(*buf1)) { if (str_cmp("save", buf1) != 0) { send_to_char(ch, "Yikes! Stop that, someone will get hurt!\r\n"); return; } save = TRUE; if (is_number(buf2)) { send_to_char(ch, "Crafts are all saved in one file. You can't specify a zone!\r\n"); return; } send_to_char(ch, "Saving all crafts.\r\n"); mudlog(CMP, MAX(LVL_BUILDER, GET_INVIS_LEV(ch)), TRUE, "OLC: %s saves craft info.", GET_NAME(ch)); /**************************************************************************/ /** Save the quest to the quest file. **/ /**************************************************************************/ craftedit_save_to_disk(); return; } /****************************************************************************/ /** If a numeric argument was given, get it. **/ /****************************************************************************/ if (number == NOWHERE) number = atoi(buf1); /****************************************************************************/ /** Check that the craft isn't already being edited. **/ /****************************************************************************/ for (d = descriptor_list; d; d = d->next) { if (STATE(d) == CON_CRAFTEDIT) { if (d->olc && OLC_NUM(d) == number) { send_to_char(ch, "That craft is currently being edited by %s.\r\n", PERS(d->character, ch)); return; } } } /****************************************************************************/ /** Point d to the builder's descriptor. **/ /****************************************************************************/ d = ch->desc; /****************************************************************************/ /** Give the descriptor an OLC structure. **/ /****************************************************************************/ if (d->olc) { mudlog(BRF, LVL_IMMORT, TRUE, "SYSERR: do_oasis_craftedit: Player already had olc structure."); free(d->olc); } CREATE(d->olc, struct oasis_olc_data, 1); /****************************************************************************/ /** Find the zone. **/ /****************************************************************************/ if ((OLC_ZNUM(d) = real_zone_by_thing(number)) == NOWHERE) { send_to_char(ch, "Sorry, there is no zone for that number!\r\n"); free(d->olc); d->olc = NULL; return; } /****************************************************************************/ /** Everyone but IMPLs can only edit zones they have been assigned. **/ /****************************************************************************/ if (!can_edit_zone(ch, OLC_ZNUM(d))) { send_to_char(ch, "You do not have permission to edit this zone.\r\n"); /**************************************************************************/ /** Free the OLC structure. **/ /**************************************************************************/ free(d->olc); d->olc = NULL; return; } OLC_NUM(d) = number; if ((cr = get_craft_by_vnum(number)) != NULL) craftedit_setup_existing(d, cr); else craftedit_setup_new(d); STATE(d) = CON_CRAFTEDIT; act("$n starts using OLC.", TRUE, d->character, 0, 0, TO_ROOM); SET_BIT_AR(PLR_FLAGS(ch), PLR_WRITING); mudlog(BRF, LVL_IMMORT, TRUE, "OLC: %s starts editing craft %d allowed zone %d", GET_NAME(ch), OLC_NUM(d), GET_OLC_ZONE(ch)); } /************************************************************************** Menu functions **************************************************************************/ /*-------------------------------------------------------------------*/ /*. Display main menu . */ static void craftedit_disp_menu(struct descriptor_data *d) { char buf[MAX_STRING_LENGTH]; get_char_colors(d->character); clear_screen(d); sprintbit(OLC_CRAFT(d)->class_req, pc_class_types, buf, sizeof(buf)); write_to_output(d, "-- Craft VNUM : %s[%s%d%s]%s\r\n" "%s1%s) Craft Name : %s%s%s\r\n" "%s2%s) Result Object : %s%d %s%s%s\r\n" "%s3%s) Allowed Classes: %s%s%s\r\n" "%s4%s) Required Skill : %s%d %s(%s)%s\r\n" "%s5%s) Minimum Skill : %s%d%s\r\n" "%s6%s) Minimum Level : %s%d%s\r\n" "%s7%s) Craft Requirements...\r\n" "%sX%s) Delete this Craft\r\n" "%sQ%s) Quit\r\n" "Enter choice : ", cyn, yel, OLC_NUM(d), cyn, nrm, cyn, nrm, OLC_CRAFT(d)->craft_name != NULL ? yel : cyn, OLC_CRAFT(d)->craft_name != NULL ? OLC_CRAFT(d)->craft_name : "<Not Set!>", nrm, cyn, nrm, yel, OLC_CRAFT(d)->result != NOTHING ? OLC_CRAFT(d)->result : 0, cyn, OLC_CRAFT(d)->result != NOTHING ? obj_proto[(real_object(OLC_CRAFT(d)->result))].short_description : "<Not Set!>", nrm, cyn, nrm, cyn, buf, nrm, cyn, nrm, yel, OLC_CRAFT(d)->skill_req, cyn, OLC_CRAFT(d)->skill_req != 0 ? spell_info[OLC_CRAFT(d)->skill_req].name : "<None>", nrm, cyn, nrm, yel, OLC_CRAFT(d)->min_skill, nrm, cyn, nrm, yel, OLC_CRAFT(d)->min_level, nrm, cyn, nrm, cyn, nrm, cyn, nrm); OLC_MODE(d) = CRAFTEDIT_MAIN_MENU; } /*-------------------------------------------------------------------*/ /*. Display craft requirements menu . */ static void craftedit_req_menu(struct descriptor_data *d) { int i; obj_rnum r_obj = NOTHING; struct craft_requirement *this_req=NULL; char buf[MAX_STRING_LENGTH]; get_char_colors(d->character); clear_screen(d); write_to_output(d, "-- Requirements for Craft VNUM : %s[%s%d%s]%s\r\n",cyn, yel, OLC_NUM(d), cyn, nrm); for (i=0; i<OLC_CRAFT(d)->num_reqs; i++) { this_req = OLC_CRAFT(d)->obj_reqs+i; r_obj = real_object(this_req->onum); sprintbitarray(this_req->req_flags, craft_req_flags, RQ_ARRAY_MAX, buf); write_to_output(d, "(%s%d%s) %d x %s[%s%d%s]%s %s %s(%s)%s\r\n", yel, i+1, nrm, this_req->num_required, cyn, yel, this_req->onum, cyn, nrm, r_obj != NOTHING ? obj_proto[r_obj].short_description : "<Invalid Obj VNUM>", cyn, buf, nrm ); } write_to_output(d, "\r\n" "%sA%s) Add a new requirement\r\n" "%sD%s) Delete a requirement\r\n" "%sX%s) Delete ALL requirements\r\n" "%sQ%s) Return to previous menu\r\n", cyn, nrm, cyn, nrm, cyn, nrm, cyn, nrm); OLC_MODE(d) = CRAFTEDIT_REQ_MENU; } /*-------------------------------------------------------------------*/ /*. Display class flags menu . */ static void craftedit_class_menu(struct descriptor_data *d) { int counter, columns = 0; char buf[MAX_STRING_LENGTH]; get_char_colors(d->character); clear_screen(d); sprintbit(OLC_CRAFT(d)->class_req, pc_class_types, buf, sizeof(buf)); write_to_output(d, "-- Allowed Classes for Craft VNUM : %s[%s%d%s]%s\r\n",cyn, yel, OLC_NUM(d), cyn, nrm); for (counter = 0; counter < NUM_CLASSES; counter++) { write_to_output(d, "%s%2d%s) %-20.20s %s", cyn, counter+1, nrm, pc_class_types[counter], !(++columns % 2) ? "\r\n" : ""); } write_to_output(d, "Class Flags: %s%s%s\r\n", cyn, buf, nrm); write_to_output(d, "\r\nEnter class (0 to finish) : "); OLC_MODE(d) = CRAFTEDIT_CLASS_MENU; } /*-------------------------------------------------------------------*/ /*. Display craft requirement flags menu . */ static void craftedit_flag_menu(struct descriptor_data *d) { int counter, columns = 0; char buf[MAX_STRING_LENGTH]; get_char_colors(d->character); clear_screen(d); sprintbitarray(temp_req.req_flags, craft_req_flags, RQ_ARRAY_MAX, buf); write_to_output(d, "-- Requirement Flags for Craft VNUM : %s[%s%d%s]%s\r\n",cyn, yel, OLC_NUM(d), cyn, nrm); for (counter = 0; counter < NUM_C_REQ_FLAGS; counter++) { write_to_output(d, "%s%2d%s) %-20.20s %s", cyn, counter+1, nrm, craft_req_flags[counter], !(++columns % 2) ? "\r\n" : ""); } write_to_output(d, "Requirement Flags: %s%s%s\r\n", cyn, buf, nrm); write_to_output(d, "\r\nEnter requirement flag (0 to finish) : "); OLC_MODE(d) = CRAFTEDIT_FLAG_MENU; } /*-------------------------------------------------------------------*/ /*. Display craft skills menu . */ static void craftedit_skill_menu(struct descriptor_data *d) { int i, counter=0, columns = 0; for (i=0; i<MAX_SKILLS; i++) { if (spell_info[i].routines == SK_CRAFT) { write_to_output(d, "%d) %-20.20s %s", ++counter, spell_info[i].name, !(++columns % 2) ? "\r\n" : ""); } } write_to_output(d, "\r\nEnter craft skill : "); OLC_MODE(d) = CRAFTEDIT_SKILL_MENU; } /*-------------------------------------------------------------------*/ /* main craftedit parser function... interpreter throws all input to here. */ void craftedit_parse(struct descriptor_data *d, char *arg) { int i, count, number = atoi(arg); switch (OLC_MODE(d)) { case CRAFTEDIT_CONFIRM_SAVESTRING: switch (*arg) { case 'y': case 'Y': craftedit_save_internally(d); mudlog(CMP, MAX(LVL_BUILDER, GET_INVIS_LEV(d->character)), TRUE, "OLC: %s edits craft %d", GET_NAME(d->character), OLC_NUM(d)); if (CONFIG_OLC_SAVE) { craftedit_save_to_disk(); write_to_output(d, "Craft saved to disk.\r\n"); } else write_to_output(d, "Craft saved to memory.\r\n"); cleanup_olc(d, CLEANUP_ALL); return; case 'n': case 'N': cleanup_olc(d, CLEANUP_ALL); return; case 'a': /* abort quit */ case 'A': craftedit_disp_menu(d); return; default: write_to_output(d, "Invalid choice!\r\n"); write_to_output(d, "Do you wish to save your changes? : \r\n"); return; } break; /*-------------------------------------------------------------------*/ case CRAFTEDIT_MAIN_MENU: switch (*arg) { case 'q': case 'Q': if (OLC_VAL(d)) { /* Something has been modified. */ write_to_output(d, "Do you wish to save your changes? : "); OLC_MODE(d) = CRAFTEDIT_CONFIRM_SAVESTRING; } else cleanup_olc(d, CLEANUP_ALL); return; case '1': write_to_output(d, "Enter craft name : "); OLC_MODE(d) = CRAFTEDIT_NAME; break; case '2': write_to_output(d, "Enter resulting object VNUM : "); OLC_MODE(d) = CRAFTEDIT_RESULT; break; case '3': craftedit_class_menu(d); break; case '4': craftedit_skill_menu(d); break; case '5': write_to_output(d, "Enter minimum skill %% (0-100) : "); OLC_MODE(d) = CRAFTEDIT_MINSKILL; break; case '6': write_to_output(d, "Enter minimum player level : (0-%d)", (LVL_IMMORT-1)); OLC_MODE(d) = CRAFTEDIT_MINLEVEL; break; case '7': craftedit_req_menu(d); break; case 'x': case 'X': write_to_output(d, "Are you SURE you wish to delete this craft? (Y/N) : "); OLC_MODE(d) = CRAFTEDIT_DEL_CRAFT; break; default: craftedit_disp_menu(d); break; } return; /* end of CRAFTEDIT_MAIN_MENU */ /*-------------------------------------------------------------------*/ case CRAFTEDIT_REQ_MENU: switch (*arg) { case 'q': case 'Q': craftedit_disp_menu(d); break; case 'a': case 'A': write_to_output(d, "Enter required object VNUM : "); OLC_MODE(d) = CRAFTEDIT_REQ_OBJECT; break; case 'd': case 'D': write_to_output(d, "Enter number of requirement to delete : "); OLC_MODE(d) = CRAFTEDIT_REQ_DELETE; break; case 'x': case 'X': write_to_output(d, "Are you sure you wish to delete ALL requirements (Y/N) : "); OLC_MODE(d) = CRAFTEDIT_REQ_DELCONF; break; default: craftedit_req_menu(d); break; } return; /* end of CRAFTEDIT_REQ_MENU */ /*-------------------------------------------------------------------*/ case CRAFTEDIT_CLASS_MENU: if (number == 0) { craftedit_disp_menu(d); return; } if (number < 1 || number > NUM_CLASSES) { write_to_output(d, "Invalid class!\r\nTry again : "); return; } TOGGLE_BIT(OLC_CRAFT(d)->class_req, (1 << (number-1))); /* 32-bit flags */ OLC_VAL(d) = 1; craftedit_class_menu(d); return; /*-------------------------------------------------------------------*/ case CRAFTEDIT_FLAG_MENU: if (number == 0) { /* Finished getting requirement data, add it to the craft */ add_craft_requirement(OLC_CRAFT(d), temp_req.onum, temp_req.num_required, temp_req.req_flags); craftedit_req_menu(d); return; } if (number < 1 || number > NUM_C_REQ_FLAGS) { write_to_output(d, "Invalid flag!\r\nTry again : "); return; } TOGGLE_BIT_AR(temp_req.req_flags, (number-1)); /* 128-bit flags */ OLC_VAL(d) = 1; craftedit_flag_menu(d); return; /*-------------------------------------------------------------------*/ case CRAFTEDIT_SKILL_MENU: if (number == 0) { /* Abort */ craftedit_disp_menu(d); return; } count = 0; for (i=0; i<MAX_SKILLS; i++) { if (spell_info[i].routines == SK_CRAFT) { if ((++count) == number) { OLC_CRAFT(d)->skill_req = i; OLC_VAL(d) = 1; craftedit_disp_menu(d); return; } } } write_to_output(d, "Invalid skill!\r\nTry again (0 to abort) : "); return; /*-------------------------------------------------------------------*/ case CRAFTEDIT_NAME: if (OLC_CRAFT(d)->craft_name) free(OLC_CRAFT(d)->craft_name); if (*arg) OLC_CRAFT(d)->craft_name = strdup(arg); else OLC_CRAFT(d)->craft_name = NULL; OLC_VAL(d) = 1; craftedit_disp_menu(d); return; /*-------------------------------------------------------------------*/ case CRAFTEDIT_RESULT: if (number == 0) { craftedit_disp_menu(d); return; } if (real_object(number) == NOTHING) { write_to_output(d, "Invalid object VNUM!\r\nTry again (0=abort) : "); return; } OLC_CRAFT(d)->result = number; OLC_VAL(d) = 1; craftedit_disp_menu(d); return; /*-------------------------------------------------------------------*/ case CRAFTEDIT_MINSKILL: OLC_CRAFT(d)->min_skill = LIMIT(number, 0, 100); OLC_VAL(d) = 1; craftedit_disp_menu(d); return; /*-------------------------------------------------------------------*/ case CRAFTEDIT_MINLEVEL: OLC_CRAFT(d)->min_level = LIMIT(number, 0, (LVL_IMMORT-1)); OLC_VAL(d) = 1; craftedit_disp_menu(d); return; /*-------------------------------------------------------------------*/ case CRAFTEDIT_REQ_OBJECT: if (number == 0) { craftedit_disp_menu(d); return; } if (real_object(number) == NOTHING) { write_to_output(d, "Invalid object VNUM!\r\nTry again (0=abort) : "); return; } temp_req.onum = number; OLC_VAL(d) = 1; write_to_output(d, "How many of this object are required? (1-%d or 0 to abort) : ", MAX_REQUIREMENTS); OLC_MODE(d) = CRAFTEDIT_REQ_NUMBER; return; /*-------------------------------------------------------------------*/ case CRAFTEDIT_REQ_NUMBER: if (number == 0) { craftedit_disp_menu(d); return; } temp_req.num_required = LIMIT(number, 1, MAX_REQUIREMENTS); craftedit_flag_menu(d); OLC_VAL(d) = 1; return; /*-------------------------------------------------------------------*/ case CRAFTEDIT_REQ_DELETE: if (number > 0 && number <= CRAFT_NUM_REQS(OLC_CRAFT(d))) { delete_craft_requirement(OLC_CRAFT(d), number-1); OLC_VAL(d) = 1; } craftedit_req_menu(d); return; /*-------------------------------------------------------------------*/ case CRAFTEDIT_REQ_DELCONF: switch (*arg) { case 'y': case 'Y': free_craft_requirements(OLC_CRAFT(d)); OLC_VAL(d) = 1; break; case 'n': case 'N': break; default: write_to_output(d, "Invalid selection - delete aborted!\r\n"); break; } craftedit_req_menu(d); return; /*-------------------------------------------------------------------*/ case CRAFTEDIT_DEL_CRAFT: switch (*arg) { case 'y': case 'Y': /* Free craft automatically checks the craft list and removes matching vnums */ free_craft(OLC_CRAFT(d)); OLC_CRAFT(d) = NULL; write_to_output(d, "Craft deleted.\r\n"); if (CONFIG_OLC_SAVE) { craftedit_save_to_disk(); write_to_output(d, "Crafts saved to disk.\r\n"); } else { write_to_output(d, "Crafts saved to memory.\r\n"); } cleanup_olc(d, CLEANUP_ALL); break; case 'n': case 'N': write_to_output(d, "Craft NOT deleted.\r\n"); craftedit_disp_menu(d); break; } return; /*-------------------------------------------------------------------*/ default: mudlog(BRF, LVL_BUILDER, TRUE, "SYSERR: OLC: Reached default case in craftedit_parse()!"); write_to_output(d, "Oops...\r\n"); break; } } #endif