dbx/cnf/
dbx/lib/
dbx/lib/misc/
dbx/lib/text/help/
dbx/lib/world/
dbx/lib/world/qst/
dbx/src/
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*  _TwyliteMud_ by Rv.                          Based on CircleMud3.0bpl9 *
*    				                                          *
*  OasisOLC - qedit.c 		                                          *
*    				                                          *
*  Copyright 1997 Mike Steinmann                                          *
*  Used at Morgaelin (mud.dwango.com 3000)				  *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*. Original author: Levork .*/

#include "conf.h"
#include "sysdep.h"
#include "structs.h"
#include "comm.h"
#include "utils.h"
#include "handler.h"
#include "interpreter.h"
#include "db.h"
#include "boards.h"
#include "olc.h"
#include "quest.h"

/*------------------------------------------------------------------------*/
/*. External data .*/

extern int      top_of_aquestt;
extern struct	aq_data *aquest_table;
extern struct   zone_data *zone_table;
extern char     *quest_types[];
extern char	*aq_flags[];
extern void	strip_string(char *buffer);

/*------------------------------------------------------------------------*/
/* function protos */
void qedit_setup_new(struct descriptor_data *d);
void qedit_setup_existing(struct descriptor_data *d, int real_num);
void qedit_save_internally(struct descriptor_data *d);
void qedit_save_to_disk(int znum);
void free_quest(struct aq_data *quest);
void qedit_disp_type_menu(struct descriptor_data *d);
void qedit_disp_menu(struct descriptor_data * d);
void qedit_parse(struct descriptor_data * d, char *arg);
void qedit_disp_flags_menu(struct descriptor_data *d);
void oedit_disp_val0_menu(struct descriptor_data *d);
void oedit_disp_val1_menu(struct descriptor_data *d);
void oedit_disp_val2_menu(struct descriptor_data *d);
void oedit_disp_val3_menu(struct descriptor_data *d);

/*------------------------------------------------------------------------*\
  Utils and exported functions.
\*------------------------------------------------------------------------*/

void smash_tilde(char *str)
{
  for (; *str != '\0'; str++) {
	 if (*str == '~')
		*str = '-';
	 if (*str == 'M')
		*str = ' ';
  }

  return;
}

void qedit_setup_new(struct descriptor_data *d)
{

  CREATE(OLC_QUEST(d), struct aq_data, 1);
  OLC_QUEST(d)->short_desc = str_dup("an unfinished quest");
  OLC_QUEST(d)->desc = str_dup("This is an unfinished quest.");
  OLC_QUEST(d)->info = str_dup("Information for unfinished quest.\r\n");
  OLC_QUEST(d)->ending = str_dup("Ending for unfinished quest.\r\n");
  OLC_QUEST(d)->next_quest = -1;
  qedit_disp_menu(d);
  OLC_VAL(d) = 0;
}

/*------------------------------------------------------------------------*/

void qedit_setup_existing(struct descriptor_data *d, int real_num)
{
  struct aq_data *quest;
  int i;

  /*. Build a copy of the quest .*/
  CREATE (quest, struct aq_data, 1);
  *quest = aquest_table[real_num];
  /* allocate space for all strings  */
  if (aquest_table[real_num].short_desc)
	 quest->short_desc = str_dup (aquest_table[real_num].short_desc);
  if (aquest_table[real_num].desc)
	 quest->desc = str_dup (aquest_table[real_num].desc);
  if (aquest_table[real_num].info)
	 quest->info = str_dup (aquest_table[real_num].info);
  if (aquest_table[real_num].ending)
	 quest->ending = str_dup (aquest_table[real_num].ending);
  quest->type = aquest_table[real_num].type;
  quest->mob_vnum = aquest_table[real_num].mob_vnum;
  quest->flags = aquest_table[real_num].flags;
  quest->target = aquest_table[real_num].target;
  quest->exp = aquest_table[real_num].exp;
  quest->next_quest = aquest_table[real_num].next_quest;
  for (i=0; i < 4; i++)
	 quest->value[i] = aquest_table[real_num].value[i];
  /*. Attach room copy to players descriptor .*/
  OLC_QUEST(d) = quest;
  OLC_VAL(d) = 0;
  qedit_disp_menu(d);
}

