Atrinik Client 2.5
gui/inventory.c
Go to the documentation of this file.
00001 /************************************************************************
00002 *            Atrinik, a Multiplayer Online Role Playing Game            *
00003 *                                                                       *
00004 *    Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team    *
00005 *                                                                       *
00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game)     *
00007 * and Crossfire (Multiplayer game for X-windows).                       *
00008 *                                                                       *
00009 * This program is free software; you can redistribute it and/or modify  *
00010 * it under the terms of the GNU General Public License as published by  *
00011 * the Free Software Foundation; either version 2 of the License, or     *
00012 * (at your option) any later version.                                   *
00013 *                                                                       *
00014 * This program is distributed in the hope that it will be useful,       *
00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00017 * GNU General Public License for more details.                          *
00018 *                                                                       *
00019 * You should have received a copy of the GNU General Public License     *
00020 * along with this program; if not, write to the Free Software           *
00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.             *
00022 *                                                                       *
00023 * The author can be reached at admin@atrinik.org                        *
00024 ************************************************************************/
00025 
00030 #include <global.h>
00031 
00032 char *skill_level_name[] =
00033 {
00034     "",
00035     "Ag",
00036     "Pe",
00037     "Me",
00038     "Ph",
00039     "Ma",
00040     "Wi"
00041 };
00042 
00044 uint64 inventory_filter = INVENTORY_FILTER_ALL;
00045 
00050 static int inventory_matches_filter(object *op)
00051 {
00052     /* No filtering of objects in the below inventory. */
00053     if (op->env == cpl.below)
00054     {
00055         return 1;
00056     }
00057 
00058     /* Always show open container. */
00059     if (cpl.container && cpl.container->tag == op->tag)
00060     {
00061         return 1;
00062     }
00063 
00064     if (inventory_filter == INVENTORY_FILTER_ALL)
00065     {
00066         return 1;
00067     }
00068 
00069     if (inventory_filter & INVENTORY_FILTER_APPLIED && op->flags & F_APPLIED)
00070     {
00071         return 1;
00072     }
00073 
00074     if (inventory_filter & INVENTORY_FILTER_CONTAINER && op->itype == TYPE_CONTAINER)
00075     {
00076         return 1;
00077     }
00078 
00079     if (inventory_filter & INVENTORY_FILTER_MAGICAL && op->flags & F_MAGIC)
00080     {
00081         return 1;
00082     }
00083 
00084     if (inventory_filter & INVENTORY_FILTER_CURSED && op->flags & (F_CURSED | F_DAMNED))
00085     {
00086         return 1;
00087     }
00088 
00089     if (inventory_filter & INVENTORY_FILTER_UNIDENTIFIED && op->item_qua == 255)
00090     {
00091         return 1;
00092     }
00093 
00094     if (inventory_filter & INVENTORY_FILTER_UNAPPLIED && !(op->flags & F_APPLIED))
00095     {
00096         return 1;
00097     }
00098 
00099     if (inventory_filter & INVENTORY_FILTER_LOCKED && op->flags & F_LOCKED)
00100     {
00101         return 1;
00102     }
00103 
00104     return 0;
00105 }
00106 
00110 void inventory_filter_set(uint64 filter)
00111 {
00112     inventory_filter = filter;
00113     cpl.win_inv_slot = 0;
00114     cpl.win_inv_start = 0;
00115     cpl.win_inv_tag = get_inventory_data(cpl.ob, &cpl.win_inv_ctag, &cpl.win_inv_slot, &cpl.win_inv_start, &cpl.win_inv_count, INVITEMXLEN, INVITEMYLEN);
00116     draw_info(COLOR_GREEN, "Inventory filter changed.");
00117 }
00118 
00122 void inventory_filter_toggle(uint64 filter)
00123 {
00124     if (inventory_filter & filter)
00125     {
00126         inventory_filter &= ~filter;
00127     }
00128     else
00129     {
00130         inventory_filter |= filter;
00131     }
00132 
00133     cpl.win_inv_slot = 0;
00134     cpl.win_inv_start = 0;
00135     cpl.win_inv_tag = get_inventory_data(cpl.ob, &cpl.win_inv_ctag, &cpl.win_inv_slot, &cpl.win_inv_start, &cpl.win_inv_count, INVITEMXLEN, INVITEMYLEN);
00136     draw_info(COLOR_GREEN, "Inventory filter changed.");
00137 }
00138 
00139 /* This function returns number of items and adjusts the inventory window data */
00140 int get_inventory_data(object *op, int *ctag, int *slot, int *start, int *count, int wxlen, int wylen)
00141 {
00142     object *tmp, *tmpc;
00143     int i = 0, ret = -1;
00144 
00145     cpl.window_weight = 0.0f;
00146     *ctag = -1;
00147     *count = 0;
00148 
00149     if (!op)
00150     {
00151         *slot = *start = 0;
00152         return -1;
00153     }
00154 
00155     if (!op->inv)
00156     {
00157         *slot = *start = 0;
00158         return -1;
00159     }
00160 
00161     if (*slot < 0)
00162         *slot = 0;
00163 
00164     /* Pre count items, and adjust slot cursor */
00165     for (tmp = op->inv; tmp; tmp = tmp->next)
00166     {
00167         if (inventory_matches_filter(tmp))
00168         {
00169             (*count)++;
00170             cpl.window_weight += tmp->weight * (float)tmp->nrof;
00171         }
00172 
00173         if (tmp->tag == cpl.container_tag)
00174             cpl.container = tmp;
00175 
00176         if (cpl.container && cpl.container->tag == tmp->tag)
00177         {
00178             tmpc = cpl.sack->inv;
00179 
00180             for (; tmpc; tmpc = tmpc->next)
00181                 (*count)++;
00182         }
00183     }
00184 
00185     if (!*count)
00186         *slot = 0;
00187     else if (*slot >= *count)
00188         *slot = *count - 1;
00189 
00190     /* Now find tag */
00191     for (tmp = op->inv; tmp; tmp = tmp->next)
00192     {
00193         if (inventory_matches_filter(tmp))
00194         {
00195             if (*slot == i)
00196                 ret = tmp->tag;
00197 
00198             i++;
00199         }
00200 
00201         if (cpl.container && cpl.container->tag == tmp->tag)
00202         {
00203             tmpc = cpl.sack->inv;
00204 
00205             for (; tmpc; tmpc = tmpc->next)
00206             {
00207                 if (*slot == i)
00208                 {
00209                     *ctag = cpl.container->tag;
00210                     ret = tmpc->tag;
00211                 }
00212 
00213                 i++;
00214             }
00215         }
00216     }
00217 
00218     /* And adjust the slot/start position of the window */
00219     if (*slot < *start)
00220         *start = *slot - (*slot % wxlen);
00221     else if (*slot > *start + (wxlen * wylen) - 1)
00222         *start = ((int)(*slot / wxlen)) * wxlen - (wxlen * (wylen - 1));
00223 
00224     return ret;
00225 }
00226 
00227 static void show_inventory_item_stats(object *tmp, widgetdata *widget)
00228 {
00229     char buf[MAX_BUF];
00230 
00231     if (tmp->nrof > 1)
00232     {
00233         snprintf(buf, sizeof(buf), "%d %s", tmp->nrof, tmp->s_name);
00234     }
00235     else
00236     {
00237         snprintf(buf, sizeof(buf), "%s", tmp->s_name);
00238     }
00239 
00240     string_truncate_overflow(FONT_ARIAL10, buf, widget->wd - 26 - 4);
00241     string_blt(ScreenSurface, FONT_ARIAL10, buf, widget->x1 + 26, widget->y1 + 2, COLOR_HGOLD, 0, NULL);
00242 
00243     snprintf(buf, sizeof(buf), "%4.3f kg", tmp->weight * (double) tmp->nrof);
00244     string_blt(ScreenSurface, FONT_ARIAL10, buf, widget->x1 + widget->wd - 4 - string_get_width(FONT_ARIAL10, buf, 0), widget->y1 + 15, COLOR_HGOLD, 0, NULL);
00245 
00246     /* This comes from server when not identified */
00247     if (tmp->item_qua == 255)
00248     {
00249         string_blt(ScreenSurface, FONT_ARIAL10, "not identified", widget->x1 + 26, widget->y1 + 15, COLOR_RED, 0, NULL);
00250     }
00251     else
00252     {
00253         string_blt(ScreenSurface, FONT_ARIAL10, "con: ", widget->x1 + 26, widget->y1 + 15, COLOR_HGOLD, 0, NULL);
00254 
00255         snprintf(buf, sizeof(buf), "%d/%d", tmp->item_qua, tmp->item_con);
00256         string_blt(ScreenSurface, FONT_ARIAL10, buf, widget->x1 + 53, widget->y1 + 15, COLOR_HGOLD, 0, NULL);
00257 
00258         if (tmp->item_level)
00259         {
00260             snprintf(buf, sizeof(buf), "allowed: lvl %d %s", tmp->item_level, skill_level_name[tmp->item_skill]);
00261 
00262             if ((!tmp->item_skill && tmp->item_level <= cpl.stats.level) || (tmp->item_skill && tmp->item_level <= cpl.stats.skill_level[tmp->item_skill - 1]))
00263             {
00264                 string_blt(ScreenSurface, FONT_ARIAL10, buf, widget->x1 + 101, widget->y1 + 15, COLOR_HGOLD, 0, NULL);
00265             }
00266             else
00267             {
00268                 string_blt(ScreenSurface, FONT_ARIAL10, buf, widget->x1 + 101, widget->y1 + 15, COLOR_RED, 0, NULL);
00269             }
00270         }
00271         else
00272         {
00273             string_blt(ScreenSurface, FONT_ARIAL10, "allowed: all", widget->x1 + 101, widget->y1 + 15, COLOR_HGOLD, 0, NULL);
00274         }
00275     }
00276 }
00277 
00278 void widget_inventory_event(widgetdata *widget, int x, int y, SDL_Event event)
00279 {
00280     int mx = 0, my = 0;
00281     mx = x - widget->x1;
00282     my = y - widget->y1;
00283 
00284     switch (event.type)
00285     {
00286         case SDL_MOUSEBUTTONUP:
00287             if (draggingInvItem(DRAG_GET_STATUS) > DRAG_IWIN_BELOW)
00288             {
00289                 /* KEYFUNC_APPLY and KEYFUNC_DROP works only if cpl.inventory_win = IWIN_INV. The tag must
00290                  * be placed in cpl.win_inv_tag. So we do this and after DnD we restore the old values. */
00291                 int old_inv_win = cpl.inventory_win;
00292                 int old_inv_tag = cpl.win_inv_tag;
00293                 cpl.inventory_win = IWIN_INV;
00294 
00295                 if (draggingInvItem(DRAG_GET_STATUS) == DRAG_PDOLL)
00296                 {
00297                     cpl.win_inv_tag = cpl.win_pdoll_tag;
00298                     /* We don't have to check for the coordinates, if we are here we are in the widget */
00299 
00300                     /* Drop to inventory */
00301                     keybind_process_command("?APPLY");
00302                 }
00303 
00304                 cpl.inventory_win = old_inv_win;
00305                 cpl.win_inv_tag = old_inv_tag;
00306             }
00307             else if (draggingInvItem(DRAG_GET_STATUS) == DRAG_IWIN_BELOW)
00308             {
00309                 keybind_process_command("?GET");
00310             }
00311 
00312             draggingInvItem(DRAG_NONE);
00313             break;
00314 
00315         case SDL_MOUSEBUTTONDOWN:
00316             /* Inventory (open / close) */
00317             if (mx >= 4 && mx <= 22 && my >= 4 && my <= 26)
00318             {
00319                 if (cpl.inventory_win == IWIN_INV)
00320                     cpl.inventory_win = IWIN_BELOW;
00321                 else
00322                     cpl.inventory_win = IWIN_INV;
00323 
00324                 break;
00325             }
00326 
00327             /* scrollbar */
00328             if (mx > 258 && mx < 268)
00329             {
00330                 if (my <= 39 && my >= 30 && cpl.win_inv_slot >= INVITEMXLEN)
00331                     cpl.win_inv_slot -= INVITEMXLEN;
00332                 else if (my >= 116 && my <= 125)
00333                 {
00334                     cpl.win_inv_slot += INVITEMXLEN;
00335 
00336                     if (cpl.win_inv_slot > cpl.win_inv_count)
00337                         cpl.win_inv_slot = cpl.win_inv_count;
00338                 }
00339             }
00340             else if (mx > 3)
00341             {
00342                 /* Stuff */
00343 
00344                 /* Mousewheel */
00345                 if (event.button.button == 4 && cpl.win_inv_slot >= INVITEMXLEN)
00346                     cpl.win_inv_slot -= INVITEMXLEN;
00347                 /* Mousewheel */
00348                 else if (event.button.button == 5)
00349                 {
00350                     cpl.win_inv_slot += INVITEMXLEN;
00351 
00352                     if (cpl.win_inv_slot > cpl.win_inv_count)
00353                         cpl.win_inv_slot = cpl.win_inv_count;
00354                 }
00355                 else if ((event.button.button == SDL_BUTTON_LEFT || event.button.button == SDL_BUTTON_RIGHT || event.button.button == SDL_BUTTON_MIDDLE) && my > 29 && my < 125)
00356                 {
00357                     cpl.win_inv_slot = (my - 30) / 32 * INVITEMXLEN + (mx - 3) / 32 + cpl.win_inv_start;
00358                     cpl.win_inv_tag = get_inventory_data(cpl.ob, &cpl.win_inv_ctag, &cpl.win_inv_slot, &cpl.win_inv_start, &cpl.win_inv_count, INVITEMXLEN, INVITEMYLEN);
00359 
00360                     if (event.button.button == SDL_BUTTON_RIGHT || event.button.button == SDL_BUTTON_MIDDLE)
00361                         keybind_process_command("?MARK");
00362                     else
00363                     {
00364                         if (cpl.inventory_win == IWIN_INV)
00365                             draggingInvItem(DRAG_IWIN_INV);
00366                     }
00367                 }
00368             }
00369 
00370             break;
00371 
00372         case SDL_MOUSEMOTION:
00373             /* Scrollbar sliders */
00374             if (event.button.button == SDL_BUTTON_LEFT && !draggingInvItem(DRAG_GET_STATUS))
00375             {
00376                 /* IWIN_INV Slider */
00377                 if (cpl.inventory_win == IWIN_INV && my + 38 && my + 116 && mx + 227 && mx + 236)
00378                 {
00379                     if (old_mouse_y - y > 0)
00380                         cpl.win_inv_slot -= INVITEMXLEN;
00381                     else if (old_mouse_y - y < 0)
00382                         cpl.win_inv_slot += INVITEMXLEN;
00383 
00384                     if (cpl.win_inv_slot > cpl.win_inv_count)
00385                         cpl.win_inv_slot = cpl.win_inv_count;
00386 
00387                     break;
00388                 }
00389             }
00390     }
00391 }
00392 
00393 void widget_show_inventory_window(widgetdata *widget)
00394 {
00395     int i, invxlen, invylen;
00396     object *op, *tmp, *tmpx = NULL;
00397     object *tmpc;
00398     char buf[256];
00399     widgetdata *tmp_widget;
00400 
00401     if (cpl.inventory_win != IWIN_INV)
00402     {
00403         if (!setting_get_int(OPT_CAT_GENERAL, OPT_PLAYERDOLL))
00404         {
00405             /* do this for all player doll widgets, even though there shouldn't be more than one */
00406             for (tmp_widget = cur_widget[PDOLL_ID]; tmp_widget; tmp_widget = tmp_widget->type_next)
00407             {
00408                 tmp_widget->show = 0;
00409             }
00410         }
00411 
00412         if (widget->ht != 32)
00413         {
00414             resize_widget(widget, RESIZE_BOTTOM, 32);
00415         }
00416 
00417         sprite_blt(Bitmaps[BITMAP_INV_BG], widget->x1, widget->y1, NULL, NULL);
00418 
00419         string_blt(ScreenSurface, FONT_ARIAL10, "Carrying", widget->x1 + 162, widget->y1 + 4, COLOR_HGOLD, 0, NULL);
00420 
00421         snprintf(buf, sizeof(buf), "%4.3f kg", cpl.real_weight);
00422         string_blt(ScreenSurface, FONT_ARIAL10, buf, widget->x1 + 207, widget->y1 + 4, COLOR_WHITE, 0, NULL);
00423 
00424         string_blt(ScreenSurface, FONT_ARIAL10, "Limit", widget->x1 + 162, widget->y1 + 15, COLOR_HGOLD, 0, NULL);
00425 
00426         snprintf(buf, sizeof(buf), "%4.3f kg", (float) cpl.weight_limit / 1000.0);
00427         string_blt(ScreenSurface, FONT_ARIAL10, buf, widget->x1 + 207, widget->y1 + 15, COLOR_WHITE, 0, NULL);
00428 
00429         string_blt(ScreenSurface, FONT_ARIAL10, "(SHIFT for inventory)", widget->x1 + 35, widget->y1 + 9, COLOR_WHITE, TEXT_OUTLINE, NULL);
00430         return;
00431     }
00432 
00433     if (!setting_get_int(OPT_CAT_GENERAL, OPT_PLAYERDOLL))
00434     {
00435         /* do this for all player doll widgets, even though there shouldn't be more than one */
00436         for (tmp_widget = cur_widget[PDOLL_ID]; tmp_widget; tmp_widget = tmp_widget->type_next)
00437         {
00438             tmp_widget->show = 1;
00439         }
00440     }
00441 
00442     if (widget->ht != 129)
00443     {
00444         resize_widget(widget, RESIZE_BOTTOM, 129);
00445     }
00446 
00447     invxlen = INVITEMXLEN;
00448     invylen = INVITEMYLEN;
00449 
00450     sprite_blt(Bitmaps[BITMAP_INVENTORY], widget->x1, widget->y1, NULL, NULL);
00451 
00452     blt_window_slider(Bitmaps[BITMAP_INV_SCROLL], ((cpl.win_inv_count - 1) / invxlen) + 1, invylen, cpl.win_inv_start / invxlen, -1, widget->x1 + 261, widget->y1 + 42);
00453 
00454     if (!cpl.ob)
00455     {
00456         return;
00457     }
00458 
00459     op = cpl.ob;
00460 
00461     for (tmpc = NULL, i = 0, tmp = op->inv; tmp && i < cpl.win_inv_start; tmp = tmp->next)
00462     {
00463         if (inventory_matches_filter(tmp))
00464         {
00465             i++;
00466         }
00467 
00468         if (cpl.container && cpl.container->tag == tmp->tag)
00469         {
00470             tmpx = tmp;
00471             tmpc = cpl.sack->inv;
00472 
00473             for (; tmpc && i < cpl.win_inv_start; tmpc = tmpc->next,i++);
00474 
00475             if (tmpc)
00476             {
00477                 break;
00478             }
00479         }
00480     }
00481 
00482     i = 0;
00483 
00484     if (tmpc)
00485     {
00486         tmp = tmpx;
00487         goto jump_in_container1;
00488     }
00489 
00490     for (; tmp && i < invxlen * invylen; tmp = tmp->next)
00491     {
00492         if (inventory_matches_filter(tmp))
00493         {
00494             if (tmp->tag == cpl.mark_count)
00495             {
00496                 sprite_blt(Bitmaps[BITMAP_INVSLOT_MARKED], widget->x1 + (i % invxlen) * 32 + 3, widget->y1 + (i / invxlen) * 32 + 31, NULL, NULL);
00497             }
00498 
00499             blt_inv_item(tmp, widget->x1 + (i % invxlen) * 32 + 4, widget->y1 + (i / invxlen) * 32 + 32);
00500 
00501             if (cpl.inventory_win != IWIN_BELOW && i + cpl.win_inv_start == cpl.win_inv_slot)
00502             {
00503                 sprite_blt(Bitmaps[BITMAP_INVSLOT], widget->x1 + (i % invxlen) * 32 + 3, widget->y1 + (i / invxlen) * 32 + 31, NULL, NULL);
00504                 show_inventory_item_stats(tmp, widget);
00505             }
00506 
00507             i++;
00508         }
00509 
00510         /* We have an open container - 'insert' the items inside in the panel */
00511         if (cpl.container && cpl.container->tag == tmp->tag)
00512         {
00513             sprite_blt(Bitmaps[BITMAP_CMARK_START], widget->x1 + ((i - 1) % invxlen) * 32 + 4, widget->y1 + ((i - 1) / invxlen) * 32 + 32, NULL, NULL);
00514             tmpc = cpl.sack->inv;
00515 
00516 jump_in_container1:
00517             for (; tmpc && i < invxlen * invylen; tmpc = tmpc->next)
00518             {
00519                 if (tmpc->tag == cpl.mark_count)
00520                 {
00521                     sprite_blt(Bitmaps[BITMAP_INVSLOT_MARKED], widget->x1 + (i % invxlen) * 32 + 3, widget->y1 + (i / invxlen) * 32 + 31, NULL, NULL);
00522                 }
00523 
00524                 blt_inv_item(tmpc, widget->x1 + (i % invxlen) * 32 + 4, widget->y1 + (i / invxlen) * 32 + 32);
00525 
00526                 if (cpl.inventory_win != IWIN_BELOW && i + cpl.win_inv_start == cpl.win_inv_slot)
00527                 {
00528                     sprite_blt(Bitmaps[BITMAP_INVSLOT], widget->x1 + (i % invxlen) * 32 + 3, widget->y1 + (i / invxlen) * 32 + 31, NULL, NULL);
00529 
00530                     show_inventory_item_stats(tmpc, widget);
00531                 }
00532 
00533                 sprite_blt(Bitmaps[BITMAP_CMARK_MIDDLE], widget->x1 + (i % invxlen) * 32 + 4, widget->y1 + (i / invxlen) * 32 + 32, NULL, NULL);
00534                 i++;
00535             }
00536 
00537             if (!tmpc)
00538             {
00539                 sprite_blt(Bitmaps[BITMAP_CMARK_END], widget->x1 + ((i - 1) % invxlen) * 32 + 4, widget->y1 + ((i - 1) / invxlen) * 32 + 32, NULL, NULL);
00540             }
00541         }
00542     }
00543 }
00544 
00545 void widget_below_window_event(widgetdata *widget, int x, int y, int MEvent)
00546 {
00547     /* ground ( IWIN_BELOW )  */
00548     if (y >= widget->y1 + 19 && y <= widget->y1 + widget->ht - 4 && x > widget->x1 + 4 && x < widget->x1 + widget->wd - 12)
00549     {
00550         if (cpl.inventory_win == IWIN_INV)
00551         {
00552             cpl.inventory_win = IWIN_BELOW;
00553         }
00554 
00555         cpl.win_below_slot = (x - widget->x1 - 5) / 32;
00556 
00557         cpl.win_below_tag = get_inventory_data(cpl.below, &cpl.win_below_ctag, &cpl.win_below_slot, &cpl.win_below_start, &cpl.win_below_count, INVITEMBELOWXLEN, INVITEMBELOWYLEN);
00558 
00559         if ((SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_LEFT)))
00560         {
00561             if (cpl.below->inv)
00562             {
00563                 draggingInvItem(DRAG_IWIN_BELOW);
00564             }
00565         }
00566         else
00567         {
00568             keybind_process_command("?APPLY");
00569         }
00570     }
00571     else if (y >= widget->y1 + 20 && y <= widget->y1 + 29 && x > widget->x1 + 262 && x < widget->x1 + 269 && MEvent == MOUSE_DOWN)
00572     {
00573         if (cpl.inventory_win == IWIN_INV)
00574         {
00575             cpl.inventory_win = IWIN_BELOW;
00576         }
00577 
00578         cpl.win_below_slot = cpl.win_below_slot - INVITEMBELOWXLEN;
00579 
00580         if (cpl.win_below_slot < 0)
00581         {
00582             cpl.win_below_slot = 0;
00583         }
00584 
00585         cpl.win_below_tag = get_inventory_data(cpl.below, &cpl.win_below_ctag, &cpl.win_below_slot, &cpl.win_below_start, &cpl.win_below_count, INVITEMBELOWXLEN, INVITEMBELOWYLEN);
00586     }
00587     else if (y >= widget->y1 + 42 && y <= widget->y1 + 51 && x > widget->x1 + 262 && x < widget->x1 + 269 && MEvent == MOUSE_DOWN)
00588     {
00589         if (cpl.inventory_win == IWIN_INV)
00590         {
00591             cpl.inventory_win = IWIN_BELOW;
00592         }
00593 
00594         cpl.win_below_slot = cpl.win_below_slot + INVITEMBELOWXLEN;
00595 
00596         if (cpl.win_below_slot > cpl.win_below_count -1)
00597         {
00598             cpl.win_below_slot = cpl.win_below_count -1;
00599         }
00600 
00601         cpl.win_below_tag = get_inventory_data(cpl.below, &cpl.win_below_ctag, &cpl.win_below_slot, &cpl.win_below_start, &cpl.win_below_count, INVITEMBELOWXLEN, INVITEMBELOWYLEN);
00602     }
00603 }
00604 
00605 void widget_show_below_window(widgetdata *widget)
00606 {
00607     int i, slot,at;
00608     object *tmp, *tmpc, *tmpx = NULL;
00609     char buf[256];
00610 
00611     sprite_blt(Bitmaps[BITMAP_BELOW], widget->x1, widget->y1, NULL, NULL);
00612 
00613     blt_window_slider(Bitmaps[BITMAP_BELOW_SCROLL], ((cpl.win_below_count - 1) / INVITEMBELOWXLEN) + 1, INVITEMBELOWYLEN, cpl.win_below_start / INVITEMBELOWXLEN, -1, widget->x1 + 263, widget->y1 + 30);
00614 
00615     if (!cpl.below)
00616     {
00617         return;
00618     }
00619 
00620     for (i = 0, tmpc = NULL, tmp = cpl.below->inv; tmp && i < cpl.win_below_start; tmp = tmp->next)
00621     {
00622         i++;
00623         tmpx = tmp;
00624 
00625         if (cpl.container && cpl.container->tag == tmp->tag)
00626         {
00627             tmpc = cpl.sack->inv;
00628 
00629             for (; tmpc && i < cpl.win_below_start; tmpc = tmpc->next, i++);
00630 
00631             if (tmpc)
00632             {
00633                 break;
00634             }
00635         }
00636     }
00637 
00638     i = 0;
00639 
00640     if (tmpc)
00641     {
00642         tmp = tmpx;
00643         goto jump_in_container2;
00644     }
00645 
00646     for (; tmp && i < INVITEMBELOWXLEN * INVITEMBELOWYLEN; tmp = tmp->next)
00647     {
00648         at = tmp->flags & F_APPLIED;
00649 
00650         if (tmp->tag != cpl.container_tag)
00651             tmp->flags &= ~F_APPLIED;
00652 
00653         blt_inv_item(tmp, widget->x1 + (i % INVITEMBELOWXLEN) * 32 + 5, widget->y1 + (i / INVITEMBELOWXLEN) * 32 + 19);
00654 
00655         if (at)
00656         {
00657             tmp->flags |= F_APPLIED;
00658         }
00659 
00660         if (i + cpl.win_below_start == cpl.win_below_slot)
00661         {
00662             if (cpl.inventory_win == IWIN_BELOW)
00663                 slot = BITMAP_INVSLOT;
00664             else
00665                 slot = BITMAP_INVSLOT_U;
00666 
00667             sprite_blt(Bitmaps[slot], widget->x1 + (i % INVITEMBELOWXLEN) * 32 + 5, widget->y1 + (i / INVITEMBELOWXLEN) * 32 + 19, NULL, NULL);
00668 
00669             if (tmp->nrof > 1)
00670                 snprintf(buf, sizeof(buf), "%d %s", tmp->nrof, tmp->s_name);
00671             else
00672                 snprintf(buf, sizeof(buf), "%s", tmp->s_name);
00673 
00674             string_truncate_overflow(FONT_ARIAL10, buf, 250);
00675             string_blt(ScreenSurface, FONT_ARIAL10, buf, widget->x1 + 6, widget->y1 + 4, COLOR_HGOLD, 0, NULL);
00676         }
00677 
00678         i++;
00679 
00680         /* We have an open container - 'insert' the items inside in the panel */
00681         if (cpl.container && cpl.container->tag == tmp->tag)
00682         {
00683             sprite_blt(Bitmaps[BITMAP_CMARK_START], widget->x1 + ((i - 1) % INVITEMBELOWXLEN) * 32 + 5, widget->y1 + ((i - 1) / INVITEMBELOWXLEN) * 32 + 19, NULL, NULL);
00684             tmpc = cpl.sack->inv;
00685 
00686 jump_in_container2:
00687             for (; tmpc && i < INVITEMBELOWXLEN * INVITEMBELOWYLEN; tmpc = tmpc->next)
00688             {
00689                 blt_inv_item(tmpc, widget->x1 + (i % INVITEMBELOWXLEN) * 32 + 5, widget->y1 + (i / INVITEMBELOWXLEN) * 32 + 19);
00690 
00691                 if (i + cpl.win_below_start == cpl.win_below_slot)
00692                 {
00693                     if (cpl.inventory_win == IWIN_BELOW)
00694                         slot = BITMAP_INVSLOT;
00695                     else
00696                         slot = BITMAP_INVSLOT_U;
00697 
00698                     sprite_blt(Bitmaps[slot], widget->x1 + (i % INVITEMBELOWXLEN) * 32 + 5, widget->y1 + (i / INVITEMBELOWXLEN) * 32 + 19, NULL, NULL);
00699 
00700                     if (tmpc->nrof > 1)
00701                         snprintf(buf, sizeof(buf), "%d %s", tmpc->nrof, tmpc->s_name);
00702                     else
00703                         snprintf(buf, sizeof(buf), "%s", tmpc->s_name);
00704 
00705                     string_truncate_overflow(FONT_ARIAL10, buf, 250);
00706                     string_blt(ScreenSurface, FONT_ARIAL10, buf, widget->x1 + 6, widget->y1 + 3, COLOR_HGOLD, 0, NULL);
00707                 }
00708 
00709                 sprite_blt(Bitmaps[BITMAP_CMARK_MIDDLE], widget->x1 + (i % INVITEMBELOWXLEN) * 32 + 5, widget->y1 + (i / INVITEMBELOWXLEN) * 32 + 19, NULL, NULL);
00710                 i++;
00711             }
00712 
00713             if (!tmpc)
00714                 sprite_blt(Bitmaps[BITMAP_CMARK_END], widget->x1 + ((i - 1) % INVITEMBELOWXLEN) * 32 + 5, widget->y1 + ((i - 1) / INVITEMBELOWXLEN) * 32 + 19, NULL, NULL);
00715         }
00716     }
00717 }
00718 
00719 #define ICONDEFLEN 32
00720 int blt_inv_item_centered(object *tmp, int x, int y)
00721 {
00722     int temp, xstart, xlen, ystart, ylen;
00723     sint16 anim1;
00724     SDL_Rect box;
00725     _BLTFX bltfx;
00726     bltfx.flags = 0;
00727     bltfx.dark_level = 0;
00728     bltfx.surface = NULL;
00729     bltfx.alpha = 128;
00730 
00731     if (!FaceList[tmp->face].sprite)
00732         return 0;
00733 
00734     anim1 = tmp->face;
00735 
00736     /* This is part of animation... Because ISO items have different offsets and sizes,
00737      * we must use ONE sprite base offset to center an animation over an animation.
00738      * we use the first frame of an animation for it.*/
00739     if (tmp->animation_id > 0)
00740     {
00741         check_animation_status(tmp->animation_id);
00742 
00743         /* First bitmap of this animation */
00744         if (animations[tmp->animation_id].num_animations && animations[tmp->animation_id].facings <= 1)
00745             anim1 = animations[tmp->animation_id].faces[0];
00746     }
00747 
00748     /* Fallback: first animation bitmap not loaded */
00749     if (!FaceList[anim1].sprite)
00750         anim1 = tmp->face;
00751 
00752     xstart = FaceList[anim1].sprite->border_left;
00753     xlen = FaceList[anim1].sprite->bitmap->w - xstart-FaceList[anim1].sprite->border_right;
00754     ystart = FaceList[anim1].sprite->border_up;
00755     ylen = FaceList[anim1].sprite->bitmap->h - ystart-FaceList[anim1].sprite->border_down;
00756 
00757     if (xlen > 32)
00758     {
00759         box.w = 32;
00760         temp = (xlen - 32) / 2;
00761         box.x = xstart + temp;
00762         xstart = 0;
00763     }
00764     else
00765     {
00766         box.w = xlen;
00767         box.x = xstart;
00768         xstart = (32 - xlen) / 2;
00769     }
00770 
00771     if (ylen > 32)
00772     {
00773         box.h = 32;
00774         temp = (ylen - 32) / 2;
00775         box.y = ystart + temp;
00776         ystart = 0;
00777     }
00778     else
00779     {
00780         box.h = ylen;
00781         box.y = ystart;
00782         ystart = (32 - ylen) / 2;
00783     }
00784 
00785     /* Now we have a perfect centered sprite.
00786      * But: If this is the start pos of our
00787      * first animation and not of our sprite,
00788      * we must shift it a bit to insert our
00789      * face exactly. */
00790     if (anim1 != tmp->face)
00791     {
00792         temp = xstart-box.x;
00793 
00794         box.x = 0;
00795         box.w = FaceList[tmp->face].sprite->bitmap->w;
00796         xstart = temp;
00797 
00798         temp = ystart - box.y + (FaceList[anim1].sprite->bitmap->h - FaceList[tmp->face].sprite->bitmap->h);
00799         box.y = 0;
00800         box.h = FaceList[tmp->face].sprite->bitmap->h;
00801         ystart = temp;
00802 
00803         if (xstart < 0)
00804         {
00805             box.x = -xstart;
00806             box.w = FaceList[tmp->face].sprite->bitmap->w + xstart;
00807 
00808             if (box.w > 32)
00809                 box.w = 32;
00810 
00811             xstart = 0;
00812         }
00813         else
00814         {
00815             if (box.w + xstart > 32)
00816                 box.w -= ((box.w + xstart) - 32);
00817         }
00818 
00819         if (ystart < 0)
00820         {
00821             box.y = -ystart;
00822             box.h = FaceList[tmp->face].sprite->bitmap->h + ystart;
00823 
00824             if (box.h > 32)
00825                 box.h = 32;
00826 
00827             ystart = 0;
00828         }
00829         else
00830         {
00831             if (box.h + ystart > 32)
00832                 box.h -= ((box.h + ystart) - 32);
00833         }
00834     }
00835 
00836     if (tmp->flags & F_INVISIBLE)
00837         bltfx.flags = BLTFX_FLAG_SRCALPHA | BLTFX_FLAG_GREY;
00838 
00839     if (tmp->flags & F_ETHEREAL)
00840         bltfx.flags = BLTFX_FLAG_SRCALPHA;
00841 
00842     sprite_blt(FaceList[tmp->face].sprite, x + xstart, y + ystart, &box, &bltfx);
00843 
00844     return 1;
00845 }
00846 
00856 void blt_inv_item(object *tmp, int x, int y)
00857 {
00858     int fire_ready;
00859 
00860     blt_inv_item_centered(tmp, x, y);
00861 
00862     if (tmp->nrof > 1)
00863     {
00864         char buf[64];
00865 
00866         if (tmp->nrof > 9999)
00867         {
00868             snprintf(buf, sizeof(buf), "many");
00869         }
00870         else
00871         {
00872             snprintf(buf, sizeof(buf), "%d", tmp->nrof);
00873         }
00874 
00875         string_blt(ScreenSurface, FONT_ARIAL10, buf, x + ICONDEFLEN / 2 - string_get_width(FONT_ARIAL10, buf, 0) / 2, y + 18, COLOR_WHITE, TEXT_OUTLINE, NULL);
00876     }
00877 
00878     /* Determine whether there is a readied object for firing or not. */
00879     fire_ready = (fire_mode_tab[FIRE_MODE_THROW].item == tmp->tag || fire_mode_tab[FIRE_MODE_BOW].amun == tmp->tag) && tmp->env == cpl.ob;
00880 
00881     if (tmp->flags & F_APPLIED)
00882     {
00883         sprite_blt(Bitmaps[BITMAP_APPLY], x, y, NULL, NULL);
00884 
00885         if (fire_ready)
00886         {
00887             sprite_blt(Bitmaps[BITMAP_FIRE_READY], x, y + 8, NULL, NULL);
00888         }
00889     }
00890     else if (tmp->flags & F_UNPAID)
00891     {
00892         sprite_blt(Bitmaps[BITMAP_UNPAID], x, y, NULL, NULL);
00893     }
00894     else if (fire_ready)
00895     {
00896         sprite_blt(Bitmaps[BITMAP_FIRE_READY], x, y, NULL, NULL);
00897     }
00898 
00899     if (tmp->flags & F_LOCKED)
00900     {
00901         sprite_blt(Bitmaps[BITMAP_LOCK], x, y + ICONDEFLEN - Bitmaps[BITMAP_LOCK]->bitmap->w - 2, NULL, NULL);
00902     }
00903 
00904     if (tmp->flags & F_MAGIC)
00905     {
00906         sprite_blt(Bitmaps[BITMAP_MAGIC], x + ICONDEFLEN - Bitmaps[BITMAP_MAGIC]->bitmap->w - 2, y + ICONDEFLEN - Bitmaps[BITMAP_MAGIC]->bitmap->h - 2, NULL, NULL);
00907     }
00908 
00909     if (tmp->flags & F_DAMNED)
00910     {
00911         sprite_blt(Bitmaps[BITMAP_DAMNED], x + ICONDEFLEN - Bitmaps[BITMAP_DAMNED]->bitmap->w - 2, y, NULL, NULL);
00912     }
00913     else if (tmp->flags & F_CURSED)
00914     {
00915         sprite_blt(Bitmaps[BITMAP_CURSED], x + ICONDEFLEN - Bitmaps[BITMAP_CURSED]->bitmap->w - 2, y, NULL, NULL);
00916     }
00917 
00918     if (tmp->flags & F_TRAPPED)
00919     {
00920         sprite_blt(Bitmaps[BITMAP_TRAPPED], x + ICONDEFLEN / 2 - Bitmaps[BITMAP_TRAPPED]->bitmap->w / 2, y + ICONDEFLEN / 2 - Bitmaps[BITMAP_TRAPPED]->bitmap->h / 2, NULL, NULL);
00921     }
00922 }