Atrinik Client 2.5
gui/quickslots.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 
00033 static _quickslot quick_slots[MAX_QUICK_SLOTS * MAX_QUICKSLOT_GROUPS];
00034 
00036 int quickslot_group = 1;
00037 
00041 int quickslots_pos[MAX_QUICK_SLOTS][2] =
00042 {
00043     {17,    1},
00044     {50,    1},
00045     {83,    1},
00046     {116,   1},
00047     {149,   1},
00048     {182,   1},
00049     {215,   1},
00050     {248,   1}
00051 };
00052 
00058 static void quickslot_set_item(uint8 slot, sint32 tag)
00059 {
00060     SockList sl;
00061     unsigned char buf[MAX_BUF];
00062 
00063     sl.buf = buf;
00064     sl.len = 0;
00065     SockList_AddString(&sl, "qs ");
00066     SockList_AddChar(&sl, CMD_QUICKSLOT_SET);
00067     SockList_AddChar(&sl, slot);
00068     SockList_AddInt(&sl, tag);
00069     send_socklist(sl);
00070 }
00071 
00077 static void quickslot_set_spell(uint8 slot, char *spell_name)
00078 {
00079     SockList sl;
00080     unsigned char buf[MAX_BUF];
00081 
00082     sl.buf = buf;
00083     sl.len = 0;
00084     SockList_AddString(&sl, "qs ");
00085     SockList_AddChar(&sl, CMD_QUICKSLOT_SETSPELL);
00086     SockList_AddChar(&sl, slot);
00087     SockList_AddString(&sl, spell_name);
00088     send_socklist(sl);
00089 }
00090 
00094 static void quickslot_unset(uint8 slot)
00095 {
00096     SockList sl;
00097     unsigned char buf[MAX_BUF];
00098 
00099     sl.buf = buf;
00100     sl.len = 0;
00101     SockList_AddString(&sl, "qs ");
00102     SockList_AddChar(&sl, CMD_QUICKSLOT_UNSET);
00103     SockList_AddChar(&sl, slot);
00104     send_socklist(sl);
00105 }
00106 
00107 void quickslots_init()
00108 {
00109     size_t slot;
00110 
00111     /* Clear all quickslots. */
00112     for (slot = 0; slot < MAX_QUICK_SLOTS * MAX_QUICKSLOT_GROUPS; slot++)
00113     {
00114         quick_slots[slot].tag = -1;
00115         quick_slots[slot].spell = NULL;
00116     }
00117 }
00118 
00126 static void quickslots_remove(int tag)
00127 {
00128     int i;
00129 
00130     for (i = 0; i < MAX_QUICK_SLOTS * MAX_QUICKSLOT_GROUPS; i++)
00131     {
00132         if (quick_slots[i].tag == tag)
00133         {
00134             quick_slots[i].tag = -1;
00135         }
00136         else if (quick_slots[i].tag != -1 && !object_find_object_inv(cpl.ob, quick_slots[i].tag))
00137         {
00138             quick_slots[i].tag = -1;
00139         }
00140     }
00141 }
00142 
00143 /* Handle quickslot key event. */
00144 void quickslots_handle_key(int slot)
00145 {
00146     int tag, real_slot;
00147 
00148     real_slot = slot;
00149     slot = MAX_QUICK_SLOTS * quickslot_group - MAX_QUICK_SLOTS + slot;
00150 
00151     /* Put item into quickslot */
00152     if (cpl.inventory_win == IWIN_INV)
00153     {
00154         tag = cpl.win_inv_tag;
00155 
00156         if (tag == -1 || !object_find(tag))
00157         {
00158             return;
00159         }
00160 
00161         quick_slots[slot].spell = NULL;
00162 
00163         if (quick_slots[slot].tag == tag)
00164         {
00165             quick_slots[slot].tag = -1;
00166             quickslot_unset(slot + 1);
00167         }
00168         else
00169         {
00170             quickslots_remove(tag);
00171 
00172             quick_slots[slot].tag = tag;
00173             quickslot_set_item(slot + 1, tag);
00174 
00175             draw_info_format(COLOR_DGOLD, "Set F%d of group %d to %s", real_slot + 1, quickslot_group, object_find(tag)->s_name);
00176         }
00177     }
00178     /* Apply item or ready spell */
00179     else
00180     {
00181         if (quick_slots[slot].spell)
00182         {
00183             fire_mode_tab[FIRE_MODE_SPELL].spell = quick_slots[slot].spell;
00184             RangeFireMode = FIRE_MODE_SPELL;
00185         }
00186         else if (quick_slots[slot].tag != -1 && object_find(quick_slots[slot].tag))
00187         {
00188             draw_info_format(COLOR_DGOLD, "F%d of group %d quick apply %s", real_slot + 1, quickslot_group, object_find(quick_slots[slot].tag)->s_name);
00189 
00190             client_send_apply(quick_slots[slot].tag);
00191         }
00192         else
00193         {
00194             draw_info_format(COLOR_DGOLD, "F%d of group %d quick slot is empty", real_slot + 1, quickslot_group);
00195         }
00196     }
00197 }
00198 
00204 int get_quickslot(int x, int y)
00205 {
00206     int i, j;
00207     int qsx, qsy, xoff;
00208 
00209     if (cur_widget[QUICKSLOT_ID]->ht > 34)
00210     {
00211         qsx = 1;
00212         qsy = 0;
00213         xoff = 0;
00214     }
00215     else
00216     {
00217         qsx = 0;
00218         qsy = 1;
00219         xoff = -17;
00220     }
00221 
00222     for (i = 0; i < MAX_QUICK_SLOTS; i++)
00223     {
00224         j = MAX_QUICK_SLOTS * quickslot_group - MAX_QUICK_SLOTS + i;
00225 
00226         if (x >= cur_widget[QUICKSLOT_ID]->x1 + quickslots_pos[i][qsx] + xoff && x <= cur_widget[QUICKSLOT_ID]->x1 + quickslots_pos[i][qsx] + xoff + 32 && y >= cur_widget[QUICKSLOT_ID]->y1 + quickslots_pos[i][qsy] && y <= cur_widget[QUICKSLOT_ID]->y1 + quickslots_pos[i][qsy] + 32)
00227         {
00228             return j;
00229         }
00230     }
00231 
00232     return -1;
00233 }
00234 
00240 void show_quickslots(int x, int y, int vertical_quickslot)
00241 {
00242     int i, j, mx, my;
00243     char buf[16];
00244     int qsx, qsy, xoff;
00245 
00246     /* Figure out which bitmap to use */
00247     if (vertical_quickslot)
00248     {
00249         qsx = 1;
00250         qsy = 0;
00251         xoff = 0;
00252         sprite_blt(Bitmaps[BITMAP_QUICKSLOTSV], x, y, NULL, NULL);
00253     }
00254     else
00255     {
00256         qsx = 0;
00257         qsy = 1;
00258         xoff = -17;
00259         sprite_blt(Bitmaps[BITMAP_QUICKSLOTS], x, y, NULL, NULL);
00260     }
00261 
00262     SDL_GetMouseState(&mx, &my);
00263     quickslots_remove(-1);
00264 
00265     /* Loop through quickslots. Do not loop through all the quickslots,
00266      * like MAX_QUICK_SLOTS * MAX_QUICKSLOT_GROUPS. */
00267     for (i = 0; i < MAX_QUICK_SLOTS; i++)
00268     {
00269         /* Now calculate the real quickslot, according to the selected group */
00270         j = MAX_QUICK_SLOTS * quickslot_group - MAX_QUICK_SLOTS + i;
00271 
00272         /* Spell in quickslot */
00273         if (quick_slots[j].spell)
00274         {
00275             /* Output the sprite */
00276             blit_face(quick_slots[j].spell->icon, x + quickslots_pos[i][qsx] + xoff, y + quickslots_pos[i][qsy]);
00277 
00278             /* If mouse is over the quickslot, show a tooltip */
00279             if (cpl.menustatus == MENU_NO && mx >= x + quickslots_pos[i][qsx] + xoff && mx < x + quickslots_pos[i][qsx] + xoff + 33 && my >= y + quickslots_pos[i][qsy] && my < y + quickslots_pos[i][qsy] + 33)
00280             {
00281                 tooltip_create(mx, my, FONT_ARIAL10, quick_slots[j].spell->name);
00282             }
00283         }
00284         /* Item in quickslot */
00285         else if (quick_slots[j].tag != -1)
00286         {
00287             object *tmp = object_find_object(cpl.ob, quick_slots[j].tag);
00288 
00289             /* If we located the item */
00290             if (tmp)
00291             {
00292                 /* Show it */
00293                 blt_inv_item(tmp, x + quickslots_pos[i][qsx] + xoff, y + quickslots_pos[i][qsy]);
00294 
00295                 /* And show tooltip, if mouse is over it */
00296                 if (mx >= x + quickslots_pos[i][qsx] + xoff && mx < x + quickslots_pos[i][qsx] + xoff + 33 && my >= y + quickslots_pos[i][qsy] && my < y + quickslots_pos[i][qsy] + 33)
00297                 {
00298                     tooltip_create(mx, my, FONT_ARIAL10, tmp->s_name);
00299                 }
00300             }
00301         }
00302 
00303         /* For each quickslot, output the F1-F8 shortcut */
00304         snprintf(buf, sizeof(buf), "F%d", i + 1);
00305         string_blt(ScreenSurface, FONT_ARIAL10, buf, x + quickslots_pos[i][qsx] + xoff + 12, y + quickslots_pos[i][qsy] - 7, COLOR_WHITE, TEXT_OUTLINE, NULL);
00306     }
00307 
00308     snprintf(buf, sizeof(buf), "Group %d", quickslot_group);
00309 
00310     /* Now output the group */
00311     if (vertical_quickslot)
00312     {
00313         string_blt(ScreenSurface, FONT_ARIAL10, buf, x - 1, y + Bitmaps[BITMAP_QUICKSLOTSV]->bitmap->h, COLOR_WHITE, TEXT_OUTLINE, NULL);
00314     }
00315     else
00316     {
00317         string_blt(ScreenSurface, FONT_ARIAL10, buf, x, y + Bitmaps[BITMAP_QUICKSLOTS]->bitmap->h, COLOR_WHITE, TEXT_OUTLINE, NULL);
00318     }
00319 }
00320 
00322 void widget_quickslots(widgetdata *widget)
00323 {
00324     if (widget->ht > 34)
00325     {
00326         show_quickslots(widget->x1, widget->y1, 1);
00327     }
00328     else
00329     {
00330         show_quickslots(widget->x1, widget->y1, 0);
00331     }
00332 }
00333 
00338 void widget_quickslots_mouse_event(widgetdata *widget, SDL_Event *event)
00339 {
00340     if (event->type == SDL_MOUSEBUTTONUP)
00341     {
00342         int i;
00343 
00344         if (draggingInvItem(DRAG_GET_STATUS) <= DRAG_IWIN_BELOW)
00345         {
00346             return;
00347         }
00348 
00349         i = get_quickslot(event->motion.x, event->motion.y);
00350 
00351         /* Valid slot */
00352         if (i != -1)
00353         {
00354             if (draggingInvItem(DRAG_GET_STATUS) == DRAG_QUICKSLOT_SPELL)
00355             {
00356                 quick_slots[i].tag = -1;
00357                 quick_slots[i].spell = cpl.dragging.spell;
00358                 quickslot_set_spell(i + 1, quick_slots[i].spell->name);
00359                 cpl.dragging.spell = NULL;
00360             }
00361             else
00362             {
00363                 if (draggingInvItem(DRAG_GET_STATUS) == DRAG_IWIN_INV)
00364                 {
00365                     cpl.dragging.tag = cpl.win_inv_tag;
00366                 }
00367                 else if (draggingInvItem(DRAG_GET_STATUS) == DRAG_PDOLL)
00368                 {
00369                     cpl.dragging.tag = cpl.win_pdoll_tag;
00370                 }
00371 
00372                 quickslots_remove(cpl.dragging.tag);
00373                 quick_slots[i].tag = cpl.dragging.tag;
00374                 quick_slots[i].spell = NULL;
00375 
00376                 if (!object_find_object_inv(cpl.ob, cpl.dragging.tag))
00377                 {
00378                     draw_info(COLOR_RED, "Only items from main inventory are allowed in quickslots.");
00379                 }
00380                 else
00381                 {
00382                     quickslot_set_item(i + 1, cpl.dragging.tag);
00383                     draw_info_format(COLOR_DGOLD, "Set F%d of group %d to %s", i + 1 - MAX_QUICK_SLOTS * quickslot_group + MAX_QUICK_SLOTS, quickslot_group, object_find(cpl.dragging.tag)->s_name);
00384                 }
00385             }
00386         }
00387 
00388         draggingInvItem(DRAG_NONE);
00389     }
00390     else if (event->type == SDL_MOUSEBUTTONDOWN)
00391     {
00392         int i = get_quickslot(event->motion.x, event->motion.y);
00393 
00394         if (i != -1)
00395         {
00396             if (event->button.button == SDL_BUTTON_LEFT)
00397             {
00398                 if (quick_slots[i].spell)
00399                 {
00400                     cpl.dragging.spell = quick_slots[i].spell;
00401                     draggingInvItem(DRAG_QUICKSLOT_SPELL);
00402                     quick_slots[i].spell = NULL;
00403                 }
00404                 else if (quick_slots[i].tag != -1)
00405                 {
00406                     cpl.dragging.tag = quick_slots[i].tag;
00407                     draggingInvItem(DRAG_QUICKSLOT);
00408                     quick_slots[i].tag = -1;
00409                 }
00410 
00411                 quickslot_unset(i + 1);
00412             }
00413             else
00414             {
00415                 draw_info_format(COLOR_DGOLD, "apply %s", object_find(quick_slots[i].tag)->s_name);
00416                 client_send_apply(quick_slots[i].tag);
00417             }
00418         }
00419         else if (event->motion.x >= widget->x1 + 266 && event->motion.x <= widget->x1 + 282 && event->motion.y >= widget->y1 && event->motion.y <= widget->y1 + 34 && (widget->ht <= 34))
00420         {
00421             widget->wd = 34;
00422             widget->ht = 282;
00423             widget->x1 += 266;
00424         }
00425         else if (event->motion.x >= widget->x1 && event->motion.x <= widget->x1 + 34 && event->motion.y >= widget->y1 && event->motion.y <= widget->y1 + 15 && (widget->ht > 34))
00426         {
00427             widget->wd = 282;
00428             widget->ht = 34;
00429             widget->x1 -= 266;
00430         }
00431     }
00432 }
00433 
00438 void QuickSlotCmd(unsigned char *data, int len)
00439 {
00440     int pos = 0;
00441     uint8 type, slot;
00442 
00443     /* Clear all quickslots. */
00444     for (slot = 0; slot < MAX_QUICK_SLOTS * MAX_QUICKSLOT_GROUPS; slot++)
00445     {
00446         quick_slots[slot].tag = -1;
00447         quick_slots[slot].spell = NULL;
00448     }
00449 
00450     while (pos < len)
00451     {
00452         type = data[pos++];
00453         slot = data[pos++];
00454 
00455         if (type == QUICKSLOT_TYPE_ITEM)
00456         {
00457             quick_slots[slot].tag = GetInt_String(data + pos);
00458             pos += 4;
00459         }
00460         else if (type == QUICKSLOT_TYPE_SPELL)
00461         {
00462             char spell_name[MAX_BUF], c;
00463             size_t i = 0;
00464             size_t spell_path, spell_id;
00465 
00466             spell_name[0] = '\0';
00467 
00468             while ((c = (char) (data[pos++])))
00469             {
00470                 spell_name[i++] = c;
00471             }
00472 
00473             spell_name[i] = '\0';
00474 
00475             if (spell_find(spell_name, &spell_path, &spell_id))
00476             {
00477                 quick_slots[slot].spell = spell_get(spell_path, spell_id);
00478             }
00479         }
00480     }
00481 }