1 /*-------------------------------------------------------------------------------
2
3 BARONY
4 File: shopgui.cpp
5 Desc: contains shop (GUI) related functions
6
7 Copyright 2013-2016 (c) Turning Wheel LLC, all rights reserved.
8 See LICENSE for details.
9
10 -------------------------------------------------------------------------------*/
11
12 #include "../main.hpp"
13 #include "../draw.hpp"
14 #include "../game.hpp"
15 #include "../stat.hpp"
16 #include "../items.hpp"
17 #include "../shops.hpp"
18 #include "../player.hpp"
19 #include "interface.hpp"
20 #include "../colors.hpp"
21
22
hideItemFromShopView(Item & item)23 bool hideItemFromShopView(Item& item)
24 {
25 if ( item.type == ARTIFACT_ORB_GREEN || item.type == ARTIFACT_ORB_RED || item.type == ARTIFACT_ORB_BLUE )
26 {
27 return true;
28 }
29 return false;
30 }
31
rebuildShopInventory()32 void rebuildShopInventory()
33 {
34 bool mysteriousShopkeeper = (shopkeepertype == 10);
35 bool mysteriousShopkeeperGreenOrb = false;
36 bool mysteriousShopkeeperBlueOrb = false;
37 bool mysteriousShopkeeperRedOrb = false;
38 if ( mysteriousShopkeeper )
39 {
40 for ( node_t* node = shopInv->first; node != NULL; node = node->next )
41 {
42 Item* item = (Item*)node->element;
43 if ( item )
44 {
45 if ( item->type == ARTIFACT_ORB_BLUE )
46 {
47 mysteriousShopkeeperBlueOrb = true;
48 }
49 else if ( item->type == ARTIFACT_ORB_RED )
50 {
51 mysteriousShopkeeperRedOrb = true;
52 }
53 else if ( item->type == ARTIFACT_ORB_GREEN )
54 {
55 mysteriousShopkeeperGreenOrb = true;
56 }
57 }
58 }
59 }
60
61 //Count number of items.
62 int c = 0;
63 node_t* node = nullptr;
64 for ( node = shopInv->first; node != NULL; node = node->next )
65 {
66 Item* item = (Item*) node->element;
67 if ( item )
68 {
69 if ( mysteriousShopkeeper )
70 {
71 if ( !mysteriousShopkeeperBlueOrb
72 && shopkeeperMysteriousItems[ARTIFACT_ORB_BLUE].find(item->type) != shopkeeperMysteriousItems[ARTIFACT_ORB_BLUE].end() )
73 {
74 continue;
75 }
76 if ( !mysteriousShopkeeperGreenOrb
77 && shopkeeperMysteriousItems[ARTIFACT_ORB_GREEN].find(item->type) != shopkeeperMysteriousItems[ARTIFACT_ORB_GREEN].end() )
78 {
79 continue;
80 }
81 if ( !mysteriousShopkeeperRedOrb
82 && shopkeeperMysteriousItems[ARTIFACT_ORB_RED].find(item->type) != shopkeeperMysteriousItems[ARTIFACT_ORB_RED].end() )
83 {
84 continue;
85 }
86 }
87 if ( hideItemFromShopView(*item) )
88 {
89 continue;
90 }
91 if ( shopinventorycategory == 0 && itemCategory(item) != WEAPON && itemCategory(item) != THROWN )
92 {
93 continue;
94 }
95 else if ( shopinventorycategory == 1 && itemCategory(item) != ARMOR )
96 {
97 continue;
98 }
99 else if ( shopinventorycategory == 2 && itemCategory(item) != AMULET && itemCategory(item) != RING )
100 {
101 continue;
102 }
103 else if ( shopinventorycategory == 3 && itemCategory(item) != SPELLBOOK && itemCategory(item) != MAGICSTAFF && itemCategory(item) != SCROLL )
104 {
105 continue;
106 }
107 else if ( shopinventorycategory == 4 && itemCategory(item) != GEM )
108 {
109 continue;
110 }
111 else if ( shopinventorycategory == 5 && itemCategory(item) != FOOD && itemCategory(item) != POTION )
112 {
113 continue;
114 }
115 else if ( shopinventorycategory == 6 && itemCategory(item) != TOOL && itemCategory(item) != BOOK )
116 {
117 continue;
118 }
119 }
120 c++;
121 }
122 //Sanitize item scroll.
123 shopitemscroll = std::max(0, std::min(shopitemscroll, c - 4));
124 //Clear out currently displayed items.
125 for ( c = 0; c < 4; c++ )
126 {
127 shopinvitems[c] = NULL;
128 }
129
130 //Display the items.
131 c = 0;
132 for ( node = shopInv->first; node != NULL; node = node->next )
133 {
134 Item* item = (Item*) node->element;
135 if (item)
136 {
137 if ( mysteriousShopkeeper )
138 {
139 if ( !mysteriousShopkeeperBlueOrb
140 && shopkeeperMysteriousItems[ARTIFACT_ORB_BLUE].find(item->type) != shopkeeperMysteriousItems[ARTIFACT_ORB_BLUE].end() )
141 {
142 continue;
143 }
144 if ( !mysteriousShopkeeperGreenOrb
145 && shopkeeperMysteriousItems[ARTIFACT_ORB_GREEN].find(item->type) != shopkeeperMysteriousItems[ARTIFACT_ORB_GREEN].end() )
146 {
147 continue;
148 }
149 if ( !mysteriousShopkeeperRedOrb
150 && shopkeeperMysteriousItems[ARTIFACT_ORB_RED].find(item->type) != shopkeeperMysteriousItems[ARTIFACT_ORB_RED].end() )
151 {
152 continue;
153 }
154 }
155 if ( hideItemFromShopView(*item) )
156 {
157 continue;
158 }
159 if ( shopinventorycategory == 0 && itemCategory(item) != WEAPON && itemCategory(item) != THROWN )
160 {
161 continue;
162 }
163 else if ( shopinventorycategory == 1 && itemCategory(item) != ARMOR )
164 {
165 continue;
166 }
167 else if ( shopinventorycategory == 2 && itemCategory(item) != AMULET && itemCategory(item) != RING )
168 {
169 continue;
170 }
171 else if ( shopinventorycategory == 3 && itemCategory(item) != SPELLBOOK && itemCategory(item) != MAGICSTAFF && itemCategory(item) != SCROLL )
172 {
173 continue;
174 }
175 else if ( shopinventorycategory == 4 && itemCategory(item) != GEM )
176 {
177 continue;
178 }
179 else if ( shopinventorycategory == 5 && itemCategory(item) != FOOD && itemCategory(item) != POTION )
180 {
181 continue;
182 }
183 else if ( shopinventorycategory == 6 && itemCategory(item) != TOOL && itemCategory(item) != BOOK )
184 {
185 continue;
186 }
187 c++;
188 if ( c <= shopitemscroll )
189 {
190 continue;
191 }
192 shopinvitems[c - shopitemscroll - 1] = item;
193 if ( c > 3 + shopitemscroll )
194 {
195 break;
196 }
197 }
198 }
199 }
200
201 struct Area
202 {
203 public:
204 int x1, x2, y1, y2;
205
AreaArea206 Area(int inX1 = 0, int inX2 = 0, int inY1 = 0, int inY2 = 0)
207 {
208 x1 = inX1;
209 x2 = inX2;
210 y1 = inY1;
211 y2 = inY2;
212 }
213 };
214
checkBuyItem()215 inline void checkBuyItem()
216 {
217 if ( (stats[clientnum]->HP <= 0) || (players[clientnum] == nullptr) || (players[clientnum]->entity == nullptr) )
218 {
219 return;
220 }
221
222 //Window bounds.
223 Area shopWindow(xres / 2 - SHOPWINDOW_SIZEX / 2, xres / 2 + SHOPWINDOW_SIZEX / 2, yres / 2 - SHOPWINDOW_SIZEY / 2, yres / 2 + SHOPWINDOW_SIZEY / 2);
224
225 //Location of inventory slots.
226 Area slotAreaBounds;
227 slotAreaBounds.x1 = shopWindow.x1 + (shopWindow.x2 - shopWindow.x1) / 2 - inventory_bmp->w / 2 + 12;
228 slotAreaBounds.x2 = slotAreaBounds.x1 + inventoryoption_bmp->w; //Original code: inventory_bmp->w - 28
229 slotAreaBounds.y1 = shopWindow.y1 + 16 + 160 + 16;
230 slotAreaBounds.y2 = slotAreaBounds.y1 + (inventoryoption_bmp->h * NUM_SHOP_GUI_SLOTS);
231
232 SDL_Rect slotPos;
233 slotPos.x = slotAreaBounds.x1;
234 slotPos.w = inventoryoption_bmp->w;
235 slotPos.y = slotAreaBounds.y1;
236 slotPos.h = inventoryoption_bmp->h;
237
238 if ( (omousex < slotPos.x) || (omousex >= slotPos.x + slotPos.w) )
239 {
240 selectedShopSlot = -1;
241 return;
242 }
243
244 bool selectingSlot = false;
245
246 for (int i = 0; i < NUM_SHOP_GUI_SLOTS; ++i, slotPos.y += slotPos.h)
247 {
248 if ( omousey >= slotPos.y && omousey < slotPos.y + slotPos.h )
249 {
250 //If moused over, highlight slot & check for mouse click or gamepad buy button.
251 selectedShopSlot = i;
252 selectingSlot = true;
253 drawImage(inventoryoption_bmp, nullptr, &slotPos);
254 if ( mousestatus[SDL_BUTTON_LEFT] || *inputPressed(joyimpulses[INJOY_MENU_USE]) )
255 {
256 mousestatus[SDL_BUTTON_LEFT] = 0;
257 *inputPressed(joyimpulses[INJOY_MENU_USE]) = 0;
258 buyItemFromShop(shopinvitems[i]);
259 //Check if no more items after this slot & deal accordingly.
260 rebuildShopInventory();
261 if ( shopinvitems[i] == nullptr )
262 {
263 if ( shopinvitems[0] == nullptr )
264 {
265 //Go back to inventory.
266 selectedShopSlot = -1;
267 warpMouseToSelectedInventorySlot();
268 }
269 else
270 {
271 //Move up one slot.
272 --selectedShopSlot;
273 warpMouseToSelectedShopSlot();
274 }
275 }
276 }
277 }
278 }
279
280 if ( !selectingSlot )
281 {
282 selectedShopSlot = -1;
283 }
284 }
285
warpMouseToSelectedShopSlot()286 void warpMouseToSelectedShopSlot()
287 {
288 Area shopWindow(xres / 2 - SHOPWINDOW_SIZEX / 2, xres / 2 + SHOPWINDOW_SIZEX / 2, yres / 2 - SHOPWINDOW_SIZEY / 2, yres / 2 + SHOPWINDOW_SIZEY / 2);
289
290 Area slotAreaBounds;
291 slotAreaBounds.x1 = shopWindow.x1 + (shopWindow.x2 - shopWindow.x1) / 2 - inventory_bmp->w / 2 + 12;
292 slotAreaBounds.x2 = slotAreaBounds.x1 + inventoryoption_bmp->w; //Original code: inventory_bmp->w - 28
293 slotAreaBounds.y1 = shopWindow.y1 + 16 + 160 + 16;
294 slotAreaBounds.y2 = slotAreaBounds.y1 + (inventoryoption_bmp->h * NUM_SHOP_GUI_SLOTS);
295
296 SDL_Rect slotPos;
297 slotPos.x = slotAreaBounds.x1;
298 slotPos.w = inventoryoption_bmp->w;
299 slotPos.h = inventoryoption_bmp->h;
300 slotPos.y = slotAreaBounds.y1 + (inventoryoption_bmp->h * selectedShopSlot);
301
302 SDL_WarpMouseInWindow(screen, slotPos.x + (slotPos.w / 2), slotPos.y + (slotPos.h / 2));
303 }
304
305 /*-------------------------------------------------------------------------------
306
307 updateShopWindow
308
309 Draws and processes everything related to the shop window
310
311 -------------------------------------------------------------------------------*/
312
updateShopWindow()313 void updateShopWindow()
314 {
315 SDL_Rect pos;
316 node_t* node;
317 int c;
318
319 if ( multiplayer != CLIENT )
320 {
321 Entity* entity = uidToEntity(shopkeeper);
322 if (entity)
323 {
324 Stat* stats = entity->getStats();
325 shopkeepername = stats->name;
326 }
327 }
328
329 // draw window
330 int x1 = xres / 2 - SHOPWINDOW_SIZEX / 2, x2 = xres / 2 + SHOPWINDOW_SIZEX / 2;
331 int y1 = yres / 2 - SHOPWINDOW_SIZEY / 2, y2 = yres / 2 + SHOPWINDOW_SIZEY / 2;
332 drawWindowFancy( x1, y1, x2, y2 );
333
334 // clicking
335 int x = x1 + (x2 - x1) / 2 - inventory_bmp->w / 2;
336 int y = y1 + 16 + 160;
337 pos.x = x;
338 pos.y = y;
339 drawImage(inventory_bmp, NULL, &pos);
340 if ( mousestatus[SDL_BUTTON_LEFT] )
341 {
342 if ( omousey >= y && omousey < y + 16 )
343 {
344 if ( omousex >= x + 12 && omousex < x + inventory_bmp->w - 12 )
345 {
346 mousestatus[SDL_BUTTON_LEFT] = 0;
347 shopinventorycategory = (omousex - x - 12) / button_bmp->w;
348 }
349 }
350 else if ( omousey >= y + 16 && omousey < y + 52 )
351 {
352 if ( omousex >= x + inventory_bmp->w - 28 && omousex < x + inventory_bmp->w - 12 )
353 {
354 mousestatus[SDL_BUTTON_LEFT] = 0;
355 buttonclick = 10;
356 shopitemscroll--;
357 }
358 }
359 else if ( omousey >= y + 52 && omousey < y + 88 )
360 {
361 if ( omousex >= x + inventory_bmp->w - 28 && omousex < x + inventory_bmp->w - 12 )
362 {
363 mousestatus[SDL_BUTTON_LEFT] = 0;
364 buttonclick = 11;
365 shopitemscroll++;
366 }
367 }
368 }
369
370 // mousewheel
371 if ( omousex >= x + 12 && omousex < x + inventory_bmp->w - 28 )
372 {
373 if ( omousey >= 16 && omousey < y + inventory_bmp->h - 8 )
374 {
375 if ( mousestatus[SDL_BUTTON_WHEELDOWN] )
376 {
377 mousestatus[SDL_BUTTON_WHEELDOWN] = 0;
378 shopitemscroll++;
379 }
380 else if ( mousestatus[SDL_BUTTON_WHEELUP] )
381 {
382 mousestatus[SDL_BUTTON_WHEELUP] = 0;
383 shopitemscroll--;
384 }
385 }
386 }
387
388 // inventory up button
389 if ( buttonclick == 10 )
390 {
391 pos.x = x + inventory_bmp->w - 28;
392 pos.y = y + 16;
393 pos.w = 0;
394 pos.h = 0;
395 drawImage(invup_bmp, NULL, &pos);
396 }
397 // inventory down button
398 if ( buttonclick == 11 )
399 {
400 pos.x = x + inventory_bmp->w - 28;
401 pos.y = y + 52;
402 pos.w = 0;
403 pos.h = 0;
404 drawImage(invdown_bmp, NULL, &pos);
405 }
406 pos.x = x + 12 + button_bmp->w * shopinventorycategory;
407 pos.y = y;
408 pos.w = 0;
409 pos.h = 0;
410 if ( shopinventorycategory <= 6 )
411 {
412 drawImage(button_bmp, NULL, &pos);
413 }
414 else
415 {
416 drawImage(smallbutton_bmp, NULL, &pos);
417 }
418
419 // inventory category labels
420 ttfPrintText(ttf8, x + 14, y + 4, language[349]);
421 ttfPrintText(ttf8, x + 14 + 60, y + 4, language[350]);
422 ttfPrintText(ttf8, x + 14 + 120, y + 4, language[351]);
423 ttfPrintText(ttf8, x + 14 + 180, y + 4, language[352]);
424 ttfPrintText(ttf8, x + 14 + 240, y + 4, language[353]);
425 ttfPrintText(ttf8, x + 14 + 300, y + 4, language[354]);
426 ttfPrintText(ttf8, x + 14 + 360, y + 4, language[355]);
427 ttfPrintText(ttf8, x + 12 + 424, y + 4, language[356]);
428
429 // buying
430 checkBuyItem();
431
432
433 rebuildShopInventory();
434
435 int y3 = y + 22;
436 bool mysteriousShopkeeper = (shopkeepertype == 10);
437 bool mysteriousShopkeeperGreenOrb = false;
438 bool mysteriousShopkeeperBlueOrb = false;
439 bool mysteriousShopkeeperRedOrb = false;
440 if ( mysteriousShopkeeper )
441 {
442 for ( node = shopInv->first; node != NULL; node = node->next )
443 {
444 Item* item = (Item*)node->element;
445 if ( item )
446 {
447 if ( item->type == ARTIFACT_ORB_BLUE )
448 {
449 mysteriousShopkeeperBlueOrb = true;
450 }
451 else if ( item->type == ARTIFACT_ORB_RED )
452 {
453 mysteriousShopkeeperRedOrb = true;
454 }
455 else if ( item->type == ARTIFACT_ORB_GREEN )
456 {
457 mysteriousShopkeeperGreenOrb = true;
458 }
459 }
460 }
461 }
462
463 c = 0;
464 for ( node = shopInv->first; node != NULL; node = node->next )
465 {
466 Item* item = (Item*) node->element;
467 if (item)
468 {
469 if ( mysteriousShopkeeper )
470 {
471 if ( !mysteriousShopkeeperBlueOrb
472 && shopkeeperMysteriousItems[ARTIFACT_ORB_BLUE].find(item->type) != shopkeeperMysteriousItems[ARTIFACT_ORB_BLUE].end() )
473 {
474 continue;
475 }
476 if ( !mysteriousShopkeeperGreenOrb
477 && shopkeeperMysteriousItems[ARTIFACT_ORB_GREEN].find(item->type) != shopkeeperMysteriousItems[ARTIFACT_ORB_GREEN].end() )
478 {
479 continue;
480 }
481 if ( !mysteriousShopkeeperRedOrb
482 && shopkeeperMysteriousItems[ARTIFACT_ORB_RED].find(item->type) != shopkeeperMysteriousItems[ARTIFACT_ORB_RED].end() )
483 {
484 continue;
485 }
486 }
487 if ( hideItemFromShopView(*item) )
488 {
489 continue;
490 }
491 if ( shopinventorycategory == 0 && itemCategory(item) != WEAPON && itemCategory(item) != THROWN )
492 {
493 continue;
494 }
495 else if ( shopinventorycategory == 1 && itemCategory(item) != ARMOR )
496 {
497 continue;
498 }
499 else if ( shopinventorycategory == 2 && itemCategory(item) != AMULET && itemCategory(item) != RING )
500 {
501 continue;
502 }
503 else if ( shopinventorycategory == 3 && itemCategory(item) != SPELLBOOK && itemCategory(item) != MAGICSTAFF && itemCategory(item) != SCROLL )
504 {
505 continue;
506 }
507 else if ( shopinventorycategory == 4 && itemCategory(item) != GEM )
508 {
509 continue;
510 }
511 else if ( shopinventorycategory == 5 && itemCategory(item) != FOOD && itemCategory(item) != POTION )
512 {
513 continue;
514 }
515 else if ( shopinventorycategory == 6 && itemCategory(item) != TOOL && itemCategory(item) != BOOK )
516 {
517 continue;
518 }
519 c++;
520 if ( c <= shopitemscroll )
521 {
522 continue;
523 }
524 char tempstr[64] = { 0 };
525 strncpy(tempstr, item->description(), 42);
526 if ( strlen(tempstr) == 42 )
527 {
528 strcat(tempstr, " ...");
529 }
530 Uint32 color = uint32ColorWhite(*mainsurface);
531 if ( item->beatitude > 0 && stats[clientnum]->PROFICIENCIES[PRO_APPRAISAL] >= SKILL_LEVEL_EXPERT )
532 {
533 color = uint32ColorGreen(*mainsurface);
534 }
535 ttfPrintTextColor(ttf8, x + 12 + 36, y3, color, true, tempstr);
536 ttfPrintTextFormatted(ttf8, x + 12 + 348, y3, "%7dG", item->buyValue(clientnum));
537
538 if ( mysteriousShopkeeper )
539 {
540 pos.x = x + 12 + (348);
541 pos.y = y + 17 + 18 * (c - shopitemscroll - 1);
542 pos.w = 16;
543 pos.h = 16;
544
545 for ( auto orbCategories : shopkeeperMysteriousItems )
546 {
547 if ( orbCategories.second.find(item->type) != orbCategories.second.end() )
548 {
549 node_t* tmpNode = items[orbCategories.first].surfaces.first;
550 if ( tmpNode )
551 {
552 drawImageScaled(*(SDL_Surface**)(tmpNode->element), NULL, &pos);
553 }
554 break;
555 }
556 }
557 }
558
559 pos.x = x + 12 + 16;
560 pos.y = y + 17 + 18 * (c - shopitemscroll - 1);
561 pos.w = 16;
562 pos.h = 16;
563 drawImageScaled(itemSprite(item), NULL, &pos);
564 y3 += 18;
565 if ( c > 3 + shopitemscroll )
566 {
567 break;
568 }
569 }
570 }
571
572 // draw money count
573 ttfPrintTextFormatted( ttf16, x1 + 16, y2 - 32, language[357], stats[clientnum]->GOLD );
574
575 // chitchat
576 if ( (ticks - shoptimer) % 600 == 0 && !mysteriousShopkeeper )
577 {
578 shopspeech = language[216 + rand() % NUMCHITCHAT];
579 shoptimer--;
580 }
581
582 // draw speech
583 if ( !strcmp(shopspeech, language[194]) || !strcmp(shopspeech, language[195]) || !strcmp(shopspeech, language[196]) )
584 {
585 if ( mysteriousShopkeeper )
586 {
587 shopspeech = language[3893 + rand() % 3];
588 }
589 else
590 {
591 ttfPrintTextFormatted( ttf16, x1 + 16 + 160 + 16, y1 + 64, language[358], shopkeepername, language[184 + shopkeepertype] );
592 }
593 }
594
595 if (sellitem)
596 {
597 ttfPrintTextFormatted( ttf16, x1 + 16 + 160 + 16, y1 + 32, shopspeech, sellitem->sellValue(clientnum) );
598 }
599 else
600 {
601 ttfPrintTextFormatted( ttf16, x1 + 16 + 160 + 16, y1 + 32, shopspeech, 0 );
602 }
603
604
605 // draw black box for shopkeeper
606 pos.x = x1 + 16;
607 pos.y = y1 + 16;
608 pos.w = 160;
609 pos.h = 160;
610 drawRect(&pos, 0, 255);
611
612 // draw shopkeeper
613 if ( uidToEntity(shopkeeper) )
614 {
615 Entity* entity = uidToEntity(shopkeeper);
616 if ( !entity->flags[INVISIBLE] )
617 {
618 pos.x = x1 + 16;
619 pos.y = y1 + 16;
620 pos.w = 160;
621 pos.h = 160;
622 if ( mysteriousShopkeeper )
623 {
624 drawImage(shopkeeper2_bmp, NULL, &pos);
625 }
626 else
627 {
628 drawImage(shopkeeper_bmp, NULL, &pos);
629 }
630 }
631 else
632 {
633 pos.x = x1 + 16;
634 pos.y = y1 + 16;
635 pos.w = 160;
636 pos.h = 160;
637 drawRect(&pos, 0, 255);
638 }
639 }
640 }
641
642 /*void warpMouseToselectedShopSlot() {
643 //Shop window boundaries.
644 int x1 = xres/2 - SHOPWINDOW_SIZEX/2, x2 = xres/2 + SHOPWINDOW_SIZEX/2;
645 int y1 = yres/2 - SHOPWINDOW_SIZEY/2, y2 = yres/2 + SHOPWINDOW_SIZEY/2;
646
647 //Calculate x that will be halfway in slot.
648 int x = x1 + (x2 - x1)/2 - inventory_bmp->w/2;
649 int y = y1 + 16 + 160 + (inventoryoption_bmp->h * selectedShopSlot) + (inventoryoption_bmp->h / 2);
650 SDL_WarpMouseInWindow(screen, x, y);
651 }*/
652
getItemInfoFromShop(int slot)653 inline Item* getItemInfoFromShop(int slot)
654 {
655 if ( slot >= 4 )
656 {
657 return nullptr; //Out of bounds,
658 }
659
660 return shopinvitems[slot];
661 }
662
selectShopSlot(int slot)663 void selectShopSlot(int slot)
664 {
665 if ( slot < selectedShopSlot )
666 {
667 //Moving up.
668
669 /*
670 * Possible cases:
671 * * 1) Move cursor up the GUI through different selectedShopSlot.
672 * * 2) Page up through shopitemscroll--
673 * * 3) Scrolling up past top of shop, no shopitemscroll (move back to inventory)
674 */
675
676 if ( selectedShopSlot <= 0 )
677 {
678 //Covers cases 2 & 3.
679
680 /*
681 * Possible cases:
682 * * A) Hit very top of shop inventory, can't go any further. Return to inventory.
683 * * B) Page up, scrolling through shopitemscroll.
684 */
685
686 if ( shopitemscroll <= 0 )
687 {
688 //Case 3/A: Return to inventory.
689 selectedShopSlot = -1;
690 }
691 else
692 {
693 //Case 2/B: Page up through shop inventory.
694 --shopitemscroll;
695 }
696 }
697 else
698 {
699 //Covers case 1.
700
701 //Move cursor up the GUI through different selectedShopSlot (--selectedShopSlot).
702 --selectedShopSlot;
703 warpMouseToSelectedShopSlot();
704 }
705 }
706 else if ( slot > selectedShopSlot )
707 {
708 //Moving down.
709
710 /*
711 * Possible cases:
712 * * 1) Moving cursor down through GUI through different selectedShopSlot.
713 * * 2) Scrolling down past bottom of shop through shopitemscroll++
714 * * 3) Scrolling down past bottom of shop, max shop scroll (revoke move -- can't go beyond limit of shop).
715 */
716
717 if ( selectedShopSlot >= NUM_SHOP_GUI_SLOTS - 1 )
718 {
719 //Covers cases 2 & 3.
720 ++shopitemscroll; //Shopitemscroll is automatically sanitized in updateShopWindow().
721 }
722 else
723 {
724 //Covers case 1.
725 //Move cursor down through the GUi through different selectedShopSlot (++selectedShopSlot).
726 //This is a little bit trickier since must revoke movement if there is no item in the next slot!
727
728 /*
729 * Two possible cases:
730 * * A) Items below this. Advance selectedShopSlot to them.
731 * * B) On last item already. Do nothing (revoke movement).
732 */
733
734 Item* item = getItemInfoFromShop(selectedShopSlot + 1);
735
736 if ( item )
737 {
738 ++selectedShopSlot;
739 warpMouseToSelectedShopSlot();
740 }
741 else
742 {
743 //No more items. Stop.
744 }
745 }
746 }
747 }
748
cycleShopCategories(int direction)749 void cycleShopCategories(int direction)
750 {
751 if ( direction < 0 )
752 {
753 //Cycle left.
754 --shopinventorycategory;
755 }
756 else if ( direction > 0 )
757 {
758 //Cycle right.
759 ++shopinventorycategory;
760 }
761
762 if ( shopinventorycategory < 0 )
763 {
764 shopinventorycategory = NUM_SHOP_CATEGORIES - 1;
765 }
766 else if ( shopinventorycategory >= NUM_SHOP_CATEGORIES )
767 {
768 shopinventorycategory = 0;
769 }
770 }