Atrinik Client  4.0
stat.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 
38 typedef struct widget_stat {
39  char *texture;
41 
45 static const char *const display_modes[] = {
46  "Sphere", "Bar", "Text"
47 };
48 
59 static bool stat_get_data(widgetdata *widget, int64_t *curr, int64_t *max,
60  double *regen)
61 {
62  if (strcmp(widget->id, "health") == 0) {
63  *curr = cpl.stats.hp;
64  *max = cpl.stats.maxhp;
65  *regen = cpl.gen_hp;
66  return true;
67  } else if (strcmp(widget->id, "mana") == 0) {
68  *curr = cpl.stats.sp;
69  *max = cpl.stats.maxsp;
70  *regen = cpl.gen_sp;
71  return true;
72  } else if (strcmp(widget->id, "food") == 0) {
73  *curr = cpl.stats.food;
74  *max = 999;
75  *regen = 0.0;
76  return true;
77  } else if (strcmp(widget->id, "exp") == 0) {
79  *max = s_settings->level_exp[cpl.stats.level + 1] -
81  *regen = 0.0;
82  return true;
83  }
84 
85  return false;
86 }
87 
89 static void widget_draw(widgetdata *widget)
90 {
91  if (!widget->redraw) {
92  return;
93  }
94 
95  widget_stat_t *stat_widget = widget->subwidget;
96 
97  int64_t curr, max;
98  double regen;
99  if (!stat_get_data(widget, &curr, &max, &regen)) {
100  LOG(ERROR, "Failed to get stat data for stat widget '%s'", widget->id);
101  return;
102  }
103 
104  SDL_Rect box;
105  if (strcmp(stat_widget->texture, "text") == 0) {
106  char buf[MAX_BUF];
107  snprintf(VS(buf), "%s: %"PRId64"/%"PRId64, widget->id, curr, max);
108  string_title(buf);
109 
110  if (regen > 0.0) {
111  snprintfcat(VS(buf), "\nRegen: %2.1f/s", regen);
112  }
113 
114  box.w = widget->surface->w;
115  box.h = widget->surface->h;
116  text_show(widget->surface, FONT_ARIAL11, buf, 0, 0, COLOR_WHITE,
118  } else if (strcmp(stat_widget->texture, "sphere") == 0) {
119  box.x = 0;
120  box.y = 0;
121  box.w = widget->w - WIDGET_BORDER_SIZE * 2;
122  box.h = widget->h - WIDGET_BORDER_SIZE * 2;
123 #define SPHERE_PADDING 2
124  text_show_format(widget->surface, FONT_ARIAL11,
125  WIDGET_BORDER_SIZE + SPHERE_PADDING,
126  WIDGET_BORDER_SIZE + SPHERE_PADDING,
127  COLOR_WHITE, TEXT_MARKUP, NULL,
128  "[icon=stat_sphere_back %d %d 1]",
129  widget->w - WIDGET_BORDER_SIZE * 2 - SPHERE_PADDING * 2,
130  widget->h - WIDGET_BORDER_SIZE * 2 - SPHERE_PADDING * 2);
131  text_show_format(widget->surface, FONT_ARIAL11,
132  WIDGET_BORDER_SIZE + 2 + SPHERE_PADDING,
133  WIDGET_BORDER_SIZE + 2 + SPHERE_PADDING,
134  COLOR_WHITE, TEXT_MARKUP, NULL,
135  "[icon=stat_sphere_%s %d %d 1 0 %f]", widget->id,
136  widget->w - WIDGET_BORDER_SIZE * 2 - 2 * 2 - SPHERE_PADDING * 2,
137  widget->h - WIDGET_BORDER_SIZE * 2 - 2 * 2 - SPHERE_PADDING * 2,
138  4.0 + ((double) MAX(0, curr) / (double) max));
139  text_show_format(widget->surface, FONT_ARIAL11,
140  WIDGET_BORDER_SIZE + SPHERE_PADDING,
141  WIDGET_BORDER_SIZE + SPHERE_PADDING,
142  COLOR_WHITE, TEXT_MARKUP, &box,
143  "[icon=stat_sphere %d %d 1]",
144  widget->w - WIDGET_BORDER_SIZE * 2 - SPHERE_PADDING * 2,
145  widget->h - WIDGET_BORDER_SIZE * 2 - SPHERE_PADDING * 2);
146 #undef SPHERE_PADDING
147  } else {
148  int thickness = (double) MIN(widget->w, widget->h) * 0.15;
149 
150  box.x = WIDGET_BORDER_SIZE;
151  box.y = WIDGET_BORDER_SIZE;
152  box.w = widget->w - WIDGET_BORDER_SIZE * 2;
153  box.h = widget->h - WIDGET_BORDER_SIZE * 2;
154  SDL_FillRect(widget->surface, &box,
155  SDL_MapRGB(widget->surface->format, 0, 0, 0));
156  border_create_texture(widget->surface, &box, thickness,
157  TEXTURE_CLIENT("stat_border"));
158 
159  box.x += thickness;
160  box.y += thickness;
161  box.w = MAX(0, box.w - thickness * 2);
162  box.h = MAX(0, box.h - thickness * 2);
163 
164  if (widget->w > widget->h) {
165  box.w *= ((double) MAX(0, curr) / (double) max);
166  } else {
167  int h = box.h * ((double) MAX(0, curr) / (double) max);
168  box.y += box.h - h;
169  box.h = h;
170  }
171 
172  char buf[MAX_BUF];
173  snprintf(VS(buf), "stat_bar_%s", widget->id);
174  surface_show_fill(widget->surface, box.x, box.y, NULL,
175  TEXTURE_CLIENT(buf), &box);
176  }
177 }
178 
180 static int widget_event(widgetdata *widget, SDL_Event *event)
181 {
182  if (event->type == SDL_MOUSEMOTION &&
183  event->motion.x - widget->x > WIDGET_BORDER_SIZE &&
184  event->motion.x - widget->x < widget->w - WIDGET_BORDER_SIZE &&
185  event->motion.y - widget->y > WIDGET_BORDER_SIZE &&
186  event->motion.y - widget->y < widget->h - WIDGET_BORDER_SIZE) {
187  int64_t curr, max;
188  double regen;
189  if (!stat_get_data(widget, &curr, &max, &regen)) {
190  LOG(ERROR, "Failed to get stat data for stat widget '%s'",
191  widget->id);
192  return 0;
193  }
194 
195  if (regen > 0.0) {
196  char buf[MAX_BUF];
197  snprintf(VS(buf), "%s", widget->id);
198  string_title(buf);
199  snprintfcat(VS(buf), ": %"PRId64"/%"PRId64"\nRegen: %2.1f/s", curr,
200  max, regen);
201  tooltip_create(event->motion.x, event->motion.y, FONT_ARIAL11, buf);
203  return 1;
204  }
205  }
206 
207  return 0;
208 }
209 
211 static void widget_deinit(widgetdata *widget)
212 {
213  widget_stat_t *stat_widget = widget->subwidget;
214  efree(stat_widget->texture);
215 }
216 
218 static int widget_load(widgetdata *widget, const char *keyword, const char *parameter)
219 {
220  widget_stat_t *stat_widget = widget->subwidget;
221 
222  if (strcmp(keyword, "texture") == 0) {
223  stat_widget->texture = estrdup(parameter);
224  return 1;
225  }
226 
227  return 0;
228 }
229 
231 static void widget_save(widgetdata *widget, FILE *fp, const char *padding)
232 {
233  widget_stat_t *stat_widget = widget->subwidget;
234  fprintf(fp, "%stexture = %s\n", padding, stat_widget->texture);
235 }
236 
237 static void menu_stat_display_change(widgetdata *widget, widgetdata *menuitem,
238  SDL_Event *event)
239 {
240  widget_stat_t *stat_widget = widget->subwidget;
241 
242  for (widgetdata *tmp = menuitem->inv; tmp != NULL; tmp = tmp->next) {
243  if (tmp->type == LABEL_ID) {
244  _widget_label *label = LABEL(tmp);
245  efree(stat_widget->texture);
246  stat_widget->texture = estrdup(label->text);
247  string_tolower(stat_widget->texture);
248  WIDGET_REDRAW(widget);
249  break;
250  }
251  }
252 }
253 
254 static void menu_stat_display(widgetdata *widget, widgetdata *menuitem,
255  SDL_Event *event)
256 {
257  widget_stat_t *stat_widget = widget->subwidget;
258  widgetdata *submenu = MENU(menuitem->env)->submenu;
259 
260  for (size_t i = 0; i < arraysize(display_modes); i++) {
261  add_menuitem(submenu, display_modes[i], &menu_stat_display_change,
262  MENU_RADIO, strcasecmp(stat_widget->texture,
263  display_modes[i]) == 0);
264  }
265 }
266 
268 static int widget_menu_handle(widgetdata *widget, SDL_Event *event)
269 {
270  widgetdata *menu = create_menu(event->motion.x, event->motion.y, widget);
271  widget_menu_standard_items(widget, menu);
272  add_menuitem(menu, "Display >", &menu_stat_display, MENU_SUBMENU, 0);
273  menu_finalize(menu);
274  return 1;
275 }
276 
283 {
284  widget_stat_t *stat_widget = ecalloc(1, sizeof(*stat_widget));
285 
286  widget->draw_func = widget_draw;
287  widget->event_func = widget_event;
288  widget->deinit_func = widget_deinit;
289  widget->load_func = widget_load;
290  widget->save_func = widget_save;
291  widget->menu_handle_func = widget_menu_handle;
292  widget->subwidget = stat_widget;
293 }
float gen_sp
Definition: player.h:149
struct widgetdata * env
Definition: widget.h:98
int32_t hp
Definition: player.h:66
int32_t maxhp
Definition: player.h:69
void widget_stat_init(widgetdata *widget)
Definition: stat.c:282
void * subwidget
Definition: widget.h:107
int64_t exp
Definition: player.h:78
SDL_Surface * surface
Definition: widget.h:110
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
static bool stat_get_data(widgetdata *widget, int64_t *curr, int64_t *max, double *regen)
Definition: stat.c:59
Stats stats
Definition: player.h:167
server_settings * s_settings
char * texture
Texture type to display. One of display_modes.
Definition: stat.c:39
void menu_finalize(widgetdata *widget)
Definition: widget.c:2524
void tooltip_create(int mx, int my, font_struct *font, const char *text)
Definition: tooltip.c:60
struct widgetdata * next
Definition: widget.h:86
#define TEXT_MARKUP
Definition: text.h:224
struct widgetdata * inv
Definition: widget.h:92
#define TEXT_ALIGN_CENTER
Definition: text.h:230
char * id
Definition: widget.h:42
static void widget_save(widgetdata *widget, FILE *fp, const char *padding)
Definition: stat.c:231
static void widget_deinit(widgetdata *widget)
Definition: stat.c:211
Client_Player cpl
Definition: client.c:50
float gen_hp
Definition: player.h:146
int32_t maxsp
Definition: player.h:75
uint8_t redraw
Definition: widget.h:72
int x
Definition: widget.h:48
#define WIDGET_REDRAW(__tmp)
Definition: widget.h:398
int64_t * level_exp
void tooltip_enable_delay(uint32_t delay)
Definition: tooltip.c:82
static int widget_menu_handle(widgetdata *widget, SDL_Event *event)
Definition: stat.c:268
widgetdata * create_menu(int x, int y, widgetdata *owner)
Definition: widget.c:2428
int16_t food
Definition: player.h:81
int w
Definition: widget.h:54
int h
Definition: widget.h:57
static void widget_draw(widgetdata *widget)
Definition: stat.c:89
uint32_t level
Definition: player.h:63
int32_t sp
Definition: player.h:72
void border_create_texture(SDL_Surface *surface, SDL_Rect *coords, int thickness, SDL_Surface *texture)
Definition: sprite.c:1388
struct widget_stat widget_stat_t
void surface_show_fill(SDL_Surface *surface, int x, int y, SDL_Rect *srcsize, SDL_Surface *src, SDL_Rect *box)
Definition: sprite.c:792
static int widget_load(widgetdata *widget, const char *keyword, const char *parameter)
Definition: stat.c:218
static int widget_event(widgetdata *widget, SDL_Event *event)
Definition: stat.c:180
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
#define TEXT_VALIGN_CENTER
Definition: text.h:246
void add_menuitem(widgetdata *menu, const char *text, void(*menu_func_ptr)(widgetdata *, widgetdata *, SDL_Event *event), int menu_type, int val)
Definition: widget.c:2451
static const char *const display_modes[]
Definition: stat.c:45
#define COLOR_WHITE
Definition: text.h:289
int y
Definition: widget.h:51
char * text
Definition: widget.h:210