• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

gui/player_shop.c

Go to the documentation of this file.
00001 /************************************************************************
00002 *            Atrinik, a Multiplayer Online Role Playing Game            *
00003 *                                                                       *
00004 *    Copyright (C) 2009-2010 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 <include.h>
00031 
00033 _shop_gui_struct *shop_gui = NULL;
00034 
00038 coins_struct coins[] =
00039 {
00040     {"m",   10000000},
00041     {"g",   10000},
00042     {"s",   100},
00043     {"c",   1},
00044 };
00045 
00047 #define COINS_ARRAY_SIZE (int) (sizeof(coins) / sizeof(coins_struct))
00048 
00049 static void shop_add_button(int x, int y, const char *text);
00050 
00055 void widget_show_shop(widgetdata *widget)
00056 {
00057     /* Show the main shop bitmap */
00058     sprite_blt(Bitmaps[BITMAP_SHOP], widget->x1, widget->y1, NULL, NULL);
00059 
00060     /* Add a close button at top right */
00061     shop_add_close_button(widget->x1 + Bitmaps[BITMAP_SHOP]->bitmap->w - 10, widget->y1 + 2);
00062 
00063     /* Sanity check, because the close button can close the GUI */
00064     if (!shop_gui)
00065     {
00066         return;
00067     }
00068 
00069     /* Show a title for the shop widget */
00070     if (shop_gui->shop_state == SHOP_STATE_BUYING)
00071     {
00072         char buf[MAX_BUF];
00073 
00074         snprintf(buf, sizeof(buf), "Shop: %s", shop_gui->shop_owner);
00075 
00076         StringBlt(ScreenSurface, &SystemFont, buf, widget->x1 + 4, widget->y1 + 1, COLOR_BLACK, NULL, NULL);
00077         StringBlt(ScreenSurface, &SystemFont, buf, widget->x1 + 5, widget->y1 + 2, COLOR_WHITE, NULL, NULL);
00078     }
00079     else
00080     {
00081         StringBlt(ScreenSurface, &SystemFont, "Shop", widget->x1 + 4, widget->y1 + 1, COLOR_BLACK, NULL, NULL);
00082         StringBlt(ScreenSurface, &SystemFont, "Shop", widget->x1 + 5, widget->y1 + 2, COLOR_WHITE, NULL, NULL);
00083     }
00084 
00085     /* Determine the right kind of buttons and inputs to show */
00086     switch (shop_gui->shop_state)
00087     {
00088         /* Show "Open" button and Price/Number inputs */
00089         case SHOP_STATE_NONE:
00090             if (shop_gui->selected_tag)
00091             {
00092                 shop_add_button(widget->x1 + 4, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - Bitmaps[BITMAP_DIALOG_BUTTON_UP]->bitmap->h - 3, "Remove");
00093             }
00094 
00095             shop_add_button(widget->x1 + Bitmaps[BITMAP_SHOP]->bitmap->w - Bitmaps[BITMAP_DIALOG_BUTTON_UP]->bitmap->w - 4, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - Bitmaps[BITMAP_DIALOG_BUTTON_UP]->bitmap->h - 3, "Open");
00096 
00097             if (!shop_gui)
00098             {
00099                 return;
00100             }
00101 
00102             StringBlt(ScreenSurface, &SystemFont, "Price:", widget->x1 + 5, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - 56, COLOR_BLACK, NULL, NULL);
00103 
00104             if (shop_gui->input_type == SHOP_INPUT_TYPE_PRICE)
00105             {
00106                 StringBlt(ScreenSurface, &SystemFont, "Price:", widget->x1 + 6, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - 55, COLOR_HGOLD, NULL, NULL);
00107             }
00108             else
00109             {
00110                 StringBlt(ScreenSurface, &SystemFont, "Price:", widget->x1 + 6, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - 55, COLOR_WHITE, NULL, NULL);
00111             }
00112 
00113             sprite_blt(Bitmaps[BITMAP_SHOP_INPUT], widget->x1 + Bitmaps[BITMAP_SHOP]->bitmap->w - Bitmaps[BITMAP_SHOP_INPUT]->bitmap->w - 4, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - 57, NULL, NULL);
00114 
00115             StringBlt(ScreenSurface, &SystemFont, "Number:", widget->x1 + 5, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - 39, COLOR_BLACK, NULL, NULL);
00116 
00117             if (shop_gui->input_type == SHOP_INPUT_TYPE_NROF)
00118             {
00119                 StringBlt(ScreenSurface, &SystemFont, "Number:", widget->x1 + 6, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - 38, COLOR_HGOLD, NULL, NULL);
00120             }
00121             else
00122             {
00123                 StringBlt(ScreenSurface, &SystemFont, "Number:", widget->x1 + 6, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - 38, COLOR_WHITE, NULL, NULL);
00124             }
00125 
00126             sprite_blt(Bitmaps[BITMAP_SHOP_INPUT], widget->x1 + Bitmaps[BITMAP_SHOP]->bitmap->w - Bitmaps[BITMAP_SHOP_INPUT]->bitmap->w - 4, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - 40, NULL, NULL);
00127 
00128             break;
00129 
00130         /* Shop "Buy" and "Examine" buttons and Number input */
00131         case SHOP_STATE_BUYING:
00132             if (shop_gui->selected_tag)
00133             {
00134                 shop_add_button(widget->x1 + 4, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - Bitmaps[BITMAP_DIALOG_BUTTON_UP]->bitmap->h - 3, "Buy");
00135 
00136                 shop_add_button(widget->x1 + Bitmaps[BITMAP_SHOP]->bitmap->w - Bitmaps[BITMAP_DIALOG_BUTTON_UP]->bitmap->w - 4, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - Bitmaps[BITMAP_DIALOG_BUTTON_UP]->bitmap->h - 3, "Examine");
00137             }
00138 
00139             StringBlt(ScreenSurface, &SystemFont, "Number:", widget->x1 + 5, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - 56, COLOR_BLACK, NULL, NULL);
00140 
00141             if (shop_gui->input_type == SHOP_INPUT_TYPE_NROF)
00142             {
00143                 StringBlt(ScreenSurface, &SystemFont, "Number:", widget->x1 + 6, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - 55, COLOR_HGOLD, NULL, NULL);
00144             }
00145             else
00146             {
00147                 StringBlt(ScreenSurface, &SystemFont, "Number:", widget->x1 + 6, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - 55, COLOR_WHITE, NULL, NULL);
00148             }
00149 
00150             sprite_blt(Bitmaps[BITMAP_SHOP_INPUT], widget->x1 + Bitmaps[BITMAP_SHOP]->bitmap->w - Bitmaps[BITMAP_SHOP_INPUT]->bitmap->w - 4, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - 57, NULL, NULL);
00151 
00152             break;
00153     }
00154 
00155     /* If there are items to show */
00156     if (shop_gui->shop_items)
00157     {
00158         _shop_struct *shop_item_tmp;
00159         int item_x = 36, item_y = 18, i = 1, found_selected = 0;
00160         int mx, my, mb;
00161         char buf[MAX_BUF];
00162 
00163         mb = SDL_GetMouseState(&mx, &my) & SDL_BUTTON(SDL_BUTTON_LEFT);
00164 
00165         /* Loop through the items */
00166         for (shop_item_tmp = shop_gui->shop_items; shop_item_tmp; shop_item_tmp = shop_item_tmp->next)
00167         {
00168             object *shop_item;
00169 
00170             /* Item is gone */
00171             if (shop_item_tmp->tag == -1)
00172             {
00173                 continue;
00174             }
00175 
00176             shop_item = object_find(shop_item_tmp->tag);
00177 
00178             if (!shop_item)
00179             {
00180                 continue;
00181             }
00182 
00183             /* If we clicked on the item, set the selected tag accordingly */
00184             if (mx > widget->x1 + item_x && mx < widget->x1 + item_x + 32 && my > widget->y1 + item_y && my < widget->y1 + item_y + 32 && mb && mb_clicked)
00185             {
00186                 shop_gui->selected_tag = shop_item_tmp->tag;
00187 
00188                 switch (shop_gui->shop_state)
00189                 {
00190                     case SHOP_STATE_NONE:
00191                         shop_gui->current_cursor_pos = (int) strlen(shop_item_tmp->price_buf);
00192 
00193                         break;
00194 
00195                     case SHOP_STATE_BUYING:
00196                         snprintf(buf, sizeof(buf), "%d", shop_item_tmp->nrof);
00197 
00198                         shop_gui->current_cursor_pos = (int) strlen(buf);
00199 
00200                         break;
00201                 }
00202             }
00203 
00204             /* If this is the selected item, show a marker */
00205             if (shop_item_tmp->tag == shop_gui->selected_tag)
00206             {
00207                 found_selected = 1;
00208 
00209                 sprite_blt(Bitmaps[BITMAP_INVSLOT], widget->x1 + item_x, widget->y1 + item_y, NULL, NULL);
00210 
00211                 switch (shop_gui->shop_state)
00212                 {
00213                     /* Show "Open" button and Price/Number inputs */
00214                     case SHOP_STATE_NONE:
00215                         snprintf(buf, sizeof(buf), "%s", shop_item_tmp->price_buf);
00216 
00217                         strcpy(buf, shop_show_input(buf, &SystemFont, Bitmaps[BITMAP_SHOP_INPUT]->bitmap->w - 5, shop_gui->input_type == SHOP_INPUT_TYPE_PRICE ? 1 : 0));
00218 
00219                         StringBlt(ScreenSurface, &SystemFont, buf, widget->x1 + Bitmaps[BITMAP_SHOP]->bitmap->w - Bitmaps[BITMAP_SHOP_INPUT]->bitmap->w, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - 55, COLOR_BLACK, NULL, NULL);
00220                         StringBlt(ScreenSurface, &SystemFont, buf, widget->x1 + Bitmaps[BITMAP_SHOP]->bitmap->w - Bitmaps[BITMAP_SHOP_INPUT]->bitmap->w - 1, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - 56, COLOR_WHITE, NULL, NULL);
00221 
00222                         snprintf(buf, sizeof(buf), "%d", shop_item_tmp->nrof);
00223 
00224                         strcpy(buf, shop_show_input(buf, &SystemFont, Bitmaps[BITMAP_SHOP_INPUT]->bitmap->w - 5, shop_gui->input_type == SHOP_INPUT_TYPE_NROF ? 1 : 0));
00225 
00226                         StringBlt(ScreenSurface, &SystemFont, buf, widget->x1 + Bitmaps[BITMAP_SHOP]->bitmap->w - Bitmaps[BITMAP_SHOP_INPUT]->bitmap->w, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - 38, COLOR_BLACK, NULL, NULL);
00227                         StringBlt(ScreenSurface, &SystemFont, buf, widget->x1 + Bitmaps[BITMAP_SHOP]->bitmap->w - Bitmaps[BITMAP_SHOP_INPUT]->bitmap->w - 1, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - 39, COLOR_WHITE, NULL, NULL);
00228 
00229                         break;
00230 
00231                     case SHOP_STATE_BUYING:
00232                         snprintf(buf, sizeof(buf), "%d", shop_item_tmp->nrof);
00233 
00234                         strcpy(buf, shop_show_input(buf, &SystemFont, Bitmaps[BITMAP_SHOP_INPUT]->bitmap->w - 5, shop_gui->input_type == SHOP_INPUT_TYPE_NROF ? 1 : 0));
00235 
00236                         StringBlt(ScreenSurface, &SystemFont, buf, widget->x1 + Bitmaps[BITMAP_SHOP]->bitmap->w - Bitmaps[BITMAP_SHOP_INPUT]->bitmap->w, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - 55, COLOR_BLACK, NULL, NULL);
00237                         StringBlt(ScreenSurface, &SystemFont, buf, widget->x1 + Bitmaps[BITMAP_SHOP]->bitmap->w - Bitmaps[BITMAP_SHOP_INPUT]->bitmap->w - 1, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - 56, COLOR_WHITE, NULL, NULL);
00238 
00239                         break;
00240                 }
00241 
00242                 if (shop_gui->shop_state != SHOP_STATE_OPEN)
00243                 {
00244                     snprintf(buf, sizeof(buf), "Price:%s", shop_int2price(shop_item_tmp->price));
00245 
00246                     StringBlt(ScreenSurface, &SystemFont, buf, widget->x1 + Bitmaps[BITMAP_SHOP]->bitmap->w - Bitmaps[BITMAP_SHOP_INPUT]->bitmap->w, widget->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h - 75, COLOR_WHITE, NULL, NULL);
00247                 }
00248             }
00249 
00250             blt_inv_item(shop_item, widget->x1 + item_x, widget->y1 + item_y, shop_gui->shop_state == SHOP_STATE_NONE ? shop_item_tmp->nrof : shop_item->nrof);
00251 
00252             /* Adjust the item X position */
00253             item_x += 32;
00254 
00255             /* If we hit fourth item, adjust the positions */
00256             if (i == 4)
00257             {
00258                 item_x = 36;
00259                 item_y += 32;
00260                 i = 0;
00261             }
00262 
00263             i++;
00264         }
00265 
00266         if (shop_gui->selected_tag && !found_selected)
00267         {
00268             shop_gui->selected_tag = 0;
00269         }
00270     }
00271 }
00272 
00275 void shop_open()
00276 {
00277     _shop_struct *shop_item_tmp;
00278     char buf[HUGE_BUF];
00279 
00280     /* Need at least one item */
00281     if (shop_gui->shop_items_count < 1)
00282     {
00283         draw_info("You need to have at least one item to sell in order to open a shop.", COLOR_RED);
00284         return;
00285     }
00286 
00287     strcpy(buf, "shop open");
00288 
00289     /* Loop through the shop items */
00290     for (shop_item_tmp = shop_gui->shop_items; shop_item_tmp; shop_item_tmp = shop_item_tmp->next)
00291     {
00292         char tmp_buf[MAX_BUF];
00293         object *shop_item = object_find(shop_item_tmp->tag);
00294 
00295         /* If the item could not be found, something is wrong */
00296         if (!shop_item)
00297         {
00298             draw_info("Unable to locate shop item from tag.", COLOR_RED);
00299             clear_shop(0);
00300             return;
00301         }
00302 
00303         /* Some checking */
00304         if (shop_item_tmp->price < 1 || shop_item_tmp->price > MAX_PRICE_VALUE)
00305         {
00306             draw_info_format(COLOR_RED, "The item %s doesn't have a valid price.", shop_item->s_name);
00307             return;
00308         }
00309         else if (shop_item_tmp->nrof < 1 || shop_item_tmp->nrof > MAX_PRICE_VALUE)
00310         {
00311             draw_info_format(COLOR_RED, "The item %s doesn't have a valid nrof.", shop_item->s_name);
00312             return;
00313         }
00314 
00315         /* Store the item tag, nrof and price */
00316         snprintf(tmp_buf, sizeof(tmp_buf), "|%d:%d:%d", shop_item_tmp->tag, shop_item_tmp->nrof, shop_item_tmp->price);
00317 
00318         /* Append it to the socket string */
00319         strncat(buf, tmp_buf, sizeof(buf) - strlen(buf) - 1);
00320     }
00321 
00322     /* Write the socket string to server */
00323     cs_write_string(buf, strlen(buf));
00324 
00325     /* The shop is now open */
00326     shop_gui->shop_state = SHOP_STATE_OPEN;
00327 }
00328 
00331 void shop_buy_item()
00332 {
00333     char buf[MAX_BUF];
00334     object *shop_item = object_find(shop_gui->selected_tag);
00335     _shop_struct *shop_item_tmp;
00336 
00337     /* Loop through the shop items */
00338     for (shop_item_tmp = shop_gui->shop_items; shop_item_tmp; shop_item_tmp = shop_item_tmp->next)
00339     {
00340         /* If the tag matches */
00341         if (shop_item_tmp->tag == shop_item->tag)
00342         {
00343             /* If the nrof is the same, we will want to remove the item from the list */
00344             if (shop_item_tmp->nrof == shop_item->nrof)
00345             {
00346                 shop_object_remove(shop_item->tag);
00347             }
00348 
00349             break;
00350         }
00351     }
00352 
00353     /* Sanity check */
00354     if (!shop_item_tmp)
00355     {
00356         return;
00357     }
00358 
00359     /* If the nrof is not the same, decrease the shop inventory item's nrof */
00360     if (shop_item_tmp->nrof != shop_item->nrof)
00361     {
00362         shop_item->nrof -= shop_item_tmp->nrof;
00363     }
00364 
00365     /* Store the information in a buffer */
00366     snprintf(buf, sizeof(buf), "shop buy %s %d %d", shop_gui->shop_owner, shop_item->tag, shop_item_tmp->nrof);
00367 
00368     /* Send the buffer */
00369     cs_write_string(buf, strlen(buf));
00370 }
00371 
00376 void initialize_shop(int shop_state)
00377 {
00378     shop_gui = (_shop_gui_struct *) malloc(sizeof(_shop_gui_struct));
00379 
00380     /* Initialize defaults */
00381     shop_gui->shop_state = shop_state;
00382     shop_gui->shop_items_count = 0;
00383     shop_gui->shop_items = NULL;
00384     shop_gui->selected_tag = 0;
00385 
00386     shop_gui->current_cursor_pos = 0;
00387     shop_gui->input_count = 0;
00388 
00389     /* Determine correct input type */
00390     switch (shop_state)
00391     {
00392         case SHOP_STATE_NONE:
00393             shop_gui->input_type = SHOP_INPUT_TYPE_PRICE;
00394 
00395             break;
00396 
00397         case SHOP_STATE_BUYING:
00398             shop_gui->input_type = SHOP_INPUT_TYPE_NROF;
00399 
00400             break;
00401     }
00402 
00403     shop_gui->shop_owner[0] = '\0';
00404 
00405     map_udate_flag = 2;
00406 
00407     /* Show the shop widget now */
00408     cur_widget[SHOP_ID]->show = 1;
00409 }
00410 
00415 void clear_shop(int send_to_server)
00416 {
00417     _shop_struct *shop_item_tmp, *shop_item;
00418 
00419     /* Hide the shop widget */
00420     cur_widget[SHOP_ID]->show = 0;
00421 
00422     /* Sanity check */
00423     if (!shop_gui)
00424     {
00425         return;
00426     }
00427 
00428     if (send_to_server)
00429     {
00430         cs_write_string("shop close", 10);
00431     }
00432 
00433     shop_item = shop_gui->shop_items;
00434 
00435     /* Loop through the shop items */
00436     while (shop_item)
00437     {
00438         shop_item_tmp = shop_item->next;
00439 
00440         free(shop_item);
00441 
00442         shop_item = shop_item_tmp;
00443     }
00444 
00445     /* Free the shop GUI */
00446     free(shop_gui);
00447 
00448     shop_gui = NULL;
00449 }
00450 
00455 void shop_add_close_button(int x, int y)
00456 {
00457     int mx, my, mb;
00458 
00459     mb = SDL_GetMouseState(&mx, &my) & SDL_BUTTON(SDL_BUTTON_LEFT);
00460 
00461     /* Show X as background */
00462     StringBlt(ScreenSurface, &SystemFont, "X", x + 1, y + 1, COLOR_BLACK, NULL, NULL);
00463 
00464     /* If mouse is over it */
00465     if (mx > x - 3 && mx < x + 7 && my > y && my < y + 12)
00466     {
00467         /* Show the X in gold */
00468         StringBlt(ScreenSurface, &SystemFont, "X", x, y, COLOR_HGOLD, NULL, NULL);
00469 
00470         /* If it was clicked, close the shop */
00471         if (mb && mb_clicked)
00472         {
00473             clear_shop(1);
00474         }
00475         /* Otherwise display a tooltip */
00476         else
00477         {
00478             if (shop_gui->shop_state == SHOP_STATE_NONE)
00479             {
00480                 show_tooltip(mx, my, "Click to cancel opening the shop");
00481             }
00482             else
00483             {
00484                 show_tooltip(mx, my, "Close the shop window");
00485             }
00486         }
00487     }
00488     /* Mouse is not over it, show in white */
00489     else
00490     {
00491         StringBlt(ScreenSurface, &SystemFont, "X", x, y, COLOR_WHITE, NULL, NULL);
00492     }
00493 }
00494 
00500 static void shop_add_button(int x, int y, const char *text)
00501 {
00502     int mx, my, mb, text_x;
00503 
00504     mb = SDL_GetMouseState(&mx, &my) & SDL_BUTTON(SDL_BUTTON_LEFT);
00505 
00506     sprite_blt(Bitmaps[BITMAP_DIALOG_BUTTON_UP], x, y, NULL, NULL);
00507 
00508     /* Calculate text X position */
00509     text_x = x + Bitmaps[BITMAP_DIALOG_BUTTON_UP]->bitmap->w / 2 - (int) strlen(text) * 2 - 1;
00510 
00511     /* Display the button text background in black */
00512     StringBlt(ScreenSurface, &SystemFont, text, text_x + 1, y + 2, COLOR_BLACK, NULL, NULL);
00513 
00514     /* If the mouse is over it */
00515     if (mx > x && my > y && mx < x + Bitmaps[BITMAP_DIALOG_BUTTON_UP]->bitmap->w && my < y + Bitmaps[BITMAP_DIALOG_BUTTON_UP]->bitmap->h)
00516     {
00517         static int delta = 0;
00518 
00519         /* Show the text in gold */
00520         StringBlt(ScreenSurface, &SystemFont, text, text_x, y + 1, COLOR_HGOLD, NULL, NULL);
00521 
00522         if (!(SDL_GetMouseState(&mx, &my) & SDL_BUTTON(SDL_BUTTON_LEFT)))
00523         {
00524             delta = 0;
00525             return;
00526         }
00527 
00528         /* If it was clicked */
00529         if (shop_gui && mb && mb_clicked && !(delta++ & 7))
00530         {
00531             /* If we are buying */
00532             if (shop_gui->shop_state == SHOP_STATE_BUYING)
00533             {
00534                 /* For Examine button, do an examine */
00535                 if (strcmp(text, "Examine") == 0)
00536                 {
00537                     char buf[MAX_BUF];
00538 
00539                     snprintf(buf, sizeof(buf), "shop examine %s %d", shop_gui->shop_owner, shop_gui->selected_tag);
00540                     cs_write_string(buf, strlen(buf));
00541                 }
00542                 /* Otherwise buy the item */
00543                 else if (strcmp(text, "Buy") == 0)
00544                 {
00545                     shop_buy_item();
00546                 }
00547             }
00548             else
00549             {
00550                 if (strcmp(text, "Open") == 0)
00551                 {
00552                     shop_open();
00553                 }
00554                 else if (strcmp(text, "Remove") == 0)
00555                 {
00556                     shop_object_remove(shop_gui->selected_tag);
00557                 }
00558             }
00559         }
00560     }
00561     /* Mouse is not over the button, show the text in white */
00562     else
00563     {
00564         StringBlt(ScreenSurface, &SystemFont, text, text_x, y + 1, COLOR_WHITE, NULL, NULL);
00565     }
00566 }
00567 
00573 int shop_put_item(int x, int y)
00574 {
00575     /* If we are in the shop GUI */
00576     if (x > cur_widget[SHOP_ID]->x1 && x < cur_widget[SHOP_ID]->x1 + Bitmaps[BITMAP_SHOP]->bitmap->w && y > cur_widget[SHOP_ID]->y1 && y < cur_widget[SHOP_ID]->y1 + Bitmaps[BITMAP_SHOP]->bitmap->h)
00577     {
00578         _shop_struct *shop_item_tmp;
00579         object *item_object;
00580         int i;
00581 
00582         /* If we're not opening or the item limit was reached, return */
00583         if (shop_gui->shop_state != SHOP_STATE_NONE || shop_gui->shop_items_count >= SHOP_MAX_ITEMS)
00584         {
00585             draggingInvItem(DRAG_NONE);
00586             itemExamined = 0;
00587             return 1;
00588         }
00589 
00590         /* Loop through shop items */
00591         for (shop_item_tmp = shop_gui->shop_items; shop_item_tmp; shop_item_tmp = shop_item_tmp->next)
00592         {
00593             /* If the item is already in the GUI, return */
00594             if (shop_item_tmp->tag == cpl.win_inv_tag)
00595             {
00596                 draggingInvItem(DRAG_NONE);
00597                 itemExamined = 0;
00598                 return 1;
00599             }
00600         }
00601 
00602         /* Locate the item */
00603         item_object = object_find(cpl.win_inv_tag);
00604 
00605         /* Sanity check, shouldn't happen */
00606         if (!item_object)
00607         {
00608             draggingInvItem(DRAG_NONE);
00609             itemExamined = 0;
00610             return 1;
00611         }
00612         else if (item_object->itype == TYPE_MONEY)
00613         {
00614             draw_info_format(COLOR_WHITE, "The %s is not allowed to be sold in a player shop.", item_object->s_name);
00615             draggingInvItem(DRAG_NONE);
00616             itemExamined = 0;
00617             return 1;
00618         }
00619         else if (item_object->flags & F_LOCKED)
00620         {
00621             draw_info_format(COLOR_WHITE, "You must unlock the %s before attempting to sell it.", item_object->s_name);
00622             draggingInvItem(DRAG_NONE);
00623             itemExamined = 0;
00624             return 1;
00625         }
00626 
00627         /* Don't allow things from the quickslots. */
00628         for (i = 0; i < MAX_QUICK_SLOTS * MAX_QUICKSLOT_GROUPS; i++)
00629         {
00630             if (quick_slots[i].tag == cpl.win_inv_tag)
00631             {
00632                 draw_info_format(COLOR_WHITE, "You must first remove %s from your quickslots.", item_object->s_name);
00633                 draggingInvItem(DRAG_NONE);
00634                 itemExamined = 0;
00635                 return 1;
00636             }
00637         }
00638 
00639         /* Allocate a new item */
00640         shop_item_tmp = (_shop_struct *) malloc(sizeof(_shop_struct));
00641 
00642         /* Initialize values for the object */
00643         shop_item_tmp->nrof = item_object->nrof;
00644         shop_item_tmp->price = 0;
00645         shop_item_tmp->price_buf[0] = '\0';
00646         shop_item_tmp->tag = cpl.win_inv_tag;
00647         shop_item_tmp->next = NULL;
00648 
00649         /* One more shop item */
00650         shop_gui->shop_items_count++;
00651 
00652         /* Set the selected tag to the object's tag */
00653         shop_gui->selected_tag = shop_item_tmp->tag;
00654 
00655         /* Easier if there are no shop items yet */
00656         if (!shop_gui->shop_items)
00657         {
00658             shop_gui->shop_items = shop_item_tmp;
00659         }
00660         /* Otherwise we want to append the item to the end of the list */
00661         else
00662         {
00663             _shop_struct *shop_item_next = shop_gui->shop_items;
00664             int i;
00665 
00666             /* Loop until we find the end of the list */
00667             for (i = 1; i < shop_gui->shop_items_count - 1 && shop_item_next; i++, shop_item_next = shop_item_next->next)
00668             {
00669             }
00670 
00671             /* Append it to the end of the list */
00672             shop_item_next->next = shop_item_tmp;
00673         }
00674 
00675         draggingInvItem(DRAG_NONE);
00676         itemExamined = 0;
00677         shop_gui->current_cursor_pos = 0;
00678 
00679         return 1;
00680     }
00681 
00682     return 0;
00683 }
00684 
00688 void shop_object_remove(sint32 tag)
00689 {
00690     _shop_struct *currP, *prevP = NULL;
00691 
00692     /* Visit each node, maintaining a pointer to the previous node we
00693      * just visited. */
00694     for (currP = shop_gui->shop_items; currP != NULL; prevP = currP, currP = currP->next)
00695     {
00696         /* Found it. */
00697         if (currP->tag == tag)
00698         {
00699             if (prevP == NULL)
00700             {
00701                 /* Fix beginning pointer. */
00702                 shop_gui->shop_items = currP->next;
00703             }
00704             else
00705             {
00706                 /* Fix previous node's next to skip over the removed
00707                  * node. */
00708                 prevP->next = currP->next;
00709 
00710                 /* If we had a selected tag, and the current pointer's
00711                  * tag matches, change the selected tag to previous
00712                  * pointer's tag. */
00713                 if (shop_gui->selected_tag && currP->tag == shop_gui->selected_tag)
00714                 {
00715                     shop_gui->selected_tag = currP->tag;
00716                 }
00717             }
00718 
00719             /* Deallocate the node. */
00720             free(currP);
00721 
00722             /* Decrease the count of shop items */
00723             shop_gui->shop_items_count--;
00724 
00725             /* Done searching. */
00726             break;
00727         }
00728     }
00729 }
00730 
00736 int check_shop_keys(SDL_KeyboardEvent *key)
00737 {
00738     char c;
00739     char buf[MAX_BUF];
00740     _shop_struct *shop_item_tmp;
00741     int i, rtn = 0;
00742 
00743     /* If no shop gui or no selected tag, we won't do anything */
00744     if (!shop_gui || !shop_gui->selected_tag || shop_gui->shop_state == SHOP_STATE_OPEN)
00745     {
00746         return 0;
00747     }
00748 
00749     /* Loop through the items */
00750     for (shop_item_tmp = shop_gui->shop_items; shop_item_tmp; shop_item_tmp = shop_item_tmp->next)
00751     {
00752         /* Found the one we're looking for? */
00753         if (shop_item_tmp->tag == shop_gui->selected_tag)
00754         {
00755             break;
00756         }
00757     }
00758 
00759     /* Sanity check */
00760     if (!shop_item_tmp)
00761     {
00762         return 0;
00763     }
00764 
00765     /* Determine which value to store in the buffer */
00766     if (shop_gui->input_type == SHOP_INPUT_TYPE_NROF)
00767     {
00768         snprintf(buf, sizeof(buf), "%d", shop_item_tmp->nrof);
00769     }
00770     else
00771     {
00772         snprintf(buf, sizeof(buf), "%s", shop_item_tmp->price_buf);
00773     }
00774 
00775     /* Calculate the input count */
00776     shop_gui->input_count = (int) strlen(buf);
00777 
00778     if (key->type == SDL_KEYDOWN)
00779     {
00780         int changed = 0;
00781 
00782         switch (key->keysym.sym)
00783         {
00784             /* Handle backspace key */
00785             case SDLK_BACKSPACE:
00786                 if (shop_gui->input_count && shop_gui->current_cursor_pos)
00787                 {
00788                     int ii;
00789 
00790                     /* Actual position of the cursor */
00791                     ii = shop_gui->current_cursor_pos;
00792 
00793                     /* Where we will end up, by default one character back */
00794                     i = ii - 1;
00795 
00796                     if (key->keysym.mod & KMOD_CTRL)
00797                     {
00798                         /* Jumps eventual whitespaces */
00799                         while (buf[i] == ' ' && i >= 0)
00800                         {
00801                             i--;
00802                         }
00803 
00804                         /* Jump a word */
00805                         while (buf[i] != ' ' && i >= 0)
00806                         {
00807                             i--;
00808                         }
00809 
00810                         /* We end up at the beginning of the current word */
00811                         i++;
00812                     }
00813 
00814                     /* This loop copies even the terminating \0 of the buffer */
00815                     while (ii <= shop_gui->input_count)
00816                     {
00817                         buf[i++] = buf[ii++];
00818                     }
00819 
00820                     shop_gui->current_cursor_pos -= (ii - i);
00821                     shop_gui->input_count -= (ii - i);
00822 
00823                     /* There was a change in the buffer */
00824                     changed = 1;
00825                 }
00826 
00827                 rtn = 1;
00828 
00829                 break;
00830 
00831             /* Handle tab key, to switch between inputs */
00832             case SDLK_TAB:
00833                 shop_gui->input_type++;
00834 
00835                 /* Sanity checks */
00836                 if (shop_gui->input_type > SHOP_INPUT_TYPES || (shop_gui->shop_state == SHOP_STATE_BUYING && shop_gui->input_type == SHOP_INPUT_TYPE_PRICE))
00837                 {
00838                     shop_gui->input_type = SHOP_INPUT_TYPE_NROF;
00839                 }
00840 
00841                 /* Again determine which value to store in the buffer, since the input type changed */
00842                 if (shop_gui->input_type == SHOP_INPUT_TYPE_NROF)
00843                 {
00844                     snprintf(buf, sizeof(buf), "%d", shop_item_tmp->nrof);
00845                 }
00846                 else
00847                 {
00848                     snprintf(buf, sizeof(buf), "%s", shop_item_tmp->price_buf);
00849                 }
00850 
00851                 /* Recalculate input count and cursor position */
00852                 shop_gui->input_count = shop_gui->current_cursor_pos = (int) strlen(buf);
00853 
00854                 return 1;
00855 
00856                 break;
00857 
00858             /* Move the cursor position to the left */
00859             case SDLK_LEFT:
00860                 shop_gui->current_cursor_pos--;
00861 
00862                 break;
00863 
00864             /* Move the cursor position to the right */
00865             case SDLK_RIGHT:
00866                 shop_gui->current_cursor_pos++;
00867 
00868                 break;
00869 
00870             /* Handle anything else */
00871             default:
00872                 if ((key->keysym.unicode & 0xFF80) == 0)
00873                 {
00874                     c = key->keysym.unicode & 0x7F;
00875                 }
00876 
00877                 c = key->keysym.unicode & 0xff;
00878 
00879                 /* If the character is a number, or the input type is price then accept " ", "c", "s", "g" and "m" as well */
00880                 if ((c >= 48 && c <= 57) || (shop_gui->input_type == SHOP_INPUT_TYPE_PRICE && (c == ' ' || c == 'c' || c == 's' || c == 'g' || c == 'm')))
00881                 {
00882                     i = shop_gui->input_count;
00883 
00884                     while (i >= shop_gui->current_cursor_pos)
00885                     {
00886                         buf[i + 1] = buf[i];
00887                         i--;
00888                     }
00889 
00890                     buf[shop_gui->current_cursor_pos] = c;
00891                     shop_gui->current_cursor_pos++;
00892                     shop_gui->input_count++;
00893                     buf[shop_gui->input_count] = 0;
00894 
00895                     shop_gui->current_cursor_pos++;
00896 
00897                     rtn = 1;
00898 
00899                     changed = 1;
00900                 }
00901 
00902                 break;
00903         }
00904 
00905         /* If there was a change in the buffer */
00906         if (changed)
00907         {
00908             int buf_int = atoi(buf);
00909 
00910             /* Only allow numbers in certain range, price input is an exception */
00911             if (shop_gui->input_type == SHOP_INPUT_TYPE_PRICE || (buf_int >= 0 && buf_int <= MAX_PRICE_VALUE))
00912             {
00913                 if (shop_gui->input_type == SHOP_INPUT_TYPE_NROF)
00914                 {
00915                     shop_item_tmp->nrof = buf_int;
00916 
00917                     /* Store the new integer in the buffer */
00918                     snprintf(buf, sizeof(buf), "%d", buf_int);
00919 
00920                     /* Recalculate input count and cursor position */
00921                     shop_gui->input_count = shop_gui->current_cursor_pos = (int) strlen(buf);
00922                 }
00923                 else
00924                 {
00925                     /* Store the price buffer */
00926                     snprintf(shop_item_tmp->price_buf, sizeof(shop_item_tmp->price_buf), "%s", buf);
00927 
00928                     /* Adjust the value of the item */
00929                     shop_item_tmp->price = shop_price2int(buf);
00930                 }
00931             }
00932         }
00933     }
00934 
00935     /* Sanity checks so the cursor position doesn't go over boundaries */
00936     if (shop_gui->current_cursor_pos < 0)
00937     {
00938         shop_gui->current_cursor_pos = 0;
00939     }
00940     else if (shop_gui->current_cursor_pos > shop_gui->input_count)
00941     {
00942         shop_gui->current_cursor_pos = shop_gui->input_count;
00943     }
00944 
00945     return rtn;
00946 }
00947 
00957 char *shop_show_input(char *text, struct _Font *font, int wlen, int append_underscore)
00958 {
00959     int i, j, len;
00960     char buf[MAX_INPUT_STR];
00961     static char buf_text[MAX_INPUT_STR];
00962 
00963     strcpy(buf, text);
00964 
00965     len = (int) strlen(buf);
00966 
00967     /* Are we going to append an underscore to the text? */
00968     if (append_underscore)
00969     {
00970         while (len >= shop_gui->current_cursor_pos)
00971         {
00972             buf[len + 1] = buf[len];
00973             len--;
00974         }
00975 
00976         buf[shop_gui->current_cursor_pos] = '_';
00977     }
00978 
00979     for (len = 25, i = shop_gui->current_cursor_pos; i >= 0; i--)
00980     {
00981         if (!buf[i])
00982             continue;
00983 
00984         if (len + font->c[(int) (buf[i])].w + font->char_offset >= wlen)
00985         {
00986             i--;
00987 
00988             break;
00989         }
00990 
00991         len += font->c[(int) (buf[i])].w + font->char_offset;
00992     }
00993 
00994     len -= 25;
00995 
00996     for (j = shop_gui->current_cursor_pos; j <= (int) strlen(buf); j++)
00997     {
00998         if (len + font->c[(int) (buf[j])].w + font->char_offset >= wlen)
00999         {
01000             break;
01001         }
01002 
01003         len += font->c[(int) (buf[j])].w + font->char_offset;
01004     }
01005 
01006     buf[j] = 0;
01007 
01008     strcpy(buf_text, &buf[++i]);
01009 
01010     return buf_text;
01011 }
01012 
01020 int shop_price2int(char *text)
01021 {
01022     int pos = 0, total_value = 0;
01023     char *word, value_buf[MAX_BUF];
01024 
01025     while ((word = get_word_from_string(text, &pos)))
01026     {
01027         int i = 0, flag = *word;
01028 
01029         while (*(word + i) != '\0')
01030         {
01031             if (*(word + i) < '0' || *(word + i) > '9')
01032             {
01033                 flag = 0;
01034             }
01035 
01036             i++;
01037         }
01038 
01039         /* If still set, we have a valid number in the word string */
01040         if (flag)
01041         {
01042             int value = atoi(word);
01043 
01044             /* A valid number - now let's look if we have a valid money keyword */
01045             if (value > 0 && value < 100000)
01046             {
01047                 if ((word = get_word_from_string(text, &pos)) && *word != '\0')
01048                 {
01049                     int len = (int) strlen(word);
01050 
01051                     for (i = 0; i < COINS_ARRAY_SIZE; i++)
01052                     {
01053                         if (!strncasecmp(coins[i].name, word, len))
01054                         {
01055                             total_value += value * coins[i].value;
01056 
01057                             break;
01058                         }
01059                     }
01060                 }
01061             }
01062         }
01063     }
01064 
01065     snprintf(value_buf, sizeof(value_buf), "%d", total_value);
01066 
01067     if (total_value > MAX_PRICE_VALUE || atoi(value_buf) < 1)
01068     {
01069         return 0;
01070     }
01071 
01072     return total_value;
01073 }
01074 
01079 char *shop_int2price(int value)
01080 {
01081     static char value_buf[MAX_BUF];
01082     char buf[MAX_BUF];
01083     int i;
01084 
01085     value_buf[0] = '\0';
01086 
01087     /* Sanity check */
01088     if (value == 0)
01089     {
01090         return value_buf;
01091     }
01092 
01093     /* Loop through the money types */
01094     for (i = 0; i < COINS_ARRAY_SIZE; i++)
01095     {
01096         int num = (value / coins[i].value);
01097 
01098         /* If we got a value */
01099         if (num)
01100         {
01101             /* Store it in a temporary buffer */
01102             snprintf(buf, sizeof(buf), " %d %s", num, coins[i].name);
01103 
01104             /* And append it to the value buffer */
01105             strcat(value_buf, buf);
01106 
01107             /* Decrease the value */
01108             value -= num * coins[i].value;
01109         }
01110     }
01111 
01112     return value_buf;
01113 }

Generated on Mon Jan 10 2011 00:00:05 for Atrinik Client by  doxygen 1.7.1