/*************************************************************************** ** Project : pDirt (Aber IV MUD daemon) ** Module : quest.c ** Author : Various ** Date : 7 April 1996 ** Description: Some quest related stuff ***************************************************************************/ #define QUEST_C /*************************************************************************** ** IMPORT ***************************************************************************/ #include "kernel.h" #include "sendsys.h" /* Message send functions */ #include "questnames.h" /* String format of the quests */ #include "questpoints.h" #include "quests.h" /* The quest defines */ #include "quest.h" /* Prototypes of the functions */ #include "parse.h" /* brkword() etc */ #include "bprintf.h" /* Standard print functions */ #include "flags.h" /* Flag maninpulation */ #include "uaf.h" /* User file manipulation */ #include "log.h" /* Syslog functions */ #include "mobile.h" #include "zones.h" #include "wizlist.h" /**************************************************************************** ** PROTOTYPES ****************************************************************************/ void set_quest(int qnum, int plx); /* Set the quest on player */ A_COMMAND(questcom); /* Show quest stat for player */ A_COMMAND(qdonecom); /* Show quests done this reset*/ extern const int zonetab[]; int get_quest_of_zone(int zone) { int i; if (zone == -1) return -1; for (i = 0; zonetab[i] != -1; i+=2) { if (zonetab[i] == zone) return zonetab[i+1]; } return -1; } int get_zone_by_quest(int q) { int i=0; while (zonetab[i+1] != q && zonetab[i] != -1) i+=2; return zonetab[i]; } int count_players_in_zone(int zone) { int start,end, ct=0, i =0; if (get_zone_locs(zone,&start,&end)< 0) return 0; else { for (i=0;i < max_players; i++) { if (is_in_game(i) && ploc(i) <= start && ploc(i) > end) ct++; } } return ct; } char * queststat(int q) { int zone = get_zone_by_quest(q); if (questsdone[q]) return "&+wDone&*"; else if (count_players_in_zone(zone) > 0) return "&+wProg&*"; else return "&+wFree&*"; } int qp_for_level(int lvl) { int i; for (i=0; QP_Per_level[i] != -1; i += 2) { if (QP_Per_level[i] == lvl) return QP_Per_level[i+1]; } return 0; } /*************************************************************************** ** Sets the questflag, updates questsdone and sends messages to the player, ** and wizards. ***************************************************************************/ void set_quest(int qnum, int plx) { /** Do a check to see if the player already did this quest. If so, we ** change the message a little **/ if (questsdone[qnum]) return; if (!qtstflg(plx,qnum)) { qsetflg(plx,qnum); /* Set the flag of this quest */ send_msg(DEST_ALL,MODE_QUIET|MODE_BRACKET,LVL_APPREN,LVL_MAX,plx,NOBODY, "%s has solved the %s Quest",pname(plx),Quests[qnum]); sendf(plx,"&+wCongratulations, You just finished the %s Quest&*\n",Quests[qnum]); addqpoints(plx,qnum); } else { send_msg(DEST_ALL,MODE_QUIET|MODE_BRACKET,LVL_APPREN,LVL_MAX,plx,NOBODY, "%s has solved the %s Quest (again)",pname(plx), Quests[qnum]); sendf(plx,"&+wCongratulations, You just finished the %s Quest, again&*\n",Quests[qnum]); } questsdone[qnum] = True; saveme(); } /**************************************************************************** ** 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> ****************************************************************************/ A_COMMAND(questcom) { int a, b, c, l; char *n; Boolean f, all; QFLAGS q, *p; PERSONA d; int *qp; f = False; if (brkword () == -1) { a = mynum; /* Index to Players[] */ p = &(qflags (a)); /* Pointer to quests bitmap */ n = pname (a); /* Pointer to name of player */ l = plev (a); /* Level of the player */ qp = &qpoints(a); } else if ((a = fpbn (wordbuf)) != -1) { if (a != mynum && plev (mynum) < LVL_APPREN) /* Level check */ { bprintf ("You can only check your own Quest-stats.\n"); return; } else if (a >= max_players) { bprintf("Mobiles don't do quests.\n"); return; } p = &(qflags (a)); n = pname (a); l = plev (a); qp = &qpoints(a); } else if (!getuaf (wordbuf, &d)) /* Data retrieval for offline players */ { bprintf ("No such persona in system.\n"); return; } else if (plev (mynum) < LVL_APPREN) { bprintf ("You can only check your own Quest-stats.\n"); return; } else { f = True; p = &(d.p_quests); n = d.p_name; l = d.p_level; qp = &d.p_questpoints; } if (brkword () == -1) { bprintf ("\nPlayer: %s\n\n", n); all = False; bprintf ("&+wCompleted Quests:&*\n"); if (q_all(p)) { bprintf("All!\n"); all = True; } else if (p->h != 0 || p->l != 0) show_bits((int *)p, sizeof(QFLAGS)/sizeof(int), ReqQuests); else bprintf("None!\n"); if (!all) { bprintf ("\n&+wStill to do:&*\n"); invert_all(&q,p); show_bits ((int *) &q, sizeof (QFLAGS) / sizeof (int), ReqQuests); } return; } else if ((b = tlookup (wordbuf, Quests)) == -1) { bprintf ("%s: No such Quest.\n", wordbuf); return; } else if (brkword () == -1 || plev (mynum) < LVL_ARCHWIZARD) { c = tst_bit(p,b) ? 1 : 0; bprintf ("Value of %s is %s, and it is worth %d questpoints.\n", Quests[b], TF[c],QuestPoints[b]); 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; } #ifdef LOG_SET mudlog ("QUEST: %s by %s, %s := %s", n, pname (mynum), Quests[b], TF[c]); #endif if (c == 0) { if (tst_bit(p,b)) (*qp) -= QuestPoints[b]; clr_bit(p,b); } else { if (!tst_bit(p,b)) (*qp) += QuestPoints[b]; set_bit(p,b); } if (f) putuaf (&d); } /***************************************************************************** ** Show which quests have been completed this reset. ** Adjusted the code to show the quests in 2 columns instead of one - Marty ***************************************************************************/ A_COMMAND(qdonecom) { int q,i=0; /* Q = Questcounter, i = indentation counter */ int free=0; #ifdef TWOCOLUMNS bprintf("&+wQuest information for this reset&*\n"); bprintf("&+w-------------------------------- --------------------------------&*\n"); for (q = 0; q <= LAST_QUEST; q++) { bprintf("%-15s %-15s ", Quests[q], (questsdone[q] == True ? "&+wcompleted&*" : "&+wyet to do!&*")); if (!i) /* IF only one column was printed */ i++; /* increase indentation counter */ else /* ELSE we have printed two columns */ { bprintf("\n"); /* And we reset the stuff */ i=0; } } bprintf("%s&+w-------------------------------- --------------------------------&*\n",i ? "\n" : ""); #else bprintf("&+wQuest Information for this reset.\n"); bprintf("&+w--------------------- --------------------- ---------------------\n"); for (q=0; q <= LAST_QUEST; q++) { /*bprintf("%-15s %s ", Quests[q], (questsdone[q] == True) ? "&+wDone&*" : "&+wFree&*");*/ bprintf("%-15s %s ",Quests[q],queststat(q)); if (questsdone[q] != True) free++; if (i != 2) i++; else { bprintf("\n"); i=0; } } bprintf("%s&+w--------------------- --------------------- ---------------------\n", (i != 0) ? "\n" : ""); bprintf("&+wOf a total of &+w%d&+w quests, &+w%d&+w are still available for players.\n",LAST_QUEST+1,free); #endif } void qinfo_list(void) { int i,indent = 0; int req=0; bprintf("&+w=============================&+w[Quest Index]&+w===================================\n" "This mud has a wide variaty of quests available for you to solve. Here is a\n" "list of all quests available on this MUD:\n\n",DOUBLELINE); for (i=0; i <= LAST_QUEST; i++) { req = isrequired(i); bprintf("%s &+w%-15s&* &+w%1d&* ", req != 0 ? "&+w*&*" : "&+w-&*", Quests[i], QuestPoints[i]); indent++; if (indent == 3) { bprintf("\n"); indent = 0; } } bprintf("%s\nUse &+wQINFO <questname>&* to get a short description of the quest.\n&+w%s\n",indent != 0 ? "\n" : "",DOUBLELINE); } void calib_questpoints(int plr) { int qp = 0,i; for (i = 0; i <= LAST_QUEST; i++) { if (qtstflg(plr,i)) qp += QuestPoints[i]; } if (qpoints(plr) != qp) { bprintf("Calibrating Questpoints...\n"); mudlog("QUEST: Calibrated questpoints for %s from %d to %d\n",pname(plr),qpoints(plr),qp); qpoints(plr) = qp; } if (!q_all(&qflags(plr)) && wlevel(plev(plr)) == LEV_SENIOR) { QFLAGS q, *pq = &(qflags(plr)); invert_all(&q,pq); bprintf("You do not qualify for the senior wizard status anymore you do not have\n" "all the quests anymore. You need the following quest(s) to become senior\n" "again:\n\n"); show_bits((int *)&q,sizeof(QFLAGS)/sizeof(int),ReqQuests); bprintf("\n"); mudlog("GAME: %s doesnt qualify for senior wizard anymore.",pname(plr)); setplev(plr,LVL_WIZARD); set_xpflags(plev(plr),&pflags(plr),&pmask(plr)); update_wizlist(pname(plr),wlevel(plev(plr))); } } Boolean q_required(LongInt *f) { int i; for (i = 0; quest_list[i] != (-1); i += 2) { if (quest_list[i+1] && !tst_bit(f,quest_list[i])) return False; } return True; } Boolean q_all(LongInt *f) { int i; for (i = 0; i <= LAST_QUEST; i++) { if (!tst_bit(f,i)) return False; } return False; } void invert_all(LongInt *inverted, LongInt *orig) { int i; inverted->h = inverted->l = 0; for (i = 0; i <= LAST_QUEST; i++) { if (tst_bit(orig,i)) clr_bit(inverted,i); else set_bit(inverted,i); } } void invert_req(LongInt *inverted, LongInt *org) { int i; inverted->h = inverted->l = 0; for (i = 0; quest_list[i] != -1 ; i += 2) { if (quest_list[i+1]) { if (tst_bit(org,quest_list[i])) clr_bit(inverted,quest_list[i]); else set_bit(inverted,quest_list[i]); } else clr_bit(org,quest_list[i]); } } Boolean isrequired(int bit) { int i; for (i = 0; quest_list[i] != -1; i += 2) { if (quest_list[i] == bit) return quest_list[i+1]; } /* Assume any entry not in the quest_list isnt required */ return False; }