Crossfire Client, Trunk
spells.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, see the
9  * 'LICENSE' and 'COPYING' files.
10  *
11  * The authors can be reached via e-mail to crossfire-devel@real-time.com
12  */
13 
19 #include "client.h"
20 
21 #include <assert.h>
22 #include <gtk/gtk.h>
23 
24 #include "image.h"
25 #include "metaserver.h"
26 #include "main.h"
27 #include "gtk2proto.h"
28 
29 enum Styles {
31 };
32 
33 static GtkListStore *spell_store;
34 static GtkTreeSelection *spell_selection;
35 static GtkWidget *spell_window, *spell_invoke,
38 
39 enum {
43 };
44 
45 static const char *Style_Names[Style_Last] = {
46  "spell_attuned", "spell_repelled", "spell_denied", "spell_normal"
47 };
49 static gpointer description_renderer = NULL;
52 static GtkStyle *spell_styles[Style_Last];
55 static int has_init = 0;
66 void spell_get_styles(void)
67 {
68  int i;
69  GtkStyle *tmp_style;
70  static int style_has_init=0;
71 
72  for (i=0; i < Style_Last; i++) {
73  if (style_has_init && spell_styles[i]) {
74  g_object_unref(spell_styles[i]);
75  }
76  tmp_style =
77  gtk_rc_get_style_by_paths(
78  gtk_settings_get_default(), NULL, Style_Names[i], G_TYPE_NONE);
79  if (tmp_style) {
80  spell_styles[i] = g_object_ref(tmp_style);
81  } else {
82  LOG(LOG_INFO, "spells.c::spell_get_styles",
83  "Unable to find style for %s", Style_Names[i]);
84  spell_styles[i] = NULL;
85  }
86  }
87  style_has_init = 1;
88 }
89 
100 static gboolean spell_selection_func(GtkTreeSelection *selection,
101  GtkTreeModel *model,
102  GtkTreePath *path,
103  gboolean path_currently_selected,
104  gpointer userdata)
105 {
106  gtk_widget_set_sensitive(spell_invoke, TRUE);
107  gtk_widget_set_sensitive(spell_cast, TRUE);
108  return TRUE;
109 }
110 
124 void on_spell_window_size_allocate(GtkWidget *widget, gpointer user_data)
125 {
126  guint i;
127  guint width;
128  gboolean valid;
129  GtkTreeIter iter;
130  guint column_count;
131  GList *column_list;
132  GtkTreeViewColumn *column;
133 
134  /* If the spell window has not been set up yet, do nothing. */
135  if (!has_init) {
136  return;
137  }
138  /*
139  * How wide is the spell window?
140  */
141  width = spell_treeview->allocation.width;
142  /*
143  * How many columns are in the spell window tree view?
144  */
145  column_list = gtk_tree_view_get_columns(GTK_TREE_VIEW(spell_treeview));
146  column_count = g_list_length(column_list);
147  /*
148  * Subtract the width of all but the last (Description) column from the
149  * total window width to figure out how much may be used for the final
150  * description column.
151  */
152  for (i = 0; i < column_count - 1; i += 1) {
153  column = g_list_nth_data(column_list, i);
154  width -= gtk_tree_view_column_get_width(column);
155  }
156  /*
157  * The column list allocated by gtk_tree_view_get_columns must be freed
158  * when it is no longer needed.
159  */
160  g_list_free(column_list);
161  /*
162  * Update the global variable used to configure the wrap-width for the
163  * spell dialog description column, then apply it to the cell renderer.
164  */
165  g_object_set(G_OBJECT(description_renderer), "wrap-width", width, NULL);
166  /*
167  * Traverse the spell store, and mark each row as changed. Get the first
168  * row, mark it, and then process the rest of the rows (if there are any).
169  * This re-flows the spell descriptions to the new wrap-width, and adjusts
170  * the height of each row as needed to optimize the vertical space used.
171  */
172  valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(spell_store), &iter);
173  while (valid) {
174  GtkTreePath *tree_path;
175 
176  tree_path =
177  gtk_tree_model_get_path(GTK_TREE_MODEL(spell_store), &iter);
178  gtk_tree_model_row_changed(
179  GTK_TREE_MODEL(spell_store), tree_path, &iter);
180  gtk_tree_path_free(tree_path);
181  valid =
182  gtk_tree_model_iter_next(GTK_TREE_MODEL(spell_store), &iter);
183  }
184 }
185 
191 {
192  int i;
193  Spell *spell;
194  GtkTreeIter iter;
195  char buf[MAX_BUF];
196  GtkStyle *row_style;
197  GdkColor *foreground=NULL;
198  GdkColor *background=NULL;
199  PangoFontDescription *font=NULL;
200 
201  /* If the window/spellstore hasn't been created, return. */
202  if (!has_init) {
203  return;
204  }
205 
206  cpl.spells_updated = 0;
207 
208  /* We could try to do this in spell_get_styles, but if the window isn't
209  * active, it won't work. This is called whenever the window is made
210  * active, so we know it will work, and the time to set this info here,
211  * even though it may not change often, is pretty trivial.
212  */
213  for (i=0; i < Style_Last; i++) {
214  if (spell_styles[i]) {
215  gtk_widget_modify_fg(spell_label[i],
216  GTK_STATE_NORMAL, &spell_styles[i]->text[GTK_STATE_NORMAL]);
217  gtk_widget_modify_font(spell_label[i], spell_styles[i]->font_desc);
218  gtk_widget_modify_bg(spell_eventbox[i],
219  GTK_STATE_NORMAL, &spell_styles[i]->base[GTK_STATE_NORMAL]);
220  } else {
221  gtk_widget_modify_fg(spell_label[i],GTK_STATE_NORMAL, NULL);
222  gtk_widget_modify_font(spell_label[i], NULL);
223  gtk_widget_modify_bg(spell_eventbox[i],GTK_STATE_NORMAL, NULL);
224  }
225  }
226 
227  gtk_list_store_clear(spell_store);
228  for (spell = cpl.spelldata; spell; spell=spell->next) {
229  gtk_list_store_append(spell_store, &iter);
230 
231  buf[0] = 0;
232  if (spell->sp) {
233  snprintf(buf, sizeof(buf), "%d Mana ", spell->sp);
234  }
235  if (spell->grace)
236  snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
237  "%d Grace", spell->grace);
238 
239  if (spell->path & cpl.stats.denied) {
240  row_style = spell_styles[Style_Denied];
241  } else if (spell->path & cpl.stats.repelled) {
242  row_style = spell_styles[Style_Repelled];
243  } else if (spell->path & cpl.stats.attuned) {
244  row_style = spell_styles[Style_Attuned];
245  } else {
246  row_style = spell_styles[Style_Normal];
247  }
248 
249  if (row_style) {
250  foreground = &row_style->text[GTK_STATE_NORMAL];
251  background = &row_style->base[GTK_STATE_NORMAL];
252  font = row_style->font_desc;
253  } else {
254  foreground=NULL;
255  background=NULL;
256  font=NULL;
257  }
258 
259  gtk_list_store_set(
260  spell_store, &iter,
261  LIST_IMAGE, (GdkPixbuf*) pixmaps[spell->face]->full_icon_image,
262  LIST_NAME, spell->name,
263  LIST_LEVEL, spell->level,
264  LIST_COST, buf,
265  LIST_DAMAGE, spell->dam,
266  LIST_SKILL, spell->skill,
267  LIST_DESCRIPTION, spell->message,
268  LIST_BACKGROUND, background,
269  LIST_FOREGROUND, foreground,
270  LIST_FONT, font,
271  LIST_MAX_SP, (spell->sp > spell->grace) ? spell->sp : spell->grace,
272  LIST_TAG, spell->tag,
273  -1
274  );
275  }
276 }
277 
283 void on_spells_activate(GtkMenuItem *menuitem, gpointer user_data) {
284  GtkWidget *widget;
285 
286  if (!has_init) {
287  GtkCellRenderer *renderer;
288  GtkTreeViewColumn *column;
289 
290  spell_window = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_window"));
291 
292  spell_invoke = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_invoke"));
293  spell_cast = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_cast"));
294  spell_options = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_options"));
295  spell_treeview = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_treeview"));
296 
297  g_signal_connect((gpointer) spell_window, "size-allocate",
298  G_CALLBACK(on_spell_window_size_allocate), NULL);
299  g_signal_connect((gpointer) spell_window, "delete-event",
300  G_CALLBACK(gtk_widget_hide_on_delete), NULL);
301  g_signal_connect((gpointer) spell_treeview, "row_activated",
302  G_CALLBACK(on_spell_treeview_row_activated), NULL);
303  g_signal_connect((gpointer) spell_cast, "clicked",
304  G_CALLBACK(on_spell_cast_clicked), NULL);
305  g_signal_connect((gpointer) spell_invoke, "clicked",
306  G_CALLBACK(on_spell_invoke_clicked), NULL);
307 
308  widget = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_close"));
309  g_signal_connect((gpointer) widget, "clicked",
310  G_CALLBACK(on_spell_close_clicked), NULL);
311 
312  spell_store =
313  gtk_list_store_new(
314  14,
315  G_TYPE_OBJECT, /* Image - not used */
316  G_TYPE_STRING, /* Name */
317  G_TYPE_INT, /* Level */
318  G_TYPE_INT, /* Time */
319  G_TYPE_STRING, /* SP/Grace */
320  G_TYPE_INT, /* Damage */
321  G_TYPE_STRING, /* Skill name */
322  G_TYPE_INT, /* Spell path */
323  G_TYPE_STRING, /* Description */
324  GDK_TYPE_COLOR, /* Background color of the entry */
325  G_TYPE_INT,
326  G_TYPE_INT,
327  GDK_TYPE_COLOR,
328  PANGO_TYPE_FONT_DESCRIPTION
329  );
330 
331  gtk_tree_view_set_model(
332  GTK_TREE_VIEW(spell_treeview), GTK_TREE_MODEL(spell_store));
333  gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(spell_treeview), TRUE);
334 
335  /* Note: it is intentional we don't show (render) some fields:
336  * image - we don't have images right now it seems.
337  * time - not sure if it worth the space.
338  * spell path - done by color
339  *
340  * Note: Cell alignment is set to top right instead of the default,
341  * to improve readability when descriptions wrap to multiple lines.
342  */
343 
344  renderer = gtk_cell_renderer_pixbuf_new();
345  renderer->xalign = 0;
346  renderer->yalign = 0;
347  column = gtk_tree_view_column_new_with_attributes(
348  "?", renderer, "pixbuf", LIST_IMAGE, NULL);
349  gtk_tree_view_append_column(GTK_TREE_VIEW(spell_treeview), column);
350  gtk_tree_view_column_set_sort_column_id(column, LIST_IMAGE);
351 
352  renderer = gtk_cell_renderer_text_new();
353  renderer->xalign = 0;
354  renderer->yalign = 0;
355  column = gtk_tree_view_column_new_with_attributes(
356  "Spell", renderer, "text", LIST_NAME, NULL);
357  gtk_tree_view_append_column(GTK_TREE_VIEW(spell_treeview), column);
358  gtk_tree_view_column_set_sort_column_id(column, LIST_NAME);
359  gtk_tree_view_column_add_attribute(
360  column, renderer, "background-gdk", LIST_BACKGROUND);
361  gtk_tree_view_column_add_attribute(
362  column, renderer, "foreground-gdk", LIST_FOREGROUND);
363  gtk_tree_view_column_add_attribute(
364  column, renderer, "font-desc", LIST_FONT);
365 
366  renderer = gtk_cell_renderer_text_new();
367  renderer->xalign = 0.4;
368  renderer->yalign = 0;
369  column = gtk_tree_view_column_new_with_attributes(
370  "Level", renderer, "text", LIST_LEVEL, NULL);
371  gtk_tree_view_append_column(GTK_TREE_VIEW(spell_treeview), column);
372  gtk_tree_view_column_set_sort_column_id(column, LIST_LEVEL);
373  gtk_tree_view_column_add_attribute(
374  column, renderer, "background-gdk", LIST_BACKGROUND);
375  gtk_tree_view_column_add_attribute(
376  column, renderer, "foreground-gdk", LIST_FOREGROUND);
377  gtk_tree_view_column_add_attribute(
378  column, renderer, "font-desc", LIST_FONT);
379 
380  renderer = gtk_cell_renderer_text_new();
381  renderer->xalign = 0.4;
382  renderer->yalign = 0;
383  column = gtk_tree_view_column_new_with_attributes(
384  "Cost/Cast", renderer, "text", LIST_COST, NULL);
385  gtk_tree_view_append_column(GTK_TREE_VIEW(spell_treeview), column);
386 
387  /* Since this is a string column, it would do a string sort. Instead,
388  * we set up a int column and tie this column to sort on that.
389  */
390  gtk_tree_view_column_set_sort_column_id(column, LIST_MAX_SP);
391  gtk_tree_view_column_add_attribute(
392  column, renderer, "background-gdk", LIST_BACKGROUND);
393  gtk_tree_view_column_add_attribute(
394  column, renderer, "foreground-gdk", LIST_FOREGROUND);
395  gtk_tree_view_column_add_attribute(
396  column, renderer, "font-desc", LIST_FONT);
397 
398  renderer = gtk_cell_renderer_text_new();
399  renderer->xalign = 0.4;
400  renderer->yalign = 0;
401  column = gtk_tree_view_column_new_with_attributes(
402  "Damage", renderer, "text", LIST_DAMAGE, NULL);
403  gtk_tree_view_append_column(GTK_TREE_VIEW(spell_treeview), column);
404  gtk_tree_view_column_set_sort_column_id(column, LIST_DAMAGE);
405  gtk_tree_view_column_add_attribute(
406  column, renderer, "background-gdk", LIST_BACKGROUND);
407  gtk_tree_view_column_add_attribute(
408  column, renderer, "foreground-gdk", LIST_FOREGROUND);
409  gtk_tree_view_column_add_attribute(
410  column, renderer, "font-desc", LIST_FONT);
411 
412  column = gtk_tree_view_column_new_with_attributes(
413  "Skill", renderer, "text", LIST_SKILL, NULL);
414  gtk_tree_view_append_column(GTK_TREE_VIEW(spell_treeview), column);
415  gtk_tree_view_column_set_sort_column_id(column, LIST_SKILL);
416  gtk_tree_view_column_add_attribute(
417  column, renderer, "background-gdk", LIST_BACKGROUND);
418  gtk_tree_view_column_add_attribute(
419  column, renderer, "foreground-gdk", LIST_FOREGROUND);
420  gtk_tree_view_column_add_attribute(
421  column, renderer, "font-desc", LIST_FONT);
422 
423  renderer = gtk_cell_renderer_text_new();
424  renderer->xalign = 0;
425  renderer->yalign = 0;
426  column = gtk_tree_view_column_new_with_attributes(
427  "Description", renderer, "text", LIST_DESCRIPTION, NULL);
428  gtk_tree_view_append_column(GTK_TREE_VIEW(spell_treeview), column);
429  gtk_tree_view_column_add_attribute(
430  column, renderer, "background-gdk", LIST_BACKGROUND);
431  gtk_tree_view_column_add_attribute(
432  column, renderer, "foreground-gdk", LIST_FOREGROUND);
433  gtk_tree_view_column_add_attribute(
434  column, renderer, "font-desc", LIST_FONT);
435  /*
436  * Set up the description column so it wraps lengthy descriptions over
437  * multiple lines and at word boundaries. A default wrap-width is
438  * applied to constrain the column width to a reasonable value. The
439  * actual value used here is somewhat unimportant since a corrected
440  * width is computed and applied later, but, it does approximate the
441  * column size that is appropriate for the dialog's default width.
442  */
443  g_object_set(G_OBJECT(renderer),
444  "wrap-width", 300, "wrap-mode", PANGO_WRAP_WORD, NULL);
445  /*
446  * Preserve the description text cell renderer pointer to facilitate
447  * setting the wrap-width relative to the dialog's size and content.
448  */
449  description_renderer = renderer;
450 
452  gtk_tree_view_get_selection(GTK_TREE_VIEW(spell_treeview));
453  gtk_tree_selection_set_mode(spell_selection, GTK_SELECTION_BROWSE);
454  gtk_tree_selection_set_select_function(
456 
457  gtk_tree_sortable_set_sort_column_id(
458  GTK_TREE_SORTABLE(spell_store), LIST_NAME, GTK_SORT_ASCENDING);
459 
460  /* The style code will set the colors for these */
462  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_label_attuned"));
464  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_label_repelled"));
466  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_label_denied"));
468  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_label_normal"));
469 
470  /* We use eventboxes because the label widget is a transparent widget.
471  * We can't set the background in it and have it work. But we can set
472  * the background in the event box, and put the label widget in the
473  * eventbox.
474  */
476  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_eventbox_attuned"));
478  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_eventbox_repelled"));
480  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_eventbox_denied"));
482  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_eventbox_normal"));
483  }
484  gtk_widget_set_sensitive(spell_invoke, FALSE);
485  gtk_widget_set_sensitive(spell_cast, FALSE);
486  gtk_widget_show(spell_window);
488 
489  has_init = 1;
490 
491  /* Must be called after has_init is set to 1 */
493 }
494 
502 void on_spell_treeview_row_activated(GtkTreeView *treeview,
503  GtkTreePath *path,
504  GtkTreeViewColumn *column,
505  gpointer user_data)
506 {
507  on_spell_cast_clicked(NULL, NULL);
508 }
509 
515 void on_spell_cast_clicked(GtkButton *button, gpointer user_data)
516 {
517  int tag;
518  char command[MAX_BUF];
519  const char *options = NULL;
520  GtkTreeIter iter;
521  GtkTreeModel *model;
522 
523  options = gtk_entry_get_text(GTK_ENTRY(spell_options));
524 
525  if (gtk_tree_selection_get_selected(spell_selection, &model, &iter)) {
526  gtk_tree_model_get(model, &iter, LIST_TAG, &tag, -1);
527 
528  if (!tag) {
529  LOG(LOG_ERROR, "spells.c::on_spell_cast_clicked",
530  "Unable to get spell tag\n");
531  return;
532  }
533  snprintf(command, MAX_BUF-1, "cast %d %s", tag, options);
534  send_command(command, -1, 1);
535  }
536 }
537 
543 void on_spell_invoke_clicked(GtkButton *button, gpointer user_data)
544 {
545  int tag;
546  char command[MAX_BUF];
547  const char *options=NULL;
548  GtkTreeIter iter;
549  GtkTreeModel *model;
550 
551  options = gtk_entry_get_text(GTK_ENTRY(spell_options));
552 
553  if (gtk_tree_selection_get_selected(spell_selection, &model, &iter)) {
554  gtk_tree_model_get(model, &iter, LIST_TAG, &tag, -1);
555 
556  if (!tag) {
557  LOG(LOG_ERROR, "spells.c::on_spell_invoke_clicked",
558  "Unable to get spell tag\n");
559  return;
560  }
561  snprintf(command, MAX_BUF-1, "invoke %d %s", tag, options);
562  send_command(command, -1, 1);
563  }
564 }
565 
571 void on_spell_close_clicked(GtkButton *button, gpointer user_data)
572 {
573  gtk_widget_hide(spell_window);
574 }
575 
Player_Struct::stats
Stats stats
Definition: client.h:347
on_spell_cast_clicked
void on_spell_cast_clicked(GtkButton *button, gpointer user_data)
Definition: spells.c:515
LOG_INFO
@ LOG_INFO
Minor, non-harmful issues.
Definition: client.h:434
LIST_DESCRIPTION
@ LIST_DESCRIPTION
Definition: spells.c:41
Spell_struct::message
char message[10000]
Definition: client.h:295
Spell_struct::tag
guint32 tag
Definition: client.h:297
metaserver.h
Styles
Styles
Definition: inventory.c:62
on_spell_close_clicked
void on_spell_close_clicked(GtkButton *button, gpointer user_data)
Definition: spells.c:571
on_spell_invoke_clicked
void on_spell_invoke_clicked(GtkButton *button, gpointer user_data)
Definition: spells.c:543
LIST_BACKGROUND
@ LIST_BACKGROUND
Definition: spells.c:41
PixmapInfo::full_icon_image
GdkPixbuf * full_icon_image
Definition: image.h:50
LIST_FONT
@ LIST_FONT
Definition: spells.c:42
update_spell_information
void update_spell_information(void)
Definition: spells.c:190
pixmaps
PixmapInfo * pixmaps[MAXPIXMAPNUM]
Definition: image.c:34
LIST_TIME
@ LIST_TIME
Definition: spells.c:40
spell_invoke
static GtkWidget * spell_invoke
Definition: spells.c:35
LIST_PATH
@ LIST_PATH
Definition: spells.c:41
options
static GOptionEntry options[]
Definition: main.c:68
spell_window
static GtkWidget * spell_window
Definition: spells.c:35
Style_Attuned
@ Style_Attuned
Definition: spells.c:30
LIST_COST
@ LIST_COST
Definition: spells.c:40
Spell_struct
Definition: client.h:292
Spell_struct::next
struct Spell_struct * next
Definition: client.h:293
Spell_struct::face
gint32 face
Definition: client.h:317
MAX_BUF
#define MAX_BUF
Definition: client.h:40
Style_Last
@ Style_Last
Definition: spells.c:30
has_init
static int has_init
Definition: spells.c:55
Spell_struct::name
char name[256]
Definition: client.h:294
spell_styles
static GtkStyle * spell_styles[Style_Last]
Definition: spells.c:52
on_spells_activate
void on_spells_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: spells.c:283
Style_Repelled
@ Style_Repelled
Definition: spells.c:30
spell_selection_func
static gboolean spell_selection_func(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer userdata)
Definition: spells.c:100
gtk2proto.h
spell_label
static GtkWidget * spell_label[Style_Last]
Definition: spells.c:37
Spell_struct::skill
char * skill
Definition: client.h:311
spell_store
static GtkListStore * spell_store
Definition: spells.c:33
spell_treeview
static GtkWidget * spell_treeview
Definition: spells.c:36
LIST_LEVEL
@ LIST_LEVEL
Definition: spells.c:40
LOG
void LOG(LogLevel level, const char *origin, const char *format,...)
Definition: misc.c:111
LIST_MAX_SP
@ LIST_MAX_SP
Definition: spells.c:42
width
static int width
Definition: mapdata.c:98
on_spell_treeview_row_activated
void on_spell_treeview_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data)
Definition: spells.c:502
image.h
Style_Denied
@ Style_Denied
Definition: spells.c:30
Spell_struct::path
guint32 path
Definition: client.h:313
spell_eventbox
static GtkWidget * spell_eventbox[Style_Last]
Definition: spells.c:37
spell_cast
static GtkWidget * spell_cast
Definition: spells.c:36
dialog_xml
GtkBuilder * dialog_xml
Definition: main.c:102
LIST_FOREGROUND
@ LIST_FOREGROUND
Definition: spells.c:42
LIST_NAME
@ LIST_NAME
Definition: spells.c:40
send_command
int send_command(const char *command, int repeat, int must_send)
Definition: player.c:235
Style_Names
static const char * Style_Names[Style_Last]
Definition: spells.c:45
LOG_ERROR
@ LOG_ERROR
Warning that something definitely didn't work.
Definition: client.h:436
spell_get_styles
void spell_get_styles(void)
Definition: spells.c:66
main.h
spell_options
static GtkWidget * spell_options
Definition: spells.c:36
cpl
Client_Player cpl
Definition: client.c:69
LIST_TAG
@ LIST_TAG
Definition: spells.c:42
Style_Normal
@ Style_Normal
Definition: spells.c:30
Spell_struct::sp
guint16 sp
Definition: client.h:301
LIST_DAMAGE
@ LIST_DAMAGE
Definition: spells.c:41
Stat_struct::repelled
guint32 repelled
Definition: client.h:280
on_spell_window_size_allocate
void on_spell_window_size_allocate(GtkWidget *widget, gpointer user_data)
Definition: spells.c:124
description_renderer
static gpointer description_renderer
Definition: spells.c:49
LIST_IMAGE
@ LIST_IMAGE
Definition: spells.c:40
Spell_struct::dam
guint16 dam
Definition: client.h:303
Spell_struct::level
guint16 level
Definition: client.h:299
spell_selection
static GtkTreeSelection * spell_selection
Definition: spells.c:34
Stat_struct::denied
guint32 denied
Definition: client.h:283
Spell_struct::grace
guint16 grace
Definition: client.h:302
LIST_SKILL
@ LIST_SKILL
Definition: spells.c:41
Stat_struct::attuned
guint32 attuned
Definition: client.h:277
Player_Struct::spelldata
Spell * spelldata
Definition: client.h:348
Player_Struct::spells_updated
guint32 spells_updated
Definition: client.h:351
client.h