Devilution
Diablo devolved - magic behind the 1996 computer game
quests.cpp
Go to the documentation of this file.
1 #include "all.h"
2 
4 
5 int qtopline;
6 BOOL questlog;
7 BYTE *pQLogCel;
9 int qline;
17 
19  // clang-format off
20  // _qdlvl, _qdmultlvl, _qlvlt, _qdtype, _qdrnd, _qslvl, _qflags, _qdmsg, _qlstr
21  { 5, -1, DTYPE_NONE, Q_ROCK, 100, 0, 0, TEXT_INFRA5, "The Magic Rock" },
22  { 9, -1, DTYPE_NONE, Q_MUSHROOM, 100, 0, 0, TEXT_MUSH8, "Black Mushroom" },
23  { 4, -1, DTYPE_NONE, Q_GARBUD, 100, 0, 0, TEXT_GARBUD1, "Gharbad The Weak" },
24  { 8, -1, DTYPE_NONE, Q_ZHAR, 100, 0, 0, TEXT_ZHAR1, "Zhar the Mad" },
25  { 14, -1, DTYPE_NONE, Q_VEIL, 100, 0, 0, TEXT_VEIL9, "Lachdanan" },
26  { 15, -1, DTYPE_NONE, Q_DIABLO, 100, 0, 1, TEXT_VILE3, "Diablo" },
27  { 2, 2, DTYPE_NONE, Q_BUTCHER, 100, 0, 1, TEXT_BUTCH9, "The Butcher" },
28  { 4, -1, DTYPE_NONE, Q_LTBANNER, 100, 0, 0, TEXT_BANNER2, "Ogden's Sign" },
29  { 7, -1, DTYPE_NONE, Q_BLIND, 100, 0, 0, TEXT_BLINDING, "Halls of the Blind" },
30  { 5, -1, DTYPE_NONE, Q_BLOOD, 100, 0, 0, TEXT_BLOODY, "Valor" },
31  { 10, -1, DTYPE_NONE, Q_ANVIL, 100, 0, 0, TEXT_ANVIL5, "Anvil of Fury" },
32  { 13, -1, DTYPE_NONE, Q_WARLORD, 100, 0, 0, TEXT_BLOODWAR, "Warlord of Blood" },
33  { 3, 3, DTYPE_CATHEDRAL, Q_SKELKING, 100, 1, 1, TEXT_KING2, "The Curse of King Leoric" },
34  { 2, -1, DTYPE_CAVES, Q_PWATER, 100, 4, 0, TEXT_POISON3, "Poisoned Water Supply" },
35  { 6, -1, DTYPE_CATACOMBS, Q_SCHAMB, 100, 2, 0, TEXT_BONER, "The Chamber of Bone" },
36  { 15, 15, DTYPE_CATHEDRAL, Q_BETRAYER, 100, 5, 1, TEXT_VILE1, "Archbishop Lazarus" },
37  // clang-format on
38 };
39 char questxoff[7] = { 0, -1, 0, -1, -2, -1, -2 };
40 char questyoff[7] = { 0, 0, -1, -1, -1, -2, -2 };
41 char *questtrigstr[5] = {
42  "King Leoric's Tomb",
43  "The Chamber of Bone",
44  "Maze",
45  "A Dark Passage",
46  "Unholy Altar"
47 };
52 
53 void InitQuests()
54 {
55  int i, initiatedQuests;
56  DWORD z;
57 
58  if (gbMaxPlayers == 1) {
59  for (i = 0; i < MAXQUESTS; i++) {
61  }
62  } else {
63  for (i = 0; i < MAXQUESTS; i++) {
64  if (!(questlist[i]._qflags & 1)) {
66  }
67  }
68  }
69 
70  questlog = FALSE;
71  PentSpn2Frame = 1;
72  WaterDone = 0;
73  initiatedQuests = 0;
74 
75  for (z = 0; z < MAXQUESTS; z++) {
76  if (gbMaxPlayers <= 1 || questlist[z]._qflags & 1) {
78  if (gbMaxPlayers > 1) {
80  if (!delta_quest_inited(initiatedQuests)) {
82  quests[z]._qvar1 = 0;
83  quests[z]._qlog = 0;
84  }
85  initiatedQuests++;
86  } else {
89  quests[z]._qvar1 = 0;
90  quests[z]._qlog = 0;
91  }
92 
93  quests[z]._qslvl = questlist[z]._qslvl;
94  quests[z]._qtx = 0;
95  quests[z]._qty = 0;
96  quests[z]._qidx = z;
98  quests[z]._qvar2 = 0;
99  quests[z]._qmsg = questlist[z]._qdmsg;
100  }
101  }
102 
103  if (gbMaxPlayers == 1) {
104  SetRndSeed(glSeedTbl[15]);
105  if (random_(0, 2))
107  else
109 
110  quests[QuestGroup1[random_(0, sizeof(QuestGroup1) / sizeof(int))]]._qactive = QUEST_NOTAVAIL;
111  quests[QuestGroup2[random_(0, sizeof(QuestGroup2) / sizeof(int))]]._qactive = QUEST_NOTAVAIL;
112  quests[QuestGroup3[random_(0, sizeof(QuestGroup3) / sizeof(int))]]._qactive = QUEST_NOTAVAIL;
113  quests[QuestGroup4[random_(0, sizeof(QuestGroup4) / sizeof(int))]]._qactive = QUEST_NOTAVAIL;
114  }
115 #ifdef _DEBUG
116  if (questdebug != -1)
117  quests[questdebug]._qactive = QUEST_ACTIVE;
118 #endif
119 
120 #ifdef SPAWN
121  for (z = 0; z < MAXQUESTS; z++) {
123  }
124 #endif
125 
126  if (!quests[Q_SKELKING]._qactive)
127  quests[Q_SKELKING]._qvar2 = 2;
128  if (!quests[Q_ROCK]._qactive)
129  quests[Q_ROCK]._qvar2 = 2;
130  quests[Q_LTBANNER]._qvar1 = 1;
131  if (gbMaxPlayers != 1)
132  quests[Q_BETRAYER]._qvar1 = 2;
133 }
134 
136 {
137 #ifndef SPAWN
138  int i, rportx, rporty;
139 
140  if (QuestStatus(Q_BETRAYER) && gbMaxPlayers != 1 && quests[Q_BETRAYER]._qvar1 == 2) {
141  AddObject(OBJ_ALTBOY, 2 * setpc_x + 20, 2 * setpc_y + 22);
142  quests[Q_BETRAYER]._qvar1 = 3;
144  }
145 
146  if (gbMaxPlayers != 1) {
147  return;
148  }
149 
150  if (currlevel == quests[Q_BETRAYER]._qlevel
151  && !setlevel
152  && quests[Q_BETRAYER]._qvar1 >= 2
153  && (quests[Q_BETRAYER]._qactive == QUEST_ACTIVE || quests[Q_BETRAYER]._qactive == QUEST_DONE)
154  && (quests[Q_BETRAYER]._qvar2 == 0 || quests[Q_BETRAYER]._qvar2 == 2)) {
157  rportx = quests[Q_BETRAYER]._qtx;
158  rporty = quests[Q_BETRAYER]._qty;
159  AddMissile(rportx, rporty, rportx, rporty, 0, MIS_RPORTAL, 0, myplr, 0, 0);
160  quests[Q_BETRAYER]._qvar2 = 1;
161  if (quests[Q_BETRAYER]._qactive == QUEST_ACTIVE) {
162  quests[Q_BETRAYER]._qvar1 = 3;
163  }
164  }
165 
166  if (quests[Q_BETRAYER]._qactive == QUEST_DONE
167  && setlevel
169  && quests[Q_BETRAYER]._qvar2 == 4) {
170  rportx = 35;
171  rporty = 32;
172  AddMissile(rportx, rporty, rportx, rporty, 0, MIS_RPORTAL, 0, myplr, 0, 0);
173  quests[Q_BETRAYER]._qvar2 = 3;
174  }
175 
176  if (setlevel) {
177  if (setlvlnum == quests[Q_PWATER]._qslvl
178  && quests[Q_PWATER]._qactive != QUEST_INIT
179  && leveltype == quests[Q_PWATER]._qlvltype
180  && nummonsters == 4
181  && quests[Q_PWATER]._qactive != QUEST_DONE) {
183  PlaySfxLoc(IS_QUESTDN, plr[myplr].WorldX, plr[myplr].WorldY);
184  LoadPalette("Levels\\L3Data\\L3pwater.pal");
185  WaterDone = 32;
186  }
187  if (WaterDone > 0) {
189  WaterDone--;
190  }
191  } else if (plr[myplr]._pmode == PM_STAND) {
192  for (i = 0; i < MAXQUESTS; i++) {
193  if (currlevel == quests[i]._qlevel
194  && quests[i]._qslvl != 0
195  && quests[i]._qactive != QUEST_NOTAVAIL
196  && plr[myplr].WorldX == quests[i]._qtx
197  && plr[myplr].WorldY == quests[i]._qty) {
198  if (quests[i]._qlvltype != DTYPE_NONE) {
200  }
201  StartNewLvl(myplr, WM_DIABSETLVL, quests[i]._qslvl);
202  }
203  }
204  }
205 #endif
206 }
207 
209 {
210 #ifndef SPAWN
211  int i, j, qx, qy, ql;
212 
213  if (gbMaxPlayers != 1) {
214  return FALSE;
215  }
216 
217  for (i = 0; i < MAXQUESTS; i++) {
218 
219  if (i != Q_BETRAYER && currlevel == quests[i]._qlevel && quests[i]._qslvl != 0) {
220  ql = quests[quests[i]._qidx]._qslvl - 1;
221  qx = quests[i]._qtx;
222  qy = quests[i]._qty;
223 
224  for (j = 0; j < 7; j++) {
225  if (qx + questxoff[j] == cursmx && qy + questyoff[j] == cursmy) {
226  sprintf(infostr, "To %s", questtrigstr[ql]);
227  cursmx = qx;
228  cursmy = qy;
229  return TRUE;
230  }
231  }
232  }
233  }
234 #endif
235 
236  return FALSE;
237 }
238 
239 BOOL QuestStatus(int i)
240 {
241  BOOL result;
242 
243  if (setlevel
244  || currlevel != quests[i]._qlevel
245  || !quests[i]._qactive
246  || (result = 1, gbMaxPlayers != 1) && !(questlist[i]._qflags & 1)) {
247  result = FALSE;
248  }
249  return result;
250 }
251 
252 void CheckQuestKill(int m, BOOL sendmsg)
253 {
254 #ifndef SPAWN
255  int i, j;
256 
257  if (monster[m].MType->mtype == MT_SKING) {
259  sfxdelay = 30;
260  if (plr[myplr]._pClass == PC_WARRIOR) {
261  sfxdnum = PS_WARR82;
262  } else if (plr[myplr]._pClass == PC_ROGUE) {
264  } else if (plr[myplr]._pClass == PC_SORCERER) {
265  sfxdnum = PS_MAGE82;
266  }
267  if (sendmsg)
269 
270  } else if (monster[m].MType->mtype == MT_CLEAVER) {
272  sfxdelay = 30;
273  if (plr[myplr]._pClass == PC_WARRIOR) {
274  sfxdnum = PS_WARR80;
275  } else if (plr[myplr]._pClass == PC_ROGUE) {
277  } else if (plr[myplr]._pClass == PC_SORCERER) {
278  sfxdnum = PS_MAGE80;
279  }
280  if (sendmsg)
281  NetSendCmdQuest(TRUE, Q_BUTCHER);
282  } else if (monster[m].mName == UniqMonst[UMT_GARBUD].mName) { //"Gharbad the Weak"
284  sfxdelay = 30;
285  if (plr[myplr]._pClass == PC_WARRIOR) {
286  sfxdnum = PS_WARR61;
287  } else if (plr[myplr]._pClass == PC_ROGUE) {
289  } else if (plr[myplr]._pClass == PC_SORCERER) {
290  sfxdnum = PS_MAGE61;
291  }
292  } else if (monster[m].mName == UniqMonst[UMT_ZHAR].mName) { //"Zhar the Mad"
294  sfxdelay = 30;
295  if (plr[myplr]._pClass == PC_WARRIOR) {
296  sfxdnum = PS_WARR62;
297  } else if (plr[myplr]._pClass == PC_ROGUE) {
299  } else if (plr[myplr]._pClass == PC_SORCERER) {
300  sfxdnum = PS_MAGE62;
301  }
302  } else if (monster[m].mName == UniqMonst[UMT_LAZURUS].mName && gbMaxPlayers != 1) { //"Arch-Bishop Lazarus"
304  quests[Q_BETRAYER]._qvar1 = 7;
305  sfxdelay = 30;
307 
308  for (j = 0; j < MAXDUNY; j++) {
309  for (i = 0; i < MAXDUNX; i++) {
310  if (dPiece[i][j] == 370) {
311  trigs[numtrigs]._tx = i;
312  trigs[numtrigs]._ty = j;
314  numtrigs++;
315  }
316  }
317  }
318  if (plr[myplr]._pClass == PC_WARRIOR) {
319  sfxdnum = PS_WARR83;
320  } else if (plr[myplr]._pClass == PC_ROGUE) {
322  } else if (plr[myplr]._pClass == PC_SORCERER) {
323  sfxdnum = PS_MAGE83;
324  }
325  if (sendmsg) {
327  NetSendCmdQuest(TRUE, Q_DIABLO);
328  }
329  } else if (monster[m].mName == UniqMonst[UMT_LAZURUS].mName && gbMaxPlayers == 1) { //"Arch-Bishop Lazarus"
331  sfxdelay = 30;
332  InitVPTriggers();
333  quests[Q_BETRAYER]._qvar1 = 7;
334  quests[Q_BETRAYER]._qvar2 = 4;
336  AddMissile(35, 32, 35, 32, 0, MIS_RPORTAL, 0, myplr, 0, 0);
337  if (plr[myplr]._pClass == PC_WARRIOR) {
338  sfxdnum = PS_WARR83;
339  } else if (plr[myplr]._pClass == PC_ROGUE) {
341  } else if (plr[myplr]._pClass == PC_SORCERER) {
342  sfxdnum = PS_MAGE83;
343  }
344  } else if (monster[m].mName == UniqMonst[UMT_WARLORD].mName) { //"Warlord of Blood"
346  sfxdelay = 30;
347  if (plr[myplr]._pClass == PC_WARRIOR) {
348  sfxdnum = PS_WARR94;
349  } else if (plr[myplr]._pClass == PC_ROGUE) {
351  } else if (plr[myplr]._pClass == PC_SORCERER) {
352  sfxdnum = PS_MAGE94;
353  }
354  }
355 #endif
356 }
357 
359 {
360  int x, y;
361 
362  x = 2 * setpc_x + 16;
363  y = 2 * setpc_y + 16;
364  DRLG_RectTrans(x + 3, y + 3, x + 10, y + 10);
365 }
366 
367 void DrawSkelKing(int q, int x, int y)
368 {
369  quests[q]._qtx = 2 * x + 28;
370  quests[q]._qty = 2 * y + 23;
371 }
372 
373 void DrawWarLord(int x, int y)
374 {
375  int rw, rh;
376  int i, j;
377  BYTE *sp, *setp;
378  int v;
379 
380  setp = LoadFileInMem("Levels\\L4Data\\Warlord2.DUN", NULL);
381  rw = *setp;
382  sp = setp + 2;
383  rh = *sp;
384  sp += 2;
385  setpc_w = rw;
386  setpc_h = rh;
387  setpc_x = x;
388  setpc_y = y;
389  for (j = y; j < y + rh; j++) {
390  for (i = x; i < x + rw; i++) {
391  if (*sp != 0) {
392  v = *sp;
393  } else {
394  v = 6;
395  }
396  dungeon[i][j] = v;
397  sp += 2;
398  }
399  }
400  mem_free_dbg(setp);
401 }
402 
403 void DrawSChamber(int q, int x, int y)
404 {
405  int i, j;
406  int rw, rh;
407  int xx, yy;
408  BYTE *sp, *setp;
409  int v;
410 
411  setp = LoadFileInMem("Levels\\L2Data\\Bonestr1.DUN", NULL);
412  rw = *setp;
413  sp = setp + 2;
414  rh = *sp;
415  sp += 2;
416  setpc_w = rw;
417  setpc_h = rh;
418  setpc_x = x;
419  setpc_y = y;
420  for (j = y; j < y + rh; j++) {
421  for (i = x; i < x + rw; i++) {
422  if (*sp != 0) {
423  v = *sp;
424  } else {
425  v = 3;
426  }
427  dungeon[i][j] = v;
428  sp += 2;
429  }
430  }
431  xx = 2 * x + 22;
432  yy = 2 * y + 23;
433  quests[q]._qtx = xx;
434  quests[q]._qty = yy;
435  mem_free_dbg(setp);
436 }
437 
438 void DrawLTBanner(int x, int y)
439 {
440  int rw, rh;
441  int i, j;
442  BYTE *sp, *setp;
443 
444  setp = LoadFileInMem("Levels\\L1Data\\Banner1.DUN", NULL);
445  rw = *setp;
446  sp = setp + 2;
447  rh = *sp;
448  sp += 2;
449  setpc_w = rw;
450  setpc_h = rh;
451  setpc_x = x;
452  setpc_y = y;
453  for (j = 0; j < rh; j++) {
454  for (i = 0; i < rw; i++) {
455  if (*sp != 0) {
456  pdungeon[x + i][y + j] = *sp;
457  }
458  sp += 2;
459  }
460  }
461  mem_free_dbg(setp);
462 }
463 
464 void DrawBlind(int x, int y)
465 {
466  int rw, rh;
467  int i, j;
468  BYTE *sp, *setp;
469 
470  setp = LoadFileInMem("Levels\\L2Data\\Blind1.DUN", NULL);
471  rw = *setp;
472  sp = setp + 2;
473  rh = *sp;
474  sp += 2;
475  setpc_x = x;
476  setpc_y = y;
477  setpc_w = rw;
478  setpc_h = rh;
479  for (j = 0; j < rh; j++) {
480  for (i = 0; i < rw; i++) {
481  if (*sp != 0) {
482  pdungeon[x + i][y + j] = *sp;
483  }
484  sp += 2;
485  }
486  }
487  mem_free_dbg(setp);
488 }
489 
490 void DrawBlood(int x, int y)
491 {
492  int rw, rh;
493  int i, j;
494  BYTE *sp, *setp;
495 
496  setp = LoadFileInMem("Levels\\L2Data\\Blood2.DUN", NULL);
497  rw = *setp;
498  sp = setp + 2;
499  rh = *sp;
500  sp += 2;
501  setpc_x = x;
502  setpc_y = y;
503  setpc_w = rw;
504  setpc_h = rh;
505  for (j = 0; j < rh; j++) {
506  for (i = 0; i < rw; i++) {
507  if (*sp != 0) {
508  dungeon[x + i][y + j] = *sp;
509  }
510  sp += 2;
511  }
512  }
513  mem_free_dbg(setp);
514 }
515 
516 void DRLG_CheckQuests(int x, int y)
517 {
518  int i;
519 
520  for (i = 0; i < MAXQUESTS; i++) {
521  if (QuestStatus(i)) {
522  switch (quests[i]._qtype) {
523  case Q_BUTCHER:
524  DrawButcher();
525  break;
526  case Q_LTBANNER:
527  DrawLTBanner(x, y);
528  break;
529  case Q_BLIND:
530  DrawBlind(x, y);
531  break;
532  case Q_BLOOD:
533  DrawBlood(x, y);
534  break;
535  case Q_WARLORD:
536  DrawWarLord(x, y);
537  break;
538  case Q_SKELKING:
539  DrawSkelKing(i, x, y);
540  break;
541  case Q_SCHAMB:
542  DrawSChamber(i, x, y);
543  break;
544  }
545  }
546  }
547 }
548 
550 {
551  switch (setlvlnum) {
552  case SL_SKELKING:
557  break;
558  case SL_BONECHAMB:
563  break;
564  case SL_POISONWATER:
569  break;
570  case SL_VILEBETRAYER:
575  break;
576  }
577 }
578 
580 {
581  if (quests[Q_BETRAYER]._qactive == QUEST_DONE)
582  quests[Q_BETRAYER]._qvar2 = 2;
583  ViewX = ReturnLvlX;
584  ViewY = ReturnLvlY;
587 }
588 
590 {
591 #ifndef SPAWN
592  if (quests[Q_SKELKING]._qactive == QUEST_INIT
593  && currlevel >= quests[Q_SKELKING]._qlevel - 1
594  && currlevel <= quests[Q_SKELKING]._qlevel + 1) {
597  }
598  if (quests[Q_BUTCHER]._qactive == QUEST_INIT
599  && currlevel >= quests[Q_BUTCHER]._qlevel - 1
600  && currlevel <= quests[Q_BUTCHER]._qlevel + 1) {
602  NetSendCmdQuest(TRUE, Q_BUTCHER);
603  }
604  if (quests[Q_BETRAYER]._qactive == QUEST_INIT && currlevel == quests[Q_BETRAYER]._qlevel - 1) {
607  }
608  if (QuestStatus(Q_BETRAYER))
609  AddObject(OBJ_ALTBOY, 2 * setpc_x + 20, 2 * setpc_y + 22);
610 #endif
611 }
612 
614 {
615 #ifndef SPAWN
616  int i, tren, x, y;
617 
618  if (setlevel && setlvlnum == quests[Q_PWATER]._qslvl && quests[Q_PWATER]._qactive != QUEST_INIT && leveltype == quests[Q_PWATER]._qlvltype) {
619 
620  if (quests[Q_PWATER]._qactive == QUEST_DONE)
621  LoadPalette("Levels\\L3Data\\L3pwater.pal");
622  else
623  LoadPalette("Levels\\L3Data\\L3pfoul.pal");
624 
625  for (i = 0; i <= 32; i++)
627  }
628 
629  if (QuestStatus(Q_LTBANNER)) {
630  if (quests[Q_LTBANNER]._qvar1 == 1)
632  setpc_w + setpc_x - 2,
633  setpc_h + setpc_y - 2,
634  setpc_w + setpc_x + 1,
635  setpc_h + setpc_y + 1);
636  if (quests[Q_LTBANNER]._qvar1 == 2) {
638  setpc_w + setpc_x - 2,
639  setpc_h + setpc_y - 2,
640  setpc_w + setpc_x + 1,
641  setpc_h + setpc_y + 1);
642  ObjChangeMapResync(setpc_x, setpc_y, (setpc_w >> 1) + setpc_x + 2, (setpc_h >> 1) + setpc_y - 2);
643  for (i = 0; i < nobjects; i++)
645  tren = TransVal;
646  TransVal = 9;
647  DRLG_MRectTrans(setpc_x, setpc_y, (setpc_w >> 1) + setpc_x + 4, setpc_y + (setpc_h >> 1));
648  TransVal = tren;
649  }
650  if (quests[Q_LTBANNER]._qvar1 == 3) {
651  x = setpc_x;
652  y = setpc_y;
653  ObjChangeMapResync(x, y, x + setpc_w + 1, y + setpc_h + 1);
654  for (i = 0; i < nobjects; i++)
656  tren = TransVal;
657  TransVal = 9;
658  DRLG_MRectTrans(setpc_x, setpc_y, (setpc_w >> 1) + setpc_x + 4, setpc_y + (setpc_h >> 1));
659  TransVal = tren;
660  }
661  }
662  if (currlevel == quests[Q_MUSHROOM]._qlevel) {
663  if (quests[Q_MUSHROOM]._qactive == QUEST_INIT && !quests[Q_MUSHROOM]._qvar1) {
664  SpawnQuestItem(IDI_FUNGALTM, 0, 0, 5, 1);
666  } else {
667  if (quests[Q_MUSHROOM]._qactive == QUEST_ACTIVE) {
668  if (quests[Q_MUSHROOM]._qvar1 >= QS_MUSHGIVEN) {
671  } else if (quests[Q_MUSHROOM]._qvar1 >= QS_BRAINGIVEN) {
673  }
674  }
675  }
676  }
677  if (currlevel == quests[Q_VEIL]._qlevel + 1 && quests[Q_VEIL]._qactive == QUEST_ACTIVE && !quests[Q_VEIL]._qvar1) {
678  quests[Q_VEIL]._qvar1 = 1;
679  SpawnQuestItem(IDI_GLDNELIX, 0, 0, 5, 1);
680  }
681  if (setlevel && setlvlnum == SL_VILEBETRAYER) {
682  if (quests[Q_BETRAYER]._qvar1 >= 4)
683  ObjChangeMapResync(1, 11, 20, 18);
684  if (quests[Q_BETRAYER]._qvar1 >= 6)
685  ObjChangeMapResync(1, 18, 20, 24);
686  if (quests[Q_BETRAYER]._qvar1 >= 7)
687  InitVPTriggers();
688  for (i = 0; i < nobjects; i++)
690  }
691  if (currlevel == quests[Q_BETRAYER]._qlevel
692  && !setlevel
693  && (quests[Q_BETRAYER]._qvar2 == 1 || quests[Q_BETRAYER]._qvar2 >= 3)
694  && (quests[Q_BETRAYER]._qactive == QUEST_ACTIVE || quests[Q_BETRAYER]._qactive == QUEST_DONE)) {
695  quests[Q_BETRAYER]._qvar2 = 2;
696  }
697 #endif
698 }
699 
700 void PrintQLString(int x, int y, BOOL cjustflag, char *str, int col)
701 {
702  int len, width, i, k, sx, sy;
703  BYTE c;
704 
705  sx = x + 96;
706  sy = y * 12 + 204;
707  len = strlen(str);
708  k = 0;
709  if (cjustflag) {
710  width = 0;
711  for (i = 0; i < len; i++)
712  width += fontkern[fontframe[gbFontTransTbl[(BYTE)str[i]]]] + 1;
713  if (width < 257)
714  k = (257 - width) >> 1;
715  sx += k;
716  }
717  if (qline == y) {
718  CelDraw(cjustflag ? x + k + 76 : x + 76, sy + 1, pSPentSpn2Cels, PentSpn2Frame, 12);
719  }
720  for (i = 0; i < len; i++) {
721  c = fontframe[gbFontTransTbl[(BYTE)str[i]]];
722  k += fontkern[c] + 1;
723  if (c && k <= 257) {
724  PrintChar(sx, sy, c, col);
725  }
726  sx += fontkern[c] + 1;
727  }
728  if (qline == y) {
729  CelDraw(cjustflag ? x + k + 100 : 340 - x, sy + 1, pSPentSpn2Cels, PentSpn2Frame, 12);
730  }
731 }
732 
734 {
735  int y, i;
736 
737  PrintQLString(0, 2, TRUE, "Quest Log", 3);
739  y = qtopline;
740  for (i = 0; i < numqlines; i++) {
741  PrintQLString(0, y, TRUE, questlist[qlist[i]]._qlstr, 0);
742  y += 2;
743  }
744  PrintQLString(0, 22, TRUE, "Close Quest Log", 0);
745  PentSpn2Spin();
746 }
747 
749 {
750  DWORD i;
751 
752  numqlines = 0;
753  for (i = 0; i < MAXQUESTS; i++) {
754  if (quests[i]._qactive == QUEST_ACTIVE && quests[i]._qlog) {
755  qlist[numqlines] = i;
756  numqlines++;
757  }
758  }
759  if (numqlines > 5) {
760  qtopline = 5 - (numqlines >> 1);
761  } else {
762  qtopline = 8;
763  }
764  qline = 22;
765  if (numqlines != 0)
766  qline = qtopline;
767  questlog = TRUE;
768  PentSpn2Frame = 1;
769 }
770 
772 {
773  if (numqlines) {
774  if (qline == qtopline) {
775  qline = 22;
776  } else if (qline == 22) {
777  qline = qtopline + 2 * numqlines - 2;
778  } else {
779  qline -= 2;
780  }
782  }
783 }
784 
786 {
787  if (numqlines) {
788  if (qline == 22) {
789  qline = qtopline;
790  } else if (qline == qtopline + 2 * numqlines - 2) {
791  qline = 22;
792  } else {
793  qline += 2;
794  }
796  }
797 }
798 
800 {
802  if (numqlines && qline != 22)
803  InitQTextMsg(quests[qlist[(qline - qtopline) >> 1]]._qmsg);
804  questlog = FALSE;
805 }
806 
808 {
809  int y, i;
810 
811  y = (MouseY - 32) / 12;
812  if (numqlines) {
813  for (i = 0; i < numqlines; i++) {
814  if (y == qtopline + 2 * i) {
815  qline = y;
816  QuestlogEnter();
817  }
818  }
819  }
820  if (y == 22) {
821  qline = 22;
822  QuestlogEnter();
823  }
824 }
825 
826 void SetMultiQuest(int q, int s, int l, int v1)
827 {
828 #ifndef SPAWN
829  if (quests[q]._qactive != QUEST_DONE) {
830  if (s > quests[q]._qactive)
831  quests[q]._qactive = s;
832  quests[q]._qlog |= l;
833  if (v1 > quests[q]._qvar1)
834  quests[q]._qvar1 = v1;
835  }
836 #endif
837 }
838 
QuestStruct::_qtx
int _qtx
Definition: structs.h:975
QuestlogEnter
void QuestlogEnter()
Definition: quests.cpp:799
SyncObjectAnim
void SyncObjectAnim(int o)
Definition: objects.cpp:4267
PS_MAGE82
@ PS_MAGE82
Definition: enums.h:894
cursmx
int cursmx
Definition: cursor.cpp:24
MIS_RPORTAL
@ MIS_RPORTAL
Definition: enums.h:1259
quests
QuestStruct quests[MAXQUESTS]
Definition: quests.cpp:8
Q_ANVIL
@ Q_ANVIL
Definition: enums.h:2558
TEXT_VILE3
@ TEXT_VILE3
Definition: enums.h:1572
UniqMonst
UniqMonstStruct UniqMonst[]
Definition: monstdat.cpp:264
PS_ROGUE94
@ PS_ROGUE94
Definition: enums.h:1009
setpc_w
int setpc_w
Definition: gendung.cpp:71
TOWN_HEALER
@ TOWN_HEALER
Definition: enums.h:2272
QuestData::_qdmsg
int _qdmsg
Definition: structs.h:993
MouseY
int MouseY
Definition: diablo.cpp:17
IS_TITLEMOV
@ IS_TITLEMOV
Definition: enums.h:352
pQLogCel
BYTE * pQLogCel
Definition: quests.cpp:7
IDI_FUNGALTM
@ IDI_FUNGALTM
Definition: enums.h:2519
UMT_GARBUD
@ UMT_GARBUD
Definition: enums.h:1490
currlevel
BYTE currlevel
Definition: gendung.cpp:40
Q_BUTCHER
@ Q_BUTCHER
Definition: enums.h:2554
QS_BRAINGIVEN
@ QS_BRAINGIVEN
Definition: enums.h:2581
PS_WARR62
@ PS_WARR62
Definition: enums.h:1086
UMT_WARLORD
@ UMT_WARLORD
Definition: enums.h:1498
setpc_h
int setpc_h
Definition: gendung.cpp:70
Qtalklist
QuestTalkData Qtalklist[11]
Definition: towners.cpp:96
ReturnLvlY
int ReturnLvlY
Definition: quests.cpp:13
WaterDone
int WaterDone
Definition: quests.cpp:12
SCREEN_Y
#define SCREEN_Y
Definition: defs.h:126
QuestStatus
BOOL QuestStatus(int i)
Definition: quests.cpp:239
setpc_x
int setpc_x
Definition: gendung.cpp:72
Q_MUSHROOM
@ Q_MUSHROOM
Definition: enums.h:2549
QuestData::_qdmultlvl
char _qdmultlvl
Definition: structs.h:987
SetRndSeed
void SetRndSeed(int s)
Set the RNG seed.
Definition: engine.cpp:728
delta_quest_inited
BOOL delta_quest_inited(int i)
Definition: msg.cpp:406
dungeon
BYTE dungeon[DMAXX][DMAXY]
Definition: gendung.cpp:18
DTYPE_CATACOMBS
@ DTYPE_CATACOMBS
Definition: enums.h:1870
pdungeon
BYTE pdungeon[DMAXX][DMAXY]
Definition: gendung.cpp:20
nobjects
int nobjects
Definition: objects.cpp:10
UMT_ZHAR
@ UMT_ZHAR
Definition: enums.h:1492
IS_QUESTDN
@ IS_QUESTDN
Definition: enums.h:295
CheckQuests
void CheckQuests()
Definition: quests.cpp:135
TEXT_ZHAR1
@ TEXT_ZHAR1
Definition: enums.h:1695
SL_VILEBETRAYER
@ SL_VILEBETRAYER
Definition: enums.h:2544
PS_WARR80
@ PS_WARR80
Definition: enums.h:1106
MAXDUNX
#define MAXDUNX
Definition: defs.h:25
pSPentSpn2Cels
BYTE * pSPentSpn2Cels
Definition: stores.cpp:31
PentSpn2Frame
BYTE PentSpn2Frame
Definition: stores.cpp:32
PS_MAGE94
@ PS_MAGE94
Definition: enums.h:906
QuestlogESC
void QuestlogESC()
Definition: quests.cpp:807
SetReturnLvlPos
void SetReturnLvlPos()
Definition: quests.cpp:549
questlog
BOOL questlog
Definition: quests.cpp:6
TEXT_BUTCH9
@ TEXT_BUTCH9
Definition: enums.h:1610
ResyncQuests
void ResyncQuests()
Definition: quests.cpp:613
ViewX
int ViewX
Definition: gendung.cpp:73
questyoff
char questyoff[7]
Definition: quests.cpp:40
PS_MAGE62
@ PS_MAGE62
Definition: enums.h:873
PentSpn2Spin
void PentSpn2Spin()
Definition: stores.cpp:76
CheckQuestKill
void CheckQuestKill(int m, BOOL sendmsg)
Definition: quests.cpp:252
QuestStruct::_qlevel
unsigned char _qlevel
Definition: structs.h:971
SpawnQuestItem
void SpawnQuestItem(int itemid, int x, int y, int randarea, int selflag)
Definition: items.cpp:2324
all.h
ViewY
int ViewY
Definition: gendung.cpp:74
QuestStruct::_qactive
unsigned char _qactive
Definition: structs.h:973
questtrigstr
char * questtrigstr[5]
Definition: quests.cpp:41
QuestData::_qlvlt
unsigned char _qlvlt
Definition: structs.h:988
PS_ROGUE62
@ PS_ROGUE62
Definition: enums.h:976
QuestlogUp
void QuestlogUp()
Definition: quests.cpp:771
QuestData::_qdtype
unsigned char _qdtype
Definition: structs.h:989
SL_BONECHAMB
@ SL_BONECHAMB
Definition: enums.h:2541
QuestGroup1
int QuestGroup1[3]
Definition: quests.cpp:48
QuestGroup3
int QuestGroup3[3]
Definition: quests.cpp:50
infostr
char infostr[256]
Definition: control.cpp:52
TEXT_ANVIL5
@ TEXT_ANVIL5
Definition: enums.h:1635
UMT_LAZURUS
@ UMT_LAZURUS
Definition: enums.h:1494
gbMaxPlayers
BYTE gbMaxPlayers
Specifies the maximum number of players in a game, where 1 represents a single player game and 4 repr...
Definition: multi.cpp:34
SetMultiQuest
void SetMultiQuest(int q, int s, int l, int v1)
Definition: quests.cpp:826
NetSendCmdQuest
void NetSendCmdQuest(BOOL bHiPri, BYTE q)
Definition: msg.cpp:737
PS_ROGUE82
@ PS_ROGUE82
Definition: enums.h:997
Q_PWATER
@ Q_PWATER
Definition: enums.h:2561
AddMissile
int AddMissile(int sx, int sy, int dx, int dy, int midir, int mitype, char micaster, int id, int midam, int spllvl)
Definition: missiles.cpp:2455
QS_MUSHGIVEN
@ QS_MUSHGIVEN
Definition: enums.h:2579
SL_POISONWATER
@ SL_POISONWATER
Definition: enums.h:2543
MAXDUNY
#define MAXDUNY
Definition: defs.h:26
TEXT_INFRA5
@ TEXT_INFRA5
Definition: enums.h:1662
ResyncMPQuests
void ResyncMPQuests()
Definition: quests.cpp:589
dPiece
int dPiece[MAXDUNX][MAXDUNY]
Definition: gendung.cpp:26
DRLG_MRectTrans
void DRLG_MRectTrans(int x1, int y1, int x2, int y2)
Definition: gendung.cpp:178
palette_update_quest_palette
void palette_update_quest_palette(int n)
Definition: palette.cpp:215
QuestData
Definition: structs.h:985
Q_BETRAYER
@ Q_BETRAYER
Definition: enums.h:2563
ObjChangeMapResync
void ObjChangeMapResync(int x1, int y1, int x2, int y2)
Definition: objects.cpp:2330
qtopline
DEVILUTION_BEGIN_NAMESPACE int qtopline
Definition: quests.cpp:5
TransVal
char TransVal
Definition: gendung.cpp:23
DrawQuestLog
void DrawQuestLog()
Definition: quests.cpp:733
PS_ROGUE83
@ PS_ROGUE83
Definition: enums.h:998
ReturnLvlT
int ReturnLvlT
Definition: quests.cpp:15
TEXT_BLINDING
@ TEXT_BLINDING
Definition: enums.h:1784
QuestGroup4
int QuestGroup4[2]
Definition: quests.cpp:51
PS_ROGUE61
@ PS_ROGUE61
Definition: enums.h:975
DEVILUTION_END_NAMESPACE
#define DEVILUTION_END_NAMESPACE
Definition: types.h:10
PS_WARR82
@ PS_WARR82
Definition: enums.h:1108
DTYPE_NONE
@ DTYPE_NONE
Definition: enums.h:1873
monster
MonsterStruct monster[MAXMONSTERS]
Definition: monster.cpp:19
QuestGroup2
int QuestGroup2[3]
Definition: quests.cpp:49
PrintQLString
void PrintQLString(int x, int y, BOOL cjustflag, char *str, int col)
Definition: quests.cpp:700
sfxdnum
int sfxdnum
Definition: effects.cpp:13
SL_SKELKING
@ SL_SKELKING
Definition: enums.h:2540
Q_VEIL
@ Q_VEIL
Definition: enums.h:2552
TEXT_MUSH8
@ TEXT_MUSH8
Definition: enums.h:1675
PS_WARR83
@ PS_WARR83
Definition: enums.h:1109
TEXT_POISON3
@ TEXT_POISON3
Definition: enums.h:1586
trigs
TriggerStruct trigs[MAXTRIGGERS]
Definition: trigs.cpp:8
MT_CLEAVER
@ MT_CLEAVER
Definition: enums.h:1425
LoadFileInMem
BYTE * LoadFileInMem(char *pszName, DWORD *pdwFileLen)
Load a file in to a buffer.
Definition: engine.cpp:801
CelDraw
void CelDraw(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth)
Blit CEL sprite to the back buffer at the given coordinates.
Definition: engine.cpp:47
TEXT_VEIL9
@ TEXT_VEIL9
Definition: enums.h:1628
questxoff
char questxoff[7]
Definition: quests.cpp:39
GetReturnLvlPos
void GetReturnLvlPos()
Definition: quests.cpp:579
objectactive
int objectactive[MAXOBJECTS]
Definition: objects.cpp:9
QuestTalkData::_qblkm
int _qblkm
Definition: structs.h:1084
PS_MAGE61
@ PS_MAGE61
Definition: enums.h:872
QuestStruct::_qmsg
unsigned char _qmsg
Definition: structs.h:979
QUEST_DONE
@ QUEST_DONE
Definition: enums.h:2570
TriggerStruct::_tmsg
int _tmsg
Definition: structs.h:1509
QUEST_NOTAVAIL
@ QUEST_NOTAVAIL
Definition: enums.h:2567
sfxdelay
DEVILUTION_BEGIN_NAMESPACE int sfxdelay
Definition: effects.cpp:12
TriggerStruct::_ty
int _ty
Definition: structs.h:1508
TEXT_BONER
@ TEXT_BONER
Definition: enums.h:1782
StartQuestlog
void StartQuestlog()
Definition: quests.cpp:748
Q_SCHAMB
@ Q_SCHAMB
Definition: enums.h:2562
Q_BLIND
@ Q_BLIND
Definition: enums.h:2556
IS_TITLSLCT
@ IS_TITLSLCT
Definition: enums.h:353
Q_LTBANNER
@ Q_LTBANNER
Definition: enums.h:2555
QuestStruct
Definition: structs.h:970
PS_WARR94
@ PS_WARR94
Definition: enums.h:1120
fontkern
const BYTE fontkern[68]
Maps from smaltext.cel frame number to character width.
Definition: control.cpp:81
TEXT_MUSH3
@ TEXT_MUSH3
Definition: enums.h:1670
PlaySFX
void PlaySFX(int psfx)
Definition: effects.cpp:1043
MT_SKING
@ MT_SKING
Definition: enums.h:1424
TEXT_VILE1
@ TEXT_VILE1
Definition: enums.h:1570
QuestData::_qdlvl
unsigned char _qdlvl
Definition: structs.h:986
SPANEL_WIDTH
#define SPANEL_WIDTH
Definition: defs.h:139
setlevel
BOOLEAN setlevel
Definition: gendung.cpp:65
QuestData::_qslvl
unsigned char _qslvl
Definition: structs.h:991
numqlines
int numqlines
Definition: quests.cpp:11
Q_ROCK
@ Q_ROCK
Definition: enums.h:2548
QuestStruct::_qslvl
unsigned char _qslvl
Definition: structs.h:977
InitQTextMsg
void InitQTextMsg(int m)
Definition: minitext.cpp:70
Q_WARLORD
@ Q_WARLORD
Definition: enums.h:2559
InitQuests
void InitQuests()
Definition: quests.cpp:53
LoadPalette
void LoadPalette(char *pszFileName)
Definition: palette.cpp:76
DTYPE_HELL
@ DTYPE_HELL
Definition: enums.h:1872
MAXQUESTS
#define MAXQUESTS
Definition: defs.h:35
questlist
QuestData questlist[MAXQUESTS]
Definition: quests.cpp:18
DrawLTBanner
void DrawLTBanner(int x, int y)
Definition: quests.cpp:438
DTYPE_CAVES
@ DTYPE_CAVES
Definition: enums.h:1871
glSeedTbl
DWORD glSeedTbl[NUMLEVELS]
Definition: diablo.cpp:20
PS_MAGE83
@ PS_MAGE83
Definition: enums.h:895
nummonsters
int nummonsters
Definition: monster.cpp:17
DRLG_CheckQuests
void DRLG_CheckQuests(int x, int y)
Definition: quests.cpp:516
WM_DIABNEXTLVL
@ WM_DIABNEXTLVL
Definition: enums.h:2106
qlist
int qlist[MAXQUESTS]
Definition: quests.cpp:10
DrawBlood
void DrawBlood(int x, int y)
Definition: quests.cpp:490
setlvlnum
BYTE setlvlnum
Definition: gendung.cpp:58
DTYPE_CATHEDRAL
@ DTYPE_CATHEDRAL
Definition: enums.h:1869
PS_ROGUE80
@ PS_ROGUE80
Definition: enums.h:995
IDI_GLDNELIX
@ IDI_GLDNELIX
Definition: enums.h:2515
QuestStruct::_qty
int _qty
Definition: structs.h:976
myplr
int myplr
Definition: player.cpp:9
ReturnLvlX
int ReturnLvlX
Definition: quests.cpp:14
random_
int random_(BYTE idx, int v)
Main RNG function.
Definition: engine.cpp:752
Q_SKELKING
@ Q_SKELKING
Definition: enums.h:2560
QS_TOMESPAWNED
@ QS_TOMESPAWNED
Definition: enums.h:2575
cursmy
int cursmy
Definition: cursor.cpp:25
mem_free_dbg
void mem_free_dbg(void *p)
Multithreaded safe memfree.
Definition: engine.cpp:786
PC_WARRIOR
@ PC_WARRIOR
Definition: enums.h:2706
Q_ZHAR
@ Q_ZHAR
Definition: enums.h:2551
QUEST_ACTIVE
@ QUEST_ACTIVE
Definition: enums.h:2569
QuestStruct::_qvar1
unsigned char _qvar1
Definition: structs.h:980
DrawWarLord
void DrawWarLord(int x, int y)
Definition: quests.cpp:373
InitVPTriggers
void InitVPTriggers()
Definition: trigs.cpp:259
QuestStruct::_qlvltype
unsigned char _qlvltype
Definition: structs.h:974
StartNewLvl
void StartNewLvl(int pnum, int fom, int lvl)
Definition: player.cpp:1967
PC_ROGUE
@ PC_ROGUE
Definition: enums.h:2707
PlaySfxLoc
void PlaySfxLoc(int psfx, int x, int y)
Definition: effects.cpp:1142
DEVILUTION_BEGIN_NAMESPACE
Definition: sha.cpp:10
QuestStruct::_qlog
int _qlog
Definition: structs.h:982
QuestStruct::_qidx
unsigned char _qidx
Definition: structs.h:978
ForceQuests
BOOL ForceQuests()
Definition: quests.cpp:208
Q_DIABLO
@ Q_DIABLO
Definition: enums.h:2553
TEXT_BANNER2
@ TEXT_BANNER2
Definition: enums.h:1559
TOWN_WITCH
@ TOWN_WITCH
Definition: enums.h:2277
qline
int qline
Definition: quests.cpp:9
SCREEN_X
#define SCREEN_X
Definition: defs.h:125
DrawBlind
void DrawBlind(int x, int y)
Definition: quests.cpp:464
AddObject
void AddObject(int ot, int ox, int oy)
Definition: objects.cpp:1326
ReturnLvl
int ReturnLvl
Definition: quests.cpp:16
TEXT_KING2
@ TEXT_KING2
Definition: enums.h:1548
DrawSChamber
void DrawSChamber(int q, int x, int y)
Definition: quests.cpp:403
PrintChar
void PrintChar(int sx, int sy, int nCel, char col)
Print letter to the back buffer.
Definition: control.cpp:504
fontframe
const BYTE fontframe[128]
Maps from font index to smaltext.cel frame number.
Definition: control.cpp:65
PS_MAGE80
@ PS_MAGE80
Definition: enums.h:892
DrawButcher
void DrawButcher()
Definition: quests.cpp:358
TriggerStruct::_tx
int _tx
Definition: structs.h:1507
QUEST_INIT
@ QUEST_INIT
Definition: enums.h:2568
gbFontTransTbl
const BYTE gbFontTransTbl[256]
Maps ASCII character code to font index, as used by the small, medium and large sized fonts; which co...
Definition: control.cpp:106
numtrigs
int numtrigs
Definition: trigs.cpp:7
WM_DIABSETLVL
@ WM_DIABSETLVL
Definition: enums.h:2109
DrawSkelKing
void DrawSkelKing(int q, int x, int y)
Definition: quests.cpp:367
PM_STAND
@ PM_STAND
Definition: enums.h:2043
setpc_y
int setpc_y
Definition: gendung.cpp:75
TEXT_BLOODY
@ TEXT_BLOODY
Definition: enums.h:1783
DRLG_RectTrans
void DRLG_RectTrans(int x1, int y1, int x2, int y2)
Definition: gendung.cpp:196
OBJ_ALTBOY
@ OBJ_ALTBOY
Definition: enums.h:2412
leveltype
BYTE leveltype
Definition: gendung.cpp:39
QuestStruct::_qtype
unsigned char _qtype
Definition: structs.h:972
TEXT_GARBUD1
@ TEXT_GARBUD1
Definition: enums.h:1691
QuestStruct::_qvar2
unsigned char _qvar2
Definition: structs.h:981
plr
PlayerStruct plr[MAX_PLRS]
Definition: player.cpp:10
TEXT_BLOODWAR
@ TEXT_BLOODWAR
Definition: enums.h:1785
PC_SORCERER
@ PC_SORCERER
Definition: enums.h:2708
Q_BLOOD
@ Q_BLOOD
Definition: enums.h:2557
QuestlogDown
void QuestlogDown()
Definition: quests.cpp:785
setlvltype
char setlvltype
Definition: gendung.cpp:64
Q_GARBUD
@ Q_GARBUD
Definition: enums.h:2550
PS_WARR61
@ PS_WARR61
Definition: enums.h:1085