/*-----------------------------------------------------------------------** ** Diablo ** ** Control panel file ** ** (C)1995 Condor, Inc. All rights reserved. ** **-----------------------------------------------------------------------** ** $Header: /Diablo/CONTROL.CPP 2 2/05/97 10:41a Dbrevik2 $ **-----------------------------------------------------------------------** ** ** File Routines **-----------------------------------------------------------------------*/ #include "diablo.h" #pragma hdrstop #include "sound.h" #include "engine.h" #include "control.h" #include "gendung.h" #include "scrollrt.h" #include "msg.h" #include "items.h" #include "itemdat.h" #include "player.h" #include "monster.h" #include "objects.h" #include "cursor.h" #include "spells.h" #include "missiles.h" #include "town.h" #include "towners.h" #include "trigs.h" #include "gamemenu.h" #include "inv.h" #include "minitext.h" #include "lighting.h" #include "stores.h" #include "automap.h" #include "quests.h" #include "multi.h" #include "error.h" #include "spelldat.h" /*-----------------------------------------------------------------------** ** Registration info **-----------------------------------------------------------------------*/ #include "regconst.h" char sgszRegSig5[REG_LEN] = "REGISTRATION_BLOCK"; /*-----------------------------------------------------------------------** ** Local defines **-----------------------------------------------------------------------*/ #define MANABUFFSIZE 7744 // 88x88 #define LIFEBUFFSIZE 7744 #define STRN_GOLD 0 #define STRN_BLUE 1 #define STRN_RED 2 #define STRN_ORANGE 3 #define STRN_GREY 4 /*-----------------------------------------------------------------------** ** Global variables **-----------------------------------------------------------------------*/ BYTE *pBtmBuff; // Offscreen control panel buffer BYTE *pStatusPanel; BYTE *pPanelButtons; BYTE *pPanelText; BYTE *pManaBuff; BYTE *pLifeBuff; BYTE *pChrPanel; BYTE *pChrButtons; BYTE *pSpellCels; BYTE *pGBoxBuff; char panelstr[4][64]; int pstrjust[4]; BOOL pinfoflag; int pnumlines; char infostr[256]; char infoclr; char tempstr[256]; int pentaspin; int dropGoldValue; int initialDropGoldValue; int initialDropGoldIndex; const BYTE fonttrans[128] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 0, 54, 44, 57, 58, 56, 55, 47, 40, 41, 59, 39, 50, 37, 51, 52, // 32-47 36, 27, 28, 29, 30, 31, 32, 33, 34, 35, 48, 49, 60, 38, 61, 53, // 48-63 62, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 64-79 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 42, 63, 43, 64, 65, // 80-95 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 96-111 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 40, 66, 41, 67, 0 }; // 112-127 const BYTE fontkern[68] = { 8, // Space/Invalid 10, 7, 9, 8, 7, 6, 8, 8, 3, 3, 8, 6, 11, 9, 10, 6, // a-p 9, 9, 6, 9, 11, 10, 13, 10, 11, 7, // q-z 5, 7, 7, 8, 7, 7, 7, 7, 7, 10, // 1-0 4, 5, 6, 3, 3, 4, 3, 6, 6, 3, 3, 3, 3, 3, 2, 7, 6, 3, 10, 10, 6, // misc 6, 7, 4, 4, 9, 6, 6, 12, 3, 7 }; // misc static const long fontofs[5][5] = { { 456433, 24576, 24576, 24576, 24756 }, { 447217, 465649, 24576, 24576, 24576 }, { 442609, 456433, 470257, 24576, 24576 }, { 439537, 451057, 461809, 473329, 24576 }, { 438001, 447217, 456433, 465649, 474097 } }; BOOL drawhpflag; BOOL drawmanaflag; BOOL chrflag; /*-----------------------------------------------------------------------*/ BOOL spselflag = FALSE; int pSpell, pSplType; byte SpellTrans[256]; static char SpellITbl[MAXSPELLS] = { 1, // Invalid 1, // SPL_FIREBOLT 2, // SPL_HEAL 3, // SPL_LIGHTNING 4, // SPL_FLASH 5, // SPL_IDENTIFY 6, // SPL_WALL 7, // SPL_TOWN 8, // SPL_STONE 9, // SPL_INFRA 28, // SPL_PHASE 13, // SPL_MANASHLD 12, // SPL_FIREBALL 18, // SPL_GUARDIAN 16, // SPL_CHAIN 14, // SPL_WAVE 18, // SPL_DOOM 19, // SPL_BLOODR 11, // SPL_NOVA 20, // SPL_INVIS 15, // SPL_FLAME 21, // SPL_GOLEM 23, // SPL_BLOODB 24, // SPL_TELE 25, // SPL_APOCA 22, // SPL_ETHER 26, // SPL_REPAIR 29, // SPL_RECHARGE 37, // SPL_DISARM 38, // SPL_ELEMENT 39, // SPL_CBOLT 42, // SPL_HBOLT 41, // SPL_RESURRECT 40, // SPL_TELEKINESIS 10, // SPL_HEALOTHER 36, // SPL_BSTAR 30, // SPL_BONESPIRT 26, // SPL_MANA 29, // SPL_FMANA 37, // SPL_RANDOM 6, // SPL_LTWALL 11, // SPL_IMMOLATION 28, // SPL_TELESTAIRS 26, // SPL_REFLECT 4, // SPL_BERSERK 6, // SPL_RINGOFFIRE 6, // SPL_RINGOFLIGHT 5, // SPL_SHOWMAGITEMS }; /*-----------------------------------------------------------------------*/ #define NUMPBTNS 8 #define SINGLE_PBTNS 6 #define MULTI_PBTNS NUMPBTNS #define PBTN_CHR 0 #define PBTN_TPLR1 0 #define PBTN_QUEST 1 #define PBTN_AMAP 2 #define PBTN_TPLR2 2 #define PBTN_MENU 3 #define PBTN_INV 4 #define PBTN_TPLR3 4 #define PBTN_SBOOK 5 #define PBTN_TALK 6 #define PBTN_ATTACK 7 // x1, y1, width, height, talk pushable int PanBtnPos[NUMPBTNS][5] = { { 9, 361, 71, 19, TRUE }, { 9, 387, 71, 19, FALSE }, { 9, 427, 71, 19, TRUE }, { 9, 453, 71, 19, FALSE }, { 560, 361, 71, 19, TRUE }, { 560, 387, 71, 19, FALSE }, { 87, 443, 33, 32, TRUE }, { 527, 443, 33, 32, TRUE }, }; char *PanBtnHotKey[NUMPBTNS] = { "'c'", "'q'", "Tab", "Esc", "'i'", "'b'", "Enter", NULL }; char *PanBtnStr[NUMPBTNS] = { "Character Information", "Quests log", "Automap", "Main Menu", "Inventory", "Spell book", "Send Message", "Player Attack" }; BOOL panbtn[NUMPBTNS]; BOOL drawbtnflag, panbtndown; BOOL panelflag; // panel info draw int numpanbtns; BYTE *pDurIcons; BOOL drawdurflag; BOOL dropGoldFlag; /*-----------------------------------------------------------------------*/ #define NUMCBTNS 4 #define CBTN_STR 0 #define CBTN_MAG 1 #define CBTN_DEX 2 #define CBTN_VIT 3 // x1, y1, width, height int ChrBtnPos[NUMCBTNS][4] = { { 137, 138, 41, 22 }, { 137, 166, 41, 22 }, { 137, 195, 41, 22 }, { 137, 223, 41, 22 } }; BOOL chrbtn[NUMCBTNS]; BOOL chrbtndown; /*-----------------------------------------------------------------------*/ BOOL lvlbtndown; /*-----------------------------------------------------------------------*/ BYTE *pSpellBkCel; BYTE *pSBkBtnCel; BYTE *pSBkIconCels; int sbooktab; BOOL sbookflag; // The first entry will be filled during init with the player types skill int SpellPages[6][7] = { { 0, SPL_FIREBOLT, SPL_CBOLT, SPL_HBOLT, SPL_HEAL, SPL_HEALOTHER, SPL_FLAME }, { SPL_RESURRECT, SPL_WALL, SPL_TELEKINESIS, SPL_LIGHTNING, SPL_TOWN, SPL_FLASH, SPL_STONE }, { SPL_PHASE, SPL_MANASHLD, SPL_ELEMENT, SPL_FIREBALL, SPL_WAVE, SPL_CHAIN, SPL_GUARDIAN}, { SPL_NOVA, SPL_GOLEM, SPL_TELE, SPL_APOCA, SPL_BONESPIRIT, SPL_BSTAR, SPL_ETHER }, { SPL_LTWALL, SPL_IMMOLATION, SPL_TELESTAIRS, SPL_REFLECT, SPL_BERSERK, SPL_RINGOFFIRE, SPL_SHOWMAGITEMS }, { -1, -1, -1, -1, -1, -1, -1 } }; /*-----------------------------------------------------------------------*/ #define MAX_TALK_SAVES 8 // must be pow2 BOOL talkflag; static int tspin; static long talkofs; static char sgszTalkMsg[MAX_SEND_STR_LEN]; static BYTE sgbTalkSavePos; static BYTE sgbNextTalkSave; static char sgszTalkSaveMsg[MAX_TALK_SAVES][MAX_SEND_STR_LEN]; static BYTE sgbPlrTalkTbl[MAX_PLRS]; static BYTE *pTalkPanel; static BYTE *pMultiBtns; static BYTE *pTalkBtns; static BOOL talkbtndown[3]; void TalkStart(); void TalkEnd(); void PlrStringXY(int x1, int y, int x2,const char * pszStr,char col); /*-----------------------------------------------------------------------** ** Prototypes **-----------------------------------------------------------------------*/ void SetPlrHandItem(ItemStruct *h, int idata); void GetPlrHandSeed(ItemStruct *h); void GetGoldSeed(int pnum, ItemStruct *h); void SetSpellTrans(char); /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void DrawSpellCel(long xp, long yp, BYTE *pCels, long nCel, long w) { BYTE *pTo; byte *ttbl; long RLELen; ttbl = &SpellTrans[0]; app_assert(gpBuffer); pTo = gpBuffer + nBuffWTbl[yp] + xp; __asm { mov ebx,dword ptr [pCels] mov eax,dword ptr [nCel] shl eax,2 add ebx,eax mov eax,dword ptr [ebx+4] sub eax,dword ptr [ebx] mov dword ptr [RLELen],eax mov esi,dword ptr [pCels] // Source add esi,dword ptr [ebx] mov edi,dword ptr [pTo] // Dest mov eax,dword ptr [RLELen] add eax,esi mov dword ptr [RLELen],eax mov ebx,dword ptr [ttbl] _T1Lp1: mov edx,dword ptr [w] _T1Lp2: xor eax,eax // Load control byte lodsb or al,al js _T1J sub edx,eax mov ecx,eax shr ecx,1 jnc _T1w lodsb xlatb stosb jecxz _T1x _T1w: shr ecx,1 jnc _T1Lp3 lodsw xlatb ror ax,8 xlatb ror ax,8 stosw jecxz _T1x _T1Lp3: lodsd xlatb ror eax,8 xlatb ror eax,8 xlatb ror eax,8 xlatb ror eax,8 stosd loop _T1Lp3 _T1x: or edx,edx jz _T1Nxt jmp _T1Lp2 _T1J: neg al // Do jump add edi,eax sub edx,eax jnz _T1Lp2 _T1Nxt: sub edi,768 sub edi,dword ptr [w] cmp esi,dword ptr [RLELen] jnz _T1Lp1 } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void SetSpellTrans(char t) { int i; if (t == STRN_GOLD) { for (i = 0; i < 128; i++) SpellTrans[i] = i; } for (i = 128; i < 256; i++) SpellTrans[i] = i; SpellTrans[255] = 0; switch (t) { case STRN_BLUE : SpellTrans[144] = 177; SpellTrans[145] = 179; SpellTrans[146] = 181; for (i = 176; i < 192; i++) { SpellTrans[i - 16] = i; // 160-175 SpellTrans[i + 16] = i; // 192-207 SpellTrans[i + 32] = i; // 208-223 } break; case STRN_ORANGE : SpellTrans[144] = 209; SpellTrans[145] = 211; SpellTrans[146] = 213; for (i = 208; i < 224; i++) { SpellTrans[i - 48] = i; // 160-175 SpellTrans[i - 16] = i; // 192-207 } break; case STRN_RED : SpellTrans[144] = 161; SpellTrans[145] = 163; SpellTrans[146] = 165; for (i = 160; i < 176; i++) { SpellTrans[i + 32] = i; // 192-207 SpellTrans[i + 48] = i; // 208-223 } break; case STRN_GREY : SpellTrans[144] = 241; SpellTrans[145] = 243; SpellTrans[146] = 245; for (i = 240; i < 255; i++) { SpellTrans[i - 80] = i; // 160-174 SpellTrans[i - 48] = i; // 192-206 SpellTrans[i - 32] = i; // 208-222 } SpellTrans[175] = 0; SpellTrans[207] = 0; SpellTrans[223] = 0; break; } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void DrawSpellIcon() { char t, sn; int sl; t = plr[myplr]._pRSplType; sn = plr[myplr]._pRSpell; sl = plr[myplr]._pSplLvl[sn] + plr[myplr]._pISplLvlAdd; if ((t == SPT_MEMORIZED) && (sn != -1)) { if (!CheckSpell(myplr, sn, t, TRUE)) t = STRN_GREY; if (sl <= 0 ) t = STRN_GREY; } if ((currlevel == 0) && (t != STRN_GREY) && (spelldata[sn].sTownSpell == FALSE)) t = STRN_GREY; if (plr[myplr]._pRSpell < 0) t = STRN_GREY; SetSpellTrans(t); if (sn != -1) DrawSpellCel(629, 631, pSpellCels, SpellITbl[sn], 56); else DrawSpellCel(629, 631, pSpellCels, 27, 56); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ #define SPLICONSIZE 56 #define SPLICONRIGHT 636 // (640 - (trunc(640 / 56) * 56)) / 2) + 640 + 64 - SPLICONSIZE #define SPLICONLEFT 20 // SPLICONRIGHT - (trunc(640 / 56) * 56) - SPLICONSIZE void DrawSpellList() { int mx,my,x,y,i,j,t; __int64 mask,spl; int s,c,hk; int v, selbox; x = SPLICONRIGHT; y = 495; pSpell = -1; infostr[0] = 0; ClearPanel(); for (j = 0; j < 4; j++) { switch(j) { case 0: SetSpellTrans(STRN_GOLD); spl = plr[myplr]._pAblSpells; selbox = 46; break; case 1: spl = plr[myplr]._pMemSpells; selbox = 47; break; case 2: SetSpellTrans(STRN_RED); spl = plr[myplr]._pScrlSpells; selbox = 44; break; case 3: SetSpellTrans(STRN_ORANGE); spl = plr[myplr]._pISpells; selbox = 45; break; } mask = 1; for (i = 1; i < SPL_LAST; i++) { if ((spl & mask) != 0) { if (j == 1) { v = plr[myplr]._pSplLvl[i] + plr[myplr]._pISplLvlAdd; if ( v < 0 ) v = 0; if (v > 0) t = STRN_BLUE; else t = STRN_GREY; SetSpellTrans(t); } if ((currlevel == 0) && (spelldata[i].sTownSpell == FALSE)) SetSpellTrans(STRN_GREY); DrawSpellCel(x, y, pSpellCels, SpellITbl[i], SPLICONSIZE); mx = x - 64; my = y - (160 + SPLICONSIZE); if ((MouseX >= mx) && (MouseX < (mx+SPLICONSIZE)) && (MouseY >= my) && (MouseY < (my+SPLICONSIZE))) { pSpell = i; pSplType = j; DrawSpellCel(x, y, pSpellCels, selbox, SPLICONSIZE); switch (j) { case 0: sprintf(infostr, "%s Skill", spelldata[pSpell].sSkillText); break; case 1: sprintf(infostr, "%s Spell", spelldata[pSpell].sNameText); if (pSpell == SPL_HBOLT) { sprintf(tempstr, "Damages undead only"); AddPanelString(tempstr, TEXT_CENTER); } if (v == 0) sprintf(tempstr, "Spell Level 0 - Unusable"); else sprintf(tempstr, "Spell Level %i", v); AddPanelString(tempstr, TEXT_CENTER); break; case 2: sprintf(infostr, "Scroll of %s", spelldata[pSpell].sNameText); c = 0; for (s = 0; s < plr[myplr]._pNumInv; s++) { if ((plr[myplr].InvList[s]._itype != -1) && ((plr[myplr].InvList[s]._iMiscId == IMID_SCROLL) || (plr[myplr].InvList[s]._iMiscId == IMID_TSCROLL))) { if (plr[myplr].InvList[s]._iSpell == pSpell) c++; } } for (s = 0; s < MAXSPD; s++) { if ((plr[myplr].SpdList[s]._itype != -1) && ((plr[myplr].SpdList[s]._iMiscId == IMID_SCROLL) || (plr[myplr].SpdList[s]._iMiscId == IMID_TSCROLL))) { if (plr[myplr].SpdList[s]._iSpell == pSpell) c++; } } if (c == 1) strcpy(tempstr, "1 Scroll"); else sprintf(tempstr, "%i Scrolls", c); AddPanelString(tempstr, TEXT_CENTER); break; case 3: sprintf(infostr, "Staff of %s", spelldata[pSpell].sNameText); if (plr[myplr].Hand1Item._iCharges == 1) strcpy(tempstr, "1 Charge"); else sprintf(tempstr, "%i Charges", plr[myplr].Hand1Item._iCharges); AddPanelString(tempstr, TEXT_CENTER); break; } for (hk = 0; hk < 4; hk++) { if ((plr[myplr]._pSplHotKey[hk] == pSpell) && (plr[myplr]._pSplTHotKey[hk] == pSplType)) { DrawSpellCel(x, y, pSpellCels, 48+hk, SPLICONSIZE); sprintf(tempstr, "Spell Hot Key #F%i", hk+5); AddPanelString(tempstr, TEXT_CENTER); } } } x -= SPLICONSIZE; if (x == SPLICONLEFT) { x = SPLICONRIGHT; y -= SPLICONSIZE; } } mask = mask << 1; } if (spl && (x != SPLICONRIGHT)) x -= SPLICONSIZE; if (x == SPLICONLEFT) { x = SPLICONRIGHT; y -= SPLICONSIZE; } } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void SetSpell() { spselflag = FALSE; if (pSpell != -1) { ClearPanel(); plr[myplr]._pRSpell = pSpell; plr[myplr]._pRSplType = pSplType; force_redraw = FULLDRAW; } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void SetSpellHK(int hk) { if (pSpell != -1) { for (int i = 0; i < 4; i++) { if ((plr[myplr]._pSplHotKey[i] == pSpell) && (plr[myplr]._pSplTHotKey[i] == pSplType)) plr[myplr]._pSplHotKey[i] = -1; } plr[myplr]._pSplHotKey[hk] = pSpell; plr[myplr]._pSplTHotKey[hk] = pSplType; } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void GetSpellHK(int hk) { __int64 spl; if (plr[myplr]._pSplHotKey[hk] == -1) return; switch(plr[myplr]._pSplTHotKey[hk]) { case 0: spl = plr[myplr]._pAblSpells; break; case 1: spl = plr[myplr]._pMemSpells; break; case 2: spl = plr[myplr]._pScrlSpells; break; case 3: spl = plr[myplr]._pISpells; break; } spl &= (((__int64)1) << (plr[myplr]._pSplHotKey[hk]-1)); if (spl) { plr[myplr]._pRSpell = plr[myplr]._pSplHotKey[hk]; plr[myplr]._pRSplType = plr[myplr]._pSplTHotKey[hk]; force_redraw = FULLDRAW; } } /*-----------------------------------------------------------------------** ** Draws a small font letter **-----------------------------------------------------------------------*/ void DrawPanelFont (long poffset, long nCel, char clr) { app_assert(gpBuffer); __asm { mov ebx,dword ptr [pPanelText] mov eax,dword ptr [nCel] shl eax,2 add ebx,eax mov edx,dword ptr [ebx+4] // Length sub edx,dword ptr [ebx] mov esi,dword ptr [pPanelText] // Source add esi,dword ptr [ebx] mov edi,dword ptr [gpBuffer] // Dest add edi,dword ptr [poffset] mov ebx,edx add ebx,esi xor edx,edx mov dl,byte ptr [clr] cmp edx,ICOLOR_WHITE jz _T1Lp1 // Normal / White cmp edx,ICOLOR_BLUE jz _T2Lp1 // Blue cmp edx,ICOLOR_RED jz _T3Lp1 // Red jmp _T4Lp1 // Gold /*- White ---------------------------------------------------------------*/ _T1Lp1: mov edx,13 _T1Lp2: xor eax,eax // Load control byte lodsb or al,al js _T1J sub edx,eax // Draw mov ecx,eax shr ecx,1 jnc _T1w movsb jecxz _T1x _T1w: shr ecx,1 jnc _T1Lp3 movsw jecxz _T1x _T1Lp3: rep movsd _T1x: or edx,edx jz _T1Nxt jmp _T1Lp2 _T1J: neg al // Do jump add edi,eax sub edx,eax jnz _T1Lp2 _T1Nxt: sub edi,781 cmp ebx,esi jnz _T1Lp1 jmp _Done /*- Blue ----------------------------------------------------------------*/ _T2Lp1: mov edx,13 _T2Lp2: xor eax,eax // Load control byte lodsb or al,al js _T2J sub edx,eax // Draw mov ecx,eax _T2Lp3: lodsb cmp al,253 ja _T2F cmp al,240 jb _T2Sv sub al,62 jmp _T2Sv _T2F: mov al,191 _T2Sv: stosb loop _T2Lp3 or edx,edx jz _T2Nxt jmp _T2Lp2 _T2J: neg al // Do jump add edi,eax sub edx,eax jnz _T2Lp2 _T2Nxt: sub edi,781 cmp ebx,esi jnz _T2Lp1 jmp _Done /*- Red -----------------------------------------------------------------*/ _T3Lp1: mov edx,13 _T3Lp2: xor eax,eax // Load control byte lodsb or al,al js _T3J sub edx,eax // Draw mov ecx,eax _T3Lp3: lodsb cmp al,240 jb _T3Sv sub al,16 _T3Sv: stosb loop _T3Lp3 or edx,edx jz _T3Nxt jmp _T3Lp2 _T3J: neg al // Do jump add edi,eax sub edx,eax jnz _T3Lp2 _T3Nxt: sub edi,781 cmp ebx,esi jnz _T3Lp1 jmp _Done /*- Gold ----------------------------------------------------------------*/ _T4Lp1: mov edx,13 _T4Lp2: xor eax,eax // Load control byte lodsb or al,al js _T4J sub edx,eax // Draw mov ecx,eax _T4Lp3: lodsb cmp al,240 jb _T4Sv cmp al,254 jae _T4val sub al,46 jmp _T4Sv _T4val: mov al,207 _T4Sv: stosb loop _T4Lp3 or edx,edx jz _T4Nxt jmp _T4Lp2 _T4J: neg al // Do jump add edi,eax sub edx,eax jnz _T4Lp2 _T4Nxt: sub edi,781 cmp ebx,esi jnz _T4Lp1 /*-----------------------------------------------------------------------*/ _Done: } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void AddPanelString(const char * str, int just) { strcpy(panelstr[pnumlines],str); pstrjust[pnumlines] = just; if (pnumlines < 4) pnumlines++; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void ClearPanel() { pnumlines = 0; pinfoflag = FALSE; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void CopyCtrlPan(int sx, int sy, int deltax, int deltay, int dx, int dy) { long src, dest; app_assert(gpBuffer); src = (sy * 640) + sx; dest = (dy * 768) + dx; __asm { mov esi,dword ptr [pBtmBuff] add esi,dword ptr [src] mov edi,dword ptr [gpBuffer] add edi,dword ptr [dest] xor ebx,ebx mov bx,word ptr [deltax] xor edx,edx mov dx,word ptr [deltay] _CLp: mov ecx,ebx shr ecx,1 jnc _Tw movsb jecxz _Tx _Tw: shr ecx,1 jnc _TLp movsw jecxz _Tx _TLp: rep movsd _Tx: add esi,640 sub esi,ebx add edi,768 sub edi,ebx dec edx jnz _CLp } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void InitPanelStr() { ClearPanel(); //AddPanelString("Welcome to Diablo", TEXT_CENTER); // This was ok (pre Demo) now its not //AddPanelString("Press F1 for help", TEXT_CENTER); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void BuffCopy(BYTE *pSrc, int y1, int y2, int dx, int dy) { long srco, desto, deltay; app_assert(gpBuffer); srco = y1 * 88; desto = (dy * 768) + dx; deltay = y2 - y1; __asm { mov esi,dword ptr [pSrc] add esi,dword ptr [srco] mov edi,dword ptr [gpBuffer] add edi,dword ptr [desto] mov edx,dword ptr [deltay] _YLp: mov ecx,22 rep movsd add edi,680 dec edx jnz _YLp } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void TransBuffCopy(BYTE *pSrc, long srcwidth, long srcoff, BYTE *pDest, long destoff, long dy) { __asm { mov esi,dword ptr [pSrc] add esi,dword ptr [srcoff] mov edi,dword ptr [pDest] add edi,dword ptr [destoff] mov edx,dword ptr [dy] _YLp: mov ecx,59 _XLp: lodsb or al,al jz _Skip mov byte ptr [edi],al _Skip: inc edi loop _XLp add esi,dword ptr [srcwidth] sub esi,59 add edi,709 dec edx jnz _YLp } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void DrawHealthTop() { double v; int dv; if (plr[myplr]._pMaxHP <= 0) v = 0.0; else v = ((double)plr[myplr]._pHitPoints / (double)plr[myplr]._pMaxHP) * 80; dv = (int)v; plr[myplr]._pHPPer = dv; long dy; dy = 80 - plr[myplr]._pHPPer; if (dy > 11) dy = 11; dy += 2; app_assert(gpBuffer); TransBuffCopy(pLifeBuff, 88, 277, gpBuffer, 383405, dy); if (dy != 13) TransBuffCopy(pBtmBuff, 640, (dy * 640) + 2029, gpBuffer, (dy * 768) + 383405, 13 - dy); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void DrawHealthBar() { double v; int dv; if (plr[myplr]._pMaxHP <= 0) v = 0.0; else v = ((double)plr[myplr]._pHitPoints / (double)plr[myplr]._pMaxHP) * 80; dv = (int)v; plr[myplr]._pHPPer = dv; if (dv > 69) dv = 69; if (dv != 69) BuffCopy(pLifeBuff, 16, 85-dv, 160, 512); if (dv != 0) CopyCtrlPan(96, 85-dv, 88, dv, 160, 581-dv); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void DrawManaTop() { long dy; dy = 80 - plr[myplr]._pManaPer; if (dy > 11) dy = 11; dy += 2; app_assert(gpBuffer); TransBuffCopy(pManaBuff, 88, 277, gpBuffer, 383771, dy); if (dy != 13) TransBuffCopy(pBtmBuff, 640, (dy * 640) + 2395, gpBuffer, (dy * 768) + 383771, 13 - dy); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void CalcInitBallPer() { double v; int dv; long m,mm; mm = plr[myplr]._pMaxMana; m = plr[myplr]._pMana; if (mm < 0) mm = 0; if (m < 0) m = 0; if (mm == 0) dv = 0; else { v = ((double)m / (double)mm) * 80; dv = (int)v; } plr[myplr]._pManaPer = dv; v = ((double)plr[myplr]._pHitPoints / (double)plr[myplr]._pMaxHP) * 80; dv = (int)v; plr[myplr]._pHPPer = dv; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void DrawManaBar() { double v; int dv; long m,mm; mm = plr[myplr]._pMaxMana; m = plr[myplr]._pMana; if (mm < 0) mm = 0; if (m < 0) m = 0; if (mm == 0) dv = 0; else { v = ((double)m / (double)mm) * 80; dv = (int)v; } plr[myplr]._pManaPer = dv; if (dv > 69) dv = 69; if (dv != 69) BuffCopy(pManaBuff, 16, 85-dv, 528, 512); if (dv != 0) CopyCtrlPan(464, 85-dv, 88, dv, 528, 581-dv); DrawSpellIcon(); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void InitControlPan() { int i; app_assert(! pBtmBuff); if (gbMaxPlayers == 1) { pBtmBuff = DiabloAllocPtrSig(BTMBUFFSIZE,'CTRL'); ZeroMemory(pBtmBuff,BTMBUFFSIZE); } else { pBtmBuff = DiabloAllocPtrSig(BTMBUFFMULTISIZE,'CTRL'); ZeroMemory(pBtmBuff,BTMBUFFMULTISIZE); } pManaBuff = DiabloAllocPtrSig(MANABUFFSIZE,'CTRL'); ZeroMemory(pManaBuff,MANABUFFSIZE); pLifeBuff = DiabloAllocPtrSig(LIFEBUFFSIZE,'CTRL'); ZeroMemory(pLifeBuff,LIFEBUFFSIZE); pPanelText = LoadFileInMemSig("CtrlPan\\SmalText.CEL",NULL,'CTRL'); pChrPanel = LoadFileInMemSig("Data\\Char.CEL",NULL,'CTRL'); pSpellCels = LoadFileInMemSig("CtrlPan\\SpelIcon.CEL",NULL,'CTRL'); SetSpellTrans(STRN_GOLD); // Init Control panel offscreen buffer pStatusPanel = LoadFileInMemSig("CtrlPan\\Panel8.CEL",NULL,'CTRL'); DrawBuffCel(pBtmBuff, 0, 143, BTMBUFFX, pStatusPanel, 1, 640); DiabloFreePtr (pStatusPanel); pStatusPanel = LoadFileInMemSig("CtrlPan\\P8Bulbs.CEL",NULL,'CTRL'); DrawBuffCel(pLifeBuff, 0, 87, 88, pStatusPanel, 1, 88); DrawBuffCel(pManaBuff, 0, 87, 88, pStatusPanel, 2, 88); DiabloFreePtr (pStatusPanel); talkflag = FALSE; if (gbMaxPlayers != 1) { pTalkPanel = LoadFileInMemSig("CtrlPan\\TalkPanl.CEL",NULL,'CTRL'); DrawBuffCel(pBtmBuff, 0, 287, BTMBUFFX, pTalkPanel, 1, 640); DiabloFreePtr (pTalkPanel); pMultiBtns = LoadFileInMemSig("CtrlPan\\P8But2.CEL",NULL,'CTRL'); pTalkBtns = LoadFileInMemSig("CtrlPan\\TalkButt.CEL",NULL,'CTRL'); talkofs = 0; sgszTalkMsg[0] = 0; for (i = 0; i < MAX_PLRS; i++) sgbPlrTalkTbl[i] = TRUE; for (i = 0; i < 3; i++) talkbtndown[i] = FALSE; } panelflag = FALSE; lvlbtndown = FALSE; pPanelButtons = LoadFileInMemSig("CtrlPan\\Panel8bu.CEL",NULL,'CTRL'); for (i = 0; i < NUMPBTNS; i++) panbtn[i] = FALSE; panbtndown = FALSE; if (gbMaxPlayers == 1) numpanbtns = SINGLE_PBTNS; else numpanbtns = MULTI_PBTNS; pChrButtons = LoadFileInMemSig("Data\\CharBut.CEL",NULL,'CTRL'); for (i = 0; i < NUMCBTNS; i++) chrbtn[i] = FALSE; chrbtndown = FALSE; pDurIcons = LoadFileInMemSig("Items\\DurIcons.CEL",NULL,'CTRL'); strcpy(infostr,""); InitPanelStr(); drawhpflag = TRUE; drawmanaflag = TRUE; chrflag = FALSE; spselflag = FALSE; pSpellBkCel = LoadFileInMemSig("Data\\SpellBk.CEL",NULL,'CTRL'); pSBkBtnCel = LoadFileInMemSig("Data\\SpellBkB.CEL",NULL,'CTRL'); pSBkIconCels = LoadFileInMemSig("Data\\SpellI2.CEL",NULL,'CTRL'); sbooktab = 0; sbookflag = FALSE; if (plr[myplr]._pClass == CLASS_WARRIOR) SpellPages[0][0] = SPL_REPAIR; #if !IS_VERSION(SHAREWARE) else if (plr[myplr]._pClass == CLASS_ROGUE) SpellPages[0][0] = SPL_DISARM; else if (plr[myplr]._pClass == CLASS_SORCEROR) SpellPages[0][0] = SPL_RECHARGE; else if (plr[myplr]._pClass == CLASS_MONK) SpellPages[0][0] = SPL_HEALOTHER; else if (plr[myplr]._pClass == CLASS_BARD) SpellPages[0][0] = SPL_IDENTIFY; #endif pQLogCel = LoadFileInMemSig("Data\\Quest.CEL",NULL,'CTRL'); pGBoxBuff = LoadFileInMemSig("CtrlPan\\Golddrop.cel",NULL,'CTRL'); // Initialize gold drop variables dropGoldFlag = FALSE; dropGoldValue = 0; initialDropGoldValue = 0; initialDropGoldIndex = 0; pentaspin = 1; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void DrawCtrlPan() { CopyCtrlPan(0, 16+talkofs, 640, 128, 64, 512); DrawInfoBox(); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void DrawButtons() { for (int i = 0; i < SINGLE_PBTNS; i++) { if (!panbtn[i]) CopyCtrlPan(PanBtnPos[i][0], PanBtnPos[i][1]-336, 71, 20, PanBtnPos[i][0] + 64, PanBtnPos[i][1] + 160); else DrawCel(PanBtnPos[i][0]+64, PanBtnPos[i][1]+178, pPanelButtons, i+1, 71); } if (numpanbtns == MULTI_PBTNS) { // Draw talk button DrawCel(151, 634, pMultiBtns, 1+panbtn[PBTN_TALK], 33); // Draw Friend or foe button if (FriendlyMode) { DrawCel(591, 634, pMultiBtns, 3+panbtn[PBTN_ATTACK], 33); } else { DrawCel(591, 634, pMultiBtns, 5+panbtn[PBTN_ATTACK], 33); } } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void SetupSpellSel() { int x,y,i,j; __int64 mask,spl; int cx, cy; spselflag = TRUE; x = SPLICONRIGHT; y = 495; cx = x - (64 - (SPLICONSIZE >> 1)); cy = y - (160 + (SPLICONSIZE >> 1)); if (plr[myplr]._pRSpell != -1) { for (j = 0; j < 4; j++) { switch(j) { case 0: spl = plr[myplr]._pAblSpells; break; case 1: spl = plr[myplr]._pMemSpells; break; case 2: spl = plr[myplr]._pScrlSpells; break; case 3: spl = plr[myplr]._pISpells; break; } mask = 1; for (i = 1; i < SPL_LAST; i++) { if ((spl & mask) != 0) { if ((i == plr[myplr]._pRSpell) && (j == plr[myplr]._pRSplType)) { cx = x - (64 - (SPLICONSIZE >> 1)); cy = y - (160 + (SPLICONSIZE >> 1)); } x -= SPLICONSIZE; if (x == SPLICONLEFT) { x = SPLICONRIGHT; y -= SPLICONSIZE; } } mask = mask << 1; } if (spl && (x != SPLICONRIGHT)) x -= SPLICONSIZE; if (x == SPLICONLEFT) { x = SPLICONRIGHT; y -= SPLICONSIZE; } } } SetCursorPos(cx,cy); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void CheckPanelBtns() { for (int i = 0; i < numpanbtns; i++) { int x2 = PanBtnPos[i][0] + PanBtnPos[i][2]; int y2 = PanBtnPos[i][1] + PanBtnPos[i][3]; if ((MouseX >= PanBtnPos[i][0]) && (MouseX <= x2) && (MouseY >= PanBtnPos[i][1]) && (MouseY <= y2)) { panbtn[i] = TRUE; drawbtnflag = TRUE; panbtndown = TRUE; } } if (!spselflag) { if (MouseX >= 565 && MouseX < 621 && MouseY >= 416 && MouseY < 472) { SetupSpellSel(); gamemenu_off(); } } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void ActivatePanelBtn(int i) { panbtn[i] = TRUE; drawbtnflag = TRUE; panbtndown = TRUE; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void CheckDeadButtons() { int x2, y2; x2 = PanBtnPos[PBTN_MENU][0] + PanBtnPos[PBTN_MENU][2]; y2 = PanBtnPos[PBTN_MENU][1] + PanBtnPos[PBTN_MENU][3]; if ((MouseX >= PanBtnPos[PBTN_MENU][0]) && (MouseX <= x2) && (MouseY >= PanBtnPos[PBTN_MENU][1]) && (MouseY <= y2)) ActivatePanelBtn(PBTN_MENU); x2 = PanBtnPos[PBTN_TALK][0] + PanBtnPos[PBTN_TALK][2]; y2 = PanBtnPos[PBTN_TALK][1] + PanBtnPos[PBTN_TALK][3]; if ((MouseX >= PanBtnPos[PBTN_TALK][0]) && (MouseX <= x2) && (MouseY >= PanBtnPos[PBTN_TALK][1]) && (MouseY <= y2)) ActivatePanelBtn(PBTN_TALK); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void DoAutoMap() { // if we are multiplayer on the town level, DO NOT display // the error message. Instead, the automap will show the // game name and password if (currlevel == 0 && gbMaxPlayers == 1) { InitDiabloMsg(MSG_AMAPTWN); return; } // toggle automap if (!automapflag) StartAutomap(); else automapflag = FALSE; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void CheckPanelInfo() { int i; int x2, y2; int pSpell, c, s; int v; panelflag = FALSE; ClearPanel(); for (i = 0; i < numpanbtns; i++) { x2 = PanBtnPos[i][0] + PanBtnPos[i][2]; y2 = PanBtnPos[i][1] + PanBtnPos[i][3]; if ((MouseX >= PanBtnPos[i][0]) && (MouseX <= x2) && (MouseY >= PanBtnPos[i][1]) && (MouseY <= y2)) { if (i != PBTN_ATTACK) strcpy(infostr, PanBtnStr[i]); else if (FriendlyMode) strcpy(infostr, "Player friendly"); else strcpy(infostr, "Player attack"); if (PanBtnHotKey[i] != NULL) { sprintf(tempstr, "Hotkey : %s", PanBtnHotKey[i]); AddPanelString(tempstr, TEXT_CENTER); } infoclr = ICOLOR_WHITE; panelflag = TRUE; pinfoflag = TRUE; } } if (!spselflag) { if ((MouseX >= 565) && (MouseX < 621) && (MouseY >= 416) && (MouseY < 472)) { strcpy(infostr, "Select current spell button"); infoclr = ICOLOR_WHITE; panelflag = TRUE; pinfoflag = TRUE; strcpy(tempstr, "Hotkey : 's'"); AddPanelString(tempstr, TEXT_CENTER); pSpell = plr[myplr]._pRSpell; if (pSpell != -1) { switch (plr[myplr]._pRSplType) { case 0: sprintf(tempstr, "%s Skill", spelldata[pSpell].sSkillText); AddPanelString(tempstr, TEXT_CENTER); break; case 1: sprintf(tempstr, "%s Spell", spelldata[pSpell].sNameText); AddPanelString(tempstr, TEXT_CENTER); v = plr[myplr]._pSplLvl[pSpell]+plr[myplr]._pISplLvlAdd; if ( v < 0 ) v = 0; if (v == 0) sprintf(tempstr, "Spell Level 0 - Unusable"); else sprintf(tempstr, "Spell Level %i", v); AddPanelString(tempstr, TEXT_CENTER); break; case 2: sprintf(tempstr, "Scroll of %s", spelldata[pSpell].sNameText); AddPanelString(tempstr, TEXT_CENTER); c = 0; for (s = 0; s < plr[myplr]._pNumInv; s++) { if ((plr[myplr].InvList[s]._itype != -1) && ((plr[myplr].InvList[s]._iMiscId == IMID_SCROLL) || (plr[myplr].InvList[s]._iMiscId == IMID_TSCROLL))) { if (plr[myplr].InvList[s]._iSpell == pSpell) c++; } } for (s = 0; s < MAXSPD; s++) { if ((plr[myplr].SpdList[s]._itype != -1) && ((plr[myplr].SpdList[s]._iMiscId == IMID_SCROLL) || (plr[myplr].SpdList[s]._iMiscId == IMID_TSCROLL))) { if (plr[myplr].SpdList[s]._iSpell == pSpell) c++; } } if (c == 1) strcpy(tempstr, "1 Scroll"); else sprintf(tempstr, "%i Scrolls", c); AddPanelString(tempstr, TEXT_CENTER); break; case 3: sprintf(tempstr, "Staff of %s", spelldata[pSpell].sNameText); AddPanelString(tempstr, TEXT_CENTER); if (plr[myplr].Hand1Item._iCharges == 1) strcpy(tempstr, "1 Charge"); else sprintf(tempstr, "%i Charges", plr[myplr].Hand1Item._iCharges); AddPanelString(tempstr, TEXT_CENTER); break; } } } } if ((MouseX > 190) && (MouseX < 437) && (MouseY > 356) && (MouseY < 385)) cursinvitem = CheckInvHLight(); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void ReleasePanelBtn() { BYTE bMenuOff = TRUE; drawbtnflag = TRUE; panbtndown = FALSE; for (int i = 0; i < NUMPBTNS; i++) { if (! panbtn[i]) continue; panbtn[i] = FALSE; // was the mouseup in this button? if (MouseX < PanBtnPos[i][0]) continue; if (MouseX > PanBtnPos[i][0] + PanBtnPos[i][2]) continue; if (MouseY < PanBtnPos[i][1]) continue; if (MouseY > PanBtnPos[i][1] + PanBtnPos[i][3]) continue; switch(i) { case PBTN_CHR : questlog = FALSE; chrflag = !chrflag; break; case PBTN_QUEST: chrflag = FALSE; if (!questlog) StartQuestlog(); else questlog = FALSE; break; case PBTN_AMAP : DoAutoMap(); break; case PBTN_MENU : qtextflag = FALSE; gamemenu_toggle(); bMenuOff = FALSE; break; case PBTN_INV : sbookflag = FALSE; invflag = !invflag; if (dropGoldFlag) { dropGoldFlag = FALSE; dropGoldValue = 0; } break; case PBTN_SBOOK : invflag = FALSE; if (dropGoldFlag) { dropGoldFlag = FALSE; dropGoldValue = 0; } sbookflag = !sbookflag; break; case PBTN_TALK: if (talkflag) TalkEnd(); else TalkStart(); break; case PBTN_ATTACK: FriendlyMode = !FriendlyMode; break; } } if (bMenuOff) gamemenu_off(); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void FreeControlPan() { DiabloFreePtr(pBtmBuff); DiabloFreePtr(pManaBuff); DiabloFreePtr(pLifeBuff); DiabloFreePtr(pPanelText); DiabloFreePtr(pChrPanel); DiabloFreePtr(pSpellCels); DiabloFreePtr(pPanelButtons); DiabloFreePtr(pMultiBtns); DiabloFreePtr(pTalkBtns); DiabloFreePtr(pChrButtons); DiabloFreePtr(pDurIcons); DiabloFreePtr(pQLogCel); DiabloFreePtr(pSpellBkCel); DiabloFreePtr(pSBkBtnCel); DiabloFreePtr(pSBkIconCels); DiabloFreePtr(pGBoxBuff); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ BOOL InfoFit(const char * p) { long tw = 0; while (*p) { BYTE c = char2print(*p++); c = fonttrans[c]; tw += fontkern[c]; if (tw >= 125) return FALSE; } return TRUE; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static void CPrintString(int l,const char * pszStr, int just, int pnl) { long boffset = fontofs[pnl][l]; int w = 0; if (just == TEXT_CENTER) { long tw = 0; const char * pszTemp = pszStr; while (*pszTemp) { BYTE c = char2print(*pszTemp++); c = fonttrans[c]; tw += fontkern[c] + 2; } if (tw < 288) w = (288 - tw) >> 1; boffset += w; } while (*pszStr) { BYTE c = char2print(*pszStr++); c = fonttrans[c]; w += fontkern[c] + 2; if (c && (w < 288)) DrawPanelFont(boffset, c, infoclr); boffset += fontkern[c] + 2; } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static void PrintInfo() { if (talkflag) return; int nOffset1 = 0; int nOffset2 = 1; if (infostr[0] != 0) { CPrintString(0, infostr, TEXT_CENTER, pnumlines); nOffset1 = 1; nOffset2 = 0; } for (int i = 0; i < pnumlines; i++) CPrintString(i+nOffset1, panelstr[i], pstrjust[i], pnumlines-nOffset2); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void DrawInfoBox() { // Erase old box CopyCtrlPan(177, 62, 288, 60, 241, 558); if ((!panelflag) && (!trigflag) && (cursinvitem == -1) && (!spselflag)) { infostr[0] = 0; infoclr = ICOLOR_WHITE; ClearPanel(); } if ((spselflag) || (trigflag)) { infoclr = ICOLOR_WHITE; } else { if (curs >= ICSTART) { if (plr[myplr].HoldItem._itype == IT_GOLD) { int nGold = plr[myplr].HoldItem._ivalue; const char * get_pieces_str(int nGold); sprintf(infostr,"%i gold %s",nGold,get_pieces_str(nGold)); } else if (!plr[myplr].HoldItem._iStatFlag) { ClearPanel(); AddPanelString("Requirements not met", TEXT_CENTER); pinfoflag = TRUE; } else { if (plr[myplr].HoldItem._iIdentified) strcpy(infostr, plr[myplr].HoldItem._iIName); else strcpy(infostr, plr[myplr].HoldItem._iName); if (plr[myplr].HoldItem._iMagical == IMAGIC_MAGIC) infoclr = ICOLOR_BLUE; if (plr[myplr].HoldItem._iMagical == IMAGIC_UNIQUE) infoclr = ICOLOR_GOLD; } } else { // if cursinvitem != -1 then the string will already be in infostr // if trigflag then the string will already be set as well if (cursitem != -1) { // @@@ drb debug #if 0 int GetLDeltaItem(); ClearPanel(); ItemStruct *pi = &item[cursitem]; strcpy(infostr, pi->_iName); sprintf(tempstr, "Delta # = %i", GetLDeltaItem()); AddPanelString(tempstr, TEXT_CENTER); //sprintf(tempstr, "seed = %i", pi->_iSeed); //AddPanelString(tempstr, TEXT_CENTER); // @@@ drb end debug #else GetItemStr(cursitem); #endif } if (cursobj != -1) GetObjectStr(cursobj); if (cursmonst != -1) { if (leveltype != 0) { infoclr = ICOLOR_WHITE; strcpy(infostr, monster[cursmonst].mName); ClearPanel(); if (monster[cursmonst]._uniqtype != 0) { infoclr = ICOLOR_GOLD; void PrintUniqueHistory(); PrintUniqueHistory(); } else PrintMonstHistory(monster[cursmonst].MType->mtype); } else strcpy(infostr, towner[cursmonst]._tName); } if (cursplr != -1) { infoclr = ICOLOR_GOLD; strcpy(infostr, plr[cursplr]._pName); ClearPanel(); sprintf(tempstr, "Level : %i", plr[cursplr]._pLevel); AddPanelString(tempstr, TEXT_CENTER); sprintf(tempstr, "Hit Points %i of %i", (plr[cursplr]._pHitPoints >> HP_SHIFT), (plr[cursplr]._pMaxHP >> HP_SHIFT)); AddPanelString(tempstr, TEXT_CENTER); } } } //if ((pinfoflag) && (cursmonst == -1) && (cursinvitem == -1) && (curs < ICSTART)) ClearPanel(); if ((infostr[0] != 0) || (pnumlines != 0)) PrintInfo(); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static void PlrStringXY(int x1, int y, int x2,const char * pszStr,char col) { long boffset = nBuffWTbl[y + 160] + x1 + 64; int aw = x2 - x1 + 1; int w = 0; // calculate string width int tw = 0; const char * pszTemp = pszStr; while (*pszTemp) { BYTE c = char2print(*pszTemp++); c = fonttrans[c]; tw += fontkern[c] + 1; } if (tw < aw) w = (aw - tw) >> 1; boffset += w; while (*pszStr) { BYTE c = char2print(*pszStr++); c = fonttrans[c]; w += fontkern[c] + 1; if (c && w < aw) DrawPanelFont(boffset, c, col); boffset += fontkern[c] + 1; } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void PrintStringXY(int x, int y,const char * pszStr, char col) { long boffset = nBuffWTbl[y + 160] + x + 64; while (*pszStr) { BYTE c = char2print(*pszStr++); c = fonttrans[c]; if (c) DrawPanelFont(boffset, c, col); boffset += fontkern[c] + 1; } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static void PlrStringXY2(int x1, int y, int x2,const char * pszStr,char col,int a) { long boffset = nBuffWTbl[y + 160] + x1 + 64; int aw = x2 - x1 + 1; int w = 0; // calculate string width int tw = 0; const char * pszTemp = pszStr; while (*pszTemp) { BYTE c = char2print(*pszTemp++); c = fonttrans[c]; tw += fontkern[c] + a; } if (tw < aw) w = (aw - tw) >> 1; boffset += w; while (*pszStr) { BYTE c = char2print(*pszStr++); c = fonttrans[c]; w += fontkern[c] + a; if (c && w < aw) DrawPanelFont(boffset, c, col); boffset += fontkern[c] + a; } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void DrawChr() { char c; char chrstr[64]; int pc; long mind, maxd; int hper, ac; DrawCel(64, 511, pChrPanel, 1, 320); PlrStringXY(20, 32, 151, plr[myplr]._pName, ICOLOR_WHITE); if (plr[myplr]._pClass == CLASS_WARRIOR) PlrStringXY(168, 32, 299, "Warrior", ICOLOR_WHITE); #if !IS_VERSION(SHAREWARE) else if (plr[myplr]._pClass == CLASS_ROGUE) PlrStringXY(168, 32, 299, "Rogue", ICOLOR_WHITE); else if (plr[myplr]._pClass == CLASS_SORCEROR) PlrStringXY(168, 32, 299, "Sorceror", ICOLOR_WHITE); else if (plr[myplr]._pClass == CLASS_MONK) PlrStringXY(168, 32, 299, "Monk", ICOLOR_WHITE); else if (plr[myplr]._pClass == CLASS_BARD) PlrStringXY(168, 32, 299, "Bard", ICOLOR_WHITE); #endif sprintf(chrstr, "%i", plr[myplr]._pLevel); PlrStringXY(66, 69, 109, chrstr, ICOLOR_WHITE); sprintf(chrstr, "%li", plr[myplr]._pExperience); PlrStringXY(216, 69, 300, chrstr, ICOLOR_WHITE); if (plr[myplr]._pLevel == 50) { strcpy(chrstr, "None"); c = ICOLOR_GOLD; } else { sprintf(chrstr, "%li", plr[myplr]._pNextExper); c = ICOLOR_WHITE; } PlrStringXY(216, 97, 300, chrstr, c); sprintf(chrstr, "%i", plr[myplr]._pGold); PlrStringXY(216, 146, 300, chrstr, ICOLOR_WHITE); c = ICOLOR_WHITE; if (plr[myplr]._pIBonusAC > 0) c = ICOLOR_BLUE; if (plr[myplr]._pIBonusAC < 0) c = ICOLOR_RED; // rjs ac = (byte)plr[myplr]._pArmorClass+plr[myplr]._pIAC+plr[myplr]._pIBonusAC; ac = plr[myplr]._pIAC+plr[myplr]._pIBonusAC; ac += (plr[myplr]._pDexterity / 5); sprintf(chrstr, "%i", ac); PlrStringXY(258, 183, 301, chrstr, c); c = ICOLOR_WHITE; if (plr[myplr]._pIBonusToHit > 0) c = ICOLOR_BLUE; if (plr[myplr]._pIBonusToHit < 0) c = ICOLOR_RED; hper = BASE_TO_HIT + (plr[myplr]._pDexterity >> 1) + plr[myplr]._pIBonusToHit; sprintf(chrstr, "%i%%", hper); PlrStringXY(258, 211, 301, chrstr, c); c = ICOLOR_WHITE; if (plr[myplr]._pIBonusDam > 0) c = ICOLOR_BLUE; if (plr[myplr]._pIBonusDam < 0) c = ICOLOR_RED; mind = plr[myplr]._pIMinDam; mind += (mind * plr[myplr]._pIBonusDam) / 100; mind += plr[myplr]._pIBonusDamMod; if (plr[myplr].Hand1Item._itype == IT_BOW) { if (plr[myplr]._pClass == CLASS_ROGUE) mind += plr[myplr]._pDamageMod; else mind += (plr[myplr]._pDamageMod >> 1); } else mind += plr[myplr]._pDamageMod; maxd = plr[myplr]._pIMaxDam; maxd += (maxd * plr[myplr]._pIBonusDam) / 100; maxd += plr[myplr]._pIBonusDamMod; if (plr[myplr].Hand1Item._itype == IT_BOW) { if (plr[myplr]._pClass == CLASS_ROGUE) maxd += plr[myplr]._pDamageMod; else maxd += (plr[myplr]._pDamageMod >> 1); } else maxd += plr[myplr]._pDamageMod; sprintf(chrstr, "%i-%i", mind, maxd); if ((mind >= 100) || (maxd >= 100)) PlrStringXY2(254, 239, 305, chrstr, c, -1); else PlrStringXY2(258, 239, 301, chrstr, c, 0); // Magic Resist if (plr[myplr]._pMagResist == 0) c = ICOLOR_WHITE; else c = ICOLOR_BLUE; if (plr[myplr]._pMagResist < RESIST_MAX) sprintf(chrstr, "%i%%", plr[myplr]._pMagResist); else { c = ICOLOR_GOLD; sprintf(chrstr, "MAX"); } PlrStringXY(257, 276, 300, chrstr, c); // Fire Resist if (plr[myplr]._pFireResist == 0) c = ICOLOR_WHITE; else c = ICOLOR_BLUE; if (plr[myplr]._pFireResist < RESIST_MAX) sprintf(chrstr, "%i%%", plr[myplr]._pFireResist); else { c = ICOLOR_GOLD; sprintf(chrstr, "MAX"); } PlrStringXY(257, 304, 300, chrstr, c); // Lightning Resist if (plr[myplr]._pLghtResist == 0) c = ICOLOR_WHITE; else c = ICOLOR_BLUE; if (plr[myplr]._pLghtResist < RESIST_MAX) sprintf(chrstr, "%i%%", plr[myplr]._pLghtResist); else { c = ICOLOR_GOLD; sprintf(chrstr, "MAX"); } PlrStringXY(257, 332, 300, chrstr, c); c = ICOLOR_WHITE; sprintf(chrstr, "%i", plr[myplr]._pBaseStr); if (MaxStats[plr[myplr]._pClass][0] == plr[myplr]._pBaseStr) c = ICOLOR_GOLD; PlrStringXY( 95, 155, 126, chrstr, c); c = ICOLOR_WHITE; sprintf(chrstr, "%i", plr[myplr]._pBaseMag); if (MaxStats[plr[myplr]._pClass][1] == plr[myplr]._pBaseMag) c = ICOLOR_GOLD; PlrStringXY( 95, 183, 126, chrstr, c); c = ICOLOR_WHITE; sprintf(chrstr, "%i", plr[myplr]._pBaseDex); if (MaxStats[plr[myplr]._pClass][2] == plr[myplr]._pBaseDex) c = ICOLOR_GOLD; PlrStringXY( 95, 211, 126, chrstr, c); c = ICOLOR_WHITE; sprintf(chrstr, "%i", plr[myplr]._pBaseVit); if (MaxStats[plr[myplr]._pClass][3] == plr[myplr]._pBaseVit) c = ICOLOR_GOLD; PlrStringXY( 95, 239, 126, chrstr, c); c = ICOLOR_WHITE; if (plr[myplr]._pStrength > plr[myplr]._pBaseStr) c = ICOLOR_BLUE; if (plr[myplr]._pStrength < plr[myplr]._pBaseStr) c = ICOLOR_RED; sprintf(chrstr, "%i", plr[myplr]._pStrength); PlrStringXY(143, 155, 173, chrstr, c); c = ICOLOR_WHITE; if (plr[myplr]._pMagic > plr[myplr]._pBaseMag) c = ICOLOR_BLUE; if (plr[myplr]._pMagic < plr[myplr]._pBaseMag) c = ICOLOR_RED; sprintf(chrstr, "%i", plr[myplr]._pMagic); PlrStringXY(143, 183, 173, chrstr, c); c = ICOLOR_WHITE; if (plr[myplr]._pDexterity > plr[myplr]._pBaseDex) c = ICOLOR_BLUE; if (plr[myplr]._pDexterity < plr[myplr]._pBaseDex) c = ICOLOR_RED; sprintf(chrstr, "%i", plr[myplr]._pDexterity); PlrStringXY(143, 211, 173, chrstr, c); c = ICOLOR_WHITE; if (plr[myplr]._pVitality > plr[myplr]._pBaseVit) c = ICOLOR_BLUE; if (plr[myplr]._pVitality < plr[myplr]._pBaseVit) c = ICOLOR_RED; sprintf(chrstr, "%i", plr[myplr]._pVitality); PlrStringXY(143, 239, 173, chrstr, c); // drb.patch1.start.2/05/97 if (plr[myplr]._pStatPts > 0) { int CalcStatDiff(int); if (CalcStatDiff(myplr) < plr[myplr]._pStatPts) plr[myplr]._pStatPts = CalcStatDiff(myplr); } // drb.patch1.end.2/05/97 // Points to distibute if (plr[myplr]._pStatPts > 0) { sprintf(chrstr, "%i", plr[myplr]._pStatPts); PlrStringXY(95, 266, 126, chrstr, ICOLOR_RED);// check x y pc = plr[myplr]._pClass; if (plr[myplr]._pBaseStr < MaxStats[pc][0]) DrawCel(201, 319, pChrButtons, 2+chrbtn[0], 41); if (plr[myplr]._pBaseMag < MaxStats[pc][1]) DrawCel(201, 347, pChrButtons, 4+chrbtn[1], 41); if (plr[myplr]._pBaseDex < MaxStats[pc][2]) DrawCel(201, 376, pChrButtons, 6+chrbtn[2], 41); if (plr[myplr]._pBaseVit < MaxStats[pc][3]) DrawCel(201, 404, pChrButtons, 8+chrbtn[3], 41); } if (plr[myplr]._pMaxHP > plr[myplr]._pMaxHPBase) c = ICOLOR_BLUE; else c = ICOLOR_WHITE; sprintf(chrstr, "%i", (plr[myplr]._pMaxHP >> HP_SHIFT)); PlrStringXY( 95, 304, 126, chrstr, c); if (plr[myplr]._pHitPoints != plr[myplr]._pMaxHP) c = ICOLOR_RED; sprintf(chrstr, "%i", (plr[myplr]._pHitPoints >> HP_SHIFT)); PlrStringXY(143, 304, 174, chrstr, c); if (plr[myplr]._pMaxMana > plr[myplr]._pMaxManaBase) c = ICOLOR_BLUE; else c = ICOLOR_WHITE; sprintf(chrstr, "%i", (plr[myplr]._pMaxMana >> MANA_SHIFT)); PlrStringXY( 95, 332, 126, chrstr, c); if (plr[myplr]._pMana != plr[myplr]._pMaxMana) c = ICOLOR_RED; sprintf(chrstr, "%i", (plr[myplr]._pMana >> MANA_SHIFT)); PlrStringXY(143, 332, 174, chrstr, c); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void CheckLvlBtn() { if (lvlbtndown) return; if ((MouseX >= 40) && (MouseX <= 81) && (MouseY >= 313) && (MouseY <= 335)) lvlbtndown = TRUE; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void ReleaseLvlBtn() { if ((MouseX >= 40) && (MouseX <= 81) && (MouseY >= 313) && (MouseY <= 335)) chrflag = TRUE; lvlbtndown = FALSE; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void DrawLevelUpIcon() { int c; if (stextflag != STORE_NONE) return; if (lvlbtndown) c = 3; else c = 2; PlrStringXY(0, 303, 120, "Level Up", ICOLOR_WHITE); DrawCel(104, 495, pChrButtons, c, 41); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void CheckChrBtns() { if (chrbtndown) return; if (! plr[myplr]._pStatPts) return; int pc = plr[myplr]._pClass; for (int i = 0; i < NUMCBTNS; i++) { switch(i) { case 0: if (plr[myplr]._pBaseStr >= MaxStats[pc][i]) continue; break; case 1: if (plr[myplr]._pBaseMag >= MaxStats[pc][i]) continue; break; case 2: if (plr[myplr]._pBaseDex >= MaxStats[pc][i]) continue; break; case 3: if (plr[myplr]._pBaseVit >= MaxStats[pc][i]) continue; break; default: continue; } int x2 = ChrBtnPos[i][0] + ChrBtnPos[i][2]; int y2 = ChrBtnPos[i][1] + ChrBtnPos[i][3]; if ((MouseX >= ChrBtnPos[i][0]) && (MouseX <= x2) && (MouseY >= ChrBtnPos[i][1]) && (MouseY <= y2)) { chrbtn[i] = TRUE; chrbtndown = TRUE; } } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void ReleaseChrBtn() { chrbtndown = FALSE; for (int i = 0; i < NUMCBTNS; i++) { if (! chrbtn[i]) continue; chrbtn[i] = FALSE; // was mouseup inside button? if (MouseX < ChrBtnPos[i][0]) continue; if (MouseX > ChrBtnPos[i][0] + ChrBtnPos[i][2]) continue; if (MouseY < ChrBtnPos[i][1]) continue; if (MouseY > ChrBtnPos[i][1] + ChrBtnPos[i][3]) continue; switch(i) { case CBTN_STR : NetSendCmdParam1(TRUE,CMD_ADDSTR,1); plr[myplr]._pStatPts--; break; case CBTN_MAG : NetSendCmdParam1(TRUE,CMD_ADDMAG,1); plr[myplr]._pStatPts--; break; case CBTN_DEX : NetSendCmdParam1(TRUE,CMD_ADDDEX,1); plr[myplr]._pStatPts--; break; case CBTN_VIT : NetSendCmdParam1(TRUE,CMD_ADDVIT,1); plr[myplr]._pStatPts--; break; } } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static int DrawDurIcon4Item(const ItemStruct * pItem, int x, int c) { // don't need to draw icon if there is no item if (pItem->_itype == -1) return x; // don't need to draw icon if durability is high if (pItem->_iDurability > 5) return x; if (c == 0) { if (pItem->_iClass == IC_WEAP) switch(pItem->_itype) { case IT_SWORD: c = 2; break; case IT_AXE: c = 6; break; case IT_BOW: c = 7; break; case IT_MACE: c = 5; break; case IT_STAFF: c = 8; break; } else { c = 1; } } // choose cel to draw based on durability if (pItem->_iDurability > 2) c += 8; // draw it DrawCel(x, 495, pDurIcons, c, 32); // adjust position for next durability icon return x - 40; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void DrawDurIcon() { if ((chrflag || questlog) && (invflag || sbookflag)) return; int x = 656; if (invflag || sbookflag) x -= 320; const PlayerStruct * p = &plr[myplr]; x = DrawDurIcon4Item(&p->InvBody[INVLOC_HEAD],x,4); x = DrawDurIcon4Item(&p->InvBody[INVLOC_BODY],x,3); x = DrawDurIcon4Item(&p->InvBody[INVLOC_HAND1],x,0); x = DrawDurIcon4Item(&p->InvBody[INVLOC_HAND2],x,0); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void RedBack() { long ltaboff; if (light4flag) ltaboff = 1536; else ltaboff = 4608; app_assert(gpBuffer); if (leveltype != 4) { __asm { mov edi,dword ptr [gpBuffer] add edi,122944 mov ebx,dword ptr [pLightTbl] add ebx,dword ptr [ltaboff] mov edx,352 _YLp: mov ecx,640 _XLp: mov al,byte ptr [edi] xlatb stosb loop _XLp add edi,128 dec edx jnz _YLp } } else { __asm { mov edi,dword ptr [gpBuffer] add edi,122944 mov ebx,dword ptr [pLightTbl] add ebx,dword ptr [ltaboff] mov edx,352 _YLp2: mov ecx,640 _XLp2: mov al,byte ptr [edi] cmp al,32 jb _Skip xlatb _Skip: stosb loop _XLp2 add edi,128 dec edx jnz _YLp2 } } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static void PrintSBookStr(int x, int y, BOOL cjustflag,const char * pszStr, char col) { long boffset = nBuffWTbl[y] + x + 440; int w = 0; if (cjustflag) { int tw = 0; const char * pszTemp = pszStr; while (*pszTemp) { BYTE c = char2print(*pszTemp++); c = fonttrans[c]; tw += fontkern[c] + 1; } if (tw < 222) w = (222 - tw) >> 1; boffset += w; } while (*pszStr) { BYTE c = char2print(*pszStr++); c = fonttrans[c]; w += fontkern[c] + 1; if (c && w <= 222) DrawPanelFont(boffset, c, col); boffset += fontkern[c] + 1; } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ char GetSBookTrans(int ii, BOOL townok) { char st, sl; st = STRN_BLUE; if (plr[myplr]._pISpells & (((__int64)1) << (ii-1))) st = STRN_ORANGE; if (plr[myplr]._pAblSpells & (1 << (ii-1))) st = STRN_GOLD; if (st == STRN_BLUE) { if (!CheckSpell(myplr, ii, SPT_MEMORIZED, TRUE)) st = STRN_GREY; sl = plr[myplr]._pSplLvl[ii] + plr[myplr]._pISplLvlAdd; if (sl <= 0 ) st = STRN_GREY; } if ((townok) && (currlevel == 0) && (st != STRN_GREY) && (spelldata[ii].sTownSpell == FALSE)) st = STRN_GREY; return(st); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void DrawSpellBook() { int i, ii, x, y, mind, maxd; __int64 tspls; char st; int v; // Drawbackground DrawCel(384, 511, pSpellBkCel, 1, 320); // Draw tab //x = (sbooktab * 51) + 391; //DrawCel(x, 508, pSBkBtnCel, 1 + sbooktab, 51); x = (sbooktab * 76) + 391; DrawCel(x, 508, pSBkBtnCel, 1 + sbooktab, 76); // Draw Spell Icons y = 215; tspls = plr[myplr]._pISpells | plr[myplr]._pMemSpells | plr[myplr]._pAblSpells; for (i = 1; i < 8; i++) { ii = SpellPages[sbooktab][i-1]; if (ii != -1) { if (tspls & (((__int64) 1) << (ii-1))) { st = GetSBookTrans(ii, TRUE); SetSpellTrans(st); DrawSpellCel(395, y, pSBkIconCels, SpellITbl[ii], 37); if ((ii == plr[myplr]._pRSpell) && (st == plr[myplr]._pRSplType)) { SetSpellTrans(STRN_GOLD); DrawSpellCel(395, y, pSBkIconCels, 43, 37); } PrintSBookStr(10, y-23, FALSE, spelldata[ii].sNameText, ICOLOR_WHITE); st = GetSBookTrans(ii, FALSE); switch (st) { case STRN_GOLD: strcpy(tempstr, "Skill"); break; case STRN_ORANGE: sprintf(tempstr, "Staff (%i charges)", plr[myplr].Hand1Item._iCharges); break; default: v = GetManaAmount(myplr, ii) >> MANA_SHIFT; GetDamageAmt(ii, &mind, &maxd); if (mind != -1) sprintf(tempstr, "Mana: %i Dam: %i - %i", v, mind, maxd); else sprintf(tempstr, "Mana: %i Dam: n/a", v); if (ii == SPL_BONESPIRIT) sprintf(tempstr, "Mana: %i Dam: 1/3 tgt hp", v); PrintSBookStr(10, y-1, FALSE, tempstr, ICOLOR_WHITE); v = plr[myplr]._pSplLvl[ii]+plr[myplr]._pISplLvlAdd; if ( v < 0 ) v = 0; if (v == 0) sprintf(tempstr, "Spell Level 0 - Unusable"); else sprintf(tempstr, "Spell Level %i", v); break; } PrintSBookStr(10, y-12, FALSE, tempstr, ICOLOR_WHITE); } } y += 43; } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void CheckSBook() { int spl; __int64 tspls; char st; // Check spell icon if ((MouseX >= 331) && (MouseX < 368) && (MouseY >= 18) && (MouseY < 314)) { spl = (MouseY - 18) / 43; spl = SpellPages[sbooktab][spl]; tspls = plr[myplr]._pISpells | plr[myplr]._pMemSpells | plr[myplr]._pAblSpells; if (spl != -1) { if (tspls & (((__int64)1) << (spl-1))) { st = SPT_MEMORIZED; if (plr[myplr]._pISpells & (((__int64)1) << (spl-1))) st = SPT_ITEM; if (plr[myplr]._pAblSpells & (1 << (spl-1))) st = SPT_ABILITY; plr[myplr]._pRSpell = spl; plr[myplr]._pRSplType = st; force_redraw = FULLDRAW; } } } // Check spell tabs if ((MouseX >= 327) && (MouseX < 633) && (MouseY >= 320) && (MouseY < 349)) { sbooktab = (MouseX - 327) / 76; } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------* BOOL CheckSBookCast() { int spl; __int64 tspls; char st; BOOL okflag; if (currlevel == 0) return(FALSE); // Check spell icon if ((MouseX >= 327) && (MouseX < 368) && (MouseY >= 29) && (MouseY < 346)) { spl = (MouseY - 29) / 46; spl = SpellPages[sbooktab][spl]; tspls = plr[myplr]._pISpells | plr[myplr]._pMemSpells | plr[myplr]._pAblSpells; if (spl != -1) { if (tspls & (1 << (spl-1))) { st = SPT_MEMORIZED; if (plr[myplr]._pISpells & (((__int64)1) << (spl-1))) st = SPT_ITEM; if (plr[myplr]._pAblSpells & (1 << (spl-1))) st = SPT_ABILITY; okflag = FALSE; switch (st) { case SPT_ABILITY : case SPT_MEMORIZED : okflag = CheckSpell(myplr, spl, st, FALSE); break; case SPT_ITEM: okflag = UseStaffSBook(spl); break; } if (okflag) { if (spelldata[spl].sTargeted) { plr[myplr]._pTSpell = spl; plr[myplr]._pTSplType = st; NewCursor(TARGET_CURS); } else { plr[myplr]._pSBkSpell = spl; plr[myplr]._pSBkSplType = st; NetSendCmdParam1(TRUE,CMD_SBSPELL,plr[myplr]._pSBkSpell); } return(TRUE); } } } } return(FALSE); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ const char * get_pieces_str(int nGold) { if (nGold == 1) return "piece"; return "pieces"; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void DrawGoldBox(int gold) { int i; long xOffset; // Initialize xOffset = 0; // Draw the box DrawCel(415, 338, pGBoxBuff, 1, 261); // Output the strings sprintf(tempstr, "You have %u gold",initialDropGoldValue); PlrStringXY(366, 87, 600, tempstr, ICOLOR_GOLD); sprintf(tempstr, "%s. How many do", get_pieces_str(initialDropGoldValue)); PlrStringXY(366, 103, 600, tempstr, ICOLOR_GOLD); PlrStringXY(366, 121, 600, "you want to remove?", ICOLOR_GOLD); if (gold > 0) { sprintf(tempstr, "%u", gold); PrintStringXY(388, 140, tempstr, ICOLOR_WHITE); } // Get x offset for pentagram if (gold > 0) { for (i = 0; i < tempstr[i] != 0; i++) { BYTE c = char2print(tempstr[i]); c = fonttrans[c]; xOffset += fontkern[c]+1; } xOffset += 452; } else xOffset = 450; // Draw the pentagram DrawCel(xOffset, 300, pSTextSpinCels, pentaspin, 12); // Increment the pentagram spinner pentaspin = (pentaspin & 0x7) + 1; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ // macro to convert char to int #define ATON(c) (c - 0x30) // keyboard constants #define DG_CR 0x0d #define DG_ESC 0x1b #define DG_BACK 0x08 void DropGoldType(char c) //, int ivalue) { char dGoldStr[6]; // Check if player is dead. This should prevent the multi player death frame // gold cheat. if ((plr[myplr]._pHitPoints >> HP_SHIFT) <= 0) { dropGoldFlag = FALSE; dropGoldValue = 0; return; } // Clear the string memset(dGoldStr, 0x00, sizeof(dGoldStr)); // Convert number to string _itoa(dropGoldValue, dGoldStr, 10); // Carriage Return was pressed so the player wants to drop some gold if (c == DG_CR) { if (dropGoldValue > 0) DropGold(myplr, initialDropGoldIndex); dropGoldFlag = FALSE; return; } // Escape was pressed so the player wants to quit w/out dropping gold if (c == DG_ESC) { dropGoldFlag = FALSE; dropGoldValue = 0; return; } // Backspace was pressed so clear the last char in the string if (c == DG_BACK) { dGoldStr[strlen(dGoldStr)-1] = NULL; dropGoldValue = atoi(dGoldStr); return; } // Check to see if the player typed a number and if so update the string if ((ATON(c) >= 0) && (ATON(c) <= 9)) { if ((dropGoldValue == 0) && (atoi(dGoldStr) > initialDropGoldValue)) dGoldStr[0] = c; else { dGoldStr[strlen(dGoldStr)] = c; if ((atoi(dGoldStr) > initialDropGoldValue) || (strlen(dGoldStr) > strlen(dGoldStr))) return; } dropGoldValue = atoi(dGoldStr); return; } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void DropGold(int pnum, int cii) { int c; if (cii <= 46) { // Item is in the InvList c = cii - 7; plr[pnum].InvList[c]._ivalue -= dropGoldValue; // Modify item cursor in the InvList if (plr[pnum].InvList[c]._ivalue > 0) SetGoldCurs(pnum, c); else RemoveInvItem(pnum, c); } else { // Item is in the SpdList c = cii - 47; plr[pnum].SpdList[c]._ivalue -= dropGoldValue; // Modify item cursor in the SpdList if (plr[pnum].SpdList[c]._ivalue > 0) SetSpdbarGoldCurs(pnum, c); else RemoveSpdBarItem(pnum, c); } // Initialize hold item to gold type SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD); GetGoldSeed(pnum, &plr[pnum].HoldItem); // Set hold item values plr[pnum].HoldItem._ivalue = dropGoldValue; plr[pnum].HoldItem._iStatFlag = TRUE; // Set cursor arrow to gold SetDropGoldCursor(pnum); // Recalculate players gold plr[pnum]._pGold = CalculateGold(pnum); dropGoldValue = 0; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void SetDropGoldCursor(int pnum) { if (plr[pnum].HoldItem._ivalue >= GOLD_VT2) plr[pnum].HoldItem._iCurs = ITEM_5GOLD; else { if (plr[pnum].HoldItem._ivalue <= GOLD_VT1) plr[pnum].HoldItem._iCurs = ITEM_1GOLD; else plr[pnum].HoldItem._iCurs = ITEM_3GOLD; } NewCursor(plr[pnum].HoldItem._iCurs + ICSTART); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ /* void WhiteCtrlPan(int sx, int sy, int deltax, int deltay, int dx, int dy) { long dest; dest = (dy * 768) + dx; __asm { mov edi,dword ptr [pBuffer] add edi,dword ptr [dest] xor ebx,ebx mov bx,word ptr [deltax] xor edx,edx mov dx,word ptr [deltay] mov eax, 0ffffffffh _CLp: mov ecx,ebx shr ecx,1 jnc _Tw stosb jecxz _Tx _Tw: shr ecx,1 jnc _TLp stosw jecxz _Tx _TLp: rep stosd _Tx: add edi,768 sub edi,ebx dec edx jnz _CLp } } */ /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static char * print_talk_string( char * pszStr, int x, int y, long * plOffset, int color ) { // move to top left of talk box x += 264; //y += 546; y += 534; int w = x; *plOffset = nBuffWTbl[y] + x; while (*pszStr) { // can we fit the next character on this row? BYTE c = char2print(*pszStr); c = fonttrans[c]; w += fontkern[c] + 1; if (w > 250+264) return pszStr; pszStr++; // draw char if (c != 0) DrawPanelFont(*plOffset, c, color); *plOffset += fontkern[c] + 1; } return NULL; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ #define TALK_ROW_HGT 13 void DrawTalkBox() { if (!talkflag) return; app_assert(gpBuffer); // erase old box CopyCtrlPan(175, 20+talkofs, 294, 5, 239, 516); for (int i = 0; i < 10; i++) CopyCtrlPan(175+(i>>1), 25+i+talkofs, 293-i, 1, 239+(i>>1), 521+i); CopyCtrlPan(185, 35+talkofs, 274, 30, 249, 531); CopyCtrlPan(180, 65+talkofs, 284, 5, 244, 561); for (i = 0; i < 10; i++) CopyCtrlPan(180, 70+i+talkofs, 284+i, 1, 244, 566+i); CopyCtrlPan(170, 80+talkofs, 310, 55, 234, 576); // 200,373-450,456 (screen coords) long lOffset; char * pszStr = sgszTalkMsg; for (int row = 0; row < 3; row++) { pszStr = print_talk_string(pszStr,0,row * TALK_ROW_HGT,&lOffset,ICOLOR_WHITE); if (! pszStr) break; } // don't allow string to be too long if (pszStr) *pszStr = 0; // draw spinnies on last row DrawCelP(gpBuffer + lOffset, pSTextSpinCels, tspin, 12); tspin = (tspin & 0x7) + 1; // draw player names row = 0; for (i = 0; i < MAX_PLRS; i++) { if (i == myplr) continue; // are we "talking" to this player int nColor, nCel; if (sgbPlrTalkTbl[i]) { nColor = ICOLOR_GOLD; if (talkbtndown[row]) { if (row == 0) nCel = 3; else nCel = 4; DrawCel(236, 596 + (row * 18), pTalkBtns, nCel, 61); } } else { nColor = ICOLOR_RED; if (row == 0) nCel = 1; else nCel = 2; if (talkbtndown[row]) nCel += 4; DrawCel(236, 596 + (row * 18), pTalkBtns, nCel, 61); } if (plr[i].plractive) print_talk_string(plr[i]._pName,46,60 + (row * 18),&lOffset,nColor); row++; } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ #define TALK_NAME_TOP 421 #define TALK_NAME_LEFT 172 #define TALK_NAME_WDT 61 #define TALK_NAME_HGT (18*(MAX_PLRS-1)) BOOL talk_click() { if (! talkflag) return FALSE; if (MouseX < TALK_NAME_LEFT) return FALSE; if (MouseY < TALK_NAME_TOP) return FALSE; if (MouseX > TALK_NAME_LEFT + TALK_NAME_WDT) return FALSE; if (MouseY > TALK_NAME_TOP + TALK_NAME_HGT) return FALSE; for (int i = 0; i < 3; i++) talkbtndown[i] = FALSE; talkbtndown[(MouseY - TALK_NAME_TOP) / 18] = TRUE; return TRUE; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void talk_release() { if (! talkflag) return; for (int i = 0; i < 3; i++) talkbtndown[i] = FALSE; if (MouseX < TALK_NAME_LEFT) return; if (MouseY < TALK_NAME_TOP) return; if (MouseX > TALK_NAME_LEFT + TALK_NAME_WDT) return; if (MouseY > TALK_NAME_TOP + TALK_NAME_HGT) return; int pnum = (MouseY - TALK_NAME_TOP) / 18; for (i = 0; (i < MAX_PLRS) && (pnum != -1); i++) //if ((i != myplr) && plr[i].plractive) pnum--; if (i != myplr) pnum--; if (i <= MAX_PLRS) sgbPlrTalkTbl[i - 1] = !sgbPlrTalkTbl[i - 1]; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void TalkStart() { if (gbMaxPlayers == 1) return; talkflag = TRUE; talkofs = 144; sgszTalkMsg[0] = 0; tspin = 1; for (int i = 0; i < 3; i++) talkbtndown[i] = FALSE; force_redraw = FULLDRAW; // reset history position sgbTalkSavePos = sgbNextTalkSave; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void TalkEnd() { talkflag = FALSE; talkofs = 0; force_redraw = FULLDRAW; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static void TalkSendMsg() { if (sgszTalkMsg[0] != 0) { // send message to all players who have flag set DWORD sendmask = 0; for (int i = 0; i < MAX_PLRS; i++) if (sgbPlrTalkTbl[i]) sendmask |= 1 << i; NetSendString(sendmask,sgszTalkMsg); // save msg in history buffer if it is unique for (i = 0; i < MAX_TALK_SAVES; i++) { if (! strcmp(sgszTalkSaveMsg[i],sgszTalkMsg)) break; } if (i >= MAX_TALK_SAVES) { // string is unique -- save in history buffer strcpy(sgszTalkSaveMsg[sgbNextTalkSave],sgszTalkMsg); sgbNextTalkSave++; sgbNextTalkSave &= MAX_TALK_SAVES - 1; } else { // string is not unique -- swap curr string with non-unique BYTE bTemp = sgbNextTalkSave - 1; bTemp &= MAX_TALK_SAVES - 1; if (i != bTemp) { strcpy(sgszTalkSaveMsg[i],sgszTalkSaveMsg[bTemp]); strcpy(sgszTalkSaveMsg[bTemp],sgszTalkMsg); } } // reset history position sgbTalkSavePos = sgbNextTalkSave; // reset talk string sgszTalkMsg[0] = 0; } TalkEnd(); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ BOOL Talk_wm_char(WPARAM wKey) { if (gbMaxPlayers == 1) return FALSE; if (! talkflag) return FALSE; if (wKey < 32) return FALSE; int i = strlen(sgszTalkMsg); if (i < (MAX_SEND_STR_LEN-2)) { sgszTalkMsg[i] = (char) wKey; sgszTalkMsg[i+1] = 0; } return TRUE; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static void talk_history(int nDelta) { for (int i = 0; i < MAX_TALK_SAVES; i++) { sgbTalkSavePos += nDelta; sgbTalkSavePos &= MAX_TALK_SAVES - 1; if (! sgszTalkSaveMsg[sgbTalkSavePos][0]) continue; // we found a string in the history strcpy(sgszTalkMsg,sgszTalkSaveMsg[sgbTalkSavePos]); break; } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ BOOL Talk_wm_keydown(WPARAM wKey) { // only in multiplayer if (gbMaxPlayers == 1) return FALSE; if (! talkflag) return FALSE; if (wKey == VK_SPACE) { // grab keystroke so // program doesn't get it } else if (wKey == VK_ESCAPE) { TalkEnd(); } else if (wKey == VK_RETURN) { TalkSendMsg(); } else if (wKey == VK_BACK) { int i = strlen(sgszTalkMsg); if (i > 0) sgszTalkMsg[i-1] = 0; } else if (wKey == VK_DOWN) { talk_history(+1); } else if (wKey == VK_UP) { talk_history(-1); } else { return FALSE; } return TRUE; } //****************************************************************** // conversion table -- converts funky ANSI/OEM chars to ASCII // NOTE: only '\0' is allowed to translate to zero // map all other characters into range 32..127 //****************************************************************** const BYTE gbFontTransTbl[256] = { // control characters 0, 1, 1, 1, 1, 1, 1, 1, // 0x00 - 0x07 1, 1, 1, 1, 1, 1, 1, 1, // 0x08 - 0x0f 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 - 0x17 1, 1, 1, 1, 1, 1, 1, 1, // 0x18 - 0x1f // punctuation/digits ' ', '!', '"', '#', '$', '%', '&', '\'',// 0x20 - 0x27 '(', ')', '*', '+', ',', '-', '.', '/', // 0x28 - 0x2f '0', '1', '2', '3', '4', '5', '6', '7', // 0x30 - 0x37 '8', '9', ':', ';', '<', '=', '>', '?', // 0x38 - 0x3f // uppercase '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', // 0x40 - 0x47 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', // 0x48 - 0x4f 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', // 0x50 - 0x57 'X', 'Y', 'Z', '[', '\\',']', '^', '_', // 0x58 - 0x5f // lowercase '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', // 0x60 - 0x67 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', // 0x68 - 0x6f 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', // 0x70 - 0x77 'x', 'y', 'z', '{', '|', '}', '~', 1, // 0x78 - 0x7f 'C', 'u', 'e', 'a', 'a', 'a', 'a', 'c', // 0x80 - 0x87 'e', 'e', 'e', 'i', 'i', 'i', 'A', 'A', // 0x88 - 0x8f 'E', 'a', 'A', 'o', 'o', 'o', 'u', 'u', // 0x90 - 0x97 'y', 'O', 'U', 'c', 'L', 'Y', 'P', 'f', // 0x98 - 0x9f 'a', 'i', 'o', 'u', 'n', 'N', 'a', 'o', // 0xa0 - 0xa7 '?', 1, 1, 1, 1, '!', '<', '>', // 0xa8 - 0xaf 'o', '+', '2', '3', '\'','u', 'P', '.', // 0xb0 - 0xb7 ',', '1', '0', '>', 1, 1, 1, '?', // 0xb8 - 0xbf 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'C', // 0xc0 - 0xc7 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', // 0xc8 - 0xcf 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'X', // 0xd0 - 0xd7 '0', 'U', 'U', 'U', 'U', 'Y', 'b', 'B', // 0xd8 - 0xdf 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c', // 0xe0 - 0xe7 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', // 0xe8 - 0xef 'o', 'n', 'o', 'o', 'o', 'o', 'o', '/', // 0xf0 - 0xf7 '0', 'u', 'u', 'u', 'u', 'y', 'b', 'y', // 0xf8 - 0xff };