/**************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* In order to use any part of this Merc Diku Mud, you must comply with *
* both the original Diku license in 'license.doc' as well the Merc *
* license in 'license.txt'. In particular, you may not remove either of *
* these copyright notices. *
* *
* Much time and thought has gone into this software and you are *
* benefiting. We hope that you share your changes too. What goes *
* around, comes around. *
***************************************************************************
* ROM 2.4 is copyright 1993-1998 Russ Taylor *
* ROM has been brought to you by the ROM consortium *
* Russ Taylor (rtaylor@hypercube.org) *
* Gabrielle Taylor (gtaylor@hypercube.org) *
* Brian Moore (zump@rom.org) *
* By using this code, you have agreed to follow the terms of the *
* ROM license, in the file Rom24/doc/rom.license *
***************************************************************************
* 1stMUD ROM Derivative (c) 2001-2002 by Ryan Jennings *
* http://1stmud.dlmud.com/ <r-jenn@shaw.ca> *
***************************************************************************/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "recycle.h"
typedef struct gquest_hist GQUEST_HIST;
struct gquest_hist
{
GQUEST_HIST *next;
const char *short_descr;
const char *text;
};
GQUEST_HIST *gqhist_first = NULL;
bool save_gquest_data (void)
{
FILE *fp;
char buf[MIL];
int i;
if (!(fp = file_open (GQUEST_FILE, "w")))
{
sprintf (log_buf,
"save_gquest_data: Could not open file %s in order to save mud data.",
buf);
bug (log_buf, 0);
file_close (fp);
return FALSE;
}
fprintf (fp, "#GQUESTDATA\n\n");
fprintf (fp, "Mobs %d ", gquest_info.mob_count);
for (i = 0; i < gquest_info.mob_count; i++)
fprintf (fp, "%ld ", gquest_info.mobs[i]);
fprintf (fp, "\n");
fprintf (fp, "Who %s~\n", gquest_info.who);
fprintf (fp, "Timer %d\n",
(gquest_info.timer >
0) ? (gquest_info.timer + 1) : gquest_info.timer);
fprintf (fp, "Involv %d\n", gquest_info.involved);
fprintf (fp, "Qpoints %d\n", gquest_info.qpoints);
fprintf (fp, "Gold %d\n", gquest_info.gold);
fprintf (fp, "MinLev %d\n", gquest_info.minlevel);
fprintf (fp, "MaxLev %d\n", gquest_info.maxlevel);
fprintf (fp, "Running %d\n", gquest_info.running);
fprintf (fp, "Next %d\n",
(gquest_info.next >
0) ? (gquest_info.next + 1) : gquest_info.next);
fprintf (fp, "#0\n");
fprintf (fp, "\nEnd\n");
file_close (fp);
return TRUE;
}
#if defined(KEY)
#undef KEY
#endif
#define KEY( literal, field, value ) \
if ( !str_cmp( word, literal ) ) \
{ \
field = value; \
fMatch = TRUE; \
break; \
}
#if defined(KEYS)
#undef KEYS
#endif
#define KEYS( literal, field, value ) \
if ( !str_cmp( word, literal ) ) \
{ \
free_string(field); \
field = value; \
fMatch = TRUE; \
break; \
}
bool load_gquest_data (void)
{
FILE *fp;
const char *word;
bool fMatch = FALSE;
end_gquest (NULL);
if (!(fp = file_open (GQUEST_FILE, "r")))
{
sprintf (log_buf,
"load_gquest_data: Could not open file %s in order to read gquest data. Creating.",
GQUEST_FILE);
bug (log_buf, 0);
file_close (fp);
return save_gquest_data ();
}
if (str_cmp (fread_word (fp), "#GQUESTDATA"))
{
sprintf (log_buf,
"load_gquest_data: Invalid gquest data file (%s).\n\r",
GQUEST_FILE);
bug (log_buf, 0);
file_close (fp);
return FALSE;
}
for (;;)
{
word = feof (fp) ? "End" : fread_word (fp);
if (!str_cmp (word, "End"))
{
fMatch = TRUE;
break;
}
fMatch = FALSE;
switch (UPPER (word[0]))
{
case '#': // comment identifier
fMatch = TRUE;
fread_to_eol (fp);
break;
case 'G':
KEY ("Gold", gquest_info.gold, fread_number (fp));
break;
case 'I':
KEY ("Involv", gquest_info.involved, fread_number (fp));
break;
case 'M':
KEY ("MinLev", gquest_info.minlevel, fread_number (fp));
KEY ("MaxLev", gquest_info.maxlevel, fread_number (fp));
if (!str_cmp (word, "Mobs"))
{
int i;
gquest_info.mob_count = fread_number (fp);
for (i = 0; i < gquest_info.mob_count; i++)
gquest_info.mobs[i] = fread_number (fp);
fMatch = TRUE;
break;
}
break;
case 'N':
KEY ("Next", gquest_info.next, fread_number (fp));
break;
case 'Q':
KEY ("Qpoints", gquest_info.qpoints, fread_number (fp));
break;
case 'R':
KEY ("Running", gquest_info.running, fread_number (fp));
break;
case 'T':
KEY ("Timer", gquest_info.timer, fread_number (fp));
break;
case 'W':
KEYS ("Who", gquest_info.who, fread_string (fp));
break;
}
if (!fMatch)
{
sprintf (log_buf, "load_gquest_data: Invalid Key: %s", word);
bug (log_buf, 0);
fread_to_eol (fp);
}
}
file_close (fp);
return TRUE;
}
bool start_gquest (CHAR_DATA * ch, const char *argument)
{
char arg1[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH];
char arg3[MAX_INPUT_LENGTH];
char buf[MAX_STRING_LENGTH];
CHAR_DATA *registar = NULL;
int mobs, blevel, elevel, cost;
for (registar = ch->in_room->people; registar != NULL;
registar = registar->next_in_room)
{
if (!IS_NPC (registar))
continue;
if (registar->spec_fun == spec_lookup ("spec_registar"))
break;
}
if (!IS_IMMORTAL (ch) &&
(registar == NULL ||
registar->spec_fun != spec_lookup ("spec_registar")))
{
chprintln (ch, "You can't do that here.");
return FALSE;
}
if (!IS_IMMORTAL (ch))
{
if (registar->fighting != NULL)
{
chprintln (ch, "Wait until the fighting stops.");
return FALSE;
}
if (gquest_info.last_registar == ch)
{
chprintln (ch, "Let someone else have a chance.");
return FALSE;
}
}
argument = one_argument (argument, arg1);
argument = one_argument (argument, arg2);
argument = one_argument (argument, arg3);
if (arg1[0] == '\0' || arg2[0] == '\0' || arg3[0] == '\0')
{
chprintln (ch,
"Syntax: gquest start <min level> <max level> <#mobs>");
return FALSE;
}
blevel = atoi (arg1);
elevel = atoi (arg2);
mobs = atoi (arg3);
if (blevel <= 0 || blevel > MAX_LEVEL)
{
chprintlnf (ch, "Level must be between 1 and %d.", MAX_LEVEL);
return FALSE;
}
if (blevel <= 0 || elevel > MAX_LEVEL)
{
chprintlnf (ch, "Level must be between 1 and %d.", MAX_LEVEL);
return FALSE;
}
if (elevel <= blevel)
{
chprintln (ch, "Max level must be greater than the min level.");
return FALSE;
}
if (elevel - blevel < 10)
{
chprintln (ch, "Level difference must 10 levels or higher.");
return FALSE;
}
if (mobs < 5 || mobs >= MAX_GQUEST_MOB)
{
chprintlnf (ch, "Number of mobs must be between 5 and %d.",
MAX_GQUEST_MOB - 1);
return FALSE;
}
if (gquest_info.running != GQUEST_OFF)
{
chprintln (ch, "There is already a global quest running!");
return FALSE;
}
cost = 5 + (mobs / 5);
if (!IS_IMMORTAL (ch))
{
if (ch->pcdata->trivia < cost)
{
sprintf (buf,
"$N tells you 'It costs %d Trivia Points to start a global quest with %d mobs.'",
cost, mobs);
act (buf, ch, NULL, registar, TO_CHAR);
return FALSE;
}
else
{
sprintf (buf,
"$N tells you '%d mobs have cost you %d trivia points.'",
mobs, cost);
act (buf, ch, NULL, registar, TO_CHAR);
ch->pcdata->trivia -= cost;
}
}
gquest_info.running = GQUEST_WAITING;
gquest_info.minlevel = blevel;
gquest_info.maxlevel = elevel;
gquest_info.mob_count = mobs;
free_string (gquest_info.who);
gquest_info.who = str_dup (ch->name);
if (!generate_gquest (ch))
{
if (!IS_IMMORTAL (ch))
{
chprintlnf (ch,
"Failed to start Gquest, you are being reimbursed %d TP.",
cost);
ch->pcdata->trivia += cost;
}
else
chprintln (ch, "Failed to start a gquest, not enogh mobs found.");
return FALSE;
}
return TRUE;
}
void auto_gquest (void)
{
CHAR_DATA *wch = NULL, *registar = NULL;
int middle = LEVEL_HERO / 2, maxlvl = 0;
int minlvl = MAX_LEVEL, count = 0, lbonus = 0, half = 0;
if (gquest_info.running != GQUEST_OFF)
return;
for (wch = char_list; wch != NULL; wch = wch->next)
{
if (!IS_NPC (wch) && !IS_IMMORTAL (wch))
{
count++;
maxlvl = UMAX (maxlvl, wch->level);
minlvl = UMIN (minlvl, wch->level);
}
}
if (count < 1)
{
end_gquest (gquest_info.last_registar);
return;
}
/* all this is basically so level ranges aren't to far apart */
lbonus = number_range (5, 10);
minlvl = UMAX (1, minlvl - lbonus);
maxlvl = UMIN (LEVEL_HERO, maxlvl + lbonus);
half = ((maxlvl - minlvl) / 2);
middle = URANGE (minlvl, maxlvl - half, maxlvl);
minlvl = number_range (minlvl, middle - lbonus);
maxlvl = number_range (middle + lbonus, maxlvl);
/* find the registar mob if he exits, (not needed only put in for RP aspects) */
for (registar = char_list; registar != NULL; registar = registar->next)
{
if (!IS_NPC (registar))
continue;
if (registar->pIndexData->vnum == MOB_VNUM_REGISTAR)
break;
}
gquest_info.running = GQUEST_WAITING;
gquest_info.mob_count = number_range (5, MAX_GQUEST_MOB - lbonus);
gquest_info.minlevel = UMAX (1, minlvl);
gquest_info.maxlevel = UMIN (LEVEL_HERO, maxlvl);
free_string (gquest_info.who);
gquest_info.who =
!registar ? str_dup ("AutoQuest (tm)") :
str_dup (registar->short_descr);
generate_gquest (registar);
return;
}
void post_gquest (CHAR_DATA * ch)
{
BUFFER *output;
CHAR_DATA *wch;
MOB_INDEX_DATA *mob;
int i;
GQUEST_HIST *hist;
char *strtime;
char shortd[MAX_INPUT_LENGTH];
char buf[MAX_STRING_LENGTH];
if (gquest_info.running == GQUEST_OFF || gquest_info.involved == 0)
return;
alloc_mem (hist, GQUEST_HIST, 1);
strtime = ctime (¤t_time);
strtime[strlen (strtime) - 1] = '\0';
sprintf (shortd, "%24s %3d %3d %4d %12s\n\r", strtime,
gquest_info.minlevel, gquest_info.maxlevel,
gquest_info.mob_count, ch->name);
hist->short_descr = str_dup (shortd);
output = new_buf ();
sprintf (buf, "GLOBAL QUEST INFO\n\r-----------------\n\r");
add_buf (output, buf);
sprintf (buf, "Started by : %s\n\r",
gquest_info.who[0] == '\0' ? "Unknown" : gquest_info.who);
add_buf (output, buf);
sprintf (buf, "Levels : %d - %d\n\r", gquest_info.minlevel,
gquest_info.maxlevel);
add_buf (output, buf);
sprintf (buf, "Those Playing\n\r-------------\n\r");
add_buf (output, buf);
for (wch = char_list; wch != NULL; wch = wch->next)
if (!IS_NPC (ch) && ON_GQUEST (wch)
&& count_gqmobs (wch) != gquest_info.mob_count)
sprintf (buf, "%s [%d mobs left]\n\r", wch->name,
gquest_info.mob_count - count_gqmobs (wch));
add_buf (output, buf);
sprintf (buf, "%s won the GQuest.\n\r", ch->name);
add_buf (output, buf);
sprintf (buf, "Quest Rewards\n\r-------------\n\r");
add_buf (output, buf);
sprintf (buf, "Qp Reward : %d + 3 QPs for each target.\n\r",
gquest_info.qpoints);
add_buf (output, buf);
sprintf (buf, "Gold Reward : %d\n\r", gquest_info.gold);
add_buf (output, buf);
sprintf (buf, "Quest Targets\n\r-------------\n\r");
add_buf (output, buf);
for (i = 0; i < gquest_info.mob_count; i++)
{
if ((mob = get_mob_index (gquest_info.mobs[i])) != NULL)
{
sprintf (buf, "%2d) [%-20s] %-30s (level %3d)\n\r", i + 1,
mob->area->name, mob->short_descr, mob->level);
add_buf (output, buf);
}
}
hist->text = str_dup (buf_string (output));
hist->next = gqhist_first;
gqhist_first = hist;
free_buf (output);
return;
}
CH_CMD (do_gquest)
{
char arg1[MAX_INPUT_LENGTH];
char buf[MAX_STRING_LENGTH];
CHAR_DATA *wch;
MOB_INDEX_DATA *mob;
int i = 0;
if (IS_NPC (ch))
{
chprintln (ch, "Your the victim not the player.");
return;
}
argument = one_argument (argument, arg1);
if (arg1[0] == '\0')
{
chprintln (ch, "Syntax: gquest join - join a global quest\n\r"
" gquest quit - quit the global quest\n\r"
" gquest info - show global quest info\n\r"
" gquest time - show global quest time\n\r"
" gquest check - show what targets you have left\n\r"
" gquest progress - show progress of other players\n\r"
" gquest complete - completes the current quest\n\r"
" gquest hist - shows gquest history since last reboot\n\r"
" gquest start - starts a gquest");
if (IS_IMMORTAL (ch))
{
chprintln (ch, " gquest end - ends the gquest (IMM)");
chprintln (ch,
" gquest next - sets time to next gquest.");
}
return;
}
else if (!str_prefix (arg1, "start"))
{
start_gquest (ch, argument);
return;
}
else if (!str_prefix (arg1, "next") && IS_IMMORTAL (ch))
{
if (gquest_info.running != GQUEST_OFF)
{
chprintln (ch, "Not while a gquest is running.");
return;
}
i = is_number (argument) ? atoi (argument) : number_range (30, 100);
gquest_info.next = i;
chprintlnf (ch, "The next gquest will start in %d minutes.",
gquest_info.next);
return;
}
else if (!str_prefix (arg1, "hist"))
{
GQUEST_HIST *hist;
int count = 0;
if (!gqhist_first)
{
chprintln (ch, "No global quests completed yet.");
return;
}
if (argument[0] == '\0')
{
BUFFER *output = new_buf ();
add_buf (output,
"Num Finished Time Levels Mobs Completed by\n\r"
"--- ------------------------ ------- ---- ------------\n\r");
for (hist = gqhist_first; hist != NULL; hist = hist->next)
{
sprintf (buf, "%2d) ", ++count);
add_buf (output, buf);
add_buf (output, hist->short_descr);
}
add_buf (output, "Type 'gquest hist #' to view details.\n\r");
page_to_char (buf_string (output), ch);
free_buf (output);
}
else
{
bool found = FALSE;
if (!is_number (argument))
{
chprintln (ch, "Syntax: gquest hist #");
return;
}
for (hist = gqhist_first; hist != NULL; hist = hist->next)
if (++count == atoi (argument))
{
chprint (ch, hist->text);
found = TRUE;
}
if (!found)
chprintln (ch, "History data not found.");
}
return;
}
else if (gquest_info.running == GQUEST_OFF)
{
chprintlnf (ch,
"There is no global quest running. The next Gquest will start in %d minutes.",
gquest_info.next);
return;
}
else if (!str_prefix (arg1, "end") && IS_IMMORTAL (ch))
{
end_gquest (gquest_info.last_registar);
chprintlnf (ch,
"You end the global quest. Next autoquest in %d minutes.",
gquest_info.next);
announce (ch, INFO_GQUEST,
"$n has ended the global quest. Next gquest in %d minutes.",
gquest_info.next);
return;
}
else if (!str_prefix (arg1, "join"))
{
/* see dlm_quest.c */
if (IS_QUESTOR (ch))
{
chprintln (ch, "Why don't you finish your other quest first.");
return;
}
if (ON_GQUEST (ch))
{
chprintln (ch, "Your allready in the global quest.");
return;
}
if (gquest_info.minlevel > ch->level ||
gquest_info.maxlevel < ch->level)
{
chprintln (ch, "This gquest is not in your level range.");
return;
}
/* see dlm_war.c
if (!IS_NPC(ch) && IS_SET(ch->act, PLR_WAR))
{
sprintf(buf, "Your %s combat right now.\n\r", war_info.iswar == WAR_WAITING ? "waiting for" : "in");
chprint(buf, ch);
return;
}
*/
/* slight hack here */
if (count_gqmobs (ch) == gquest_info.mob_count)
{
chprintln (ch, "You have already quit this gquest.");
return;
}
for (i = 0; i < gquest_info.mob_count; i++)
ch->pcdata->gq_mobs[i] = gquest_info.mobs[i];
SET_BIT (ch->act, PLR_GQUEST);
gquest_info.involved++;
chprintln
(ch,
"Your global quest flag is now on. Use 'gquest info' to see the quest(s).");
announce (ch, INFO_GQUEST, "$n has joined the global quest.");
return;
}
else if (!str_prefix (arg1, "quit"))
{
if (!ON_GQUEST (ch))
{
chprintln (ch, "Your not in a global quest.");
return;
}
/* hack to prevent coming back */
reset_gqmob (ch, -1);
REMOVE_BIT (ch->act, PLR_GQUEST);
gquest_info.involved--;
chprintln (ch,
"Your global quest flag is now off. Sorry you couldn't complete it.");
announce (ch, INFO_GQUEST,
"$n has quit the global quest, what a sore loser.");
return;
}
else if (!str_prefix (arg1, "info"))
{
char cbuf[MIL];
chprintln (ch, "[ GLOBAL QUEST INFO ]");
chprintlnf (ch, "Started by : %s",
gquest_info.who[0] == '\0' ? "Unknown" : gquest_info.who);
chprintlnf (ch, "Playing : %d player%s.",
gquest_info.involved,
gquest_info.involved == 1 ? "" : "s");
chprintlnf (ch, "Levels : %d - %d", gquest_info.minlevel,
gquest_info.maxlevel);
chprintlnf (ch, "Status : %s for %d minute%s.",
gquest_info.running ==
GQUEST_WAITING ? "Waiting" : "Running",
gquest_info.timer, gquest_info.timer == 1 ? "" : "s");
chprintln (ch, "[ Quest Rewards ]");
chprintlnf (ch, "Qp Reward : %d", gquest_info.qpoints);
chprintlnf (ch, "Gold Reward : %d", gquest_info.gold);
chprintln (ch, "[ Quest Targets ]");
for (i = 0; i < gquest_info.mob_count; i++)
{
if ((mob = get_mob_index (gquest_info.mobs[i])) != NULL)
{
smash_colour (cbuf, mob->short_descr);
chprintlnf (ch,
"%2d) [%-20s] %-30s (level %3d)",
i + 1, mob->area->name, cbuf, mob->level);
}
}
return;
}
else if (!str_prefix (arg1, "time"))
{
if (gquest_info.next > 0)
sprintf (buf,
"THe next Global Quest will start in %d minute%s.\n\r",
gquest_info.next, gquest_info.next == 1 ? "" : "s");
else
chprintlnf (ch, "The Global Quest is %s for %d minute%s.",
gquest_info.running ==
GQUEST_WAITING ? "Waiting" : "Running",
gquest_info.timer, gquest_info.timer == 1 ? "" : "s");
return;
}
else if (!str_prefix (arg1, "progress"))
{
if (gquest_info.running == GQUEST_WAITING)
{
chprintln (ch, "The global quest hasn't started yet.");
return;
}
for (wch = char_list; wch != NULL; wch = wch->next)
{
if (!IS_NPC (wch) && ON_GQUEST (wch) && wch != ch)
{
chprintlnf (ch, "%-12s has %d of %d mobs left.",
wch->name,
gquest_info.mob_count -
count_gqmobs (wch), gquest_info.mob_count);
}
}
return;
}
else if (!str_prefix (arg1, "check"))
{
if (IS_IMMORTAL (ch) && argument[0] != '\0')
{
if ((wch = get_char_world (ch, argument)) == NULL || IS_NPC (wch))
{
chprintln (ch, "That player is not here.");
return;
}
}
else
wch = ch;
if (!ON_GQUEST (wch))
{
chprintlnf (ch, "%s aren't on a global quest.",
wch == ch ? "You" : wch->name);
return;
}
chprintlnf (ch, "[ %s have %d of %d mobs left ]",
wch == ch ? "You" : wch->name,
gquest_info.mob_count - count_gqmobs (wch),
gquest_info.mob_count);
for (i = 0; i < gquest_info.mob_count; i++)
{
if ((mob = get_mob_index (wch->pcdata->gq_mobs[i])) != NULL)
{
chprintlnf (ch,
"%2d) [%-20s] %-30s (level %3d)",
i + 1, mob->area->name, mob->short_descr,
mob->level);
}
}
return;
}
else if (!str_prefix (arg1, "complete"))
{
if (!ON_GQUEST (ch))
{
chprintln (ch, "Your not in a global quest.");
return;
}
if (count_gqmobs (ch) != gquest_info.mob_count)
{
chprintlnf (ch,
"You haven't finished just yet, theres still %d mobs to kill.",
gquest_info.mob_count - count_gqmobs (ch));
return;
}
chprintln (ch, "YES! You have completed the global quest.");
ch->pcdata->questpoints += gquest_info.qpoints;
ch->gold += gquest_info.gold;
post_gquest (ch);
chprintlnf (ch, "You receive %d gold and %d quest points.",
gquest_info.gold, gquest_info.qpoints);
end_gquest (gquest_info.last_registar);
sprintf (buf,
"$n has completed the global quest, next gquest in %d minutes.",
gquest_info.next);
announce (ch, INFO_GQUEST, buf);
return;
}
else
do_gquest (ch, "");
return;
}
void end_gquest (CHAR_DATA * who)
{
CHAR_DATA *wch;
gquest_info.running = GQUEST_OFF;
free_string (gquest_info.who);
gquest_info.who = str_dup ("");
gquest_info.mob_count = 0;
gquest_info.timer = 0;
gquest_info.involved = 0;
gquest_info.qpoints = 0;
gquest_info.gold = 0;
gquest_info.minlevel = 0;
gquest_info.maxlevel = 0;
gquest_info.next = number_range (100, 200);
reset_gqmob (NULL, 0);
gquest_info.last_registar = who;
for (wch = char_list; wch != NULL; wch = wch->next)
{
if (!IS_NPC (wch) && IS_SET (wch->act, PLR_GQUEST))
{
REMOVE_BIT (wch->act, PLR_GQUEST);
reset_gqmob (wch, 0);
}
}
}
void gquest_update (void)
{
char buf[MSL];
if (gquest_info.running == GQUEST_OFF)
{
if (--gquest_info.next <= 0)
auto_gquest ();
}
else if (gquest_info.running == GQUEST_WAITING)
{
gquest_info.timer--;
if (gquest_info.timer > 0)
{
sprintf (buf,
"%d minute%s left to join the global quest. (Levels %d - %d)",
gquest_info.timer,
gquest_info.timer == 1 ? "" : "s",
gquest_info.minlevel, gquest_info.maxlevel);
announce (NULL, INFO_GQUEST, buf);
}
else
{
if (gquest_info.involved == 0)
{
end_gquest (gquest_info.last_registar);
sprintf (buf,
"Not enough people for the global quest. The next quest will start in %d minutes.",
gquest_info.next);
announce (NULL, INFO_GQUEST, buf);
}
else
{
gquest_info.timer =
number_range (4 * gquest_info.mob_count,
6 * gquest_info.mob_count);
gquest_info.running = GQUEST_RUNNING;
sprintf (buf,
"The Global Quest begins! You have %d minutes to complete the task!",
gquest_info.timer);
announce (NULL, INFO_GQUEST, buf);
}
}
}
else if (gquest_info.running == GQUEST_RUNNING)
{
if (gquest_info.involved == 0)
{
end_gquest (gquest_info.last_registar);
sprintf (buf,
"No one left in the Global Quest, next quest will start in %d minutes.",
gquest_info.next);
announce (NULL, INFO_GQUEST, buf);
return;
}
switch (gquest_info.timer)
{
case 0:
end_gquest (gquest_info.last_registar);
sprintf (buf,
"Time has run out on the Global Quest, next quest will start in %d minutes.",
gquest_info.next);
announce (NULL, INFO_GQUEST, buf);
return;
case 1:
case 2:
case 3:
case 4:
case 5:
case 10:
case 15:
sprintf (buf,
"%d minute%s remaining in the global quest.",
gquest_info.timer, gquest_info.timer > 1 ? "s" : "");
announce (NULL, INFO_GQUEST, buf);
default:
gquest_info.timer--;
break;
}
return;
}
}
bool generate_gquest (CHAR_DATA * who)
{
CHAR_DATA *victim = NULL;
vnum_t *vnums;
int mob_count, randm;
char buf[MAX_STRING_LENGTH];
int i;
reset_gqmob (NULL, 0);
mob_count = 0;
alloc_mem (vnums, vnum_t, top_mob_index);
for (victim = char_list; victim; victim = victim->next)
{
if (!IS_NPC (victim))
{
REMOVE_BIT (victim->act, PLR_GQUEST);
reset_gqmob (victim, 0);
continue;
}
else if (!IS_NPC (victim)
|| victim->level > (gquest_info.maxlevel + 10)
|| victim->level < (gquest_info.minlevel - 10)
|| (victim->pIndexData == NULL
|| victim->in_room == NULL
|| victim->pIndexData->pShop != NULL)
|| victim->pIndexData->vnum < 100
|| IS_SET (victim->in_room->room_flags, ROOM_PET_SHOP)
|| victim->in_room->clan > -1
|| IS_SET (victim->imm_flags, IMM_WEAPON | IMM_MAGIC)
|| IS_SET (victim->act,
ACT_TRAIN | ACT_PRACTICE | ACT_IS_HEALER |
ACT_PET | ACT_GAIN)
|| IS_SET (victim->affected_by, AFF_CHARM)
|| (IS_SET (victim->act, ACT_SENTINEL)
&& IS_SET (victim->in_room->room_flags,
ROOM_PRIVATE | ROOM_SOLITARY | ROOM_SAFE)))
continue;
vnums[mob_count] = victim->pIndexData->vnum;
mob_count++;
if (mob_count >= top_mob_index)
break;
}
if (mob_count < 5)
{
end_gquest (who);
free_mem (vnums);
return FALSE;
}
else if (mob_count < gquest_info.mob_count)
{
gquest_info.mob_count = mob_count;
}
for (i = 0; i < gquest_info.mob_count; i++)
{
randm = number_range (0, mob_count - 1);
while (!is_random_gqmob (vnums[randm]))
randm = number_range (0, mob_count - 1);
gquest_info.mobs[i] = vnums[randm];
}
gquest_info.qpoints = number_range (15, 30) * gquest_info.mob_count;
gquest_info.gold = number_range (100, 150) * gquest_info.mob_count;
gquest_info.timer = 3;
gquest_info.next = 0;
sprintf (buf,
"%s Global Quest for levels %d to %d%s. Type 'GQUEST INFO' to see the quest.",
!who ? "A" : "$n announces a", gquest_info.minlevel,
gquest_info.maxlevel, !who ? " has started" : "");
announce (who, INFO_GQUEST, buf);
chprintlnf (who,
"You announce a Global Quest for levels %d to %d with %d targets.\n\r",
gquest_info.minlevel, gquest_info.maxlevel,
gquest_info.mob_count);
free_mem (vnums);
return TRUE;
}
int is_gqmob (CHAR_DATA * ch, vnum_t vnum)
{
int i;
if (gquest_info.running == GQUEST_OFF)
return -1;
for (i = 0; i < gquest_info.mob_count; i++)
{
if (ch && !IS_NPC (ch))
{
if (ch->pcdata->gq_mobs[i] == vnum)
return i;
else
continue;
}
else
{
if (gquest_info.mobs[i] == vnum)
return i;
else
continue;
}
}
return -1;
}
int count_gqmobs (CHAR_DATA * ch)
{
int i, count = 0;
if (IS_NPC (ch))
return 0;
for (i = 0; i < gquest_info.mob_count; i++)
if (ch->pcdata->gq_mobs[i] == -1)
count++;
return count;
}
void reset_gqmob (CHAR_DATA * ch, vnum_t value)
{
int i;
for (i = 0; i < MAX_GQUEST_MOB; i++)
{
if (ch && !IS_NPC (ch))
ch->pcdata->gq_mobs[i] = value;
else
gquest_info.mobs[i] = value;
}
}
bool is_random_gqmob (vnum_t vnum)
{
int i;
if (get_mob_index (vnum) == NULL)
return FALSE;
for (i = 0; i < gquest_info.mob_count; i++)
if (gquest_info.mobs[i] == vnum)
return FALSE;
return TRUE;
}