/*------------------------------------------------------------------------*/
void qedit_save_internally(struct descriptor_data *d)
{
  int i, quest_num, found = 0;
  struct aq_data *new_quest;

  quest_num = real_quest(OLC_NUM(d));
  if (quest_num >= 0)
  {
	 free_quest(aquest_table + quest_num);
	 aquest_table[quest_num] = *OLC_QUEST(d);
  } else {
	 /*. Quest doesn't exist, hafta add it .*/
	 CREATE(new_quest, struct aq_data, top_of_aquestt + 2);

	 /* count thru quest tables */
	 for (i = 0; i <= top_of_aquestt; i++)
	 {
		if (!found) {
		  /*. Is this the place? .*/
		  if (aquest_table[i].virtual > OLC_NUM(d))
	{
	  found = 1;

	  new_quest[i] = *(OLC_QUEST(d));
	  new_quest[i].virtual = OLC_NUM(d);
			 quest_num  = i;
			 new_quest[i + 1] = aquest_table[i];

		  } else {
	  new_quest[i] = aquest_table[i];
		  }
		} else
		{ /*. Already been found  .*/
		  new_quest[i + 1] = aquest_table[i];
		}
	 }
	 if (!found)
	 { /*. Still not found, insert at top of table .*/
		new_quest[i] = *(OLC_QUEST(d));
		new_quest[i].virtual = OLC_NUM(d);
		quest_num  = i;
	 }

	 /* copy quest table over */
	 free(aquest_table);
	 aquest_table = new_quest;
	 top_of_aquestt++;

  }
  olc_add_to_save_list(zone_table[OLC_ZNUM(d)].number, OLC_SAVE_QUEST);
}


/*------------------------------------------------------------------------*/

void qedit_save_to_disk(int znum)
{
  int counter, realcounter;
  FILE *fp;
  struct aq_data *quest;
  char buf3[MAX_STRING_LENGTH];
  char buf4[MAX_STRING_LENGTH];

  sprintf(buf, "%s/%d.qst", QST_PREFIX, zone_table[znum].number);
  if (!(fp = fopen(buf, "w+")))
  { mudlog("SYSERR: OLC: Cannot open quest file!", BRF, LVL_BUILDER, TRUE);
	 return;
  }

  for (counter = zone_table[znum].number * 100;
		 counter <= zone_table[znum].top;
		 counter++)
  { realcounter = real_quest(counter);
	 if (realcounter >= 0)
	 {
		quest = (aquest_table + realcounter);
		strcpy(buf1, quest->short_desc ? quest->short_desc : "an unfinished quest");
		smash_tilde(buf1);
		strcpy(buf2, quest->desc ? quest->desc : "This is an unfinished quest.");
		smash_tilde(buf2);
		strcpy(buf3, quest->info ? quest->info : "Information for an unfinished quest.\r\n");
		strip_string(buf3);
		smash_tilde(buf3);
		strcpy(buf4, quest->ending ? quest->ending : "There is no ending!\r\n");
		strip_string(buf4);
		smash_tilde(buf4);

		/*. Build a buffer ready to save .*/
		sprintf(buf, "#%d\n%s~\n%s~\n%s~\n%s~\n%d %d %ld %d %d %d\n",
				counter, buf1, buf2, buf3, buf4,
				quest->type, quest->mob_vnum,
				quest->flags, quest->target, quest->exp, quest->next_quest
		);
		/*. Save this section .*/
		fputs(buf, fp);

		sprintf(buf, "%d %d %d %d\n", quest->value[0], quest->value[1],
			quest->value[2], quest->value[3]);
		fputs(buf, fp);

		fprintf(fp, "S\n");
	 }
  }
  /* write final line and close */
  fprintf(fp, "$~\n");
  fclose(fp);
  olc_remove_from_save_list(zone_table[znum].number, OLC_SAVE_QUEST);
}

/*------------------------------------------------------------------------*/

void free_quest(struct aq_data *quest)
{
  if (quest->desc)
	 free(quest->desc);
  if (quest->short_desc)
	 free(quest->short_desc);
  if (quest->info)
	 free(quest->info);
  if (quest->ending)
	 free(quest->ending);
}

/**************************************************************************
 Menu functions
 **************************************************************************/

