diff --git a/Source/items.cpp b/Source/items.cpp index 007083ba2..d7cb176af 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -1292,6 +1292,11 @@ void GetPlrHandSeed(ItemStruct *h) h->_iSeed = AdvanceRndSeed(); } +/** + * @brief Set a new unique seed value on the given item + * @param pnum Player id + * @param h Item to update + */ void GetGoldSeed(int pnum, ItemStruct *h) { int i, ii, s; diff --git a/Source/stores.cpp b/Source/stores.cpp index c6050bf50..311b1553f 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -8,45 +8,55 @@ DEVILUTION_BEGIN_NAMESPACE -int stextup; -int storenumh; -/** Remember currently selected store item while displaying a dialog */ -int stextlhold; -ItemStruct boyitem; -/** Remember list scoll position while displaying a dialog */ -int stextshold; -ItemStruct premiumitem[SMITH_PREMIUM_ITEMS]; -BYTE *pSTextBoxCels; -int premiumlevel; +namespace { + +/** The current towner being interacted with */ _talker_id talker; -STextStruct stext[STORE_LINES]; -char stextsize; + +/** Is the curren dialog full size */ +bool stextsize; + +/** Number of text lines in the current dialog */ int stextsmax; -ItemStruct storehold[48]; -int gossipstart; -ItemStruct witchitem[WITCH_ITEMS]; -BOOL stextscrl; -int numpremium; -ItemStruct healitem[20]; -ItemStruct golditem; -char storehidx[48]; -BYTE *pSTextSlidCels; -int stextvhold; -/** Currently selected text line */ +/** Remember currently selected text line from stext while displaying a dialog */ +int stextlhold; +/** Currently selected text line from stext */ int stextsel; -char stextscrldbtn; -int gossipend; -BYTE *pSPentSpn2Cels; +/** Text lines */ +STextStruct stext[STORE_LINES]; + +/** Does the current panel have a scrollbar */ +bool stextscrl; +/** Remember last scoll position */ +int stextvhold; /** Scoll position */ int stextsval; -int boylevel; -ItemStruct smithitem[SMITH_ITEMS]; +/** Next scoll position */ int stextdown; +/** Previous scoll position */ +int stextup; +/** Count down for the push state of the scroll up button */ char stextscrlubtn; -char stextflag; +/** Count down for the push state of the scroll down button */ +char stextscrldbtn; + +/** Remember current store while displaying a dialog */ +talk_id stextshold; + +/** Current index into storehidx/storehold */ +int storenumh; +/** Map of inventory items being presented in the store */ +char storehidx[48]; +/** Copies of the players items as presented in the store */ +ItemStruct storehold[48]; + +/** Start of possible gossip dialogs for current store */ +_speech_id gossipstart; +/** End of possible gossip dialogs for current store */ +_speech_id gossipend; /** Maps from towner IDs to NPC names. */ -const char *const talkname[9] = { +const char *const talkname[] = { "Griswold", "Pepin", "", @@ -58,158 +68,13 @@ const char *const talkname[9] = { "Wirt" }; -void InitStores() -{ - int i; - - pSTextBoxCels = LoadFileInMem("Data\\TextBox2.CEL", NULL); - pSPentSpn2Cels = LoadFileInMem("Data\\PentSpn2.CEL", NULL); - pSTextSlidCels = LoadFileInMem("Data\\TextSlid.CEL", NULL); - ClearSText(0, STORE_LINES); - stextflag = STORE_NONE; - stextsize = FALSE; - stextscrl = FALSE; - numpremium = 0; - premiumlevel = 1; - - for (i = 0; i < SMITH_PREMIUM_ITEMS; i++) - premiumitem[i]._itype = ITYPE_NONE; - - boyitem._itype = ITYPE_NONE; - boylevel = 0; -} - -int PentSpn2Spin() -{ - return (SDL_GetTicks() / 50) % 8 + 1; -} - -void SetupTownStores() -{ - int i, l; - - SetRndSeed(glSeedTbl[currlevel] * SDL_GetTicks()); - if (!gbIsMultiplayer) { - l = 0; - for (i = 0; i < NUMLEVELS; i++) { - if (plr[myplr]._pLvlVisited[i]) - l = i; - } - } else { - l = plr[myplr]._pLevel >> 1; - } - l += 2; - if (l < 6) - l = 6; - if (l > 16) - l = 16; - SpawnStoreGold(); - SpawnSmith(l); - SpawnWitch(l); - SpawnHealer(l); - SpawnBoy(plr[myplr]._pLevel); - SpawnPremium(myplr); -} - -void FreeStoreMem() -{ - MemFreeDbg(pSTextBoxCels); - MemFreeDbg(pSPentSpn2Cels); - MemFreeDbg(pSTextSlidCels); -} - -static void DrawSTextBack(CelOutputBuffer out) +void DrawSTextBack(CelOutputBuffer out) { CelDrawTo(out, PANEL_X + 344, 327 + SCREEN_Y + UI_OFFSET_Y, pSTextBoxCels, 1, 271); DrawHalfTransparentRectTo(out, PANEL_X + 347, SCREEN_Y + UI_OFFSET_Y + 28, 265, 297); } -void PrintSString(CelOutputBuffer out, int x, int y, BOOL cjustflag, const char *str, char col, int val) -{ - int len, width, sx, sy, i, k, s; - int xx, yy; - BYTE c; - char valstr[32]; - - s = y * 12 + stext[y]._syoff; - if (stextsize != 0) - xx = PANEL_X + 32; - else - xx = PANEL_X + 352; - sx = xx + x; - sy = s + 44 + SCREEN_Y + UI_OFFSET_Y; - len = strlen(str); - if (stextsize != 0) - yy = 577; - else - yy = 257; - k = 0; - if (cjustflag) { - width = 0; - for (i = 0; i < len; i++) - width += fontkern[fontframe[gbFontTransTbl[(BYTE)str[i]]]] + 1; - if (width < yy) - k = (yy - width) >> 1; - sx += k; - } - if (stextsel == y) { - CelDrawTo(out, cjustflag ? xx + x + k - 20 : xx + x - 20, s + 45 + SCREEN_Y + UI_OFFSET_Y, pSPentSpn2Cels, PentSpn2Spin(), 12); - } - for (i = 0; i < len; i++) { - c = fontframe[gbFontTransTbl[(BYTE)str[i]]]; - k += fontkern[c] + 1; - if (c != 0 && k <= yy) { - PrintChar(out, sx, sy, c, col); - } - sx += fontkern[c] + 1; - } - if (!cjustflag && val >= 0) { - sprintf(valstr, "%i", val); - sx = PANEL_X + 592 - x; - len = strlen(valstr); - for (i = len - 1; i >= 0; i--) { - c = fontframe[gbFontTransTbl[(BYTE)valstr[i]]]; - sx -= fontkern[c] + 1; - if (c != 0) { - PrintChar(out, sx, sy, c, col); - } - } - } - if (stextsel == y) { - CelDrawTo(out, cjustflag ? (xx + x + k + 4) : (PANEL_X + 596 - x), s + 45 + SCREEN_Y + UI_OFFSET_Y, pSPentSpn2Cels, PentSpn2Spin(), 12); - } -} - -void DrawSLine(int y) -{ - int xy, yy, width, line, sy; - - sy = y * 12; - if (stextsize) { - xy = SCREENXY(PANEL_LEFT + 26, 25 + UI_OFFSET_Y); - yy = BUFFER_WIDTH * (sy + 38 + SCREEN_Y + UI_OFFSET_Y) + 26 + PANEL_X; - width = 586 / 4; // BUGFIX: should be 587, not 586 - line = BUFFER_WIDTH - 586; // BUGFIX: should be 587, not 586 - } else { - xy = SCREENXY(PANEL_LEFT + 346, 25 + UI_OFFSET_Y); - yy = BUFFER_WIDTH * (sy + 38 + SCREEN_Y + UI_OFFSET_Y) + 346 + PANEL_X; - width = 266 / 4; // BUGFIX: should be 267, not 266 - line = BUFFER_WIDTH - 266; // BUGFIX: should be 267, not 266 - } - - /// ASSERT: assert(gpBuffer); - - int i; - BYTE *src, *dst; - - src = &gpBuffer[xy]; - dst = &gpBuffer[yy]; - - for (i = 0; i < 3; i++, src += BUFFER_WIDTH, dst += BUFFER_WIDTH) - memcpy(dst, src, BUFFER_WIDTH - line); -} - -static void DrawSSlider(CelOutputBuffer out, int y1, int y2) +void DrawSSlider(CelOutputBuffer out, int y1, int y2) { int yd1, yd2, yd3; @@ -238,28 +103,6 @@ static void DrawSSlider(CelOutputBuffer out, int y1, int y2) CelDrawTo(out, PANEL_X + 601, (y1 + 1) * 12 + 44 + SCREEN_Y + UI_OFFSET_Y + yd3, pSTextSlidCels, 13, 12); } -void DrawSTextHelp() -{ - stextsel = -1; - stextsize = TRUE; -} - -void ClearSText(int s, int e) -{ - int i; - - for (i = s; i < e; i++) { - stext[i]._sx = 0; - stext[i]._syoff = 0; - stext[i]._sstr[0] = 0; - stext[i]._sjust = FALSE; - stext[i]._sclr = COL_WHITE; - stext[i]._sline = 0; - stext[i]._ssel = FALSE; - stext[i]._sval = -1; - } -} - void AddSLine(int y) { stext[y]._sx = 0; @@ -278,7 +121,7 @@ void OffsetSTextY(int y, int yo) stext[y]._syoff = yo; } -void AddSText(int x, int y, BOOL j, const char *str, char clr, BOOL sel) +void AddSText(int x, int y, bool j, const char *str, char clr, BOOL sel) { stext[y]._sx = x; stext[y]._syoff = 0; @@ -289,7 +132,7 @@ void AddSText(int x, int y, BOOL j, const char *str, char clr, BOOL sel) stext[y]._ssel = sel; } -static void PrintStoreItem(ItemStruct *x, int l, char iclr) +void PrintStoreItem(ItemStruct *x, int l, char iclr) { char sstr[128]; char str, dex; @@ -428,8 +271,8 @@ void StoreAutoPlace() void S_StartSmith() { - stextsize = FALSE; - stextscrl = FALSE; + stextsize = false; + stextscrl = false; AddSText(0, 1, TRUE, "Welcome to the", COL_GOLD, FALSE); AddSText(0, 3, TRUE, "Blacksmith's shop", COL_GOLD, FALSE); AddSText(0, 7, TRUE, "Would you like to:", COL_GOLD, FALSE); @@ -476,7 +319,7 @@ void S_ScrollSBuy(int idx) } } - if (!stext[stextsel]._ssel && stextsel != 22) + if (stextsel != -1 && !stext[stextsel]._ssel && stextsel != 22) stextsel = stextdown; } @@ -484,8 +327,8 @@ void S_StartSBuy() { int i; - stextsize = TRUE; - stextscrl = TRUE; + stextsize = true; + stextscrl = true; stextsval = 0; sprintf(tempstr, "I have these items for sale: Your gold: %i", plr[myplr]._pGold); AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE); @@ -534,7 +377,7 @@ void S_ScrollSPBuy(int idx) } idx++; } - if (!stext[stextsel]._ssel && stextsel != 22) + if (stextsel != -1 && !stext[stextsel]._ssel && stextsel != 22) stextsel = stextdown; } @@ -553,8 +396,8 @@ BOOL S_StartSPBuy() return FALSE; } - stextsize = TRUE; - stextscrl = TRUE; + stextsize = true; + stextscrl = true; stextsval = 0; sprintf(tempstr, "I have these premium items for sale: Your gold: %i", plr[myplr]._pGold); @@ -650,7 +493,7 @@ void S_StartSSell() int i; BOOL sellok; - stextsize = TRUE; + stextsize = true; sellok = FALSE; storenumh = 0; @@ -694,7 +537,7 @@ void S_StartSSell() } if (!sellok) { - stextscrl = FALSE; + stextscrl = false; sprintf(tempstr, "You have nothing I want. Your gold: %i", plr[myplr]._pGold); AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE); AddSLine(3); @@ -702,7 +545,7 @@ void S_StartSSell() AddSText(0, 22, TRUE, "Back", COL_WHITE, TRUE); OffsetSTextY(22, 6); } else { - stextscrl = TRUE; + stextscrl = true; stextsval = 0; stextsmax = plr[myplr]._pNumInv; sprintf(tempstr, "Which item is for sale? Your gold: %i", plr[myplr]._pGold); @@ -759,7 +602,7 @@ void S_StartSRepair() BOOL repairok; int i; - stextsize = TRUE; + stextsize = true; repairok = FALSE; storenumh = 0; for (i = 0; i < 48; i++) @@ -789,7 +632,7 @@ void S_StartSRepair() } } if (!repairok) { - stextscrl = FALSE; + stextscrl = false; sprintf(tempstr, "You have nothing to repair. Your gold: %i", plr[myplr]._pGold); AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE); AddSLine(3); @@ -799,7 +642,7 @@ void S_StartSRepair() return; } - stextscrl = TRUE; + stextscrl = true; stextsval = 0; stextsmax = plr[myplr]._pNumInv; sprintf(tempstr, "Repair which item? Your gold: %i", plr[myplr]._pGold); @@ -811,7 +654,7 @@ void S_StartSRepair() OffsetSTextY(22, 6); } -static void FillManaPlayer() +void FillManaPlayer() { if (!sgOptions.Gameplay.bAdriaRefillsMana) return; @@ -826,8 +669,8 @@ static void FillManaPlayer() void S_StartWitch() { FillManaPlayer(); - stextsize = FALSE; - stextscrl = FALSE; + stextsize = false; + stextscrl = false; AddSText(0, 2, TRUE, "Witch's shack", COL_GOLD, FALSE); AddSText(0, 9, TRUE, "Would you like to:", COL_GOLD, FALSE); AddSText(0, 12, TRUE, "Talk to Adria", COL_BLUE, TRUE); @@ -872,7 +715,7 @@ void S_ScrollWBuy(int idx) } } - if (!stext[stextsel]._ssel && stextsel != 22) + if (stextsel != -1 && !stext[stextsel]._ssel && stextsel != 22) stextsel = stextdown; } @@ -880,8 +723,8 @@ void S_StartWBuy() { int i; - stextsize = TRUE; - stextscrl = TRUE; + stextsize = true; + stextscrl = true; stextsval = 0; stextsmax = 20; sprintf(tempstr, "I have these items for sale: Your gold: %i", plr[myplr]._pGold); @@ -933,7 +776,7 @@ void S_StartWSell() int i; BOOL sellok; - stextsize = TRUE; + stextsize = true; sellok = FALSE; storenumh = 0; @@ -977,7 +820,7 @@ void S_StartWSell() } if (!sellok) { - stextscrl = FALSE; + stextscrl = false; sprintf(tempstr, "You have nothing I want. Your gold: %i", plr[myplr]._pGold); AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE); AddSLine(3); @@ -985,7 +828,7 @@ void S_StartWSell() AddSText(0, 22, TRUE, "Back", COL_WHITE, TRUE); OffsetSTextY(22, 6); } else { - stextscrl = TRUE; + stextscrl = true; stextsval = 0; stextsmax = plr[myplr]._pNumInv; sprintf(tempstr, "Which item is for sale? Your gold: %i", plr[myplr]._pGold); @@ -1029,7 +872,7 @@ void S_StartWRecharge() int i; BOOL rechargeok; - stextsize = TRUE; + stextsize = true; rechargeok = FALSE; storenumh = 0; @@ -1053,7 +896,7 @@ void S_StartWRecharge() } if (!rechargeok) { - stextscrl = FALSE; + stextscrl = false; sprintf(tempstr, "You have nothing to recharge. Your gold: %i", plr[myplr]._pGold); AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE); AddSLine(3); @@ -1061,7 +904,7 @@ void S_StartWRecharge() AddSText(0, 22, TRUE, "Back", COL_WHITE, TRUE); OffsetSTextY(22, 6); } else { - stextscrl = TRUE; + stextscrl = true; stextsval = 0; stextsmax = plr[myplr]._pNumInv; sprintf(tempstr, "Recharge which item? Your gold: %i", plr[myplr]._pGold); @@ -1077,8 +920,8 @@ void S_StartWRecharge() void S_StartNoMoney() { StartStore(stextshold); - stextscrl = FALSE; - stextsize = TRUE; + stextscrl = false; + stextsize = true; ClearSText(5, 23); AddSText(0, 14, TRUE, "You do not have enough gold", COL_WHITE, TRUE); } @@ -1086,7 +929,7 @@ void S_StartNoMoney() void S_StartNoRoom() { StartStore(stextshold); - stextscrl = FALSE; + stextscrl = false; ClearSText(5, 23); AddSText(0, 14, TRUE, "You do not have enough room in inventory", COL_WHITE, TRUE); } @@ -1097,7 +940,7 @@ void S_StartConfirm() char iclr; StartStore(stextshold); - stextscrl = FALSE; + stextscrl = false; ClearSText(5, 23); iclr = COL_WHITE; @@ -1159,8 +1002,8 @@ void S_StartConfirm() void S_StartBoy() { - stextsize = FALSE; - stextscrl = FALSE; + stextsize = false; + stextscrl = false; AddSText(0, 2, TRUE, "Wirt the Peg-legged boy", COL_GOLD, FALSE); AddSLine(5); if (!boyitem.isEmpty()) { @@ -1180,8 +1023,8 @@ void S_StartBBoy() { int iclr; - stextsize = TRUE; - stextscrl = FALSE; + stextsize = true; + stextscrl = false; sprintf(tempstr, "I have this item for sale: Your gold: %i", plr[myplr]._pGold); AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE); AddSLine(3); @@ -1206,7 +1049,7 @@ void S_StartBBoy() OffsetSTextY(22, 6); } -static void HealPlayer() +void HealPlayer() { if (plr[myplr]._pHitPoints != plr[myplr]._pMaxHP) { PlaySFX(IS_CAST8); @@ -1219,8 +1062,8 @@ static void HealPlayer() void S_StartHealer() { HealPlayer(); - stextsize = FALSE; - stextscrl = FALSE; + stextsize = false; + stextscrl = false; AddSText(0, 1, TRUE, "Welcome to the", COL_GOLD, FALSE); AddSText(0, 3, TRUE, "Healer's home", COL_GOLD, FALSE); AddSText(0, 9, TRUE, "Would you like to:", COL_GOLD, FALSE); @@ -1253,7 +1096,7 @@ void S_ScrollHBuy(int idx) } } - if (!stext[stextsel]._ssel && stextsel != 22) + if (stextsel != -1 && !stext[stextsel]._ssel && stextsel != 22) stextsel = stextdown; } @@ -1261,8 +1104,8 @@ void S_StartHBuy() { int i; - stextsize = TRUE; - stextscrl = TRUE; + stextsize = true; + stextscrl = true; stextsval = 0; sprintf(tempstr, "I have these items for sale: Your gold: %i", plr[myplr]._pGold); AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE); @@ -1283,8 +1126,8 @@ void S_StartHBuy() void S_StartStory() { - stextsize = FALSE; - stextscrl = FALSE; + stextsize = false; + stextscrl = false; AddSText(0, 2, TRUE, "The Town Elder", COL_GOLD, FALSE); AddSText(0, 9, TRUE, "Would you like to:", COL_GOLD, FALSE); AddSText(0, 12, TRUE, "Talk to Cain", COL_BLUE, TRUE); @@ -1319,7 +1162,7 @@ void S_StartSIdentify() int i; idok = FALSE; - stextsize = TRUE; + stextsize = true; storenumh = 0; for (i = 0; i < 48; i++) @@ -1364,7 +1207,7 @@ void S_StartSIdentify() } if (!idok) { - stextscrl = FALSE; + stextscrl = false; sprintf(tempstr, "You have nothing to identify. Your gold: %i", plr[myplr]._pGold); AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE); AddSLine(3); @@ -1372,7 +1215,7 @@ void S_StartSIdentify() AddSText(0, 22, TRUE, "Back", COL_WHITE, TRUE); OffsetSTextY(22, 6); } else { - stextscrl = TRUE; + stextscrl = true; stextsval = 0; stextsmax = plr[myplr]._pNumInv; sprintf(tempstr, "Identify which item? Your gold: %i", plr[myplr]._pGold); @@ -1390,7 +1233,7 @@ void S_StartIdShow() char iclr; StartStore(stextshold); - stextscrl = FALSE; + stextscrl = false; ClearSText(5, 23); iclr = COL_WHITE; @@ -1409,8 +1252,8 @@ void S_StartTalk() { int i, sn, sn2, la; - stextsize = FALSE; - stextscrl = FALSE; + stextsize = false; + stextscrl = false; sprintf(tempstr, "Talk to %s", talkname[talker]); AddSText(0, 2, TRUE, tempstr, COL_GOLD, FALSE); AddSLine(5); @@ -1452,8 +1295,8 @@ void S_StartTalk() void S_StartTavern() { - stextsize = FALSE; - stextscrl = FALSE; + stextsize = false; + stextscrl = false; AddSText(0, 1, TRUE, "Welcome to the", COL_GOLD, FALSE); AddSText(0, 3, TRUE, "Rising Sun", COL_GOLD, FALSE); AddSText(0, 9, TRUE, "Would you like to:", COL_GOLD, FALSE); @@ -1465,8 +1308,8 @@ void S_StartTavern() void S_StartBarMaid() { - stextsize = FALSE; - stextscrl = FALSE; + stextsize = false; + stextscrl = false; AddSText(0, 2, TRUE, "Gillian", COL_GOLD, FALSE); AddSText(0, 9, TRUE, "Would you like to:", COL_GOLD, FALSE); AddSText(0, 12, TRUE, "Talk to Gillian", COL_BLUE, TRUE); @@ -1477,8 +1320,8 @@ void S_StartBarMaid() void S_StartDrunk() { - stextsize = FALSE; - stextscrl = FALSE; + stextsize = false; + stextscrl = false; AddSText(0, 2, TRUE, "Farnham the Drunk", COL_GOLD, FALSE); AddSText(0, 9, TRUE, "Would you like to:", COL_GOLD, FALSE); AddSText(0, 12, TRUE, "Talk to Farnham", COL_BLUE, TRUE); @@ -1487,714 +1330,750 @@ void S_StartDrunk() storenumh = 20; } -void StartStore(char s) +void S_SmithEnter() { - char t; - int i; + switch (stextsel) { + case 10: + talker = TOWN_SMITH; + stextlhold = 10; + stextshold = STORE_SMITH; + gossipstart = TEXT_GRISWOLD2; + gossipend = TEXT_GRISWOLD13; + StartStore(STORE_GOSSIP); + break; + case 12: + StartStore(STORE_SBUY); + break; + case 14: + StartStore(STORE_SPBUY); + break; + case 16: + StartStore(STORE_SSELL); + break; + case 18: + StartStore(STORE_SREPAIR); + break; + case 20: + stextflag = STORE_NONE; + break; + } +} - for (t = s;; t = STORE_SMITH) { - sbookflag = FALSE; - invflag = FALSE; - chrflag = FALSE; - questlog = FALSE; - dropGoldFlag = FALSE; - ClearSText(0, STORE_LINES); - ReleaseStoreBtn(); - switch (t) { - case STORE_SMITH: - S_StartSmith(); - break; - case STORE_SBUY: - if (storenumh > 0) - S_StartSBuy(); - break; - case STORE_SSELL: - S_StartSSell(); - break; - case STORE_SREPAIR: - S_StartSRepair(); - break; - case STORE_WITCH: - S_StartWitch(); - break; - case STORE_WBUY: - if (storenumh > 0) - S_StartWBuy(); - break; - case STORE_WSELL: - S_StartWSell(); - break; - case STORE_WRECHARGE: - S_StartWRecharge(); - break; - case STORE_NOMONEY: - S_StartNoMoney(); - break; - case STORE_NOROOM: - S_StartNoRoom(); - break; - case STORE_CONFIRM: - S_StartConfirm(); - break; - case STORE_BOY: - S_StartBoy(); - break; - case STORE_BBOY: - S_StartBBoy(); - break; - case STORE_HEALER: - S_StartHealer(); - break; - case STORE_STORY: - S_StartStory(); - break; - case STORE_HBUY: - if (storenumh > 0) - S_StartHBuy(); - break; - case STORE_SIDENTIFY: - S_StartSIdentify(); - break; - case STORE_SPBUY: - if (!S_StartSPBuy()) - return; - break; - case STORE_GOSSIP: - S_StartTalk(); - break; - case STORE_IDSHOW: - S_StartIdShow(); - break; - case STORE_TAVERN: - S_StartTavern(); - break; - case STORE_DRUNK: - S_StartDrunk(); - break; - case STORE_BARMAID: - S_StartBarMaid(); - break; - } +/** + * @brief Purchases an item from the smith. + */ +void SmithBuyItem() +{ + int idx; - for (i = 0; i < STORE_LINES; i++) { - if (stext[i]._ssel) - break; + TakePlrsMoney(plr[myplr].HoldItem._iIvalue); + if (plr[myplr].HoldItem._iMagical == ITEM_QUALITY_NORMAL) + plr[myplr].HoldItem._iIdentified = FALSE; + StoreAutoPlace(); + idx = stextvhold + ((stextlhold - stextup) >> 2); + if (idx == SMITH_ITEMS - 1) { + smithitem[SMITH_ITEMS - 1]._itype = ITYPE_NONE; + } else { + for (; !smithitem[idx + 1].isEmpty(); idx++) { + smithitem[idx] = smithitem[idx + 1]; } - - stextsel = i == STORE_LINES ? -1 : i; - stextflag = t; - if (t != STORE_SBUY || storenumh) - break; + smithitem[idx]._itype = ITYPE_NONE; } + CalcPlrInv(myplr, TRUE); } -void DrawSText(CelOutputBuffer out) +void S_SBuyEnter() { - int i; + int idx, i; + BOOL done; - if (!stextsize) - DrawSTextBack(out); - else - DrawQTextBack(out); + if (stextsel == 22) { + StartStore(STORE_SMITH); + stextsel = 12; + } else { + stextlhold = stextsel; + stextvhold = stextsval; + stextshold = STORE_SBUY; + idx = stextsval + ((stextsel - stextup) >> 2); + if (plr[myplr]._pGold < smithitem[idx]._iIvalue) { + StartStore(STORE_NOMONEY); + } else { + plr[myplr].HoldItem = smithitem[idx]; + SetCursor_(plr[myplr].HoldItem._iCurs + CURSOR_FIRSTITEM); + done = FALSE; - if (stextscrl) { - switch (stextflag) { - case STORE_SBUY: - S_ScrollSBuy(stextsval); - break; - case STORE_SSELL: - case STORE_SREPAIR: - case STORE_WSELL: - case STORE_WRECHARGE: - case STORE_SIDENTIFY: - S_ScrollSSell(stextsval); - break; - case STORE_WBUY: - S_ScrollWBuy(stextsval); - break; - case STORE_HBUY: - S_ScrollHBuy(stextsval); - break; - case STORE_SPBUY: - S_ScrollSPBuy(stextsval); - break; + for (i = 0; i < NUM_INV_GRID_ELEM && !done; i++) { + done = AutoPlace(myplr, i, cursW / 28, cursH / 28, FALSE); + } + if (done) + StartStore(STORE_CONFIRM); + else + StartStore(STORE_NOROOM); + SetCursor_(CURSOR_HAND); } } +} - for (i = 0; i < STORE_LINES; i++) { - if (stext[i]._sline) - DrawSLine(i); - if (stext[i]._sstr[0]) - PrintSString(out, stext[i]._sx, i, stext[i]._sjust, stext[i]._sstr, stext[i]._sclr, stext[i]._sval); +/** + * @brief Purchases a premium item from the smith. + */ +void SmithBuyPItem() +{ + int i, xx, idx; + + TakePlrsMoney(plr[myplr].HoldItem._iIvalue); + if (plr[myplr].HoldItem._iMagical == ITEM_QUALITY_NORMAL) + plr[myplr].HoldItem._iIdentified = FALSE; + StoreAutoPlace(); + + idx = stextvhold + ((stextlhold - stextup) >> 2); + xx = 0; + for (i = 0; idx >= 0; i++) { + if (!premiumitem[i].isEmpty()) { + idx--; + xx = i; + } } - if (stextscrl) - DrawSSlider(out, 4, 20); + premiumitem[xx]._itype = ITYPE_NONE; + numpremium--; + SpawnPremium(myplr); } -void STextESC() +void S_SPBuyEnter() { - if (qtextflag) { - qtextflag = FALSE; - if (leveltype == DTYPE_TOWN) - stream_stop(); + int i, idx, xx; + BOOL done; + + if (stextsel == 22) { + StartStore(STORE_SMITH); + stextsel = 14; } else { - switch (stextflag) { - case STORE_SMITH: - case STORE_WITCH: - case STORE_BOY: - case STORE_BBOY: - case STORE_HEALER: - case STORE_STORY: - case STORE_TAVERN: - case STORE_DRUNK: - case STORE_BARMAID: - stextflag = STORE_NONE; - break; - case STORE_GOSSIP: - StartStore(stextshold); - stextsel = stextlhold; - break; - case STORE_SBUY: - StartStore(STORE_SMITH); - stextsel = 12; - break; - case STORE_SPBUY: - StartStore(STORE_SMITH); - stextsel = 14; - break; - case STORE_SSELL: - StartStore(STORE_SMITH); - stextsel = 16; - break; - case STORE_SREPAIR: - StartStore(STORE_SMITH); - stextsel = 18; - break; - case STORE_WBUY: - StartStore(STORE_WITCH); - stextsel = 14; - break; - case STORE_WSELL: - StartStore(STORE_WITCH); - stextsel = 16; - break; - case STORE_WRECHARGE: - StartStore(STORE_WITCH); - stextsel = 18; - break; - case STORE_HBUY: - StartStore(STORE_HEALER); - stextsel = 16; - break; - case STORE_SIDENTIFY: - StartStore(STORE_STORY); - stextsel = 14; - break; - case STORE_IDSHOW: - StartStore(STORE_SIDENTIFY); - break; - case STORE_NOMONEY: - case STORE_NOROOM: - case STORE_CONFIRM: - StartStore(stextshold); - stextsel = stextlhold; - stextsval = stextvhold; - break; + stextshold = STORE_SPBUY; + stextlhold = stextsel; + stextvhold = stextsval; + xx = stextsval + ((stextsel - stextup) >> 2); + idx = 0; + for (i = 0; xx >= 0; i++) { + if (!premiumitem[i].isEmpty()) { + xx--; + idx = i; + } + } + if (plr[myplr]._pGold < premiumitem[idx]._iIvalue) { + StartStore(STORE_NOMONEY); + } else { + plr[myplr].HoldItem = premiumitem[idx]; + SetCursor_(plr[myplr].HoldItem._iCurs + CURSOR_FIRSTITEM); + done = FALSE; + for (i = 0; i < NUM_INV_GRID_ELEM && !done; i++) { + done = AutoPlace(myplr, i, cursW / 28, cursH / 28, FALSE); + } + if (done) + StartStore(STORE_CONFIRM); + else + StartStore(STORE_NOROOM); + SetCursor_(CURSOR_HAND); } } } -void STextUp() +BOOL StoreGoldFit(int idx) { - PlaySFX(IS_TITLEMOV); - if (stextsel == -1) { - return; - } + int i, sz, cost, numsqrs; - if (stextscrl) { - if (stextsel == stextup) { - if (stextsval) - stextsval--; - return; - } + cost = storehold[idx]._iIvalue; + sz = cost / GOLD_MAX_LIMIT; + if (cost % GOLD_MAX_LIMIT != 0) + sz++; - stextsel--; - while (!stext[stextsel]._ssel) { - if (!stextsel) - stextsel = STORE_LINES - 1; + SetCursor_(storehold[idx]._iCurs + CURSOR_FIRSTITEM); + numsqrs = cursW / 28 * (cursH / 28); + SetCursor_(CURSOR_HAND); + + if (numsqrs >= sz) + return TRUE; + + for (i = 0; i < NUM_INV_GRID_ELEM; i++) { + if (plr[myplr].InvGrid[i] == 0) + numsqrs++; + } + + for (i = 0; i < plr[myplr]._pNumInv; i++) { + if (plr[myplr].InvList[i]._itype == ITYPE_GOLD && plr[myplr].InvList[i]._ivalue != GOLD_MAX_LIMIT) { + if (cost + plr[myplr].InvList[i]._ivalue <= GOLD_MAX_LIMIT) + cost = 0; else - stextsel--; + cost -= GOLD_MAX_LIMIT - plr[myplr].InvList[i]._ivalue; } - return; } - if (!stextsel) - stextsel = STORE_LINES - 1; - else - stextsel--; + sz = cost / GOLD_MAX_LIMIT; + if (cost % GOLD_MAX_LIMIT) + sz++; - while (!stext[stextsel]._ssel) { - if (!stextsel) - stextsel = STORE_LINES - 1; - else - stextsel--; - } + return numsqrs >= sz; } -void STextDown() +/** + * @brief Add gold pile to the players invetory + * @param v The value of the gold pile + */ +void PlaceStoreGold(int v) { - PlaySFX(IS_TITLEMOV); - if (stextsel == -1) { - return; - } + BOOL done; + int ii, xx, yy, i; - if (stextscrl) { - if (stextsel == stextdown) { - if (stextsval < stextsmax) - stextsval++; - return; - } + done = FALSE; - stextsel++; - while (!stext[stextsel]._ssel) { - if (stextsel == STORE_LINES - 1) - stextsel = 0; - else - stextsel++; + for (i = 0; i < NUM_INV_GRID_ELEM && !done; i++) { + yy = 10 * (i / 10); + xx = i % 10; + if (plr[myplr].InvGrid[xx + yy] == 0) { + ii = plr[myplr]._pNumInv; + GetGoldSeed(myplr, &golditem); + plr[myplr].InvList[ii] = golditem; + plr[myplr]._pNumInv++; + plr[myplr].InvGrid[xx + yy] = plr[myplr]._pNumInv; + plr[myplr].InvList[ii]._ivalue = v; + SetGoldCurs(myplr, ii); + done = TRUE; } - return; } +} - if (stextsel == STORE_LINES - 1) - stextsel = 0; +/** + * @brief Sells an item from the player's inventory or belt. + */ +void StoreSellItem() +{ + int i, idx, cost; + + idx = stextvhold + ((stextlhold - stextup) >> 2); + if (storehidx[idx] >= 0) + RemoveInvItem(myplr, storehidx[idx]); else - stextsel++; + RemoveSpdBarItem(myplr, -(storehidx[idx] + 1)); + cost = storehold[idx]._iIvalue; + storenumh--; + if (idx != storenumh) { + while (idx < storenumh) { + storehold[idx] = storehold[idx + 1]; + storehidx[idx] = storehidx[idx + 1]; + idx++; + } + } + plr[myplr]._pGold += cost; + for (i = 0; i < plr[myplr]._pNumInv && cost > 0; i++) { + if (plr[myplr].InvList[i]._itype == ITYPE_GOLD && plr[myplr].InvList[i]._ivalue != GOLD_MAX_LIMIT) { + if (cost + plr[myplr].InvList[i]._ivalue <= GOLD_MAX_LIMIT) { + plr[myplr].InvList[i]._ivalue += cost; + SetGoldCurs(myplr, i); + cost = 0; + } else { + cost -= GOLD_MAX_LIMIT - plr[myplr].InvList[i]._ivalue; + plr[myplr].InvList[i]._ivalue = GOLD_MAX_LIMIT; + SetGoldCurs(myplr, i); + } + } + } + if (cost > 0) { + while (cost > GOLD_MAX_LIMIT) { + PlaceStoreGold(GOLD_MAX_LIMIT); + cost -= GOLD_MAX_LIMIT; + } + PlaceStoreGold(cost); + } +} - while (!stext[stextsel]._ssel) { - if (stextsel == STORE_LINES - 1) - stextsel = 0; +void S_SSellEnter() +{ + int idx; + + if (stextsel == 22) { + StartStore(STORE_SMITH); + stextsel = 16; + } else { + stextlhold = stextsel; + idx = stextsval + ((stextsel - stextup) >> 2); + stextshold = STORE_SSELL; + stextvhold = stextsval; + plr[myplr].HoldItem = storehold[idx]; + + if (StoreGoldFit(idx)) + StartStore(STORE_CONFIRM); else - stextsel++; + StartStore(STORE_NOROOM); } } -void STextPrior() +/** + * @brief Repairs an item in the player's inventory or body in the smith. + */ +void SmithRepairItem() { - PlaySFX(IS_TITLEMOV); - if (stextsel != -1 && stextscrl) { - if (stextsel == stextup) { - if (stextsval) - stextsval -= 4; - stextsval = stextsval; - if (stextsval < 0) - stextsval = 0; - } else { - stextsel = stextup; - } + int i, idx; + + TakePlrsMoney(plr[myplr].HoldItem._iIvalue); + + idx = stextvhold + ((stextlhold - stextup) >> 2); + storehold[idx]._iDurability = storehold[idx]._iMaxDur; + + i = storehidx[idx]; + if (i < 0) { + if (i == -1) + plr[myplr].InvBody[INVLOC_HEAD]._iDurability = plr[myplr].InvBody[INVLOC_HEAD]._iMaxDur; + if (i == -2) + plr[myplr].InvBody[INVLOC_CHEST]._iDurability = plr[myplr].InvBody[INVLOC_CHEST]._iMaxDur; + if (i == -3) + plr[myplr].InvBody[INVLOC_HAND_LEFT]._iDurability = plr[myplr].InvBody[INVLOC_HAND_LEFT]._iMaxDur; + if (i == -4) + plr[myplr].InvBody[INVLOC_HAND_RIGHT]._iDurability = plr[myplr].InvBody[INVLOC_HAND_RIGHT]._iMaxDur; + } else { + plr[myplr].InvList[i]._iDurability = plr[myplr].InvList[i]._iMaxDur; } } -void STextNext() +void S_SRepairEnter() { - PlaySFX(IS_TITLEMOV); - if (stextsel != -1 && stextscrl) { - if (stextsel == stextdown) { - if (stextsval < stextsmax) - stextsval += 4; - if (stextsval > stextsmax) - stextsval = stextsmax; - } else { - stextsel = stextdown; - } + int idx; + + if (stextsel == 22) { + StartStore(STORE_SMITH); + stextsel = 18; + } else { + stextshold = STORE_SREPAIR; + stextlhold = stextsel; + stextvhold = stextsval; + idx = stextsval + ((stextsel - stextup) >> 2); + plr[myplr].HoldItem = storehold[idx]; + if (plr[myplr]._pGold < storehold[idx]._iIvalue) + StartStore(STORE_NOMONEY); + else + StartStore(STORE_CONFIRM); } } -void S_SmithEnter() +void S_WitchEnter() { switch (stextsel) { - case 10: - talker = TOWN_SMITH; - stextlhold = 10; - stextshold = STORE_SMITH; - gossipstart = TEXT_GRISWOLD2; - gossipend = TEXT_GRISWOLD13; - StartStore(STORE_GOSSIP); - break; case 12: - StartStore(STORE_SBUY); - break; + stextlhold = 12; + talker = TOWN_WITCH; + stextshold = STORE_WITCH; + gossipstart = TEXT_ADRIA2; + gossipend = TEXT_ADRIA13; + StartStore(STORE_GOSSIP); + return; case 14: - StartStore(STORE_SPBUY); - break; + StartStore(STORE_WBUY); + return; case 16: - StartStore(STORE_SSELL); - break; + StartStore(STORE_WSELL); + return; case 18: - StartStore(STORE_SREPAIR); - break; + StartStore(STORE_WRECHARGE); + return; case 20: stextflag = STORE_NONE; break; } } -void SetGoldCurs(int pnum, int i) +/** + * @brief Purchases an item from the witch. + */ +void WitchBuyItem() { - SetPlrHandGoldCurs(&plr[pnum].InvList[i]); -} + int idx; -void SetSpdbarGoldCurs(int pnum, int i) -{ - SetPlrHandGoldCurs(&plr[pnum].SpdList[i]); -} + idx = stextvhold + ((stextlhold - stextup) >> 2); -void TakePlrsMoney(int cost) -{ - int i; + if (idx < 3) + plr[myplr].HoldItem._iSeed = AdvanceRndSeed(); - plr[myplr]._pGold = CalculateGold(myplr) - cost; - for (i = 0; i < MAXBELTITEMS && cost > 0; i++) { - if (plr[myplr].SpdList[i]._itype == ITYPE_GOLD && plr[myplr].SpdList[i]._ivalue != GOLD_MAX_LIMIT) { - if (cost < plr[myplr].SpdList[i]._ivalue) { - plr[myplr].SpdList[i]._ivalue -= cost; - SetSpdbarGoldCurs(myplr, i); - cost = 0; - } else { - cost -= plr[myplr].SpdList[i]._ivalue; - RemoveSpdBarItem(myplr, i); - i = -1; + TakePlrsMoney(plr[myplr].HoldItem._iIvalue); + StoreAutoPlace(); + + if (idx >= 3) { + if (idx == WITCH_ITEMS - 1) { + witchitem[WITCH_ITEMS - 1]._itype = ITYPE_NONE; + } else { + for (; !witchitem[idx + 1].isEmpty(); idx++) { + witchitem[idx] = witchitem[idx + 1]; } + witchitem[idx]._itype = ITYPE_NONE; } } - if (cost > 0) { - for (i = 0; i < MAXBELTITEMS && cost > 0; i++) { - if (plr[myplr].SpdList[i]._itype == ITYPE_GOLD) { - if (cost < plr[myplr].SpdList[i]._ivalue) { - plr[myplr].SpdList[i]._ivalue -= cost; - SetSpdbarGoldCurs(myplr, i); - cost = 0; - } else { - cost -= plr[myplr].SpdList[i]._ivalue; - RemoveSpdBarItem(myplr, i); - i = -1; - } + + CalcPlrInv(myplr, TRUE); +} + +void S_WBuyEnter() +{ + int i, idx; + BOOL done; + + if (stextsel == 22) { + StartStore(STORE_WITCH); + stextsel = 14; + } else { + stextlhold = stextsel; + stextvhold = stextsval; + stextshold = STORE_WBUY; + idx = stextsval + ((stextsel - stextup) >> 2); + + if (plr[myplr]._pGold < witchitem[idx]._iIvalue) { + StartStore(STORE_NOMONEY); + } else { + plr[myplr].HoldItem = witchitem[idx]; + SetCursor_(plr[myplr].HoldItem._iCurs + CURSOR_FIRSTITEM); + done = FALSE; + + for (i = 0; i < NUM_INV_GRID_ELEM && !done; i++) { + done = SpecialAutoPlace(myplr, i, plr[myplr].HoldItem); } + + if (done) + StartStore(STORE_CONFIRM); + else + StartStore(STORE_NOROOM); + + SetCursor_(CURSOR_HAND); } } - force_redraw = 255; - if (cost > 0) { - for (i = 0; i < plr[myplr]._pNumInv && cost > 0; i++) { - if (plr[myplr].InvList[i]._itype == ITYPE_GOLD && plr[myplr].InvList[i]._ivalue != GOLD_MAX_LIMIT) { - if (cost < plr[myplr].InvList[i]._ivalue) { - plr[myplr].InvList[i]._ivalue -= cost; - SetGoldCurs(myplr, i); - cost = 0; - } else { - cost -= plr[myplr].InvList[i]._ivalue; - RemoveInvItem(myplr, i); - i = -1; - } - } - } - if (cost > 0) { - for (i = 0; i < plr[myplr]._pNumInv && cost > 0; i++) { - if (plr[myplr].InvList[i]._itype == ITYPE_GOLD) { - if (cost < plr[myplr].InvList[i]._ivalue) { - plr[myplr].InvList[i]._ivalue -= cost; - SetGoldCurs(myplr, i); - cost = 0; - } else { - cost -= plr[myplr].InvList[i]._ivalue; - RemoveInvItem(myplr, i); - i = -1; - } - } - } - } +} + +void S_WSellEnter() +{ + int idx; + + if (stextsel == 22) { + StartStore(STORE_WITCH); + stextsel = 16; + } else { + stextlhold = stextsel; + idx = stextsval + ((stextsel - stextup) >> 2); + stextshold = STORE_WSELL; + stextvhold = stextsval; + plr[myplr].HoldItem = storehold[idx]; + if (StoreGoldFit(idx)) + StartStore(STORE_CONFIRM); + else + StartStore(STORE_NOROOM); } } /** - * @brief Purchases an item from the smith. + * @brief Recharges an item in the player's inventory or body in the witch. */ -void SmithBuyItem() +void WitchRechargeItem() { - int idx; + int i, idx; TakePlrsMoney(plr[myplr].HoldItem._iIvalue); - if (plr[myplr].HoldItem._iMagical == ITEM_QUALITY_NORMAL) - plr[myplr].HoldItem._iIdentified = FALSE; - StoreAutoPlace(); + idx = stextvhold + ((stextlhold - stextup) >> 2); - if (idx == SMITH_ITEMS - 1) { - smithitem[SMITH_ITEMS - 1]._itype = ITYPE_NONE; - } else { - for (; !smithitem[idx + 1].isEmpty(); idx++) { - smithitem[idx] = smithitem[idx + 1]; - } - smithitem[idx]._itype = ITYPE_NONE; - } + storehold[idx]._iCharges = storehold[idx]._iMaxCharges; + + i = storehidx[idx]; + if (i < 0) + plr[myplr].InvBody[INVLOC_HAND_LEFT]._iCharges = plr[myplr].InvBody[INVLOC_HAND_LEFT]._iMaxCharges; + else + plr[myplr].InvList[i]._iCharges = plr[myplr].InvList[i]._iMaxCharges; + CalcPlrInv(myplr, TRUE); } -void S_SBuyEnter() +void S_WRechargeEnter() { - int idx, i; - BOOL done; + int idx; if (stextsel == 22) { - StartStore(STORE_SMITH); - stextsel = 12; + StartStore(STORE_WITCH); + stextsel = 18; } else { + stextshold = STORE_WRECHARGE; stextlhold = stextsel; stextvhold = stextsval; - stextshold = STORE_SBUY; idx = stextsval + ((stextsel - stextup) >> 2); - if (plr[myplr]._pGold < smithitem[idx]._iIvalue) { + plr[myplr].HoldItem = storehold[idx]; + if (plr[myplr]._pGold < storehold[idx]._iIvalue) + StartStore(STORE_NOMONEY); + else + StartStore(STORE_CONFIRM); + } +} + +void S_BoyEnter() +{ + if (!boyitem.isEmpty() && stextsel == 18) { + if (plr[myplr]._pGold < 50) { + stextshold = STORE_BOY; + stextlhold = 18; + stextvhold = stextsval; StartStore(STORE_NOMONEY); } else { - plr[myplr].HoldItem = smithitem[idx]; - SetCursor_(plr[myplr].HoldItem._iCurs + CURSOR_FIRSTITEM); - done = FALSE; - - for (i = 0; i < NUM_INV_GRID_ELEM && !done; i++) { - done = AutoPlace(myplr, i, cursW / 28, cursH / 28, FALSE); - } - if (done) - StartStore(STORE_CONFIRM); - else - StartStore(STORE_NOROOM); - SetCursor_(CURSOR_HAND); + TakePlrsMoney(50); + StartStore(STORE_BBOY); } + } else if (stextsel == 8 && !boyitem.isEmpty() || stextsel == 12 && boyitem.isEmpty()) { + talker = TOWN_PEGBOY; + stextshold = STORE_BOY; + stextlhold = stextsel; + gossipstart = TEXT_WIRT2; + gossipend = TEXT_WIRT12; + StartStore(STORE_GOSSIP); + } else { + stextflag = STORE_NONE; } } +void BoyBuyItem() +{ + TakePlrsMoney(plr[myplr].HoldItem._iIvalue); + StoreAutoPlace(); + boyitem._itype = ITYPE_NONE; + stextshold = STORE_BOY; + CalcPlrInv(myplr, TRUE); +} + /** - * @brief Purchases a premium item from the smith. + * @brief Purchases an item from the healer. */ -void SmithBuyPItem() +void HealerBuyItem() { - int i, xx, idx; + int idx; + + idx = stextvhold + ((stextlhold - stextup) >> 2); + if (!gbIsMultiplayer) { + if (idx < 2) + plr[myplr].HoldItem._iSeed = AdvanceRndSeed(); + } else { + if (idx < 3) + plr[myplr].HoldItem._iSeed = AdvanceRndSeed(); + } TakePlrsMoney(plr[myplr].HoldItem._iIvalue); if (plr[myplr].HoldItem._iMagical == ITEM_QUALITY_NORMAL) plr[myplr].HoldItem._iIdentified = FALSE; StoreAutoPlace(); - idx = stextvhold + ((stextlhold - stextup) >> 2); - xx = 0; - for (i = 0; idx >= 0; i++) { - if (!premiumitem[i].isEmpty()) { - idx--; - xx = i; - } + if (!gbIsMultiplayer) { + if (idx < 2) + return; + } else { + if (idx < 3) + return; } - - premiumitem[xx]._itype = ITYPE_NONE; - numpremium--; - SpawnPremium(myplr); -} - -void S_SPBuyEnter() -{ - int i, idx, xx; - BOOL done; - - if (stextsel == 22) { - StartStore(STORE_SMITH); - stextsel = 14; + idx = stextvhold + ((stextlhold - stextup) >> 2); + if (idx == 19) { + healitem[19]._itype = ITYPE_NONE; } else { - stextshold = STORE_SPBUY; - stextlhold = stextsel; - stextvhold = stextsval; - xx = stextsval + ((stextsel - stextup) >> 2); - idx = 0; - for (i = 0; xx >= 0; i++) { - if (!premiumitem[i].isEmpty()) { - xx--; - idx = i; - } - } - if (plr[myplr]._pGold < premiumitem[idx]._iIvalue) { - StartStore(STORE_NOMONEY); - } else { - plr[myplr].HoldItem = premiumitem[idx]; - SetCursor_(plr[myplr].HoldItem._iCurs + CURSOR_FIRSTITEM); - done = FALSE; - for (i = 0; i < NUM_INV_GRID_ELEM && !done; i++) { - done = AutoPlace(myplr, i, cursW / 28, cursH / 28, FALSE); - } - if (done) - StartStore(STORE_CONFIRM); - else - StartStore(STORE_NOROOM); - SetCursor_(CURSOR_HAND); + for (; !healitem[idx + 1].isEmpty(); idx++) { + healitem[idx] = healitem[idx + 1]; } + healitem[idx]._itype = ITYPE_NONE; } + CalcPlrInv(myplr, TRUE); } -BOOL StoreGoldFit(int idx) +void S_BBuyEnter() { - int i, sz, cost, numsqrs; - - cost = storehold[idx]._iIvalue; - sz = cost / GOLD_MAX_LIMIT; - if (cost % GOLD_MAX_LIMIT != 0) - sz++; - - SetCursor_(storehold[idx]._iCurs + CURSOR_FIRSTITEM); - numsqrs = cursW / 28 * (cursH / 28); - SetCursor_(CURSOR_HAND); + if (stextsel != 10) { + stextflag = STORE_NONE; + return; + } - if (numsqrs >= sz) - return TRUE; + stextshold = STORE_BBOY; + stextvhold = stextsval; + stextlhold = 10; + int price = boyitem._iIvalue; + if (gbIsHellfire) + price -= boyitem._iIvalue >> 2; + else + price += boyitem._iIvalue >> 1; - for (i = 0; i < NUM_INV_GRID_ELEM; i++) { - if (plr[myplr].InvGrid[i] == 0) - numsqrs++; + if (plr[myplr]._pGold < price) { + StartStore(STORE_NOMONEY); + return; } - for (i = 0; i < plr[myplr]._pNumInv; i++) { - if (plr[myplr].InvList[i]._itype == ITYPE_GOLD && plr[myplr].InvList[i]._ivalue != GOLD_MAX_LIMIT) { - if (cost + plr[myplr].InvList[i]._ivalue <= GOLD_MAX_LIMIT) - cost = 0; - else - cost -= GOLD_MAX_LIMIT - plr[myplr].InvList[i]._ivalue; - } + plr[myplr].HoldItem = boyitem; + plr[myplr].HoldItem._iIvalue = price; + SetCursor_(plr[myplr].HoldItem._iCurs + CURSOR_FIRSTITEM); + + bool done = false; + for (int i = 0; i < NUM_INV_GRID_ELEM && !done; i++) { + done = AutoPlace(myplr, i, cursW / 28, cursH / 28, false); } - sz = cost / GOLD_MAX_LIMIT; - if (cost % GOLD_MAX_LIMIT) - sz++; + StartStore(done ? STORE_CONFIRM : STORE_NOROOM); - return numsqrs >= sz; + SetCursor_(CURSOR_HAND); } -void PlaceStoreGold(int v) +void StoryIdItem() { - BOOL done; - int ii, xx, yy, i; - - done = FALSE; + int idx; - for (i = 0; i < NUM_INV_GRID_ELEM && !done; i++) { - yy = 10 * (i / 10); - xx = i % 10; - if (plr[myplr].InvGrid[xx + yy] == 0) { - ii = plr[myplr]._pNumInv; - GetGoldSeed(myplr, &golditem); - plr[myplr].InvList[ii] = golditem; - plr[myplr]._pNumInv++; - plr[myplr].InvGrid[xx + yy] = plr[myplr]._pNumInv; - plr[myplr].InvList[ii]._ivalue = v; - SetGoldCurs(myplr, ii); - done = TRUE; - } + idx = storehidx[((stextlhold - stextup) >> 2) + stextvhold]; + if (idx < 0) { + if (idx == -1) + plr[myplr].InvBody[INVLOC_HEAD]._iIdentified = TRUE; + if (idx == -2) + plr[myplr].InvBody[INVLOC_CHEST]._iIdentified = TRUE; + if (idx == -3) + plr[myplr].InvBody[INVLOC_HAND_LEFT]._iIdentified = TRUE; + if (idx == -4) + plr[myplr].InvBody[INVLOC_HAND_RIGHT]._iIdentified = TRUE; + if (idx == -5) + plr[myplr].InvBody[INVLOC_RING_LEFT]._iIdentified = TRUE; + if (idx == -6) + plr[myplr].InvBody[INVLOC_RING_RIGHT]._iIdentified = TRUE; + if (idx == -7) + plr[myplr].InvBody[INVLOC_AMULET]._iIdentified = TRUE; + } else { + plr[myplr].InvList[idx]._iIdentified = TRUE; } + plr[myplr].HoldItem._iIdentified = TRUE; + TakePlrsMoney(plr[myplr].HoldItem._iIvalue); + CalcPlrInv(myplr, TRUE); } -/** - * @brief Sells an item from the player's inventory or belt. - */ -void StoreSellItem() +void S_ConfirmEnter() { - int i, idx, cost; - - idx = stextvhold + ((stextlhold - stextup) >> 2); - if (storehidx[idx] >= 0) - RemoveInvItem(myplr, storehidx[idx]); - else - RemoveSpdBarItem(myplr, -(storehidx[idx] + 1)); - cost = storehold[idx]._iIvalue; - storenumh--; - if (idx != storenumh) { - while (idx < storenumh) { - storehold[idx] = storehold[idx + 1]; - storehidx[idx] = storehidx[idx + 1]; - idx++; - } - } - plr[myplr]._pGold += cost; - for (i = 0; i < plr[myplr]._pNumInv && cost > 0; i++) { - if (plr[myplr].InvList[i]._itype == ITYPE_GOLD && plr[myplr].InvList[i]._ivalue != GOLD_MAX_LIMIT) { - if (cost + plr[myplr].InvList[i]._ivalue <= GOLD_MAX_LIMIT) { - plr[myplr].InvList[i]._ivalue += cost; - SetGoldCurs(myplr, i); - cost = 0; - } else { - cost -= GOLD_MAX_LIMIT - plr[myplr].InvList[i]._ivalue; - plr[myplr].InvList[i]._ivalue = GOLD_MAX_LIMIT; - SetGoldCurs(myplr, i); - } + if (stextsel == 18) { + switch (stextshold) { + case STORE_SBUY: + SmithBuyItem(); + break; + case STORE_SSELL: + case STORE_WSELL: + StoreSellItem(); + break; + case STORE_SREPAIR: + SmithRepairItem(); + break; + case STORE_WBUY: + WitchBuyItem(); + break; + case STORE_WRECHARGE: + WitchRechargeItem(); + break; + case STORE_BBOY: + BoyBuyItem(); + break; + case STORE_HBUY: + HealerBuyItem(); + break; + case STORE_SIDENTIFY: + StoryIdItem(); + StartStore(STORE_IDSHOW); + return; + case STORE_SPBUY: + SmithBuyPItem(); + break; } } - if (cost > 0) { - while (cost > GOLD_MAX_LIMIT) { - PlaceStoreGold(GOLD_MAX_LIMIT); - cost -= GOLD_MAX_LIMIT; - } - PlaceStoreGold(cost); + + StartStore(stextshold); + + if (stextsel == 22) + return; + + stextsel = stextlhold; + stextsval = std::min(stextvhold, stextsmax); + + while (stextsel != -1 && !stext[stextsel]._ssel) { + stextsel--; } } -void S_SSellEnter() +void S_HealerEnter() { - int idx; + switch (stextsel) { + case 12: + stextlhold = 12; + talker = TOWN_HEALER; + stextshold = STORE_HEALER; + gossipstart = TEXT_PEPIN2; + gossipend = TEXT_PEPIN11; + StartStore(STORE_GOSSIP); + break; + case 14: + StartStore(STORE_HBUY); + break; + case 16: + stextflag = STORE_NONE; + break; + } +} + +void S_HBuyEnter() +{ + int i, idx; + BOOL done; if (stextsel == 22) { - StartStore(STORE_SMITH); + StartStore(STORE_HEALER); stextsel = 16; } else { stextlhold = stextsel; - idx = stextsval + ((stextsel - stextup) >> 2); - stextshold = STORE_SSELL; stextvhold = stextsval; - plr[myplr].HoldItem = storehold[idx]; + stextshold = STORE_HBUY; + idx = stextsval + ((stextsel - stextup) >> 2); - if (StoreGoldFit(idx)) - StartStore(STORE_CONFIRM); - else - StartStore(STORE_NOROOM); - } -} + if (plr[myplr]._pGold < healitem[idx]._iIvalue) { + StartStore(STORE_NOMONEY); + } else { + plr[myplr].HoldItem = healitem[idx]; + SetCursor_(plr[myplr].HoldItem._iCurs + CURSOR_FIRSTITEM); + done = FALSE; -/** - * @brief Repairs an item in the player's inventory or body in the smith. - */ -void SmithRepairItem() -{ - int i, idx; + for (i = 0; i < NUM_INV_GRID_ELEM && !done; i++) { + done = SpecialAutoPlace(myplr, i, plr[myplr].HoldItem); + } - TakePlrsMoney(plr[myplr].HoldItem._iIvalue); + if (done) + StartStore(STORE_CONFIRM); + else + StartStore(STORE_NOROOM); - idx = stextvhold + ((stextlhold - stextup) >> 2); - storehold[idx]._iDurability = storehold[idx]._iMaxDur; + SetCursor_(CURSOR_HAND); + } + } +} - i = storehidx[idx]; - if (i < 0) { - if (i == -1) - plr[myplr].InvBody[INVLOC_HEAD]._iDurability = plr[myplr].InvBody[INVLOC_HEAD]._iMaxDur; - if (i == -2) - plr[myplr].InvBody[INVLOC_CHEST]._iDurability = plr[myplr].InvBody[INVLOC_CHEST]._iMaxDur; - if (i == -3) - plr[myplr].InvBody[INVLOC_HAND_LEFT]._iDurability = plr[myplr].InvBody[INVLOC_HAND_LEFT]._iMaxDur; - if (i == -4) - plr[myplr].InvBody[INVLOC_HAND_RIGHT]._iDurability = plr[myplr].InvBody[INVLOC_HAND_RIGHT]._iMaxDur; - } else { - plr[myplr].InvList[i]._iDurability = plr[myplr].InvList[i]._iMaxDur; +void S_StoryEnter() +{ + switch (stextsel) { + case 12: + stextlhold = 12; + talker = TOWN_STORY; + stextshold = STORE_STORY; + gossipstart = TEXT_STORY2; + gossipend = TEXT_STORY11; + StartStore(STORE_GOSSIP); + break; + case 14: + StartStore(STORE_SIDENTIFY); + break; + case 18: + stextflag = STORE_NONE; + break; } } -void S_SRepairEnter() +void S_SIDEnter() { int idx; if (stextsel == 22) { - StartStore(STORE_SMITH); - stextsel = 18; + StartStore(STORE_STORY); + stextsel = 14; } else { - stextshold = STORE_SREPAIR; + stextshold = STORE_SIDENTIFY; stextlhold = stextsel; stextvhold = stextsval; idx = stextsval + ((stextsel - stextup) >> 2); @@ -2206,525 +2085,677 @@ void S_SRepairEnter() } } -void S_WitchEnter() +void S_TalkEnter() +{ + int i, tq, sn, la; + + if (stextsel == 22) { + StartStore(stextshold); + stextsel = stextlhold; + return; + } + + sn = 0; + for (i = 0; i < MAXQUESTS; i++) { + if (quests[i]._qactive == QUEST_ACTIVE && Qtalklist[talker][i] != TEXT_NONE && quests[i]._qlog) + sn++; + } + if (sn > 6) { + sn = 14 - (sn >> 1); + la = 1; + } else { + sn = 15 - sn; + la = 2; + } + + if (stextsel == sn - 2) { + SetRndSeed(towner[talker]._tSeed); + tq = gossipstart + random_(0, gossipend - gossipstart + 1); + InitQTextMsg(tq); + return; + } + + for (i = 0; i < MAXQUESTS; i++) { + if (quests[i]._qactive == QUEST_ACTIVE && Qtalklist[talker][i] != TEXT_NONE && quests[i]._qlog) { + if (sn == stextsel) { + InitQTextMsg(Qtalklist[talker][i]); + } + sn += la; + } + } +} + +void S_TavernEnter() { switch (stextsel) { case 12: stextlhold = 12; - talker = TOWN_WITCH; - stextshold = STORE_WITCH; - gossipstart = TEXT_ADRIA2; - gossipend = TEXT_ADRIA13; + talker = TOWN_TAVERN; + stextshold = STORE_TAVERN; + gossipstart = TEXT_OGDEN2; + gossipend = TEXT_OGDEN10; StartStore(STORE_GOSSIP); - return; - case 14: - StartStore(STORE_WBUY); - return; - case 16: - StartStore(STORE_WSELL); - return; + break; case 18: - StartStore(STORE_WRECHARGE); - return; - case 20: stextflag = STORE_NONE; break; } } -/** - * @brief Purchases an item from the witch. - */ -void WitchBuyItem() +void S_BarmaidEnter() { - int idx; - - idx = stextvhold + ((stextlhold - stextup) >> 2); - - if (idx < 3) - plr[myplr].HoldItem._iSeed = AdvanceRndSeed(); - - TakePlrsMoney(plr[myplr].HoldItem._iIvalue); - StoreAutoPlace(); + switch (stextsel) { + case 12: + stextlhold = 12; + talker = TOWN_BMAID; + stextshold = STORE_BARMAID; + gossipstart = TEXT_GILLIAN2; + gossipend = TEXT_GILLIAN10; + StartStore(STORE_GOSSIP); + break; + case 18: + stextflag = STORE_NONE; + break; + } +} - if (idx >= 3) { - if (idx == WITCH_ITEMS - 1) { - witchitem[WITCH_ITEMS - 1]._itype = ITYPE_NONE; - } else { - for (; !witchitem[idx + 1].isEmpty(); idx++) { - witchitem[idx] = witchitem[idx + 1]; - } - witchitem[idx]._itype = ITYPE_NONE; - } +void S_DrunkEnter() +{ + switch (stextsel) { + case 12: + stextlhold = 12; + talker = TOWN_DRUNK; + stextshold = STORE_DRUNK; + gossipstart = TEXT_FARNHAM2; + gossipend = TEXT_FARNHAM13; + StartStore(STORE_GOSSIP); + break; + case 18: + stextflag = STORE_NONE; + break; } +} - CalcPlrInv(myplr, TRUE); } -void S_WBuyEnter() -{ - int i, idx; - BOOL done; +ItemStruct golditem; - if (stextsel == 22) { - StartStore(STORE_WITCH); - stextsel = 14; - } else { - stextlhold = stextsel; - stextvhold = stextsval; - stextshold = STORE_WBUY; - idx = stextsval + ((stextsel - stextup) >> 2); +Uint8 *pSTextBoxCels; +Uint8 *pSPentSpn2Cels; +Uint8 *pSTextSlidCels; + +talk_id stextflag; + +ItemStruct smithitem[SMITH_ITEMS]; +int numpremium; +int premiumlevel; +ItemStruct premiumitem[SMITH_PREMIUM_ITEMS]; - if (plr[myplr]._pGold < witchitem[idx]._iIvalue) { - StartStore(STORE_NOMONEY); - } else { - plr[myplr].HoldItem = witchitem[idx]; - SetCursor_(plr[myplr].HoldItem._iCurs + CURSOR_FIRSTITEM); - done = FALSE; +ItemStruct healitem[20]; - for (i = 0; i < NUM_INV_GRID_ELEM && !done; i++) { - done = SpecialAutoPlace(myplr, i, plr[myplr].HoldItem); - } +ItemStruct witchitem[WITCH_ITEMS]; - if (done) - StartStore(STORE_CONFIRM); - else - StartStore(STORE_NOROOM); +int boylevel; +ItemStruct boyitem; - SetCursor_(CURSOR_HAND); - } - } +void InitStores() +{ + pSTextBoxCels = LoadFileInMem("Data\\TextBox2.CEL", NULL); + pSPentSpn2Cels = LoadFileInMem("Data\\PentSpn2.CEL", NULL); + pSTextSlidCels = LoadFileInMem("Data\\TextSlid.CEL", NULL); + ClearSText(0, STORE_LINES); + stextflag = STORE_NONE; + stextsize = false; + stextscrl = false; + numpremium = 0; + premiumlevel = 1; + + for (int i = 0; i < SMITH_PREMIUM_ITEMS; i++) + premiumitem[i]._itype = ITYPE_NONE; + + boyitem._itype = ITYPE_NONE; + boylevel = 0; } -void S_WSellEnter() +int PentSpn2Spin() { - int idx; + return (SDL_GetTicks() / 50) % 8 + 1; +} - if (stextsel == 22) { - StartStore(STORE_WITCH); - stextsel = 16; +void SetupTownStores() +{ + int i, l; + + SetRndSeed(glSeedTbl[currlevel] * SDL_GetTicks()); + if (!gbIsMultiplayer) { + l = 0; + for (i = 0; i < NUMLEVELS; i++) { + if (plr[myplr]._pLvlVisited[i]) + l = i; + } } else { - stextlhold = stextsel; - idx = stextsval + ((stextsel - stextup) >> 2); - stextshold = STORE_WSELL; - stextvhold = stextsval; - plr[myplr].HoldItem = storehold[idx]; - if (StoreGoldFit(idx)) - StartStore(STORE_CONFIRM); - else - StartStore(STORE_NOROOM); + l = plr[myplr]._pLevel >> 1; } + l += 2; + if (l < 6) + l = 6; + if (l > 16) + l = 16; + SpawnStoreGold(); + SpawnSmith(l); + SpawnWitch(l); + SpawnHealer(l); + SpawnBoy(plr[myplr]._pLevel); + SpawnPremium(myplr); } -/** - * @brief Recharges an item in the player's inventory or body in the witch. - */ -void WitchRechargeItem() +void FreeStoreMem() { - int i, idx; - - TakePlrsMoney(plr[myplr].HoldItem._iIvalue); - - idx = stextvhold + ((stextlhold - stextup) >> 2); - storehold[idx]._iCharges = storehold[idx]._iMaxCharges; - - i = storehidx[idx]; - if (i < 0) - plr[myplr].InvBody[INVLOC_HAND_LEFT]._iCharges = plr[myplr].InvBody[INVLOC_HAND_LEFT]._iMaxCharges; - else - plr[myplr].InvList[i]._iCharges = plr[myplr].InvList[i]._iMaxCharges; - - CalcPlrInv(myplr, TRUE); + MemFreeDbg(pSTextBoxCels); + MemFreeDbg(pSPentSpn2Cels); + MemFreeDbg(pSTextSlidCels); } -void S_WRechargeEnter() +void PrintSString(CelOutputBuffer out, int x, int y, bool cjustflag, const char *str, char col, int val) { - int idx; + int len, width, sx, sy, i, k, s; + int xx, yy; + BYTE c; + char valstr[32]; - if (stextsel == 22) { - StartStore(STORE_WITCH); - stextsel = 18; - } else { - stextshold = STORE_WRECHARGE; - stextlhold = stextsel; - stextvhold = stextsval; - idx = stextsval + ((stextsel - stextup) >> 2); - plr[myplr].HoldItem = storehold[idx]; - if (plr[myplr]._pGold < storehold[idx]._iIvalue) - StartStore(STORE_NOMONEY); - else - StartStore(STORE_CONFIRM); + s = y * 12 + stext[y]._syoff; + if (stextsize) + xx = PANEL_X + 32; + else + xx = PANEL_X + 352; + sx = xx + x; + sy = s + 44 + SCREEN_Y + UI_OFFSET_Y; + len = strlen(str); + if (stextsize) + yy = 577; + else + yy = 257; + k = 0; + if (cjustflag) { + width = 0; + for (i = 0; i < len; i++) + width += fontkern[fontframe[gbFontTransTbl[(BYTE)str[i]]]] + 1; + if (width < yy) + k = (yy - width) >> 1; + sx += k; + } + if (stextsel == y) { + CelDrawTo(out, cjustflag ? xx + x + k - 20 : xx + x - 20, s + 45 + SCREEN_Y + UI_OFFSET_Y, pSPentSpn2Cels, PentSpn2Spin(), 12); + } + for (i = 0; i < len; i++) { + c = fontframe[gbFontTransTbl[(BYTE)str[i]]]; + k += fontkern[c] + 1; + if (c != 0 && k <= yy) { + PrintChar(out, sx, sy, c, col); + } + sx += fontkern[c] + 1; + } + if (!cjustflag && val >= 0) { + sprintf(valstr, "%i", val); + sx = PANEL_X + 592 - x; + len = strlen(valstr); + for (i = len - 1; i >= 0; i--) { + c = fontframe[gbFontTransTbl[(BYTE)valstr[i]]]; + sx -= fontkern[c] + 1; + if (c != 0) { + PrintChar(out, sx, sy, c, col); + } + } + } + if (stextsel == y) { + CelDrawTo(out, cjustflag ? (xx + x + k + 4) : (PANEL_X + 596 - x), s + 45 + SCREEN_Y + UI_OFFSET_Y, pSPentSpn2Cels, PentSpn2Spin(), 12); } } -void S_BoyEnter() +void DrawSLine(int y) { - if (!boyitem.isEmpty() && stextsel == 18) { - if (plr[myplr]._pGold < 50) { - stextshold = STORE_BOY; - stextlhold = 18; - stextvhold = stextsval; - StartStore(STORE_NOMONEY); - } else { - TakePlrsMoney(50); - StartStore(STORE_BBOY); - } - } else if (stextsel == 8 && !boyitem.isEmpty() || stextsel == 12 && boyitem.isEmpty()) { - talker = TOWN_PEGBOY; - stextshold = STORE_BOY; - stextlhold = stextsel; - gossipstart = TEXT_WIRT2; - gossipend = TEXT_WIRT12; - StartStore(STORE_GOSSIP); + int xy, yy, width, line, sy; + + sy = y * 12; + if (stextsize) { + xy = SCREENXY(PANEL_LEFT + 26, 25 + UI_OFFSET_Y); + yy = BUFFER_WIDTH * (sy + 38 + SCREEN_Y + UI_OFFSET_Y) + 26 + PANEL_X; + width = 586 / 4; // BUGFIX: should be 587, not 586 + line = BUFFER_WIDTH - 586; // BUGFIX: should be 587, not 586 } else { - stextflag = STORE_NONE; + xy = SCREENXY(PANEL_LEFT + 346, 25 + UI_OFFSET_Y); + yy = BUFFER_WIDTH * (sy + 38 + SCREEN_Y + UI_OFFSET_Y) + 346 + PANEL_X; + width = 266 / 4; // BUGFIX: should be 267, not 266 + line = BUFFER_WIDTH - 266; // BUGFIX: should be 267, not 266 } + + /// ASSERT: assert(gpBuffer); + + int i; + BYTE *src, *dst; + + src = &gpBuffer[xy]; + dst = &gpBuffer[yy]; + + for (i = 0; i < 3; i++, src += BUFFER_WIDTH, dst += BUFFER_WIDTH) + memcpy(dst, src, BUFFER_WIDTH - line); } -void BoyBuyItem() +void DrawSTextHelp() { - TakePlrsMoney(plr[myplr].HoldItem._iIvalue); - StoreAutoPlace(); - boyitem._itype = ITYPE_NONE; - stextshold = STORE_BOY; - CalcPlrInv(myplr, TRUE); + stextsel = -1; + stextsize = true; } -/** - * @brief Purchases an item from the healer. - */ -void HealerBuyItem() +void ClearSText(int s, int e) { - int idx; + int i; - idx = stextvhold + ((stextlhold - stextup) >> 2); - if (!gbIsMultiplayer) { - if (idx < 2) - plr[myplr].HoldItem._iSeed = AdvanceRndSeed(); - } else { - if (idx < 3) - plr[myplr].HoldItem._iSeed = AdvanceRndSeed(); + for (i = s; i < e; i++) { + stext[i]._sx = 0; + stext[i]._syoff = 0; + stext[i]._sstr[0] = 0; + stext[i]._sjust = false; + stext[i]._sclr = COL_WHITE; + stext[i]._sline = 0; + stext[i]._ssel = FALSE; + stext[i]._sval = -1; } +} - TakePlrsMoney(plr[myplr].HoldItem._iIvalue); - if (plr[myplr].HoldItem._iMagical == ITEM_QUALITY_NORMAL) - plr[myplr].HoldItem._iIdentified = FALSE; - StoreAutoPlace(); - - if (!gbIsMultiplayer) { - if (idx < 2) - return; - } else { - if (idx < 3) +void StartStore(talk_id s) +{ + sbookflag = FALSE; + invflag = FALSE; + chrflag = FALSE; + questlog = FALSE; + dropGoldFlag = FALSE; + ClearSText(0, STORE_LINES); + ReleaseStoreBtn(); + switch (s) { + case STORE_SMITH: + S_StartSmith(); + break; + case STORE_SBUY: + if (storenumh > 0) + S_StartSBuy(); + else + S_StartSmith(); + break; + case STORE_SSELL: + S_StartSSell(); + break; + case STORE_SREPAIR: + S_StartSRepair(); + break; + case STORE_WITCH: + S_StartWitch(); + break; + case STORE_WBUY: + if (storenumh > 0) + S_StartWBuy(); + break; + case STORE_WSELL: + S_StartWSell(); + break; + case STORE_WRECHARGE: + S_StartWRecharge(); + break; + case STORE_NOMONEY: + S_StartNoMoney(); + break; + case STORE_NOROOM: + S_StartNoRoom(); + break; + case STORE_CONFIRM: + S_StartConfirm(); + break; + case STORE_BOY: + S_StartBoy(); + break; + case STORE_BBOY: + S_StartBBoy(); + break; + case STORE_HEALER: + S_StartHealer(); + break; + case STORE_STORY: + S_StartStory(); + break; + case STORE_HBUY: + if (storenumh > 0) + S_StartHBuy(); + break; + case STORE_SIDENTIFY: + S_StartSIdentify(); + break; + case STORE_SPBUY: + if (!S_StartSPBuy()) return; + break; + case STORE_GOSSIP: + S_StartTalk(); + break; + case STORE_IDSHOW: + S_StartIdShow(); + break; + case STORE_TAVERN: + S_StartTavern(); + break; + case STORE_DRUNK: + S_StartDrunk(); + break; + case STORE_BARMAID: + S_StartBarMaid(); + break; } - idx = stextvhold + ((stextlhold - stextup) >> 2); - if (idx == 19) { - healitem[19]._itype = ITYPE_NONE; - } else { - for (; !healitem[idx + 1].isEmpty(); idx++) { - healitem[idx] = healitem[idx + 1]; + + stextsel = -1; + for (int i = 0; i < STORE_LINES; i++) { + if (stext[i]._ssel) { + stextsel = i; + break; } - healitem[idx]._itype = ITYPE_NONE; } - CalcPlrInv(myplr, TRUE); + + stextflag = s; } -void S_BBuyEnter() +void DrawSText(CelOutputBuffer out) { - if (stextsel != 10) { - stextflag = STORE_NONE; - return; - } + int i; - stextshold = STORE_BBOY; - stextvhold = stextsval; - stextlhold = 10; - int price = boyitem._iIvalue; - if (gbIsHellfire) - price -= boyitem._iIvalue >> 2; + if (!stextsize) + DrawSTextBack(out); else - price += boyitem._iIvalue >> 1; + DrawQTextBack(out); - if (plr[myplr]._pGold < price) { - StartStore(STORE_NOMONEY); - return; + if (stextscrl) { + switch (stextflag) { + case STORE_SBUY: + S_ScrollSBuy(stextsval); + break; + case STORE_SSELL: + case STORE_SREPAIR: + case STORE_WSELL: + case STORE_WRECHARGE: + case STORE_SIDENTIFY: + S_ScrollSSell(stextsval); + break; + case STORE_WBUY: + S_ScrollWBuy(stextsval); + break; + case STORE_HBUY: + S_ScrollHBuy(stextsval); + break; + case STORE_SPBUY: + S_ScrollSPBuy(stextsval); + break; + } } - plr[myplr].HoldItem = boyitem; - plr[myplr].HoldItem._iIvalue = price; - SetCursor_(plr[myplr].HoldItem._iCurs + CURSOR_FIRSTITEM); - - bool done = false; - for (int i = 0; i < NUM_INV_GRID_ELEM && !done; i++) { - done = AutoPlace(myplr, i, cursW / 28, cursH / 28, false); + for (i = 0; i < STORE_LINES; i++) { + if (stext[i]._sline) + DrawSLine(i); + if (stext[i]._sstr[0]) + PrintSString(out, stext[i]._sx, i, stext[i]._sjust, stext[i]._sstr, stext[i]._sclr, stext[i]._sval); } - StartStore(done ? STORE_CONFIRM : STORE_NOROOM); - - SetCursor_(CURSOR_HAND); + if (stextscrl) + DrawSSlider(out, 4, 20); } -void StoryIdItem() +void STextESC() { - int idx; - - idx = storehidx[((stextlhold - stextup) >> 2) + stextvhold]; - if (idx < 0) { - if (idx == -1) - plr[myplr].InvBody[INVLOC_HEAD]._iIdentified = TRUE; - if (idx == -2) - plr[myplr].InvBody[INVLOC_CHEST]._iIdentified = TRUE; - if (idx == -3) - plr[myplr].InvBody[INVLOC_HAND_LEFT]._iIdentified = TRUE; - if (idx == -4) - plr[myplr].InvBody[INVLOC_HAND_RIGHT]._iIdentified = TRUE; - if (idx == -5) - plr[myplr].InvBody[INVLOC_RING_LEFT]._iIdentified = TRUE; - if (idx == -6) - plr[myplr].InvBody[INVLOC_RING_RIGHT]._iIdentified = TRUE; - if (idx == -7) - plr[myplr].InvBody[INVLOC_AMULET]._iIdentified = TRUE; + if (qtextflag) { + qtextflag = FALSE; + if (leveltype == DTYPE_TOWN) + stream_stop(); } else { - plr[myplr].InvList[idx]._iIdentified = TRUE; - } - plr[myplr].HoldItem._iIdentified = TRUE; - TakePlrsMoney(plr[myplr].HoldItem._iIvalue); - CalcPlrInv(myplr, TRUE); -} - -void S_ConfirmEnter() -{ - if (stextsel == 18) { - switch (stextshold) { + switch (stextflag) { + case STORE_SMITH: + case STORE_WITCH: + case STORE_BOY: + case STORE_BBOY: + case STORE_HEALER: + case STORE_STORY: + case STORE_TAVERN: + case STORE_DRUNK: + case STORE_BARMAID: + stextflag = STORE_NONE; + break; + case STORE_GOSSIP: + StartStore(stextshold); + stextsel = stextlhold; + break; case STORE_SBUY: - SmithBuyItem(); + StartStore(STORE_SMITH); + stextsel = 12; + break; + case STORE_SPBUY: + StartStore(STORE_SMITH); + stextsel = 14; break; case STORE_SSELL: - case STORE_WSELL: - StoreSellItem(); + StartStore(STORE_SMITH); + stextsel = 16; break; case STORE_SREPAIR: - SmithRepairItem(); + StartStore(STORE_SMITH); + stextsel = 18; break; case STORE_WBUY: - WitchBuyItem(); + StartStore(STORE_WITCH); + stextsel = 14; break; - case STORE_WRECHARGE: - WitchRechargeItem(); + case STORE_WSELL: + StartStore(STORE_WITCH); + stextsel = 16; break; - case STORE_BBOY: - BoyBuyItem(); + case STORE_WRECHARGE: + StartStore(STORE_WITCH); + stextsel = 18; break; case STORE_HBUY: - HealerBuyItem(); + StartStore(STORE_HEALER); + stextsel = 16; break; case STORE_SIDENTIFY: - StoryIdItem(); - StartStore(STORE_IDSHOW); - return; - case STORE_SPBUY: - SmithBuyPItem(); + StartStore(STORE_STORY); + stextsel = 14; + break; + case STORE_IDSHOW: + StartStore(STORE_SIDENTIFY); + break; + case STORE_NOMONEY: + case STORE_NOROOM: + case STORE_CONFIRM: + StartStore(stextshold); + stextsel = stextlhold; + stextsval = stextvhold; break; - } - } - - StartStore(stextshold); - - if (stextsel == 22) - return; - - stextsel = stextlhold; - stextsval = std::min(stextvhold, stextsmax); - - while (!stext[stextsel]._ssel) { - stextsel--; - } -} - -void S_HealerEnter() -{ - switch (stextsel) { - case 12: - stextlhold = 12; - talker = TOWN_HEALER; - stextshold = STORE_HEALER; - gossipstart = TEXT_PEPIN2; - gossipend = TEXT_PEPIN11; - StartStore(STORE_GOSSIP); - break; - case 14: - StartStore(STORE_HBUY); - break; - case 16: - stextflag = STORE_NONE; - break; - } -} - -void S_HBuyEnter() -{ - int i, idx; - BOOL done; - - if (stextsel == 22) { - StartStore(STORE_HEALER); - stextsel = 16; - } else { - stextlhold = stextsel; - stextvhold = stextsval; - stextshold = STORE_HBUY; - idx = stextsval + ((stextsel - stextup) >> 2); - - if (plr[myplr]._pGold < healitem[idx]._iIvalue) { - StartStore(STORE_NOMONEY); - } else { - plr[myplr].HoldItem = healitem[idx]; - SetCursor_(plr[myplr].HoldItem._iCurs + CURSOR_FIRSTITEM); - done = FALSE; - - for (i = 0; i < NUM_INV_GRID_ELEM && !done; i++) { - done = SpecialAutoPlace(myplr, i, plr[myplr].HoldItem); - } - - if (done) - StartStore(STORE_CONFIRM); - else - StartStore(STORE_NOROOM); - - SetCursor_(CURSOR_HAND); } } } -void S_StoryEnter() +void STextUp() { - switch (stextsel) { - case 12: - stextlhold = 12; - talker = TOWN_STORY; - stextshold = STORE_STORY; - gossipstart = TEXT_STORY2; - gossipend = TEXT_STORY11; - StartStore(STORE_GOSSIP); - break; - case 14: - StartStore(STORE_SIDENTIFY); - break; - case 18: - stextflag = STORE_NONE; - break; + PlaySFX(IS_TITLEMOV); + if (stextsel == -1) { + return; } -} -void S_SIDEnter() -{ - int idx; + if (stextscrl) { + if (stextsel == stextup) { + if (stextsval) + stextsval--; + return; + } - if (stextsel == 22) { - StartStore(STORE_STORY); - stextsel = 14; - } else { - stextshold = STORE_SIDENTIFY; - stextlhold = stextsel; - stextvhold = stextsval; - idx = stextsval + ((stextsel - stextup) >> 2); - plr[myplr].HoldItem = storehold[idx]; - if (plr[myplr]._pGold < storehold[idx]._iIvalue) - StartStore(STORE_NOMONEY); + stextsel--; + while (!stext[stextsel]._ssel) { + if (!stextsel) + stextsel = STORE_LINES - 1; + else + stextsel--; + } + return; + } + + if (!stextsel) + stextsel = STORE_LINES - 1; + else + stextsel--; + + while (!stext[stextsel]._ssel) { + if (!stextsel) + stextsel = STORE_LINES - 1; else - StartStore(STORE_CONFIRM); + stextsel--; } } -void S_TalkEnter() +void STextDown() { - int i, tq, sn, la; - - if (stextsel == 22) { - StartStore(stextshold); - stextsel = stextlhold; + PlaySFX(IS_TITLEMOV); + if (stextsel == -1) { return; } - sn = 0; - for (i = 0; i < MAXQUESTS; i++) { - if (quests[i]._qactive == QUEST_ACTIVE && Qtalklist[talker][i] != TEXT_NONE && quests[i]._qlog) - sn++; - } - if (sn > 6) { - sn = 14 - (sn >> 1); - la = 1; - } else { - sn = 15 - sn; - la = 2; - } + if (stextscrl) { + if (stextsel == stextdown) { + if (stextsval < stextsmax) + stextsval++; + return; + } - if (stextsel == sn - 2) { - SetRndSeed(towner[talker]._tSeed); - tq = gossipstart + random_(0, gossipend - gossipstart + 1); - InitQTextMsg(tq); + stextsel++; + while (!stext[stextsel]._ssel) { + if (stextsel == STORE_LINES - 1) + stextsel = 0; + else + stextsel++; + } return; } - for (i = 0; i < MAXQUESTS; i++) { - if (quests[i]._qactive == QUEST_ACTIVE && Qtalklist[talker][i] != TEXT_NONE && quests[i]._qlog) { - if (sn == stextsel) { - InitQTextMsg(Qtalklist[talker][i]); - } - sn += la; - } + if (stextsel == STORE_LINES - 1) + stextsel = 0; + else + stextsel++; + + while (!stext[stextsel]._ssel) { + if (stextsel == STORE_LINES - 1) + stextsel = 0; + else + stextsel++; } } -void S_TavernEnter() +void STextPrior() { - switch (stextsel) { - case 12: - stextlhold = 12; - talker = TOWN_TAVERN; - stextshold = STORE_TAVERN; - gossipstart = TEXT_OGDEN2; - gossipend = TEXT_OGDEN10; - StartStore(STORE_GOSSIP); - break; - case 18: - stextflag = STORE_NONE; - break; + PlaySFX(IS_TITLEMOV); + if (stextsel != -1 && stextscrl) { + if (stextsel == stextup) { + if (stextsval) + stextsval -= 4; + stextsval = stextsval; + if (stextsval < 0) + stextsval = 0; + } else { + stextsel = stextup; + } } } -void S_BarmaidEnter() +void STextNext() { - switch (stextsel) { - case 12: - stextlhold = 12; - talker = TOWN_BMAID; - stextshold = STORE_BARMAID; - gossipstart = TEXT_GILLIAN2; - gossipend = TEXT_GILLIAN10; - StartStore(STORE_GOSSIP); - break; - case 18: - stextflag = STORE_NONE; - break; + PlaySFX(IS_TITLEMOV); + if (stextsel != -1 && stextscrl) { + if (stextsel == stextdown) { + if (stextsval < stextsmax) + stextsval += 4; + if (stextsval > stextsmax) + stextsval = stextsmax; + } else { + stextsel = stextdown; + } } } -void S_DrunkEnter() +void SetGoldCurs(int pnum, int i) { - switch (stextsel) { - case 12: - stextlhold = 12; - talker = TOWN_DRUNK; - stextshold = STORE_DRUNK; - gossipstart = TEXT_FARNHAM2; - gossipend = TEXT_FARNHAM13; - StartStore(STORE_GOSSIP); - break; - case 18: - stextflag = STORE_NONE; - break; + SetPlrHandGoldCurs(&plr[pnum].InvList[i]); +} + +void SetSpdbarGoldCurs(int pnum, int i) +{ + SetPlrHandGoldCurs(&plr[pnum].SpdList[i]); +} + +void TakePlrsMoney(int cost) +{ + int i; + + plr[myplr]._pGold = CalculateGold(myplr) - cost; + for (i = 0; i < MAXBELTITEMS && cost > 0; i++) { + if (plr[myplr].SpdList[i]._itype == ITYPE_GOLD && plr[myplr].SpdList[i]._ivalue != GOLD_MAX_LIMIT) { + if (cost < plr[myplr].SpdList[i]._ivalue) { + plr[myplr].SpdList[i]._ivalue -= cost; + SetSpdbarGoldCurs(myplr, i); + cost = 0; + } else { + cost -= plr[myplr].SpdList[i]._ivalue; + RemoveSpdBarItem(myplr, i); + i = -1; + } + } + } + if (cost > 0) { + for (i = 0; i < MAXBELTITEMS && cost > 0; i++) { + if (plr[myplr].SpdList[i]._itype == ITYPE_GOLD) { + if (cost < plr[myplr].SpdList[i]._ivalue) { + plr[myplr].SpdList[i]._ivalue -= cost; + SetSpdbarGoldCurs(myplr, i); + cost = 0; + } else { + cost -= plr[myplr].SpdList[i]._ivalue; + RemoveSpdBarItem(myplr, i); + i = -1; + } + } + } + } + force_redraw = 255; + if (cost > 0) { + for (i = 0; i < plr[myplr]._pNumInv && cost > 0; i++) { + if (plr[myplr].InvList[i]._itype == ITYPE_GOLD && plr[myplr].InvList[i]._ivalue != GOLD_MAX_LIMIT) { + if (cost < plr[myplr].InvList[i]._ivalue) { + plr[myplr].InvList[i]._ivalue -= cost; + SetGoldCurs(myplr, i); + cost = 0; + } else { + cost -= plr[myplr].InvList[i]._ivalue; + RemoveInvItem(myplr, i); + i = -1; + } + } + } + if (cost > 0) { + for (i = 0; i < plr[myplr]._pNumInv && cost > 0; i++) { + if (plr[myplr].InvList[i]._itype == ITYPE_GOLD) { + if (cost < plr[myplr].InvList[i]._ivalue) { + plr[myplr].InvList[i]._ivalue -= cost; + SetGoldCurs(myplr, i); + cost = 0; + } else { + cost -= plr[myplr].InvList[i]._ivalue; + RemoveInvItem(myplr, i); + i = -1; + } + } + } + } } } diff --git a/Source/stores.h b/Source/stores.h index 24205c60a..213f46689 100644 --- a/Source/stores.h +++ b/Source/stores.h @@ -14,6 +14,33 @@ DEVILUTION_BEGIN_NAMESPACE extern "C" { #endif +typedef enum talk_id { + STORE_NONE, + STORE_SMITH, + STORE_SBUY, + STORE_SSELL, + STORE_SREPAIR, + STORE_WITCH, + STORE_WBUY, + STORE_WSELL, + STORE_WRECHARGE, + STORE_NOMONEY, + STORE_NOROOM, + STORE_CONFIRM, + STORE_BOY, + STORE_BBOY, + STORE_HEALER, + STORE_STORY, + STORE_HBUY, + STORE_SIDENTIFY, + STORE_SPBUY, + STORE_GOSSIP, + STORE_IDSHOW, + STORE_TAVERN, + STORE_DRUNK, + STORE_BARMAID, +} talk_id; + typedef struct STextStruct { int _sx; int _syoff; @@ -25,29 +52,48 @@ typedef struct STextStruct { int _sval; } STextStruct; -extern ItemStruct boyitem; -extern ItemStruct premiumitem[SMITH_PREMIUM_ITEMS]; +/** Shop frame graphics */ extern BYTE *pSTextBoxCels; -extern int premiumlevel; -extern ItemStruct witchitem[WITCH_ITEMS]; +/** Small text selection cursor */ +extern BYTE *pSPentSpn2Cels; +/** Scrollbar graphics */ +extern BYTE *pSTextSlidCels; + +/** Currently active store */ +extern talk_id stextflag; + +/** Temporary item used to generate gold piles by various function */ +extern ItemStruct golditem; + +/** Items sold by Griswold */ +extern ItemStruct smithitem[SMITH_ITEMS]; +/** Number of premium items for sale by Griswold */ extern int numpremium; +/** Base level of current premium items sold by Griswold */ +extern int premiumlevel; +/** Premium items sold by Griswold */ +extern ItemStruct premiumitem[SMITH_PREMIUM_ITEMS]; + +/** Items sold by Pepin */ extern ItemStruct healitem[20]; -extern ItemStruct golditem; -extern BYTE *pSTextSlidCels; -extern BYTE *pSPentSpn2Cels; + +/** Items sold by Adria */ +extern ItemStruct witchitem[WITCH_ITEMS]; + +/** Current level of the item sold by Wirt */ extern int boylevel; -extern ItemStruct smithitem[SMITH_ITEMS]; -extern char stextflag; +/** Current item sold by Wirt */ +extern ItemStruct boyitem; void InitStores(); int PentSpn2Spin(); void SetupTownStores(); void FreeStoreMem(); -void PrintSString(CelOutputBuffer out, int x, int y, BOOL cjustflag, const char *str, char col, int val); +void PrintSString(CelOutputBuffer out, int x, int y, bool cjustflag, const char *str, char col, int val); void DrawSLine(int y); void DrawSTextHelp(); void ClearSText(int s, int e); -void StartStore(char s); +void StartStore(talk_id s); void DrawSText(CelOutputBuffer out); void STextESC(); void STextUp(); diff --git a/enums.h b/enums.h index ca9a9703f..57196f13e 100644 --- a/enums.h +++ b/enums.h @@ -2393,33 +2393,6 @@ typedef enum quest_mush_state { QS_BRAINGIVEN = 7, } quest_mush_state; -typedef enum talk_id { - STORE_NONE = 0x0, - STORE_SMITH = 0x1, - STORE_SBUY = 0x2, - STORE_SSELL = 0x3, - STORE_SREPAIR = 0x4, - STORE_WITCH = 0x5, - STORE_WBUY = 0x6, - STORE_WSELL = 0x7, - STORE_WRECHARGE = 0x8, - STORE_NOMONEY = 0x9, - STORE_NOROOM = 0xA, - STORE_CONFIRM = 0xB, - STORE_BOY = 0xC, - STORE_BBOY = 0xD, - STORE_HEALER = 0xE, - STORE_STORY = 0xF, - STORE_HBUY = 0x10, - STORE_SIDENTIFY = 0x11, - STORE_SPBUY = 0x12, - STORE_GOSSIP = 0x13, - STORE_IDSHOW = 0x14, - STORE_TAVERN = 0x15, - STORE_DRUNK = 0x16, - STORE_BARMAID = 0x17, -} talk_id; - typedef enum _unique_items { UITEM_CLEAVER = 0x0, UITEM_SKCROWN = 0x1,