/************************************************************************** * 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; }