#include "conf.h"
#include "sysdep.h"
#include "structs.h"
#include "utils.h"
#include "db.h"
#include "comm.h"
#include "interpreter.h"
#include "oasis.h"
#include "quest.h"
#include "boards.h"
#include "improved-edit.h"
/* Structs */
extern struct quest_data *quest;
extern struct descriptor_data *descriptor_list;
/* Functions */
void qedit_setup_existing(struct descriptor_data *d);
void qedit_setup_new(struct descriptor_data *d);
void qedit_disp_menu(struct descriptor_data *d);
void qedit_parse(struct descriptor_data *d, char *arg);
void qedit_update(struct descriptor_data *d);
void free_quest_strings(struct quest_data *free_quest);
void free_tasks(struct task_data *head);
void copy_quest_strings(struct quest_data *dest, struct quest_data *source);
void copy_tasks(struct task_data **to, struct task_data *from);
int count_tasks(struct quest_data *targ_quest);
struct task_data *get_last_task(struct quest_data *targ_quest);
struct task_data *get_num_task(int num, struct quest_data *targ_quest);
void qedit_string_cleanup(struct descriptor_data *d, int terminator);
int count_hash_records(FILE * fl);
char *str_udup(const char *);
/* Global Definitions */
int top_quest = -1;
/* ACMD's */
ACMD(do_qedit);
ACMD(do_qlist);
ACMD(do_quests);
void save_quests(void)
{
FILE *f;
int i;
struct quest_data *sav_quest;
void strip_cr(char *);
/* Open file */
if(!(f = fopen(QUEST_FILE, "wb"))) {
log("SYSERR: quest file does not exist or is unusable.");
return;
}
/* Interate through quests, saving each */
for (i = 0; i <= top_quest; i++) {
sav_quest = (quest + i);
/* Write Header data to quest file buffer */
fprintf(f, "#%d\n"
"%s%c\n",
sav_quest->number,
sav_quest->name ? sav_quest->name : "Default Quest Name",
STRING_TERMINATOR);
/* Write out the quest task descriptions */
if (sav_quest->task) {
struct task_data *sav_task;
for (sav_task = sav_quest->task; sav_task; sav_task = sav_task->next) {
strcpy(buf, sav_task->description);
strip_cr(buf);
fprintf(f, "T\n"
"%s~\n", buf);
}
}
}
fprintf(f, "$\n");
fclose(f);
}
void boot_quests(FILE *f, int nr) {
int rec_count = 0;
int quest_nr = 0;
char line[256];
struct task_data *new_task;
struct task_data *prev_task = NULL;
/* Open file */
if(!(f = fopen(QUEST_FILE, "rb"))) {
log("SYSERR: quest file does not exist or is unusable.");
return;
}
/* Allocate Storage for thequests */
rec_count = count_hash_records(f);
CREATE(quest, struct quest_data, rec_count);
/* Step through file loading quests */
rewind(f);
for (;;) {
if (!get_line(f, line)) {
if (nr == -1) {
log("SYSERR: Quest file is empty");
exit(1);
} }
if (*line == '$')
return;
if (*line == '#') {
sscanf(line, "#%d", &quest_nr);
quest[quest_nr].name = fread_string(f, buf);
quest[quest_nr].number = quest_nr;
top_quest++;
prev_task = NULL;
}
if (*line == 'T') {
CREATE(new_task, struct task_data, 1);
new_task->description = fread_string(f, buf);
new_task->next = NULL;
if (prev_task == NULL)
quest[quest_nr].task = new_task;
else
prev_task->next = new_task;
prev_task = new_task;
}
}
log("Done");
}
/**************************************************
* Quest editor OLC intergration
**************************************************/
ACMD(do_qedit) {
int quest_num;
struct descriptor_data *d;
/* Parse Arguments */
two_arguments(argument, buf1, buf2);
if (!*buf1) {
send_to_char("Specify a Quest to edit\r\n", ch);
return;
}
/* Request to save changes */
if (str_cmp("save", buf1) == 0) {
save_quests();
return;
}
if (isdigit(*buf1))
quest_num = atoi(buf1);
else {
send_to_char("Watch what you're doing bub!\r\n", ch);
return; }
/*
* Check that 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) == quest_num) {
send_to_char("That quest is being edited", ch);
return;
}
d = ch->desc;
/*
* Give descriptor an OLC structure.
*/
if (d->olc) {
mudlog("SYSERR: do_oasis: Player already had olc structure.", BRF, LVL_IMMORT, TRUE);
free(d->olc);
}
CREATE(d->olc, struct oasis_olc_data, 1);
/* Set Olc State */
OLC_NUM(d) = quest_num;
OLC_MODE(d) = QEDIT_MAIN_MENU;
STATE(d) = CON_QEDIT;
/* Setup editor struct */
if (OLC_NUM(d) > top_quest)
qedit_setup_new(d);
else
qedit_setup_existing(d);
act("$n starts to edit a quest.", TRUE, ch, 0, 0, TO_ROOM);
SET_BIT(PLR_FLAGS(ch), PLR_WRITING);
}
void qedit_parse(struct descriptor_data *d, char *arg)
{
char *oldtext = NULL;
struct task_data *last_task;
struct task_data *new_task;
switch (OLC_MODE(d)) {
case QEDIT_CONFIRM_SAVE:
switch (*arg) {
case 'y':
case 'Y':
qedit_update(d);
sprintf(buf, "OLC: %s edits quest %d.", GET_NAME(d->character), OLC_NUM(d));
mudlog(buf, CMP, MAX(LVL_GRGOD, GET_INVIS_LEV(d->character)), TRUE);
/*
* Do NOT free strings! Just the quest structure.
*/
cleanup_olc(d, CLEANUP_STRUCTS);
break;
case 'n':
case 'N':
/*
* Free everything up, including strings, etc.
*/
cleanup_olc(d, CLEANUP_ALL);
break;
default:
SEND_TO_Q("Invalid choice!\r\nDo you wish to save this quest internally? : ", d);
break;
}
return;
break;
case QEDIT_MAIN_MENU:
switch (*arg) {
case 'q':
case 'Q':
if (OLC_VAL(d)) { /* Something has been modified. */
SEND_TO_Q("Do you wish to save this quest internally? : ", d);
OLC_MODE(d) = QEDIT_CONFIRM_SAVE;
} else
cleanup_olc(d, CLEANUP_ALL);
return;
break;
case 'c':
case 'C':
SEND_TO_Q("Enter quest name:-\r\n] ", d);
OLC_MODE(d) = QEDIT_NAME;
break;
case 'e':
case 'E':
SEND_TO_Q("Edit which task number: ", d);
OLC_MODE(d) = QEDIT_TASK_EDIT;
return;
break;
case 'n':
case 'N':
send_editor_help(d);
SEND_TO_Q("Enter the new task's description:\r\n\r\n", d);
OLC_MODE(d) = QEDIT_TASK_NEW;
CREATE(new_task, struct task_data, 1);
new_task->next = NULL;
oldtext = str_dup("An Unfinished Task\r\n");
SEND_TO_Q("&yAn Unfinished Task\r\n&n", d);
string_write(d, &new_task->description, MAX_MESSAGE_LENGTH,0,oldtext);
last_task = get_last_task(OLC_QUEST(d));
if (last_task == NULL)
OLC_QUEST(d)->task = new_task;
else last_task->next = new_task;
OLC_VAL(d) = 1;
break;
default:
SEND_TO_Q("Invalid choice!", d);
qedit_disp_menu(d);
break;
}
return;
break;
case QEDIT_NAME:
if (OLC_QUEST(d)->name)
free(OLC_QUEST(d)->name);
arg[MAX_ROOM_NAME - 1] = '\0';
OLC_QUEST(d)->name = str_udup(arg);
qedit_disp_menu(d);
break;
case QEDIT_TASK_EDIT:
OLC_VAL(d) = atoi(arg);
if ( (OLC_VAL(d) < 1) || (OLC_VAL(d) > count_tasks(OLC_QUEST(d))) ) {
SEND_TO_Q("Invalid or Nonexistant task number!\r\n", d);
qedit_disp_menu(d);
break; }
clear_screen(d);
send_editor_help(d);
SEND_TO_Q("Edit task description:\r\n\r\n", d);
new_task = get_num_task(OLC_VAL(d), OLC_QUEST(d));
if (new_task->description)
SEND_TO_Q(new_task->description, d);
oldtext = str_dup(new_task->description);
string_write(d,&new_task->description,MAX_MESSAGE_LENGTH,0,oldtext);
return;
break;
default:
/*
* We should never get here.
*/
mudlog("SYSERR: Reached default case in parse_qedit", BRF, LVL_GRGOD,TRUE);
break;
}
/*
* If we get this far, something has been changed.
*/
OLC_VAL(d) = 1;
}
void qedit_disp_menu(struct descriptor_data *d) {
struct task_data *cur_task;
int i = 0;
sprintf(buf,
#if defined(CLEAR_SCREEN)
"^[[H^[[J"
#endif
"\r\n &cQuest Editor V1.0\r\n"
"_______________________\r\n"
"&n Quest [&c%d&n] [&c%s&n]\r\n",
OLC_QUEST(d)->number, OLC_QUEST(d)->name);
send_to_char(buf, d->character);
/* List taks if any */
sprintf(buf, "\r\n____Task List____\r\n");
send_to_char(buf, d->character);
if (OLC_QUEST(d)->task != NULL) {
for (cur_task = OLC_QUEST(d)->task; cur_task; cur_task = cur_task->next) {
i++;
sprintf(buf, "&c%d&n) %s", i, cur_task->description);
send_to_char(buf, d->character);
}
} else send_to_char("&c[&nNo tasks&c]&n\r\n", d->character);
send_to_char("\r\nC&c)&n Change Quest Name\r\n", d->character);
send_to_char("E&c)&n Edit a task\r\n", d->character);
send_to_char("N&c)&n New Task\r\n", d->character);
send_to_char("Q&c)&n Quit\r\n", d->character);
send_to_char("Choice: ", d->character);
OLC_MODE(d) = QEDIT_MAIN_MENU;
}
void qedit_setup_new(struct descriptor_data *d) {
CREATE(OLC_QUEST(d), struct quest_data, 1);
/* Setup Default Values */
OLC_QUEST(d)->number = OLC_NUM(d);
OLC_QUEST(d)->name = str_dup("Unfinished Quest");
OLC_QUEST(d)->task = NULL;
OLC_VAL(d) = 0;
qedit_disp_menu(d);
}
void qedit_setup_existing(struct descriptor_data *d) {
CREATE(OLC_QUEST(d), struct quest_data, 1);
/* Setup Default Values */
OLC_QUEST(d)->number = OLC_NUM(d);
OLC_QUEST(d)->name = str_udup(quest[OLC_NUM(d)].name);
/*
* Extra descriptions, if necessary.
*/
if (quest[OLC_NUM(d)].task) {
struct task_data *tdesc, *temp, *temp2;
CREATE(temp, struct task_data, 1);
OLC_QUEST(d)->task = temp;
for (tdesc = quest[OLC_NUM(d)].task; tdesc; tdesc = tdesc->next) {
temp->description = str_dup(tdesc->description);
if (tdesc->next) {
CREATE(temp2, struct task_data, 1);
temp->next = temp2;
temp = temp2;
} else
temp->next = NULL;
}
}
OLC_VAL(d) = 0;
qedit_disp_menu(d);
}
void qedit_update(struct descriptor_data *d) {
/* New Quest */
if (OLC_NUM(d) > top_quest) {
RECREATE(quest, struct quest_data, top_quest +2);
top_quest++;
}
quest[OLC_NUM(d)].number = OLC_NUM(d);
quest[OLC_NUM(d)].task = NULL;
copy_quest_strings(&quest[OLC_NUM(d)], OLC_QUEST(d));
send_to_char("Quest was saved to memory.\r\n", d->character);
}
ACMD(do_qlist) {
int i;
for (i=0; i <= top_quest; i++) {
sprintf(buf, "Quest Number [%d]\r\n"
"Quest Name [%s]\r\n",
i, quest[i].name);
send_to_char(buf, ch);
}
}
void free_quest_strings(struct quest_data *free_quest)
{
if (free_quest->name)
free(free_quest->name);
if (free_quest->task)
free_tasks(free_quest->task);
}
void free_tasks(struct task_data *head)
{
struct task_data *this_one, *next_one;
if (!head) {
log("free_taskss: NULL pointer or NULL data.");
return;
}
for (this_one = head; this_one; this_one = next_one) {
next_one = this_one->next;
if (this_one->description)
free(this_one->description);
free(this_one);
}
}
void copy_quest_strings(struct quest_data *dest, struct quest_data *source)
{
if (dest == NULL || source == NULL) {
log("SYSERR: Qedit: copy_quest_strings: NULL values passed.");
return;
}
dest->name = str_dup(source->name);
if (source->task)
copy_tasks(&dest->task, source->task);
}
void copy_tasks(struct task_data **to, struct task_data *from)
{
struct task_data *wpos;
CREATE(*to, struct task_data, 1);
wpos = *to;
for (; from; from = from->next, wpos = wpos->next) {
wpos->description = str_dup(from->description);
if (from->next)
CREATE(wpos->next, struct task_data, 1);
}
}
int count_tasks(struct quest_data *targ_quest) {
int i = 1;
struct task_data *cnt_task;
cnt_task = targ_quest->task;
if (!cnt_task)
return 0;
while (cnt_task->next != NULL) {
i++;
cnt_task = cnt_task->next;
}
return i;
}
struct task_data *get_last_task(struct quest_data *targ_quest) {
struct task_data *last_task;
last_task = targ_quest->task;
if (!last_task)
return NULL;
while (last_task->next) {
last_task = last_task->next;
}
return last_task;
}
struct task_data *get_num_task(int num, struct quest_data *targ_quest) {
struct task_data *num_task;
int i = 1;
num_task = targ_quest->task;
if (!num_task)
return NULL;
while (i != num) {
num_task = num_task->next;
i++;
}
return num_task;
}
void qedit_string_cleanup(struct descriptor_data *d, int terminator)
{
qedit_disp_menu(d);
}
ACMD(do_quests) {
char outmsg[MAX_STRING_LENGTH];
int i = 0;
int num_found = 0;
struct task_data *tmp_task;
/* Display number of quest points. */
if (GET_QUEST_POINTS(ch)) {
sprintf(outmsg, "You have accumulated &c[&w%d&c]&n quest points.\r\n", GET_QUEST_POINTS(ch));
send_to_char(outmsg, ch);
} else { send_to_char("You have not earned any quest points.\r\n", ch); }
/* See if they have accepted any quests */
for (i = 0; i < (NUM_OF_QUESTS); i++) {
if (GET_QUEST(ch, i) != 0)
num_found++; }
/* Ok, there are quests, list them and their status */
if (num_found) {
send_to_char("You have accepted the following quests:\r\n\r\n", ch);
for (i = 1; i <= top_quest; i++) {
/* Char has quest, list it */
if (GET_QUEST(ch, i) != 0) {
/* List Quest title and state */
sprintf(outmsg, "%-31s (%s)\r\n",quest[i].name,
((GET_QUEST(ch, i) == 127) ? "&rRejected&n" :
(GET_QUEST(ch,i) == -1) ? "&cCompleted&n" : "&cUnfinished&n"));
send_to_char(outmsg, ch);
/* List current task if quest not completed */
if ( (GET_QUEST(ch,i) > 0) && (GET_QUEST(ch,i) < 127) ) {
tmp_task = get_num_task(GET_QUEST(ch,i), &quest[i]);
sprintf(outmsg, "%s\r\n",
tmp_task->description);
send_to_char(outmsg, ch); }
}
}
} else
send_to_char("You have no quests accepted or completed.\r\n",ch);
return; }