1
0
Fork 0
mirror of https://github.com/galaxyhaxz/devilution synced 2025-02-23 12:44:54 +00:00
devilution/2020_03_31/Source/control.cpp

2928 lines
60 KiB
C++
Raw Normal View History

2020-11-28 18:24:54 -06:00
#include "diablo.h"
BYTE sgbNextTalkSave; // weak
BYTE sgbTalkSavePos; // weak
void *pDurIcons;
void *pChrButtons;
int drawhpflag; // idb
int dropGoldFlag; // weak
int panbtn[8];
int chrbtn[4];
void *pMultiBtns;
void *pPanelButtons;
void *pChrPanel;
int lvlbtndown; // weak
char sgszTalkSave[8][80];
int dropGoldValue; // idb
int drawmanaflag; // idb
int chrbtnactive; // weak
char sgszTalkMsg[80];
BYTE *pPanelText;
int frame_4B8800; // idb
BYTE *pLifeBuff;
BYTE *pBtmBuff;
void *pTalkBtns;
int pstrjust[4];
int pnumlines; // idb
int pinfoflag; // weak
int talkbtndown[3];
int pSpell; // weak
BYTE *pManaBuff;
char infoclr; // weak
int sgbPlrTalkTbl; // weak // should be char [4]
void *pGBoxBuff;
void *pSBkBtnCel;
char tempstr[256];
char byte_4B894C[4];
int sbooktab; // weak
int pSplType; // weak
int frame; // idb
int initialDropGoldIndex; // idb
int talkflag; // weak
void *pSBkIconCels;
int sbookflag; // weak
int chrflag;
int drawbtnflag; // idb
void *pSpellBkCel;
char infostr[256];
int numpanbtns; // weak
void *pStatusPanel;
char panelstr[4][64];
int panelflag; // weak
BYTE SplTransTbl[256];
int initialDropGoldValue; // idb
void *pSpellCels;
int panbtndown; // weak
void *pTalkPanel; // idb
int spselflag; // weak
const unsigned char fontframe[128] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 54, 44, 57, 58, 56, 55, 47, 40, 41, 59, 39, 50, 37, 51, 52,
36, 27, 28, 29, 30, 31, 32, 33, 34, 35, 48, 49, 60, 38, 61, 53,
62, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 42, 63, 43, 64, 65,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 40, 66, 41, 67, 0
};
const unsigned char fontkern[68] =
{
8, 10, 7, 9, 8, 7, 6, 8, 8, 3,
3, 8, 6, 11, 9, 10, 6, 9, 9, 6,
9, 11, 10, 13, 10, 11, 7, 5, 7, 7,
8, 7, 7, 7, 7, 7, 10, 4, 5, 6,
3, 3, 4, 3, 6, 6, 3, 3, 3, 3,
3, 2, 7, 6, 3, 10, 10, 6, 6, 7,
4, 4, 9, 6, 6, 12, 3, 7
};
const int lineoffset[5][5] =
{
{ SCREENXY(177, 434), BUFFER_WIDTH * 32, BUFFER_WIDTH * 32, BUFFER_WIDTH * 32, 180 + BUFFER_WIDTH * 32 },
{ SCREENXY(177, 422), SCREENXY(177, 446), BUFFER_WIDTH * 32, BUFFER_WIDTH * 32, BUFFER_WIDTH * 32 },
{ SCREENXY(177, 416), SCREENXY(177, 434), SCREENXY(177, 452), BUFFER_WIDTH * 32, BUFFER_WIDTH * 32 },
{ SCREENXY(177, 412), SCREENXY(177, 427), SCREENXY(177, 441), SCREENXY(177, 456), BUFFER_WIDTH * 32 },
{ SCREENXY(177, 410), SCREENXY(177, 422), SCREENXY(177, 434), SCREENXY(177, 446), SCREENXY(177, 457) }
};
const unsigned char gbFontTransTbl[256] =
{
'\0', 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
' ', '!', '\"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', 0x01,
'C', 'u', 'e', 'a', 'a', 'a', 'a', 'c', 'e', 'e', 'e', 'i', 'i', 'i', 'A', 'A',
'E', 'a', 'A', 'o', 'o', 'o', 'u', 'u', 'y', 'O', 'U', 'c', 'L', 'Y', 'P', 'f',
'a', 'i', 'o', 'u', 'n', 'N', 'a', 'o', '?', 0x01, 0x01, 0x01, 0x01, '!', '<', '>',
'o', '+', '2', '3', '\'', 'u', 'P', '.', ',', '1', '0', '>', 0x01, 0x01, 0x01, '?',
'A', 'A', 'A', 'A', 'A', 'A', 'A', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I',
'D', 'N', 'O', 'O', 'O', 'O', 'O', 'X', '0', 'U', 'U', 'U', 'U', 'Y', 'b', 'B',
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i',
'o', 'n', 'o', 'o', 'o', 'o', 'o', '/', '0', 'u', 'u', 'u', 'u', 'y', 'b', 'y'
};
/* data */
char SpellITbl[37] =
{
1, 1, 2, 3, 4, 5, 6, 7, 8, 9,
28, 13, 12, 18, 16, 14, 18, 19, 11, 20,
15, 21, 23, 24, 25, 22, 26, 29, 37, 38,
39, 42, 41, 40, 10, 36, 30
};
int PanBtnPos[8][5] =
{
{ 9, 361, 71, 19, 1 },
{ 9, 387, 71, 19, 0 },
{ 9, 427, 71, 19, 1 },
{ 9, 453, 71, 19, 0 },
{ 560, 361, 71, 19, 1 },
{ 560, 387, 71, 19, 0 },
{ 87, 443, 33, 32, 1 },
{ 527, 443, 33, 32, 1 }
};
char *PanBtnHotKey[8] = { "'c'", "'q'", "Tab", "Esc", "'i'", "'b'", "Enter", NULL };
char *PanBtnStr[8] =
{
"Character Information",
"Quests log",
"Automap",
"Main Menu",
"Inventory",
"Spell book",
"Send Message",
"Player Attack"
};
int attribute_inc_rects[4][4] =
{
{ 137, 138, 41, 22 },
{ 137, 166, 41, 22 },
{ 137, 195, 41, 22 },
{ 137, 223, 41, 22 }
};
int SpellPages[6][7] =
{
{ SPL_NULL, SPL_FIREBOLT, SPL_CBOLT, SPL_HBOLT, SPL_HEAL, SPL_HEALOTHER, SPL_FLAME },
{ SPL_RESURRECT, SPL_FIREWALL, SPL_TELEKINESIS, SPL_LIGHTNING, SPL_TOWN, SPL_FLASH, SPL_STONE },
{ SPL_RNDTELEPORT, SPL_MANASHIELD, SPL_ELEMENT, SPL_FIREBALL, SPL_WAVE, SPL_CHAIN, SPL_GUARDIAN },
{ SPL_NOVA, SPL_GOLEM, SPL_TELEPORT, SPL_APOCA, SPL_BONESPIRIT, SPL_FLARE, SPL_ETHEREALIZE },
{ -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1 }
};
void DrawSpellCel(int xp, int yp, BYTE *pCelBuff, int nCel, int w)
{
BYTE *dst, *tbl, *end;
tbl = SplTransTbl;
/// ASSERT: assert(gpBuffer);
dst = &gpBuffer[xp + PitchTbl[yp]];
#ifdef USE_ASM
__asm {
mov ebx, pCelBuff
mov eax, nCel
shl eax, 2
add ebx, eax
mov eax, [ebx+4]
sub eax, [ebx]
mov end, eax
mov esi, pCelBuff
add esi, [ebx]
mov edi, dst
mov eax, end
add eax, esi
mov end, eax
mov ebx, tbl
label1:
mov edx, w
label2:
xor eax, eax
lodsb
or al, al
js label6
sub edx, eax
mov ecx, eax
shr ecx, 1
jnb label3
lodsb
xlat
stosb
jecxz label5
label3:
shr ecx, 1
jnb label4
lodsw
xlat
ror ax, 8
xlat
ror ax, 8
stosw
jecxz label5
label4:
lodsd
xlat
ror eax, 8
xlat
ror eax, 8
xlat
ror eax, 8
xlat
ror eax, 8
stosd
loop label4
label5:
or edx, edx
jz label7
jmp label2
label6:
neg al
add edi, eax
sub edx, eax
jnz label2
label7:
sub edi, 768
sub edi, w
cmp esi, end
jnz label1
}
#else
int i;
BYTE width;
BYTE *src;
DWORD *pFrameTable;
pFrameTable = (DWORD *)pCelBuff;
src = &pCelBuff[pFrameTable[nCel]];
end = &src[pFrameTable[nCel + 1] - pFrameTable[nCel]];
for(; src != end; dst -= 768 + w) {
for(i = w; i;) {
width = *src++;
if(!(width & 0x80)) {
i -= width;
if(width & 1) {
dst[0] = tbl[src[0]];
src++;
dst++;
}
width >>= 1;
if(width & 1) {
dst[0] = tbl[src[0]];
dst[1] = tbl[src[1]];
src += 2;
dst += 2;
}
width >>= 1;
for(; width; width--) {
dst[0] = tbl[src[0]];
dst[1] = tbl[src[1]];
dst[2] = tbl[src[2]];
dst[3] = tbl[src[3]];
src += 4;
dst += 4;
}
} else {
width = -(char)width;
dst += width;
i -= width;
}
}
}
#endif
}
void SetSpellTrans(char t)
{
int i;
if(t == RSPLTYPE_SKILL) {
for(i = 0; i < 128; i++) {
SplTransTbl[i] = i;
}
}
for(i = 128; i < 256; i++) {
SplTransTbl[i] = i;
}
SplTransTbl[255] = 0;
switch(t) {
case RSPLTYPE_SPELL:
SplTransTbl[PAL8_YELLOW] = PAL16_BLUE + 1;
SplTransTbl[PAL8_YELLOW + 1] = PAL16_BLUE + 3;
SplTransTbl[PAL8_YELLOW + 2] = PAL16_BLUE + 5;
for(i = PAL16_BLUE; i < PAL16_BLUE + 16; i++) {
SplTransTbl[PAL16_BEIGE - PAL16_BLUE + i] = i;
SplTransTbl[PAL16_YELLOW - PAL16_BLUE + i] = i;
SplTransTbl[PAL16_ORANGE - PAL16_BLUE + i] = i;
}
break;
case RSPLTYPE_SCROLL:
SplTransTbl[PAL8_YELLOW] = PAL16_BEIGE + 1;
SplTransTbl[PAL8_YELLOW + 1] = PAL16_BEIGE + 3;
SplTransTbl[PAL8_YELLOW + 2] = PAL16_BEIGE + 5;
for(i = PAL16_BEIGE; i < PAL16_BEIGE + 16; i++) {
SplTransTbl[PAL16_YELLOW - PAL16_BEIGE + i] = i;
SplTransTbl[PAL16_ORANGE - PAL16_BEIGE + i] = i;
}
break;
case RSPLTYPE_CHARGES:
SplTransTbl[PAL8_YELLOW] = PAL16_ORANGE + 1;
SplTransTbl[PAL8_YELLOW + 1] = PAL16_ORANGE + 3;
SplTransTbl[PAL8_YELLOW + 2] = PAL16_ORANGE + 5;
for(i = PAL16_ORANGE; i < PAL16_ORANGE + 16; i++) {
SplTransTbl[PAL16_BEIGE - PAL16_ORANGE + i] = i;
SplTransTbl[PAL16_YELLOW - PAL16_ORANGE + i] = i;
}
break;
case RSPLTYPE_INVALID:
SplTransTbl[PAL8_YELLOW] = PAL16_GRAY + 1;
SplTransTbl[PAL8_YELLOW + 1] = PAL16_GRAY + 3;
SplTransTbl[PAL8_YELLOW + 2] = PAL16_GRAY + 5;
for(i = PAL16_GRAY; i < PAL16_GRAY + 15; i++) {
SplTransTbl[PAL16_BEIGE - PAL16_GRAY + i] = i;
SplTransTbl[PAL16_YELLOW - PAL16_GRAY + i] = i;
SplTransTbl[PAL16_ORANGE - PAL16_GRAY + i] = i;
}
SplTransTbl[PAL16_BEIGE + 15] = 0;
SplTransTbl[PAL16_YELLOW + 15] = 0;
SplTransTbl[PAL16_ORANGE + 15] = 0;
break;
}
}
void DrawSpell()
{
char st, sn;
int sl;
st = plr[myplr]._pRSplType;
sn = plr[myplr]._pRSpell;
sl = plr[myplr]._pSplLvl[sn] + plr[myplr]._pISplLvlAdd;
if(st == RSPLTYPE_SPELL && sn != -1) {
if(!CheckSpell(myplr, sn, st, TRUE)) {
st = RSPLTYPE_INVALID;
}
if(sl <= 0) {
st = RSPLTYPE_INVALID;
}
}
if(currlevel == 0 && st != RSPLTYPE_INVALID && !spelldata[sn].sTownSpell) {
st = RSPLTYPE_INVALID;
}
if(plr[myplr]._pRSpell < 0) {
st = RSPLTYPE_INVALID;
}
SetSpellTrans(st);
if(sn != -1) {
DrawSpellCel(629, 631, (BYTE *)pSpellCels, SpellITbl[sn], 56);
} else {
DrawSpellCel(629, 631, (BYTE *)pSpellCels, 27, 56);
}
}
void DrawSpellList()
{
int x, y, i, j, t, s, c, v, trans, lx, ly, nCel;
__int64 mask, spl;
x = 636;
y = 495;
pSpell = -1;
infostr[0] = '\0';
ClearPanel();
for(t = 0; t < 4; t++) {
switch(t) {
case RSPLTYPE_SKILL:
SetSpellTrans(RSPLTYPE_SKILL);
spl = plr[myplr]._pAblSpells64;
nCel = 46;
break;
case RSPLTYPE_SPELL:
spl = plr[myplr]._pMemSpells64;
nCel = 47;
break;
case RSPLTYPE_SCROLL:
SetSpellTrans(RSPLTYPE_SCROLL);
spl = plr[myplr]._pScrlSpells64;
nCel = 44;
break;
case RSPLTYPE_CHARGES:
SetSpellTrans(RSPLTYPE_CHARGES);
spl = plr[myplr]._pISpells64;
nCel = 45;
break;
}
mask = 1;
for(s = 1; s < 37; s++) {
if(spl & mask) {
if(t == RSPLTYPE_SPELL) {
v = plr[myplr]._pSplLvl[s] + plr[myplr]._pISplLvlAdd;
if(v < 0) {
v = 0;
}
if(v > 0) {
trans = RSPLTYPE_SPELL;
} else {
trans = RSPLTYPE_INVALID;
}
SetSpellTrans(trans);
}
if(currlevel == 0 && !spelldata[s].sTownSpell) {
SetSpellTrans(RSPLTYPE_INVALID);
}
DrawSpellCel(x, y, (BYTE *)pSpellCels, SpellITbl[s], 56);
lx = x - 64;
ly = y - 216;
if(MouseX >= lx && MouseX < lx + 56 && MouseY >= ly && MouseY < ly + 56) {
pSpell = s;
pSplType = t;
DrawSpellCel(x, y, (BYTE *)pSpellCels, nCel, 56);
switch(t) {
case RSPLTYPE_SKILL:
sprintf(infostr, "%s Skill", spelldata[pSpell].sSkillText);
break;
case RSPLTYPE_SPELL:
sprintf(infostr, "%s Spell", spelldata[pSpell].sNameText);
if(pSpell == SPL_HBOLT) {
sprintf(tempstr, "Damages undead only");
AddPanelString(tempstr, TRUE);
}
if(v == 0) {
sprintf(tempstr, "Spell Level 0 - Unusable");
} else {
sprintf(tempstr, "Spell Level %i", v);
}
AddPanelString(tempstr, TRUE);
break;
case RSPLTYPE_SCROLL:
sprintf(infostr, "Scroll of %s", spelldata[pSpell].sNameText);
c = 0;
for(i = 0; i < plr[myplr]._pNumInv; i++) {
if(plr[myplr].InvList[i]._itype != -1
&& (plr[myplr].InvList[i]._iMiscId == IMISC_SCROLL
|| plr[myplr].InvList[i]._iMiscId == IMISC_SCROLLT)
&& plr[myplr].InvList[i]._iSpell == pSpell) {
c++;
}
}
for(i = 0; i < 8; i++) {
if(plr[myplr].SpdList[i]._itype != -1
&& (plr[myplr].SpdList[i]._iMiscId == IMISC_SCROLL
|| plr[myplr].SpdList[i]._iMiscId == IMISC_SCROLLT)
&& plr[myplr].SpdList[i]._iSpell == pSpell) {
c++;
}
}
if(c == 1) {
strcpy(tempstr, "1 Scroll");
} else {
sprintf(tempstr, "%i Scrolls", c);
}
AddPanelString(tempstr, TRUE);
break;
case RSPLTYPE_CHARGES:
sprintf(infostr, "Staff of %s", spelldata[pSpell].sNameText);
if(plr[myplr].InvBody[4]._iCharges == 1) {
strcpy(tempstr, "1 Charge");
} else {
sprintf(tempstr, "%i Charges", plr[myplr].InvBody[4]._iCharges);
}
AddPanelString(tempstr, TRUE);
break;
}
for(j = 0; j < 4; j++) {
if(plr[myplr]._pSplHotKey[j] == pSpell && plr[myplr]._pSplTHotKey[j] == pSplType) {
DrawSpellCel(x, y, (BYTE *)pSpellCels, j + 48, 56);
sprintf(tempstr, "Spell Hot Key #F%i", j + 5);
AddPanelString(tempstr, TRUE);
}
}
}
x -= 56;
if(x == 20) {
x = 636;
y -= 56;
}
}
mask <<= 1;
}
if(spl != 0 && x != 636) {
x -= 56;
}
if(x == 20) {
x = 636;
y -= 56;
}
}
}
void SetSpell()
{
spselflag = 0;
if(pSpell != -1) {
ClearPanel();
force_redraw = 255;
plr[myplr]._pRSpell = pSpell;
plr[myplr]._pRSplType = pSplType;
}
}
void SetSpeedSpell(int slot)
{
int i;
if(pSpell != -1) {
for(i = 0; i < 4; i++) {
if(plr[myplr]._pSplHotKey[i] == pSpell && plr[myplr]._pSplTHotKey[i] == pSplType) {
plr[myplr]._pSplHotKey[i] = -1;
}
}
plr[myplr]._pSplHotKey[slot] = pSpell;
plr[myplr]._pSplTHotKey[slot] = pSplType;
}
}
void ToggleSpell(int slot)
{
__int64 spl;
if(plr[myplr]._pSplHotKey[slot] == -1) {
return;
}
switch(plr[myplr]._pSplTHotKey[slot]) {
case RSPLTYPE_SKILL:
spl = plr[myplr]._pAblSpells64;
break;
case RSPLTYPE_SPELL:
spl = plr[myplr]._pMemSpells64;
break;
case RSPLTYPE_SCROLL:
spl = plr[myplr]._pScrlSpells64;
break;
case RSPLTYPE_CHARGES:
spl = plr[myplr]._pISpells64;
break;
}
if(spl & (__int64)1 << (plr[myplr]._pSplHotKey[slot] - 1)) {
force_redraw = 255;
plr[myplr]._pRSpell = plr[myplr]._pSplHotKey[slot];
plr[myplr]._pRSplType = plr[myplr]._pSplTHotKey[slot];
}
}
void PrintChar(int nOffset, int nCel, char col)
{
/// ASSERT: assert(gpBuffer);
#ifdef USE_ASM
__asm {
mov ebx, pPanelText
mov eax, nCel
shl eax, 2
add ebx, eax
mov edx, [ebx+4]
sub edx, [ebx]
mov esi, pPanelText
add esi, [ebx]
mov edi, gpBuffer
add edi, nOffset
mov ebx, edx
add ebx, esi
xor edx, edx
mov dl, col
cmp edx, COL_WHITE
jz c0_label1
cmp edx, COL_BLUE
jz c1_label1
cmp edx, COL_RED
jz c2_label1
jmp d_label1
// Case 0
c0_label1:
mov edx, 13
c0_label2:
xor eax, eax
lodsb
or al, al
js c0_label6
sub edx, eax
mov ecx, eax
shr ecx, 1
jnb c0_label3
movsb
jecxz c0_label5
c0_label3:
shr ecx, 1
jnb c0_label4
movsw
jecxz c0_label5
c0_label4:
rep movsd
c0_label5:
or edx, edx
jz c0_label7
jmp c0_label2
c0_label6:
neg al
add edi, eax
sub edx, eax
jnz c0_label2
c0_label7:
sub edi, 768 + 13
cmp ebx, esi
jnz c0_label1
jmp labret
// Case 1
c1_label1:
mov edx, 13
c1_label2:
xor eax, eax
lodsb
or al, al
js c1_label6
sub edx, eax
mov ecx, eax
c1_label3:
lodsb
cmp al, PAL16_GRAY + 13
ja c1_label4
cmp al, PAL16_GRAY
jb c1_label5
sub al, PAL16_GRAY - (PAL16_BLUE + 2)
jmp c1_label5
c1_label4:
mov al, PAL16_BLUE + 15
c1_label5:
stosb
loop c1_label3
or edx, edx
jz c1_label7
jmp c1_label2
c1_label6:
neg al
add edi, eax
sub edx, eax
jnz c1_label2
c1_label7:
sub edi, 768 + 13
cmp ebx, esi
jnz c1_label1
jmp labret
// Case 2
c2_label1:
mov edx, 13
c2_label2:
xor eax, eax
lodsb
or al, al
js c2_label5
sub edx, eax
mov ecx, eax
c2_label3:
lodsb
cmp al, PAL16_GRAY
jb c2_label4
sub al, PAL16_GRAY - PAL16_RED
c2_label4:
stosb
loop c2_label3
or edx, edx
jz c2_label6
jmp c2_label2
c2_label5:
neg al
add edi, eax
sub edx, eax
jnz c2_label2
c2_label6:
sub edi, 768 + 13
cmp ebx, esi
jnz c2_label1
jmp labret
// Default
d_label1:
mov edx, 13
d_label2:
xor eax, eax
lodsb
or al, al
js d_label6
sub edx, eax
mov ecx, eax
d_label3:
lodsb
cmp al, PAL16_GRAY
jb d_label5
cmp al, PAL16_GRAY + 14
jnb d_label4
sub al, PAL16_GRAY - (PAL16_YELLOW + 2)
jmp d_label5
d_label4:
mov al, PAL16_YELLOW + 15
d_label5:
stosb
loop d_label3
or edx, edx
jz d_label7
jmp d_label2
d_label6:
neg al
add edi, eax
sub edx, eax
jnz d_label2
d_label7:
sub edi, 768 + 13
cmp ebx, esi
jnz d_label1
labret:
}
#else
int i;
BYTE width, pix;
BYTE *src, *dst, *end;
DWORD *pFrameTable;
pFrameTable = (DWORD *)pPanelText;
src = &pPanelText[pFrameTable[nCel]];
end = &src[pFrameTable[nCel + 1] - pFrameTable[nCel]];
dst = &gpBuffer[nOffset];
switch(col) {
case COL_WHITE:
for(; src != end; dst -= 768 + 13) {
for(i = 13; i;) {
width = *src++;
if(!(width & 0x80)) {
i -= width;
if(width & 1) {
dst[0] = src[0];
src++;
dst++;
}
width >>= 1;
if(width & 1) {
dst[0] = src[0];
dst[1] = src[1];
src += 2;
dst += 2;
}
width >>= 1;
while(width) {
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
src += 4;
dst += 4;
width--;
}
} else {
width = -(char)width;
dst += width;
i -= width;
}
}
}
break;
case COL_BLUE:
for(; src != end; dst -= 768 + 13) {
for(i = 13; i;) {
width = *src++;
if(!(width & 0x80)) {
i -= width;
while(width) {
pix = *src++;
if(pix > PAL16_GRAY + 13) {
pix = PAL16_BLUE + 15;
} else if(pix >= PAL16_GRAY) {
pix -= PAL16_GRAY - (PAL16_BLUE + 2);
}
*dst++ = pix;
width--;
}
} else {
width = -(char)width;
dst += width;
i -= width;
}
}
}
break;
case COL_RED:
for(; src != end; dst -= 768 + 13) {
for(i = 13; i;) {
width = *src++;
if(!(width & 0x80)) {
i -= width;
while(width) {
pix = *src++;
if(pix >= PAL16_GRAY) {
pix -= PAL16_GRAY - PAL16_RED;
}
*dst++ = pix;
width--;
}
} else {
width = -(char)width;
dst += width;
i -= width;
}
}
}
break;
default:
for(; src != end; dst -= 768 + 13) {
for(i = 13; i;) {
width = *src++;
if(!(width & 0x80)) {
i -= width;
while(width) {
pix = *src++;
if(pix >= PAL16_GRAY) {
if(pix >= PAL16_GRAY + 14) {
pix = PAL16_YELLOW + 15;
} else {
pix -= PAL16_GRAY - (PAL16_YELLOW + 2);
}
}
*dst++ = pix;
width--;
}
} else {
width = -(char)width;
dst += width;
i -= width;
}
}
}
break;
}
#endif
}
void AddPanelString(const char *str, BOOL just)
{
strcpy(panelstr[pnumlines], str);
pstrjust[pnumlines] = just;
if(pnumlines < 4) {
pnumlines++;
}
}
void ClearPanel()
{
pnumlines = 0;
pinfoflag = 0;
}
void DrawPanelBox(int x, int y, int w, int h, int sx, int sy)
{
int nSrcOff, nDstOff;
/// ASSERT: assert(gpBuffer);
nSrcOff = x + 640 * y;
nDstOff = sx + 768 * sy;
#ifdef USE_ASM
__asm {
mov esi, pBtmBuff
add esi, nSrcOff
mov edi, gpBuffer
add edi, nDstOff
xor ebx, ebx
mov bx, word ptr w
xor edx, edx
mov dx, word ptr h
label1:
mov ecx, ebx
shr ecx, 1
jnb label2
movsb
jecxz label4
label2:
shr ecx, 1
jnb label3
movsw
jecxz label4
label3:
rep movsd
label4:
add esi, 640
sub esi, ebx
add edi, 768
sub edi, ebx
dec edx
jnz label1
}
#else
int wdt, hgt;
BYTE *src, *dst;
src = &pBtmBuff[nSrcOff];
dst = &gpBuffer[nDstOff];
for(hgt = h; hgt; hgt--, src += 640 - w, dst += 768 - w) {
wdt = w;
if(wdt & 1) {
dst[0] = src[0];
src++;
dst++;
}
wdt >>= 1;
if(wdt & 1) {
dst[0] = src[0];
dst[1] = src[1];
src += 2;
dst += 2;
}
wdt >>= 1;
while(wdt) {
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
src += 4;
dst += 4;
wdt--;
}
}
#endif
}
void SetFlaskHeight(BYTE *pCelBuff, int min, int max, int x, int y)
{
int nSrcOff, nDstOff, w;
/// ASSERT: assert(gpBuffer);
nSrcOff = 88 * min;
nDstOff = x + 768 * y;
w = max - min;
#ifdef USE_ASM
__asm {
mov esi, pCelBuff
add esi, nSrcOff
mov edi, gpBuffer
add edi, nDstOff
mov edx, w
label1:
mov ecx, 88 / 4
rep movsd
add edi, 768 - 88
dec edx
jnz label1
}
#else
BYTE *src, *dst;
src = &pCelBuff[nSrcOff];
dst = &gpBuffer[nDstOff];
for(; w; w--, src += 88, dst += 768) {
memcpy(dst, src, 88);
}
#endif
}
void DrawFlask(BYTE *pCelBuff, int w, int nSrcOff, BYTE *pBuff, int nDstOff, int h)
{
#ifdef USE_ASM
__asm {
mov esi, pCelBuff
add esi, nSrcOff
mov edi, pBuff
add edi, nDstOff
mov edx, h
label1:
mov ecx, 59
label2:
lodsb
or al, al
jz label3
mov [edi], al
label3:
inc edi
loop label2
add esi, w
sub esi, 59
add edi, 768 - 59
dec edx
jnz label1
}
#else
int wdt, hgt;
BYTE *src, *dst;
src = &pCelBuff[nSrcOff];
dst = &pBuff[nDstOff];
for(hgt = h; hgt; hgt--, src += w - 59, dst += 768 - 59) {
for(wdt = 59; wdt; wdt--) {
if(*src != 0) {
*dst = *src;
}
src++;
dst++;
}
}
#endif
}
void DrawLifeFlask()
{
int p;
p = (double)plr[myplr]._pHitPoints / (double)plr[myplr]._pMaxHP * 80.0;
plr[myplr]._pHPPer = p;
if(p > 80) {
p = 80;
}
p = 80 - p;
if(p > 11) {
p = 11;
}
p += 2;
/// ASSERT: assert(gpBuffer);
DrawFlask(pLifeBuff, 88, 13 + 88 * 3, gpBuffer, SCREENXY(109, 339), p);
if(p != 13) {
DrawFlask(pBtmBuff, 640, 109 + (p + 3) * 640, gpBuffer, SCREENXY(109, 339 + p), 13 - p);
}
}
void UpdateLifeFlask()
{
int p;
p = (double)plr[myplr]._pHitPoints / (double)plr[myplr]._pMaxHP * 80.0;
plr[myplr]._pHPPer = p;
if(p > 69) {
p = 69;
} else if(p < 0) {
p = 0;
}
if(p != 69) {
SetFlaskHeight(pLifeBuff, 16, 16 + 69 - p, 96 + SCREEN_X, 352 + SCREEN_Y);
}
if(p != 0) {
DrawPanelBox(96, 16 + 69 - p, 88, p, 96 + SCREEN_X, 352 + 69 - p + SCREEN_Y);
}
}
void DrawManaFlask()
{
int p;
p = plr[myplr]._pManaPer;
if(p > 80) {
p = 80;
}
p = 80 - p;
if(p > 11) {
p = 11;
}
p += 2;
/// ASSERT: assert(gpBuffer);
DrawFlask(pManaBuff, 88, 13 + 88 * 3, gpBuffer, SCREENXY(475, 339), p);
if(p != 13) {
DrawFlask(pBtmBuff, 640, 475 + (p + 3) * 640, gpBuffer, SCREENXY(475, 339 + p), 13 - p);
}
}
void control_update_life_mana()
{
int cm, mm, p;
mm = plr[myplr]._pMaxMana;
cm = plr[myplr]._pMana;
if(mm < 0) {
mm = 0;
}
if(cm < 0) {
cm = 0;
}
if(mm == 0) {
p = 0;
} else {
p = (double)cm / (double)mm * 80.0;
}
plr[myplr]._pManaPer = p;
p = (double)plr[myplr]._pHitPoints / (double)plr[myplr]._pMaxHP * 80.0;
plr[myplr]._pHPPer = p;
}
void UpdateManaFlask()
{
int cm, mm, p;
mm = plr[myplr]._pMaxMana;
cm = plr[myplr]._pMana;
if(mm < 0) {
mm = 0;
}
if(cm < 0) {
cm = 0;
}
if(mm == 0) {
p = 0;
} else {
p = (double)cm / (double)mm * 80.0;
}
plr[myplr]._pManaPer = p;
if(p > 69) {
p = 69;
}
if(p != 69) {
SetFlaskHeight(pManaBuff, 16, 16 + 69 - p, 464 + SCREEN_X, 352 + SCREEN_Y);
}
if(p != 0) {
DrawPanelBox(464, 16 + 69 - p, 88, p, 464 + SCREEN_X, 352 + 69 - p + SCREEN_Y);
}
DrawSpell();
}
void InitControlPan()
{
int i;
/// ASSERT: assert(! pBtmBuff);
if(gbMaxPlayers == 1) {
pBtmBuff = DiabloAllocPtr(0x16800);
memset(pBtmBuff, 0, 0x16800);
} else {
pBtmBuff = DiabloAllocPtr(0x2D000);
memset(pBtmBuff, 0, 0x2D000);
}
pManaBuff = DiabloAllocPtr(88 * 88);
memset(pManaBuff, 0, 88 * 88);
pLifeBuff = DiabloAllocPtr(88 * 88);
memset(pLifeBuff, 0, 88 * 88);
pPanelText = DiabLoad("CtrlPan\\SmalText.CEL", NULL, 'CTRL');
pChrPanel = DiabLoad("Data\\Char.CEL", NULL, 'CTRL');
pSpellCels = DiabLoad("CtrlPan\\SpelIcon.CEL", NULL, 'CTRL');
SetSpellTrans(RSPLTYPE_SKILL);
pStatusPanel = DiabLoad("CtrlPan\\Panel8.CEL", NULL, 'CTRL');
CelDecodeRect((BYTE *)pBtmBuff, 0, 143, 640, (BYTE *)pStatusPanel, 1, 640);
MemFreeDbg(pStatusPanel);
pStatusPanel = DiabLoad("CtrlPan\\P8Bulbs.CEL", NULL, 'CTRL');
CelDecodeRect((BYTE *)pLifeBuff, 0, 87, 88, (BYTE *)pStatusPanel, 1, 88);
CelDecodeRect((BYTE *)pManaBuff, 0, 87, 88, (BYTE *)pStatusPanel, 2, 88);
MemFreeDbg(pStatusPanel);
talkflag = 0;
if(gbMaxPlayers != 1) {
pTalkPanel = DiabLoad("CtrlPan\\TalkPanl.CEL", NULL, 'CTRL');
CelDecodeRect((BYTE *)pBtmBuff, 0, 287, 640, (BYTE *)pTalkPanel, 1, 640);
MemFreeDbg(pTalkPanel);
pMultiBtns = DiabLoad("CtrlPan\\P8But2.CEL", NULL, 'CTRL');
pTalkBtns = DiabLoad("CtrlPan\\TalkButt.CEL", NULL, 'CTRL');
sgbPlrTalkTbl = 0;
sgszTalkMsg[0] = '\0';
for(i = 0; i < 4; i++) {
byte_4B894C[i] = 1;
}
for(i = 0; i < 3; i++) {
talkbtndown[i] = 0;
}
}
panelflag = 0;
lvlbtndown = 0;
pPanelButtons = DiabLoad("CtrlPan\\Panel8bu.CEL", NULL, 'CTRL');
for(i = 0; i < 8; i++) {
panbtn[i] = 0;
}
panbtndown = 0;
if(gbMaxPlayers == 1) {
numpanbtns = 6;
} else {
numpanbtns = 8;
}
pChrButtons = DiabLoad("Data\\CharBut.CEL", NULL, 'CTRL');
for(i = 0; i < 4; i++) {
chrbtn[i] = 0;
}
chrbtnactive = 0;
pDurIcons = DiabLoad("Items\\DurIcons.CEL", NULL, 'CTRL');
strcpy(infostr, "");
ClearPanel();
drawhpflag = 1;
drawmanaflag = 1;
chrflag = 0;
spselflag = 0;
pSpellBkCel = DiabLoad("Data\\SpellBk.CEL", NULL, 'CTRL');
pSBkBtnCel = DiabLoad("Data\\SpellBkB.CEL", NULL, 'CTRL');
pSBkIconCels = DiabLoad("Data\\SpellI2.CEL", NULL, 'CTRL');
sbooktab = 0;
sbookflag = 0;
if(plr[myplr]._pClass == PC_WARRIOR) {
SpellPages[0][0] = SPL_REPAIR;
} else if(plr[myplr]._pClass == PC_ROGUE) {
SpellPages[0][0] = SPL_DISARM;
} else if(plr[myplr]._pClass == PC_SORCERER) {
SpellPages[0][0] = SPL_RECHARGE;
}
pQLogCel = DiabLoad("Data\\Quest.CEL", NULL, 'CTRL');
pGBoxBuff = DiabLoad("CtrlPan\\Golddrop.cel", NULL, 'CTRL');
dropGoldFlag = 0;
dropGoldValue = 0;
initialDropGoldValue = 0;
initialDropGoldIndex = 0;
frame_4B8800 = 1;
}
void DrawCtrlPan()
{
DrawPanelBox(0, sgbPlrTalkTbl + 16, 640, 128, 0 + SCREEN_X, 352 + SCREEN_Y);
DrawInfoBox();
}
void DrawCtrlBtns()
{
int i;
for(i = 0; i < 6; i++) {
if(!panbtn[i]) {
DrawPanelBox(PanBtnPos[i][0], PanBtnPos[i][1] - 336, 71, 20, PanBtnPos[i][0] + SCREEN_X, PanBtnPos[i][1] + SCREEN_Y);
} else {
CelDecodeOnly(PanBtnPos[i][0] + SCREEN_X, PanBtnPos[i][1] + 18 + SCREEN_Y, (BYTE *)pPanelButtons, i + 1, 71);
}
}
if(numpanbtns == 8) {
CelDecodeOnly(87 + SCREEN_X, 474 + SCREEN_Y, (BYTE *)pMultiBtns, panbtn[6] + 1, 33);
if(FriendlyMode) {
CelDecodeOnly(527 + SCREEN_X, 474 + SCREEN_Y, (BYTE *)pMultiBtns, panbtn[7] + 3, 33);
} else {
CelDecodeOnly(527 + SCREEN_X, 474 + SCREEN_Y, (BYTE *)pMultiBtns, panbtn[7] + 5, 33);
}
}
}
void DoSpeedBook()
{
int x, y, cx, cy, t, s;
__int64 spl, mask;
spselflag = 1;
x = 636;
y = 495;
cx = x - 36;
cy = y - 188;
if(plr[myplr]._pRSpell != -1) {
for(t = 0; t < 4; t++) {
switch(t) {
case RSPLTYPE_SKILL:
spl = plr[myplr]._pAblSpells64;
break;
case RSPLTYPE_SPELL:
spl = plr[myplr]._pMemSpells64;
break;
case RSPLTYPE_SCROLL:
spl = plr[myplr]._pScrlSpells64;
break;
case RSPLTYPE_CHARGES:
spl = plr[myplr]._pISpells64;
break;
}
mask = 1;
for(s = 1; s < 37; s++) {
if(spl & mask) {
if(s == plr[myplr]._pRSpell && t == plr[myplr]._pRSplType) {
cx = x - 36;
cy = y - 188;
}
x -= 56;
if(x == 20) {
x = 636;
y -= 56;
}
}
mask <<= 1;
}
if(spl != 0 && x != 636) {
x -= 56;
}
if(x == 20) {
x = 636;
y -= 56;
}
}
}
SetCursorPos(cx, cy);
}
void DoPanBtn()
{
int i, x2, y2;
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) {
panbtn[i] = 1;
drawbtnflag = 1;
panbtndown = 1;
}
}
if(!spselflag && MouseX >= 565 && MouseX < 565 + 56 && MouseY >= 416 && MouseY < 416 + 56) {
DoSpeedBook();
gamemenu_off();
}
}
void control_set_button_down(int btn_id)
{
panbtn[btn_id] = 1;
drawbtnflag = 1;
panbtndown = 1;
}
void control_check_btn_press()
{
int x2, y2;
x2 = PanBtnPos[3][0] + PanBtnPos[3][2];
y2 = PanBtnPos[3][1] + PanBtnPos[3][3];
if(MouseX >= PanBtnPos[3][0] && MouseX <= x2 && MouseY >= PanBtnPos[3][1] && MouseY <= y2) {
control_set_button_down(3);
}
x2 = PanBtnPos[6][0] + PanBtnPos[6][2];
y2 = PanBtnPos[6][1] + PanBtnPos[6][3];
if(MouseX >= PanBtnPos[6][0] && MouseX <= x2 && MouseY >= PanBtnPos[6][1] && MouseY <= y2) {
control_set_button_down(6);
}
}
void DoAutoMap()
{
if(currlevel == 0 && gbMaxPlayers == 1) {
InitDiabloMsg(1);
return;
}
if(!automapflag) {
StartAutomap();
} else {
automapflag = 0;
}
}
void CheckPanelInfo()
{
int i, j, x2, y2, c, s, v;
panelflag = 0;
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 != 7) {
strcpy(infostr, PanBtnStr[i]);
} else if(FriendlyMode) {
strcpy(infostr, "Player friendly");
} else {
strcpy(infostr, "Player attack");
}
if(PanBtnHotKey[i] != 0) {
sprintf(tempstr, "Hotkey : %s", PanBtnHotKey[i]);
AddPanelString(tempstr, TRUE);
}
infoclr = COL_WHITE;
panelflag = 1;
pinfoflag = 1;
}
}
if(!spselflag && MouseX >= 565 && MouseX < 565 + 56 && MouseY >= 416 && MouseY < 416 + 56) {
strcpy(infostr, "Select current spell button");
infoclr = COL_WHITE;
panelflag = 1;
pinfoflag = 1;
strcpy(tempstr, "Hotkey : 's'");
AddPanelString(tempstr, TRUE);
s = plr[myplr]._pRSpell;
if(s != -1) {
switch(plr[myplr]._pRSplType) {
case RSPLTYPE_SKILL:
sprintf(tempstr, "%s Skill", spelldata[s].sSkillText);
AddPanelString(tempstr, TRUE);
break;
case RSPLTYPE_SPELL:
sprintf(tempstr, "%s Spell", spelldata[s].sNameText);
AddPanelString(tempstr, TRUE);
v = plr[myplr]._pSplLvl[s] + 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, TRUE);
break;
case RSPLTYPE_SCROLL:
sprintf(tempstr, "Scroll of %s", spelldata[s].sNameText);
AddPanelString(tempstr, TRUE);
c = 0;
for(j = 0; j < plr[myplr]._pNumInv; j++) {
if(plr[myplr].InvList[j]._itype != -1
&& (plr[myplr].InvList[j]._iMiscId == IMISC_SCROLL
|| plr[myplr].InvList[j]._iMiscId == IMISC_SCROLLT)
&& plr[myplr].InvList[j]._iSpell == s) {
c++;
}
}
for(j = 0; j < 8; j++) {
if(plr[myplr].SpdList[j]._itype != -1
&& (plr[myplr].SpdList[j]._iMiscId == IMISC_SCROLL
|| plr[myplr].SpdList[j]._iMiscId == IMISC_SCROLLT)
&& plr[myplr].SpdList[j]._iSpell == s) {
c++;
}
}
if(c == 1) {
strcpy(tempstr, "1 Scroll");
} else {
sprintf(tempstr, "%i Scrolls", c);
}
AddPanelString(tempstr, TRUE);
break;
case RSPLTYPE_CHARGES:
sprintf(tempstr, "Staff of %s", spelldata[s].sNameText);
AddPanelString(tempstr, TRUE);
if(plr[myplr].InvBody[4]._iCharges == 1) {
strcpy(tempstr, "1 Charge");
} else {
sprintf(tempstr, "%i Charges", plr[myplr].InvBody[4]._iCharges);
}
AddPanelString(tempstr, TRUE);
break;
}
}
}
if(MouseX > 190 && MouseX < 437 && MouseY > 356 && MouseY < 385) {
pcursinvitem = CheckInvHLight();
}
}
void CheckBtnUp()
{
int i;
BOOLEAN menu;
menu = TRUE;
drawbtnflag = 1;
panbtndown = 0;
for(i = 0; i < 8; i++) {
if(!panbtn[i]) {
continue;
}
panbtn[i] = 0;
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 PANBTN_CHARINFO:
questlog = 0;
chrflag = !chrflag;
break;
case PANBTN_QLOG:
chrflag = 0;
if(!questlog) {
StartQuestlog();
} else {
questlog = 0;
}
break;
case PANBTN_AUTOMAP:
DoAutoMap();
break;
case PANBTN_MAINMENU:
qtextflag = 0;
gamemenu_handle_previous();
menu = FALSE;
break;
case PANBTN_INVENTORY:
sbookflag = 0;
invflag = !invflag;
if(dropGoldFlag) {
dropGoldFlag = 0;
dropGoldValue = 0;
}
break;
case PANBTN_SPELLBOOK:
invflag = 0;
if(dropGoldFlag) {
dropGoldFlag = 0;
dropGoldValue = 0;
}
sbookflag = !sbookflag;
break;
case PANBTN_SENDMSG:
if(talkflag) {
control_reset_talk();
} else {
control_type_message();
}
break;
case PANBTN_FRIENDLY:
FriendlyMode = !FriendlyMode;
break;
}
}
if(menu) {
gamemenu_off();
}
}
void FreeControlPan()
{
MemFreeDbg(pBtmBuff);
MemFreeDbg(pManaBuff);
MemFreeDbg(pLifeBuff);
MemFreeDbg(pPanelText);
MemFreeDbg(pChrPanel);
MemFreeDbg(pSpellCels);
MemFreeDbg(pPanelButtons);
MemFreeDbg(pMultiBtns);
MemFreeDbg(pTalkBtns);
MemFreeDbg(pChrButtons);
MemFreeDbg(pDurIcons);
MemFreeDbg(pQLogCel);
MemFreeDbg(pSpellBkCel);
MemFreeDbg(pSBkBtnCel);
MemFreeDbg(pSBkIconCels);
MemFreeDbg(pGBoxBuff);
}
BOOL control_WriteStringToBuffer(const char *str)
{
int w;
BYTE c;
w = 0;
while(*str != '\0') {
c = gbFontTransTbl[(BYTE)*str];
str++;
w += fontkern[fontframe[c]];
if(w >= 125) {
return FALSE;
}
}
return TRUE;
}
void DrawInfoBox()
{
int nGold;
DrawPanelBox(177, 62, 288, 60, 177 + SCREEN_X, 398 + SCREEN_Y);
if(!panelflag && !trigflag && pcursinvitem == -1 && !spselflag) {
infostr[0] = '\0';
infoclr = COL_WHITE;
ClearPanel();
}
if(spselflag || trigflag) {
infoclr = COL_WHITE;
} else if(pcurs >= CURSOR_FIRSTITEM) {
if(plr[myplr].HoldItem._itype == ITYPE_GOLD) {
nGold = plr[myplr].HoldItem._ivalue;
sprintf(infostr, "%i gold %s", nGold, get_pieces_str(nGold));
} else if(!plr[myplr].HoldItem._iStatFlag) {
ClearPanel();
AddPanelString("Requirements not met", TRUE);
pinfoflag = 1;
} else {
if(plr[myplr].HoldItem._iIdentified) {
strcpy(infostr, plr[myplr].HoldItem._iIName);
} else {
strcpy(infostr, plr[myplr].HoldItem._iName);
}
if(plr[myplr].HoldItem._iMagical == 1) {
infoclr = COL_BLUE;
}
if(plr[myplr].HoldItem._iMagical == 2) {
infoclr = COL_GOLD;
}
}
} else {
if(pcursitem != -1) {
GetItemStr(pcursitem);
}
if(pcursobj != -1) {
GetObjectStr(pcursobj);
}
if(pcursmonst != -1) {
if(leveltype != DTYPE_TOWN) {
infoclr = COL_WHITE;
strcpy(infostr, monster[pcursmonst].mName);
ClearPanel();
if(monster[pcursmonst]._uniqtype != 0) {
infoclr = COL_GOLD;
PrintUniqueHistory();
} else {
PrintMonstHistory(monster[pcursmonst].MType->mtype);
}
} else {
strcpy(infostr, towner[pcursmonst]._tName);
}
}
if(pcursplr != -1) {
infoclr = COL_GOLD;
strcpy(infostr, plr[pcursplr]._pName);
ClearPanel();
sprintf(tempstr, "Level : %i", plr[pcursplr]._pLevel);
AddPanelString(tempstr, TRUE);
sprintf(tempstr, "Hit Points %i of %i", plr[pcursplr]._pHitPoints >> 6, plr[pcursplr]._pMaxHP >> 6);
AddPanelString(tempstr, TRUE);
}
}
if(infostr[0] != '\0' || pnumlines != 0) {
PrintInfo();
}
}
void PrintInfo()
{
int i, nOffset1, nlines;
if(talkflag) {
return;
}
nOffset1 = 0;
nlines = 1;
if(infostr[0] != '\0') {
CPrintString(0, infostr, TRUE, pnumlines);
nOffset1 = 1;
nlines = 0;
}
for(i = 0; i < pnumlines; i++) {
CPrintString(i + nOffset1, panelstr[i], pstrjust[i], pnumlines - nlines);
}
}
void CPrintString(int No, char *pszStr, BOOL Just, int lines)
{
int nOffset, w, cw;
BYTE c;
char *s;
nOffset = lineoffset[lines][No];
w = 0;
if(Just == TRUE) {
cw = 0;
s = pszStr;
while(*s != '\0') {
c = gbFontTransTbl[(BYTE)*s];
s++;
c = fontframe[c];
cw += fontkern[c] + 2;
}
if(cw < 288) {
w = (288 - cw) >> 1;
}
nOffset += w;
}
while(*pszStr != '\0') {
c = gbFontTransTbl[(BYTE)*pszStr];
pszStr++;
c = fontframe[c];
w += fontkern[c] + 2;
if(c != 0 && w < 288) {
PrintChar(nOffset, c, infoclr);
}
nOffset += fontkern[c] + 2;
}
}
void PrintGameStr(int x, int y, const char *pszStr, int col)
{
int nOffset;
BYTE c;
nOffset = x + SCREEN_X + PitchTbl[y + SCREEN_Y];
while(*pszStr != '\0') {
c = gbFontTransTbl[(BYTE)*pszStr];
pszStr++;
c = fontframe[c];
if(c != 0) {
PrintChar(nOffset, c, col);
}
nOffset += fontkern[c] + 1;
}
}
void DrawChr()
{
int hper, ac, pc;
long mind, maxd;
char c;
char chrstr[64];
CelDecodeOnly(64, 511, (BYTE *)pChrPanel, 1, 320);
ADD_PlrStringXY(20, 32, 151, plr[myplr]._pName, COL_WHITE);
if(plr[myplr]._pClass == PC_WARRIOR) {
ADD_PlrStringXY(168, 32, 299, "Warrior", COL_WHITE);
} else if(plr[myplr]._pClass == PC_ROGUE) {
ADD_PlrStringXY(168, 32, 299, "Rogue", COL_WHITE);
} else if(plr[myplr]._pClass == PC_SORCERER) {
ADD_PlrStringXY(168, 32, 299, "Sorceror", COL_WHITE);
}
sprintf(chrstr, "%i", plr[myplr]._pLevel);
ADD_PlrStringXY(66, 69, 109, chrstr, COL_WHITE);
sprintf(chrstr, "%li", plr[myplr]._pExperience);
ADD_PlrStringXY(216, 69, 300, chrstr, COL_WHITE);
if(plr[myplr]._pLevel == 50) {
strcpy(chrstr, "None");
c = COL_GOLD;
} else {
sprintf(chrstr, "%li", plr[myplr]._pNextExper);
c = COL_WHITE;
}
ADD_PlrStringXY(216, 97, 300, chrstr, c);
sprintf(chrstr, "%i", plr[myplr]._pGold);
ADD_PlrStringXY(216, 146, 300, chrstr, COL_WHITE);
c = COL_WHITE;
if(plr[myplr]._pIBonusAC > 0) {
c = COL_BLUE;
}
if(plr[myplr]._pIBonusAC < 0) {
c = COL_RED;
}
ac = plr[myplr]._pIAC + plr[myplr]._pIBonusAC + plr[myplr]._pDexterity / 5;
sprintf(chrstr, "%i", ac);
ADD_PlrStringXY(258, 183, 301, chrstr, c);
c = COL_WHITE;
if(plr[myplr]._pIBonusToHit > 0) {
c = COL_BLUE;
}
if(plr[myplr]._pIBonusToHit < 0) {
c = COL_RED;
}
hper = 50 + plr[myplr]._pIBonusToHit + (plr[myplr]._pDexterity >> 1);
sprintf(chrstr, "%i%%", hper);
ADD_PlrStringXY(258, 211, 301, chrstr, c);
c = COL_WHITE;
if(plr[myplr]._pIBonusDam > 0) {
c = COL_BLUE;
}
if(plr[myplr]._pIBonusDam < 0) {
c = COL_RED;
}
mind = plr[myplr]._pIMinDam;
mind += mind * plr[myplr]._pIBonusDam / 100;
mind += plr[myplr]._pIBonusDamMod;
if(plr[myplr].InvBody[4]._itype == ITYPE_BOW) {
if(plr[myplr]._pClass == PC_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].InvBody[4]._itype == ITYPE_BOW) {
if(plr[myplr]._pClass == PC_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) {
MY_PlrStringXY(254, 239, 305, chrstr, c, -1);
} else {
MY_PlrStringXY(258, 239, 301, chrstr, c, 0);
}
if(plr[myplr]._pMagResist == 0) {
c = COL_WHITE;
} else {
c = COL_BLUE;
}
if(plr[myplr]._pMagResist < 75) {
sprintf(chrstr, "%i%%", plr[myplr]._pMagResist);
} else {
c = COL_GOLD;
sprintf(chrstr, "MAX");
}
ADD_PlrStringXY(257, 276, 300, chrstr, c);
if(plr[myplr]._pFireResist == 0) {
c = COL_WHITE;
} else {
c = COL_BLUE;
}
if(plr[myplr]._pFireResist < 75) {
sprintf(chrstr, "%i%%", plr[myplr]._pFireResist);
} else {
c = COL_GOLD;
sprintf(chrstr, "MAX");
}
ADD_PlrStringXY(257, 304, 300, chrstr, c);
if(plr[myplr]._pLghtResist == 0) {
c = COL_WHITE;
} else {
c = COL_BLUE;
}
if(plr[myplr]._pLghtResist < 75) {
sprintf(chrstr, "%i%%", plr[myplr]._pLghtResist);
} else {
c = COL_GOLD;
sprintf(chrstr, "MAX");
}
ADD_PlrStringXY(257, 332, 300, chrstr, c);
c = COL_WHITE;
sprintf(chrstr, "%i", plr[myplr]._pBaseStr);
if(MaxStats[plr[myplr]._pClass][0] == plr[myplr]._pBaseStr) {
c = COL_GOLD;
}
ADD_PlrStringXY(95, 155, 126, chrstr, c);
c = COL_WHITE;
sprintf(chrstr, "%i", plr[myplr]._pBaseMag);
if(MaxStats[plr[myplr]._pClass][1] == plr[myplr]._pBaseMag) {
c = COL_GOLD;
}
ADD_PlrStringXY(95, 183, 126, chrstr, c);
c = COL_WHITE;
sprintf(chrstr, "%i", plr[myplr]._pBaseDex);
if(MaxStats[plr[myplr]._pClass][2] == plr[myplr]._pBaseDex) {
c = COL_GOLD;
}
ADD_PlrStringXY(95, 211, 126, chrstr, c);
c = COL_WHITE;
sprintf(chrstr, "%i", plr[myplr]._pBaseVit);
if(MaxStats[plr[myplr]._pClass][3] == plr[myplr]._pBaseVit) {
c = COL_GOLD;
}
ADD_PlrStringXY(95, 239, 126, chrstr, c);
c = COL_WHITE;
if(plr[myplr]._pStrength > plr[myplr]._pBaseStr) {
c = COL_BLUE;
}
if(plr[myplr]._pStrength < plr[myplr]._pBaseStr) {
c = COL_RED;
}
sprintf(chrstr, "%i", plr[myplr]._pStrength);
ADD_PlrStringXY(143, 155, 173, chrstr, c);
c = COL_WHITE;
if(plr[myplr]._pMagic > plr[myplr]._pBaseMag) {
c = COL_BLUE;
}
if(plr[myplr]._pMagic < plr[myplr]._pBaseMag) {
c = COL_RED;
}
sprintf(chrstr, "%i", plr[myplr]._pMagic);
ADD_PlrStringXY(143, 183, 173, chrstr, c);
c = COL_WHITE;
if(plr[myplr]._pDexterity > plr[myplr]._pBaseDex) {
c = COL_BLUE;
}
if(plr[myplr]._pDexterity < plr[myplr]._pBaseDex) {
c = COL_RED;
}
sprintf(chrstr, "%i", plr[myplr]._pDexterity);
ADD_PlrStringXY(143, 211, 173, chrstr, c);
c = COL_WHITE;
if(plr[myplr]._pVitality > plr[myplr]._pBaseVit) {
c = COL_BLUE;
}
if(plr[myplr]._pVitality < plr[myplr]._pBaseVit) {
c = COL_RED;
}
sprintf(chrstr, "%i", plr[myplr]._pVitality);
ADD_PlrStringXY(143, 239, 173, chrstr, c);
if(plr[myplr]._pStatPts > 0 && CalcStatDiff(myplr) < plr[myplr]._pStatPts) {
plr[myplr]._pStatPts = CalcStatDiff(myplr);
}
if(plr[myplr]._pStatPts > 0) {
sprintf(chrstr, "%i", plr[myplr]._pStatPts);
ADD_PlrStringXY(95, 266, 126, chrstr, COL_RED);
pc = plr[myplr]._pClass;
if(plr[myplr]._pBaseStr < MaxStats[pc][0]) {
CelDecodeOnly(201, 319, (BYTE *)pChrButtons, chrbtn[0] + 2, 41);
}
if(plr[myplr]._pBaseMag < MaxStats[pc][1]) {
CelDecodeOnly(201, 347, (BYTE *)pChrButtons, chrbtn[1] + 4, 41);
}
if(plr[myplr]._pBaseDex < MaxStats[pc][2]) {
CelDecodeOnly(201, 376, (BYTE *)pChrButtons, chrbtn[2] + 6, 41);
}
if(plr[myplr]._pBaseVit < MaxStats[pc][3]) {
CelDecodeOnly(201, 404, (BYTE *)pChrButtons, chrbtn[3] + 8, 41);
}
}
if(plr[myplr]._pMaxHP > plr[myplr]._pMaxHPBase) {
c = COL_BLUE;
} else {
c = COL_WHITE;
}
sprintf(chrstr, "%i", plr[myplr]._pMaxHP >> 6);
ADD_PlrStringXY(95, 304, 126, chrstr, c);
if(plr[myplr]._pHitPoints != plr[myplr]._pMaxHP) {
c = COL_RED;
}
sprintf(chrstr, "%i", plr[myplr]._pHitPoints >> 6);
ADD_PlrStringXY(143, 304, 174, chrstr, c);
if(plr[myplr]._pMaxMana > plr[myplr]._pMaxManaBase) {
c = COL_BLUE;
} else {
c = COL_WHITE;
}
sprintf(chrstr, "%i", plr[myplr]._pMaxMana >> 6);
ADD_PlrStringXY(95, 332, 126, chrstr, c);
if(plr[myplr]._pMana != plr[myplr]._pMaxMana) {
c = COL_RED;
}
sprintf(chrstr, "%i", plr[myplr]._pMana >> 6);
ADD_PlrStringXY(143, 332, 174, chrstr, c);
}
void ADD_PlrStringXY(int x, int y, int x2, const char *pszStr, char col)
{
int nOffset, width, w, cw;
BYTE c;
const char *s;
nOffset = x + SCREEN_X + PitchTbl[y + SCREEN_Y];
width = x2 - x + 1;
w = 0;
cw = 0;
s = pszStr;
while(*s != '\0') {
c = gbFontTransTbl[(BYTE)*s];
s++;
c = fontframe[c];
cw += fontkern[c] + 1;
}
if(cw < width) {
w = (width - cw) >> 1;
}
nOffset += w;
while(*pszStr != '\0') {
c = gbFontTransTbl[(BYTE)*pszStr];
pszStr++;
c = fontframe[c];
w += fontkern[c] + 1;
if(c != 0 && w < width) {
PrintChar(nOffset, c, col);
}
nOffset += fontkern[c] + 1;
}
}
void MY_PlrStringXY(int x, int y, int x2, const char *pszStr, char col, int base)
{
int nOffset, width, w, cw;
BYTE c;
const char *s;
nOffset = x + SCREEN_X + PitchTbl[y + SCREEN_Y];
width = x2 - x + 1;
w = 0;
cw = 0;
s = pszStr;
while(*s != '\0') {
c = gbFontTransTbl[(BYTE)*s];
s++;
c = fontframe[c];
cw += fontkern[c] + base;
}
if(cw < width) {
w = (width - cw) >> 1;
}
nOffset += w;
while(*pszStr != '\0') {
c = gbFontTransTbl[(BYTE)*pszStr];
pszStr++;
c = fontframe[c];
w += fontkern[c] + base;
if(c != 0 && w < width) {
PrintChar(nOffset, c, col);
}
nOffset += fontkern[c] + base;
}
}
void CheckLvlBtn()
{
if(lvlbtndown) {
return;
}
if(MouseX >= 40 && MouseX <= 81 && MouseY >= 313 && MouseY <= 335) {
lvlbtndown = 1;
}
}
void ReleaseLvlBtn()
{
if(MouseX >= 40 && MouseX <= 81 && MouseY >= 313 && MouseY <= 335) {
chrflag = 1;
}
lvlbtndown = 0;
}
void DrawLevelUpIcon()
{
int nCel;
if(stextflag) {
return;
}
if(lvlbtndown) {
nCel = 3;
} else {
nCel = 2;
}
ADD_PlrStringXY(0, 303, 120, "Level Up", COL_WHITE);
CelDecodeOnly(104, 495, (BYTE *)pChrButtons, nCel, 41);
}
void CheckChrBtns()
{
int i, pc, x2, y2;
if(chrbtnactive) {
return;
}
if(plr[myplr]._pStatPts == 0) {
return;
}
pc = plr[myplr]._pClass;
for(i = 0; i < 4; i++) {
switch(i) {
case 0:
if(plr[myplr]._pBaseStr >= MaxStats[pc][0]) {
continue;
}
break;
case 1:
if(plr[myplr]._pBaseMag >= MaxStats[pc][1]) {
continue;
}
break;
case 2:
if(plr[myplr]._pBaseDex >= MaxStats[pc][2]) {
continue;
}
break;
case 3:
if(plr[myplr]._pBaseVit >= MaxStats[pc][3]) {
continue;
}
break;
default:
continue;
}
x2 = attribute_inc_rects[i][0] + attribute_inc_rects[i][2];
y2 = attribute_inc_rects[i][1] + attribute_inc_rects[i][3];
if(MouseX >= attribute_inc_rects[i][0] && MouseX <= x2
&& MouseY >= attribute_inc_rects[i][1] && MouseY <= y2) {
chrbtn[i] = 1;
chrbtnactive = 1;
}
}
}
void ReleaseChrBtns()
{
int i;
chrbtnactive = 0;
for(i = 0; i < 4; i++) {
if(!chrbtn[i]) {
continue;
}
chrbtn[i] = 0;
if(MouseX < attribute_inc_rects[i][0]) {
continue;
}
if(MouseX > attribute_inc_rects[i][0] + attribute_inc_rects[i][2]) {
continue;
}
if(MouseY < attribute_inc_rects[i][1]) {
continue;
}
if(MouseY > attribute_inc_rects[i][1] + attribute_inc_rects[i][3]) {
continue;
}
switch(i) {
case ATTRIB_STR:
NetSendCmdParam1(TRUE, CMD_ADDSTR, 1);
plr[myplr]._pStatPts--;
break;
case ATTRIB_MAG:
NetSendCmdParam1(TRUE, CMD_ADDMAG, 1);
plr[myplr]._pStatPts--;
break;
case ATTRIB_DEX:
NetSendCmdParam1(TRUE, CMD_ADDDEX, 1);
plr[myplr]._pStatPts--;
break;
case ATTRIB_VIT:
NetSendCmdParam1(TRUE, CMD_ADDVIT, 1);
plr[myplr]._pStatPts--;
break;
}
}
}
void DrawDurIcon()
{
int x;
PlayerStruct *p;
if((chrflag || questlog) && (invflag || sbookflag)) {
return;
}
x = 656;
if(invflag || sbookflag) {
x -= 320;
}
p = &plr[myplr];
x = DrawDurIcon4Item(&p->InvBody[0], x, 4);
x = DrawDurIcon4Item(&p->InvBody[6], x, 3);
x = DrawDurIcon4Item(&p->InvBody[4], x, 0);
x = DrawDurIcon4Item(&p->InvBody[5], x, 0);
}
int DrawDurIcon4Item(const ItemStruct *pItem, int x, int c)
{
if(pItem->_itype == -1) {
return x;
}
if(pItem->_iDurability > 5) {
return x;
}
if(c == 0) {
if(pItem->_iClass == ICLASS_WEAPON) {
switch(pItem->_itype) {
case ITYPE_SWORD:
c = 2;
break;
case ITYPE_AXE:
c = 6;
break;
case ITYPE_BOW:
c = 7;
break;
case ITYPE_MACE:
c = 5;
break;
case ITYPE_STAFF:
c = 8;
break;
}
} else {
c = 1;
}
}
if(pItem->_iDurability > 2) {
c += 8;
}
CelDecodeOnly(x, 495, (BYTE *)pDurIcons, c, 32);
return x - 40;
}
void RedBack()
{
int idx;
if(light4flag) {
idx = 1536;
} else {
idx = 4608;
}
/// ASSERT: assert(gpBuffer);
#ifdef USE_ASM
if(leveltype != DTYPE_HELL) {
__asm {
mov edi, gpBuffer
add edi, SCREENXY(0, 0)
mov ebx, pLightTbl
add ebx, idx
mov edx, 352
lx_label1:
mov ecx, 640
lx_label2:
mov al, [edi]
xlat
stosb
loop lx_label2
add edi, 768 - 640
dec edx
jnz lx_label1
}
} else {
__asm {
mov edi, gpBuffer
add edi, SCREENXY(0, 0)
mov ebx, pLightTbl
add ebx, idx
mov edx, 352
l4_label1:
mov ecx, 640
l4_label2:
mov al, [edi]
cmp al, 32
jb l4_label3
xlat
l4_label3:
stosb
loop l4_label2
add edi, 768 - 640
dec edx
jnz l4_label1
}
}
#else
int w, h;
BYTE *dst, *tbl;
if(leveltype != DTYPE_HELL) {
dst = &gpBuffer[SCREENXY(0, 0)];
tbl = &pLightTbl[idx];
for(h = 352; h != 0; h--, dst += 768 - 640) {
for(w = 640; w != 0; w--) {
*dst = tbl[*dst];
dst++;
}
}
} else {
dst = &gpBuffer[SCREENXY(0, 0)];
tbl = &pLightTbl[idx];
for(h = 352; h != 0; h--, dst += 768 - 640) {
for(w = 640; w != 0; w--) {
if(*dst >= 32) {
*dst = tbl[*dst];
}
dst++;
}
}
}
#endif
}
char GetSBookTrans(int ii, BOOL townok)
{
char st, sl;
st = RSPLTYPE_SPELL;
if(plr[myplr]._pISpells64 & (__int64)1 << (ii - 1)) {
st = RSPLTYPE_CHARGES;
}
if(plr[myplr]._pAblSpells64 & 1 << (ii - 1)) { /// BUGFIX: missing (__int64)
st = RSPLTYPE_SKILL;
}
if(st == RSPLTYPE_SPELL) {
if(!CheckSpell(myplr, ii, RSPLTYPE_SPELL, TRUE)) {
st = RSPLTYPE_INVALID;
}
sl = plr[myplr]._pSplLvl[ii] + plr[myplr]._pISplLvlAdd;
if(sl <= 0) {
st = RSPLTYPE_INVALID;
}
}
if(townok && currlevel == 0 && st != RSPLTYPE_INVALID && !spelldata[ii].sTownSpell) {
st = RSPLTYPE_INVALID;
}
return st;
}
void DrawSpellBook()
{
int i, ii, x, y, mind, maxd, c, v;
char st;
__int64 tspls;
CelDecodeOnly(384, 511, (BYTE *)pSpellBkCel, 1, 320);
x = 76 * sbooktab + 391;
CelDecodeOnly(x, 508, (BYTE *)pSBkBtnCel, sbooktab + 1, 76);
y = 215;
tspls = plr[myplr]._pMemSpells64 | plr[myplr]._pISpells64 | plr[myplr]._pAblSpells64;
for(i = 1; i < 8; i++) { /* redundant, use 'i = 0; i < 7' */
ii = SpellPages[sbooktab][i - 1];
if(ii != -1 && tspls & (__int64)1 << (ii - 1)) {
st = GetSBookTrans(ii, TRUE);
SetSpellTrans(st);
DrawSpellCel(395, y, (BYTE *)pSBkIconCels, SpellITbl[ii], 37);
if(ii == plr[myplr]._pRSpell && st == plr[myplr]._pRSplType) {
SetSpellTrans(RSPLTYPE_SKILL);
DrawSpellCel(395, y, (BYTE *)pSBkIconCels, 43, 37);
}
PrintSBookStr(10, y - 23, FALSE, spelldata[ii].sNameText, COL_WHITE);
st = GetSBookTrans(ii, FALSE);
switch(st) {
case RSPLTYPE_SKILL:
strcpy(tempstr, "Skill");
break;
case RSPLTYPE_CHARGES:
sprintf(tempstr, "Staff (%i charges)", plr[myplr].InvBody[4]._iCharges);
break;
default:
c = GetManaAmount(myplr, ii) >> 6;
GetDamageAmt(ii, &mind, &maxd);
if(mind != -1) {
sprintf(tempstr, "Mana: %i Dam: %i - %i", c, mind, maxd);
} else {
sprintf(tempstr, "Mana: %i Dam: n/a", c);
}
if(ii == SPL_BONESPIRIT) {
sprintf(tempstr, "Mana: %i Dam: 1/3 tgt hp", c);
}
PrintSBookStr(10, y - 1, FALSE, tempstr, COL_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, COL_WHITE);
}
y += 43;
}
}
void PrintSBookStr(int x, int y, BOOL cjustflag, const char *pszStr, char col)
{
int nOffset, w, cw;
BYTE c;
const char *s;
nOffset = x + PitchTbl[y] + 440;
w = 0;
if(cjustflag) {
cw = 0;
s = pszStr;
while(*s != '\0') {
c = gbFontTransTbl[(BYTE)*s];
s++;
c = fontframe[c];
cw += fontkern[c] + 1;
}
if(cw < 222) {
w = (222 - cw) >> 1;
}
nOffset += w;
}
while(*pszStr != '\0') {
c = gbFontTransTbl[(BYTE)*pszStr];
pszStr++;
c = fontframe[c];
w += fontkern[c] + 1;
if(c != 0 && w <= 222) {
PrintChar(nOffset, c, col);
}
nOffset += fontkern[c] + 1;
}
}
void CheckSBook()
{
int ii;
char st;
__int64 tspls;
if(MouseX >= 331 && MouseX < 368 && MouseY >= 18 && MouseY < 314) {
ii = (MouseY - 18) / 43;
ii = SpellPages[sbooktab][ii];
tspls = plr[myplr]._pMemSpells64 | plr[myplr]._pISpells64 | plr[myplr]._pAblSpells64;
if(ii != -1 && tspls & (__int64)1 << (ii - 1)) {
st = RSPLTYPE_SPELL;
if(plr[myplr]._pISpells64 & (__int64)1 << (ii - 1)) {
st = RSPLTYPE_CHARGES;
}
if(plr[myplr]._pAblSpells64 & (__int64)1 << (ii - 1)) {
st = RSPLTYPE_SKILL;
}
plr[myplr]._pRSpell = ii;
plr[myplr]._pRSplType = st;
force_redraw = 255;
}
}
if(MouseX >= 327 && MouseX < 633 && MouseY >= 320 && MouseY < 349) { /// BUGFIX: change `< 633` to `< 631`
sbooktab = (MouseX - 327) / 76;
}
}
const char *get_pieces_str(int nGold)
{
if(nGold == 1) {
return "piece";
} else {
return "pieces";
}
}
void DrawGoldSplit(int amount)
{
int i, sx;
BYTE c;
sx = 0;
CelDecodeOnly(415, 338, (BYTE *)pGBoxBuff, 1, 261);
sprintf(tempstr, "You have %u gold", initialDropGoldValue);
ADD_PlrStringXY(366, 87, 600, tempstr, COL_GOLD);
sprintf(tempstr, "%s. How many do", get_pieces_str(initialDropGoldValue));
ADD_PlrStringXY(366, 103, 600, tempstr, COL_GOLD);
ADD_PlrStringXY(366, 121, 600, "you want to remove?", COL_GOLD);
if(amount > 0) {
sprintf(tempstr, "%u", amount);
PrintGameStr(388, 140, tempstr, COL_WHITE);
for(i = 0; i < tempstr[i]; i++) {
c = gbFontTransTbl[(BYTE)tempstr[i]];
c = fontframe[c];
sx += fontkern[c] + 1;
}
sx += 452;
} else {
sx = 450;
}
CelDecodeOnly(sx, 300, (BYTE *)pSPentSpnCels, frame_4B8800, 12);
frame_4B8800 = (frame_4B8800 & 7) + 1;
}
void control_drop_gold(char vkey)
{
int l, l2;
char split[6];
if(plr[myplr]._pHitPoints >> 6 <= 0) {
dropGoldFlag = 0;
dropGoldValue = 0;
return;
}
memset(split, 0, sizeof(split));
_itoa(dropGoldValue, split, 10);
if(vkey == VK_RETURN) {
if(dropGoldValue > 0) {
control_remove_gold(myplr, initialDropGoldIndex);
}
dropGoldFlag = 0;
return;
}
if(vkey == VK_ESCAPE) {
dropGoldFlag = 0;
dropGoldValue = 0;
return;
}
if(vkey == VK_BACK) {
l = strlen(split);
split[l - 1] = '\0';
dropGoldValue = atoi(split);
return;
}
if(vkey - '0' >= 0 && vkey - '0' <= 9) {
if(dropGoldValue == 0 && atoi(split) > initialDropGoldValue) {
split[0] = vkey;
} else {
l2 = strlen(split);
split[l2] = vkey;
if(atoi(split) > initialDropGoldValue || strlen(split) > strlen(split)) { /// BUGFIX: 'strlen(split) > 5'?
return;
}
}
dropGoldValue = atoi(split);
return;
}
}
void control_remove_gold(int pnum, int ii)
{
int i;
if(ii <= 46) {
i = ii - 7;
plr[pnum].InvList[i]._ivalue -= dropGoldValue;
if(plr[pnum].InvList[i]._ivalue > 0) {
SetGoldCurs(pnum, i);
} else {
RemoveInvItem(pnum, i);
}
} else {
i = ii - 47;
plr[pnum].SpdList[i]._ivalue -= dropGoldValue;
if(plr[pnum].SpdList[i]._ivalue > 0) {
SetSpdbarGoldCurs(pnum, i);
} else {
RemoveSpdBarItem(pnum, i);
}
}
SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD);
GetGoldSeed(pnum, &plr[pnum].HoldItem);
plr[pnum].HoldItem._ivalue = dropGoldValue;
plr[pnum].HoldItem._iStatFlag = 1;
control_set_gold_curs(pnum);
plr[pnum]._pGold = CalculateGold(pnum);
dropGoldValue = 0;
}
void control_set_gold_curs(int pnum)
{
if(plr[pnum].HoldItem._ivalue >= 2500) {
plr[pnum].HoldItem._iCurs = 6;
} else if(plr[pnum].HoldItem._ivalue <= 1000) {
plr[pnum].HoldItem._iCurs = 4;
} else {
plr[pnum].HoldItem._iCurs = 5;
}
SetCursor_(plr[pnum].HoldItem._iCurs + 12);
}
void DrawTalkPan()
{
int i, x, nOffset, btn, col, nCel;
char *s;
if(!talkflag) {
return;
}
/// ASSERT: assert(gpBuffer);
DrawPanelBox(175, sgbPlrTalkTbl + 20, 294, 5, 175 + SCREEN_X, 356 + SCREEN_Y);
for(i = 0; i < 10; i++) {
x = i >> 1;
DrawPanelBox(x + 175, sgbPlrTalkTbl + i + 25, 293 - i, 1, x + 175 + SCREEN_X, i + 361 + SCREEN_Y);
}
DrawPanelBox(185, sgbPlrTalkTbl + 35, 274, 30, 185 + SCREEN_X, 371 + SCREEN_Y);
DrawPanelBox(180, sgbPlrTalkTbl + 65, 284, 5, 180 + SCREEN_X, 401 + SCREEN_Y);
for(i = 0; i < 10; i++) {
DrawPanelBox(180, sgbPlrTalkTbl + i + 70, i + 284, 1, 180 + SCREEN_X, i + 406 + SCREEN_Y);
}
DrawPanelBox(170, sgbPlrTalkTbl + 80, 310, 55, 170 + SCREEN_X, 416 + SCREEN_Y);
s = sgszTalkMsg;
for(i = 0; i < 39; i += 13) {
s = control_print_talk_msg(s, 0, i, &nOffset, COL_WHITE);
if(s == NULL) {
break;
}
}
if(s != NULL) {
s[0] = '\0';
}
CelDecDatOnly(&gpBuffer[nOffset], (BYTE *)pSPentSpnCels, frame, 12);
frame = (frame & 7) + 1;
btn = 0;
for(i = 0; i < MAX_PLRS; i++) {
if(i == myplr) {
continue;
}
if(byte_4B894C[i]) {
col = COL_GOLD;
if(talkbtndown[btn]) {
if(btn == 0) {
nCel = 3;
} else {
nCel = 4;
}
CelDecodeOnly(236, 18 * btn + 596, (BYTE *)pTalkBtns, nCel, 61);
}
} else {
col = COL_RED;
if(btn == 0) {
nCel = 1;
} else {
nCel = 2;
}
if(talkbtndown[btn]) {
nCel += 4;
}
CelDecodeOnly(236, 18 * btn + 596, (BYTE *)pTalkBtns, nCel, 61);
}
if(plr[i].plractive) {
control_print_talk_msg(plr[i]._pName, 46, 18 * btn + 60, &nOffset, col);
}
btn++;
}
}
char *control_print_talk_msg(char *msg, int x, int y, int *pnOffset, int col)
{
int w;
BYTE c;
x += 264;
w = x;
*pnOffset = x + PitchTbl[y + 534];
while(*msg != '\0') {
c = gbFontTransTbl[(BYTE)*msg];
c = fontframe[c];
w += fontkern[c] + 1;
if(w > 514) {
return msg;
}
msg++;
if(c != 0) {
PrintChar(*pnOffset, c, col);
}
*pnOffset += fontkern[c] + 1;
}
return NULL;
}
BOOL control_check_talk_btn()
{
int i;
if(!talkflag) {
return FALSE;
}
if(MouseX < 172) {
return FALSE;
}
if(MouseY < 421) {
return FALSE;
}
if(MouseX > 233) {
return FALSE;
}
if(MouseY > 475) {
return FALSE;
}
for(i = 0; i < 3; i++) {
talkbtndown[i] = 0;
}
i = (MouseY - 421) / 18;
talkbtndown[i] = 1;
return TRUE;
}
void control_release_talk_btn()
{
int i, y;
if(!talkflag) {
return;
}
for(i = 0; i < 3; i++) {
talkbtndown[i] = 0;
}
if(MouseX < 172) {
return;
}
if(MouseY < 421) {
return;
}
if(MouseX > 233) {
return;
}
if(MouseY > 475) {
return;
}
y = (MouseY - 421) / 18;
for(i = 0; i < 4 && y != -1; i++) {
if(i != myplr) {
y--;
}
}
if(i <= 4) {
byte_4B894C[i - 1] = !byte_4B894C[i - 1];
}
}
void control_reset_talk_msg(char *msg)
{
int i, msk;
msk = 0;
for(i = 0; i < 4; i++) {
if(byte_4B894C[i]) {
msk |= 1 << i;
}
}
if(!msgcmd_add_server_cmd_W(sgszTalkMsg)) { /// BUGFIX: supposed to use unused arg 'msg' here?
NetSendCmdString(msk, sgszTalkMsg);
}
}
void control_type_message()
{
int i;
if(gbMaxPlayers == 1) {
return;
}
talkflag = 1;
sgbPlrTalkTbl = 144;
sgszTalkMsg[0] = '\0';
frame = 1;
for(i = 0; i < 3; i++) {
talkbtndown[i] = 0;
}
force_redraw = 255;
sgbTalkSavePos = sgbNextTalkSave;
}
void control_reset_talk()
{
talkflag = 0;
sgbPlrTalkTbl = 0;
force_redraw = 255;
}
BOOL control_talk_last_key(int vkey)
{
int l;
if(gbMaxPlayers == 1) {
return FALSE;
}
if(!talkflag) {
return FALSE;
}
if((DWORD)vkey < VK_SPACE) {
return FALSE;
}
l = strlen(sgszTalkMsg);
if(l < 78) {
sgszTalkMsg[l] = vkey;
sgszTalkMsg[l + 1] = '\0';
}
return TRUE;
}
BOOL control_presskeys(int vkey)
{
int l;
if(gbMaxPlayers == 1) {
return FALSE;
}
if(!talkflag) {
return FALSE;
}
if(vkey == VK_SPACE) {
return TRUE;
}
if(vkey == VK_ESCAPE) {
control_reset_talk();
} else if(vkey == VK_RETURN) {
control_press_enter();
} else if(vkey == VK_BACK) {
l = strlen(sgszTalkMsg);
if(l > 0) {
sgszTalkMsg[l - 1] = '\0';
}
} else if(vkey == VK_DOWN) {
control_up_down(1);
} else if(vkey == VK_UP) {
control_up_down(-1);
} else {
return FALSE;
}
return TRUE;
}
void control_press_enter()
{
int i;
BYTE save;
if(sgszTalkMsg[0] != '\0') {
control_reset_talk_msg(sgszTalkMsg);
for(i = 0; i < 8; i++) {
if(strcmp(sgszTalkSave[i], sgszTalkMsg) == 0) {
break;
}
}
if(i >= 8) {
strcpy(sgszTalkSave[sgbNextTalkSave], sgszTalkMsg);
sgbNextTalkSave = (sgbNextTalkSave + 1) & 7;
} else {
save = (sgbNextTalkSave - 1) & 7;
if(i != save) {
strcpy(sgszTalkSave[i], sgszTalkSave[save]);
strcpy(sgszTalkSave[save], sgszTalkMsg);
}
}
sgbTalkSavePos = sgbNextTalkSave;
sgszTalkMsg[0] = '\0';
}
control_reset_talk();
}
void control_up_down(int v)
{
int i;
for(i = 0; i < 8; i++) {
sgbTalkSavePos = (sgbTalkSavePos + v) & 7;
if(sgszTalkSave[sgbTalkSavePos][0] != '\0') {
strcpy(sgszTalkMsg, sgszTalkSave[sgbTalkSavePos]);
return;
}
}
}