void qedit_disp_flags_menu(struct descriptor_data * d)
{ int counter, columns = 0;

  get_char_cols(d->character);
  send_to_char("", d->character);
  for (counter = 0; counter < NUM_AQ_FLAGS; counter++)
  { sprintf(buf, "%s%2d%s) %-20.20s ",
		 grn, counter + 1, nrm, aq_flags[counter]);
	 if(!(++columns % 2))
		strcat(buf, "\r\n");
	 send_to_char(buf, d->character);
  }
  sprintbit(OLC_QUEST(d)->flags, aq_flags, buf1);
  sprintf(buf,
	"\r\nQuest flags: %s%s%s\r\n"
	"Enter quest flags, 0 to quit : ",
	cyn, buf1, nrm
  );
  send_to_char(buf, d->character);
  OLC_MODE(d) = QEDIT_FLAGS;
}


void qedit_disp_type_menu(struct descriptor_data *d)
{
  int counter, columns = 0;

  send_to_char("", d->character);
  for (counter = 0; counter < NUM_AQ_TYPES; counter++) {
	 sprintf(buf, "%s%2d%s) %-20.20s ",
			 cyn, counter, nrm, quest_types[counter]);
	 if(!(++columns % 2))
		strcat(buf, "\r\n");
	 send_to_char(buf, d->character);
  }
  send_to_char("\r\nEnter quest type : ", d->character);
  OLC_MODE(d) = QEDIT_TYPE;
}

void qedit_disp_val0_menu(struct descriptor_data *d)
{
  OLC_MODE(d) = QEDIT_VALUE_0;
  switch(OLC_QUEST(d)->type) {
	 case AQ_RETURN_OBJ:
		send_to_char("Enter vnum of mob to receive object: ", d->character);
		break;
	 default:
		qedit_disp_menu(d);
  }
}

void qedit_disp_val1_menu(struct descriptor_data *d)
{
  OLC_MODE(d) = QEDIT_VALUE_1;
  switch(OLC_QUEST(d)->type) {
	 default:
		qedit_disp_menu(d);
  }
}

void qedit_disp_val2_menu(struct descriptor_data *d)
{
  OLC_MODE(d) = QEDIT_VALUE_2;
  switch(OLC_QUEST(d)->type) {
	 default:
		qedit_disp_menu(d);
  }
}

void qedit_disp_val3_menu(struct descriptor_data *d)
{
  OLC_MODE(d) = QEDIT_VALUE_3;
  switch(OLC_QUEST(d)->type) {
	 default:
		qedit_disp_menu(d);
  }
}

/* the main menu */
void qedit_disp_menu(struct descriptor_data * d)
{
  struct aq_data *quest;
  extern struct char_data *mob_proto;

  get_char_cols(d->character);
  quest = OLC_QUEST(d);

  sprintbit(quest->flags, aq_flags, buf1);
  sprintf(buf2, "%d %d %d %d", quest->value[0], quest->value[1], quest->value[2],
	quest->value[3]);
  sprintf(buf,
	""
	"-- Quest number : [%s%d%s]  	Quest zone: [%s%d%s]\r\n"
	"%s1%s) Name        : %s%s%s\r\n"
	"%s2%s) Description :\r\n%s%s%s\r\n"
	"%s3%s) Information :\r\n%s%s%s"
	"%s4%s) Ending      :\r\n%s%s%s"
		  "%s5%s) Questmaster : %s%d%s -- %s%s%s\r\n"
		  "%s6%s) Type        : %s%s%s\r\n"
		  "%s7%s) Flags       : %s%s%s\r\n"
		  "%s8%s) Target vnum : %s%d%s\r\n"
		  "%s9%s) Experience  : %s%d%s\r\n"
		  "%sA%s) Next quest  : %s%d%s\r\n"
		  "%sB%s) Values      : %s%s%s\r\n"
	"%sQ%s) Quit\r\n"
	"Enter choice : ",

	cyn, OLC_NUM(d), nrm,
	cyn, zone_table[OLC_ZNUM(d)].number, nrm,
	cyn, nrm, grn, quest->short_desc, nrm,
	cyn, nrm, grn, quest->desc, nrm,
	cyn, nrm, grn, quest->info, nrm,
	cyn, nrm, grn, quest->ending, nrm,
	cyn, nrm, grn, quest->mob_vnum, nrm, grn,
	real_mobile(quest->mob_vnum) > -1 ? mob_proto[real_mobile(quest->mob_vnum)].player.short_descr : "None", nrm,
	cyn, nrm, grn, quest_types[quest->type], nrm,
	cyn, nrm, grn, buf1, nrm,
	cyn, nrm, grn, quest->target, nrm,
	cyn, nrm, grn, quest->exp, nrm,
	cyn, nrm, grn, quest->next_quest, nrm,
	cyn, nrm, grn, buf2, nrm,
	cyn, nrm
  );
  send_to_char(buf, d->character);

  OLC_MODE(d) = QEDIT_MAIN_MENU;
}



