Atrinik Client  4.0
quickslots.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
32 #include <global.h>
33 #include <toolkit/packet.h>
34 #include <toolkit/string.h>
35 
39 typedef struct widget_quickslots {
42 
46 void quickslots_init(void)
47 {
48  for (widgetdata *widget = cur_widget[QUICKSLOT_ID]; widget != NULL;
49  widget = widget->type_next) {
50  widget_quickslots_t *tmp = widget->subwidget;
51  list_clear(tmp->list);
52 
53  for (uint32_t i = 0; i < MAX_QUICK_SLOTS * MAX_QUICKSLOT_GROUPS; i++) {
54  list_add(tmp->list, i / MAX_QUICK_SLOTS, i % tmp->list->cols, NULL);
55  }
56  }
57 }
58 
67 static void quickslots_set(widgetdata *widget, uint32_t row, uint32_t col,
68  tag_t tag)
69 {
70  widget_quickslots_t *tmp = widget->subwidget;
71 
72  packet_struct *packet = packet_new(SERVER_CMD_QUICKSLOT, 32, 0);
73  packet_append_uint8(packet, (row * MAX_QUICK_SLOTS) + col + 1);
74  packet_append_uint32(packet, tag);
75  socket_send_packet(packet);
76 
77  if (tmp->list->text[row][col] != NULL) {
78  efree(tmp->list->text[row][col]);
79  tmp->list->text[row][col] = NULL;
80  }
81 
82  if (tag != 0) {
83  char buf[MAX_BUF];
84  snprintf(VS(buf), "%" PRIu32, tag);
85  tmp->list->text[row][col] = estrdup(buf);
86  }
87 }
88 
98 void quickslots_scroll(widgetdata *widget, int up, int scroll)
99 {
100  widget_quickslots_t *tmp = widget->subwidget;
101  list_scroll(tmp->list, up, scroll);
102 
103  widget->redraw = 1;
104 }
105 
112 {
113  widget_quickslots_t *tmp = widget->subwidget;
114 
115  if (tmp->list->row_selected == tmp->list->rows) {
116  list_scroll(tmp->list, 1, tmp->list->rows);
117  } else {
118  list_scroll(tmp->list, 0, 1);
119  }
120 
121  widget->redraw = 1;
122 }
123 
129 static void quickslots_remove(widgetdata *widget, tag_t tag)
130 {
131  widget_quickslots_t *tmp = widget->subwidget;
132 
133  for (uint32_t row = 0; row < tmp->list->rows; row++) {
134  for (uint32_t col = 0; col < tmp->list->cols; col++) {
135  if (tmp->list->text[row][col] == NULL) {
136  continue;
137  }
138 
139  if (tag == strtoul(tmp->list->text[row][col], NULL, 10)) {
140  efree(tmp->list->text[row][col]);
141  tmp->list->text[row][col] = NULL;
142  break;;
143  }
144  }
145  }
146 }
147 
159 static int quickslots_trigger(widgetdata *widget, uint32_t row, uint32_t col)
160 {
161  HARD_ASSERT(widget != NULL);
162 
163  widget_quickslots_t *tmp = widget->subwidget;
164  unsigned long int tag = tmp->list->text[row][col] != NULL ?
165  strtoul(tmp->list->text[row][col], NULL, 10) : 0;
166  if (tag == 0) {
167  return 0;
168  }
169 
170  object *ob = object_find(tag);
171  SOFT_ASSERT_RC(ob != NULL, 0, "Could not find object by tag: %lu", tag);
172 
173  if (ob->itype == TYPE_SPELL) {
174  size_t spell_path, spell_id;
175  if (spell_find(ob->s_name, &spell_path, &spell_id)) {
176  spell_entry_struct *spell = spell_get(spell_path, spell_id);
177  if (spell != NULL && spell->flags & SPELL_DESC_SELF) {
178  char buf[MAX_BUF];
179  snprintf(VS(buf), "/cast %s", ob->s_name);
180  send_command_check(buf);
181  return 1;
182  }
183  }
184  }
185 
186  client_send_apply(ob);
187  return 1;
188 }
189 
201 static int quickslots_change(widgetdata *widget, uint32_t row, uint32_t col)
202 {
203  HARD_ASSERT(widget != NULL);
204 
206  if (ob == NULL || ob->env != cpl.ob) {
207  return 0;
208  }
209 
210  widget_quickslots_t *tmp = widget->subwidget;
211 
212  unsigned long int tag = tmp->list->text[row][col] != NULL ?
213  strtoul(tmp->list->text[row][col], NULL, 10) : 0;
214  if ((tag_t) ob->tag == tag) {
215  quickslots_set(widget, row, col, 0);
216  } else {
217  quickslots_remove(widget, ob->tag);
218  quickslots_set(widget, row, col, ob->tag);
219  }
220 
221  widget->redraw = 1;
222  return 1;
223 }
224 
230 void quickslots_handle_key(int slot)
231 {
232  for (widgetdata *widget = cur_widget[QUICKSLOT_ID]; widget != NULL;
233  widget = widget->type_next) {
234  widget_quickslots_t *tmp = widget->subwidget;
235 
236  if (keybind_command_matches_state("?QUICKSLOT_SET_KEY")) {
237  if (quickslots_change(widget, tmp->list->row_offset, slot)) {
238  break;
239  }
240  } else if (quickslots_trigger(widget, tmp->list->row_offset, slot)) {
241  break;
242  }
243  }
244 }
245 
247 static void list_post_column(list_struct *list, uint32_t row, uint32_t col)
248 {
249  if (list->text[row][col] == NULL) {
250  return;
251  }
252 
253  object *tmp = object_find_object(cpl.ob,
254  strtoul(list->text[row][col], NULL, 10));
255  if (tmp == NULL) {
256  return;
257  }
258 
259  int x = list->x + list->frame_offset + (INVENTORY_ICON_SIZE + 1) * col;
260  int y = LIST_ROWS_START(list) + (LIST_ROW_OFFSET(row, list) *
261  LIST_ROW_HEIGHT(list));
262  object_show_inventory(list->surface, tmp, x, y);
263 
264  char buf[MAX_BUF];
265  snprintf(VS(buf), "?QUICKSLOT_%" PRIu32, col + 1);
266  keybind_struct *keybind = keybind_find_by_command(buf);
267 
268  if (keybind != NULL) {
269  SDL_Rect box;
270  box.w = INVENTORY_ICON_SIZE;
271  box.h = INVENTORY_ICON_SIZE;
272 
273  keybind_get_key_shortcut(keybind->key, keybind->mod, VS(buf));
274  text_show_format(list->surface, FONT("sans", 8), x, y,
275  COLOR_HGOLD, TEXT_MARKUP, &box,
276  "[right][alpha=220][o=#000000]%s[/o][/alpha][/right]", buf);
277  }
278 }
279 
281 static void list_row_color(list_struct *list, int row, SDL_Rect box)
282 {
283  Uint32 color = SDL_MapRGB(list->surface->format, 25, 25, 25);
284  SDL_FillRect(list->surface, &box, color);
285  box.w = 1;
286 
287  color = SDL_MapRGB(list->surface->format, 130, 130, 130);
288  for (int i = 0; i < MAX_QUICK_SLOTS; i++) {
289  box.x = (INVENTORY_ICON_SIZE + 1) * i + 1;
290  SDL_FillRect(list->surface, &box, color);
291  }
292 }
293 
295 static void widget_draw(widgetdata *widget)
296 {
297  if (!widget->redraw) {
298  return;
299  }
300 
301  widget_quickslots_t *tmp = widget->subwidget;
302  tmp->list->surface = widget->surface;
303  list_set_parent(tmp->list, widget->x, widget->y);
304  list_show(tmp->list, 2, 2);
305 }
306 
308 static int widget_event(widgetdata *widget, SDL_Event *event)
309 {
310  if (!EVENT_IS_MOUSE(event)) {
311  return 0;
312  }
313 
314  widget_quickslots_t *tmp = widget->subwidget;
315 
316  uint32_t row, col;
317  if (list_mouse_get_pos(tmp->list, event->motion.x, event->motion.y,
318  &row, &col)) {
319  if (event->button.button == SDL_BUTTON_LEFT) {
320  if (event->type == SDL_MOUSEBUTTONUP) {
321  if (event_dragging_check()) {
323  draw_info(COLOR_RED, "Only items from main inventory "
324  "are allowed in quickslots.");
325  } else {
327  quickslots_set(widget, row, col, cpl.dragging_tag);
328  widget->redraw = 1;
329  }
330 
331  event_dragging_stop();
332  } else {
333  quickslots_trigger(widget, row, col);
334  }
335 
336  return 1;
337  } else if (event->type == SDL_MOUSEBUTTONDOWN &&
338  tmp->list->text[row][col] != NULL) {
339  event_dragging_start(strtoul(tmp->list->text[row][col], NULL,
340  10), event->motion.x, event->motion.y);
341  return 1;
342  }
343  } else if (event->type == SDL_MOUSEMOTION) {
344  if (tmp->list->text[row][col] != NULL) {
345  object *ob = object_find_object(cpl.ob,
346  strtoul(tmp->list->text[row][col], NULL, 10));
347 
348  if (ob != NULL) {
349  tooltip_create(event->motion.x, event->motion.y,
350  FONT_ARIAL11, ob->s_name);
351  }
352  }
353  }
354  }
355 
356  if (list_handle_mouse(tmp->list, event)) {
357  widget->redraw = 1;
358  return 1;
359  }
360 
361  return 0;
362 }
363 
365 static void widget_deinit(widgetdata *widget)
366 {
367  widget_quickslots_t *tmp = widget->subwidget;
368  list_remove(tmp->list);
369 }
370 
377 {
378  widget_quickslots_t *tmp;
379  uint32_t i;
380 
381  tmp = ecalloc(1, sizeof(*tmp));
382  tmp->list = list_create(1, MAX_QUICK_SLOTS, 0);
385  tmp->list->row_selected_func = NULL;
386  tmp->list->row_highlight_func = NULL;
388  tmp->list->header_height = tmp->list->frame_offset = 0;
389  list_set_font(tmp->list, NULL);
391 
392  for (i = 0; i < tmp->list->cols; i++) {
393  list_set_column(tmp->list, i, INVENTORY_ICON_SIZE + 1, 0, NULL, -1);
394  }
395 
396  widget->draw_func = widget_draw;
397  widget->event_func = widget_event;;
398  widget->deinit_func = widget_deinit;
399  widget->subwidget = tmp;
400 }
401 
403 void socket_command_quickslots(uint8_t *data, size_t len, size_t pos)
404 {
405  quickslots_init();
406 
407  while (pos < len) {
408  uint8_t slot = packet_to_uint8(data, len, &pos);
409  tag_t tag = packet_to_uint32(data, len, &pos);
410  char buf[MAX_BUF];
411  snprintf(VS(buf), "%" PRIu32, tag);
412 
413  for (widgetdata *widget = cur_widget[QUICKSLOT_ID]; widget != NULL;
414  widget = widget->type_next) {
415  widget_quickslots_t *tmp = widget->subwidget;
416  list_add(tmp->list, slot / MAX_QUICK_SLOTS, slot % tmp->list->cols,
417  buf);
418  }
419  }
420 }
static void list_row_color(list_struct *list, int row, SDL_Rect box)
Definition: quickslots.c:281
#define FONT(font_name, font_size)
Definition: text.h:63
void(* row_selected_func)(struct list_struct *list, SDL_Rect box)
Definition: list.h:184
list_struct * list_create(uint32_t max_rows, uint32_t cols, int spacing)
Definition: list.c:113
void quickslots_init(void)
Definition: quickslots.c:46
static void list_post_column(list_struct *list, uint32_t row, uint32_t col)
Definition: quickslots.c:247
object * object_find_object(object *op, tag_t tag)
Definition: item.c:116
void object_show_inventory(SDL_Surface *surface, object *tmp, int x, int y)
Definition: inventory.c:870
char s_name[NAME_LEN]
Definition: item.h:60
void draw_info(const char *color, const char *str)
Definition: textwin.c:448
list_struct * list
The quickslots list.
Definition: quickslots.c:40
void * subwidget
Definition: widget.h:107
void list_remove(list_struct *list)
Definition: list.c:522
static int quickslots_trigger(widgetdata *widget, uint32_t row, uint32_t col)
Definition: quickslots.c:159
int x
Definition: list.h:36
SDL_Surface * surface
Definition: widget.h:110
void list_clear(list_struct *list)
Definition: list.c:486
void list_set_column(list_struct *list, uint32_t col, int width, int spacing, const char *name, int centered)
Definition: list.c:242
object * widget_inventory_get_selected(widgetdata *widget)
Definition: inventory.c:750
object * object_find_object_inv(object *op, tag_t tag)
Definition: item.c:96
int list_handle_mouse(list_struct *list, SDL_Event *event)
Definition: list.c:698
void list_add(list_struct *list, uint32_t row, uint32_t col, const char *str)
Definition: list.c:163
int16_t frame_offset
Definition: list.h:94
#define LIST_ROWS_START(list)
Definition: list.h:258
#define COLOR_HGOLD
Definition: text.h:319
void tooltip_create(int mx, int my, font_struct *font, const char *text)
Definition: tooltip.c:60
#define SPELL_DESC_SELF
Definition: client.h:114
struct widgetdata * type_next
Definition: widget.h:101
uint32_t row_offset
Definition: list.h:117
void quickslots_handle_key(int slot)
Definition: quickslots.c:230
static int widget_event(widgetdata *widget, SDL_Event *event)
Definition: quickslots.c:308
char *** text
Definition: list.h:85
#define TEXT_MARKUP
Definition: text.h:224
#define LIST_ROW_HEIGHT(list)
Definition: list.h:256
int keybind_command_matches_state(const char *cmd)
Definition: keybind.c:414
void list_scroll(list_struct *list, int up, int scroll)
Definition: list.c:564
uint32_t tag
Definition: item.h:63
#define COLOR_RED
Definition: text.h:295
#define LIST_ROW_OFFSET(row, list)
Definition: list.h:267
static int quickslots_change(widgetdata *widget, uint32_t row, uint32_t col)
Definition: quickslots.c:201
tag_t dragging_tag
Definition: player.h:187
static void widget_draw(widgetdata *widget)
Definition: quickslots.c:295
Client_Player cpl
Definition: client.c:50
char * keybind_get_key_shortcut(SDLKey key, SDLMod mod, char *buf, size_t len)
Definition: keybind.c:336
struct obj * env
Definition: item.h:54
void quickslots_cycle(widgetdata *widget)
Definition: quickslots.c:111
void(* row_color_func)(struct list_struct *list, int row, SDL_Rect box)
Definition: list.h:166
widgetdata * cur_widget[TOTAL_SUBWIDGETS]
Definition: widget.c:75
uint8_t redraw
Definition: widget.h:72
struct widget_quickslots widget_quickslots_t
Definition: main.h:158
SDLKey key
Definition: keybind.h:44
int x
Definition: widget.h:48
void(* row_highlight_func)(struct list_struct *list, SDL_Rect box)
Definition: list.h:175
static void widget_deinit(widgetdata *widget)
Definition: quickslots.c:365
#define INVENTORY_ICON_SIZE
Definition: inventory.h:60
void socket_command_quickslots(uint8_t *data, size_t len, size_t pos)
Definition: quickslots.c:403
void(* post_column_func)(struct list_struct *list, uint32_t row, uint32_t col)
Definition: list.h:239
spell_entry_struct * spell_get(size_t spell_path, size_t spell_id)
Definition: spells.c:294
SDL_Surface * surface
Definition: list.h:138
void quickslots_scroll(widgetdata *widget, int up, int scroll)
Definition: quickslots.c:98
object * object_find(tag_t tag)
Definition: item.c:139
uint32_t flags
Definition: main.h:172
static void quickslots_set(widgetdata *widget, uint32_t row, uint32_t col, tag_t tag)
Definition: quickslots.c:67
keybind_struct * keybind_find_by_command(const char *cmd)
Definition: keybind.c:371
uint16_t header_height
Definition: list.h:97
void list_set_font(list_struct *list, font_struct *font)
Definition: list.c:284
int spell_find(const char *name, size_t *spell_path, size_t *spell_id)
Definition: spells.c:198
void list_show(list_struct *list, int x, int y)
Definition: list.c:337
int send_command_check(const char *cmd)
Definition: menu.c:376
uint8_t itype
Definition: item.h:90
void widget_quickslots_init(widgetdata *widget)
Definition: quickslots.c:376
widgetdata * inventory_focus
Definition: player.h:200
static void quickslots_remove(widgetdata *widget, tag_t tag)
Definition: quickslots.c:129
int16_t row_height_adjust
Definition: list.h:88
void list_set_parent(list_struct *list, int px, int py)
Definition: list.c:96
uint32_t cols
Definition: list.h:63
void client_send_apply(object *op)
Definition: player.c:119
void text_show_format(SDL_Surface *surface, font_struct *font, int x, int y, const char *color_notation, uint64_t flags, SDL_Rect *box, const char *format,...)
Definition: text.c:2289
void list_scrollbar_enable(list_struct *list)
Definition: list.c:302
uint32_t rows
Definition: list.h:60
uint32_t row_selected
Definition: list.h:109
object * ob
Definition: player.h:111
SDLMod mod
Definition: keybind.h:47
int y
Definition: widget.h:51