/* *********************************************************************** * File: qedit.c Part of CircleMUD * * Version: 2.0 (November 2005) Written for CircleMud CWG / Suntzu * * Purpose: To provide special quest-related code. * * Copyright: Kenneth Ray * * * * Made for Oasis OLC * * Copyright 1996 Harvey Gilpin. * *********************************************************************** */ #include "conf.h" #include "sysdep.h" #include "structs.h" #include "utils.h" #include "comm.h" #include "db.h" #include "oasis.h" #include "improved-edit.h" #include "screen.h" #include "genolc.h" #include "genzon.h" #include "interpreter.h" #include "modify.h" #include "quest.h" /*-------------------------------------------------------------------*/ /*. Function prototypes . */ static void qedit_setup_new(struct descriptor_data *d); static void qedit_setup_existing(struct descriptor_data *d, qst_rnum rnum); static void qedit_disp_menu(struct descriptor_data *d); static void qedit_save_internally(struct descriptor_data *d); static void qedit_save_to_disk(int num); /*-------------------------------------------------------------------*/ static void qedit_save_internally(struct descriptor_data *d) { add_quest(OLC_QUEST(d)); } static void qedit_save_to_disk(int num) { save_quests(num); } /*-------------------------------------------------------------------*\ utility functions \*-------------------------------------------------------------------*/ ACMD(do_oasis_qedit) { int save = 0; qst_rnum real_num; qst_vnum number = NOWHERE; struct descriptor_data *d; 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 quest 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)) number = atoi(buf2); else if (GET_OLC_ZONE(ch) > 0) { zone_rnum zlok; if ((zlok = real_zone(GET_OLC_ZONE(ch))) == NOWHERE) number = NOWHERE; else number = genolc_zone_bottom(zlok); } if (number == NOWHERE) { send_to_char(ch, "Save which zone?\r\n"); return; } } /****************************************************************************/ /** If a numeric argument was given, get it. **/ /****************************************************************************/ if (number == NOWHERE) number = atoi(buf1); /****************************************************************************/ /** Check that the quest isn't already being edited. **/ /****************************************************************************/ for (d = descriptor_list; d; d = d->next) { if (STATE(d) == CON_QEDIT) { if (d->olc && OLC_NUM(d) == number) { send_to_char(ch, "That quest 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_quest: 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; } if (save) { send_to_char(ch, "Saving all quests in zone %d.\r\n", zone_table[OLC_ZNUM(d)].number); mudlog(CMP, MAX(LVL_BUILDER, GET_INVIS_LEV(ch)), TRUE, "OLC: %s saves quest info for zone %d.", GET_NAME(ch), zone_table[OLC_ZNUM(d)].number); /**************************************************************************/ /** Save the quest to the quest file. **/ /**************************************************************************/ qedit_save_to_disk(OLC_ZNUM(d)); /**************************************************************************/ /** Free the OLC structure. **/ /**************************************************************************/ free(d->olc); d->olc = NULL; return; } OLC_NUM(d) = number; if ((real_num = real_quest(number)) != NOTHING) qedit_setup_existing(d, real_num); else qedit_setup_new(d); STATE(d) = CON_QEDIT; 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 zone %d allowed zone %d", GET_NAME(ch), zone_table[OLC_ZNUM(d)].number, GET_OLC_ZONE(ch)); } static void qedit_setup_new(struct descriptor_data *d) { struct aq_data *quest; /* Allociate some quest shaped space */ CREATE(quest, struct aq_data, 1); /* Set default values */ quest->vnum = OLC_NUM(d); /* Quest vnum */ quest->qm = NOBODY; /* Questmaster rnum */ quest->flags = 0; /* Quest bitflags */ quest->type = AQ_UNDEFINED; /* Quest type */ quest->target = NOTHING; /* Quest target */ quest->prereq = NOTHING; /* Prerequisite object */ quest->value[0] = 0; /* Points for completing */ quest->value[1] = 0; /* Points for abandoning */ quest->value[2] = 0; /* Minimum level */ quest->value[3] = LVL_IMPL; /* Maximim level */ quest->value[4] = -1; /* Time limit */ quest->value[5] = NOBODY; /* Mob to return object */ quest->value[6] = 1; /* Quantity of targets */ quest->prev_quest = NOTHING; /* Previous quest */ quest->next_quest = NOTHING; /* Next quest */ quest->gold_reward= 0; /* Prize in gold coins */ quest->exp_reward = 0; /* Prize in exp points */ quest->obj_reward = NOTHING; /* vnum of reward object */ quest->name = strdup("Undefined Quest"); quest->desc = strdup("Quest definition is incomplete."); quest->info = strdup("There is no information on this quest.\r\n"); quest->done = strdup("You have completed the quest.\r\n"); quest->quit = strdup("You have abandoned the quest.\r\n"); quest->func = NULL; /* Secondary qm spec proc */ /* Set the descriptor OLC structure to point to this quest */ OLC_QUEST(d) = quest; /* Show the main quest edit menu */ qedit_disp_menu(d); } /*-------------------------------------------------------------------*/ static void qedit_setup_existing(struct descriptor_data *d, qst_rnum r_num) { /*. Alloc some quest shaped space . */ CREATE(OLC_QUEST(d), struct aq_data, 1); copy_quest(OLC_QUEST(d), aquest_table + r_num, FALSE); qedit_disp_menu(d); } /*-------------------------------------------------------------------*/ /************************************************************************** Menu functions **************************************************************************/ /*-------------------------------------------------------------------*/ /*. Display main menu . */ static void qedit_disp_menu(struct descriptor_data *d) { struct aq_data *quest; char quest_flags[MAX_STRING_LENGTH], buf2[MAX_STRING_LENGTH]; char targetname[MAX_STRING_LENGTH]; mob_vnum return_mob; quest = OLC_QUEST(d); clear_screen(d); sprintbit(quest->flags, aq_flags, quest_flags, sizeof(quest_flags)); if (quest->type == AQ_OBJ_RETURN) { if ((return_mob = real_mobile(quest->value[5])) != NOBODY) snprintf(buf2, sizeof(buf2), "to %s [%d]", mob_proto[return_mob].player.short_descr, quest->value[5]); else snprintf(buf2, sizeof(buf2), "to an unknown mob [%d].", quest->value[5]); } switch (quest->type) { case AQ_OBJ_FIND: case AQ_OBJ_RETURN: snprintf(targetname, sizeof(targetname), "%s", real_object(quest->target) == NOTHING ? "An unknown object" : obj_proto[real_object(quest->target)].short_description); break; case AQ_ROOM_FIND: case AQ_ROOM_CLEAR: snprintf(targetname, sizeof(targetname), "%s", real_room(quest->target) == NOWHERE ? "An unknown room" : world[real_room(quest->target)].name); break; case AQ_MOB_FIND: case AQ_MOB_KILL: case AQ_MOB_SAVE: snprintf(targetname, sizeof(targetname), "%s", real_mobile(quest->target) == NOBODY ? "An unknown mobile" : GET_NAME(&mob_proto[real_mobile(quest->target)])); break; default: snprintf(targetname, sizeof(targetname), "Unknown"); break; } write_to_output(d, "-- Quest Number : @n[@c%6d@n]\r\n" "@g 1@n) Quest Name : @y%s\r\n" "@g 2@n) Description : @y%s\r\n" "@g 3@n) Accept Message\r\n@y%s" "@g 4@n) Completion Message\r\n@y%s" "@g 5@n) Quit Message\r\n@y%s" "@g 6@n) Quest Flags : @c%s\r\n" "@g 7@n) Quest Type : @c%s %s\r\n" "@g 8@n) Quest Master : [@c%6d@n] @y%s\r\n" "@g 9@n) Quest Target : [@c%6d@n] @y%s\r\n" "@g A@n) Quantity : [@c%6d@n]\r\n" "@n Quest Point Rewards\r\n" "@g B@n) Completed : [@c%6d@n] @g C@n) Abandoned : [@c%6d@n]\r\n" "@n Other Rewards Rewards\r\n" "@g G@n) Gold Coins : [@c%6d@n] @g T@n) Exp Points : [@c%6d@n] @g O@n) Object : [@c%6d@n]\r\n" "@n Level Limits to Accept Quest\r\n" "@g D@n) Lower Level : [@c%6d@n] @g E@n) Upper Level : [@c%6d@n]\r\n" "@g F@n) Prerequisite : [@c%6d@n] @y%s\r\n" "@g L@n) Time Limit : [@c%6d@n]\r\n" "@g N@n) Next Quest : [@c%6d@n] @y%s\r\n" "@g P@n) Previous Quest : [@c%6d@n] @y%s\r\n" "@g X@n) Delete Quest\r\n" "@g Q@n) Quit\r\n" "Enter Choice : ", quest->vnum, quest->name, quest->desc, quest->info && (str_cmp(quest->info, "undefined")) ? quest->info : "Nothing\r\n", quest->done && (str_cmp(quest->done, "undefined")) ? quest->done : "Nothing\r\n", quest->quit && (str_cmp(quest->quit, "undefined")) ? quest->quit : "Nothing\r\n", quest_flags, quest_types[quest->type], quest->type == AQ_OBJ_RETURN ? buf2 : "", quest->qm == NOBODY ? -1 : quest->qm, real_mobile(quest->qm) == NOBODY ? "Invalid Mob" : mob_proto[(real_mobile(quest->qm))].player.short_descr, quest->target == NOBODY ? -1 : quest->target, targetname, quest->value[6], quest->value[0], quest->value[1], quest->gold_reward, quest->exp_reward, quest->obj_reward == NOTHING ? -1 : quest->obj_reward, quest->value[2], quest->value[3], quest->prereq == NOTHING ? -1 : quest->prereq, quest->prereq == NOTHING ? "" : real_object(quest->prereq) == NOTHING ? "an unknown object" : obj_proto[real_object(quest->prereq)].short_description, quest->value[4], quest->next_quest == NOTHING ? -1 : quest->next_quest, real_quest(quest->next_quest) == NOTHING ? "" : QST_DESC(real_quest(quest->next_quest)), quest->prev_quest == NOTHING ? -1 : quest->prev_quest, real_quest(quest->prev_quest) == NOTHING ? "" : QST_DESC(real_quest(quest->prev_quest))); OLC_MODE(d) = QEDIT_MAIN_MENU; } /* For sector type. */ void qedit_disp_type_menu(struct descriptor_data *d) { int counter, columns = 0; clear_screen(d); for (counter = 0; counter < NUM_AQ_TYPES; counter++) { write_to_output(d, "@g%2d@n) %-20.20s %s", counter, quest_types[counter], !(++columns % 2) ? "\r\n" : ""); } write_to_output(d, "\r\nEnter Quest type : "); OLC_MODE(d) = QEDIT_TYPES; } /* For quest flags. */ void qedit_disp_flag_menu(struct descriptor_data *d) { char bits[MAX_STRING_LENGTH]; int counter, columns = 0; get_char_colors(d->character); clear_screen(d); for (counter = 0; counter < NUM_AQ_FLAGS; counter++) { write_to_output(d, "%s%2d%s) %-20.20s %s", grn, counter + 1, nrm, aq_flags[counter], !(++columns % 2) ? "\r\n" : ""); } sprintbit(OLC_QUEST(d)->flags, aq_flags, bits, sizeof(bits)); write_to_output(d, "\r\nQuest flags: @c%s@n\r\n" "Enter quest flags, 0 to quit : ", bits); OLC_MODE(d) = QEDIT_FLAGS; } /************************************************************************** The GARGANTUAN event handler **************************************************************************/ void qedit_parse(struct descriptor_data *d, char *arg) { int number = atoi(arg); char *oldtext = NULL; switch (OLC_MODE(d)) { /*-------------------------------------------------------------------*/ case QEDIT_CONFIRM_SAVESTRING: switch (*arg) { case 'y': case 'Y': send_to_char(d->character, "Saving Quest to memory.\r\n"); qedit_save_internally(d); mudlog(CMP, MAX(LVL_BUILDER, GET_INVIS_LEV(d->character)), TRUE, "OLC: %s edits quest %d", GET_NAME(d->character), OLC_NUM(d)); if (CONFIG_OLC_SAVE) { qedit_save_to_disk(real_zone_by_thing(OLC_NUM(d))); write_to_output(d, "Quest %d saved to disk.\r\n", OLC_NUM(d)); } else write_to_output(d, "Quest %d saved to memory.\r\n", OLC_NUM(d)); cleanup_olc(d, CLEANUP_STRUCTS); return; case 'n': case 'N': cleanup_olc(d, CLEANUP_ALL); return; default: write_to_output(d, "Invalid choice!\r\nDo you wish to save the quest? : "); return; } break; /*-------------------------------------------------------------------*/ case QEDIT_CONFIRM_DELETE: switch (*arg) { case 'y': case 'Y': if (delete_quest(real_quest(OLC_NUM(d)))) write_to_output(d, "Quest deleted.\r\n"); else write_to_output(d, "Couldn't delete the quest!\r\n"); if (CONFIG_OLC_SAVE) { qedit_save_to_disk(real_zone_by_thing(OLC_NUM(d))); write_to_output(d, "Quest file saved to disk.\r\n"); } else write_to_output(d, "Quest file saved to memory.\r\n"); cleanup_olc(d, CLEANUP_ALL); return; case 'n': case 'N': qedit_disp_menu(d); return; default: write_to_output(d, "Invalid choice!\r\nDo you wish to delete the quest? : "); return; } break; /*-------------------------------------------------------------------*/ case QEDIT_MAIN_MENU: switch (*arg) { case 'q': case 'Q': if (OLC_VAL(d)) { /*. Anything been changed? . */ write_to_output(d, "Do you wish to save the changes to the Quest? (y/n) : "); OLC_MODE(d) = QEDIT_CONFIRM_SAVESTRING; } else cleanup_olc(d, CLEANUP_ALL); return; case 'x': case 'X': OLC_MODE(d) = QEDIT_CONFIRM_DELETE; write_to_output(d, "Do you wish to delete the Quest? (y/n) : "); break; case '1': OLC_MODE(d) = QEDIT_NAME; write_to_output(d, "Enter the quest name : "); break; case '2': OLC_MODE(d) = QEDIT_DESC; write_to_output(d, "Enter the quest description :-\r\n] "); break; case '3': OLC_MODE(d) = QEDIT_INFO; clear_screen(d); send_editor_help(d); write_to_output(d, "Enter quest acceptance message:\r\n\r\n"); if (OLC_QUEST(d)->info) { write_to_output(d, "%s", OLC_QUEST(d)->info); oldtext = strdup(OLC_QUEST(d)->info); } string_write(d, &OLC_QUEST(d)->info, MAX_QUEST_MSG, 0, oldtext); OLC_VAL(d) = 1; break; case '4': OLC_MODE(d) = QEDIT_COMPLETE; clear_screen(d); send_editor_help(d); write_to_output(d, "Enter quest completion message:\r\n\r\n"); if (OLC_QUEST(d)->done) { write_to_output(d, "%s", OLC_QUEST(d)->done); oldtext = strdup(OLC_QUEST(d)->done); } string_write(d, &OLC_QUEST(d)->done, MAX_QUEST_MSG, 0, oldtext); OLC_VAL(d) = 1; break; case '5': OLC_MODE(d) = QEDIT_ABANDON; clear_screen(d); send_editor_help(d); write_to_output(d, "Enter quest quit message:\r\n\r\n"); if (OLC_QUEST(d)->quit) { write_to_output(d, "%s", OLC_QUEST(d)->quit); oldtext = strdup(OLC_QUEST(d)->quit); } string_write(d, &OLC_QUEST(d)->quit, MAX_QUEST_MSG, 0, oldtext); OLC_VAL(d) = 1; break; case '6': OLC_MODE(d) = QEDIT_FLAGS; qedit_disp_flag_menu(d); break; case '7': OLC_MODE(d) = QEDIT_TYPES; qedit_disp_type_menu(d); break; case '8': OLC_MODE(d) = QEDIT_QUESTMASTER; write_to_output(d, "Enter vnum of quest master : "); break; case '9': OLC_MODE(d) = QEDIT_TARGET; write_to_output(d, "Enter target vnum : "); break; case 'a': case 'A': OLC_MODE(d) = QEDIT_QUANTITY; write_to_output(d, "Enter quantity of target : "); break; case 'b': case 'B': OLC_MODE(d) = QEDIT_POINTSCOMP; write_to_output(d, "Enter points for completing the quest : " ); break; case 'c': case 'C': OLC_MODE(d) = QEDIT_POINTSQUIT; write_to_output(d, "Enter points for quitting the quest : " ); break; case 'd': case 'D': OLC_MODE(d) = QEDIT_LEVELMIN; write_to_output(d, "Enter minimum level to accept the quest : " ); break; case 'e': case 'E': OLC_MODE(d) = QEDIT_LEVELMAX; write_to_output(d, "Enter maximum level to accept the quest : " ); break; case 'f': case 'F': OLC_MODE(d) = QEDIT_PREREQ; write_to_output(d, "Enter a prerequisite object vnum (-1 for none) : "); break; case 'g': case 'G': OLC_MODE(d) = QEDIT_GOLD; write_to_output(d, "Enter the number of gold coins (0 for none) : "); break; case 't': case 'T': OLC_MODE(d) = QEDIT_EXP; write_to_output(d, "Enter a number of experience points (0 for none) : "); break; case 'o': case 'O': OLC_MODE(d) = QEDIT_OBJ; write_to_output(d, "Enter the prize object vnum (-1 for none) : "); break; case 'l': case 'L': OLC_MODE(d) = QEDIT_TIMELIMIT; write_to_output(d, "Enter time limit to complete (-1 for none) : " ); break; case 'n': case 'N': OLC_MODE(d) = QEDIT_NEXTQUEST; write_to_output(d, "Enter vnum of next quest (-1 for none) : "); break; case 'p': case 'P': OLC_MODE(d) = QEDIT_PREVQUEST; write_to_output(d, "Enter vnum of previous quest (-1 for none) : "); break; default: write_to_output(d, "Invalid choice!\r\n"); qedit_disp_menu(d); break; } return; /*-------------------------------------------------------------------*/ case QEDIT_NAME: if (!genolc_checkstring(d, arg)) break; if (OLC_QUEST(d)->name) free(OLC_QUEST(d)->name); arg[MAX_QUEST_NAME - 1] = '\0'; OLC_QUEST(d)->name = str_udup(arg); break; case QEDIT_DESC: if (!genolc_checkstring(d, arg)) break; if (OLC_QUEST(d)->desc) free(OLC_QUEST(d)->desc); arg[MAX_QUEST_DESC - 1] = '\0'; OLC_QUEST(d)->desc = str_udup(arg); break; case QEDIT_QUESTMASTER: if (number != -1) if (real_mobile(number) == NOBODY) { write_to_output(d, "That mobile does not exist, try again : "); return; } OLC_QUEST(d)->qm = number; break; case QEDIT_TYPES: if (number < 0 || number >= NUM_AQ_TYPES) { write_to_output(d, "Invalid choice!\r\n"); qedit_disp_type_menu(d); return; } OLC_QUEST(d)->type = number; if (number == AQ_OBJ_RETURN) { OLC_MODE(d) = QEDIT_RETURNMOB; write_to_output(d, "Enter mob vnum to return object to : "); return; } break; case QEDIT_FLAGS: if (number < 0 || number > NUM_AQ_FLAGS) { write_to_output(d, "That is not a valid choice!\r\n"); qedit_disp_flag_menu(d); } else if (number == 0) break; else { TOGGLE_BIT(OLC_QUEST(d)->flags, number ); qedit_disp_flag_menu(d); } return; case QEDIT_QUANTITY: OLC_QUEST(d)->value[6] = LIMIT(number, 1, 50); break; case QEDIT_POINTSCOMP: OLC_QUEST(d)->value[0] = LIMIT(number, 0, 999999); break; case QEDIT_POINTSQUIT: OLC_QUEST(d)->value[1] = LIMIT(number, 0, 999999); break; case QEDIT_PREREQ: if ((number = atoi(arg)) != -1) if (real_object(number) == NOTHING) { write_to_output(d, "That object does not exist, try again : "); return; } OLC_QUEST(d)->prereq = number; break; case QEDIT_LEVELMIN: if (number < 0 || number > LVL_IMPL) { write_to_output(d, "Level must be between 0 and %d!\r\n", LVL_IMPL); write_to_output(d, "Enter minimum level to accept the quest : " ); return; } else if (number > OLC_QUEST(d)->value[3]) { write_to_output(d, "Minimum level can't be above maximum level!\r\n"); write_to_output(d, "Enter minimum level to accept the quest : " ); return; } else { OLC_QUEST(d)->value[2] = number; break; } case QEDIT_LEVELMAX: if (number < 0 || number > LVL_IMPL) { write_to_output(d, "Level must be between 0 and %d!\r\n", LVL_IMPL); write_to_output(d, "Enter maximum level to accept the quest : " ); return; } else if (number < OLC_QUEST(d)->value[2]) { write_to_output(d, "Maximum level can't be below minimum level!\r\n"); write_to_output(d, "Enter maximum level to accept the quest : " ); return; } else { OLC_QUEST(d)->value[3] = number; break; } case QEDIT_TIMELIMIT: OLC_QUEST(d)->value[4] = LIMIT(number, -1, 100); break; case QEDIT_RETURNMOB: if ((number = atoi(arg)) != -1) if (real_mobile(number) == NOBODY) { write_to_output(d, "That mobile does not exist, try again : "); return; } OLC_QUEST(d)->value[5] = number; break; case QEDIT_TARGET: OLC_QUEST(d)->target = number; break; case QEDIT_NEXTQUEST: if ((number = atoi(arg)) != -1) { if (real_quest(number) == NOTHING) { write_to_output(d, "That is not a valid quest, try again (-1 for none) : "); return; } } OLC_QUEST(d)->next_quest = (number == -1 ? NOTHING : atoi(arg)); break; case QEDIT_PREVQUEST: if ((number = atoi(arg)) != -1) { if (real_quest(number) == NOTHING) { write_to_output(d, "That is not a valid quest, try again (-1 for none) : "); return; } } OLC_QUEST(d)->prev_quest = (number == -1 ? NOTHING : atoi(arg)); break; case QEDIT_GOLD: OLC_QUEST(d)->gold_reward = LIMIT(number, 0, 99999); break; case QEDIT_EXP: OLC_QUEST(d)->exp_reward = LIMIT(number, 0, 99999); break; case QEDIT_OBJ: if ((number = atoi(arg)) != -1) if (real_object(number) == NOTHING) { write_to_output(d, "That object does not exist, try again : "); return; } OLC_QUEST(d)->obj_reward = number; break; default: /*. We should never get here . */ cleanup_olc(d, CLEANUP_ALL); mudlog(BRF, LVL_BUILDER, TRUE, "SYSERR: OLC: qedit_parse(): " "Reached default case!"); write_to_output(d, "Oops...\r\n"); break; } /*-------------------------------------------------------------------*/ /*. END OF CASE If we get here, we have probably changed something, and now want to return to main menu. Use OLC_VAL as a 'has changed' flag . */ OLC_VAL(d) = 1; qedit_disp_menu(d); } void qedit_string_cleanup(struct descriptor_data *d, int terminator) { switch (OLC_MODE(d)) { case QEDIT_INFO: case QEDIT_COMPLETE: case QEDIT_ABANDON: qedit_disp_menu(d); break; } }