/**************************************************************************
  The main loop
 **************************************************************************/

void qedit_parse(struct descriptor_data * d, char *arg)
{
  extern struct aq_data *aquest_table;
  int number=0;

  switch (OLC_MODE(d)) {
  case QEDIT_CONFIRM_SAVESTRING:
	 switch (*arg) {
	 case 'y':
	 case 'Y':
		qedit_save_internally(d);
		sprintf(buf, "OLC: %s edits quest %d", GET_NAME(d->character), OLC_NUM(d));
		mudlog(buf, CMP, LVL_BUILDER, TRUE);
		/*. Do NOT free strings! just the room structure .*/
		cleanup_olc(d, CLEANUP_STRUCTS);
		send_to_char("Quest saved to memory.\r\n", d->character);
		break;
	 case 'n':
	 case 'N':
		/* free everything up, including strings etc */
		cleanup_olc(d, CLEANUP_ALL);
		break;
	 default:
		send_to_char("Invalid choice!\r\n", d->character);
		send_to_char("Do you wish to save this quest internally? : ", d->character);
		break;
	 }
	 return;

  case QEDIT_MAIN_MENU:
	 switch (*arg) {
	 case 'q':
	 case 'Q':
		if (OLC_VAL(d))
		{ /*. Something has been modified .*/
		  send_to_char("Do you wish to save this quest internally? : ", d->character);
		  OLC_MODE(d) = QEDIT_CONFIRM_SAVESTRING;
		} else
		  cleanup_olc(d, CLEANUP_ALL);
		return;
	 case '1':
		send_to_char("Enter quest name:-\r\n| ", d->character);
		OLC_MODE(d) = QEDIT_NAME;
		break;
	 case '2':
		send_to_char("Enter quest description:-\r\n| ", d->character);
		OLC_MODE(d) = QEDIT_DESC;
		break;
	 case '3':
		OLC_MODE(d) = QEDIT_INFO;
		#if defined(CLEAR_SCREEN)
		  SEND_TO_Q("\x1B[H\x1B[J", d);
		#endif
		SEND_TO_Q("Enter quest information: (/s saves /h for help)\r\n\r\n", d);
		d->backstr = NULL;
		if (OLC_QUEST(d)->info) {
		  SEND_TO_Q(OLC_QUEST(d)->info, d);
		  d->backstr = str_dup(OLC_QUEST(d)->info);
		}
		d->str = &OLC_QUEST(d)->info;
		d->max_str = MAX_QUEST_INFO;
		d->mail_to = 0;
		OLC_VAL(d) = 1;
		break;
	 case '4':
		OLC_MODE(d) = QEDIT_ENDING;
		#if defined(CLEAR_SCREEN)
		  SEND_TO_Q("\x1B[H\x1B[J", d);
		#endif
		SEND_TO_Q("Enter quest ending: (/s saves /h for help)\r\n\r\n", d);
		d->backstr = NULL;
		if (OLC_QUEST(d)->ending) {
		  SEND_TO_Q(OLC_QUEST(d)->ending, d);
		  d->backstr = str_dup(OLC_QUEST(d)->ending);
		}
		d->str = &OLC_QUEST(d)->ending;
		d->max_str = MAX_QUEST_ENDING;
		d->mail_to = 0;
		OLC_VAL(d) = 1;
		break;
	 case '5':
		send_to_char("Enter questmaster vnum: ", d->character);
		OLC_MODE(d) = QEDIT_QUESTMASTER;
		break;
	 case '6':
		qedit_disp_type_menu(d);
		break;
	 case '7':
		qedit_disp_flags_menu(d);
		break;
	 case '8':
		send_to_char("Enter target vnum: ", d->character);
		OLC_MODE(d) = QEDIT_TARGET;
		break;
	 case '9':
		send_to_char("Enter experience: ", d->character);
		OLC_MODE(d) = QEDIT_EXP;
		break;
	 case 'a':
	 case 'A':
		send_to_char("Next quest (-1 to end): ", d->character);
		OLC_MODE(d) = QEDIT_NEXT;
		break;
	 case 'b':
	 case 'B':
		OLC_QUEST(d)->value[0] = 0;
		OLC_QUEST(d)->value[1] = 0;
		OLC_QUEST(d)->value[2] = 0;
		OLC_QUEST(d)->value[3] = 0;
		qedit_disp_val0_menu(d);
		break;
	 default:
		send_to_char("Invalid choice!", d->character);
		qedit_disp_menu(d);
		break;
	 }
	 return;

  case QEDIT_NAME:
	 if (OLC_QUEST(d)->short_desc)
		free(OLC_QUEST(d)->short_desc);
	 if (strlen(arg) > MAX_QUEST_NAME)
		arg[MAX_QUEST_NAME -1] = 0;
	 OLC_QUEST(d)->short_desc = str_dup(arg);
	 break;

  case QEDIT_DESC:
	 if (OLC_QUEST(d)->desc)
		free(OLC_QUEST(d)->desc);
	 if (strlen(arg) > 80)
		arg[79] = 0;
	 OLC_QUEST(d)->desc = str_dup(arg);
	 break;

  case QEDIT_INFO:
	 /*
	  * We will NEVER get here, we hope.
	  */
	 mudlog("SYSERR: Reached QEDIT_INFO case in parse_qedit", BRF, LVL_BUILDER, TRUE);
	 break;

  case QEDIT_ENDING:
	 /*
	  * We will NEVER get here, we hope.
	  */
	 mudlog("SYSERR: Reached QEDIT_ENDING case in parse_qedit", BRF, LVL_BUILDER, TRUE);
	 break;

  case QEDIT_QUESTMASTER:
	 number = atoi(arg);
	 if (real_mobile(number) >= 0)
		OLC_QUEST(d)->mob_vnum = number;
	 else
		OLC_QUEST(d)->mob_vnum = -1;
	 break;

  case QEDIT_TYPE:
	 number = atoi(arg);
	 if (number < 0 || number >= NUM_AQ_TYPES) {
		send_to_char("Invalid choice!", d->character);
		qedit_disp_type_menu(d);
		return;
	 } else
		OLC_QUEST(d)->type = number;
	 break;

  case QEDIT_FLAGS:
	 number = atoi(arg);
	 if ((number < 0) || (number > NUM_AQ_FLAGS)) {
		send_to_char("That's not a valid choice!\r\n", d->character);
		qedit_disp_flags_menu(d);
	 } else {
		if (number == 0)
		  break;
		else {
	/* toggle bits */
	if (IS_SET(OLC_QUEST(d)->flags, 1 << (number - 1)))
	  REMOVE_BIT(OLC_QUEST(d)->flags, 1 << (number - 1));
	else
	  SET_BIT(OLC_QUEST(d)->flags, 1 << (number - 1));
	qedit_disp_flags_menu(d);
		}
	 }
	 return;

  case QEDIT_TARGET:
	 number = atoi(arg);
	 OLC_QUEST(d)->target = MAX(0, number);
	 break;

  case QEDIT_EXP:
	 number = atoi(arg);
	 OLC_QUEST(d)->exp = MAX(0, MIN(number, 100000));
	 break;

  case QEDIT_NEXT:
	 number = atoi(arg);
	 if (real_quest(number) >= 0)
		OLC_QUEST(d)->next_quest = number;
	 else
		OLC_QUEST(d)->next_quest = -1;
	 break;

  case QEDIT_VALUE_0:
	 number = atoi(arg);
	 switch (OLC_QUEST(d)->type) {
		case AQ_RETURN_OBJ:
		  if (real_mobile(number) < 0)
			 number = 0;
		  break;
	 }
	 OLC_QUEST(d)->value[0] = number;
	 qedit_disp_val1_menu(d);
	 return;

  case QEDIT_VALUE_1:
	 OLC_QUEST(d)->value[1] = atoi(arg);
	 qedit_disp_val2_menu(d);
	 return;

  case QEDIT_VALUE_2:
	 OLC_QUEST(d)->value[2] = atoi(arg);
	 qedit_disp_val3_menu(d);
	 return;

  case QEDIT_VALUE_3:
	 OLC_QUEST(d)->value[3] = atoi(arg);
	 break;

  default:
	 /* we should never get here */
	 mudlog("SYSERR: Reached default case in parse_qedit",BRF,LVL_BUILDER,TRUE);
	 break;
  }
  /*. If we get this far, something has be changed .*/
  OLC_VAL(d) = 1;
  qedit_disp_menu(d);
}