Devilution
Diablo devolved - magic behind the 1996 computer game
control.cpp
Go to the documentation of this file.
1 
6 #include "all.h"
7 
9 
12 BYTE *pDurIcons;
16 BOOL panbtn[8];
17 BOOL chrbtn[4];
18 BYTE *pMultiBtns;
20 BYTE *pChrPanel;
22 char sgszTalkSave[8][80];
27 BYTE *pPanelText;
28 BYTE *pLifeBuff;
29 BYTE *pBtmBuff;
30 BYTE *pTalkBtns;
31 BOOL pstrjust[4];
33 BOOL pinfoflag;
34 BOOL talkbtndown[3];
35 int pSpell;
36 BYTE *pManaBuff;
37 char infoclr;
39 BYTE *pGBoxBuff;
40 BYTE *pSBkBtnCel;
41 char tempstr[256];
42 BOOLEAN whisper[MAX_PLRS];
46 BOOL talkflag;
48 BOOL sbookflag;
49 BOOL chrflag;
52 char infostr[256];
55 char panelstr[4][64];
56 BOOL panelflag;
57 BYTE SplTransTbl[256];
59 BYTE *pSpellCels;
61 BYTE *pTalkPanel;
62 BOOL spselflag;
63 
65 const BYTE fontframe[128] = {
66  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
67  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
68  0, 54, 44, 57, 58, 56, 55, 47, 40, 41, 59, 39, 50, 37, 51, 52,
69  36, 27, 28, 29, 30, 31, 32, 33, 34, 35, 48, 49, 60, 38, 61, 53,
70  62, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
71  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 42, 63, 43, 64, 65,
72  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
73  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 40, 66, 41, 67, 0
74 };
75 
81 const BYTE fontkern[68] = {
82  8, 10, 7, 9, 8, 7, 6, 8, 8, 3,
83  3, 8, 6, 11, 9, 10, 6, 9, 9, 6,
84  9, 11, 10, 13, 10, 11, 7, 5, 7, 7,
85  8, 7, 7, 7, 7, 7, 10, 4, 5, 6,
86  3, 3, 4, 3, 6, 6, 3, 3, 3, 3,
87  3, 2, 7, 6, 3, 10, 10, 6, 6, 7,
88  4, 4, 9, 6, 6, 12, 3, 7
89 };
93 const int lineOffsets[5][5] = {
94  { 82 },
95  { 70, 94 },
96  { 64, 82, 100 },
97  { 60, 75, 89, 104 },
98  { 58, 70, 82, 94, 105 },
99 };
100 
106 const BYTE gbFontTransTbl[256] = {
107  // clang-format off
108  '\0', 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
109  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
110  ' ', '!', '\"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/',
111  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
112  '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
113  'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
114  '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
115  'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', 0x01,
116  'C', 'u', 'e', 'a', 'a', 'a', 'a', 'c', 'e', 'e', 'e', 'i', 'i', 'i', 'A', 'A',
117  'E', 'a', 'A', 'o', 'o', 'o', 'u', 'u', 'y', 'O', 'U', 'c', 'L', 'Y', 'P', 'f',
118  'a', 'i', 'o', 'u', 'n', 'N', 'a', 'o', '?', 0x01, 0x01, 0x01, 0x01, '!', '<', '>',
119  'o', '+', '2', '3', '\'', 'u', 'P', '.', ',', '1', '0', '>', 0x01, 0x01, 0x01, '?',
120  'A', 'A', 'A', 'A', 'A', 'A', 'A', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I',
121  'D', 'N', 'O', 'O', 'O', 'O', 'O', 'X', '0', 'U', 'U', 'U', 'U', 'Y', 'b', 'B',
122  'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i',
123  'o', 'n', 'o', 'o', 'o', 'o', 'o', '/', '0', 'u', 'u', 'u', 'u', 'y', 'b', 'y',
124  // clang-format on
125 };
126 
127 /* data */
128 
131  1,
132  1,
133  2,
134  3,
135  4,
136  5,
137  6,
138  7,
139  8,
140  9,
141  28,
142  13,
143  12,
144  18,
145  16,
146  14,
147  18,
148  19,
149  11,
150  20,
151  15,
152  21,
153  23,
154  24,
155  25,
156  22,
157  26,
158  29,
159  37,
160  38,
161  39,
162  42,
163  41,
164  40,
165  10,
166  36,
167  30,
168 };
170 int PanBtnPos[8][5] = {
171  // clang-format off
172  { PANEL_LEFT + 9, PANEL_TOP + 9, 71, 19, TRUE }, // char button
173  { PANEL_LEFT + 9, PANEL_TOP + 35, 71, 19, FALSE }, // quests button
174  { PANEL_LEFT + 9, PANEL_TOP + 75, 71, 19, TRUE }, // map button
175  { PANEL_LEFT + 9, PANEL_TOP + 101, 71, 19, FALSE }, // menu button
176  { PANEL_LEFT + 560, PANEL_TOP + 9, 71, 19, TRUE }, // inv button
177  { PANEL_LEFT + 560, PANEL_TOP + 35, 71, 19, FALSE }, // spells button
178  { PANEL_LEFT + 87, PANEL_TOP + 91, 33, 32, TRUE }, // chat button
179  { PANEL_LEFT + 527, PANEL_TOP + 91, 33, 32, TRUE }, // friendly fire button
180  // clang-format on
181 };
183 char *PanBtnHotKey[8] = { "'c'", "'q'", "Tab", "Esc", "'i'", "'b'", "Enter", NULL };
185 char *PanBtnStr[8] = {
186  "Character Information",
187  "Quests log",
188  "Automap",
189  "Main Menu",
190  "Inventory",
191  "Spell book",
192  "Send Message",
193  "Player Attack"
194 };
197  { 137, 138, 41, 22 },
198  { 137, 166, 41, 22 },
199  { 137, 195, 41, 22 },
200  { 137, 223, 41, 22 }
201 };
202 
204 int SpellPages[6][7] = {
209  { -1, -1, -1, -1, -1, -1, -1 },
210  { -1, -1, -1, -1, -1, -1, -1 }
211 };
212 
213 #define SPLICONLENGTH 56
214 #define SPLROWICONLS 10
215 #define SPLICONLAST 43
216 
225 void DrawSpellCel(int xp, int yp, BYTE *Trans, int nCel, int w)
226 {
227  CelDrawLight(xp, yp, Trans, nCel, w, SplTransTbl);
228 }
229 
230 void SetSpellTrans(char t)
231 {
232  int i;
233 
234  if (t == RSPLTYPE_SKILL) {
235  for (i = 0; i < 128; i++)
236  SplTransTbl[i] = i;
237  }
238  for (i = 128; i < 256; i++)
239  SplTransTbl[i] = i;
240  SplTransTbl[255] = 0;
241 
242  switch (t) {
243  case RSPLTYPE_SPELL:
247  for (i = PAL16_BLUE; i < PAL16_BLUE + 16; i++) {
251  }
252  break;
253  case RSPLTYPE_SCROLL:
257  for (i = PAL16_BEIGE; i < PAL16_BEIGE + 16; i++) {
260  }
261  break;
262  case RSPLTYPE_CHARGES:
266  for (i = PAL16_ORANGE; i < PAL16_ORANGE + 16; i++) {
269  }
270  break;
271  case RSPLTYPE_INVALID:
275  for (i = PAL16_GRAY; i < PAL16_GRAY + 15; i++) {
279  }
280  SplTransTbl[PAL16_BEIGE + 15] = 0;
281  SplTransTbl[PAL16_YELLOW + 15] = 0;
282  SplTransTbl[PAL16_ORANGE + 15] = 0;
283  break;
284  }
285 }
286 
290 void DrawSpell()
291 {
292  char st;
293  int spl, tlvl;
294 
295  spl = plr[myplr]._pRSpell;
296  st = plr[myplr]._pRSplType;
297 
298  // BUGFIX: Move the next line into the if statement to avoid OOB (SPL_INVALID is -1) (fixed)
299  if (st == RSPLTYPE_SPELL && spl != SPL_INVALID) {
300  tlvl = plr[myplr]._pISplLvlAdd + plr[myplr]._pSplLvl[spl];
301  if (!CheckSpell(myplr, spl, RSPLTYPE_SPELL, TRUE))
302  st = RSPLTYPE_INVALID;
303  if (tlvl <= 0)
304  st = RSPLTYPE_INVALID;
305  }
306  if (currlevel == 0 && st != RSPLTYPE_INVALID && !spelldata[spl].sTownSpell)
307  st = RSPLTYPE_INVALID;
308  if (plr[myplr]._pRSpell < 0)
309  st = RSPLTYPE_INVALID;
310  SetSpellTrans(st);
311  if (spl != SPL_INVALID)
313  else
315 }
316 
318 {
319  int i, j, x, y, c, s, t, v, lx, ly, trans;
320  unsigned __int64 mask, spl;
321 
323  infostr[0] = '\0';
324  x = PANEL_X + 12 + SPLICONLENGTH * SPLROWICONLS;
325  y = PANEL_Y - 17;
326  ClearPanel();
327  for (i = 0; i < 4; i++) {
328  switch ((spell_type)i) {
329  case RSPLTYPE_SKILL:
331  c = SPLICONLAST + 3;
332  mask = plr[myplr]._pAblSpells;
333  break;
334  case RSPLTYPE_SPELL:
335  c = SPLICONLAST + 4;
336  mask = plr[myplr]._pMemSpells;
337  break;
338  case RSPLTYPE_SCROLL:
340  c = SPLICONLAST + 1;
341  mask = plr[myplr]._pScrlSpells;
342  break;
343  case RSPLTYPE_CHARGES:
345  c = SPLICONLAST + 2;
346  mask = plr[myplr]._pISpells;
347  break;
348  }
349  for (spl = 1, j = 1; j < MAX_SPELLS; spl <<= 1, j++) {
350  if (!(mask & spl))
351  continue;
352  if (i == RSPLTYPE_SPELL) {
353  s = plr[myplr]._pISplLvlAdd + plr[myplr]._pSplLvl[j];
354  if (s < 0)
355  s = 0;
356  if (s > 0)
357  trans = RSPLTYPE_SPELL;
358  else
359  trans = RSPLTYPE_INVALID;
360  SetSpellTrans(trans);
361  }
362  if (currlevel == 0 && !spelldata[j].sTownSpell)
365  lx = x - BORDER_LEFT;
366  ly = y - BORDER_TOP - SPLICONLENGTH;
367  if (MouseX >= lx && MouseX < lx + SPLICONLENGTH && MouseY >= ly && MouseY < ly + SPLICONLENGTH) {
368  pSpell = j;
369  pSplType = i;
371  switch (i) {
372  case RSPLTYPE_SKILL:
373  sprintf(infostr, "%s Skill", spelldata[pSpell].sSkillText);
374  break;
375  case RSPLTYPE_SPELL:
376  sprintf(infostr, "%s Spell", spelldata[pSpell].sNameText);
377  if (pSpell == SPL_HBOLT) {
378  sprintf(tempstr, "Damages undead only");
379  AddPanelString(tempstr, TRUE);
380  }
381  if (s == 0)
382  sprintf(tempstr, "Spell Level 0 - Unusable");
383  else
384  sprintf(tempstr, "Spell Level %i", s);
385  AddPanelString(tempstr, TRUE);
386  break;
387  case RSPLTYPE_SCROLL:
388  sprintf(infostr, "Scroll of %s", spelldata[pSpell].sNameText);
389  v = 0;
390  for (t = 0; t < plr[myplr]._pNumInv; t++) {
391  if (plr[myplr].InvList[t]._itype != ITYPE_NONE
392  && (plr[myplr].InvList[t]._iMiscId == IMISC_SCROLL || plr[myplr].InvList[t]._iMiscId == IMISC_SCROLLT)
393  && plr[myplr].InvList[t]._iSpell == pSpell) {
394  v++;
395  }
396  }
397  for (t = 0; t < MAXBELTITEMS; t++) {
398  if (plr[myplr].SpdList[t]._itype != ITYPE_NONE
399  && (plr[myplr].SpdList[t]._iMiscId == IMISC_SCROLL || plr[myplr].SpdList[t]._iMiscId == IMISC_SCROLLT)
400  && plr[myplr].SpdList[t]._iSpell == pSpell) {
401  v++;
402  }
403  }
404  if (v == 1)
405  strcpy(tempstr, "1 Scroll");
406  else
407  sprintf(tempstr, "%i Scrolls", v);
408  AddPanelString(tempstr, TRUE);
409  break;
410  case RSPLTYPE_CHARGES:
411  sprintf(infostr, "Staff of %s", spelldata[pSpell].sNameText);
412  if (plr[myplr].InvBody[INVLOC_HAND_LEFT]._iCharges == 1)
413  strcpy(tempstr, "1 Charge");
414  else
415  sprintf(tempstr, "%i Charges", plr[myplr].InvBody[INVLOC_HAND_LEFT]._iCharges);
416  AddPanelString(tempstr, TRUE);
417  break;
418  }
419  for (t = 0; t < 4; t++) {
420  if (plr[myplr]._pSplHotKey[t] == pSpell && plr[myplr]._pSplTHotKey[t] == pSplType) {
422  sprintf(tempstr, "Spell Hot Key #F%i", t + 5);
423  AddPanelString(tempstr, TRUE);
424  }
425  }
426  }
427  x -= SPLICONLENGTH;
428  if (x == PANEL_X + 12 - SPLICONLENGTH) {
429  x = PANEL_X + 12 + SPLICONLENGTH * SPLROWICONLS;
430  y -= SPLICONLENGTH;
431  }
432  }
433  if (mask != 0 && x != PANEL_X + 12 + SPLICONLENGTH * SPLROWICONLS)
434  x -= SPLICONLENGTH;
435  if (x == PANEL_X + 12 - SPLICONLENGTH) {
436  x = PANEL_X + 12 + SPLICONLENGTH * SPLROWICONLS;
437  y -= SPLICONLENGTH;
438  }
439  }
440 }
441 
442 void SetSpell()
443 {
444  spselflag = FALSE;
445  if (pSpell != SPL_INVALID) {
446  ClearPanel();
449  force_redraw = 255;
450  }
451 }
452 
453 void SetSpeedSpell(int slot)
454 {
455  int i;
456 
457  if (pSpell != SPL_INVALID) {
458  for (i = 0; i < 4; ++i) {
459  if (plr[myplr]._pSplHotKey[i] == pSpell && plr[myplr]._pSplTHotKey[i] == pSplType)
461  }
462  plr[myplr]._pSplHotKey[slot] = pSpell;
463  plr[myplr]._pSplTHotKey[slot] = pSplType;
464  }
465 }
466 
467 void ToggleSpell(int slot)
468 {
469  unsigned __int64 spells;
470 
471  if (plr[myplr]._pSplHotKey[slot] == -1) {
472  return;
473  }
474 
475  switch (plr[myplr]._pSplTHotKey[slot]) {
476  case RSPLTYPE_SKILL:
477  spells = plr[myplr]._pAblSpells;
478  break;
479  case RSPLTYPE_SPELL:
480  spells = plr[myplr]._pMemSpells;
481  break;
482  case RSPLTYPE_SCROLL:
483  spells = plr[myplr]._pScrlSpells;
484  break;
485  case RSPLTYPE_CHARGES:
486  spells = plr[myplr]._pISpells;
487  break;
488  }
489 
490  if (spells & (__int64)1 << (plr[myplr]._pSplHotKey[slot] - 1)) {
493  force_redraw = 255;
494  }
495 }
496 
504 void PrintChar(int sx, int sy, int nCel, char col)
505 {
506  assert(gpBuffer);
507 
508  int i;
509  BYTE pix;
510  BYTE tbl[256];
511 
512  switch (col) {
513  case COL_WHITE:
514  CelDraw(sx, sy, pPanelText, nCel, 13);
515  return;
516  case COL_BLUE:
517  for (i = 0; i < 256; i++) {
518  pix = i;
519  if (pix > PAL16_GRAY + 13)
520  pix = PAL16_BLUE + 15;
521  else if (pix >= PAL16_GRAY)
522  pix -= PAL16_GRAY - (PAL16_BLUE + 2);
523  tbl[i] = pix;
524  }
525  break;
526  case COL_RED:
527  for (i = 0; i < 256; i++) {
528  pix = i;
529  if (pix >= PAL16_GRAY)
530  pix -= PAL16_GRAY - PAL16_RED;
531  tbl[i] = pix;
532  }
533  break;
534  default:
535  for (i = 0; i < 256; i++) {
536  pix = i;
537  if (pix >= PAL16_GRAY) {
538  if (pix >= PAL16_GRAY + 14)
539  pix = PAL16_YELLOW + 15;
540  else
541  pix -= PAL16_GRAY - (PAL16_YELLOW + 2);
542  }
543  tbl[i] = pix;
544  }
545  break;
546  }
547  CelDrawLight(sx, sy, pPanelText, nCel, 13, tbl);
548 }
549 
550 void AddPanelString(char *str, BOOL just)
551 {
552  strcpy(panelstr[pnumlines], str);
553  pstrjust[pnumlines] = just;
554 
555  if (pnumlines < 4)
556  pnumlines++;
557 }
558 
560 {
561  pnumlines = 0;
562  pinfoflag = FALSE;
563 }
564 
565 void DrawPanelBox(int x, int y, int w, int h, int sx, int sy)
566 {
567  int nSrcOff, nDstOff;
568 
569  assert(gpBuffer);
570 
571  nSrcOff = x + PANEL_WIDTH * y;
572  nDstOff = sx + BUFFER_WIDTH * sy;
573 
574  int hgt;
575  BYTE *src, *dst;
576 
577  src = &pBtmBuff[nSrcOff];
578  dst = &gpBuffer[nDstOff];
579 
580  for (hgt = h; hgt; hgt--, src += PANEL_WIDTH, dst += BUFFER_WIDTH) {
581  memcpy(dst, src, w);
582  }
583 }
584 
595 void SetFlaskHeight(BYTE *pCelBuff, int min, int max, int sx, int sy)
596 {
597  int nSrcOff, nDstOff, w;
598 
599  assert(gpBuffer);
600 
601  nSrcOff = 88 * min;
602  nDstOff = sx + BUFFER_WIDTH * sy;
603  w = max - min;
604 
605  BYTE *src, *dst;
606 
607  src = &pCelBuff[nSrcOff];
608  dst = &gpBuffer[nDstOff];
609 
610  for (; w; w--, src += 88, dst += BUFFER_WIDTH)
611  memcpy(dst, src, 88);
612 }
613 
625 void DrawFlask(BYTE *pCelBuff, int w, int nSrcOff, BYTE *pBuff, int nDstOff, int h)
626 {
627  int wdt, hgt;
628  BYTE *src, *dst;
629 
630  src = &pCelBuff[nSrcOff];
631  dst = &pBuff[nDstOff];
632 
633  for (hgt = h; hgt; hgt--, src += w - 59, dst += BUFFER_WIDTH - 59) {
634  for (wdt = 59; wdt; wdt--) {
635  if (*src)
636  *dst = *src;
637  src++;
638  dst++;
639  }
640  }
641 }
642 
648 {
649  int filled = (double)plr[myplr]._pHitPoints / (double)plr[myplr]._pMaxHP * 80.0;
650  plr[myplr]._pHPPer = filled;
651 
652  if (filled > 80)
653  filled = 80;
654  filled = 80 - filled;
655  if (filled > 11)
656  filled = 11;
657  filled += 2;
658 
659  DrawFlask(pLifeBuff, 88, 277, gpBuffer, SCREENXY(PANEL_LEFT + 109, PANEL_TOP - 13), filled);
660  if (filled != 13)
661  DrawFlask(pBtmBuff, PANEL_WIDTH, PANEL_WIDTH * (filled + 3) + 109, gpBuffer, SCREENXY(PANEL_LEFT + 109, PANEL_TOP - 13 + filled), 13 - filled);
662 }
663 
670 {
671  int filled = (double)plr[myplr]._pHitPoints / (double)plr[myplr]._pMaxHP * 80.0;
672  plr[myplr]._pHPPer = filled;
673 
674  if (filled > 69)
675  filled = 69;
676  else if (filled < 0)
677  filled = 0;
678  if (filled != 69)
679  SetFlaskHeight(pLifeBuff, 16, 85 - filled, 96 + PANEL_X, PANEL_Y);
680  if (filled != 0)
681  DrawPanelBox(96, 85 - filled, 88, filled, 96 + PANEL_X, PANEL_Y + 69 - filled);
682 }
683 
685 {
686  int filled = plr[myplr]._pManaPer;
687  if (filled > 80)
688  filled = 80;
689  filled = 80 - filled;
690  if (filled > 11)
691  filled = 11;
692  filled += 2;
693 
694  DrawFlask(pManaBuff, 88, 277, gpBuffer, SCREENXY(PANEL_LEFT + 475, PANEL_TOP - 13), filled);
695  if (filled != 13)
696  DrawFlask(pBtmBuff, PANEL_WIDTH, PANEL_WIDTH * (filled + 3) + 475, gpBuffer, SCREENXY(PANEL_LEFT + 475, PANEL_TOP - 13 + filled), 13 - filled);
697 }
698 
700 {
701  int manaPer;
702  int maxMana = plr[myplr]._pMaxMana;
703  int mana = plr[myplr]._pMana;
704  if (maxMana < 0)
705  maxMana = 0;
706  if (mana < 0)
707  mana = 0;
708  if (maxMana == 0)
709  manaPer = 0;
710  else
711  manaPer = (double)mana / (double)maxMana * 80.0;
712  plr[myplr]._pManaPer = manaPer;
713  plr[myplr]._pHPPer = (double)plr[myplr]._pHitPoints / (double)plr[myplr]._pMaxHP * 80.0;
714 }
715 
721 {
722  int filled;
723  int maxMana = plr[myplr]._pMaxMana;
724  int mana = plr[myplr]._pMana;
725  if (maxMana < 0)
726  maxMana = 0;
727  if (mana < 0)
728  mana = 0;
729 
730  if (maxMana == 0)
731  filled = 0;
732  else
733  filled = (double)mana / (double)maxMana * 80.0;
734 
735  plr[myplr]._pManaPer = filled;
736 
737  if (filled > 69)
738  filled = 69;
739  if (filled != 69)
740  SetFlaskHeight(pManaBuff, 16, 85 - filled, 96 + PANEL_X + 368, PANEL_Y);
741  if (filled != 0)
742  DrawPanelBox(96 + 368, 85 - filled, 88, filled, 96 + PANEL_X + 368, PANEL_Y + 69 - filled);
743 
744  DrawSpell();
745 }
746 
748 {
749  int i;
750 
751  if (gbMaxPlayers == 1) {
753  memset(pBtmBuff, 0, (PANEL_HEIGHT + 16) * PANEL_WIDTH);
754  } else {
756  memset(pBtmBuff, 0, (PANEL_HEIGHT + 16) * 2 * PANEL_WIDTH);
757  }
758  pManaBuff = DiabloAllocPtr(88 * 88);
759  memset(pManaBuff, 0, 88 * 88);
760  pLifeBuff = DiabloAllocPtr(88 * 88);
761  memset(pLifeBuff, 0, 88 * 88);
762  pPanelText = LoadFileInMem("CtrlPan\\SmalText.CEL", NULL);
763  pChrPanel = LoadFileInMem("Data\\Char.CEL", NULL);
764  pSpellCels = LoadFileInMem("CtrlPan\\SpelIcon.CEL", NULL);
766  pStatusPanel = LoadFileInMem("CtrlPan\\Panel8.CEL", NULL);
769  pStatusPanel = LoadFileInMem("CtrlPan\\P8Bulbs.CEL", NULL);
770  CelBlitWidth(pLifeBuff, 0, 87, 88, pStatusPanel, 1, 88);
771  CelBlitWidth(pManaBuff, 0, 87, 88, pStatusPanel, 2, 88);
773  talkflag = FALSE;
774  if (gbMaxPlayers != 1) {
775  pTalkPanel = LoadFileInMem("CtrlPan\\TalkPanl.CEL", NULL);
778  pMultiBtns = LoadFileInMem("CtrlPan\\P8But2.CEL", NULL);
779  pTalkBtns = LoadFileInMem("CtrlPan\\TalkButt.CEL", NULL);
780  sgbPlrTalkTbl = 0;
781  sgszTalkMsg[0] = 0;
782  for (i = 0; i < MAX_PLRS; i++)
783  whisper[i] = TRUE;
784  for (i = 0; i < sizeof(talkbtndown) / sizeof(talkbtndown[0]); i++)
785  talkbtndown[i] = FALSE;
786  }
787  panelflag = FALSE;
788  lvlbtndown = FALSE;
789  pPanelButtons = LoadFileInMem("CtrlPan\\Panel8bu.CEL", NULL);
790  for (i = 0; i < sizeof(panbtn) / sizeof(panbtn[0]); i++)
791  panbtn[i] = FALSE;
792  panbtndown = FALSE;
793  if (gbMaxPlayers == 1)
794  numpanbtns = 6;
795  else
796  numpanbtns = 8;
797  pChrButtons = LoadFileInMem("Data\\CharBut.CEL", NULL);
798  for (i = 0; i < sizeof(chrbtn) / sizeof(chrbtn[0]); i++)
799  chrbtn[i] = FALSE;
800  chrbtnactive = FALSE;
801  pDurIcons = LoadFileInMem("Items\\DurIcons.CEL", NULL);
802  strcpy(infostr, "");
803  ClearPanel();
804  drawhpflag = TRUE;
805  drawmanaflag = TRUE;
806  chrflag = FALSE;
807  spselflag = FALSE;
808  pSpellBkCel = LoadFileInMem("Data\\SpellBk.CEL", NULL);
809  pSBkBtnCel = LoadFileInMem("Data\\SpellBkB.CEL", NULL);
810  pSBkIconCels = LoadFileInMem("Data\\SpellI2.CEL", NULL);
811  sbooktab = 0;
812  sbookflag = FALSE;
813  if (plr[myplr]._pClass == PC_WARRIOR) {
814  SpellPages[0][0] = SPL_REPAIR;
815 #ifndef SPAWN
816  } else if (plr[myplr]._pClass == PC_ROGUE) {
817  SpellPages[0][0] = SPL_DISARM;
818  } else if (plr[myplr]._pClass == PC_SORCERER) {
819  SpellPages[0][0] = SPL_RECHARGE;
820 #endif
821  }
822  pQLogCel = LoadFileInMem("Data\\Quest.CEL", NULL);
823  pGBoxBuff = LoadFileInMem("CtrlPan\\Golddrop.cel", NULL);
824  dropGoldFlag = FALSE;
825  dropGoldValue = 0;
828  PentSpn2Frame = 1;
829 }
830 
832 {
834  DrawInfoBox();
835 }
836 
842 {
843  int i;
844 
845  for (i = 0; i < 6; i++) {
846  if (!panbtn[i])
847  DrawPanelBox(PanBtnPos[i][0] - PANEL_LEFT, PanBtnPos[i][1] - (PANEL_TOP - 16), 71, 20, PanBtnPos[i][0] + SCREEN_X, PanBtnPos[i][1] + SCREEN_Y);
848  else
849  CelDraw(PanBtnPos[i][0] + SCREEN_X, PanBtnPos[i][1] + SCREEN_Y + 18, pPanelButtons, i + 1, 71);
850  }
851  if (numpanbtns == 8) {
852  CelDraw(87 + PANEL_X, 122 + PANEL_Y, pMultiBtns, panbtn[6] + 1, 33);
853  if (FriendlyMode)
854  CelDraw(527 + PANEL_X, 122 + PANEL_Y, pMultiBtns, panbtn[7] + 3, 33);
855  else
856  CelDraw(527 + PANEL_X, 122 + PANEL_Y, pMultiBtns, panbtn[7] + 5, 33);
857  }
858 }
859 
865 {
866  unsigned __int64 spells, spell;
867  int xo, yo, X, Y, i, j;
868 
869  spselflag = TRUE;
870  xo = PANEL_X + 12 + SPLICONLENGTH * 10;
871  yo = PANEL_Y - 17;
872  X = xo - (BORDER_LEFT - SPLICONLENGTH / 2);
873  Y = yo - (BORDER_TOP + SPLICONLENGTH / 2);
874  if (plr[myplr]._pRSpell != SPL_INVALID) {
875  for (i = 0; i < 4; i++) {
876  switch (i) {
877  case RSPLTYPE_SKILL:
878  spells = plr[myplr]._pAblSpells;
879  break;
880  case RSPLTYPE_SPELL:
881  spells = plr[myplr]._pMemSpells;
882  break;
883  case RSPLTYPE_SCROLL:
884  spells = plr[myplr]._pScrlSpells;
885  break;
886  case RSPLTYPE_CHARGES:
887  spells = plr[myplr]._pISpells;
888  break;
889  }
890  spell = (__int64)1;
891  for (j = 1; j < MAX_SPELLS; j++) {
892  if (spell & spells) {
893  if (j == plr[myplr]._pRSpell && i == plr[myplr]._pRSplType) {
894  X = xo - (BORDER_LEFT - SPLICONLENGTH / 2);
895  Y = yo - (BORDER_TOP + SPLICONLENGTH / 2);
896  }
897  xo -= SPLICONLENGTH;
898  if (xo == PANEL_X + 12 - SPLICONLENGTH) {
899  xo = PANEL_X + 12 + SPLICONLENGTH * SPLROWICONLS;
900  yo -= SPLICONLENGTH;
901  }
902  }
903  spell <<= (__int64)1;
904  }
905  if (spells && xo != PANEL_X + 12 + SPLICONLENGTH * SPLROWICONLS)
906  xo -= SPLICONLENGTH;
907  if (xo == PANEL_X + 12 - SPLICONLENGTH) {
908  xo = PANEL_X + 12 + SPLICONLENGTH * SPLROWICONLS;
909  yo -= SPLICONLENGTH;
910  }
911  }
912  }
913 
914  SetCursorPos(X, Y);
915 }
916 
920 void DoPanBtn()
921 {
922  int i;
923 
924  for (i = 0; i < numpanbtns; i++) {
925  if (MouseX >= PanBtnPos[i][0] && MouseX <= PanBtnPos[i][0] + PanBtnPos[i][2]) {
926  if (MouseY >= PanBtnPos[i][1] && MouseY <= PanBtnPos[i][1] + PanBtnPos[i][3]) {
927  panbtn[i] = TRUE;
928  drawbtnflag = TRUE;
929  panbtndown = TRUE;
930  }
931  }
932  }
933  if (!spselflag && MouseX >= 565 + PANEL_LEFT && MouseX < 621 + PANEL_LEFT && MouseY >= 64 + PANEL_TOP && MouseY < 120 + PANEL_TOP) {
934  DoSpeedBook();
935  gamemenu_off();
936  }
937 }
938 
939 void control_set_button_down(int btn_id)
940 {
941  panbtn[btn_id] = TRUE;
942  drawbtnflag = TRUE;
943  panbtndown = TRUE;
944 }
945 
947 {
948  if (MouseX >= PanBtnPos[3][0]
949  && MouseX <= PanBtnPos[3][0] + PanBtnPos[3][2]
950  && MouseY >= PanBtnPos[3][1]
951  && MouseY <= PanBtnPos[3][1] + PanBtnPos[3][3]) {
953  }
954  if (MouseX >= PanBtnPos[6][0]
955  && MouseX <= PanBtnPos[6][0] + PanBtnPos[6][2]
956  && MouseY >= PanBtnPos[6][1]
957  && MouseY <= PanBtnPos[6][1] + PanBtnPos[6][3]) {
959  }
960 }
961 
962 void DoAutoMap()
963 {
964  if (currlevel != 0 || gbMaxPlayers != 1) {
965  if (!automapflag)
966  StartAutomap();
967  else
968  automapflag = FALSE;
969  } else {
971  }
972 }
973 
979 {
980  int i, c, v, s, xend, yend;
981 
982  panelflag = FALSE;
983  ClearPanel();
984  for (i = 0; i < numpanbtns; i++) {
985  xend = PanBtnPos[i][0] + PanBtnPos[i][2];
986  yend = PanBtnPos[i][1] + PanBtnPos[i][3];
987  if (MouseX >= PanBtnPos[i][0] && MouseX <= xend && MouseY >= PanBtnPos[i][1] && MouseY <= yend) {
988  if (i != 7) {
989  strcpy(infostr, PanBtnStr[i]);
990  } else {
991  if (FriendlyMode)
992  strcpy(infostr, "Player friendly");
993  else
994  strcpy(infostr, "Player attack");
995  }
996  if (PanBtnHotKey[i] != NULL) {
997  sprintf(tempstr, "Hotkey : %s", PanBtnHotKey[i]);
998  AddPanelString(tempstr, TRUE);
999  }
1000  infoclr = COL_WHITE;
1001  panelflag = TRUE;
1002  pinfoflag = TRUE;
1003  }
1004  }
1005  if (!spselflag && MouseX >= 565 + PANEL_LEFT && MouseX < 621 + PANEL_LEFT && MouseY >= 64 + PANEL_TOP && MouseY < 120 + PANEL_TOP) {
1006  strcpy(infostr, "Select current spell button");
1007  infoclr = COL_WHITE;
1008  panelflag = TRUE;
1009  pinfoflag = TRUE;
1010  strcpy(tempstr, "Hotkey : 's'");
1011  AddPanelString(tempstr, TRUE);
1012  v = plr[myplr]._pRSpell;
1013  if (v != SPL_INVALID) {
1014  switch (plr[myplr]._pRSplType) {
1015  case RSPLTYPE_SKILL:
1016  sprintf(tempstr, "%s Skill", spelldata[v].sSkillText);
1017  AddPanelString(tempstr, TRUE);
1018  break;
1019  case RSPLTYPE_SPELL:
1020  sprintf(tempstr, "%s Spell", spelldata[v].sNameText);
1021  AddPanelString(tempstr, TRUE);
1022  c = plr[myplr]._pISplLvlAdd + plr[myplr]._pSplLvl[v];
1023  if (c < 0)
1024  c = 0;
1025  if (c == 0)
1026  sprintf(tempstr, "Spell Level 0 - Unusable");
1027  else
1028  sprintf(tempstr, "Spell Level %i", c);
1029  AddPanelString(tempstr, TRUE);
1030  break;
1031  case RSPLTYPE_SCROLL:
1032  sprintf(tempstr, "Scroll of %s", spelldata[v].sNameText);
1033  AddPanelString(tempstr, TRUE);
1034  s = 0;
1035  for (i = 0; i < plr[myplr]._pNumInv; i++) {
1036  if (plr[myplr].InvList[i]._itype != ITYPE_NONE
1037  && (plr[myplr].InvList[i]._iMiscId == IMISC_SCROLL || plr[myplr].InvList[i]._iMiscId == IMISC_SCROLLT)
1038  && plr[myplr].InvList[i]._iSpell == v) {
1039  s++;
1040  }
1041  }
1042  for (i = 0; i < MAXBELTITEMS; i++) {
1043  if (plr[myplr].SpdList[i]._itype != ITYPE_NONE
1044  && (plr[myplr].SpdList[i]._iMiscId == IMISC_SCROLL || plr[myplr].SpdList[i]._iMiscId == IMISC_SCROLLT)
1045  && plr[myplr].SpdList[i]._iSpell == v) {
1046  s++;
1047  }
1048  }
1049  if (s == 1)
1050  strcpy(tempstr, "1 Scroll");
1051  else
1052  sprintf(tempstr, "%i Scrolls", s);
1053  AddPanelString(tempstr, TRUE);
1054  break;
1055  case RSPLTYPE_CHARGES:
1056  sprintf(tempstr, "Staff of %s", spelldata[v].sNameText);
1057  AddPanelString(tempstr, TRUE);
1058  if (plr[myplr].InvBody[INVLOC_HAND_LEFT]._iCharges == 1)
1059  strcpy(tempstr, "1 Charge");
1060  else
1061  sprintf(tempstr, "%i Charges", plr[myplr].InvBody[INVLOC_HAND_LEFT]._iCharges);
1062  AddPanelString(tempstr, TRUE);
1063  break;
1064  }
1065  }
1066  }
1067  if (MouseX > 190 + PANEL_LEFT && MouseX < 437 + PANEL_LEFT && MouseY > 4 + PANEL_TOP && MouseY < 33 + PANEL_TOP)
1069 }
1070 
1076 {
1077  int i;
1078  BOOLEAN gamemenuOff;
1079 
1080  gamemenuOff = TRUE;
1081  drawbtnflag = TRUE;
1082  panbtndown = FALSE;
1083 
1084  for (i = 0; i < 8; i++) {
1085  if (!panbtn[i]) {
1086  continue;
1087  }
1088 
1089  panbtn[i] = FALSE;
1090 
1091  if (MouseX < PanBtnPos[i][0]
1092  || MouseX > PanBtnPos[i][0] + PanBtnPos[i][2]
1093  || MouseY < PanBtnPos[i][1]
1094  || MouseY > PanBtnPos[i][1] + PanBtnPos[i][3]) {
1095  continue;
1096  }
1097 
1098  switch (i) {
1099  case PANBTN_CHARINFO:
1100  questlog = FALSE;
1101  chrflag = !chrflag;
1102  break;
1103  case PANBTN_QLOG:
1104  chrflag = FALSE;
1105  if (!questlog)
1106  StartQuestlog();
1107  else
1108  questlog = FALSE;
1109  break;
1110  case PANBTN_AUTOMAP:
1111  DoAutoMap();
1112  break;
1113  case PANBTN_MAINMENU:
1114  qtextflag = FALSE;
1116  gamemenuOff = FALSE;
1117  break;
1118  case PANBTN_INVENTORY:
1119  sbookflag = FALSE;
1120  invflag = !invflag;
1121  if (dropGoldFlag) {
1122  dropGoldFlag = FALSE;
1123  dropGoldValue = 0;
1124  }
1125  break;
1126  case PANBTN_SPELLBOOK:
1127  invflag = FALSE;
1128  if (dropGoldFlag) {
1129  dropGoldFlag = FALSE;
1130  dropGoldValue = 0;
1131  }
1132  sbookflag = !sbookflag;
1133  break;
1134  case PANBTN_SENDMSG:
1135  if (talkflag)
1137  else
1139  break;
1140  case PANBTN_FRIENDLY:
1142  break;
1143  }
1144  }
1145 
1146  if (gamemenuOff)
1147  gamemenu_off();
1148 }
1149 
1151 {
1168 }
1169 
1171 {
1172  int k;
1173  BYTE ichar;
1174 
1175  k = 0;
1176  while (*str) {
1177  ichar = gbFontTransTbl[*str];
1178  str++;
1179  k += fontkern[fontframe[ichar]];
1180  if (k >= 125)
1181  return FALSE;
1182  }
1183 
1184  return TRUE;
1185 }
1186 
1191 {
1192  int nGold;
1193 
1194  DrawPanelBox(177, 62, 288, 60, PANEL_X + 177, PANEL_Y + 46);
1195  if (!panelflag && !trigflag && pcursinvitem == -1 && !spselflag) {
1196  infostr[0] = '\0';
1197  infoclr = COL_WHITE;
1198  ClearPanel();
1199  }
1200  if (spselflag || trigflag) {
1201  infoclr = COL_WHITE;
1202  } else if (pcurs >= CURSOR_FIRSTITEM) {
1203  if (plr[myplr].HoldItem._itype == ITYPE_GOLD) {
1204  nGold = plr[myplr].HoldItem._ivalue;
1205  sprintf(infostr, "%i gold %s", nGold, get_pieces_str(nGold));
1206  } else if (!plr[myplr].HoldItem._iStatFlag) {
1207  ClearPanel();
1208  AddPanelString("Requirements not met", TRUE);
1209  pinfoflag = TRUE;
1210  } else {
1211  if (plr[myplr].HoldItem._iIdentified)
1212  strcpy(infostr, plr[myplr].HoldItem._iIName);
1213  else
1214  strcpy(infostr, plr[myplr].HoldItem._iName);
1215  if (plr[myplr].HoldItem._iMagical == ITEM_QUALITY_MAGIC)
1216  infoclr = COL_BLUE;
1217  if (plr[myplr].HoldItem._iMagical == ITEM_QUALITY_UNIQUE)
1218  infoclr = COL_GOLD;
1219  }
1220  } else {
1221  if (pcursitem != -1)
1223  else if (pcursobj != -1)
1225  if (pcursmonst != -1) {
1226  if (leveltype != DTYPE_TOWN) {
1227  infoclr = COL_WHITE;
1228  strcpy(infostr, monster[pcursmonst].mName);
1229  ClearPanel();
1230  if (monster[pcursmonst]._uniqtype != 0) {
1231  infoclr = COL_GOLD;
1233  } else {
1234  PrintMonstHistory(monster[pcursmonst].MType->mtype);
1235  }
1236  } else if (pcursitem == -1) {
1237  strcpy(infostr, towner[pcursmonst]._tName);
1238  }
1239  }
1240  if (pcursplr != -1) {
1241  infoclr = COL_GOLD;
1242  strcpy(infostr, plr[pcursplr]._pName);
1243  ClearPanel();
1244  sprintf(tempstr, "Level : %i", plr[pcursplr]._pLevel);
1245  AddPanelString(tempstr, TRUE);
1246  sprintf(tempstr, "Hit Points %i of %i", plr[pcursplr]._pHitPoints >> 6, plr[pcursplr]._pMaxHP >> 6);
1247  AddPanelString(tempstr, TRUE);
1248  }
1249  }
1250  if (infostr[0] != '\0' || pnumlines != 0)
1251  PrintInfo();
1252 }
1253 
1255 {
1256  int yo, lo, i;
1257 
1258  if (!talkflag) {
1259  yo = 0;
1260  lo = 1;
1261  if (infostr[0] != '\0') {
1262  CPrintString(0, infostr, TRUE, pnumlines);
1263  yo = 1;
1264  lo = 0;
1265  }
1266 
1267  for (i = 0; i < pnumlines; i++) {
1268  CPrintString(i + yo, panelstr[i], pstrjust[i], pnumlines - lo);
1269  }
1270  }
1271 }
1272 
1273 void CPrintString(int y, char *str, BOOL center, int lines)
1274 {
1275  BYTE c;
1276  char *tmp;
1277  int lineOffset, strWidth, sx, sy;
1278 
1279  lineOffset = 0;
1280  sx = 177 + PANEL_X;
1281  sy = lineOffsets[lines][y] + PANEL_Y;
1282  if (center == 1) {
1283  strWidth = 0;
1284  tmp = str;
1285  while (*tmp) {
1286  c = gbFontTransTbl[(BYTE)*tmp++];
1287  strWidth += fontkern[fontframe[c]] + 2;
1288  }
1289  if (strWidth < 288)
1290  lineOffset = (288 - strWidth) >> 1;
1291  sx += lineOffset;
1292  }
1293  while (*str) {
1294  c = gbFontTransTbl[(BYTE)*str++];
1295  c = fontframe[c];
1296  lineOffset += fontkern[c] + 2;
1297  if (c) {
1298  if (lineOffset < 288) {
1299  PrintChar(sx, sy, c, infoclr);
1300  }
1301  }
1302  sx += fontkern[c] + 2;
1303  }
1304 }
1305 
1306 void PrintGameStr(int x, int y, const char *str, int color)
1307 {
1308  BYTE c;
1309  int sx, sy;
1310  sx = x + SCREEN_X;
1311  sy = y + SCREEN_Y;
1312  while (*str) {
1313  c = gbFontTransTbl[(BYTE)*str++];
1314  c = fontframe[c];
1315  if (c)
1316  PrintChar(sx, sy, c, color);
1317  sx += fontkern[c] + 1;
1318  }
1319 }
1320 
1321 void DrawChr()
1322 {
1323  char col;
1324  char chrstr[64];
1325  int pc, mindam, maxdam;
1326 
1328  ADD_PlrStringXY(20, 32, 151, plr[myplr]._pName, COL_WHITE);
1329 
1330  if (plr[myplr]._pClass == PC_WARRIOR) {
1331  ADD_PlrStringXY(168, 32, 299, "Warrior", COL_WHITE);
1332 #ifndef SPAWN
1333  } else if (plr[myplr]._pClass == PC_ROGUE) {
1334  ADD_PlrStringXY(168, 32, 299, "Rogue", COL_WHITE);
1335  } else if (plr[myplr]._pClass == PC_SORCERER) {
1336  ADD_PlrStringXY(168, 32, 299, "Sorceror", COL_WHITE);
1337 #endif
1338  }
1339 
1340  sprintf(chrstr, "%i", plr[myplr]._pLevel);
1341  ADD_PlrStringXY(66, 69, 109, chrstr, COL_WHITE);
1342 
1343  sprintf(chrstr, "%li", plr[myplr]._pExperience);
1344  ADD_PlrStringXY(216, 69, 300, chrstr, COL_WHITE);
1345 
1346  if (plr[myplr]._pLevel == MAXCHARLEVEL - 1) {
1347  strcpy(chrstr, "None");
1348  col = COL_GOLD;
1349  } else {
1350  sprintf(chrstr, "%li", plr[myplr]._pNextExper);
1351  col = COL_WHITE;
1352  }
1353  ADD_PlrStringXY(216, 97, 300, chrstr, col);
1354 
1355  sprintf(chrstr, "%i", plr[myplr]._pGold);
1356  ADD_PlrStringXY(216, 146, 300, chrstr, COL_WHITE);
1357 
1358  col = COL_WHITE;
1359  if (plr[myplr]._pIBonusAC > 0)
1360  col = COL_BLUE;
1361  if (plr[myplr]._pIBonusAC < 0)
1362  col = COL_RED;
1363  sprintf(chrstr, "%i", plr[myplr]._pIBonusAC + plr[myplr]._pIAC + plr[myplr]._pDexterity / 5);
1364  ADD_PlrStringXY(258, 183, 301, chrstr, col);
1365 
1366  col = COL_WHITE;
1367  if (plr[myplr]._pIBonusToHit > 0)
1368  col = COL_BLUE;
1369  if (plr[myplr]._pIBonusToHit < 0)
1370  col = COL_RED;
1371  sprintf(chrstr, "%i%%", (plr[myplr]._pDexterity >> 1) + plr[myplr]._pIBonusToHit + 50);
1372  ADD_PlrStringXY(258, 211, 301, chrstr, col);
1373 
1374  col = COL_WHITE;
1375  if (plr[myplr]._pIBonusDam > 0)
1376  col = COL_BLUE;
1377  if (plr[myplr]._pIBonusDam < 0)
1378  col = COL_RED;
1379  mindam = plr[myplr]._pIMinDam;
1380  mindam += plr[myplr]._pIBonusDam * mindam / 100;
1381  mindam += plr[myplr]._pIBonusDamMod;
1382  if (plr[myplr].InvBody[INVLOC_HAND_LEFT]._itype == ITYPE_BOW) {
1383  if (plr[myplr]._pClass == PC_ROGUE)
1384  mindam += plr[myplr]._pDamageMod;
1385  else
1386  mindam += plr[myplr]._pDamageMod >> 1;
1387  } else {
1388  mindam += plr[myplr]._pDamageMod;
1389  }
1390  maxdam = plr[myplr]._pIMaxDam;
1391  maxdam += plr[myplr]._pIBonusDam * maxdam / 100;
1392  maxdam += plr[myplr]._pIBonusDamMod;
1393  if (plr[myplr].InvBody[INVLOC_HAND_LEFT]._itype == ITYPE_BOW) {
1394  if (plr[myplr]._pClass == PC_ROGUE)
1395  maxdam += plr[myplr]._pDamageMod;
1396  else
1397  maxdam += plr[myplr]._pDamageMod >> 1;
1398  } else {
1399  maxdam += plr[myplr]._pDamageMod;
1400  }
1401  sprintf(chrstr, "%i-%i", mindam, maxdam);
1402  if (mindam >= 100 || maxdam >= 100)
1403  MY_PlrStringXY(254, 239, 305, chrstr, col, -1);
1404  else
1405  MY_PlrStringXY(258, 239, 301, chrstr, col, 0);
1406 
1407  col = plr[myplr]._pMagResist == 0 ? COL_WHITE : COL_BLUE;
1408  if (plr[myplr]._pMagResist < MAXRESIST) {
1409  sprintf(chrstr, "%i%%", plr[myplr]._pMagResist);
1410  } else {
1411  col = COL_GOLD;
1412  sprintf(chrstr, "MAX");
1413  }
1414  ADD_PlrStringXY(257, 276, 300, chrstr, col);
1415 
1416  col = plr[myplr]._pFireResist == 0 ? COL_WHITE : COL_BLUE;
1417  if (plr[myplr]._pFireResist < MAXRESIST) {
1418  sprintf(chrstr, "%i%%", plr[myplr]._pFireResist);
1419  } else {
1420  col = COL_GOLD;
1421  sprintf(chrstr, "MAX");
1422  }
1423  ADD_PlrStringXY(257, 304, 300, chrstr, col);
1424 
1425  col = plr[myplr]._pLghtResist == 0 ? COL_WHITE : COL_BLUE;
1426  if (plr[myplr]._pLghtResist < MAXRESIST) {
1427  sprintf(chrstr, "%i%%", plr[myplr]._pLghtResist);
1428  } else {
1429  col = COL_GOLD;
1430  sprintf(chrstr, "MAX");
1431  }
1432  ADD_PlrStringXY(257, 332, 300, chrstr, col);
1433 
1434  col = COL_WHITE;
1435  sprintf(chrstr, "%i", plr[myplr]._pBaseStr);
1436  if (MaxStats[plr[myplr]._pClass][ATTRIB_STR] == plr[myplr]._pBaseStr)
1437  col = COL_GOLD;
1438  ADD_PlrStringXY(95, 155, 126, chrstr, col);
1439 
1440  col = COL_WHITE;
1441  sprintf(chrstr, "%i", plr[myplr]._pBaseMag);
1442  if (MaxStats[plr[myplr]._pClass][ATTRIB_MAG] == plr[myplr]._pBaseMag)
1443  col = COL_GOLD;
1444  ADD_PlrStringXY(95, 183, 126, chrstr, col);
1445 
1446  col = COL_WHITE;
1447  sprintf(chrstr, "%i", plr[myplr]._pBaseDex);
1448  if (MaxStats[plr[myplr]._pClass][ATTRIB_DEX] == plr[myplr]._pBaseDex)
1449  col = COL_GOLD;
1450  ADD_PlrStringXY(95, 211, 126, chrstr, col);
1451 
1452  col = COL_WHITE;
1453  sprintf(chrstr, "%i", plr[myplr]._pBaseVit);
1454  if (MaxStats[plr[myplr]._pClass][ATTRIB_VIT] == plr[myplr]._pBaseVit)
1455  col = COL_GOLD;
1456  ADD_PlrStringXY(95, 239, 126, chrstr, col);
1457 
1458  col = COL_WHITE;
1459  if (plr[myplr]._pStrength > plr[myplr]._pBaseStr)
1460  col = COL_BLUE;
1461  if (plr[myplr]._pStrength < plr[myplr]._pBaseStr)
1462  col = COL_RED;
1463  sprintf(chrstr, "%i", plr[myplr]._pStrength);
1464  ADD_PlrStringXY(143, 155, 173, chrstr, col);
1465 
1466  col = COL_WHITE;
1467  if (plr[myplr]._pMagic > plr[myplr]._pBaseMag)
1468  col = COL_BLUE;
1469  if (plr[myplr]._pMagic < plr[myplr]._pBaseMag)
1470  col = COL_RED;
1471  sprintf(chrstr, "%i", plr[myplr]._pMagic);
1472  ADD_PlrStringXY(143, 183, 173, chrstr, col);
1473 
1474  col = COL_WHITE;
1475  if (plr[myplr]._pDexterity > plr[myplr]._pBaseDex)
1476  col = COL_BLUE;
1477  if (plr[myplr]._pDexterity < plr[myplr]._pBaseDex)
1478  col = COL_RED;
1479  sprintf(chrstr, "%i", plr[myplr]._pDexterity);
1480  ADD_PlrStringXY(143, 211, 173, chrstr, col);
1481 
1482  col = COL_WHITE;
1483  if (plr[myplr]._pVitality > plr[myplr]._pBaseVit)
1484  col = COL_BLUE;
1485  if (plr[myplr]._pVitality < plr[myplr]._pBaseVit)
1486  col = COL_RED;
1487  sprintf(chrstr, "%i", plr[myplr]._pVitality);
1488  ADD_PlrStringXY(143, 239, 173, chrstr, col);
1489 
1490  if (plr[myplr]._pStatPts > 0) {
1491  if (CalcStatDiff(myplr) < plr[myplr]._pStatPts) {
1493  }
1494  }
1495  if (plr[myplr]._pStatPts > 0) {
1496  sprintf(chrstr, "%i", plr[myplr]._pStatPts);
1497  ADD_PlrStringXY(95, 266, 126, chrstr, COL_RED);
1498  pc = plr[myplr]._pClass;
1499  if (plr[myplr]._pBaseStr < MaxStats[pc][ATTRIB_STR])
1500  CelDraw(137 + SCREEN_X, 159 + SCREEN_Y, pChrButtons, chrbtn[ATTRIB_STR] + 2, 41);
1501  if (plr[myplr]._pBaseMag < MaxStats[pc][ATTRIB_MAG])
1502  CelDraw(137 + SCREEN_X, 187 + SCREEN_Y, pChrButtons, chrbtn[ATTRIB_MAG] + 4, 41);
1503  if (plr[myplr]._pBaseDex < MaxStats[pc][ATTRIB_DEX])
1504  CelDraw(137 + SCREEN_X, 216 + SCREEN_Y, pChrButtons, chrbtn[ATTRIB_DEX] + 6, 41);
1505  if (plr[myplr]._pBaseVit < MaxStats[pc][ATTRIB_VIT])
1506  CelDraw(137 + SCREEN_X, 244 + SCREEN_Y, pChrButtons, chrbtn[ATTRIB_VIT] + 8, 41);
1507  }
1508 
1510  sprintf(chrstr, "%i", plr[myplr]._pMaxHP >> 6);
1511  ADD_PlrStringXY(95, 304, 126, chrstr, col);
1512  if (plr[myplr]._pHitPoints != plr[myplr]._pMaxHP)
1513  col = COL_RED;
1514  sprintf(chrstr, "%i", plr[myplr]._pHitPoints >> 6);
1515  ADD_PlrStringXY(143, 304, 174, chrstr, col);
1516 
1518  sprintf(chrstr, "%i", plr[myplr]._pMaxMana >> 6);
1519  ADD_PlrStringXY(95, 332, 126, chrstr, col);
1520  if (plr[myplr]._pMana != plr[myplr]._pMaxMana)
1521  col = COL_RED;
1522  sprintf(chrstr, "%i", plr[myplr]._pMana >> 6);
1523  ADD_PlrStringXY(143, 332, 174, chrstr, col);
1524 }
1525 
1535 void MY_PlrStringXY(int x, int y, int endX, char *pszStr, char col, int base)
1536 {
1537  BYTE c;
1538  char *tmp;
1539  int sx, sy, screen_x, line, widthOffset;
1540 
1541  sx = x + SCREEN_X;
1542  sy = y + SCREEN_Y;
1543  widthOffset = endX - x + 1;
1544  line = 0;
1545  screen_x = 0;
1546  tmp = pszStr;
1547  while (*tmp) {
1548  c = gbFontTransTbl[(BYTE)*tmp++];
1549  screen_x += fontkern[fontframe[c]] + base;
1550  }
1551  if (screen_x < widthOffset)
1552  line = (widthOffset - screen_x) >> 1;
1553  sx += line;
1554  while (*pszStr) {
1555  c = gbFontTransTbl[(BYTE)*pszStr++];
1556  c = fontframe[c];
1557  line += fontkern[c] + base;
1558  if (c) {
1559  if (line < widthOffset)
1560  PrintChar(sx, sy, c, col);
1561  }
1562  sx += fontkern[c] + base;
1563  }
1564 }
1565 
1567 {
1568  if (!lvlbtndown && MouseX >= 40 + PANEL_LEFT && MouseX <= 81 + PANEL_LEFT && MouseY >= -39 + PANEL_TOP && MouseY <= -17 + PANEL_TOP)
1569  lvlbtndown = TRUE;
1570 }
1571 
1573 {
1574  if (MouseX >= 40 + PANEL_LEFT && MouseX <= 81 + PANEL_LEFT && MouseY >= -39 + PANEL_TOP && MouseY <= -17 + PANEL_TOP)
1575  chrflag = TRUE;
1576  lvlbtndown = FALSE;
1577 }
1578 
1580 {
1581  int nCel;
1582 
1583  if (!stextflag) {
1584  nCel = lvlbtndown ? 3 : 2;
1585  ADD_PlrStringXY(PANEL_LEFT + 0, PANEL_TOP - 49, PANEL_LEFT + 120, "Level Up", COL_WHITE);
1586  CelDraw(40 + PANEL_X, -17 + PANEL_Y, pChrButtons, nCel, 41);
1587  }
1588 }
1589 
1591 {
1592  int pc, i;
1593 
1594  if (!chrbtnactive && plr[myplr]._pStatPts) {
1595  pc = plr[myplr]._pClass;
1596  for (i = 0; i < 4; i++) {
1597  switch (i) {
1598  case ATTRIB_STR:
1599  if (plr[myplr]._pBaseStr >= MaxStats[pc][ATTRIB_STR])
1600  continue;
1601  break;
1602  case ATTRIB_MAG:
1603  if (plr[myplr]._pBaseMag >= MaxStats[pc][ATTRIB_MAG])
1604  continue;
1605  break;
1606  case ATTRIB_DEX:
1607  if (plr[myplr]._pBaseDex >= MaxStats[pc][ATTRIB_DEX])
1608  continue;
1609  break;
1610  case ATTRIB_VIT:
1611  if (plr[myplr]._pBaseVit >= MaxStats[pc][ATTRIB_VIT])
1612  continue;
1613  break;
1614  default:
1615  continue;
1616  }
1617  if (MouseX >= ChrBtnsRect[i].x
1618  && MouseX <= ChrBtnsRect[i].x + ChrBtnsRect[i].w
1619  && MouseY >= ChrBtnsRect[i].y
1620  && MouseY <= ChrBtnsRect[i].y + ChrBtnsRect[i].h) {
1621  chrbtn[i] = TRUE;
1622  chrbtnactive = TRUE;
1623  }
1624  }
1625  }
1626 }
1627 
1629 {
1630  int i;
1631 
1632  chrbtnactive = FALSE;
1633  for (i = 0; i < 4; ++i) {
1634  if (chrbtn[i]) {
1635  chrbtn[i] = FALSE;
1636  if (MouseX >= ChrBtnsRect[i].x
1637  && MouseX <= ChrBtnsRect[i].x + ChrBtnsRect[i].w
1638  && MouseY >= ChrBtnsRect[i].y
1639  && MouseY <= ChrBtnsRect[i].y + ChrBtnsRect[i].h) {
1640  switch (i) {
1641  case 0:
1642  NetSendCmdParam1(TRUE, CMD_ADDSTR, 1);
1643  plr[myplr]._pStatPts--;
1644  break;
1645  case 1:
1646  NetSendCmdParam1(TRUE, CMD_ADDMAG, 1);
1647  plr[myplr]._pStatPts--;
1648  break;
1649  case 2:
1650  NetSendCmdParam1(TRUE, CMD_ADDDEX, 1);
1651  plr[myplr]._pStatPts--;
1652  break;
1653  case 3:
1654  NetSendCmdParam1(TRUE, CMD_ADDVIT, 1);
1655  plr[myplr]._pStatPts--;
1656  break;
1657  }
1658  }
1659  }
1660  }
1661 }
1662 
1664 {
1665  PlayerStruct *p;
1666  int x1, x2, x3, x4;
1667 
1668  if (!chrflag && !questlog || !invflag && !sbookflag) {
1669  x1 = 272 + RIGHT_PANEL_X;
1670  if (invflag || sbookflag)
1671  x1 = 272 + PANEL_X;
1672  p = &plr[myplr];
1673  x2 = DrawDurIcon4Item(&p->InvBody[INVLOC_HEAD], x1, 4);
1674  x3 = DrawDurIcon4Item(&p->InvBody[INVLOC_CHEST], x2, 3);
1675  x4 = DrawDurIcon4Item(&p->InvBody[INVLOC_HAND_LEFT], x3, 0);
1677  }
1678 }
1679 
1680 int DrawDurIcon4Item(ItemStruct *pItem, int x, int c)
1681 {
1682  if (pItem->_itype == ITYPE_NONE)
1683  return x;
1684  if (pItem->_iDurability > 5)
1685  return x;
1686  if (c == 0) {
1687  if (pItem->_iClass == ICLASS_WEAPON) {
1688  switch (pItem->_itype) {
1689  case ITYPE_SWORD:
1690  c = 2;
1691  break;
1692  case ITYPE_AXE:
1693  c = 6;
1694  break;
1695  case ITYPE_BOW:
1696  c = 7;
1697  break;
1698  case ITYPE_MACE:
1699  c = 5;
1700  break;
1701  case ITYPE_STAFF:
1702  c = 8;
1703  break;
1704  }
1705  } else {
1706  c = 1;
1707  }
1708  }
1709  if (pItem->_iDurability > 2)
1710  c += 8;
1711  CelDraw(x, -17 + PANEL_Y, pDurIcons, c, 32);
1712  return x - 40;
1713 }
1714 
1715 void RedBack()
1716 {
1717  int idx;
1718 
1719  idx = light4flag ? 1536 : 4608;
1720 
1721  assert(gpBuffer);
1722 
1723  int w, h;
1724  BYTE *dst, *tbl;
1725 
1726  if (leveltype != DTYPE_HELL) {
1727  dst = &gpBuffer[SCREENXY(0, 0)];
1728  tbl = &pLightTbl[idx];
1729  for (h = VIEWPORT_HEIGHT; h; h--, dst += BUFFER_WIDTH - SCREEN_WIDTH) {
1730  for (w = SCREEN_WIDTH; w; w--) {
1731  *dst = tbl[*dst];
1732  dst++;
1733  }
1734  }
1735  } else {
1736  dst = &gpBuffer[SCREENXY(0, 0)];
1737  tbl = &pLightTbl[idx];
1738  for (h = VIEWPORT_HEIGHT; h; h--, dst += BUFFER_WIDTH - SCREEN_WIDTH) {
1739  for (w = SCREEN_WIDTH; w; w--) {
1740  if (*dst >= 32)
1741  *dst = tbl[*dst];
1742  dst++;
1743  }
1744  }
1745  }
1746 }
1747 
1748 char GetSBookTrans(int ii, BOOL townok)
1749 {
1750  char st;
1751 
1752  st = RSPLTYPE_SPELL;
1753  if (plr[myplr]._pISpells & (__int64)1 << (ii - 1)) {
1754  st = RSPLTYPE_CHARGES;
1755  }
1756  if (plr[myplr]._pAblSpells & (__int64)1 << (ii - 1)) {
1757  st = RSPLTYPE_SKILL;
1758  }
1759  if (st == RSPLTYPE_SPELL) {
1760  if (!CheckSpell(myplr, ii, RSPLTYPE_SPELL, TRUE)) {
1761  st = RSPLTYPE_INVALID;
1762  }
1763  if ((char)(plr[myplr]._pSplLvl[ii] + plr[myplr]._pISplLvlAdd) <= 0) {
1764  st = RSPLTYPE_INVALID;
1765  }
1766  }
1767  if (townok && currlevel == 0 && st != RSPLTYPE_INVALID && !spelldata[ii].sTownSpell) {
1768  st = RSPLTYPE_INVALID;
1769  }
1770 
1771  return st;
1772 }
1773 
1775 {
1776  int i, sn, mana, lvl, yp, min, max;
1777  char st;
1778  unsigned __int64 spl;
1779 
1781  CelDraw(RIGHT_PANEL_X + 76 * sbooktab + 7, 348 + SCREEN_Y, pSBkBtnCel, sbooktab + 1, 76);
1782 
1784 
1785  yp = 215;
1786  for (i = 1; i < 8; i++) {
1787  sn = SpellPages[sbooktab][i - 1];
1788  if (sn != -1 && spl & (__int64)1 << (sn - 1)) {
1789  st = GetSBookTrans(sn, TRUE);
1790  SetSpellTrans(st);
1791  DrawSpellCel(RIGHT_PANEL + 75, yp, pSBkIconCels, SpellITbl[sn], 37);
1792  if (sn == plr[myplr]._pRSpell && st == plr[myplr]._pRSplType) {
1795  }
1796  PrintSBookStr(10, yp - 23, FALSE, spelldata[sn].sNameText, COL_WHITE);
1797  switch (GetSBookTrans(sn, FALSE)) {
1798  case RSPLTYPE_SKILL:
1799  strcpy(tempstr, "Skill");
1800  break;
1801  case RSPLTYPE_CHARGES:
1802  sprintf(tempstr, "Staff (%i charges)", plr[myplr].InvBody[INVLOC_HAND_LEFT]._iCharges);
1803  break;
1804  default:
1805  mana = GetManaAmount(myplr, sn) >> 6;
1806  GetDamageAmt(sn, &min, &max);
1807  if (min != -1) {
1808  sprintf(tempstr, "Mana: %i Dam: %i - %i", mana, min, max);
1809  } else {
1810  sprintf(tempstr, "Mana: %i Dam: n/a", mana);
1811  }
1812  if (sn == SPL_BONESPIRIT) {
1813  sprintf(tempstr, "Mana: %i Dam: 1/3 tgt hp", mana);
1814  }
1815  PrintSBookStr(10, yp - 1, FALSE, tempstr, COL_WHITE);
1816  lvl = plr[myplr]._pSplLvl[sn] + plr[myplr]._pISplLvlAdd;
1817  if (lvl < 0) {
1818  lvl = 0;
1819  }
1820  if (lvl == 0) {
1821  sprintf(tempstr, "Spell Level 0 - Unusable");
1822  } else {
1823  sprintf(tempstr, "Spell Level %i", lvl);
1824  }
1825  break;
1826  }
1827  PrintSBookStr(10, yp - 12, FALSE, tempstr, COL_WHITE);
1828  }
1829  yp += 43;
1830  }
1831 }
1832 
1833 void PrintSBookStr(int x, int y, BOOL cjustflag, char *pszStr, char col)
1834 {
1835  BYTE c;
1836  char *tmp;
1837  int screen_x, line, sx;
1838 
1839  sx = x + RIGHT_PANEL + 120;
1840  line = 0;
1841  if (cjustflag) {
1842  screen_x = 0;
1843  tmp = pszStr;
1844  while (*tmp) {
1845  c = gbFontTransTbl[(BYTE)*tmp++];
1846  screen_x += fontkern[fontframe[c]] + 1;
1847  }
1848  if (screen_x < 222)
1849  line = (222 - screen_x) >> 1;
1850  sx += line;
1851  }
1852  while (*pszStr) {
1853  c = gbFontTransTbl[(BYTE)*pszStr++];
1854  c = fontframe[c];
1855  line += fontkern[c] + 1;
1856  if (c) {
1857  if (line <= 222)
1858  PrintChar(sx, y, c, col);
1859  }
1860  sx += fontkern[c] + 1;
1861  }
1862 }
1863 
1865 {
1866  int sn;
1867  char st;
1868  unsigned __int64 spl;
1869 
1870  if (MouseX >= RIGHT_PANEL + 11 && MouseX < RIGHT_PANEL + 48 && MouseY >= 18 && MouseY < 314) {
1872  sn = SpellPages[sbooktab][(MouseY - 18) / 43];
1873  if (sn != -1 && spl & (__int64)1 << (sn - 1)) {
1874  st = RSPLTYPE_SPELL;
1875  if (plr[myplr]._pISpells & (__int64)1 << (sn - 1)) {
1876  st = RSPLTYPE_CHARGES;
1877  }
1878  if (plr[myplr]._pAblSpells & (__int64)1 << (sn - 1)) {
1879  st = RSPLTYPE_SKILL;
1880  }
1881  plr[myplr]._pRSpell = sn;
1882  plr[myplr]._pRSplType = st;
1883  force_redraw = 255;
1884  }
1885  }
1886  if (MouseX >= RIGHT_PANEL + 7 && MouseX < RIGHT_PANEL + 311 && MouseY >= SPANEL_WIDTH && MouseY < 349) {
1887  sbooktab = (MouseX - (RIGHT_PANEL + 7)) / 76;
1888  }
1889 }
1890 
1891 char *get_pieces_str(int nGold)
1892 {
1893  char *result;
1894 
1895  result = "piece";
1896  if (nGold != 1)
1897  result = "pieces";
1898  return result;
1899 }
1900 
1901 void DrawGoldSplit(int amount)
1902 {
1903  int screen_x, i;
1904 
1905  screen_x = 0;
1906  CelDraw(351 + SCREEN_X, 178 + SCREEN_Y, pGBoxBuff, 1, 261);
1907  sprintf(tempstr, "You have %u gold", initialDropGoldValue);
1908  ADD_PlrStringXY(366, 87, 600, tempstr, COL_GOLD);
1909  sprintf(tempstr, "%s. How many do", get_pieces_str(initialDropGoldValue));
1910  ADD_PlrStringXY(366, 103, 600, tempstr, COL_GOLD);
1911  ADD_PlrStringXY(366, 121, 600, "you want to remove?", COL_GOLD);
1912  if (amount > 0) {
1913  sprintf(tempstr, "%u", amount);
1914  PrintGameStr(388, 140, tempstr, 0);
1915  for (i = 0; i < tempstr[i]; i++) {
1916  screen_x += fontkern[fontframe[gbFontTransTbl[(BYTE)tempstr[i]]]] + 1;
1917  }
1918  screen_x += 452;
1919  } else {
1920  screen_x = 450;
1921  }
1922  CelDraw(screen_x, 140 + SCREEN_Y, pSPentSpn2Cels, PentSpn2Frame, 12);
1923  PentSpn2Spin();
1924 }
1925 
1926 void control_drop_gold(char vkey)
1927 {
1928  char input[6];
1929 
1930  if (plr[myplr]._pHitPoints >> 6 <= 0) {
1931  dropGoldFlag = FALSE;
1932  dropGoldValue = 0;
1933  return;
1934  }
1935 
1936  memset(input, 0, sizeof(input));
1937  snprintf(input, sizeof(input), "%d", dropGoldValue);
1938  if (vkey == VK_RETURN) {
1939  if (dropGoldValue > 0)
1941  dropGoldFlag = FALSE;
1942  } else if (vkey == VK_ESCAPE) {
1943  dropGoldFlag = FALSE;
1944  dropGoldValue = 0;
1945  } else if (vkey == VK_BACK) {
1946  input[strlen(input) - 1] = '\0';
1947  dropGoldValue = atoi(input);
1948  } else if (vkey - '0' >= 0 && vkey - '0' <= 9) {
1949  if (dropGoldValue || atoi(input) <= initialDropGoldValue) {
1950  input[strlen(input)] = vkey;
1951  if (atoi(input) > initialDropGoldValue)
1952  return;
1953  if (strlen(input) > strlen(input))
1954  return;
1955  } else {
1956  input[0] = vkey;
1957  }
1958  dropGoldValue = atoi(input);
1959  }
1960 }
1961 
1962 void control_remove_gold(int pnum, int gold_index)
1963 {
1964  int gi;
1965 
1966  if (gold_index <= INVITEM_INV_LAST) {
1967  gi = gold_index - INVITEM_INV_FIRST;
1968  plr[pnum].InvList[gi]._ivalue -= dropGoldValue;
1969  if (plr[pnum].InvList[gi]._ivalue > 0)
1970  SetGoldCurs(pnum, gi);
1971  else
1972  RemoveInvItem(pnum, gi);
1973  } else {
1974  gi = gold_index - INVITEM_BELT_FIRST;
1975  plr[pnum].SpdList[gi]._ivalue -= dropGoldValue;
1976  if (plr[pnum].SpdList[gi]._ivalue > 0)
1977  SetSpdbarGoldCurs(pnum, gi);
1978  else
1979  RemoveSpdBarItem(pnum, gi);
1980  }
1981  SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD);
1982  GetGoldSeed(pnum, &plr[pnum].HoldItem);
1984  plr[pnum].HoldItem._iStatFlag = TRUE;
1985  control_set_gold_curs(pnum);
1986  plr[pnum]._pGold = CalculateGold(pnum);
1987  dropGoldValue = 0;
1988 }
1989 
1991 {
1992  if (plr[pnum].HoldItem._ivalue >= GOLD_MEDIUM_LIMIT)
1994  else if (plr[pnum].HoldItem._ivalue <= GOLD_SMALL_LIMIT)
1996  else
1998 
1999  NewCursor(plr[pnum].HoldItem._iCurs + CURSOR_FIRSTITEM);
2000 }
2001 
2003 {
2004  int i, off, talk_btn, color, nCel, x;
2005  char *msg;
2006 
2007  if (!talkflag)
2008  return;
2009 
2010  DrawPanelBox(175, sgbPlrTalkTbl + 20, 294, 5, PANEL_X + 175, PANEL_Y + 4);
2011  off = 0;
2012  for (i = 293; i > 283; off++, i--) {
2013  DrawPanelBox((off >> 1) + 175, sgbPlrTalkTbl + off + 25, i, 1, (off >> 1) + PANEL_X + 175, off + PANEL_Y + 9);
2014  }
2015  DrawPanelBox(185, sgbPlrTalkTbl + 35, 274, 30, PANEL_X + 185, PANEL_Y + 19);
2016  DrawPanelBox(180, sgbPlrTalkTbl + 65, 284, 5, PANEL_X + 180, PANEL_Y + 49);
2017  for (i = 0; i < 10; i++) {
2018  DrawPanelBox(180, sgbPlrTalkTbl + i + 70, i + 284, 1, PANEL_X + 180, i + PANEL_Y + 54);
2019  }
2020  DrawPanelBox(170, sgbPlrTalkTbl + 80, 310, 55, PANEL_X + 170, PANEL_Y + 64);
2021  msg = sgszTalkMsg;
2022  for (i = 0; i < 39; i += 13) {
2023  x = 0 + PANEL_LEFT;
2024  msg = control_print_talk_msg(msg, &x, i, 0);
2025  if (!msg)
2026  break;
2027  }
2028  if (msg)
2029  *msg = '\0';
2030  CelDraw(x, i + 22 + PANEL_Y, pSPentSpn2Cels, PentSpn2Frame, 12);
2031  PentSpn2Spin();
2032  talk_btn = 0;
2033  for (i = 0; i < 4; i++) {
2034  if (i == myplr)
2035  continue;
2036  if (whisper[i]) {
2037  color = COL_GOLD;
2038  if (talkbtndown[talk_btn]) {
2039  if (talk_btn != 0)
2040  nCel = 4;
2041  else
2042  nCel = 3;
2043  CelDraw(172 + PANEL_X, 84 + 18 * talk_btn + PANEL_Y, pTalkBtns, nCel, 61);
2044  }
2045  } else {
2046  color = COL_RED;
2047  if (talk_btn != 0)
2048  nCel = 2;
2049  else
2050  nCel = 1;
2051  if (talkbtndown[talk_btn])
2052  nCel += 4;
2053  CelDraw(172 + PANEL_X, 84 + 18 * talk_btn + PANEL_Y, pTalkBtns, nCel, 61);
2054  }
2055  if (plr[i].plractive) {
2056  x = 46 + PANEL_LEFT;
2057  control_print_talk_msg(plr[i]._pName, &x, 60 + talk_btn * 18, color);
2058  }
2059 
2060  talk_btn++;
2061  }
2062 }
2063 
2064 char *control_print_talk_msg(char *msg, int *x, int y, int color)
2065 {
2066  BYTE c;
2067  int width;
2068 
2069  *x += 264;
2070  width = *x;
2071  while (*msg) {
2072 
2073  c = fontframe[gbFontTransTbl[(BYTE)*msg]];
2074  width += fontkern[c] + 1;
2075  if (width > 514 + PANEL_LEFT)
2076  return msg;
2077  msg++;
2078  if (c) {
2079  PrintChar(*x, y + 22 + PANEL_Y, c, color);
2080  }
2081  *x += fontkern[c] + 1;
2082  }
2083  return NULL;
2084 }
2085 
2087 {
2088  int i;
2089 
2090  if (!talkflag)
2091  return FALSE;
2092 
2093  if (MouseX < 172 + PANEL_LEFT)
2094  return FALSE;
2095  if (MouseY < 69 + PANEL_TOP)
2096  return FALSE;
2097  if (MouseX > 233 + PANEL_LEFT)
2098  return FALSE;
2099  if (MouseY > 123 + PANEL_TOP)
2100  return FALSE;
2101 
2102  for (i = 0; i < sizeof(talkbtndown) / sizeof(talkbtndown[0]); i++) {
2103  talkbtndown[i] = FALSE;
2104  }
2105 
2106  talkbtndown[(MouseY - (69 + PANEL_TOP)) / 18] = TRUE;
2107 
2108  return TRUE;
2109 }
2110 
2112 {
2113  int i, p, off;
2114 
2115  if (talkflag) {
2116  for (i = 0; i < sizeof(talkbtndown) / sizeof(talkbtndown[0]); i++)
2117  talkbtndown[i] = FALSE;
2118  if (MouseX >= 172 + PANEL_LEFT && MouseY >= 421 + PANEL_LEFT && MouseX <= -119 + PANEL_TOP && MouseY <= 123 + PANEL_TOP) {
2119  off = (MouseY - (69 + PANEL_TOP)) / 18;
2120 
2121  for (p = 0; p < MAX_PLRS && off != -1; p++) {
2122  if (p != myplr)
2123  off--;
2124  }
2125  if (p <= MAX_PLRS)
2126  whisper[p - 1] = !whisper[p - 1];
2127  }
2128  }
2129 }
2130 
2131 void control_reset_talk_msg(char *msg)
2132 {
2133  int i, pmask;
2134  pmask = 0;
2135 
2136  for (i = 0; i < MAX_PLRS; i++) {
2137  if (whisper[i])
2138  pmask |= 1 << i;
2139  }
2140  NetSendCmdString(pmask, sgszTalkMsg);
2141 }
2142 
2144 {
2145  int i;
2146 
2147  if (gbMaxPlayers == 1) {
2148  return;
2149  }
2150 
2151  talkflag = TRUE;
2152  sgszTalkMsg[0] = 0;
2153  PentSpn2Frame = 1;
2154  for (i = 0; i < 3; i++) {
2155  talkbtndown[i] = FALSE;
2156  }
2157  sgbPlrTalkTbl = PANEL_HEIGHT + 16;
2158  force_redraw = 255;
2160 }
2161 
2163 {
2164  talkflag = FALSE;
2165  sgbPlrTalkTbl = 0;
2166  force_redraw = 255;
2167 }
2168 
2170 {
2171  int result;
2172 
2173  if (gbMaxPlayers == 1)
2174  return FALSE;
2175 
2176  if (!talkflag)
2177  return FALSE;
2178 
2179  if ((DWORD)vkey < VK_SPACE)
2180  return FALSE;
2181 
2182  result = strlen(sgszTalkMsg);
2183  if (result < 78) {
2184  sgszTalkMsg[result] = vkey;
2185  sgszTalkMsg[result + 1] = '\0';
2186  }
2187  return TRUE;
2188 }
2189 
2190 BOOL control_presskeys(int vkey)
2191 {
2192  int len;
2193  BOOL ret;
2194 
2195  if (gbMaxPlayers != 1) {
2196  if (!talkflag) {
2197  ret = FALSE;
2198  } else {
2199  if (vkey == VK_SPACE) {
2200  } else if (vkey == VK_ESCAPE) {
2202  } else if (vkey == VK_RETURN) {
2204  } else if (vkey == VK_BACK) {
2205  len = strlen(sgszTalkMsg);
2206  if (len > 0)
2207  sgszTalkMsg[len - 1] = '\0';
2208  } else if (vkey == VK_DOWN) {
2209  control_up_down(1);
2210  } else if (vkey == VK_UP) {
2211  control_up_down(-1);
2212  } else {
2213  return FALSE;
2214  }
2215  ret = TRUE;
2216  }
2217  } else {
2218  ret = FALSE;
2219  }
2220  return ret;
2221 }
2222 
2224 {
2225  int i;
2226  BYTE talk_save;
2227 
2228  if (sgszTalkMsg[0]) {
2230  for (i = 0; i < 8; i++) {
2231  if (!strcmp(sgszTalkSave[i], sgszTalkMsg))
2232  break;
2233  }
2234  if (i >= 8) {
2236  sgbNextTalkSave++;
2237  sgbNextTalkSave &= 7;
2238  } else {
2239  talk_save = sgbNextTalkSave - 1;
2240  talk_save &= 7;
2241  if (i != talk_save) {
2242  strcpy(sgszTalkSave[i], sgszTalkSave[talk_save]);
2243  strcpy(sgszTalkSave[talk_save], sgszTalkMsg);
2244  }
2245  }
2246  sgszTalkMsg[0] = '\0';
2248  }
2250 }
2251 
2252 void control_up_down(int v)
2253 {
2254  int i;
2255 
2256  for (i = 0; i < 8; i++) {
2257  sgbTalkSavePos = (v + sgbTalkSavePos) & 7;
2258  if (sgszTalkSave[sgbTalkSavePos][0]) {
2260  return;
2261  }
2262  }
2263 }
2264 
InitControlPan
void InitControlPan()
Definition: control.cpp:747
DrawFlask
void DrawFlask(BYTE *pCelBuff, int w, int nSrcOff, BYTE *pBuff, int nDstOff, int h)
Draws the dome of the flask that protrudes above the panel top line.
Definition: control.cpp:625
gpBuffer
BYTE * gpBuffer
sgbNextTalkSave
DEVILUTION_BEGIN_NAMESPACE BYTE sgbNextTalkSave
Definition: control.cpp:10
PlayerStruct::_pMagResist
char _pMagResist
Definition: structs.h:272
SPL_HBOLT
@ SPL_HBOLT
Definition: enums.h:2161
pGBoxBuff
BYTE * pGBoxBuff
Definition: control.cpp:39
PlayerStruct::_pGold
int _pGold
Definition: structs.h:275
control_release_talk_btn
void control_release_talk_btn()
Definition: control.cpp:2111
ATTRIB_STR
@ ATTRIB_STR
Definition: enums.h:2322
chrbtn
BOOL chrbtn[4]
Definition: control.cpp:17
control_remove_gold
void control_remove_gold(int pnum, int gold_index)
Definition: control.cpp:1962
SPL_FLAME
@ SPL_FLAME
Definition: enums.h:2150
pSBkBtnCel
BYTE * pSBkBtnCel
Definition: control.cpp:40
talkflag
BOOL talkflag
Definition: control.cpp:46
MouseY
int MouseY
Definition: diablo.cpp:17
control_talk_last_key
BOOL control_talk_last_key(int vkey)
Definition: control.cpp:2169
pQLogCel
BYTE * pQLogCel
Definition: quests.cpp:7
PANEL_X
#define PANEL_X
Definition: defs.h:136
SetGoldCurs
void SetGoldCurs(int pnum, int i)
Definition: stores.cpp:1762
SCREENXY
#define SCREENXY(x, y)
Definition: defs.h:155
ITEM_QUALITY_MAGIC
@ ITEM_QUALITY_MAGIC
Definition: enums.h:9
DrawCtrlPan
void DrawCtrlPan()
Definition: control.cpp:831
force_redraw
int force_redraw
Definition: diablo.cpp:30
currlevel
BYTE currlevel
Definition: gendung.cpp:40
PlayerStruct::_pMaxHP
int _pMaxHP
Definition: structs.h:259
SPL_FIREBOLT
@ SPL_FIREBOLT
Definition: enums.h:2131
PlayerStruct::_pMana
int _pMana
Definition: structs.h:263
SPL_RESURRECT
@ SPL_RESURRECT
Definition: enums.h:2162
ItemStruct::_iCurs
int _iCurs
Definition: structs.h:121
DrawChr
void DrawChr()
Definition: control.cpp:1321
DoPanBtn
void DoPanBtn()
Checks if the mouse cursor is within any of the panel buttons and flag it if so.
Definition: control.cpp:920
SPL_HEALOTHER
@ SPL_HEALOTHER
Definition: enums.h:2164
CMD_ADDMAG
@ CMD_ADDMAG
Definition: enums.h:2175
PANEL_Y
#define PANEL_Y
Definition: defs.h:137
SPL_NULL
@ SPL_NULL
Definition: enums.h:2130
CMD_ADDVIT
@ CMD_ADDVIT
Definition: enums.h:2177
RSPLTYPE_CHARGES
@ RSPLTYPE_CHARGES
Definition: enums.h:2061
control_check_btn_press
void control_check_btn_press()
Definition: control.cpp:946
SCREEN_Y
#define SCREEN_Y
Definition: defs.h:126
GetItemStr
void GetItemStr(int i)
Definition: items.cpp:2496
MAX_PLRS
#define MAX_PLRS
Definition: defs.h:16
INVITEM_INV_FIRST
@ INVITEM_INV_FIRST
Definition: enums.h:2807
pLightTbl
BYTE * pLightTbl
Definition: lighting.cpp:21
INVLOC_HEAD
@ INVLOC_HEAD
Definition: enums.h:2789
sgbPlrTalkTbl
int sgbPlrTalkTbl
Definition: control.cpp:38
pBtmBuff
BYTE * pBtmBuff
Definition: control.cpp:29
GOLD_MEDIUM_LIMIT
#define GOLD_MEDIUM_LIMIT
Definition: defs.h:67
DrawTalkPan
void DrawTalkPan()
Definition: control.cpp:2002
ReleaseChrBtns
void ReleaseChrBtns()
Definition: control.cpp:1628
get_pieces_str
char * get_pieces_str(int nGold)
Definition: control.cpp:1891
pDurIcons
BYTE * pDurIcons
Definition: control.cpp:12
PlayerStruct::_pMaxHPBase
int _pMaxHPBase
Definition: structs.h:257
PlayerStruct::_pIBonusDamMod
int _pIBonusDamMod
Definition: structs.h:325
PANBTN_AUTOMAP
@ PANBTN_AUTOMAP
Definition: enums.h:2313
SPLICONLENGTH
#define SPLICONLENGTH
Definition: control.cpp:213
ItemStruct::_iStatFlag
BOOL _iStatFlag
Definition: structs.h:169
SPL_STONE
@ SPL_STONE
Definition: enums.h:2138
DrawSpellList
void DrawSpellList()
Definition: control.cpp:317
INVLOC_CHEST
@ INVLOC_CHEST
Definition: enums.h:2795
PrintSBookStr
void PrintSBookStr(int x, int y, BOOL cjustflag, char *pszStr, char col)
Definition: control.cpp:1833
PlayerStruct::_pNumInv
int _pNumInv
Definition: structs.h:315
PANBTN_FRIENDLY
@ PANBTN_FRIENDLY
Definition: enums.h:2318
pcursinvitem
char pcursinvitem
inv_item value
Definition: cursor.cpp:19
PlayerStruct::_pAblSpells
uint64_t _pAblSpells
Definition: structs.h:227
PlayerStruct::_pRSpell
int _pRSpell
Definition: structs.h:220
ItemStruct::_iDurability
int _iDurability
Definition: structs.h:135
gamemenu_off
void gamemenu_off()
Definition: gamemenu.cpp:85
pcursplr
char pcursplr
Definition: cursor.cpp:23
pSPentSpn2Cels
BYTE * pSPentSpn2Cels
Definition: stores.cpp:31
PentSpn2Frame
BYTE PentSpn2Frame
Definition: stores.cpp:32
SPLROWICONLS
#define SPLROWICONLS
Definition: control.cpp:214
PlayerStruct::_pISpells
uint64_t _pISpells
Definition: structs.h:326
ICURS_GOLD_MEDIUM
@ ICURS_GOLD_MEDIUM
Definition: enums.h:178
GetObjectStr
void GetObjectStr(int i)
Definition: objects.cpp:4317
SplTransTbl
BYTE SplTransTbl[256]
Definition: control.cpp:57
ItemStruct::_itype
int _itype
Definition: structs.h:102
SPL_TOWN
@ SPL_TOWN
Definition: enums.h:2137
PlayerStruct::HoldItem
ItemStruct HoldItem
Definition: structs.h:318
questlog
BOOL questlog
Definition: quests.cpp:6
EMSG_NO_AUTOMAP_IN_TOWN
@ EMSG_NO_AUTOMAP_IN_TOWN
Definition: enums.h:1897
SPL_FIREWALL
@ SPL_FIREWALL
Definition: enums.h:2136
pStatusPanel
BYTE * pStatusPanel
Definition: control.cpp:54
ITYPE_NONE
@ ITYPE_NONE
Definition: enums.h:2495
pSpellBkCel
BYTE * pSpellBkCel
Definition: control.cpp:51
DrawDurIcon
void DrawDurIcon()
Definition: control.cpp:1663
COL_WHITE
@ COL_WHITE
Definition: enums.h:1993
SPL_FIREBALL
@ SPL_FIREBALL
Definition: enums.h:2142
sgszTalkMsg
char sgszTalkMsg[MAX_SEND_STR_LEN]
Definition: control.cpp:26
PlayerStruct::_pSplLvl
char _pSplLvl[64]
Definition: structs.h:225
SetFlaskHeight
void SetFlaskHeight(BYTE *pCelBuff, int min, int max, int sx, int sy)
Draws a section of the empty flask cel on top of the panel to create the illusion of the flask gettin...
Definition: control.cpp:595
INVLOC_HAND_LEFT
@ INVLOC_HAND_LEFT
Definition: enums.h:2793
dropGoldValue
int dropGoldValue
Definition: control.cpp:23
PlayerStruct::InvList
ItemStruct InvList[NUM_INV_GRID_ELEM]
Definition: structs.h:314
control_reset_talk_msg
void control_reset_talk_msg(char *msg)
Definition: control.cpp:2131
CheckBtnUp
void CheckBtnUp()
Check if the mouse is within a control panel button that's flagged.
Definition: control.cpp:1075
trigflag
BOOL trigflag
Definition: trigs.cpp:6
RSPLTYPE_SPELL
@ RSPLTYPE_SPELL
Definition: enums.h:2059
PentSpn2Spin
void PentSpn2Spin()
Definition: stores.cpp:76
COL_GOLD
@ COL_GOLD
Definition: enums.h:1996
VIEWPORT_HEIGHT
#define VIEWPORT_HEIGHT
Definition: defs.h:149
PANBTN_CHARINFO
@ PANBTN_CHARINFO
Definition: enums.h:2311
MemFreeDbg
#define MemFreeDbg(p)
Definition: defs.h:157
gamemenu_handle_previous
void gamemenu_handle_previous()
Definition: gamemenu.cpp:90
DrawSpell
void DrawSpell()
Sets the spell frame to draw and its position then draws it.
Definition: control.cpp:290
pChrButtons
BYTE * pChrButtons
Definition: control.cpp:13
NetSendCmdString
void NetSendCmdString(int pmask, const char *pszStr)
Definition: msg.cpp:965
towner
TownerStruct towner[16]
Definition: towners.cpp:13
automapflag
BOOL automapflag
Specifies whether the automap is enabled.
Definition: automap.cpp:18
StartAutomap
void StartAutomap()
Definition: automap.cpp:119
PAL16_YELLOW
#define PAL16_YELLOW
Definition: defs.h:100
ItemStruct::_ivalue
int _ivalue
Definition: structs.h:122
all.h
DoAutoMap
void DoAutoMap()
Definition: control.cpp:962
DrawLevelUpIcon
void DrawLevelUpIcon()
Definition: control.cpp:1579
CalcStatDiff
int CalcStatDiff(int pnum)
Definition: player.cpp:685
SetSpdbarGoldCurs
void SetSpdbarGoldCurs(int pnum, int i)
Definition: stores.cpp:1772
PlayerStruct::SpdList
ItemStruct SpdList[MAXBELTITEMS]
Definition: structs.h:317
GetGoldSeed
void GetGoldSeed(int pnum, ItemStruct *h)
Definition: items.cpp:823
PlayerStruct::_pIMaxDam
int _pIMaxDam
Definition: structs.h:320
control_drop_gold
void control_drop_gold(char vkey)
Definition: control.cpp:1926
whisper
BOOLEAN whisper[MAX_PLRS]
Definition: control.cpp:42
GOLD_SMALL_LIMIT
#define GOLD_SMALL_LIMIT
Definition: defs.h:66
initialDropGoldIndex
int initialDropGoldIndex
Definition: control.cpp:45
pSplType
int pSplType
Definition: control.cpp:44
pnumlines
int pnumlines
Definition: control.cpp:32
spelldata
DEVILUTION_BEGIN_NAMESPACE SpellData spelldata[]
Data related to each spell ID.
Definition: spelldat.cpp:6
infostr
char infostr[256]
Definition: control.cpp:52
DrawDurIcon4Item
int DrawDurIcon4Item(ItemStruct *pItem, int x, int c)
Definition: control.cpp:1680
PlayerStruct::_pClass
char _pClass
Definition: structs.h:244
MAXBELTITEMS
#define MAXBELTITEMS
Definition: defs.h:28
ItemStruct
Definition: structs.h:99
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
PlayerStruct::_pSplHotKey
int _pSplHotKey[4]
Definition: structs.h:230
sgbTalkSavePos
BYTE sgbTalkSavePos
Definition: control.cpp:11
PanBtnPos
int PanBtnPos[8][5]
Maps from panel_button_id to the position and dimensions of a panel button.
Definition: control.cpp:170
SCREEN_WIDTH
#define SCREEN_WIDTH
Definition: defs.h:105
RIGHT_PANEL
#define RIGHT_PANEL
Definition: defs.h:143
PANBTN_MAINMENU
@ PANBTN_MAINMENU
Definition: enums.h:2314
control_type_message
void control_type_message()
Definition: control.cpp:2143
numpanbtns
int numpanbtns
Definition: control.cpp:53
UpdateManaFlask
void UpdateManaFlask()
Controls the drawing of the area of the life flask within the control panel.
Definition: control.cpp:720
ChrBtnsRect
RECT32 ChrBtnsRect[4]
Maps from attribute_id to the rectangle on screen used for attribute increment buttons.
Definition: control.cpp:196
sbookflag
BOOL sbookflag
Definition: control.cpp:48
ClearPanel
void ClearPanel()
Definition: control.cpp:559
SPL_RNDTELEPORT
@ SPL_RNDTELEPORT
Definition: enums.h:2140
INVLOC_HAND_RIGHT
@ INVLOC_HAND_RIGHT
Definition: enums.h:2794
lineOffsets
const int lineOffsets[5][5]
Line start position for info box text when displaying 1, 2, 3, 4 and 5 lines respectivly.
Definition: control.cpp:93
ICURS_GOLD_SMALL
@ ICURS_GOLD_SMALL
Definition: enums.h:177
DrawPanelBox
void DrawPanelBox(int x, int y, int w, int h, int sx, int sy)
Definition: control.cpp:565
PlayerStruct::_pMaxMana
int _pMaxMana
Definition: structs.h:264
CURSOR_FIRSTITEM
@ CURSOR_FIRSTITEM
Definition: enums.h:2078
light4flag
BOOL light4flag
Definition: diablo.cpp:34
NetSendCmdParam1
void NetSendCmdParam1(BOOL bHiPri, BYTE bCmd, WORD wParam1)
Definition: msg.cpp:698
SPL_MANASHIELD
@ SPL_MANASHIELD
Definition: enums.h:2141
control_presskeys
BOOL control_presskeys(int vkey)
Definition: control.cpp:2190
SPL_ETHEREALIZE
@ SPL_ETHEREALIZE
Definition: enums.h:2155
CheckSBook
void CheckSBook()
Definition: control.cpp:1864
ATTRIB_VIT
@ ATTRIB_VIT
Definition: enums.h:2325
ICURS_GOLD_LARGE
@ ICURS_GOLD_LARGE
Definition: enums.h:179
SPL_DISARM
@ SPL_DISARM
Definition: enums.h:2158
assert
#define assert(exp)
Definition: defs.h:168
ReleaseLvlBtn
void ReleaseLvlBtn()
Definition: control.cpp:1572
drawbtnflag
BOOL drawbtnflag
Definition: control.cpp:50
SPL_LIGHTNING
@ SPL_LIGHTNING
Definition: enums.h:2133
pMultiBtns
BYTE * pMultiBtns
Definition: control.cpp:18
ItemStruct::_iClass
char _iClass
Definition: structs.h:120
PlayerStruct::_pFireResist
char _pFireResist
Definition: structs.h:273
pTalkPanel
BYTE * pTalkPanel
Definition: control.cpp:61
UpdateLifeFlask
void UpdateLifeFlask()
Controls the drawing of the area of the life flask within the control panel.
Definition: control.cpp:669
DrawManaFlask
void DrawManaFlask()
Definition: control.cpp:684
SPL_GOLEM
@ SPL_GOLEM
Definition: enums.h:2151
PrintInfo
void PrintInfo()
Definition: control.cpp:1254
SpellITbl
char SpellITbl[MAX_SPELLS]
Maps from spell_id to spelicon.cel frame number.
Definition: control.cpp:130
PanBtnStr
char * PanBtnStr[8]
Maps from panel_button_id to panel button description.
Definition: control.cpp:185
RECT32
Definition: structs.h:11
SPL_REPAIR
@ SPL_REPAIR
Definition: enums.h:2156
control_check_talk_btn
BOOL control_check_talk_btn()
Definition: control.cpp:2086
pLifeBuff
BYTE * pLifeBuff
Definition: control.cpp:28
DEVILUTION_END_NAMESPACE
#define DEVILUTION_END_NAMESPACE
Definition: types.h:10
SPLICONLAST
#define SPLICONLAST
Definition: control.cpp:215
ITYPE_GOLD
@ ITYPE_GOLD
Definition: enums.h:2491
PrintMonstHistory
void PrintMonstHistory(int mt)
Definition: monster.cpp:4977
SPL_CHAIN
@ SPL_CHAIN
Definition: enums.h:2144
pChrPanel
BYTE * pChrPanel
Definition: control.cpp:20
FriendlyMode
BOOL FriendlyMode
Specifies whether players are in non-PvP mode.
Definition: diablo.cpp:72
monster
MonsterStruct monster[MAXMONSTERS]
Definition: monster.cpp:19
SetPlrHandItem
void SetPlrHandItem(ItemStruct *h, int idata)
Definition: items.cpp:779
PlayerStruct::_pISplLvlAdd
char _pISplLvlAdd
Definition: structs.h:329
SPL_ELEMENT
@ SPL_ELEMENT
Definition: enums.h:2159
AddPanelString
void AddPanelString(char *str, BOOL just)
Definition: control.cpp:550
PrintUniqueHistory
void PrintUniqueHistory()
Definition: monster.cpp:5042
DrawCtrlBtns
void DrawCtrlBtns()
Draws the control panel buttons in their current state.
Definition: control.cpp:841
PlayerStruct::_pDamageMod
int _pDamageMod
Definition: structs.h:254
RSPLTYPE_SCROLL
@ RSPLTYPE_SCROLL
Definition: enums.h:2060
pstrjust
BOOL pstrjust[4]
Definition: control.cpp:31
SPL_TELEKINESIS
@ SPL_TELEKINESIS
Definition: enums.h:2163
ITYPE_BOW
@ ITYPE_BOW
Definition: enums.h:2483
ATTRIB_DEX
@ ATTRIB_DEX
Definition: enums.h:2324
RSPLTYPE_INVALID
@ RSPLTYPE_INVALID
Definition: enums.h:2062
LoadFileInMem
BYTE * LoadFileInMem(char *pszName, DWORD *pdwFileLen)
Load a file in to a buffer.
Definition: engine.cpp:801
RemoveInvItem
void RemoveInvItem(int pnum, int iv)
Definition: inv.cpp:1276
pSpellCels
BYTE * pSpellCels
Definition: control.cpp:59
pSBkIconCels
BYTE * pSBkIconCels
Definition: control.cpp:47
PANEL_WIDTH
#define PANEL_WIDTH
Definition: defs.h:132
SPL_CBOLT
@ SPL_CBOLT
Definition: enums.h:2160
CalculateGold
int CalculateGold(int pnum)
Definition: inv.cpp:2217
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
SPL_FLARE
@ SPL_FLARE
Definition: enums.h:2165
PAL16_GRAY
#define PAL16_GRAY
Definition: defs.h:103
RIGHT_PANEL_X
#define RIGHT_PANEL_X
Definition: defs.h:144
pSpell
int pSpell
Definition: control.cpp:35
RSPLTYPE_SKILL
@ RSPLTYPE_SKILL
Definition: enums.h:2058
pManaBuff
BYTE * pManaBuff
Definition: control.cpp:36
MAXRESIST
#define MAXRESIST
Definition: defs.h:64
control_press_enter
void control_press_enter()
Definition: control.cpp:2223
chrbtnactive
BOOL chrbtnactive
Definition: control.cpp:25
SPL_BONESPIRIT
@ SPL_BONESPIRIT
Definition: enums.h:2166
CMD_ADDSTR
@ CMD_ADDSTR
Definition: enums.h:2174
GetSBookTrans
char GetSBookTrans(int ii, BOOL townok)
Definition: control.cpp:1748
COL_RED
@ COL_RED
Definition: enums.h:1995
control_WriteStringToBuffer
BOOL control_WriteStringToBuffer(BYTE *str)
Definition: control.cpp:1170
NewCursor
void NewCursor(int i)
Definition: cursor.cpp:107
ITYPE_STAFF
@ ITYPE_STAFF
Definition: enums.h:2490
IDI_GOLD
@ IDI_GOLD
Definition: enums.h:2499
SPL_HEAL
@ SPL_HEAL
Definition: enums.h:2132
FreeControlPan
void FreeControlPan()
Definition: control.cpp:1150
sbooktab
int sbooktab
Definition: control.cpp:43
PlayerStruct::_pMaxManaBase
int _pMaxManaBase
Definition: structs.h:262
PlayerStruct::_pLghtResist
char _pLghtResist
Definition: structs.h:274
ITEM_QUALITY_UNIQUE
@ ITEM_QUALITY_UNIQUE
Definition: enums.h:10
PlayerStruct::_pMemSpells
uint64_t _pMemSpells
Definition: structs.h:226
panbtndown
BOOL panbtndown
Definition: control.cpp:60
StartQuestlog
void StartQuestlog()
Definition: quests.cpp:748
panbtn
BOOL panbtn[8]
Definition: control.cpp:16
GetDamageAmt
void GetDamageAmt(int i, int *mind, int *maxd)
Definition: missiles.cpp:24
COL_BLUE
@ COL_BLUE
Definition: enums.h:1994
DoSpeedBook
void DoSpeedBook()
Draws the "Speed Book": the rows of known spells for quick-setting a spell that show up when you clic...
Definition: control.cpp:864
spell_type
spell_type
Definition: enums.h:2057
SpellPages
int SpellPages[6][7]
Maps from spellbook page number and position to spell_id.
Definition: control.cpp:204
fontkern
const BYTE fontkern[68]
Maps from smaltext.cel frame number to character width.
Definition: control.cpp:81
CheckSpell
BOOL CheckSpell(int id, int sn, char st, BOOL manaonly)
Definition: spells.cpp:81
CheckPanelInfo
void CheckPanelInfo()
Checks the mouse cursor position within the control panel and sets information strings if needed.
Definition: control.cpp:978
CelBlitWidth
void CelBlitWidth(BYTE *pBuff, int x, int y, int wdt, BYTE *pCelBuff, int nCel, int nWidth)
Blit to a buffer at given coordinates.
Definition: engine.cpp:509
control_print_talk_msg
char * control_print_talk_msg(char *msg, int *x, int y, int color)
Definition: control.cpp:2064
SPANEL_WIDTH
#define SPANEL_WIDTH
Definition: defs.h:139
pcursmonst
int pcursmonst
Definition: cursor.cpp:13
ADD_PlrStringXY
#define ADD_PlrStringXY(x, y, width, pszStr, col)
Definition: control.h:94
PlayerStruct::_pIBonusDam
int _pIBonusDam
Definition: structs.h:322
pcursobj
char pcursobj
Definition: cursor.cpp:22
DrawLifeFlask
void DrawLifeFlask()
Draws the top dome of the life flask (that part that protrudes out of the control panel).
Definition: control.cpp:647
control_up_down
void control_up_down(int v)
Definition: control.cpp:2252
pinfoflag
BOOL pinfoflag
Definition: control.cpp:33
GetManaAmount
DEVILUTION_BEGIN_NAMESPACE int GetManaAmount(int id, int sn)
Definition: spells.cpp:5
DTYPE_TOWN
@ DTYPE_TOWN
Definition: enums.h:1868
DTYPE_HELL
@ DTYPE_HELL
Definition: enums.h:1872
ToggleSpell
void ToggleSpell(int slot)
Definition: control.cpp:467
PAL16_ORANGE
#define PAL16_ORANGE
Definition: defs.h:101
SetSpellTrans
void SetSpellTrans(char t)
Definition: control.cpp:230
PlayerStruct::_pIMinDam
int _pIMinDam
Definition: structs.h:319
spselflag
BOOL spselflag
Definition: control.cpp:62
tempstr
char tempstr[256]
Definition: control.cpp:41
invflag
DEVILUTION_BEGIN_NAMESPACE BOOL invflag
Definition: inv.cpp:10
CheckChrBtns
void CheckChrBtns()
Definition: control.cpp:1590
PAL8_YELLOW
#define PAL8_YELLOW
Definition: defs.h:96
IMISC_SCROLLT
@ IMISC_SCROLLT
Definition: enums.h:2453
pTalkBtns
BYTE * pTalkBtns
Definition: control.cpp:30
pPanelText
BYTE * pPanelText
Definition: control.cpp:27
sgszTalkSave
char sgszTalkSave[8][80]
Definition: control.cpp:22
DiabloAllocPtr
BYTE * DiabloAllocPtr(DWORD dwBytes)
Multithreaded safe malloc.
Definition: engine.cpp:765
PlayerStruct::InvBody
ItemStruct InvBody[NUM_INVLOC]
Definition: structs.h:313
PANBTN_SENDMSG
@ PANBTN_SENDMSG
Definition: enums.h:2317
PlayerStruct::_pStatPts
int _pStatPts
Definition: structs.h:253
PANBTN_SPELLBOOK
@ PANBTN_SPELLBOOK
Definition: enums.h:2316
DrawSpellCel
void DrawSpellCel(int xp, int yp, BYTE *Trans, int nCel, int w)
Draw spell cell onto the back buffer.
Definition: control.cpp:225
PAL16_RED
#define PAL16_RED
Definition: defs.h:102
control_set_button_down
void control_set_button_down(int btn_id)
Definition: control.cpp:939
initialDropGoldValue
int initialDropGoldValue
Definition: control.cpp:58
CMD_ADDDEX
@ CMD_ADDDEX
Definition: enums.h:2176
INVITEM_INV_LAST
@ INVITEM_INV_LAST
Definition: enums.h:2808
control_update_life_mana
void control_update_life_mana()
Definition: control.cpp:699
MAXCHARLEVEL
#define MAXCHARLEVEL
Definition: defs.h:42
SPL_RECHARGE
@ SPL_RECHARGE
Definition: enums.h:2157
chrflag
BOOL chrflag
Definition: control.cpp:49
CheckInvHLight
char CheckInvHLight()
Definition: inv.cpp:1918
pcursitem
char pcursitem
Definition: cursor.cpp:21
myplr
int myplr
Definition: player.cpp:9
SPL_APOCA
@ SPL_APOCA
Definition: enums.h:2154
PAL16_BEIGE
#define PAL16_BEIGE
Definition: defs.h:98
SPL_NOVA
@ SPL_NOVA
Definition: enums.h:2148
DrawSpellBook
void DrawSpellBook()
Definition: control.cpp:1774
DrawInfoBox
void DrawInfoBox()
Sets a string to be drawn in the info box and then draws it.
Definition: control.cpp:1190
ITYPE_SWORD
@ ITYPE_SWORD
Definition: enums.h:2481
SetSpeedSpell
void SetSpeedSpell(int slot)
Definition: control.cpp:453
PC_WARRIOR
@ PC_WARRIOR
Definition: enums.h:2706
drawmanaflag
BOOL drawmanaflag
Definition: control.cpp:24
MAX_SEND_STR_LEN
#define MAX_SEND_STR_LEN
Definition: defs.h:21
BUFFER_WIDTH
#define BUFFER_WIDTH
Definition: defs.h:128
INVITEM_BELT_FIRST
@ INVITEM_BELT_FIRST
Definition: enums.h:2809
PlayerStruct::_pScrlSpells
uint64_t _pScrlSpells
Definition: structs.h:228
PANBTN_QLOG
@ PANBTN_QLOG
Definition: enums.h:2312
PC_ROGUE
@ PC_ROGUE
Definition: enums.h:2707
pcurs
int pcurs
Definition: cursor.cpp:27
InitDiabloMsg
void InitDiabloMsg(char e)
Definition: error.cpp:63
DEVILUTION_BEGIN_NAMESPACE
Definition: sha.cpp:10
ITYPE_AXE
@ ITYPE_AXE
Definition: enums.h:2482
PANEL_TOP
#define PANEL_TOP
Definition: defs.h:134
CPrintString
void CPrintString(int y, char *str, BOOL center, int lines)
Definition: control.cpp:1273
SPL_GUARDIAN
@ SPL_GUARDIAN
Definition: enums.h:2143
SPL_FLASH
@ SPL_FLASH
Definition: enums.h:2134
PANBTN_INVENTORY
@ PANBTN_INVENTORY
Definition: enums.h:2315
panelstr
char panelstr[4][64]
Definition: control.cpp:55
SPL_TELEPORT
@ SPL_TELEPORT
Definition: enums.h:2153
CheckLvlBtn
void CheckLvlBtn()
Definition: control.cpp:1566
dropGoldFlag
BOOL dropGoldFlag
Definition: control.cpp:15
SCREEN_X
#define SCREEN_X
Definition: defs.h:125
infoclr
char infoclr
Definition: control.cpp:37
PANEL_LEFT
#define PANEL_LEFT
Definition: defs.h:135
panelflag
BOOL panelflag
Definition: control.cpp:56
DrawGoldSplit
void DrawGoldSplit(int amount)
Definition: control.cpp:1901
PlayerStruct::_pManaPer
int _pManaPer
Definition: structs.h:265
SPL_INVALID
@ SPL_INVALID
Definition: enums.h:2167
PrintChar
void PrintChar(int sx, int sy, int nCel, char col)
Print letter to the back buffer.
Definition: control.cpp:504
MY_PlrStringXY
void MY_PlrStringXY(int x, int y, int endX, char *pszStr, char col, int base)
Render text string to back buffer.
Definition: control.cpp:1535
ITYPE_MACE
@ ITYPE_MACE
Definition: enums.h:2484
pPanelButtons
BYTE * pPanelButtons
Definition: control.cpp:19
fontframe
const BYTE fontframe[128]
Maps from font index to smaltext.cel frame number.
Definition: control.cpp:65
PAL16_BLUE
#define PAL16_BLUE
Definition: defs.h:99
PlayerStruct::_pHPPer
int _pHPPer
Definition: structs.h:260
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
drawhpflag
BOOL drawhpflag
Definition: control.cpp:14
PANEL_HEIGHT
#define PANEL_HEIGHT
Definition: defs.h:133
talkbtndown
BOOL talkbtndown[3]
Definition: control.cpp:34
SPL_WAVE
@ SPL_WAVE
Definition: enums.h:2145
IMISC_SCROLL
@ IMISC_SCROLL
Definition: enums.h:2452
ICLASS_WEAPON
@ ICLASS_WEAPON
Definition: enums.h:2738
control_set_gold_curs
void control_set_gold_curs(int pnum)
Definition: control.cpp:1990
qtextflag
BOOLEAN qtextflag
Definition: minitext.cpp:13
RedBack
void RedBack()
Definition: control.cpp:1715
ATTRIB_MAG
@ ATTRIB_MAG
Definition: enums.h:2323
PanBtnHotKey
char * PanBtnHotKey[8]
Maps from panel_button_id to hotkey name.
Definition: control.cpp:183
leveltype
BYTE leveltype
Definition: gendung.cpp:39
PlayerStruct::_pRSplType
char _pRSplType
Definition: structs.h:222
MaxStats
int MaxStats[3][4]
Definition: player.cpp:60
plr
PlayerStruct plr[MAX_PLRS]
Definition: player.cpp:10
RemoveSpdBarItem
void RemoveSpdBarItem(int pnum, int iv)
Definition: inv.cpp:1321
PlayerStruct
Definition: structs.h:178
lvlbtndown
BOOL lvlbtndown
Definition: control.cpp:21
BORDER_LEFT
#define BORDER_LEFT
Definition: defs.h:120
BORDER_TOP
#define BORDER_TOP
Definition: defs.h:121
MAX_SPELLS
#define MAX_SPELLS
Definition: defs.h:22
PC_SORCERER
@ PC_SORCERER
Definition: enums.h:2708
control_reset_talk
void control_reset_talk()
Definition: control.cpp:2162
MouseX
int MouseX
Definition: diablo.cpp:18
stextflag
char stextflag
Definition: stores.cpp:39
SetSpell
void SetSpell()
Definition: control.cpp:442
PrintGameStr
void PrintGameStr(int x, int y, const char *str, int color)
Definition: control.cpp:1306
PlayerStruct::_pSplTHotKey
char _pSplTHotKey[4]
Definition: structs.h:231
CelDrawLight
void CelDrawLight(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, BYTE *tbl)
Blit CEL sprite, and apply lighting, to the back buffer at the given coordinates.
Definition: engine.cpp:104