#include "kernel.h" #include "locations.h" #include "objects.h" #include "mobiles.h" #include "mudmacros.h" #include "ctype.h" #include "bprintf.h" #include "utils.h" #include "uaf.h" #include "mobile.h" #include "objsys.h" #include "sendsys.h" #include "questnames.h" #include "parse.h" #include "log.h" #include "quests.h" #include "qlevels.h" int quest_index[][2] = { {LOCMIN_EFOREST, LOCMAX_EFOREST}, {LOCMIN_TOWER, LOCMAX_TOWER}, {LOCMIN_SEA, LOCMAX_SEA}, {LOCMIN_CATACOMB, LOCMAX_CATACOMB}, {LOCMIN_WASTE, LOCMAX_WASTE}, {LOCMIN_OAKTREE, LOCMAX_OAKTREE}, {LOCMIN_FROBOZZ, LOCMAX_FROBOZZ}, {LOCMIN_THYRANNEN, LOCMAX_THYRANNEN}, {LOCMIN_EVOLUTION, LOCMAX_EVOLUTION}, {LOCMIN_ZODIAC, LOCMAX_ZODIAC}, {LOCMIN_ANCIENT, LOCMAX_ANCIENT}, {LOCMIN_VOLCANO, LOCMAX_VOLCANO}, {LOCMIN_PIRATE, LOCMAX_PIRATE}, {LOCMIN_RAINFOREST, LOCMAX_RAINFOREST}, {LOCMIN_NOXYPICKLE, LOCMAX_NOXYPICKLE}, {LOCMIN_ABYSS, LOCMAX_ABYSS}, {LOCMIN_MITHDAN, LOCMAX_MITHDAN}, {LOCMIN_ORCHOLD, LOCMAX_ORCHOLD} }; extern int count_players_in_zone(int zone); extern int count_players_between_locs(int, int); char *quest_status(int quest) { int i = quest; if (xtstbit(the_world->q_done, i)) return("&+RDone "); else if (count_players_between_locs(quest_index[i][0], quest_index[i][1]) > 0) return("&+YIn Progress"); else return("&+GAvailable"); } /* ** To set a quest flag. Makes check to see if gaining quest allows player to ** level, as well as sets the_world->q_done flags. */ void set_quest(int p, int v) { if (mynum < max_players) sendf(p, "Congratulations! You have completed the quest %s.\n", Quests[v].name); mudlog ("Quest &+M%s&N completed by %s", Quests[v].name, pname(p)); send_msg(DEST_ALL,MODE_QUIET, LVL_WIZARD,LVL_MAX,NOBODY,NOBODY, "&+Y[Quest &+M%s&+Y completed by %s]\n", Quests[v].name, pname(p)); if (mynum < max_players) qsetflg(p, v); else bprintf("Really useful, completing quests as a mobile..\n"); xsetbit(the_world->q_done, v); return; } /* ** QLIST shows current list of quests and what points they are worth. ** Points are only appropriate to certain quests systems, as is this command. */ void qlistcom() { int i = 0; int qpoints = 0; Boolean nl; nl = False; bprintf(" &-BQuest Status for This Reset\n\n"); bprintf("&+WQUEST PTS CRIT STATUS " "QUEST PTS CRIT STATUS\n"); while(Quests[i].name != TABLE_END) { if( Quests[i].name[0] ) { bprintf("%-13s %-4d%s %-14s&N", Quests[i].name, Quests[i].pnt, (Quests[i].crit ? "&+WYes&N " : "No "), quest_status(i)); qpoints += Quests[i].pnt; bprintf( "%s", nl ? "\n" : " &N" ); if( !nl ) nl = True; else nl = False; } i++; } if( nl ) bprintf( "\n" ); #if QTYPE <= 1 bprintf("\nPoints, and critical have no meaning, please ignore.\n"); #elif QTYPE == 2 bprintf("\nCritical has no meaning, please ignore\n"); #elif QTYPE == 4 bprintf( "\nYou must have %d (of %d) quest points and all the critical quests done to wiz.\n", WIZ_QPOINTS, qpoints ); #endif bprintf("\n"); return; } /* * Returns level a player could have according to quests/quest points they * have. qpoints() decides if it is dependent on points or just number of * quests. */ int qcheck(int pl) { int pnt, i; i = -1; if ((plev(pl) >= LVL_WIZARD) || (plev(pl) < 1)) return plev(pl); #if QTYPE == 0 if (!tstbits(qflags(pl), Q_ALL)) return LVL_WIZARD - 1; else return LVL_WIZARD; #elif (QTYPE == 1 || QTYPE == 2) pnt = qpoints(pl); for(i = LVL_WIZARD; i > 0; i--) { if (pnt >= qlevels[i]) return i; } #elif QTYPE == 3 pnt = qpoints(pl); if (pnt >= WIZ_QPOINTS && crit_qtest(pl)) return LVL_WIZARD; else for(i = LVL_WIZARD; i > 0; i--) { if (pnt >= qlevels[i]) return i; } #elif QTYPE == 4 pnt = qpoints(pl); if(pnt >= WIZ_QPOINTS && crit_qtest(pl)) return LVL_WIZARD; else return LVL_WIZARD - 1; #endif } /* ** For quests systems with critical quests, that is ones players MUST do */ Boolean crit_qtest(int pl) { int i = 0; while(Quests[i].name != TABLE_END) { if (Quests[i].crit && !qtstflg(pl, i)) return False; i++; } return True; } /* ** Depending on the QTYPE defined, this function returns either the number ** of quests done, or number of quest points obtained, which ever is ** appropriate to the quest system. Default is number of quests */ int qpoints(int pl) { int pnt = 0; int i = 0; int num = 0; while(Quests[i].name != TABLE_END) { if (qtstflg(pl, i)) { num++; pnt += Quests[i].pnt; } i++; } #if ((QTYPE == 2) || (QTYPE == 3) || (QTYPE == 4)) return pnt; #else return num; #endif } /* ** The QUESTS-Command. Mortals may find out which quests they have ** comleted and which are left. Arch-Wizards may in addition set or ** clear quests for a mortal, Wizards only for themselves. ** Usage: QUESTS <player> <questname> <true/false> ** (Moved over from commands.c file to keep quest code together) */ void questcom(void) { int a, b, c, l; char *n; Boolean f, all; QFLAGS q, *p; PERSONA d; f = False; if (brkword() == -1) { a = mynum; p = &(qflags(a)); n = pname(a); l = plev(a); } else if ((a = fpbn(wordbuf)) != -1) { if (a != mynum && plev(mynum) < LVL_WIZARD) { bprintf("You can only check your own Quest-stats.\n"); return; } p = &(qflags(a)); n = pname(a); l = plev(a); } else if (!getuaf(wordbuf,&d)) { bprintf("No such persona in system.\n"); return; } else if (plev(mynum) < LVL_WIZARD) { bprintf("You can only check your own Quest-stats.\n"); return; } else { f = True; p = &(d.player.pquests); n = d.ublock.pname; l = d.ublock.plev; } if (brkword() == -1) { all = False; if ((*p & Q_ALL) == Q_ALL) { bprintf("&+C%s has completed all quests!\n", n); all = True; } else if ((*p & Q_ALL) != 0) { bprintf("\n&+c----------------------------------" "--------------------------------------------\n"); bprintf(" &+MQUESTS COMPLETED\n\n"); show_quests((int *)p, sizeof(QFLAGS)/sizeof(int)); bprintf("&+c----------------------------------" "--------------------------------------------\n"); } else { bprintf("&+W%s has completed no quests!\n", n); } if (!all) { bprintf("\n&+c----------------------------------" "--------------------------------------------\n"); bprintf(" &+YQUESTS NOT COMPLETED\n\n"); q = (~*p & Q_ALL); show_quests((int *)&q, sizeof(QFLAGS)/sizeof(int)); bprintf("&+c----------------------------------" "--------------------------------------------\n"); } return; } else if ((b = qlookup(wordbuf)) == -1) { bprintf("%s: No such Quest.\n", wordbuf); return; } else if (brkword() == -1 || plev(mynum) < LVL_WIZARD) { c = xtstbit(*p,b)?1:0; bprintf("Value of %s is %s\n", Quests[b].name, TF[c]); return; } else if (plev(mynum) < LVL_ARCHWIZARD && !EQ(n, pname(mynum)) ) { bprintf("You can't change other players Quest-stats.\n"); return; } else if ((c = tlookup(wordbuf,TF)) == -1) { bprintf("Value must be True or False.\n"); return; } mudlog("Quest: %s by %s, %s := %s", n, pname(mynum), Quests[b].name, TF[c]); if (c == 0) xclrbit(*p,b); else xsetbit(*p,b); if (f) putuaf(&d); } /* ** Basically just show_bits, modified to deal with just the Quests[] struct */ void show_quests(int *bits, int n) { int *b; int bno; int xno; int cno; int c2; char *p; Boolean t_end; char buff[16]; int t; cno = n; b = bits + n - 1; bno = 0; xno = 0; c2 = 0; t = 0; t_end = False; for (;b >= bits; --b, ++cno) { for (bno = 0; bno < 32; bno++, xno++, t++) { if (((*b) & (1<<bno)) != 0) { if (t_end) p = NULL; else if ((p = Quests[t].name) == TABLE_END) { t_end = True; p = NULL; } if (p == NULL) { sprintf(buff,"<Spare%d>", xno); p = buff; } if (++c2 == 6) { bprintf("\n"); c2 = 1; } if (c2 > 1) bprintf("\t"); bprintf("%-14s", p); } } } bprintf("\n"); return; } /* ** Return array index for name in Quests[].name struct */ int qlookup(char *name) { int i = 0; while(Quests[i].name != TABLE_END) { if (strncasecmp(Quests[i].name, name, strlen(name)) == 0) { return i; } i++; } return -1; }