Atrinik Client  4.0
skills.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/string.h>
34 
35 enum {
36  BUTTON_CLOSE,
38 
39  BUTTON_NUM
40 } ;
41 
45 static button_struct buttons[BUTTON_NUM];
53 static size_t skill_list_num;
57 static list_struct *list_skills = NULL;
61 static size_t selected_skill;
62 
66 void skills_init(void)
67 {
68  skill_list = NULL;
69  skill_list_num = 0;
70  selected_skill = 0;
71 }
72 
76 void skills_deinit(void)
77 {
78  for (size_t i = 0; i < skill_list_num; i++) {
79  efree(skill_list[i]);
80  }
81 
82  skill_list_num = 0;
83 
84  if (skill_list != NULL) {
85  efree(skill_list);
86  }
87 }
88 
90 static void list_post_column(list_struct *list, uint32_t row, uint32_t col)
91 {
92  size_t skill_id;
93  SDL_Rect box;
94 
95  skill_id = row * list->cols + col;
96 
97  if (skill_id >= skill_list_num) {
98  return;
99  }
100 
101  if (!FaceList[skill_list[skill_id]->skill->face].sprite) {
102  return;
103  }
104 
105  box.x = list->x + list->frame_offset + INVENTORY_ICON_SIZE * col;
106  box.y = LIST_ROWS_START(list) + (LIST_ROW_OFFSET(row, list) * LIST_ROW_HEIGHT(list));
107  box.w = INVENTORY_ICON_SIZE;
108  box.h = INVENTORY_ICON_SIZE;
109 
110  surface_show(list->surface, box.x, box.y, NULL, FaceList[skill_list[skill_id]->skill->face].sprite->bitmap);
111 
112  if (selected_skill != skill_id) {
113  return;
114  }
115  border_create_color(list->surface, &box, 1, "ff0000");
116 
117  char buf[MAX_BUF];
118  snprintf(VS(buf), "%s", skill_list[skill_id]->skill->s_name);
119  string_title(buf);
120 
121  box.w = 160;
122  text_show(list->surface,
123  FONT_SERIF12,
124  buf,
125  150,
126  18,
127  COLOR_HGOLD,
129  &box);
130 
131  box.h = 100;
132  text_show(list->surface,
133  FONT_ARIAL11,
134  skill_list[skill_id]->msg,
135  150,
136  38,
137  COLOR_WHITE,
139  &box);
140 
141  if (skill_list[skill_id]->level == 0) {
142  return;
143  }
144 
145  widgetdata *widget = widget_find(NULL, -1, NULL, list->surface);
146  SOFT_ASSERT(widget != NULL, "Could not find widget");
147 
148  text_show(list->surface, FONT("arial", 10), "[b]Experience[/b]", 167, widget->h - 47, COLOR_WHITE, TEXT_MARKUP, NULL);
149  player_draw_exp_progress(list->surface, 160, widget->h - 32, skill_list[skill_id]->exp, skill_list[skill_id]->level);
150 
151  box.h = 30;
152  box.w = 35;
153  text_show(list->surface,
154  FONT("arial", 10),
155  "[b]Level[/b]",
156  widget->w - 45,
157  widget->h - 47,
158  COLOR_WHITE,
160  &box);
162  FONT_SERIF18,
163  widget->w - 45,
164  widget->h - 30,
165  COLOR_HGOLD,
167  &box,
168  "%" PRIu8,
169  skill_list[skill_id]->level);
170 }
171 
173 static void list_row_color(list_struct *list, int row, SDL_Rect box)
174 {
175  SDL_FillRect(list->surface, &box, SDL_MapRGB(list->surface->format, 25, 25, 25));
176 }
177 
181 static void skill_list_reload(void)
182 {
183  size_t i;
184  uint32_t offset, rows, selected;
185 
186  if (!list_skills) {
187  return;
188  }
189 
190  offset = list_skills->row_offset;
191  selected = list_skills->row_selected;
192  rows = list_skills->rows;
193  list_clear(list_skills);
194 
195  for (i = 0; i < skill_list_num; i++) {
196  list_add(list_skills, list_skills->rows - (i % list_skills->cols == 0 ? 0 : 1), i % list_skills->cols, NULL);
197  }
198 
199  if (list_skills->rows == rows) {
200  list_skills->row_offset = offset;
201  list_skills->row_selected = selected;
202  }
203 
204  cur_widget[SKILLS_ID]->redraw = 1;
205 }
206 
217 int skill_find(const char *name, size_t *id)
218 {
219  for (*id = 0; *id < skill_list_num; *id += 1) {
220  if (!strncasecmp(skill_list[*id]->skill->s_name, name, strlen(name))) {
221  return 1;
222  }
223  }
224 
225  return 0;
226 }
227 
228 int skill_find_object(object *op, size_t *id)
229 {
230  for (*id = 0; *id < skill_list_num; *id += 1) {
231  if (skill_list[*id]->skill == op) {
232  return 1;
233  }
234  }
235 
236  return 0;
237 }
238 
247 {
248  return skill_list[id];
249 }
250 
251 void
252 skills_update (object *op,
253  uint8_t level,
254  int64_t xp,
255  const char *msg)
256 {
257  size_t skill_id;
258  skill_entry_struct *skill;
259 
260  if (skill_find_object(op, &skill_id)) {
261  skill = skill_get(skill_id);
262  } else {
263  skill = ecalloc(1, sizeof(*skill));
264  skill->skill = op;
265 
266  skill_list = erealloc(skill_list, sizeof(*skill_list) * (skill_list_num + 1));
267  skill_list[skill_list_num] = skill;
268  skill_list_num++;
269  }
270 
271  skill->level = level;
272  skill->exp = xp;
273  snprintf(VS(skill->msg), "%s", msg);
274 
276 }
277 
278 void skills_remove(object *op)
279 {
280  size_t skill_id, i;
281 
282  if (!skill_find_object(op, &skill_id)) {
283  LOG(BUG, "Tried to remove skill '%s', but it was not in skill list.", op->s_name);
284  return;
285  }
286 
287  efree(skill_list[skill_id]);
288 
289  for (i = skill_id + 1; i < skill_list_num; i++) {
290  skill_list[i - 1] = skill_list[i];
291  }
292 
293  skill_list = erealloc(skill_list, sizeof(*skill_list) * (skill_list_num - 1));
294  skill_list_num--;
295 
297 }
298 
300 static void widget_draw(widgetdata *widget)
301 {
302  SDL_Rect box;
303  size_t i;
304 
305  /* Create the skill list. */
306  if (!list_skills) {
307  list_skills = list_create(5, 4, 8);
308  list_skills->post_column_func = list_post_column;
309  list_skills->row_color_func = list_row_color;
310  list_skills->row_selected_func = NULL;
311  list_skills->row_highlight_func = NULL;
312  list_skills->surface = widget->surface;
313  list_skills->row_height_adjust = INVENTORY_ICON_SIZE;
314  list_set_font(list_skills, NULL);
315  list_scrollbar_enable(list_skills);
316  list_set_column(list_skills, 0, INVENTORY_ICON_SIZE, 0, NULL, -1);
317  list_set_column(list_skills, 1, INVENTORY_ICON_SIZE, 0, NULL, -1);
318  list_set_column(list_skills, 2, INVENTORY_ICON_SIZE, 0, NULL, -1);
319  list_set_column(list_skills, 3, INVENTORY_ICON_SIZE, 0, NULL, -1);
321 
322  for (i = 0; i < BUTTON_NUM; i++) {
323  button_create(&buttons[i]);
324  buttons[i].texture = texture_get(TEXTURE_TYPE_CLIENT, "button_round");
325  buttons[i].texture_pressed = texture_get(TEXTURE_TYPE_CLIENT, "button_round_down");
326  buttons[i].texture_over = texture_get(TEXTURE_TYPE_CLIENT, "button_round_over");
327  }
328  }
329 
330  if (widget->redraw) {
331  box.h = 0;
332  box.w = widget->w;
333  text_show(widget->surface, FONT_SERIF12, "Skills", 0, 3, COLOR_HGOLD, TEXT_ALIGN_CENTER, &box);
334  list_set_parent(list_skills, widget->x, widget->y);
335  list_show(list_skills, 10, 2);
336 
337  for (i = 0; i < BUTTON_NUM; i++) {
338  buttons[i].surface = widget->surface;
339  button_set_parent(&buttons[i], widget->x, widget->y);
340  }
341 
342  buttons[BUTTON_CLOSE].x = widget->w - texture_surface(buttons[BUTTON_CLOSE].texture)->w - 4;
343  buttons[BUTTON_CLOSE].y = 4;
344  button_show(&buttons[BUTTON_CLOSE], "X");
345 
346  buttons[BUTTON_HELP].x = widget->w - texture_surface(buttons[BUTTON_HELP].texture)->w * 2 - 4;
347  buttons[BUTTON_HELP].y = 4;
348  button_show(&buttons[BUTTON_HELP], "?");
349  }
350 }
351 
353 static void widget_background(widgetdata *widget, int draw)
354 {
355  if (!widget->redraw) {
356  widget->redraw = list_need_redraw(list_skills);
357  }
358 
359  if (!widget->redraw) {
360  size_t i;
361 
362  for (i = 0; i < BUTTON_NUM; i++) {
363  if (button_need_redraw(&buttons[i])) {
364  widget->redraw = 1;
365  break;
366  }
367  }
368  }
369 }
370 
372 static int widget_event(widgetdata *widget, SDL_Event *event)
373 {
374  uint32_t row, col;
375  size_t i;
376 
377  if (EVENT_IS_MOUSE(event) && event->button.button == SDL_BUTTON_LEFT && list_mouse_get_pos(list_skills, event->motion.x, event->motion.y, &row, &col)) {
378  size_t skill_id;
379 
380  skill_id = row * list_skills->cols + col;
381 
382  if (skill_id < skill_list_num) {
383  if (event->type == SDL_MOUSEBUTTONUP) {
384  if (selected_skill != skill_id) {
385  selected_skill = skill_id;
386  widget->redraw = 1;
387  return 1;
388  }
389  } else if (event->type == SDL_MOUSEBUTTONDOWN) {
390  event_dragging_start(skill_list[skill_id]->skill->tag, event->motion.x, event->motion.y);
391  return 1;
392  }
393  }
394  }
395 
396  /* If the list has handled the mouse event, we need to redraw the
397  * widget. */
398  if (list_skills && list_handle_mouse(list_skills, event)) {
399  widget->redraw = 1;
400  return 1;
401  }
402 
403 
404  for (i = 0; i < BUTTON_NUM; i++) {
405  if (button_event(&buttons[i], event)) {
406  switch (i) {
407  case BUTTON_CLOSE:
408  widget->show = 0;
409  break;
410 
411  case BUTTON_HELP:
412  help_show("skill list");
413  break;
414  }
415 
416  widget->redraw = 1;
417  return 1;
418  }
419 
420  if (buttons[i].redraw) {
421  widget->redraw = 1;
422  }
423  }
424 
425  return 0;
426 }
427 
429 static void widget_deinit(widgetdata *widget)
430 {
431  if (list_skills != NULL) {
432  list_remove(list_skills);
433  list_skills = NULL;
434  }
435 
436  for (size_t i = 0; i < BUTTON_NUM; i++) {
437  button_destroy(&buttons[i]);
438  }
439 }
440 
445 {
446  widget->draw_func = widget_draw;
447  widget->background_func = widget_background;
448  widget->event_func = widget_event;
449  widget->deinit_func = widget_deinit;
450 }
#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
#define TEXT_WORD_WRAP
Definition: text.h:226
static int widget_event(widgetdata *widget, SDL_Event *event)
Definition: skills.c:372
char s_name[NAME_LEN]
Definition: item.h:60
SDL_Surface * bitmap
Definition: sprite.h:96
void list_remove(list_struct *list)
Definition: list.c:522
SDL_Surface * texture_surface(texture_struct *texture)
Definition: texture.c:303
void skills_deinit(void)
Definition: skills.c:76
int x
Definition: list.h:36
SDL_Surface * surface
Definition: widget.h:110
int button_event(button_struct *button, SDL_Event *event)
Definition: button.c:222
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
int16_t face
Definition: item.h:72
void button_destroy(button_struct *button)
Definition: button.c:94
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
void text_show(SDL_Surface *surface, font_struct *font, const char *text, int x, int y, const char *color_notation, uint64_t flags, SDL_Rect *box)
Definition: text.c:1983
int16_t frame_offset
Definition: list.h:94
#define LIST_ROWS_START(list)
Definition: list.h:258
#define COLOR_HGOLD
Definition: text.h:319
int skill_find(const char *name, size_t *id)
Definition: skills.c:217
uint32_t row_offset
Definition: list.h:117
static button_struct buttons[BUTTON_NUM]
Definition: skills.c:45
texture_struct * texture_get(texture_type_t type, const char *name)
Definition: texture.c:279
skill_entry_struct * skill_get(size_t id)
Definition: skills.c:246
#define TEXT_MARKUP
Definition: text.h:224
#define LIST_ROW_HEIGHT(list)
Definition: list.h:256
#define TEXT_ALIGN_CENTER
Definition: text.h:230
static size_t skill_list_num
Definition: skills.c:53
static void list_post_column(list_struct *list, uint32_t row, uint32_t col)
Definition: skills.c:90
widgetdata * widget_find(widgetdata *where, int type, const char *id, SDL_Surface *surface)
Definition: widget.c:2091
void help_show(const char *name)
Definition: help.c:219
#define LIST_ROW_OFFSET(row, list)
Definition: list.h:267
void widget_skills_init(widgetdata *widget)
Definition: skills.c:444
uint8_t show
Definition: widget.h:69
_face_struct FaceList[MAX_FACE_TILES]
Definition: main.c:77
int list_need_redraw(list_struct *list)
Definition: list.c:315
texture_struct * texture_over
Definition: button.h:67
static void widget_draw(widgetdata *widget)
Definition: skills.c:300
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
void button_create(button_struct *button)
Definition: button.c:65
static size_t selected_skill
Definition: skills.c:61
static void skill_list_reload(void)
Definition: skills.c:181
static void widget_background(widgetdata *widget, int draw)
Definition: skills.c:353
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: skills.c:429
#define TEXT_OUTLINE
Definition: text.h:255
void skills_init(void)
Definition: skills.c:66
#define INVENTORY_ICON_SIZE
Definition: inventory.h:60
texture_struct * texture
Definition: button.h:61
void(* post_column_func)(struct list_struct *list, uint32_t row, uint32_t col)
Definition: list.h:239
static skill_entry_struct ** skill_list
Definition: skills.c:49
static list_struct * list_skills
Definition: skills.c:57
SDL_Surface * surface
Definition: list.h:138
SDL_Surface * surface
Definition: button.h:46
int w
Definition: widget.h:54
int h
Definition: widget.h:57
texture_struct * texture_pressed
Definition: button.h:73
void list_set_font(list_struct *list, font_struct *font)
Definition: list.c:284
void list_show(list_struct *list, int x, int y)
Definition: list.c:337
void surface_show(SDL_Surface *surface, int x, int y, SDL_Rect *srcrect, SDL_Surface *src)
Definition: sprite.c:761
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 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 border_create_color(SDL_Surface *surface, SDL_Rect *coords, int thickness, const char *color_notation)
Definition: sprite.c:1359
void list_scrollbar_enable(list_struct *list)
Definition: list.c:302
void button_show(button_struct *button, const char *text)
Definition: button.c:161
Definition: main.h:191
uint32_t rows
Definition: list.h:60
static void list_row_color(list_struct *list, int row, SDL_Rect box)
Definition: skills.c:173
uint32_t row_selected
Definition: list.h:109
#define COLOR_WHITE
Definition: text.h:289
int y
Definition: widget.h:51