1 /**
2 * @file stores.cpp
3 *
4 * Implementation of functionality for stores and towner dialogs.
5 */
6 #include "all.h"
7 #include "options.h"
8 #include <algorithm>
9
10 DEVILUTION_BEGIN_NAMESPACE
11
12 namespace {
13
14 /** The current towner being interacted with */
15 _talker_id talker;
16
17 /** Is the curren dialog full size */
18 bool stextsize;
19
20 /** Number of text lines in the current dialog */
21 int stextsmax;
22 /** Remember currently selected text line from stext while displaying a dialog */
23 int stextlhold;
24 /** Currently selected text line from stext */
25 int stextsel;
26 /** Text lines */
27 STextStruct stext[STORE_LINES];
28
29 /** Does the current panel have a scrollbar */
30 bool stextscrl;
31 /** Remember last scoll position */
32 int stextvhold;
33 /** Scoll position */
34 int stextsval;
35 /** Next scoll position */
36 int stextdown;
37 /** Previous scoll position */
38 int stextup;
39 /** Count down for the push state of the scroll up button */
40 char stextscrlubtn;
41 /** Count down for the push state of the scroll down button */
42 char stextscrldbtn;
43
44 /** Remember current store while displaying a dialog */
45 talk_id stextshold;
46
47 /** Start of possible gossip dialogs for current store */
48 _speech_id gossipstart;
49 /** End of possible gossip dialogs for current store */
50 _speech_id gossipend;
51
52 /** Maps from towner IDs to NPC names. */
53 const char *const talkname[] = {
54 "Griswold",
55 "Pepin",
56 "",
57 "Ogden",
58 "Cain",
59 "Farnham",
60 "Adria",
61 "Gillian",
62 "Wirt"
63 };
64
DrawSTextBack(CelOutputBuffer out)65 void DrawSTextBack(CelOutputBuffer out)
66 {
67 CelDrawTo(out, PANEL_X + 344, 327 + UI_OFFSET_Y, pSTextBoxCels, 1, 271);
68 DrawHalfTransparentRectTo(out, PANEL_X + 347, UI_OFFSET_Y + 28, 265, 297);
69 }
70
DrawSSlider(CelOutputBuffer out,int y1,int y2)71 void DrawSSlider(CelOutputBuffer out, int y1, int y2)
72 {
73 int yd1, yd2, yd3;
74
75 yd1 = y1 * 12 + 44 + UI_OFFSET_Y;
76 yd2 = y2 * 12 + 44 + UI_OFFSET_Y;
77 if (stextscrlubtn != -1)
78 CelDrawTo(out, PANEL_X + 601, yd1, pSTextSlidCels, 12, 12);
79 else
80 CelDrawTo(out, PANEL_X + 601, yd1, pSTextSlidCels, 10, 12);
81 if (stextscrldbtn != -1)
82 CelDrawTo(out, PANEL_X + 601, yd2, pSTextSlidCels, 11, 12);
83 else
84 CelDrawTo(out, PANEL_X + 601, yd2, pSTextSlidCels, 9, 12);
85 yd1 += 12;
86 for (yd3 = yd1; yd3 < yd2; yd3 += 12) {
87 CelDrawTo(out, PANEL_X + 601, yd3, pSTextSlidCels, 14, 12);
88 }
89 if (stextsel == 22)
90 yd3 = stextlhold;
91 else
92 yd3 = stextsel;
93 if (storenumh > 1)
94 yd3 = 1000 * (stextsval + ((yd3 - stextup) >> 2)) / (storenumh - 1) * (y2 * 12 - y1 * 12 - 24) / 1000;
95 else
96 yd3 = 0;
97 CelDrawTo(out, PANEL_X + 601, (y1 + 1) * 12 + 44 + UI_OFFSET_Y + yd3, pSTextSlidCels, 13, 12);
98 }
99
AddSLine(int y)100 void AddSLine(int y)
101 {
102 stext[y]._sx = 0;
103 stext[y]._syoff = 0;
104 stext[y]._sstr[0] = 0;
105 stext[y]._sline = 1;
106 }
107
AddSTextVal(int y,int val)108 void AddSTextVal(int y, int val)
109 {
110 stext[y]._sval = val;
111 }
112
OffsetSTextY(int y,int yo)113 void OffsetSTextY(int y, int yo)
114 {
115 stext[y]._syoff = yo;
116 }
117
AddSText(int x,int y,bool j,const char * str,text_color clr,BOOL sel)118 void AddSText(int x, int y, bool j, const char *str, text_color clr, BOOL sel)
119 {
120 stext[y]._sx = x;
121 stext[y]._syoff = 0;
122 strcpy(stext[y]._sstr, str);
123 stext[y]._sjust = j;
124 stext[y]._sclr = clr;
125 stext[y]._sline = 0;
126 stext[y]._ssel = sel;
127 }
128
PrintStoreItem(ItemStruct * x,int l,text_color iclr)129 void PrintStoreItem(ItemStruct *x, int l, text_color iclr)
130 {
131 char sstr[128];
132 char str, dex;
133 BYTE mag;
134
135 sstr[0] = '\0';
136 if (x->_iIdentified) {
137 if (x->_iMagical != ITEM_QUALITY_UNIQUE) {
138 if (x->_iPrePower != -1) {
139 PrintItemPower(x->_iPrePower, x);
140 strcat(sstr, tempstr);
141 }
142 }
143 if (x->_iSufPower != -1) {
144 PrintItemPower(x->_iSufPower, x);
145 if (sstr[0])
146 strcat(sstr, ", ");
147 strcat(sstr, tempstr);
148 }
149 }
150 if (x->_iMiscId == IMISC_STAFF && x->_iMaxCharges) {
151 sprintf(tempstr, "Charges: %i/%i", x->_iCharges, x->_iMaxCharges);
152 if (sstr[0])
153 strcat(sstr, ", ");
154 strcat(sstr, tempstr);
155 }
156 if (sstr[0]) {
157 AddSText(40, l, FALSE, sstr, iclr, FALSE);
158 l++;
159 }
160 sstr[0] = '\0';
161 if (x->_iClass == ICLASS_WEAPON)
162 sprintf(sstr, "Damage: %i-%i ", x->_iMinDam, x->_iMaxDam);
163 if (x->_iClass == ICLASS_ARMOR)
164 sprintf(sstr, "Armor: %i ", x->_iAC);
165 if (x->_iMaxDur != DUR_INDESTRUCTIBLE && x->_iMaxDur) {
166 sprintf(tempstr, "Dur: %i/%i, ", x->_iDurability, x->_iMaxDur);
167 strcat(sstr, tempstr);
168 } else {
169 strcat(sstr, "Indestructible, ");
170 }
171 if (x->_itype == ITYPE_MISC)
172 sstr[0] = '\0';
173 str = x->_iMinStr;
174 mag = x->_iMinMag;
175 dex = x->_iMinDex;
176 if (str == 0 && mag == 0 && dex == 0) {
177 strcat(sstr, "No required attributes");
178 } else {
179 strcpy(tempstr, "Required:");
180 if (str)
181 sprintf(tempstr + strlen(tempstr), " %i Str", str);
182 if (mag)
183 sprintf(tempstr + strlen(tempstr), " %i Mag", mag);
184 if (dex)
185 sprintf(tempstr + strlen(tempstr), " %i Dex", dex);
186 strcat(sstr, tempstr);
187 }
188 AddSText(40, l++, FALSE, sstr, iclr, FALSE);
189 if (x->_iMagical == ITEM_QUALITY_UNIQUE) {
190 if (x->_iIdentified)
191 AddSText(40, l, FALSE, "Unique Item", iclr, FALSE);
192 }
193 }
194
StoreAutoPlace()195 void StoreAutoPlace()
196 {
197 BOOL done;
198 int i, w, h, idx;
199
200 SetICursor(plr[myplr].HoldItem._iCurs + CURSOR_FIRSTITEM);
201 w = icursW28;
202 h = icursH28;
203 done = FALSE;
204 if (AutoEquipEnabled(plr[myplr], plr[myplr].HoldItem) && AutoEquip(myplr, plr[myplr].HoldItem)) {
205 done = TRUE;
206 }
207
208 if (w == 1 && h == 1 && !done) {
209 idx = plr[myplr].HoldItem.IDidx;
210 if (plr[myplr].HoldItem._iStatFlag && AllItemsList[idx].iUsable) {
211 for (i = 0; i < MAXBELTITEMS && !done; i++) {
212 if (plr[myplr].SpdList[i].isEmpty()) {
213 plr[myplr].SpdList[i] = plr[myplr].HoldItem;
214 done = TRUE;
215 }
216 }
217 }
218 for (i = 30; i <= 39 && !done; i++) {
219 done = AutoPlace(myplr, i, w, h, TRUE);
220 }
221 for (i = 20; i <= 29 && !done; i++) {
222 done = AutoPlace(myplr, i, w, h, TRUE);
223 }
224 for (i = 10; i <= 19 && !done; i++) {
225 done = AutoPlace(myplr, i, w, h, TRUE);
226 }
227 for (i = 0; i <= 9 && !done; i++) {
228 done = AutoPlace(myplr, i, w, h, TRUE);
229 }
230 }
231 if (w == 1 && h == 2 && !done) {
232 for (i = 29; i >= 20 && !done; i--) {
233 done = AutoPlace(myplr, i, w, h, TRUE);
234 }
235 for (i = 9; i >= 0 && !done; i--) {
236 done = AutoPlace(myplr, i, w, h, TRUE);
237 }
238 for (i = 19; i >= 10 && !done; i--) {
239 done = AutoPlace(myplr, i, w, h, TRUE);
240 }
241 }
242 if (w == 1 && h == 3 && !done) {
243 for (i = 0; i < 20 && !done; i++) {
244 done = AutoPlace(myplr, i, w, h, TRUE);
245 }
246 }
247 if (w == 2 && h == 2 && !done) {
248 for (i = 0; i < 10 && !done; i++) {
249 done = AutoPlace(myplr, AP2x2Tbl[i], w, h, TRUE);
250 }
251 for (i = 21; i < 29 && !done; i += 2) {
252 done = AutoPlace(myplr, i, w, h, TRUE);
253 }
254 for (i = 1; i < 9 && !done; i += 2) {
255 done = AutoPlace(myplr, i, w, h, TRUE);
256 }
257 for (i = 10; i < 19 && !done; i++) {
258 done = AutoPlace(myplr, i, w, h, TRUE);
259 }
260 }
261 if (w == 2 && h == 3 && !done) {
262 for (i = 0; i < 9 && !done; i++) {
263 done = AutoPlace(myplr, i, w, h, TRUE);
264 }
265 for (i = 10; i < 19 && !done; i++) {
266 done = AutoPlace(myplr, i, w, h, TRUE);
267 }
268 }
269 }
270
S_StartSmith()271 void S_StartSmith()
272 {
273 stextsize = false;
274 stextscrl = false;
275 AddSText(0, 1, TRUE, "Welcome to the", COL_GOLD, FALSE);
276 AddSText(0, 3, TRUE, "Blacksmith's shop", COL_GOLD, FALSE);
277 AddSText(0, 7, TRUE, "Would you like to:", COL_GOLD, FALSE);
278 AddSText(0, 10, TRUE, "Talk to Griswold", COL_BLUE, TRUE);
279 AddSText(0, 12, TRUE, "Buy basic items", COL_WHITE, TRUE);
280 AddSText(0, 14, TRUE, "Buy premium items", COL_WHITE, TRUE);
281 AddSText(0, 16, TRUE, "Sell items", COL_WHITE, TRUE);
282 AddSText(0, 18, TRUE, "Repair items", COL_WHITE, TRUE);
283 AddSText(0, 20, TRUE, "Leave the shop", COL_WHITE, TRUE);
284 AddSLine(5);
285 storenumh = 20;
286 }
287
S_ScrollSBuy(int idx)288 void S_ScrollSBuy(int idx)
289 {
290 int l, ls;
291
292 ls = idx;
293 ClearSText(5, 21);
294 stextup = 5;
295
296 for (l = 5; l < 20; l += 4) {
297 if (!smithitem[ls].isEmpty()) {
298 text_color iclr = COL_WHITE;
299 if (smithitem[ls]._iMagical) {
300 iclr = COL_BLUE;
301 }
302
303 if (!smithitem[ls]._iStatFlag) {
304 iclr = COL_RED;
305 }
306
307 if (smithitem[ls]._iMagical) {
308 AddSText(20, l, FALSE, smithitem[ls]._iIName, iclr, TRUE);
309 } else {
310 AddSText(20, l, FALSE, smithitem[ls]._iName, iclr, TRUE);
311 }
312
313 AddSTextVal(l, smithitem[ls]._iIvalue);
314 PrintStoreItem(&smithitem[ls], l + 1, iclr);
315 stextdown = l;
316 ls++;
317 }
318 }
319
320 if (stextsel != -1 && !stext[stextsel]._ssel && stextsel != 22)
321 stextsel = stextdown;
322 }
323
S_StartSBuy()324 void S_StartSBuy()
325 {
326 int i;
327
328 stextsize = true;
329 stextscrl = true;
330 stextsval = 0;
331 sprintf(tempstr, "I have these items for sale: Your gold: %i", plr[myplr]._pGold);
332 AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE);
333 AddSLine(3);
334 AddSLine(21);
335 S_ScrollSBuy(stextsval);
336 AddSText(0, 22, TRUE, "Back", COL_WHITE, FALSE);
337 OffsetSTextY(22, 6);
338 storenumh = 0;
339 for (i = 0; !smithitem[i].isEmpty(); i++) {
340 storenumh++;
341 }
342
343 stextsmax = storenumh - 4;
344 if (stextsmax < 0)
345 stextsmax = 0;
346 }
347
S_ScrollSPBuy(int idx)348 void S_ScrollSPBuy(int idx)
349 {
350 int l, boughtitems;
351
352 ClearSText(5, 21);
353 boughtitems = idx;
354
355 stextup = 5;
356 for (idx = 0; boughtitems; idx++) {
357 if (!premiumitem[idx].isEmpty())
358 boughtitems--;
359 }
360
361 for (l = 5; l < 20 && idx < SMITH_PREMIUM_ITEMS; l += 4) {
362 if (!premiumitem[idx].isEmpty()) {
363 text_color iclr = COL_WHITE;
364 if (premiumitem[idx]._iMagical)
365 iclr = COL_BLUE;
366 if (!premiumitem[idx]._iStatFlag)
367 iclr = COL_RED;
368 AddSText(20, l, FALSE, premiumitem[idx]._iIName, iclr, TRUE);
369 AddSTextVal(l, premiumitem[idx]._iIvalue);
370 PrintStoreItem(&premiumitem[idx], l + 1, iclr);
371 stextdown = l;
372 } else {
373 l -= 4;
374 }
375 idx++;
376 }
377 if (stextsel != -1 && !stext[stextsel]._ssel && stextsel != 22)
378 stextsel = stextdown;
379 }
380
S_StartSPBuy()381 BOOL S_StartSPBuy()
382 {
383 int i;
384
385 storenumh = 0;
386 for (i = 0; i < SMITH_PREMIUM_ITEMS; i++) {
387 if (!premiumitem[i].isEmpty())
388 storenumh++;
389 }
390 if (!storenumh) {
391 StartStore(STORE_SMITH);
392 stextsel = 14;
393 return FALSE;
394 }
395
396 stextsize = true;
397 stextscrl = true;
398 stextsval = 0;
399
400 sprintf(tempstr, "I have these premium items for sale: Your gold: %i", plr[myplr]._pGold);
401 AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE);
402 AddSLine(3);
403 AddSLine(21);
404 AddSText(0, 22, TRUE, "Back", COL_WHITE, FALSE);
405 OffsetSTextY(22, 6);
406
407 stextsmax = storenumh - 4;
408 if (stextsmax < 0)
409 stextsmax = 0;
410
411 S_ScrollSPBuy(stextsval);
412
413 return TRUE;
414 }
415
SmithSellOk(int i)416 BOOL SmithSellOk(int i)
417 {
418 ItemStruct *pI;
419
420 if (i >= 0) {
421 pI = &plr[myplr].InvList[i];
422 } else {
423 pI = &plr[myplr].SpdList[-(i + 1)];
424 }
425
426 if (pI->isEmpty())
427 return FALSE;
428
429 if (pI->_iMiscId > IMISC_OILFIRST && pI->_iMiscId < IMISC_OILLAST)
430 return TRUE;
431
432 if (pI->_itype == ITYPE_MISC)
433 return FALSE;
434 if (pI->_itype == ITYPE_GOLD)
435 return FALSE;
436 if (pI->_itype == ITYPE_STAFF && (!gbIsHellfire || pI->_iSpell != SPL_NULL))
437 return FALSE;
438 if (pI->_iClass == ICLASS_QUEST)
439 return FALSE;
440 if (pI->IDidx == IDI_LAZSTAFF)
441 return FALSE;
442
443 return TRUE;
444 }
445
S_ScrollSSell(int idx)446 void S_ScrollSSell(int idx)
447 {
448 int l;
449
450 ClearSText(5, 21);
451 stextup = 5;
452
453 for (l = 5; l < 20; l += 4) {
454 if (idx >= storenumh)
455 break;
456 if (!storehold[idx].isEmpty()) {
457 text_color iclr = COL_WHITE;
458 if (storehold[idx]._iMagical) {
459 iclr = COL_BLUE;
460 }
461
462 if (!storehold[idx]._iStatFlag) {
463 iclr = COL_RED;
464 }
465
466 if (storehold[idx]._iMagical && storehold[idx]._iIdentified) {
467 AddSText(20, l, FALSE, storehold[idx]._iIName, iclr, TRUE);
468 AddSTextVal(l, storehold[idx]._iIvalue);
469 } else {
470 AddSText(20, l, FALSE, storehold[idx]._iName, iclr, TRUE);
471 AddSTextVal(l, storehold[idx]._ivalue);
472 }
473
474 PrintStoreItem(&storehold[idx], l + 1, iclr);
475 stextdown = l;
476 }
477 idx++;
478 }
479
480 stextsmax = storenumh - 4;
481 if (stextsmax < 0)
482 stextsmax = 0;
483 }
484
S_StartSSell()485 void S_StartSSell()
486 {
487 int i;
488 BOOL sellok;
489
490 stextsize = true;
491 sellok = FALSE;
492 storenumh = 0;
493
494 for (i = 0; i < 48; i++)
495 storehold[i]._itype = ITYPE_NONE;
496
497 for (i = 0; i < plr[myplr]._pNumInv; i++) {
498 if (storenumh >= 48)
499 break;
500 if (SmithSellOk(i)) {
501 sellok = TRUE;
502 storehold[storenumh] = plr[myplr].InvList[i];
503
504 if (storehold[storenumh]._iMagical != ITEM_QUALITY_NORMAL && storehold[storenumh]._iIdentified)
505 storehold[storenumh]._ivalue = storehold[storenumh]._iIvalue;
506
507 if ((storehold[storenumh]._ivalue >>= 2) == 0)
508 storehold[storenumh]._ivalue = 1;
509
510 storehold[storenumh]._iIvalue = storehold[storenumh]._ivalue;
511 storehidx[storenumh++] = i;
512 }
513 }
514
515 for (i = 0; i < MAXBELTITEMS; i++) {
516 if (storenumh >= 48)
517 break;
518 if (SmithSellOk(-(i + 1))) {
519 storehold[storenumh] = plr[myplr].SpdList[i];
520 sellok = TRUE;
521
522 if (storehold[storenumh]._iMagical != ITEM_QUALITY_NORMAL && storehold[storenumh]._iIdentified)
523 storehold[storenumh]._ivalue = storehold[storenumh]._iIvalue;
524
525 if (!(storehold[storenumh]._ivalue >>= 2))
526 storehold[storenumh]._ivalue = 1;
527
528 storehold[storenumh]._iIvalue = storehold[storenumh]._ivalue;
529 storehidx[storenumh++] = -(i + 1);
530 }
531 }
532
533 if (!sellok) {
534 stextscrl = false;
535 sprintf(tempstr, "You have nothing I want. Your gold: %i", plr[myplr]._pGold);
536 AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE);
537 AddSLine(3);
538 AddSLine(21);
539 AddSText(0, 22, TRUE, "Back", COL_WHITE, TRUE);
540 OffsetSTextY(22, 6);
541 } else {
542 stextscrl = true;
543 stextsval = 0;
544 stextsmax = plr[myplr]._pNumInv;
545 sprintf(tempstr, "Which item is for sale? Your gold: %i", plr[myplr]._pGold);
546 AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE);
547 AddSLine(3);
548 AddSLine(21);
549 S_ScrollSSell(stextsval);
550 AddSText(0, 22, TRUE, "Back", COL_WHITE, TRUE);
551 OffsetSTextY(22, 6);
552 }
553 }
554
SmithRepairOk(int i)555 BOOL SmithRepairOk(int i)
556 {
557 if (plr[myplr].InvList[i].isEmpty())
558 return FALSE;
559 if (plr[myplr].InvList[i]._itype == ITYPE_MISC)
560 return FALSE;
561 if (plr[myplr].InvList[i]._itype == ITYPE_GOLD)
562 return FALSE;
563 if (plr[myplr].InvList[i]._iDurability == plr[myplr].InvList[i]._iMaxDur)
564 return FALSE;
565
566 return TRUE;
567 }
568
S_StartSRepair()569 void S_StartSRepair()
570 {
571 BOOL repairok;
572 int i;
573
574 stextsize = true;
575 repairok = FALSE;
576 storenumh = 0;
577 for (i = 0; i < 48; i++)
578 storehold[i]._itype = ITYPE_NONE;
579 if (!plr[myplr].InvBody[INVLOC_HEAD].isEmpty() && plr[myplr].InvBody[INVLOC_HEAD]._iDurability != plr[myplr].InvBody[INVLOC_HEAD]._iMaxDur) {
580 repairok = TRUE;
581 AddStoreHoldRepair(plr[myplr].InvBody, -1);
582 }
583 if (!plr[myplr].InvBody[INVLOC_CHEST].isEmpty() && plr[myplr].InvBody[INVLOC_CHEST]._iDurability != plr[myplr].InvBody[INVLOC_CHEST]._iMaxDur) {
584 repairok = TRUE;
585 AddStoreHoldRepair(&plr[myplr].InvBody[INVLOC_CHEST], -2);
586 }
587 if (!plr[myplr].InvBody[INVLOC_HAND_LEFT].isEmpty() && plr[myplr].InvBody[INVLOC_HAND_LEFT]._iDurability != plr[myplr].InvBody[INVLOC_HAND_LEFT]._iMaxDur) {
588 repairok = TRUE;
589 AddStoreHoldRepair(&plr[myplr].InvBody[INVLOC_HAND_LEFT], -3);
590 }
591 if (!plr[myplr].InvBody[INVLOC_HAND_RIGHT].isEmpty() && plr[myplr].InvBody[INVLOC_HAND_RIGHT]._iDurability != plr[myplr].InvBody[INVLOC_HAND_RIGHT]._iMaxDur) {
592 repairok = TRUE;
593 AddStoreHoldRepair(&plr[myplr].InvBody[INVLOC_HAND_RIGHT], -4);
594 }
595 for (i = 0; i < plr[myplr]._pNumInv; i++) {
596 if (storenumh >= 48)
597 break;
598 if (SmithRepairOk(i)) {
599 repairok = TRUE;
600 AddStoreHoldRepair(&plr[myplr].InvList[i], i);
601 }
602 }
603 if (!repairok) {
604 stextscrl = false;
605 sprintf(tempstr, "You have nothing to repair. Your gold: %i", plr[myplr]._pGold);
606 AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE);
607 AddSLine(3);
608 AddSLine(21);
609 AddSText(0, 22, TRUE, "Back", COL_WHITE, TRUE);
610 OffsetSTextY(22, 6);
611 return;
612 }
613
614 stextscrl = true;
615 stextsval = 0;
616 stextsmax = plr[myplr]._pNumInv;
617 sprintf(tempstr, "Repair which item? Your gold: %i", plr[myplr]._pGold);
618 AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE);
619 AddSLine(3);
620 AddSLine(21);
621 S_ScrollSSell(stextsval);
622 AddSText(0, 22, TRUE, "Back", COL_WHITE, TRUE);
623 OffsetSTextY(22, 6);
624 }
625
FillManaPlayer()626 void FillManaPlayer()
627 {
628 if (!sgOptions.Gameplay.bAdriaRefillsMana)
629 return;
630 if (plr[myplr]._pMana != plr[myplr]._pMaxMana) {
631 PlaySFX(IS_CAST8);
632 }
633 plr[myplr]._pMana = plr[myplr]._pMaxMana;
634 plr[myplr]._pManaBase = plr[myplr]._pMaxManaBase;
635 drawmanaflag = TRUE;
636 }
637
S_StartWitch()638 void S_StartWitch()
639 {
640 FillManaPlayer();
641 stextsize = false;
642 stextscrl = false;
643 AddSText(0, 2, TRUE, "Witch's shack", COL_GOLD, FALSE);
644 AddSText(0, 9, TRUE, "Would you like to:", COL_GOLD, FALSE);
645 AddSText(0, 12, TRUE, "Talk to Adria", COL_BLUE, TRUE);
646 AddSText(0, 14, TRUE, "Buy items", COL_WHITE, TRUE);
647 AddSText(0, 16, TRUE, "Sell items", COL_WHITE, TRUE);
648 AddSText(0, 18, TRUE, "Recharge staves", COL_WHITE, TRUE);
649 AddSText(0, 20, TRUE, "Leave the shack", COL_WHITE, TRUE);
650 AddSLine(5);
651 storenumh = 20;
652 }
653
S_ScrollWBuy(int idx)654 void S_ScrollWBuy(int idx)
655 {
656 int l, ls;
657
658 ls = idx;
659 ClearSText(5, 21);
660 stextup = 5;
661
662 for (l = 5; l < 20; l += 4) {
663 if (!witchitem[ls].isEmpty()) {
664 text_color iclr = COL_WHITE;
665 if (witchitem[ls]._iMagical) {
666 iclr = COL_BLUE;
667 }
668
669 if (!witchitem[ls]._iStatFlag) {
670 iclr = COL_RED;
671 }
672
673 if (witchitem[ls]._iMagical) {
674 AddSText(20, l, FALSE, witchitem[ls]._iIName, iclr, TRUE);
675 } else {
676 AddSText(20, l, FALSE, witchitem[ls]._iName, iclr, TRUE);
677 }
678
679 AddSTextVal(l, witchitem[ls]._iIvalue);
680 PrintStoreItem(&witchitem[ls], l + 1, iclr);
681 stextdown = l;
682 ls++;
683 }
684 }
685
686 if (stextsel != -1 && !stext[stextsel]._ssel && stextsel != 22)
687 stextsel = stextdown;
688 }
689
S_StartWBuy()690 void S_StartWBuy()
691 {
692 int i;
693
694 stextsize = true;
695 stextscrl = true;
696 stextsval = 0;
697 stextsmax = 20;
698 sprintf(tempstr, "I have these items for sale: Your gold: %i", plr[myplr]._pGold);
699 AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE);
700 AddSLine(3);
701 AddSLine(21);
702 S_ScrollWBuy(stextsval);
703 AddSText(0, 22, TRUE, "Back", COL_WHITE, FALSE);
704 OffsetSTextY(22, 6);
705
706 storenumh = 0;
707 for (i = 0; !witchitem[i].isEmpty(); i++) {
708 storenumh++;
709 }
710 stextsmax = storenumh - 4;
711 if (stextsmax < 0)
712 stextsmax = 0;
713 }
714
WitchSellOk(int i)715 BOOL WitchSellOk(int i)
716 {
717 BOOL rv;
718 ItemStruct *pI;
719
720 rv = FALSE;
721
722 if (i >= 0)
723 pI = &plr[myplr].InvList[i];
724 else
725 pI = &plr[myplr].SpdList[-(i + 1)];
726
727 if (pI->_itype == ITYPE_MISC)
728 rv = TRUE;
729 if (pI->_iMiscId > 29 && pI->_iMiscId < 41)
730 rv = FALSE;
731 if (pI->_iClass == ICLASS_QUEST)
732 rv = FALSE;
733 if (pI->_itype == ITYPE_STAFF && (!gbIsHellfire || pI->_iSpell != SPL_NULL))
734 rv = TRUE;
735 if (pI->IDidx >= IDI_FIRSTQUEST && pI->IDidx <= IDI_LASTQUEST)
736 rv = FALSE;
737 if (pI->IDidx == IDI_LAZSTAFF)
738 rv = FALSE;
739 return rv;
740 }
741
S_StartWSell()742 void S_StartWSell()
743 {
744 int i;
745 BOOL sellok;
746
747 stextsize = true;
748 sellok = FALSE;
749 storenumh = 0;
750
751 for (i = 0; i < 48; i++)
752 storehold[i]._itype = ITYPE_NONE;
753
754 for (i = 0; i < plr[myplr]._pNumInv; i++) {
755 if (storenumh >= 48)
756 break;
757 if (WitchSellOk(i)) {
758 sellok = TRUE;
759 storehold[storenumh] = plr[myplr].InvList[i];
760
761 if (storehold[storenumh]._iMagical != ITEM_QUALITY_NORMAL && storehold[storenumh]._iIdentified)
762 storehold[storenumh]._ivalue = storehold[storenumh]._iIvalue;
763
764 if ((storehold[storenumh]._ivalue >>= 2) == 0)
765 storehold[storenumh]._ivalue = 1;
766
767 storehold[storenumh]._iIvalue = storehold[storenumh]._ivalue;
768 storehidx[storenumh++] = i;
769 }
770 }
771
772 for (i = 0; i < MAXBELTITEMS; i++) {
773 if (storenumh >= 48)
774 break;
775 if (!plr[myplr].SpdList[i].isEmpty() && WitchSellOk(-(i + 1))) {
776 sellok = TRUE;
777 storehold[storenumh] = plr[myplr].SpdList[i];
778
779 if (storehold[storenumh]._iMagical != ITEM_QUALITY_NORMAL && storehold[storenumh]._iIdentified)
780 storehold[storenumh]._ivalue = storehold[storenumh]._iIvalue;
781
782 if ((storehold[storenumh]._ivalue >>= 2) == 0)
783 storehold[storenumh]._ivalue = 1;
784
785 storehold[storenumh]._iIvalue = storehold[storenumh]._ivalue;
786 storehidx[storenumh++] = -(i + 1);
787 }
788 }
789
790 if (!sellok) {
791 stextscrl = false;
792 sprintf(tempstr, "You have nothing I want. Your gold: %i", plr[myplr]._pGold);
793 AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE);
794 AddSLine(3);
795 AddSLine(21);
796 AddSText(0, 22, TRUE, "Back", COL_WHITE, TRUE);
797 OffsetSTextY(22, 6);
798 } else {
799 stextscrl = true;
800 stextsval = 0;
801 stextsmax = plr[myplr]._pNumInv;
802 sprintf(tempstr, "Which item is for sale? Your gold: %i", plr[myplr]._pGold);
803 AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE);
804 AddSLine(3);
805 AddSLine(21);
806 S_ScrollSSell(stextsval);
807 AddSText(0, 22, TRUE, "Back", COL_WHITE, TRUE);
808 OffsetSTextY(22, 6);
809 }
810 }
811
WitchRechargeOk(int i)812 BOOL WitchRechargeOk(int i)
813 {
814 BOOL rv;
815
816 rv = FALSE;
817 if (plr[myplr].InvList[i]._itype == ITYPE_STAFF
818 && plr[myplr].InvList[i]._iCharges != plr[myplr].InvList[i]._iMaxCharges) {
819 rv = TRUE;
820 }
821 if ((plr[myplr].InvList[i]._iMiscId == IMISC_UNIQUE || plr[myplr].InvList[i]._iMiscId == IMISC_STAFF)
822 && plr[myplr].InvList[i]._iCharges < plr[myplr].InvList[i]._iMaxCharges) {
823 rv = TRUE;
824 }
825 return rv;
826 }
827
AddStoreHoldRecharge(ItemStruct itm,int i)828 void AddStoreHoldRecharge(ItemStruct itm, int i)
829 {
830 storehold[storenumh] = itm;
831 storehold[storenumh]._ivalue += spelldata[itm._iSpell].sStaffCost;
832 storehold[storenumh]._ivalue = storehold[storenumh]._ivalue * (storehold[storenumh]._iMaxCharges - storehold[storenumh]._iCharges) / (storehold[storenumh]._iMaxCharges * 2);
833 storehold[storenumh]._iIvalue = storehold[storenumh]._ivalue;
834 storehidx[storenumh] = i;
835 storenumh++;
836 }
837
S_StartWRecharge()838 void S_StartWRecharge()
839 {
840 int i;
841 BOOL rechargeok;
842
843 stextsize = true;
844 rechargeok = FALSE;
845 storenumh = 0;
846
847 for (i = 0; i < 48; i++) {
848 storehold[i]._itype = ITYPE_NONE;
849 }
850
851 if ((plr[myplr].InvBody[INVLOC_HAND_LEFT]._itype == ITYPE_STAFF || plr[myplr].InvBody[INVLOC_HAND_LEFT]._iMiscId == IMISC_UNIQUE)
852 && plr[myplr].InvBody[INVLOC_HAND_LEFT]._iCharges != plr[myplr].InvBody[INVLOC_HAND_LEFT]._iMaxCharges) {
853 rechargeok = TRUE;
854 AddStoreHoldRecharge(plr[myplr].InvBody[INVLOC_HAND_LEFT], -1);
855 }
856
857 for (i = 0; i < plr[myplr]._pNumInv; i++) {
858 if (storenumh >= 48)
859 break;
860 if (WitchRechargeOk(i)) {
861 rechargeok = TRUE;
862 AddStoreHoldRecharge(plr[myplr].InvList[i], i);
863 }
864 }
865
866 if (!rechargeok) {
867 stextscrl = false;
868 sprintf(tempstr, "You have nothing to recharge. Your gold: %i", plr[myplr]._pGold);
869 AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE);
870 AddSLine(3);
871 AddSLine(21);
872 AddSText(0, 22, TRUE, "Back", COL_WHITE, TRUE);
873 OffsetSTextY(22, 6);
874 } else {
875 stextscrl = true;
876 stextsval = 0;
877 stextsmax = plr[myplr]._pNumInv;
878 sprintf(tempstr, "Recharge which item? Your gold: %i", plr[myplr]._pGold);
879 AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE);
880 AddSLine(3);
881 AddSLine(21);
882 S_ScrollSSell(stextsval);
883 AddSText(0, 22, TRUE, "Back", COL_WHITE, TRUE);
884 OffsetSTextY(22, 6);
885 }
886 }
887
S_StartNoMoney()888 void S_StartNoMoney()
889 {
890 StartStore(stextshold);
891 stextscrl = false;
892 stextsize = true;
893 ClearSText(5, 23);
894 AddSText(0, 14, TRUE, "You do not have enough gold", COL_WHITE, TRUE);
895 }
896
S_StartNoRoom()897 void S_StartNoRoom()
898 {
899 StartStore(stextshold);
900 stextscrl = false;
901 ClearSText(5, 23);
902 AddSText(0, 14, TRUE, "You do not have enough room in inventory", COL_WHITE, TRUE);
903 }
904
S_StartConfirm()905 void S_StartConfirm()
906 {
907 BOOL idprint;
908
909 StartStore(stextshold);
910 stextscrl = false;
911 ClearSText(5, 23);
912 text_color iclr = COL_WHITE;
913
914 if (plr[myplr].HoldItem._iMagical != ITEM_QUALITY_NORMAL)
915 iclr = COL_BLUE;
916 if (!plr[myplr].HoldItem._iStatFlag)
917 iclr = COL_RED;
918
919 idprint = plr[myplr].HoldItem._iMagical != ITEM_QUALITY_NORMAL;
920
921 if (stextshold == STORE_SIDENTIFY)
922 idprint = FALSE;
923 if (plr[myplr].HoldItem._iMagical != ITEM_QUALITY_NORMAL && !plr[myplr].HoldItem._iIdentified) {
924 if (stextshold == STORE_SSELL)
925 idprint = FALSE;
926 if (stextshold == STORE_WSELL)
927 idprint = FALSE;
928 if (stextshold == STORE_SREPAIR)
929 idprint = FALSE;
930 if (stextshold == STORE_WRECHARGE)
931 idprint = FALSE;
932 }
933 if (idprint)
934 AddSText(20, 8, FALSE, plr[myplr].HoldItem._iIName, iclr, FALSE);
935 else
936 AddSText(20, 8, FALSE, plr[myplr].HoldItem._iName, iclr, FALSE);
937
938 AddSTextVal(8, plr[myplr].HoldItem._iIvalue);
939 PrintStoreItem(&plr[myplr].HoldItem, 9, iclr);
940
941 switch (stextshold) {
942 case STORE_BBOY:
943 strcpy(tempstr, "Do we have a deal?");
944 break;
945 case STORE_SIDENTIFY:
946 strcpy(tempstr, "Are you sure you want to identify this item?");
947 break;
948 case STORE_HBUY:
949 case STORE_SPBUY:
950 case STORE_WBUY:
951 case STORE_SBUY:
952 strcpy(tempstr, "Are you sure you want to buy this item?");
953 break;
954 case STORE_WRECHARGE:
955 strcpy(tempstr, "Are you sure you want to recharge this item?");
956 break;
957 case STORE_SSELL:
958 case STORE_WSELL:
959 strcpy(tempstr, "Are you sure you want to sell this item?");
960 break;
961 case STORE_SREPAIR:
962 strcpy(tempstr, "Are you sure you want to repair this item?");
963 break;
964 default:
965 app_fatal("Unknown store dialog %d", stextshold);
966 }
967 AddSText(0, 15, TRUE, tempstr, COL_WHITE, FALSE);
968 AddSText(0, 18, TRUE, "Yes", COL_WHITE, TRUE);
969 AddSText(0, 20, TRUE, "No", COL_WHITE, TRUE);
970 }
971
S_StartBoy()972 void S_StartBoy()
973 {
974 stextsize = false;
975 stextscrl = false;
976 AddSText(0, 2, TRUE, "Wirt the Peg-legged boy", COL_GOLD, FALSE);
977 AddSLine(5);
978 if (!boyitem.isEmpty()) {
979 AddSText(0, 8, TRUE, "Talk to Wirt", COL_BLUE, TRUE);
980 AddSText(0, 12, TRUE, "I have something for sale,", COL_GOLD, FALSE);
981 AddSText(0, 14, TRUE, "but it will cost 50 gold", COL_GOLD, FALSE);
982 AddSText(0, 16, TRUE, "just to take a look. ", COL_GOLD, FALSE);
983 AddSText(0, 18, TRUE, "What have you got?", COL_WHITE, TRUE);
984 AddSText(0, 20, TRUE, "Say goodbye", COL_WHITE, TRUE);
985 } else {
986 AddSText(0, 12, TRUE, "Talk to Wirt", COL_BLUE, TRUE);
987 AddSText(0, 18, TRUE, "Say goodbye", COL_WHITE, TRUE);
988 }
989 }
990
S_StartBBoy()991 void S_StartBBoy()
992 {
993 stextsize = true;
994 stextscrl = false;
995 sprintf(tempstr, "I have this item for sale: Your gold: %i", plr[myplr]._pGold);
996 AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE);
997 AddSLine(3);
998 AddSLine(21);
999 text_color iclr = COL_WHITE;
1000
1001 if (boyitem._iMagical != ITEM_QUALITY_NORMAL)
1002 iclr = COL_BLUE;
1003 if (!boyitem._iStatFlag)
1004 iclr = COL_RED;
1005 if (boyitem._iMagical != ITEM_QUALITY_NORMAL)
1006 AddSText(20, 10, FALSE, boyitem._iIName, iclr, TRUE);
1007 else
1008 AddSText(20, 10, FALSE, boyitem._iName, iclr, TRUE);
1009
1010 if (gbIsHellfire)
1011 AddSTextVal(10, boyitem._iIvalue - (boyitem._iIvalue >> 2));
1012 else
1013 AddSTextVal(10, boyitem._iIvalue + (boyitem._iIvalue >> 1));
1014 PrintStoreItem(&boyitem, 11, iclr);
1015 AddSText(0, 22, TRUE, "Leave", COL_WHITE, TRUE);
1016 OffsetSTextY(22, 6);
1017 }
1018
HealPlayer()1019 void HealPlayer()
1020 {
1021 if (plr[myplr]._pHitPoints != plr[myplr]._pMaxHP) {
1022 PlaySFX(IS_CAST8);
1023 }
1024 plr[myplr]._pHitPoints = plr[myplr]._pMaxHP;
1025 plr[myplr]._pHPBase = plr[myplr]._pMaxHPBase;
1026 drawhpflag = TRUE;
1027 }
1028
S_StartHealer()1029 void S_StartHealer()
1030 {
1031 HealPlayer();
1032 stextsize = false;
1033 stextscrl = false;
1034 AddSText(0, 1, TRUE, "Welcome to the", COL_GOLD, FALSE);
1035 AddSText(0, 3, TRUE, "Healer's home", COL_GOLD, FALSE);
1036 AddSText(0, 9, TRUE, "Would you like to:", COL_GOLD, FALSE);
1037 AddSText(0, 12, TRUE, "Talk to Pepin", COL_BLUE, TRUE);
1038 AddSText(0, 14, TRUE, "Buy items", COL_WHITE, TRUE);
1039 AddSText(0, 16, TRUE, "Leave Healer's home", COL_WHITE, TRUE);
1040 AddSLine(5);
1041 storenumh = 20;
1042 }
1043
S_ScrollHBuy(int idx)1044 void S_ScrollHBuy(int idx)
1045 {
1046 int l;
1047
1048 ClearSText(5, 21);
1049 stextup = 5;
1050 for (l = 5; l < 20; l += 4) {
1051 if (!healitem[idx].isEmpty()) {
1052 text_color iclr = COL_WHITE;
1053 if (!healitem[idx]._iStatFlag) {
1054 iclr = COL_RED;
1055 }
1056
1057 AddSText(20, l, FALSE, healitem[idx]._iName, iclr, TRUE);
1058 AddSTextVal(l, healitem[idx]._iIvalue);
1059 PrintStoreItem(&healitem[idx], l + 1, iclr);
1060 stextdown = l;
1061 idx++;
1062 }
1063 }
1064
1065 if (stextsel != -1 && !stext[stextsel]._ssel && stextsel != 22)
1066 stextsel = stextdown;
1067 }
1068
S_StartHBuy()1069 void S_StartHBuy()
1070 {
1071 int i;
1072
1073 stextsize = true;
1074 stextscrl = true;
1075 stextsval = 0;
1076 sprintf(tempstr, "I have these items for sale: Your gold: %i", plr[myplr]._pGold);
1077 AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE);
1078 AddSLine(3);
1079 AddSLine(21);
1080 S_ScrollHBuy(stextsval);
1081 AddSText(0, 22, TRUE, "Back", COL_WHITE, FALSE);
1082 OffsetSTextY(22, 6);
1083
1084 storenumh = 0;
1085 for (i = 0; !healitem[i].isEmpty(); i++) {
1086 storenumh++;
1087 }
1088 stextsmax = storenumh - 4;
1089 if (stextsmax < 0)
1090 stextsmax = 0;
1091 }
1092
S_StartStory()1093 void S_StartStory()
1094 {
1095 stextsize = false;
1096 stextscrl = false;
1097 AddSText(0, 2, TRUE, "The Town Elder", COL_GOLD, FALSE);
1098 AddSText(0, 9, TRUE, "Would you like to:", COL_GOLD, FALSE);
1099 AddSText(0, 12, TRUE, "Talk to Cain", COL_BLUE, TRUE);
1100 AddSText(0, 14, TRUE, "Identify an item", COL_WHITE, TRUE);
1101 AddSText(0, 18, TRUE, "Say goodbye", COL_WHITE, TRUE);
1102 AddSLine(5);
1103 }
1104
IdItemOk(ItemStruct * i)1105 BOOL IdItemOk(ItemStruct *i)
1106 {
1107 if (i->isEmpty()) {
1108 return FALSE;
1109 }
1110 if (i->_iMagical == ITEM_QUALITY_NORMAL) {
1111 return FALSE;
1112 }
1113 return !i->_iIdentified;
1114 }
1115
AddStoreHoldId(ItemStruct itm,int i)1116 void AddStoreHoldId(ItemStruct itm, int i)
1117 {
1118 storehold[storenumh] = itm;
1119 storehold[storenumh]._ivalue = 100;
1120 storehold[storenumh]._iIvalue = 100;
1121 storehidx[storenumh] = i;
1122 storenumh++;
1123 }
1124
S_StartSIdentify()1125 void S_StartSIdentify()
1126 {
1127 BOOL idok;
1128 int i;
1129
1130 idok = FALSE;
1131 stextsize = true;
1132 storenumh = 0;
1133
1134 for (i = 0; i < 48; i++)
1135 storehold[i]._itype = ITYPE_NONE;
1136
1137 if (IdItemOk(&plr[myplr].InvBody[INVLOC_HEAD])) {
1138 idok = TRUE;
1139 AddStoreHoldId(plr[myplr].InvBody[INVLOC_HEAD], -1);
1140 }
1141 if (IdItemOk(&plr[myplr].InvBody[INVLOC_CHEST])) {
1142 idok = TRUE;
1143 AddStoreHoldId(plr[myplr].InvBody[INVLOC_CHEST], -2);
1144 }
1145 if (IdItemOk(&plr[myplr].InvBody[INVLOC_HAND_LEFT])) {
1146 idok = TRUE;
1147 AddStoreHoldId(plr[myplr].InvBody[INVLOC_HAND_LEFT], -3);
1148 }
1149 if (IdItemOk(&plr[myplr].InvBody[INVLOC_HAND_RIGHT])) {
1150 idok = TRUE;
1151 AddStoreHoldId(plr[myplr].InvBody[INVLOC_HAND_RIGHT], -4);
1152 }
1153 if (IdItemOk(&plr[myplr].InvBody[INVLOC_RING_LEFT])) {
1154 idok = TRUE;
1155 AddStoreHoldId(plr[myplr].InvBody[INVLOC_RING_LEFT], -5);
1156 }
1157 if (IdItemOk(&plr[myplr].InvBody[INVLOC_RING_RIGHT])) {
1158 idok = TRUE;
1159 AddStoreHoldId(plr[myplr].InvBody[INVLOC_RING_RIGHT], -6);
1160 }
1161 if (IdItemOk(&plr[myplr].InvBody[INVLOC_AMULET])) {
1162 idok = TRUE;
1163 AddStoreHoldId(plr[myplr].InvBody[INVLOC_AMULET], -7);
1164 }
1165
1166 for (i = 0; i < plr[myplr]._pNumInv; i++) {
1167 if (storenumh >= 48)
1168 break;
1169 if (IdItemOk(&plr[myplr].InvList[i])) {
1170 idok = TRUE;
1171 AddStoreHoldId(plr[myplr].InvList[i], i);
1172 }
1173 }
1174
1175 if (!idok) {
1176 stextscrl = false;
1177 sprintf(tempstr, "You have nothing to identify. Your gold: %i", plr[myplr]._pGold);
1178 AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE);
1179 AddSLine(3);
1180 AddSLine(21);
1181 AddSText(0, 22, TRUE, "Back", COL_WHITE, TRUE);
1182 OffsetSTextY(22, 6);
1183 } else {
1184 stextscrl = true;
1185 stextsval = 0;
1186 stextsmax = plr[myplr]._pNumInv;
1187 sprintf(tempstr, "Identify which item? Your gold: %i", plr[myplr]._pGold);
1188 AddSText(0, 1, TRUE, tempstr, COL_GOLD, FALSE);
1189 AddSLine(3);
1190 AddSLine(21);
1191 S_ScrollSSell(stextsval);
1192 AddSText(0, 22, TRUE, "Back", COL_WHITE, TRUE);
1193 OffsetSTextY(22, 6);
1194 }
1195 }
1196
S_StartIdShow()1197 void S_StartIdShow()
1198 {
1199 StartStore(stextshold);
1200 stextscrl = false;
1201 ClearSText(5, 23);
1202 text_color iclr = COL_WHITE;
1203
1204 if (plr[myplr].HoldItem._iMagical != ITEM_QUALITY_NORMAL)
1205 iclr = COL_BLUE;
1206 if (!plr[myplr].HoldItem._iStatFlag)
1207 iclr = COL_RED;
1208
1209 AddSText(0, 7, TRUE, "This item is:", COL_WHITE, FALSE);
1210 AddSText(20, 11, FALSE, plr[myplr].HoldItem._iIName, iclr, FALSE);
1211 PrintStoreItem(&plr[myplr].HoldItem, 12, iclr);
1212 AddSText(0, 18, TRUE, "Done", COL_WHITE, TRUE);
1213 }
1214
S_StartTalk()1215 void S_StartTalk()
1216 {
1217 int i, sn, sn2, la;
1218
1219 stextsize = false;
1220 stextscrl = false;
1221 sprintf(tempstr, "Talk to %s", talkname[talker]);
1222 AddSText(0, 2, TRUE, tempstr, COL_GOLD, FALSE);
1223 AddSLine(5);
1224 if (gbIsSpawn) {
1225 sprintf(tempstr, "Talking to %s", talkname[talker]);
1226 AddSText(0, 10, TRUE, tempstr, COL_WHITE, FALSE);
1227 AddSText(0, 12, TRUE, "is not available", COL_WHITE, FALSE);
1228 AddSText(0, 14, TRUE, "in the shareware", COL_WHITE, FALSE);
1229 AddSText(0, 16, TRUE, "version", COL_WHITE, FALSE);
1230 AddSText(0, 22, TRUE, "Back", COL_WHITE, TRUE);
1231 return;
1232 }
1233
1234 sn = 0;
1235 for (i = 0; i < MAXQUESTS; i++) {
1236 if (quests[i]._qactive == QUEST_ACTIVE && Qtalklist[talker][i] != TEXT_NONE && quests[i]._qlog)
1237 sn++;
1238 }
1239
1240 if (sn > 6) {
1241 sn = 14 - (sn >> 1);
1242 la = 1;
1243 } else {
1244 sn = 15 - sn;
1245 la = 2;
1246 }
1247
1248 sn2 = sn - 2;
1249
1250 for (i = 0; i < MAXQUESTS; i++) {
1251 if (quests[i]._qactive == QUEST_ACTIVE && Qtalklist[talker][i] != TEXT_NONE && quests[i]._qlog) {
1252 AddSText(0, sn, TRUE, questlist[i]._qlstr, COL_WHITE, TRUE);
1253 sn += la;
1254 }
1255 }
1256 AddSText(0, sn2, TRUE, "Gossip", COL_BLUE, TRUE);
1257 AddSText(0, 22, TRUE, "Back", COL_WHITE, TRUE);
1258 }
1259
S_StartTavern()1260 void S_StartTavern()
1261 {
1262 stextsize = false;
1263 stextscrl = false;
1264 AddSText(0, 1, TRUE, "Welcome to the", COL_GOLD, FALSE);
1265 AddSText(0, 3, TRUE, "Rising Sun", COL_GOLD, FALSE);
1266 AddSText(0, 9, TRUE, "Would you like to:", COL_GOLD, FALSE);
1267 AddSText(0, 12, TRUE, "Talk to Ogden", COL_BLUE, TRUE);
1268 AddSText(0, 18, TRUE, "Leave the tavern", COL_WHITE, TRUE);
1269 AddSLine(5);
1270 storenumh = 20;
1271 }
1272
S_StartBarMaid()1273 void S_StartBarMaid()
1274 {
1275 stextsize = false;
1276 stextscrl = false;
1277 AddSText(0, 2, TRUE, "Gillian", COL_GOLD, FALSE);
1278 AddSText(0, 9, TRUE, "Would you like to:", COL_GOLD, FALSE);
1279 AddSText(0, 12, TRUE, "Talk to Gillian", COL_BLUE, TRUE);
1280 AddSText(0, 18, TRUE, "Say goodbye", COL_WHITE, TRUE);
1281 AddSLine(5);
1282 storenumh = 20;
1283 }
1284
S_StartDrunk()1285 void S_StartDrunk()
1286 {
1287 stextsize = false;
1288 stextscrl = false;
1289 AddSText(0, 2, TRUE, "Farnham the Drunk", COL_GOLD, FALSE);
1290 AddSText(0, 9, TRUE, "Would you like to:", COL_GOLD, FALSE);
1291 AddSText(0, 12, TRUE, "Talk to Farnham", COL_BLUE, TRUE);
1292 AddSText(0, 18, TRUE, "Say Goodbye", COL_WHITE, TRUE);
1293 AddSLine(5);
1294 storenumh = 20;
1295 }
1296
S_SmithEnter()1297 void S_SmithEnter()
1298 {
1299 switch (stextsel) {
1300 case 10:
1301 talker = TOWN_SMITH;
1302 stextlhold = 10;
1303 stextshold = STORE_SMITH;
1304 gossipstart = TEXT_GRISWOLD2;
1305 gossipend = TEXT_GRISWOLD13;
1306 StartStore(STORE_GOSSIP);
1307 break;
1308 case 12:
1309 StartStore(STORE_SBUY);
1310 break;
1311 case 14:
1312 StartStore(STORE_SPBUY);
1313 break;
1314 case 16:
1315 StartStore(STORE_SSELL);
1316 break;
1317 case 18:
1318 StartStore(STORE_SREPAIR);
1319 break;
1320 case 20:
1321 stextflag = STORE_NONE;
1322 break;
1323 }
1324 }
1325
1326 /**
1327 * @brief Purchases an item from the smith.
1328 */
SmithBuyItem()1329 void SmithBuyItem()
1330 {
1331 int idx;
1332
1333 TakePlrsMoney(plr[myplr].HoldItem._iIvalue);
1334 if (plr[myplr].HoldItem._iMagical == ITEM_QUALITY_NORMAL)
1335 plr[myplr].HoldItem._iIdentified = FALSE;
1336 StoreAutoPlace();
1337 idx = stextvhold + ((stextlhold - stextup) >> 2);
1338 if (idx == SMITH_ITEMS - 1) {
1339 smithitem[SMITH_ITEMS - 1]._itype = ITYPE_NONE;
1340 } else {
1341 for (; !smithitem[idx + 1].isEmpty(); idx++) {
1342 smithitem[idx] = smithitem[idx + 1];
1343 }
1344 smithitem[idx]._itype = ITYPE_NONE;
1345 }
1346 CalcPlrInv(myplr, TRUE);
1347 }
1348
S_SBuyEnter()1349 void S_SBuyEnter()
1350 {
1351 int idx, i;
1352 BOOL done;
1353
1354 if (stextsel == 22) {
1355 StartStore(STORE_SMITH);
1356 stextsel = 12;
1357 } else {
1358 stextlhold = stextsel;
1359 stextvhold = stextsval;
1360 stextshold = STORE_SBUY;
1361 idx = stextsval + ((stextsel - stextup) >> 2);
1362 if (plr[myplr]._pGold < smithitem[idx]._iIvalue) {
1363 StartStore(STORE_NOMONEY);
1364 } else {
1365 plr[myplr].HoldItem = smithitem[idx];
1366 SetCursor_(plr[myplr].HoldItem._iCurs + CURSOR_FIRSTITEM);
1367 done = FALSE;
1368 if (AutoEquipEnabled(plr[myplr], plr[myplr].HoldItem) && AutoEquip(myplr, plr[myplr].HoldItem, false)) {
1369 done = TRUE;
1370 }
1371
1372 for (i = 0; i < NUM_INV_GRID_ELEM && !done; i++) {
1373 done = AutoPlace(myplr, i, cursW / 28, cursH / 28, FALSE);
1374 }
1375 if (done)
1376 StartStore(STORE_CONFIRM);
1377 else
1378 StartStore(STORE_NOROOM);
1379 SetCursor_(CURSOR_HAND);
1380 }
1381 }
1382 }
1383
1384 /**
1385 * @brief Purchases a premium item from the smith.
1386 */
SmithBuyPItem()1387 void SmithBuyPItem()
1388 {
1389 int i, xx, idx;
1390
1391 TakePlrsMoney(plr[myplr].HoldItem._iIvalue);
1392 if (plr[myplr].HoldItem._iMagical == ITEM_QUALITY_NORMAL)
1393 plr[myplr].HoldItem._iIdentified = FALSE;
1394 StoreAutoPlace();
1395
1396 idx = stextvhold + ((stextlhold - stextup) >> 2);
1397 xx = 0;
1398 for (i = 0; idx >= 0; i++) {
1399 if (!premiumitem[i].isEmpty()) {
1400 idx--;
1401 xx = i;
1402 }
1403 }
1404
1405 premiumitem[xx]._itype = ITYPE_NONE;
1406 numpremium--;
1407 SpawnPremium(myplr);
1408 }
1409
S_SPBuyEnter()1410 void S_SPBuyEnter()
1411 {
1412 int i, idx, xx;
1413 BOOL done;
1414
1415 if (stextsel == 22) {
1416 StartStore(STORE_SMITH);
1417 stextsel = 14;
1418 } else {
1419 stextshold = STORE_SPBUY;
1420 stextlhold = stextsel;
1421 stextvhold = stextsval;
1422 xx = stextsval + ((stextsel - stextup) >> 2);
1423 idx = 0;
1424 for (i = 0; xx >= 0; i++) {
1425 if (!premiumitem[i].isEmpty()) {
1426 xx--;
1427 idx = i;
1428 }
1429 }
1430 if (plr[myplr]._pGold < premiumitem[idx]._iIvalue) {
1431 StartStore(STORE_NOMONEY);
1432 } else {
1433 plr[myplr].HoldItem = premiumitem[idx];
1434 SetCursor_(plr[myplr].HoldItem._iCurs + CURSOR_FIRSTITEM);
1435 done = FALSE;
1436 if (AutoEquipEnabled(plr[myplr], plr[myplr].HoldItem) && AutoEquip(myplr, plr[myplr].HoldItem, false)) {
1437 done = TRUE;
1438 }
1439
1440 for (i = 0; i < NUM_INV_GRID_ELEM && !done; i++) {
1441 done = AutoPlace(myplr, i, cursW / 28, cursH / 28, FALSE);
1442 }
1443 if (done)
1444 StartStore(STORE_CONFIRM);
1445 else
1446 StartStore(STORE_NOROOM);
1447 SetCursor_(CURSOR_HAND);
1448 }
1449 }
1450 }
1451
StoreGoldFit(int idx)1452 BOOL StoreGoldFit(int idx)
1453 {
1454 int i, sz, cost, numsqrs;
1455
1456 cost = storehold[idx]._iIvalue;
1457 sz = cost / MaxGold;
1458 if (cost % MaxGold != 0)
1459 sz++;
1460
1461 SetCursor_(storehold[idx]._iCurs + CURSOR_FIRSTITEM);
1462 numsqrs = cursW / 28 * (cursH / 28);
1463 SetCursor_(CURSOR_HAND);
1464
1465 if (numsqrs >= sz)
1466 return TRUE;
1467
1468 for (i = 0; i < NUM_INV_GRID_ELEM; i++) {
1469 if (plr[myplr].InvGrid[i] == 0)
1470 numsqrs++;
1471 }
1472
1473 for (i = 0; i < plr[myplr]._pNumInv; i++) {
1474 if (plr[myplr].InvList[i]._itype == ITYPE_GOLD && plr[myplr].InvList[i]._ivalue != MaxGold) {
1475 if (cost + plr[myplr].InvList[i]._ivalue <= MaxGold)
1476 cost = 0;
1477 else
1478 cost -= MaxGold - plr[myplr].InvList[i]._ivalue;
1479 }
1480 }
1481
1482 sz = cost / MaxGold;
1483 if (cost % MaxGold)
1484 sz++;
1485
1486 return numsqrs >= sz;
1487 }
1488
1489 /**
1490 * @brief Add gold pile to the players invetory
1491 * @param v The value of the gold pile
1492 */
PlaceStoreGold(int v)1493 void PlaceStoreGold(int v)
1494 {
1495 BOOL done;
1496 int ii, xx, yy, i;
1497
1498 done = FALSE;
1499
1500 for (i = 0; i < NUM_INV_GRID_ELEM && !done; i++) {
1501 yy = 10 * (i / 10);
1502 xx = i % 10;
1503 if (plr[myplr].InvGrid[xx + yy] == 0) {
1504 ii = plr[myplr]._pNumInv;
1505 GetGoldSeed(myplr, &golditem);
1506 plr[myplr].InvList[ii] = golditem;
1507 plr[myplr]._pNumInv++;
1508 plr[myplr].InvGrid[xx + yy] = plr[myplr]._pNumInv;
1509 plr[myplr].InvList[ii]._ivalue = v;
1510 SetGoldCurs(myplr, ii);
1511 done = TRUE;
1512 }
1513 }
1514 }
1515
1516 /**
1517 * @brief Sells an item from the player's inventory or belt.
1518 */
StoreSellItem()1519 void StoreSellItem()
1520 {
1521 int i, idx, cost;
1522
1523 idx = stextvhold + ((stextlhold - stextup) >> 2);
1524 if (storehidx[idx] >= 0)
1525 RemoveInvItem(myplr, storehidx[idx]);
1526 else
1527 RemoveSpdBarItem(myplr, -(storehidx[idx] + 1));
1528 cost = storehold[idx]._iIvalue;
1529 storenumh--;
1530 if (idx != storenumh) {
1531 while (idx < storenumh) {
1532 storehold[idx] = storehold[idx + 1];
1533 storehidx[idx] = storehidx[idx + 1];
1534 idx++;
1535 }
1536 }
1537 plr[myplr]._pGold += cost;
1538 for (i = 0; i < plr[myplr]._pNumInv && cost > 0; i++) {
1539 if (plr[myplr].InvList[i]._itype == ITYPE_GOLD && plr[myplr].InvList[i]._ivalue != MaxGold) {
1540 if (cost + plr[myplr].InvList[i]._ivalue <= MaxGold) {
1541 plr[myplr].InvList[i]._ivalue += cost;
1542 SetGoldCurs(myplr, i);
1543 cost = 0;
1544 } else {
1545 cost -= MaxGold - plr[myplr].InvList[i]._ivalue;
1546 plr[myplr].InvList[i]._ivalue = MaxGold;
1547 SetGoldCurs(myplr, i);
1548 }
1549 }
1550 }
1551 if (cost > 0) {
1552 while (cost > MaxGold) {
1553 PlaceStoreGold(MaxGold);
1554 cost -= MaxGold;
1555 }
1556 PlaceStoreGold(cost);
1557 }
1558 }
1559
S_SSellEnter()1560 void S_SSellEnter()
1561 {
1562 int idx;
1563
1564 if (stextsel == 22) {
1565 StartStore(STORE_SMITH);
1566 stextsel = 16;
1567 } else {
1568 stextlhold = stextsel;
1569 idx = stextsval + ((stextsel - stextup) >> 2);
1570 stextshold = STORE_SSELL;
1571 stextvhold = stextsval;
1572 plr[myplr].HoldItem = storehold[idx];
1573
1574 if (StoreGoldFit(idx))
1575 StartStore(STORE_CONFIRM);
1576 else
1577 StartStore(STORE_NOROOM);
1578 }
1579 }
1580
1581 /**
1582 * @brief Repairs an item in the player's inventory or body in the smith.
1583 */
SmithRepairItem()1584 void SmithRepairItem()
1585 {
1586 int i, idx;
1587
1588 TakePlrsMoney(plr[myplr].HoldItem._iIvalue);
1589
1590 idx = stextvhold + ((stextlhold - stextup) >> 2);
1591 storehold[idx]._iDurability = storehold[idx]._iMaxDur;
1592
1593 i = storehidx[idx];
1594 if (i < 0) {
1595 if (i == -1)
1596 plr[myplr].InvBody[INVLOC_HEAD]._iDurability = plr[myplr].InvBody[INVLOC_HEAD]._iMaxDur;
1597 if (i == -2)
1598 plr[myplr].InvBody[INVLOC_CHEST]._iDurability = plr[myplr].InvBody[INVLOC_CHEST]._iMaxDur;
1599 if (i == -3)
1600 plr[myplr].InvBody[INVLOC_HAND_LEFT]._iDurability = plr[myplr].InvBody[INVLOC_HAND_LEFT]._iMaxDur;
1601 if (i == -4)
1602 plr[myplr].InvBody[INVLOC_HAND_RIGHT]._iDurability = plr[myplr].InvBody[INVLOC_HAND_RIGHT]._iMaxDur;
1603 } else {
1604 plr[myplr].InvList[i]._iDurability = plr[myplr].InvList[i]._iMaxDur;
1605 }
1606 }
1607
S_SRepairEnter()1608 void S_SRepairEnter()
1609 {
1610 int idx;
1611
1612 if (stextsel == 22) {
1613 StartStore(STORE_SMITH);
1614 stextsel = 18;
1615 } else {
1616 stextshold = STORE_SREPAIR;
1617 stextlhold = stextsel;
1618 stextvhold = stextsval;
1619 idx = stextsval + ((stextsel - stextup) >> 2);
1620 plr[myplr].HoldItem = storehold[idx];
1621 if (plr[myplr]._pGold < storehold[idx]._iIvalue)
1622 StartStore(STORE_NOMONEY);
1623 else
1624 StartStore(STORE_CONFIRM);
1625 }
1626 }
1627
S_WitchEnter()1628 void S_WitchEnter()
1629 {
1630 switch (stextsel) {
1631 case 12:
1632 stextlhold = 12;
1633 talker = TOWN_WITCH;
1634 stextshold = STORE_WITCH;
1635 gossipstart = TEXT_ADRIA2;
1636 gossipend = TEXT_ADRIA13;
1637 StartStore(STORE_GOSSIP);
1638 return;
1639 case 14:
1640 StartStore(STORE_WBUY);
1641 return;
1642 case 16:
1643 StartStore(STORE_WSELL);
1644 return;
1645 case 18:
1646 StartStore(STORE_WRECHARGE);
1647 return;
1648 case 20:
1649 stextflag = STORE_NONE;
1650 break;
1651 }
1652 }
1653
1654 /**
1655 * @brief Purchases an item from the witch.
1656 */
WitchBuyItem()1657 void WitchBuyItem()
1658 {
1659 int idx;
1660
1661 idx = stextvhold + ((stextlhold - stextup) >> 2);
1662
1663 if (idx < 3)
1664 plr[myplr].HoldItem._iSeed = AdvanceRndSeed();
1665
1666 TakePlrsMoney(plr[myplr].HoldItem._iIvalue);
1667 StoreAutoPlace();
1668
1669 if (idx >= 3) {
1670 if (idx == WITCH_ITEMS - 1) {
1671 witchitem[WITCH_ITEMS - 1]._itype = ITYPE_NONE;
1672 } else {
1673 for (; !witchitem[idx + 1].isEmpty(); idx++) {
1674 witchitem[idx] = witchitem[idx + 1];
1675 }
1676 witchitem[idx]._itype = ITYPE_NONE;
1677 }
1678 }
1679
1680 CalcPlrInv(myplr, TRUE);
1681 }
1682
S_WBuyEnter()1683 void S_WBuyEnter()
1684 {
1685 int i, idx;
1686 BOOL done;
1687
1688 if (stextsel == 22) {
1689 StartStore(STORE_WITCH);
1690 stextsel = 14;
1691 } else {
1692 stextlhold = stextsel;
1693 stextvhold = stextsval;
1694 stextshold = STORE_WBUY;
1695 idx = stextsval + ((stextsel - stextup) >> 2);
1696
1697 if (plr[myplr]._pGold < witchitem[idx]._iIvalue) {
1698 StartStore(STORE_NOMONEY);
1699 } else {
1700 plr[myplr].HoldItem = witchitem[idx];
1701 SetCursor_(plr[myplr].HoldItem._iCurs + CURSOR_FIRSTITEM);
1702 done = FALSE;
1703 if (AutoEquipEnabled(plr[myplr], plr[myplr].HoldItem) && AutoEquip(myplr, plr[myplr].HoldItem, false)) {
1704 done = TRUE;
1705 }
1706
1707 for (i = 0; i < NUM_INV_GRID_ELEM && !done; i++) {
1708 done = SpecialAutoPlace(myplr, i, plr[myplr].HoldItem);
1709 }
1710
1711 if (done)
1712 StartStore(STORE_CONFIRM);
1713 else
1714 StartStore(STORE_NOROOM);
1715
1716 SetCursor_(CURSOR_HAND);
1717 }
1718 }
1719 }
1720
S_WSellEnter()1721 void S_WSellEnter()
1722 {
1723 int idx;
1724
1725 if (stextsel == 22) {
1726 StartStore(STORE_WITCH);
1727 stextsel = 16;
1728 } else {
1729 stextlhold = stextsel;
1730 idx = stextsval + ((stextsel - stextup) >> 2);
1731 stextshold = STORE_WSELL;
1732 stextvhold = stextsval;
1733 plr[myplr].HoldItem = storehold[idx];
1734 if (StoreGoldFit(idx))
1735 StartStore(STORE_CONFIRM);
1736 else
1737 StartStore(STORE_NOROOM);
1738 }
1739 }
1740
1741 /**
1742 * @brief Recharges an item in the player's inventory or body in the witch.
1743 */
WitchRechargeItem()1744 void WitchRechargeItem()
1745 {
1746 int i, idx;
1747
1748 TakePlrsMoney(plr[myplr].HoldItem._iIvalue);
1749
1750 idx = stextvhold + ((stextlhold - stextup) >> 2);
1751 storehold[idx]._iCharges = storehold[idx]._iMaxCharges;
1752
1753 i = storehidx[idx];
1754 if (i < 0)
1755 plr[myplr].InvBody[INVLOC_HAND_LEFT]._iCharges = plr[myplr].InvBody[INVLOC_HAND_LEFT]._iMaxCharges;
1756 else
1757 plr[myplr].InvList[i]._iCharges = plr[myplr].InvList[i]._iMaxCharges;
1758
1759 CalcPlrInv(myplr, TRUE);
1760 }
1761
S_WRechargeEnter()1762 void S_WRechargeEnter()
1763 {
1764 int idx;
1765
1766 if (stextsel == 22) {
1767 StartStore(STORE_WITCH);
1768 stextsel = 18;
1769 } else {
1770 stextshold = STORE_WRECHARGE;
1771 stextlhold = stextsel;
1772 stextvhold = stextsval;
1773 idx = stextsval + ((stextsel - stextup) >> 2);
1774 plr[myplr].HoldItem = storehold[idx];
1775 if (plr[myplr]._pGold < storehold[idx]._iIvalue)
1776 StartStore(STORE_NOMONEY);
1777 else
1778 StartStore(STORE_CONFIRM);
1779 }
1780 }
1781
S_BoyEnter()1782 void S_BoyEnter()
1783 {
1784 if (!boyitem.isEmpty() && stextsel == 18) {
1785 if (plr[myplr]._pGold < 50) {
1786 stextshold = STORE_BOY;
1787 stextlhold = 18;
1788 stextvhold = stextsval;
1789 StartStore(STORE_NOMONEY);
1790 } else {
1791 TakePlrsMoney(50);
1792 StartStore(STORE_BBOY);
1793 }
1794 } else if ((stextsel == 8 && !boyitem.isEmpty()) || (stextsel == 12 && boyitem.isEmpty())) {
1795 talker = TOWN_PEGBOY;
1796 stextshold = STORE_BOY;
1797 stextlhold = stextsel;
1798 gossipstart = TEXT_WIRT2;
1799 gossipend = TEXT_WIRT12;
1800 StartStore(STORE_GOSSIP);
1801 } else {
1802 stextflag = STORE_NONE;
1803 }
1804 }
1805
BoyBuyItem()1806 void BoyBuyItem()
1807 {
1808 TakePlrsMoney(plr[myplr].HoldItem._iIvalue);
1809 StoreAutoPlace();
1810 boyitem._itype = ITYPE_NONE;
1811 stextshold = STORE_BOY;
1812 CalcPlrInv(myplr, TRUE);
1813 stextlhold = 12;
1814 }
1815
1816 /**
1817 * @brief Purchases an item from the healer.
1818 */
HealerBuyItem()1819 void HealerBuyItem()
1820 {
1821 int idx;
1822
1823 idx = stextvhold + ((stextlhold - stextup) >> 2);
1824 if (!gbIsMultiplayer) {
1825 if (idx < 2)
1826 plr[myplr].HoldItem._iSeed = AdvanceRndSeed();
1827 } else {
1828 if (idx < 3)
1829 plr[myplr].HoldItem._iSeed = AdvanceRndSeed();
1830 }
1831
1832 TakePlrsMoney(plr[myplr].HoldItem._iIvalue);
1833 if (plr[myplr].HoldItem._iMagical == ITEM_QUALITY_NORMAL)
1834 plr[myplr].HoldItem._iIdentified = FALSE;
1835 StoreAutoPlace();
1836
1837 if (!gbIsMultiplayer) {
1838 if (idx < 2)
1839 return;
1840 } else {
1841 if (idx < 3)
1842 return;
1843 }
1844 idx = stextvhold + ((stextlhold - stextup) >> 2);
1845 if (idx == 19) {
1846 healitem[19]._itype = ITYPE_NONE;
1847 } else {
1848 for (; !healitem[idx + 1].isEmpty(); idx++) {
1849 healitem[idx] = healitem[idx + 1];
1850 }
1851 healitem[idx]._itype = ITYPE_NONE;
1852 }
1853 CalcPlrInv(myplr, TRUE);
1854 }
1855
S_BBuyEnter()1856 void S_BBuyEnter()
1857 {
1858 if (stextsel != 10) {
1859 stextflag = STORE_NONE;
1860 return;
1861 }
1862
1863 stextshold = STORE_BBOY;
1864 stextvhold = stextsval;
1865 stextlhold = 10;
1866 int price = boyitem._iIvalue;
1867 if (gbIsHellfire)
1868 price -= boyitem._iIvalue >> 2;
1869 else
1870 price += boyitem._iIvalue >> 1;
1871
1872 if (plr[myplr]._pGold < price) {
1873 StartStore(STORE_NOMONEY);
1874 return;
1875 }
1876
1877 plr[myplr].HoldItem = boyitem;
1878 plr[myplr].HoldItem._iIvalue = price;
1879 SetCursor_(plr[myplr].HoldItem._iCurs + CURSOR_FIRSTITEM);
1880
1881 bool done = false;
1882 if (AutoEquipEnabled(plr[myplr], plr[myplr].HoldItem) && AutoEquip(myplr, plr[myplr].HoldItem, false)) {
1883 done = true;
1884 }
1885
1886 for (int i = 0; i < NUM_INV_GRID_ELEM && !done; i++) {
1887 done = AutoPlace(myplr, i, cursW / 28, cursH / 28, false);
1888 }
1889
1890 StartStore(done ? STORE_CONFIRM : STORE_NOROOM);
1891
1892 SetCursor_(CURSOR_HAND);
1893 }
1894
StoryIdItem()1895 void StoryIdItem()
1896 {
1897 int idx;
1898
1899 idx = storehidx[((stextlhold - stextup) >> 2) + stextvhold];
1900 if (idx < 0) {
1901 if (idx == -1)
1902 plr[myplr].InvBody[INVLOC_HEAD]._iIdentified = TRUE;
1903 if (idx == -2)
1904 plr[myplr].InvBody[INVLOC_CHEST]._iIdentified = TRUE;
1905 if (idx == -3)
1906 plr[myplr].InvBody[INVLOC_HAND_LEFT]._iIdentified = TRUE;
1907 if (idx == -4)
1908 plr[myplr].InvBody[INVLOC_HAND_RIGHT]._iIdentified = TRUE;
1909 if (idx == -5)
1910 plr[myplr].InvBody[INVLOC_RING_LEFT]._iIdentified = TRUE;
1911 if (idx == -6)
1912 plr[myplr].InvBody[INVLOC_RING_RIGHT]._iIdentified = TRUE;
1913 if (idx == -7)
1914 plr[myplr].InvBody[INVLOC_AMULET]._iIdentified = TRUE;
1915 } else {
1916 plr[myplr].InvList[idx]._iIdentified = TRUE;
1917 }
1918 plr[myplr].HoldItem._iIdentified = TRUE;
1919 TakePlrsMoney(plr[myplr].HoldItem._iIvalue);
1920 CalcPlrInv(myplr, TRUE);
1921 }
1922
S_ConfirmEnter()1923 void S_ConfirmEnter()
1924 {
1925 if (stextsel == 18) {
1926 switch (stextshold) {
1927 case STORE_SBUY:
1928 SmithBuyItem();
1929 break;
1930 case STORE_SSELL:
1931 case STORE_WSELL:
1932 StoreSellItem();
1933 break;
1934 case STORE_SREPAIR:
1935 SmithRepairItem();
1936 break;
1937 case STORE_WBUY:
1938 WitchBuyItem();
1939 break;
1940 case STORE_WRECHARGE:
1941 WitchRechargeItem();
1942 break;
1943 case STORE_BBOY:
1944 BoyBuyItem();
1945 break;
1946 case STORE_HBUY:
1947 HealerBuyItem();
1948 break;
1949 case STORE_SIDENTIFY:
1950 StoryIdItem();
1951 StartStore(STORE_IDSHOW);
1952 return;
1953 case STORE_SPBUY:
1954 SmithBuyPItem();
1955 break;
1956 default:
1957 break;
1958 }
1959 }
1960
1961 StartStore(stextshold);
1962
1963 if (stextsel == 22)
1964 return;
1965
1966 stextsel = stextlhold;
1967 stextsval = std::min(stextvhold, stextsmax);
1968
1969 while (stextsel != -1 && !stext[stextsel]._ssel) {
1970 stextsel--;
1971 }
1972 }
1973
S_HealerEnter()1974 void S_HealerEnter()
1975 {
1976 switch (stextsel) {
1977 case 12:
1978 stextlhold = 12;
1979 talker = TOWN_HEALER;
1980 stextshold = STORE_HEALER;
1981 gossipstart = TEXT_PEPIN2;
1982 gossipend = TEXT_PEPIN11;
1983 StartStore(STORE_GOSSIP);
1984 break;
1985 case 14:
1986 StartStore(STORE_HBUY);
1987 break;
1988 case 16:
1989 stextflag = STORE_NONE;
1990 break;
1991 }
1992 }
1993
S_HBuyEnter()1994 void S_HBuyEnter()
1995 {
1996 int i, idx;
1997 BOOL done;
1998
1999 if (stextsel == 22) {
2000 StartStore(STORE_HEALER);
2001 stextsel = 16;
2002 } else {
2003 stextlhold = stextsel;
2004 stextvhold = stextsval;
2005 stextshold = STORE_HBUY;
2006 idx = stextsval + ((stextsel - stextup) >> 2);
2007
2008 if (plr[myplr]._pGold < healitem[idx]._iIvalue) {
2009 StartStore(STORE_NOMONEY);
2010 } else {
2011 plr[myplr].HoldItem = healitem[idx];
2012 SetCursor_(plr[myplr].HoldItem._iCurs + CURSOR_FIRSTITEM);
2013 done = FALSE;
2014 if (AutoEquipEnabled(plr[myplr], plr[myplr].HoldItem) && AutoEquip(myplr, plr[myplr].HoldItem, false)) {
2015 done = TRUE;
2016 }
2017
2018 for (i = 0; i < NUM_INV_GRID_ELEM && !done; i++) {
2019 done = SpecialAutoPlace(myplr, i, plr[myplr].HoldItem);
2020 }
2021
2022 if (done)
2023 StartStore(STORE_CONFIRM);
2024 else
2025 StartStore(STORE_NOROOM);
2026
2027 SetCursor_(CURSOR_HAND);
2028 }
2029 }
2030 }
2031
S_StoryEnter()2032 void S_StoryEnter()
2033 {
2034 switch (stextsel) {
2035 case 12:
2036 stextlhold = 12;
2037 talker = TOWN_STORY;
2038 stextshold = STORE_STORY;
2039 gossipstart = TEXT_STORY2;
2040 gossipend = TEXT_STORY11;
2041 StartStore(STORE_GOSSIP);
2042 break;
2043 case 14:
2044 StartStore(STORE_SIDENTIFY);
2045 break;
2046 case 18:
2047 stextflag = STORE_NONE;
2048 break;
2049 }
2050 }
2051
S_SIDEnter()2052 void S_SIDEnter()
2053 {
2054 int idx;
2055
2056 if (stextsel == 22) {
2057 StartStore(STORE_STORY);
2058 stextsel = 14;
2059 } else {
2060 stextshold = STORE_SIDENTIFY;
2061 stextlhold = stextsel;
2062 stextvhold = stextsval;
2063 idx = stextsval + ((stextsel - stextup) >> 2);
2064 plr[myplr].HoldItem = storehold[idx];
2065 if (plr[myplr]._pGold < storehold[idx]._iIvalue)
2066 StartStore(STORE_NOMONEY);
2067 else
2068 StartStore(STORE_CONFIRM);
2069 }
2070 }
2071
S_TalkEnter()2072 void S_TalkEnter()
2073 {
2074 int i, tq, sn, la;
2075
2076 if (stextsel == 22) {
2077 StartStore(stextshold);
2078 stextsel = stextlhold;
2079 return;
2080 }
2081
2082 sn = 0;
2083 for (i = 0; i < MAXQUESTS; i++) {
2084 if (quests[i]._qactive == QUEST_ACTIVE && Qtalklist[talker][i] != TEXT_NONE && quests[i]._qlog)
2085 sn++;
2086 }
2087 if (sn > 6) {
2088 sn = 14 - (sn >> 1);
2089 la = 1;
2090 } else {
2091 sn = 15 - sn;
2092 la = 2;
2093 }
2094
2095 if (stextsel == sn - 2) {
2096 SetRndSeed(towner[talker]._tSeed);
2097 tq = gossipstart + random_(0, gossipend - gossipstart + 1);
2098 InitQTextMsg(tq);
2099 return;
2100 }
2101
2102 for (i = 0; i < MAXQUESTS; i++) {
2103 if (quests[i]._qactive == QUEST_ACTIVE && Qtalklist[talker][i] != TEXT_NONE && quests[i]._qlog) {
2104 if (sn == stextsel) {
2105 InitQTextMsg(Qtalklist[talker][i]);
2106 }
2107 sn += la;
2108 }
2109 }
2110 }
2111
S_TavernEnter()2112 void S_TavernEnter()
2113 {
2114 switch (stextsel) {
2115 case 12:
2116 stextlhold = 12;
2117 talker = TOWN_TAVERN;
2118 stextshold = STORE_TAVERN;
2119 gossipstart = TEXT_OGDEN2;
2120 gossipend = TEXT_OGDEN10;
2121 StartStore(STORE_GOSSIP);
2122 break;
2123 case 18:
2124 stextflag = STORE_NONE;
2125 break;
2126 }
2127 }
2128
S_BarmaidEnter()2129 void S_BarmaidEnter()
2130 {
2131 switch (stextsel) {
2132 case 12:
2133 stextlhold = 12;
2134 talker = TOWN_BMAID;
2135 stextshold = STORE_BARMAID;
2136 gossipstart = TEXT_GILLIAN2;
2137 gossipend = TEXT_GILLIAN10;
2138 StartStore(STORE_GOSSIP);
2139 break;
2140 case 18:
2141 stextflag = STORE_NONE;
2142 break;
2143 }
2144 }
2145
S_DrunkEnter()2146 void S_DrunkEnter()
2147 {
2148 switch (stextsel) {
2149 case 12:
2150 stextlhold = 12;
2151 talker = TOWN_DRUNK;
2152 stextshold = STORE_DRUNK;
2153 gossipstart = TEXT_FARNHAM2;
2154 gossipend = TEXT_FARNHAM13;
2155 StartStore(STORE_GOSSIP);
2156 break;
2157 case 18:
2158 stextflag = STORE_NONE;
2159 break;
2160 }
2161 }
2162
2163 }
2164
2165 ItemStruct golditem;
2166
2167 Uint8 *pSTextBoxCels;
2168 Uint8 *pSPentSpn2Cels;
2169 Uint8 *pSTextSlidCels;
2170
2171 talk_id stextflag;
2172
2173 int storenumh;
2174 char storehidx[48];
2175 ItemStruct storehold[48];
2176
2177 ItemStruct smithitem[SMITH_ITEMS];
2178 int numpremium;
2179 int premiumlevel;
2180 ItemStruct premiumitem[SMITH_PREMIUM_ITEMS];
2181
2182 ItemStruct healitem[20];
2183
2184 ItemStruct witchitem[WITCH_ITEMS];
2185
2186 int boylevel;
2187 ItemStruct boyitem;
2188
AddStoreHoldRepair(ItemStruct * itm,int i)2189 void AddStoreHoldRepair(ItemStruct *itm, int i)
2190 {
2191 ItemStruct *item;
2192 int v;
2193
2194 item = &storehold[storenumh];
2195 storehold[storenumh] = *itm;
2196
2197 int due = item->_iMaxDur - item->_iDurability;
2198 if (item->_iMagical != ITEM_QUALITY_NORMAL && item->_iIdentified) {
2199 v = 30 * item->_iIvalue * due / (item->_iMaxDur * 100 * 2);
2200 if (v == 0)
2201 return;
2202 } else {
2203 v = item->_ivalue * due / (item->_iMaxDur * 2);
2204 v = std::max(v, 1);
2205 }
2206 item->_iIvalue = v;
2207 item->_ivalue = v;
2208 storehidx[storenumh] = i;
2209 storenumh++;
2210 }
2211
InitStores()2212 void InitStores()
2213 {
2214 pSTextBoxCels = LoadFileInMem("Data\\TextBox2.CEL", NULL);
2215 pSPentSpn2Cels = LoadFileInMem("Data\\PentSpn2.CEL", NULL);
2216 pSTextSlidCels = LoadFileInMem("Data\\TextSlid.CEL", NULL);
2217 ClearSText(0, STORE_LINES);
2218 stextflag = STORE_NONE;
2219 stextsize = false;
2220 stextscrl = false;
2221 numpremium = 0;
2222 premiumlevel = 1;
2223
2224 for (int i = 0; i < SMITH_PREMIUM_ITEMS; i++)
2225 premiumitem[i]._itype = ITYPE_NONE;
2226
2227 boyitem._itype = ITYPE_NONE;
2228 boylevel = 0;
2229 }
2230
PentSpn2Spin()2231 int PentSpn2Spin()
2232 {
2233 return (SDL_GetTicks() / 50) % 8 + 1;
2234 }
2235
SetupTownStores()2236 void SetupTownStores()
2237 {
2238 int i, l;
2239
2240 SetRndSeed(glSeedTbl[currlevel] * SDL_GetTicks());
2241 if (!gbIsMultiplayer) {
2242 l = 0;
2243 for (i = 0; i < NUMLEVELS; i++) {
2244 if (plr[myplr]._pLvlVisited[i])
2245 l = i;
2246 }
2247 } else {
2248 l = plr[myplr]._pLevel >> 1;
2249 }
2250 l += 2;
2251 if (l < 6)
2252 l = 6;
2253 if (l > 16)
2254 l = 16;
2255 SpawnStoreGold();
2256 SpawnSmith(l);
2257 SpawnWitch(l);
2258 SpawnHealer(l);
2259 SpawnBoy(plr[myplr]._pLevel);
2260 SpawnPremium(myplr);
2261 }
2262
FreeStoreMem()2263 void FreeStoreMem()
2264 {
2265 MemFreeDbg(pSTextBoxCels);
2266 MemFreeDbg(pSPentSpn2Cels);
2267 MemFreeDbg(pSTextSlidCels);
2268 }
2269
PrintSString(CelOutputBuffer out,int x,int y,bool cjustflag,const char * str,text_color col,int val)2270 void PrintSString(CelOutputBuffer out, int x, int y, bool cjustflag, const char *str, text_color col, int val)
2271 {
2272 int len, width, sx, sy, i, k, s;
2273 int xx, yy;
2274 BYTE c;
2275 char valstr[32];
2276
2277 s = y * 12 + stext[y]._syoff;
2278 if (stextsize)
2279 xx = PANEL_X + 32;
2280 else
2281 xx = PANEL_X + 352;
2282 sx = xx + x;
2283 sy = s + 44 + UI_OFFSET_Y;
2284 len = strlen(str);
2285 if (stextsize)
2286 yy = 577;
2287 else
2288 yy = 257;
2289 k = 0;
2290 if (cjustflag) {
2291 width = 0;
2292 for (i = 0; i < len; i++)
2293 width += fontkern[fontframe[gbFontTransTbl[(BYTE)str[i]]]] + 1;
2294 if (width < yy)
2295 k = (yy - width) >> 1;
2296 sx += k;
2297 }
2298 if (stextsel == y) {
2299 CelDrawTo(out, cjustflag ? xx + x + k - 20 : xx + x - 20, s + 45 + UI_OFFSET_Y, pSPentSpn2Cels, PentSpn2Spin(), 12);
2300 }
2301 for (i = 0; i < len; i++) {
2302 c = fontframe[gbFontTransTbl[(BYTE)str[i]]];
2303 k += fontkern[c] + 1;
2304 if (c != 0 && k <= yy) {
2305 PrintChar(out, sx, sy, c, col);
2306 }
2307 sx += fontkern[c] + 1;
2308 }
2309 if (!cjustflag && val >= 0) {
2310 sprintf(valstr, "%i", val);
2311 sx = PANEL_X + 592 - x;
2312 len = strlen(valstr);
2313 for (i = len - 1; i >= 0; i--) {
2314 c = fontframe[gbFontTransTbl[(BYTE)valstr[i]]];
2315 sx -= fontkern[c] + 1;
2316 if (c != 0) {
2317 PrintChar(out, sx, sy, c, col);
2318 }
2319 }
2320 }
2321 if (stextsel == y) {
2322 CelDrawTo(out, cjustflag ? (xx + x + k + 4) : (PANEL_X + 596 - x), s + 45 + UI_OFFSET_Y, pSPentSpn2Cels, PentSpn2Spin(), 12);
2323 }
2324 }
2325
DrawSLine(CelOutputBuffer out,int y)2326 void DrawSLine(CelOutputBuffer out, int y)
2327 {
2328 const int sy = y * 12;
2329 BYTE *src, *dst;
2330 int width;
2331 if (stextsize) {
2332 src = out.at(PANEL_LEFT + 26, 25 + UI_OFFSET_Y);
2333 dst = out.at(26 + PANEL_X, sy + 38 + UI_OFFSET_Y);
2334 width = 587; // BUGFIX: should be 587, not 586 (fixed)
2335 } else {
2336 src = out.at(PANEL_LEFT + 346, 25 + UI_OFFSET_Y);
2337 dst = out.at(346 + PANEL_X, sy + 38 + UI_OFFSET_Y);
2338 width = 267; // BUGFIX: should be 267, not 266 (fixed)
2339 }
2340
2341 for (int i = 0; i < 3; i++, src += out.pitch(), dst += out.pitch())
2342 memcpy(dst, src, width);
2343 }
2344
DrawSTextHelp()2345 void DrawSTextHelp()
2346 {
2347 stextsel = -1;
2348 stextsize = true;
2349 }
2350
ClearSText(int s,int e)2351 void ClearSText(int s, int e)
2352 {
2353 int i;
2354
2355 for (i = s; i < e; i++) {
2356 stext[i]._sx = 0;
2357 stext[i]._syoff = 0;
2358 stext[i]._sstr[0] = 0;
2359 stext[i]._sjust = false;
2360 stext[i]._sclr = COL_WHITE;
2361 stext[i]._sline = 0;
2362 stext[i]._ssel = FALSE;
2363 stext[i]._sval = -1;
2364 }
2365 }
2366
StartStore(talk_id s)2367 void StartStore(talk_id s)
2368 {
2369 sbookflag = FALSE;
2370 invflag = FALSE;
2371 chrflag = FALSE;
2372 questlog = FALSE;
2373 dropGoldFlag = FALSE;
2374 ClearSText(0, STORE_LINES);
2375 ReleaseStoreBtn();
2376 switch (s) {
2377 case STORE_SMITH:
2378 S_StartSmith();
2379 break;
2380 case STORE_SBUY:
2381 if (storenumh > 0)
2382 S_StartSBuy();
2383 else
2384 S_StartSmith();
2385 break;
2386 case STORE_SSELL:
2387 S_StartSSell();
2388 break;
2389 case STORE_SREPAIR:
2390 S_StartSRepair();
2391 break;
2392 case STORE_WITCH:
2393 S_StartWitch();
2394 break;
2395 case STORE_WBUY:
2396 if (storenumh > 0)
2397 S_StartWBuy();
2398 break;
2399 case STORE_WSELL:
2400 S_StartWSell();
2401 break;
2402 case STORE_WRECHARGE:
2403 S_StartWRecharge();
2404 break;
2405 case STORE_NOMONEY:
2406 S_StartNoMoney();
2407 break;
2408 case STORE_NOROOM:
2409 S_StartNoRoom();
2410 break;
2411 case STORE_CONFIRM:
2412 S_StartConfirm();
2413 break;
2414 case STORE_BOY:
2415 S_StartBoy();
2416 break;
2417 case STORE_BBOY:
2418 S_StartBBoy();
2419 break;
2420 case STORE_HEALER:
2421 S_StartHealer();
2422 break;
2423 case STORE_STORY:
2424 S_StartStory();
2425 break;
2426 case STORE_HBUY:
2427 if (storenumh > 0)
2428 S_StartHBuy();
2429 break;
2430 case STORE_SIDENTIFY:
2431 S_StartSIdentify();
2432 break;
2433 case STORE_SPBUY:
2434 if (!S_StartSPBuy())
2435 return;
2436 break;
2437 case STORE_GOSSIP:
2438 S_StartTalk();
2439 break;
2440 case STORE_IDSHOW:
2441 S_StartIdShow();
2442 break;
2443 case STORE_TAVERN:
2444 S_StartTavern();
2445 break;
2446 case STORE_DRUNK:
2447 S_StartDrunk();
2448 break;
2449 case STORE_BARMAID:
2450 S_StartBarMaid();
2451 break;
2452 case STORE_NONE:
2453 break;
2454 }
2455
2456 stextsel = -1;
2457 for (int i = 0; i < STORE_LINES; i++) {
2458 if (stext[i]._ssel) {
2459 stextsel = i;
2460 break;
2461 }
2462 }
2463
2464 stextflag = s;
2465 }
2466
DrawSText(CelOutputBuffer out)2467 void DrawSText(CelOutputBuffer out)
2468 {
2469 int i;
2470
2471 if (!stextsize)
2472 DrawSTextBack(out);
2473 else
2474 DrawQTextBack(out);
2475
2476 if (stextscrl) {
2477 switch (stextflag) {
2478 case STORE_SBUY:
2479 S_ScrollSBuy(stextsval);
2480 break;
2481 case STORE_SSELL:
2482 case STORE_SREPAIR:
2483 case STORE_WSELL:
2484 case STORE_WRECHARGE:
2485 case STORE_SIDENTIFY:
2486 S_ScrollSSell(stextsval);
2487 break;
2488 case STORE_WBUY:
2489 S_ScrollWBuy(stextsval);
2490 break;
2491 case STORE_HBUY:
2492 S_ScrollHBuy(stextsval);
2493 break;
2494 case STORE_SPBUY:
2495 S_ScrollSPBuy(stextsval);
2496 break;
2497 default:
2498 break;
2499 }
2500 }
2501
2502 for (i = 0; i < STORE_LINES; i++) {
2503 if (stext[i]._sline)
2504 DrawSLine(out, i);
2505 if (stext[i]._sstr[0])
2506 PrintSString(out, stext[i]._sx, i, stext[i]._sjust, stext[i]._sstr, stext[i]._sclr, stext[i]._sval);
2507 }
2508
2509 if (stextscrl)
2510 DrawSSlider(out, 4, 20);
2511 }
2512
STextESC()2513 void STextESC()
2514 {
2515 if (qtextflag) {
2516 qtextflag = FALSE;
2517 if (leveltype == DTYPE_TOWN)
2518 stream_stop();
2519 } else {
2520 switch (stextflag) {
2521 case STORE_SMITH:
2522 case STORE_WITCH:
2523 case STORE_BOY:
2524 case STORE_BBOY:
2525 case STORE_HEALER:
2526 case STORE_STORY:
2527 case STORE_TAVERN:
2528 case STORE_DRUNK:
2529 case STORE_BARMAID:
2530 stextflag = STORE_NONE;
2531 break;
2532 case STORE_GOSSIP:
2533 StartStore(stextshold);
2534 stextsel = stextlhold;
2535 break;
2536 case STORE_SBUY:
2537 StartStore(STORE_SMITH);
2538 stextsel = 12;
2539 break;
2540 case STORE_SPBUY:
2541 StartStore(STORE_SMITH);
2542 stextsel = 14;
2543 break;
2544 case STORE_SSELL:
2545 StartStore(STORE_SMITH);
2546 stextsel = 16;
2547 break;
2548 case STORE_SREPAIR:
2549 StartStore(STORE_SMITH);
2550 stextsel = 18;
2551 break;
2552 case STORE_WBUY:
2553 StartStore(STORE_WITCH);
2554 stextsel = 14;
2555 break;
2556 case STORE_WSELL:
2557 StartStore(STORE_WITCH);
2558 stextsel = 16;
2559 break;
2560 case STORE_WRECHARGE:
2561 StartStore(STORE_WITCH);
2562 stextsel = 18;
2563 break;
2564 case STORE_HBUY:
2565 StartStore(STORE_HEALER);
2566 stextsel = 16;
2567 break;
2568 case STORE_SIDENTIFY:
2569 StartStore(STORE_STORY);
2570 stextsel = 14;
2571 break;
2572 case STORE_IDSHOW:
2573 StartStore(STORE_SIDENTIFY);
2574 break;
2575 case STORE_NOMONEY:
2576 case STORE_NOROOM:
2577 case STORE_CONFIRM:
2578 StartStore(stextshold);
2579 stextsel = stextlhold;
2580 stextsval = stextvhold;
2581 break;
2582 case STORE_NONE:
2583 break;
2584 }
2585 }
2586 }
2587
STextUp()2588 void STextUp()
2589 {
2590 PlaySFX(IS_TITLEMOV);
2591 if (stextsel == -1) {
2592 return;
2593 }
2594
2595 if (stextscrl) {
2596 if (stextsel == stextup) {
2597 if (stextsval)
2598 stextsval--;
2599 return;
2600 }
2601
2602 stextsel--;
2603 while (!stext[stextsel]._ssel) {
2604 if (!stextsel)
2605 stextsel = STORE_LINES - 1;
2606 else
2607 stextsel--;
2608 }
2609 return;
2610 }
2611
2612 if (!stextsel)
2613 stextsel = STORE_LINES - 1;
2614 else
2615 stextsel--;
2616
2617 while (!stext[stextsel]._ssel) {
2618 if (!stextsel)
2619 stextsel = STORE_LINES - 1;
2620 else
2621 stextsel--;
2622 }
2623 }
2624
STextDown()2625 void STextDown()
2626 {
2627 PlaySFX(IS_TITLEMOV);
2628 if (stextsel == -1) {
2629 return;
2630 }
2631
2632 if (stextscrl) {
2633 if (stextsel == stextdown) {
2634 if (stextsval < stextsmax)
2635 stextsval++;
2636 return;
2637 }
2638
2639 stextsel++;
2640 while (!stext[stextsel]._ssel) {
2641 if (stextsel == STORE_LINES - 1)
2642 stextsel = 0;
2643 else
2644 stextsel++;
2645 }
2646 return;
2647 }
2648
2649 if (stextsel == STORE_LINES - 1)
2650 stextsel = 0;
2651 else
2652 stextsel++;
2653
2654 while (!stext[stextsel]._ssel) {
2655 if (stextsel == STORE_LINES - 1)
2656 stextsel = 0;
2657 else
2658 stextsel++;
2659 }
2660 }
2661
STextPrior()2662 void STextPrior()
2663 {
2664 PlaySFX(IS_TITLEMOV);
2665 if (stextsel != -1 && stextscrl) {
2666 if (stextsel == stextup) {
2667 if (stextsval)
2668 stextsval -= 4;
2669 stextsval = stextsval;
2670 if (stextsval < 0)
2671 stextsval = 0;
2672 } else {
2673 stextsel = stextup;
2674 }
2675 }
2676 }
2677
STextNext()2678 void STextNext()
2679 {
2680 PlaySFX(IS_TITLEMOV);
2681 if (stextsel != -1 && stextscrl) {
2682 if (stextsel == stextdown) {
2683 if (stextsval < stextsmax)
2684 stextsval += 4;
2685 if (stextsval > stextsmax)
2686 stextsval = stextsmax;
2687 } else {
2688 stextsel = stextdown;
2689 }
2690 }
2691 }
2692
SetGoldCurs(int pnum,int i)2693 void SetGoldCurs(int pnum, int i)
2694 {
2695 SetPlrHandGoldCurs(&plr[pnum].InvList[i]);
2696 }
2697
SetSpdbarGoldCurs(int pnum,int i)2698 void SetSpdbarGoldCurs(int pnum, int i)
2699 {
2700 SetPlrHandGoldCurs(&plr[pnum].SpdList[i]);
2701 }
2702
TakePlrsMoney(int cost)2703 void TakePlrsMoney(int cost)
2704 {
2705 int i;
2706
2707 plr[myplr]._pGold = CalculateGold(myplr) - cost;
2708 for (i = 0; i < MAXBELTITEMS && cost > 0; i++) {
2709 if (plr[myplr].SpdList[i]._itype == ITYPE_GOLD && plr[myplr].SpdList[i]._ivalue != MaxGold) {
2710 if (cost < plr[myplr].SpdList[i]._ivalue) {
2711 plr[myplr].SpdList[i]._ivalue -= cost;
2712 SetSpdbarGoldCurs(myplr, i);
2713 cost = 0;
2714 } else {
2715 cost -= plr[myplr].SpdList[i]._ivalue;
2716 RemoveSpdBarItem(myplr, i);
2717 i = -1;
2718 }
2719 }
2720 }
2721 if (cost > 0) {
2722 for (i = 0; i < MAXBELTITEMS && cost > 0; i++) {
2723 if (plr[myplr].SpdList[i]._itype == ITYPE_GOLD) {
2724 if (cost < plr[myplr].SpdList[i]._ivalue) {
2725 plr[myplr].SpdList[i]._ivalue -= cost;
2726 SetSpdbarGoldCurs(myplr, i);
2727 cost = 0;
2728 } else {
2729 cost -= plr[myplr].SpdList[i]._ivalue;
2730 RemoveSpdBarItem(myplr, i);
2731 i = -1;
2732 }
2733 }
2734 }
2735 }
2736 force_redraw = 255;
2737 if (cost > 0) {
2738 for (i = 0; i < plr[myplr]._pNumInv && cost > 0; i++) {
2739 if (plr[myplr].InvList[i]._itype == ITYPE_GOLD && plr[myplr].InvList[i]._ivalue != MaxGold) {
2740 if (cost < plr[myplr].InvList[i]._ivalue) {
2741 plr[myplr].InvList[i]._ivalue -= cost;
2742 SetGoldCurs(myplr, i);
2743 cost = 0;
2744 } else {
2745 cost -= plr[myplr].InvList[i]._ivalue;
2746 RemoveInvItem(myplr, i);
2747 i = -1;
2748 }
2749 }
2750 }
2751 if (cost > 0) {
2752 for (i = 0; i < plr[myplr]._pNumInv && cost > 0; i++) {
2753 if (plr[myplr].InvList[i]._itype == ITYPE_GOLD) {
2754 if (cost < plr[myplr].InvList[i]._ivalue) {
2755 plr[myplr].InvList[i]._ivalue -= cost;
2756 SetGoldCurs(myplr, i);
2757 cost = 0;
2758 } else {
2759 cost -= plr[myplr].InvList[i]._ivalue;
2760 RemoveInvItem(myplr, i);
2761 i = -1;
2762 }
2763 }
2764 }
2765 }
2766 }
2767 }
2768
STextEnter()2769 void STextEnter()
2770 {
2771 if (qtextflag) {
2772 qtextflag = FALSE;
2773 if (leveltype == DTYPE_TOWN)
2774 stream_stop();
2775
2776 return;
2777 }
2778
2779 PlaySFX(IS_TITLSLCT);
2780 switch (stextflag) {
2781 case STORE_SMITH:
2782 S_SmithEnter();
2783 break;
2784 case STORE_SPBUY:
2785 S_SPBuyEnter();
2786 break;
2787 case STORE_SBUY:
2788 S_SBuyEnter();
2789 break;
2790 case STORE_SSELL:
2791 S_SSellEnter();
2792 break;
2793 case STORE_SREPAIR:
2794 S_SRepairEnter();
2795 break;
2796 case STORE_WITCH:
2797 S_WitchEnter();
2798 break;
2799 case STORE_WBUY:
2800 S_WBuyEnter();
2801 break;
2802 case STORE_WSELL:
2803 S_WSellEnter();
2804 break;
2805 case STORE_WRECHARGE:
2806 S_WRechargeEnter();
2807 break;
2808 case STORE_NOMONEY:
2809 case STORE_NOROOM:
2810 StartStore(stextshold);
2811 stextsel = stextlhold;
2812 stextsval = stextvhold;
2813 break;
2814 case STORE_CONFIRM:
2815 S_ConfirmEnter();
2816 break;
2817 case STORE_BOY:
2818 S_BoyEnter();
2819 break;
2820 case STORE_BBOY:
2821 S_BBuyEnter();
2822 break;
2823 case STORE_HEALER:
2824 S_HealerEnter();
2825 break;
2826 case STORE_STORY:
2827 S_StoryEnter();
2828 break;
2829 case STORE_HBUY:
2830 S_HBuyEnter();
2831 break;
2832 case STORE_SIDENTIFY:
2833 S_SIDEnter();
2834 break;
2835 case STORE_GOSSIP:
2836 S_TalkEnter();
2837 break;
2838 case STORE_IDSHOW:
2839 StartStore(STORE_SIDENTIFY);
2840 break;
2841 case STORE_DRUNK:
2842 S_DrunkEnter();
2843 break;
2844 case STORE_TAVERN:
2845 S_TavernEnter();
2846 break;
2847 case STORE_BARMAID:
2848 S_BarmaidEnter();
2849 break;
2850 case STORE_NONE:
2851 break;
2852 }
2853 }
2854
CheckStoreBtn()2855 void CheckStoreBtn()
2856 {
2857 int y;
2858
2859 if (qtextflag) {
2860 qtextflag = FALSE;
2861 if (leveltype == DTYPE_TOWN)
2862 stream_stop();
2863 } else if (stextsel != -1 && MouseY >= (32 + UI_OFFSET_Y) && MouseY <= (320 + UI_OFFSET_Y)) {
2864 if (!stextsize) {
2865 if (MouseX < 344 + PANEL_LEFT || MouseX > 616 + PANEL_LEFT)
2866 return;
2867 } else {
2868 if (MouseX < 24 + PANEL_LEFT || MouseX > 616 + PANEL_LEFT)
2869 return;
2870 }
2871 y = (MouseY - (32 + UI_OFFSET_Y)) / 12;
2872 if (stextscrl && MouseX > 600 + PANEL_LEFT) {
2873 if (y == 4) {
2874 if (stextscrlubtn <= 0) {
2875 STextUp();
2876 stextscrlubtn = 10;
2877 } else {
2878 stextscrlubtn--;
2879 }
2880 }
2881 if (y == 20) {
2882 if (stextscrldbtn <= 0) {
2883 STextDown();
2884 stextscrldbtn = 10;
2885 } else {
2886 stextscrldbtn--;
2887 }
2888 }
2889 } else if (y >= 5) {
2890 if (y >= 23)
2891 y = 22;
2892 if (stextscrl && y < 21 && !stext[y]._ssel) {
2893 if (stext[y - 2]._ssel) {
2894 y -= 2;
2895 } else if (stext[y - 1]._ssel) {
2896 y--;
2897 }
2898 }
2899 if (stext[y]._ssel || (stextscrl && y == 22)) {
2900 stextsel = y;
2901 STextEnter();
2902 }
2903 }
2904 }
2905 }
2906
ReleaseStoreBtn()2907 void ReleaseStoreBtn()
2908 {
2909 stextscrlubtn = -1;
2910 stextscrldbtn = -1;
2911 }
2912
2913 DEVILUTION_END_NAMESPACE
2914