/************************************************************************** * Automated GLobal Quest Code * * Telnet : <akbearsden.com:3778> * * E-Mail : <dlmud@dlmud.com > * * Website: <http://dlmud.akbearsden.com> * * * * Provides automated, saveable global quests for a level range. * * * * This version has been redone and attempted to fit stock rom. * * Some things you will need to change to fit your mud * ***************************************************************************/ #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <time.h> #include "merc.h" #include "recycle.h" #include "const.h" typedef struct gquest_hist GQUEST_HIST; struct gquest_hist { GQUEST_HIST *next; char *short_descr; char *text; }; GQUEST_HIST *gqhist_first = NULL; void gquest_channel(CHAR_DATA *ch, char *message) { DESCRIPTOR_DATA *d; CHAR_DATA *dch; char buf[MAX_INPUT_LENGTH]; for(d = descriptor_list; d != NULL; d = d->next) { if(d->connected != CON_PLAYING) continue; if((dch = d->character) == NULL || dch == ch) continue; sprintf(buf, "GQUEST: %s",message); if(ch) /* don't use $N only $n in message */ act(buf, ch, NULL, dch, TO_VICT); else { send_to_char(buf, dch); send_to_char("\n\r", dch); } } } bool save_gquest_data(void) { FILE *fp = NULL; char buf[MIL]; int i; sprintf(buf, "../area/%s", GQUEST_FILE ); fp = file_open( buf, "w" ); if(!fp) { logf2("Bug with saving gquest file."); 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, "%d ", 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(); fp = file_open( GQUEST_FILE, "r" ); 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, 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"))) { send_to_char("You can't do that here.\n\r", ch); return FALSE; } if (!IS_IMMORTAL(ch) && registar->fighting != NULL) { send_to_char("Wait until the fighting stops.\n\r", ch); 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') { send_to_char("Syntax: gquest start <min level> <max level> <#mobs>\n\r", ch); return FALSE; } blevel = atoi(arg1); elevel = atoi(arg2); mobs = atoi(arg3); if (blevel <= 0 || blevel > MAX_LEVEL) { sprintf(buf, "Level must be between 1 and %d.\n\r", MAX_LEVEL); send_to_char( buf,ch); return FALSE; } if (blevel <= 0 || elevel > MAX_LEVEL) { sprintf(buf, "Level must be between 1 and %d.\n\r", MAX_LEVEL); send_to_char(buf,ch); return FALSE; } if (elevel <= blevel) { send_to_char("Max level must be greater than the min level.\n\r", ch); return FALSE; } if (elevel - blevel < 10) { send_to_char("Level difference must 10 levels or higher.\n\r", ch); return FALSE; } if (mobs < 5 || mobs >= MAX_GQUEST_MOB) { sprintf(buf, "Number of mobs must be between 5 and %d.\n\r", MAX_GQUEST_MOB - 1); send_to_char(buf,ch); return FALSE; } if (gquest_info.running != GQUEST_OFF) { send_to_char("There is already a global quest running!\n\r", ch); 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; } send_to_char("Oops you can't start a global quest!\n\r", ch); return FALSE; } 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)) { sprintf(buf, "Failed to start Gquest, you are being reimbursed %d TP.\n\r", cost); send_to_char( buf, ch ); ch->pcdata->trivia += cost; } else send_to_char("Failed to start a gquest, not enogh mobs found.\n\r", ch); 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(); return; } 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); 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; hist = (GQUEST_HIST *)alloc_mem(sizeof(hist)); 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; } void do_gquest(CHAR_DATA *ch, char *argument) { char arg1[MAX_INPUT_LENGTH], buf[MSL]; CHAR_DATA *wch; MOB_INDEX_DATA *mob; int i = 0; if (IS_NPC(ch)) { send_to_char("Your the victim not the player.\n\r", ch); return; } argument = one_argument(argument, arg1); if (arg1[0] == '\0') { send_to_char("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\n\r", ch); if (IS_IMMORTAL(ch)) { send_to_char(" gquest end - ends the gquest (IMM)\n\r", ch); send_to_char(" gquest next - sets time to next gquest.\n\r", ch); } 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) { send_to_char("Not while a gquest is running.\n\r", ch); return; } i = is_number(argument) ? atoi(argument) : number_range(30, 100); gquest_info.next = i; printf_to_char(ch, "The next gquest will start in %dminutes.\n\r", gquest_info.next); return; } else if (!str_prefix(arg1, "hist")) { GQUEST_HIST *hist; int count = 0; if (!gqhist_first) { send_to_char("No global quests completed yet.\n\r", ch); 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)) { send_to_char("Syntax: gquest hist #\n\r", ch); return; } for (hist = gqhist_first; hist != NULL; hist = hist->next) { if (++count == atoi(argument)) { send_to_char(hist->text, ch); found = TRUE; } } if (!found) send_to_char("History data not found.\n\r", ch); } return; } else if (gquest_info.running == GQUEST_OFF) { printf_to_char(ch, "There is no global quest running. The next Gquest will start in %d minutes.\n\r", gquest_info.next); return; } else if (!str_prefix(arg1, "end") && IS_IMMORTAL(ch)) { end_gquest(); sprintf(buf, "You end the global quest. Next autoquest in %d minutes.\n\r", gquest_info.next); send_to_char(buf,ch); sprintf(buf, "$n has ended the global quest. Next gquest in %d minutes.", gquest_info.next); return; } else if (!str_prefix(arg1, "join")) { if (IS_QUESTOR(ch)) { send_to_char("Why don't you finish your other quest first.\n\r", ch); return; } if (ON_GQUEST(ch)) { send_to_char("Your allready in the global quest.\n\r", ch); return; } if (gquest_info.minlevel > ch->level || gquest_info.maxlevel < ch->level) { send_to_char("This gquest is not in your level range.\n\r", ch); return; } 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"); send_to_char(buf, ch); return; } if (count_gqmobs(ch) == gquest_info.mob_count) { send_to_char("You have already quit this gquest.\n\r", ch); 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++; } send_to_char("Your global quest flag is now on. Use 'gquest info' to see the quest(s).\n\r", ch); gquest_channel(ch, "$n has joined the global quest."); return; } else if (!str_prefix(arg1, "quit")) { if (!ON_GQUEST(ch)) { send_to_char("Your not in a global quest.\n\r", ch); return; } reset_gqmob(ch, -1); REMOVE_BIT(ch->act, PLR_GQUEST); gquest_info.involved--; send_to_char("Your global quest flag is now off. Sorry you couldn't complete it.\n\r",ch); gquest_channel(ch, "$n has quit the global quest, what a sore loser."); return; } else if (!str_prefix(arg1, "info")) { send_to_char("[ GLOBAL QUEST INFO ]",ch); sprintf(buf, "Started by : %s\n\r", gquest_info.who[0] == '\0' ? "Unknown" : gquest_info.who); send_to_char(buf,ch); sprintf(buf, "Playing : %d player%s.\n\r", gquest_info.involved, gquest_info.involved == 1 ? "" : "s"); send_to_char(buf,ch); sprintf(buf, "Levels : %d - %d\n\r", gquest_info.minlevel, gquest_info.maxlevel); send_to_char(buf,ch); sprintf(buf, "Status : %s for %d minute%s.\n\r", gquest_info.running == GQUEST_WAITING ? "Waiting" : "Running", gquest_info.timer, gquest_info.timer == 1 ? "" : "s"); send_to_char(buf,ch); send_to_char("[ Quest Rewards ]",ch); send_to_char(buf,ch); sprintf(buf, "Qp Reward : %d\n\r", gquest_info.qpoints); send_to_char(buf,ch); sprintf(buf, "Gold Reward : %d\n\r", gquest_info.gold); send_to_char(buf,ch); send_to_char("[ Quest Targets ]",ch); send_to_char(buf,ch); 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); send_to_char(buf,ch); } } 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 sprintf(buf, "The Global Quest is %s for %d minute%s.\n\r", gquest_info.running == GQUEST_WAITING ? "Waiting" : "Running", gquest_info.timer, gquest_info.timer == 1 ? "" : "s"); send_to_char(buf, ch); return; } else if (!str_prefix(arg1, "progress")) { if (gquest_info.running == GQUEST_WAITING) { send_to_char("The global quest hasn't started yet.\n\r", ch); return; } for (wch = char_list; wch != NULL; wch = wch->next) { if (!IS_NPC(wch) && ON_GQUEST(wch) && wch != ch) { sprintf(buf, "%-12s has %d of %d mobs left.\n\r", wch->name, gquest_info.mob_count - count_gqmobs(wch), gquest_info.mob_count); send_to_char(buf,ch); } } 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)) { send_to_char("That player is not here.\n\r", ch); return; } } else wch = ch; if (!ON_GQUEST(wch)) { sprintf(buf, "%s aren't on a global quest.\n\r", wch == ch ? "You" : wch->name); send_to_char(buf,ch); return; } sprintf(buf, "[ %s have %d of %d mobs left ]\n\r", wch == ch ? "You" : wch->name, gquest_info.mob_count - count_gqmobs(wch), gquest_info.mob_count); send_to_char(buf,ch); for (i = 0; i < gquest_info.mob_count; i++) { if ((mob = get_mob_index(wch->pcdata->gq_mobs[i])) != NULL) { sprintf(buf, "%2d) [%-20s] %-30s (level %3d)\n\r", i + 1, mob->area->name, mob->short_descr, mob->level); send_to_char(buf,ch); } } return; } else if (!str_prefix(arg1, "complete")) { if (!ON_GQUEST(ch)) { send_to_char("Your not in a global quest.\n\r", ch); return; } if (count_gqmobs(ch) != gquest_info.mob_count) { sprintf(buf, "You haven't finished just yet, theres still %d mobs to kill.\n\r", gquest_info.mob_count - count_gqmobs(ch)); send_to_char(buf,ch); return; } send_to_char("YES! You have completed the global quest.\n\r", ch); ch->pcdata->questpoints += gquest_info.qpoints; ch->gold += gquest_info.gold; post_gquest(ch); sprintf(buf, "You receive %d gold and %d quest points.\n\r", gquest_info.gold, gquest_info.qpoints); send_to_char(buf,ch); end_gquest(); sprintf(buf, "$n has completed the global quest, next gquest in %d minutes.", gquest_info.next); gquest_channel(ch,buf); return; } else do_gquest(ch, ""); return; } void end_gquest(void) { 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(70, 100); reset_gqmob(NULL, 0); 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 ); gquest_channel(NULL, buf); } else { if ( gquest_info.involved == 0 ) { end_gquest ( ); sprintf ( buf, "Not enough people for the global quest. The next quest will start in %d minutes.", gquest_info.next ); gquest_channel(NULL, 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 ); gquest_channel(NULL, buf); } } } else if ( gquest_info.running == GQUEST_RUNNING ) { if ( gquest_info.involved == 0 ) { end_gquest ( ); sprintf ( buf, "No one left in the Global Quest, next quest will start in %d minutes.", gquest_info.next ); gquest_channel(NULL, buf); return; } switch ( gquest_info.timer ) { case 0: end_gquest ( ); sprintf ( buf, "Time has run out on the Global Quest, next quest will start in %d minutes.", gquest_info.next ); gquest_channel(NULL, 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" : "" ); gquest_channel(NULL, buf); default: gquest_info.timer--; break; } return; } } bool generate_gquest(CHAR_DATA * who) { CHAR_DATA *victim = NULL; long vnums[top_mob_index]; size_t mob_count, randm; char buf[MAX_STRING_LENGTH]; int i; reset_gqmob(NULL, 0); mob_count = 0; 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 || 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 >= (size_t)top_mob_index) break; } if (mob_count < 5) { end_gquest(); return FALSE; } else if (mob_count < (size_t)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" : ""); gquest_channel(who, buf); sprintf(buf, "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); send_to_char(buf, who); return TRUE; } int is_gqmob(CHAR_DATA * ch, int 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, int 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(int 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; }