Crossfire Client, Trunk  R20612
item.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, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
19 #include "client.h"
20 
21 #include <ctype.h> /* needed for isdigit */
22 
23 #include "external.h"
24 #include "item.h"
25 #include "script.h"
26 
27 static item *free_items; /* the list of free (unused) items */
28 static item *player, *map; /* these lists contains rest of items */
29 /* player = pl->ob, map = pl->below */
30 
31 #define NROF_ITEMS 50 /* how many items are reserved initially */
32 /* for the item spool */
33 
34 #include "item-types.h"
35 
36 /* This uses the item_types table above. We try to figure out if
37  * name has a match above. Matching is done pretty loosely - however
38  * we try to match the start of the name because that is more reliable.
39  * We return the 'type' (matching array element above), 255 if no match
40  * (so unknown objects put at the end)
41  */
42 guint8 get_type_from_name(const char *name)
43 {
44  int type, pos;
45 
46  for (type = 0; type < NUM_ITEM_TYPES; type++) {
47  pos = 0;
48  while (item_types[type][pos] != NULL) {
49  /* Only search at start of line */
50  if (item_types[type][pos][0] == '^') {
51  if (!g_ascii_strncasecmp(name, item_types[type][pos]+1, strlen(item_types[type][pos]+1))) {
52  return type;
53  }
54  }
55  /* String anywhere in name */
56  else if (strstr(name, item_types[type][pos]) != NULL) {
57 #if 0
58  fprintf(stderr, "Returning type %d for %s\n", type, name);
59 #endif
60  return type;
61  }
62  pos++;
63  }
64  }
65  LOG(LOG_WARNING, "common::get_type_from_name", "Could not find match for %s", name);
66  return 255;
67 }
68 
69 /* Does what is says - inserts newitem before the object.
70  * the parameters can not be null
71  */
72 static void insert_item_before_item(item *newitem, item *before)
73 {
74  if (before->prev) {
75  before->prev->next = newitem;
76  } else {
77  newitem->env->inv = newitem;
78  }
79 
80  newitem->prev = before->prev;
81 
82  before->prev = newitem;
83  newitem->next = before;
84 
85  if (newitem->env) {
86  newitem->env->inv_updated = 1;
87  }
88 }
89 
90 /* Item it has gotten an item type, so we need to resort its location */
92 {
93  item *itmp, *last = NULL;
94 
95  /* If not in some environment or the map, return */
96  /* Sorting on the map doesn't work. In theory, it would be nice,
97  * but the server really must know the map order for things to
98  * work.
99  */
100  if (!it->env || it->env == it || it->env == map) {
101  return;
102  }
103 
104  /* If we are already sorted properly, don't do anything further.
105  * this is prevents the order of the inventory from changing around
106  * if you just equip something.
107  */
108  if (it->prev && it->prev->type == it->type &&
109  it->prev->locked == it->locked &&
110  !g_ascii_strcasecmp(it->prev->s_name, it->s_name)) {
111  return;
112  }
113 
114  if (it->next && it->next->type == it->type &&
115  it->next->locked == it->locked &&
116  !g_ascii_strcasecmp(it->next->s_name, it->s_name)) {
117  return;
118  }
119 
120  /* Remove this item from the list */
121  if (it->prev) {
122  it->prev->next = it->next;
123  }
124  if (it->next) {
125  it->next->prev = it->prev;
126  }
127  if (it->env->inv == it) {
128  it->env->inv = it->next;
129  }
130 
131  for (itmp = it->env->inv; itmp != NULL; itmp = itmp->next) {
132  last = itmp;
133 
134  /* If the next item is higher in the order, insert here */
135  if (itmp->type > it->type) {
136  insert_item_before_item(it, itmp);
137  return;
138  } else if (itmp->type == it->type) {
139 #if 0
140  /* This could be a nice idea, but doesn't work very well if you
141  * have a few unidentified wands, as the position of a wand
142  * which you know the effect will move around as you equip others.
143  */
144  /* Hmm. We can actually use the tag value of the items to reduce
145  * this a bit - do this by grouping, but if name is equal, then
146  * sort by tag. Needs further investigation.
147  */
148 
149  /* applied items go first */
150  if (itmp->applied) {
151  continue;
152  }
153  /* put locked items before others */
154  if (itmp->locked && !it->locked) {
155  continue;
156  }
157 #endif
158 
159  /* Now alphabetise */
160  if (g_ascii_strcasecmp(itmp->s_name, it->s_name) < 0) {
161  continue;
162  }
163 
164  /* IF we got here, it means it passed all our sorting tests */
165  insert_item_before_item(it, itmp);
166  return;
167  }
168  }
169  /* No match - put it at the end */
170 
171  /* If there was a previous item, update pointer. IF no previous
172  * item, we need to update the environment to point to us */
173  if (last) {
174  last->next = it;
175  } else {
176  it->env->inv = it;
177  }
178 
179  it->prev = last;
180  it->next = NULL;
181 }
182 
183 /* Stolen from common/item.c */
184 /*
185  * get_number(integer) returns the text-representation of the given number
186  * in a static buffer. The buffer might be overwritten at the next
187  * call to get_number().
188  * It is currently only used by the query_name() function.
189  */
190 const char *get_number(guint32 i)
191 {
192  static const char *numbers[] = {
193  "no", "a", "two", "three", "four",
194  "five", "six", "seven", "eight", "nine",
195  "ten", "eleven", "twelve", "thirteen", "fourteen",
196  "fifteen", "sixteen", "seventeen", "eighteen", "nineteen",
197  "twenty",
198  };
199  static char buf[MAX_BUF];
200 
201  if (i <= 20) {
202  return numbers[i];
203  } else {
204  snprintf(buf, sizeof(buf), "%u", i);
205  return buf;
206  }
207 }
208 
209 /*
210  * new_item() returns pointer to new item which
211  * is allocated and initialized correctly
212  */
213 static item *new_item(void)
214 {
215  item *op = g_malloc(sizeof(item));
216 
217  if (!op) {
218  exit(0);
219  }
220 
221  op->next = op->prev = NULL;
222  copy_name(op->d_name, "");
223  copy_name(op->s_name, "");
224  copy_name(op->p_name, "");
225  op->inv = NULL;
226  op->env = NULL;
227  op->tag = 0;
228  op->face = 0;
229  op->weight = 0;
230  op->magical = op->cursed = op->damned = op->blessed = 0;
231  op->unpaid = op->locked = op->applied = 0;
232  op->flagsval = 0;
233  op->animation_id = 0;
234  op->last_anim = 0;
235  op->anim_state = 0;
236  op->nrof = 0;
237  op->open = 0;
238  op->type = NO_ITEM_TYPE;
239  op->inv_updated = 0;
240  return op;
241 }
242 
243 /*
244  * alloc_items() returns pointer to list of allocated objects
245  */
246 static item *alloc_items(int nrof)
247 {
248  item *op, *list;
249  int i;
250 
251  list = op = new_item();
252 
253  for (i = 1; i < nrof; i++) {
254  op->next = new_item();
255  op->next->prev = op;
256  op = op->next;
257  }
258  return list;
259 }
260 
261 /*
262  * free_items() frees all allocated items from list
263  */
265 {
266  item *tmp;
267 
268  while (op) {
269  if (op->inv) {
270  free_all_items(op->inv);
271  }
272  tmp = op->next;
273  free(op);
274  op = tmp;
275  }
276 }
277 
278 /*
279  * Recursive function, used by locate_item()
280  */
281 static item *locate_item_from_item(item *op, gint32 tag)
282 {
283  item *tmp;
284 
285  for (; op; op = op->next) {
286  if (op->tag == tag) {
287  return op;
288  } else if (op->inv && (tmp = locate_item_from_item(op->inv, tag))) {
289  return tmp;
290  }
291  }
292 
293  return NULL;
294 }
295 
296 /*
297  * locate_item() returns pointer to the item which tag is given
298  * as parameter or if item is not found returns NULL
299  */
300 item *locate_item(gint32 tag)
301 {
302  item *op;
303 
304  if (tag == 0) {
305  return map;
306  }
307 
308  if ((op = locate_item_from_item(map->inv, tag)) != NULL) {
309  return op;
310  }
311 
312  if ((op = locate_item_from_item(player, tag)) != NULL) {
313  return op;
314  }
315 
316  if (cpl.container && cpl.container->tag == tag) {
317  return cpl.container;
318  }
319 
320  if (cpl.container && (op = locate_item_from_item(cpl.container->inv, tag)) != NULL) {
321  return op;
322  }
323 
324  return NULL;
325 }
326 
327 /*
328  * remove_item() inserts op the the list of free items
329  * Note that it don't clear all fields in item
330  */
331 void remove_item(item *op)
332 {
333  /* IF no op, or it is the player */
334  if (!op || op == player || op == map) {
335  return;
336  }
337 
339 
340  op->env->inv_updated = 1;
341 
342  /* Do we really want to do this? */
343  if (op->inv && op != cpl.container) {
345  }
346 
347  if (op->prev) {
348  op->prev->next = op->next;
349  } else {
350  op->env->inv = op->next;
351  }
352  if (op->next) {
353  op->next->prev = op->prev;
354  }
355 
356  if (cpl.container == op) {
357  return; /* Don't free this! */
358  }
359 
360  /* add object to a list of free objects */
361  op->next = free_items;
362  if (op->next != NULL) {
363  op->next->prev = op;
364  }
365  free_items = op;
366 
367  /* Clear all these values, since this item will get re-used */
368  op->prev = NULL;
369  op->env = NULL;
370  op->tag = 0;
371  copy_name(op->d_name, "");
372  copy_name(op->s_name, "");
373  copy_name(op->p_name, "");
374  op->inv = NULL;
375  op->env = NULL;
376  op->tag = 0;
377  op->face = 0;
378  op->weight = 0;
379  op->magical = op->cursed = op->damned = op->blessed = 0;
380  op->unpaid = op->locked = op->applied = 0;
381  op->flagsval = 0;
382  op->animation_id = 0;
383  op->last_anim = 0;
384  op->anim_state = 0;
385  op->nrof = 0;
386  op->open = 0;
387  op->type = NO_ITEM_TYPE;
388 }
389 
390 /*
391  * remove_item_inventory() recursive frees items inventory
392  */
394 {
395  if (!op) {
396  return;
397  }
398 
400 
401  op->inv_updated = 1;
402  while (op->inv) {
403  remove_item(op->inv);
404  }
405 }
406 
407 /*
408  * add_item() adds item op to end of the inventory of item env
409  */
410 static void add_item(item *env, item *op)
411 {
412  item *tmp;
413 
414  for (tmp = env->inv; tmp && tmp->next; tmp = tmp->next)
415  ;
416 
417  op->next = NULL;
418  op->prev = tmp;
419  op->env = env;
420  if (!tmp) {
421  env->inv = op;
422  } else {
423  if (tmp->next) {
424  tmp->next->prev = op;
425  }
426  tmp->next = op;
427  }
428 }
429 
430 /*
431  * create_new_item() returns pointer to a new item, inserts it to env
432  * and sets its tag field and clears locked flag (all other fields
433  * are unitialized and may contain random values)
434  */
435 item *create_new_item(item *env, gint32 tag)
436 {
437  item *op;
438 
439  if (!free_items) {
440  free_items = alloc_items(NROF_ITEMS);
441  }
442 
443  op = free_items;
444  free_items = free_items->next;
445  if (free_items) {
446  free_items->prev = NULL;
447  }
448 
449  op->tag = tag;
450  op->locked = 0;
451  if (env) {
452  add_item(env, op);
453  }
454 
455  return op;
456 }
457 
458 int num_free_items(void)
459 {
460  item *tmp;
461  int count = 0;
462 
463  for (tmp = free_items; tmp; tmp = tmp->next) {
464  count++;
465  }
466 
467  return count;
468 }
469 
470 /*
471  * Hardcoded now, server could send these at initiation phase.
472  */
473 static const char *const apply_string[] = {
474  "", " (readied)", " (wielded)", " (worn)", " (active)", " (applied)",
475 };
476 
477 static void set_flag_string(item *op)
478 {
479  op->flags[0] = 0;
480 
481  if (op->locked) {
482  strcat(op->flags, " *");
483  }
484  if (op->apply_type) {
485  if (op->apply_type < sizeof(apply_string)/sizeof(apply_string[0])) {
486  strcat(op->flags, apply_string[op->apply_type]);
487  } else {
488  strcat(op->flags, " (undefined)");
489  }
490  }
491  if (op->open) {
492  strcat(op->flags, " (open)");
493  }
494  if (op->damned) {
495  strcat(op->flags, " (damned)");
496  }
497  if (op->cursed) {
498  strcat(op->flags, " (cursed)");
499  }
500  if (op->blessed) {
501  strcat(op->flags, " (blessed)");
502  }
503  if (op->magical) {
504  strcat(op->flags, " (magic)");
505  }
506  if (op->unpaid) {
507  strcat(op->flags, " (unpaid)");
508  }
509 }
510 
511 static void get_flags(item *op, guint16 flags)
512 {
513  op->was_open = op->open;
514  op->open = flags&F_OPEN ? 1 : 0;
515  op->damned = flags&F_DAMNED ? 1 : 0;
516  op->cursed = flags&F_CURSED ? 1 : 0;
517  op->blessed = flags&F_BLESSED ? 1 : 0;
518  op->magical = flags&F_MAGIC ? 1 : 0;
519  op->unpaid = flags&F_UNPAID ? 1 : 0;
520  op->applied = flags&F_APPLIED ? 1 : 0;
521  op->locked = flags&F_LOCKED ? 1 : 0;
522  op->flagsval = flags;
523  op->apply_type = flags&F_APPLIED;
524  set_flag_string(op);
525 }
526 
527 void set_item_values(item *op, char *name, gint32 weight, guint16 face,
528  guint16 flags, guint16 anim, guint16 animspeed,
529  guint32 nrof, guint16 type)
530 {
531  int resort = 1;
532 
533  if (!op) {
534  printf("Error in set_item_values(): item pointer is NULL.\n");
535  return;
536  }
537 
538  /* Program always expect at least 1 object internall */
539  if (nrof == 0) {
540  nrof = 1;
541  }
542 
543  if (*name != '\0') {
544  copy_name(op->s_name, name);
545 
546  /* Unfortunately, we don't get a length parameter, so we just have
547  * to assume that if it is a new server, it is giving us two piece
548  * names.
549  */
550  if (csocket.sc_version >= 1024) {
551  copy_name(op->p_name, name+strlen(name)+1);
552  } else { /* If not new version, just use same for both */
553  copy_name(op->p_name, name);
554  }
555 
556  /* Necessary so that d_name is updated below */
557  op->nrof = nrof+1;
558  } else {
559  resort = 0; /* no name - don't resort */
560  }
561 
562  if (op->nrof != nrof) {
563  if (nrof != 1 ) {
564  snprintf(op->d_name, sizeof(op->d_name), "%s %s", get_number(nrof),
565  op->p_name);
566  } else {
567  strcpy(op->d_name, op->s_name);
568  }
569  op->nrof = nrof;
570  }
571 
572  if (op->env) {
573  op->env->inv_updated = 1;
574  }
575  op->weight = (float)weight/1000;
576  op->face = face;
577  op->animation_id = anim;
578  op->anim_speed = animspeed;
579  op->type = type;
580  get_flags(op, flags);
581 
582  /* We don't sort the map, so lets not bother figuring out the
583  * type. Likewiwse, only figure out item type if this
584  * doesn't have a type (item2 provides us with a type
585  */
586  if (op->env != map && op->type == NO_ITEM_TYPE) {
587  op->type = get_type_from_name(op->s_name);
588  }
589  if (resort) {
590  update_item_sort(op);
591  }
592 
594 }
595 
597 {
598  SockList sl;
599  guint8 buf[MAX_BUF];
600 
601  if (op->env->tag == 0) {
602  return; /* if item is on the ground, don't lock it */
603  }
604 
605  snprintf((char*)buf, sizeof(buf), "lock %c %d", !op->locked, op->tag);
606  script_monitor_str((char*)buf);
607  SockList_Init(&sl, buf);
608  SockList_AddString(&sl, "lock ");
609  SockList_AddChar(&sl, !op->locked);
610  SockList_AddInt(&sl, op->tag);
611  SockList_Send(&sl, csocket.fd);
612 }
613 
615 {
616  SockList sl;
617  guint8 buf[MAX_BUF];
618 
619  if (op->env->tag == 0) {
620  return; /* if item is on the ground, don't mark it */
621  }
622 
623  snprintf((char*)buf, sizeof(buf), "mark %d", op->tag);
624  script_monitor_str((char*)buf);
625  SockList_Init(&sl, buf);
626  SockList_AddString(&sl, "mark ");
627  SockList_AddInt(&sl, op->tag);
628  SockList_Send(&sl, csocket.fd);
629 }
630 
632 {
633  player = new_item();
634  return player;
635 }
636 
637 item *map_item (void)
638 {
639  map = new_item();
640  map->weight = -1;
641  return map;
642 }
643 
644 /* Upates an item with new attributes. */
645 void update_item(int tag, int loc, char *name, int weight, int face, int flags,
646  int anim, int animspeed, guint32 nrof, int type)
647 {
648  item *ip = locate_item(tag), *env = locate_item(loc);
649 
650  /* Need to do some special handling if this is the player that is
651  * being updated.
652  */
653  if (player->tag == tag) {
654  copy_name(player->d_name, name);
655  /* I don't think this makes sense, as you can have
656  * two players merged together, so nrof should always be one
657  */
658  player->nrof = nrof;
659  player->weight = (float)weight/1000;
660  player->face = face;
661  get_flags(player, flags);
662  if (player->inv) {
663  player->inv->inv_updated = 1;
664  }
665  player->animation_id = anim;
666  player->anim_speed = animspeed;
667  player->nrof = nrof;
668  } else {
669  if (ip && ip->env != env) {
670  remove_item(ip);
671  ip = NULL;
672  }
673  set_item_values(ip ? ip : create_new_item(env, tag), name, weight, face, flags,
674  anim, animspeed, nrof, type);
675  }
676 }
677 
678 /*
679  * Prints players inventory, contain extra information for debugging purposes
680  * This isn't pretty, but is only used for debugging, so it doesn't need to be.
681  */
683 {
684  char buf[MAX_BUF];
685  char buf2[MAX_BUF];
686  item *tmp;
687  static int l = 0;
688 #if 0
689  int info_width = get_info_width();
690 #else
691  /* A callback for a debugging command seems pretty pointless. If anything,
692  * it may be more useful to dump this out to stderr
693  */
694  int info_width = 40;
695 #endif
696 
697  if (l == 0) {
698  snprintf(buf, sizeof(buf), "%s's inventory (%d):", op->d_name, op->tag);
699  snprintf(buf2, sizeof(buf2), "%-*s%6.1f kg", info_width-10, buf, op->weight);
701  }
702 
703  l += 2;
704  for (tmp = op->inv; tmp; tmp = tmp->next) {
705  snprintf(buf, sizeof(buf), "%*s- %d %s%s (%d)", l-2, "", tmp->nrof, tmp->d_name, tmp->flags, tmp->tag);
706  snprintf(buf2, sizeof(buf2), "%-*s%6.1f kg", info_width-8-l, buf, tmp->nrof*tmp->weight);
708  if (tmp->inv) {
709  print_inventory(tmp);
710  }
711  }
712  l -= 2;
713 }
714 
715 /* Check the objects, animate the ones as necessary */
716 void animate_objects(void)
717 {
718  item *ip;
719  int got_one = 0;
720 
721  /* Animate players inventory */
722  for (ip = player->inv; ip; ip = ip->next) {
723  if (ip->animation_id > 0 && ip->anim_speed) {
724  ip->last_anim++;
725  if (ip->last_anim >= ip->anim_speed) {
726  ip->anim_state++;
728  ip->anim_state = 0;
729  }
730  ip->face = animations[ip->animation_id].faces[ip->anim_state];
731  ip->last_anim = 0;
732  got_one = 1;
733  }
734  }
735  }
736 #ifndef GTK_CLIENT
737  if (got_one) {
738  player->inv_updated = 1;
739  }
740 #endif
741  if (cpl.container) {
742  /* Now do a container if one is active */
743  for (ip = cpl.container->inv; ip; ip = ip->next) {
744  if (ip->animation_id > 0 && ip->anim_speed) {
745  ip->last_anim++;
746  if (ip->last_anim >= ip->anim_speed) {
747  ip->anim_state++;
749  ip->anim_state = 0;
750  }
751  ip->face = animations[ip->animation_id].faces[ip->anim_state];
752  ip->last_anim = 0;
753  got_one = 1;
754  }
755  }
756  }
757  if (got_one) {
759  }
760  } else {
761  /* Now do the map (look window) */
762  for (ip = cpl.below->inv; ip; ip = ip->next) {
763  if (ip->animation_id > 0 && ip->anim_speed) {
764  ip->last_anim++;
765  if (ip->last_anim >= ip->anim_speed) {
766  ip->anim_state++;
768  ip->anim_state = 0;
769  }
770  ip->face = animations[ip->animation_id].faces[ip->anim_state];
771  ip->last_anim = 0;
772  got_one = 1;
773  }
774  }
775  }
776  if (got_one) {
777  cpl.below->inv_updated = 1;
778  }
779  }
780 }
781 
783 {
784  return (it->type == 661);
785 }
786 
787 void inscribe_magical_scroll(item *scroll, Spell *spell)
788 {
789  SockList sl;
790  guint8 buf[MAX_BUF];
791 
792  snprintf((char*)buf, sizeof(buf), "inscribe 0 %d %d", scroll->tag, spell->tag);
793  script_monitor_str((char*)buf);
794  SockList_Init(&sl, buf);
795  SockList_AddString(&sl, "inscribe ");
796  SockList_AddChar(&sl, 0);
797  SockList_AddInt(&sl, scroll->tag);
798  SockList_AddInt(&sl, spell->tag);
799  SockList_Send(&sl, csocket.fd);
800 }
float weight
Definition: item.h:61
Animations animations[MAXANIM]
Definition: commands.c:1127
char s_name[NAME_LEN]
Definition: item.h:56
int num_free_items(void)
Definition: item.c:458
#define copy_name(t, f)
Definition: item.h:43
static void add_item(item *env, item *op)
Definition: item.c:410
int can_write_spell_on(item *it)
Definition: item.c:782
GSocketConnection * fd
Definition: client.h:120
item * create_new_item(item *env, gint32 tag)
Definition: item.c:435
item * locate_item(gint32 tag)
Definition: item.c:300
#define F_LOCKED
Definition: newclient.h:266
void script_monitor_str(const char *command)
Definition: script.c:931
guint8 num_animations
Definition: client.h:100
char flags[NAME_LEN]
Definition: item.h:58
int sc_version
Definition: client.h:121
guint16 inv_updated
Definition: item.h:76
void animate_objects(void)
Definition: item.c:716
void item_event_container_clearing(item *container)
Definition: inventory.c:677
struct item_struct * env
Definition: item.h:53
Warning that something might not work.
Definition: client.h:443
static item * free_items
Definition: item.c:27
void item_event_item_deleting(item *it)
Definition: inventory.c:674
static item * new_item(void)
Definition: item.c:213
struct item_struct * next
Definition: item.h:51
ClientSocket csocket
Definition: client.c:69
static void insert_item_before_item(item *newitem, item *before)
Definition: item.c:72
char p_name[NAME_LEN]
Definition: item.h:57
#define MSG_TYPE_CLIENT
Definition: newclient.h:395
#define NO_ITEM_TYPE
Definition: item.h:45
static item * player
Definition: item.c:28
#define F_DAMNED
Definition: newclient.h:263
#define NDI_BLACK
Definition: newclient.h:221
gint32 tag
Definition: item.h:59
guint32 nrof
Definition: item.h:60
guint16 locked
Definition: item.h:72
void item_event_item_changed(item *it)
Definition: inventory.c:680
static item * alloc_items(int nrof)
Definition: item.c:246
guint16 type
Definition: item.h:81
void LOG(LogLevel level, const char *origin, const char *format,...)
Definition: misc.c:109
#define F_UNPAID
Definition: newclient.h:260
void SockList_AddInt(SockList *sl, guint32 data)
Definition: newsocket.c:80
#define F_BLESSED
Definition: newclient.h:267
void set_item_values(item *op, char *name, gint32 weight, guint16 face, guint16 flags, guint16 anim, guint16 animspeed, guint32 nrof, guint16 type)
Definition: item.c:527
#define F_APPLIED
Definition: newclient.h:258
#define NROF_ITEMS
Definition: item.c:31
char d_name[NAME_LEN]
Definition: item.h:55
#define F_MAGIC
Definition: newclient.h:261
static void set_flag_string(item *op)
Definition: item.c:477
guint16 last_anim
Definition: item.h:66
int SockList_Send(SockList *sl, GSocketConnection *c)
Definition: newsocket.c:112
item * below
Definition: client.h:337
Client_Player cpl
Definition: client.c:68
item * container
Definition: client.h:339
guint8 get_type_from_name(const char *name)
Definition: item.c:42
guint16 was_open
Definition: item.h:75
guint32 flagsval
Definition: item.h:80
void inscribe_magical_scroll(item *scroll, Spell *spell)
Definition: item.c:787
void SockList_AddString(SockList *sl, const char *str)
Definition: newsocket.c:98
void update_item(int tag, int loc, char *name, int weight, int face, int flags, int anim, int animspeed, guint32 nrof, int type)
Definition: item.c:645
#define MAX_BUF
Definition: client.h:40
guint8 apply_type
Definition: item.h:79
guint32 tag
Definition: client.h:299
guint16 animation_id
Definition: item.h:63
void send_mark_obj(item *op)
Definition: item.c:614
guint8 anim_speed
Definition: item.h:64
guint16 unpaid
Definition: item.h:71
#define F_OPEN
Definition: newclient.h:264
void toggle_locked(item *op)
Definition: item.c:596
static void get_flags(item *op, guint16 flags)
Definition: item.c:511
void SockList_AddChar(SockList *sl, char c)
Definition: newsocket.c:43
static const char *const item_types[256][64]
Definition: item-types.h:8
guint16 open
Definition: item.h:74
void print_inventory(item *op)
Definition: item.c:682
int get_info_width(void)
void draw_ext_info(int orig_color, int type, int subtype, const char *message)
Definition: info.c:932
void remove_item_inventory(item *op)
Definition: item.c:393
guint16 * faces
Definition: client.h:107
static item * locate_item_from_item(item *op, gint32 tag)
Definition: item.c:281
void SockList_Init(SockList *sl, guint8 *buf)
Definition: newsocket.c:32
struct item_struct * prev
Definition: item.h:52
#define NUM_ITEM_TYPES
Definition: item-types.h:5
item * map_item(void)
Definition: item.c:637
guint16 damned
Definition: item.h:69
#define MSG_TYPE_CLIENT_DEBUG
Definition: newclient.h:663
guint16 cursed
Definition: item.h:68
guint16 magical
Definition: item.h:67
const char * get_number(guint32 i)
Definition: item.c:190
guint16 applied
Definition: item.h:73
char * name
Definition: image.c:39
guint16 blessed
Definition: item.h:70
gint16 face
Definition: item.h:62
void free_all_items(item *op)
Definition: item.c:264
item * player_item(void)
Definition: item.c:631
guint8 anim_state
Definition: item.h:65
struct item_struct * inv
Definition: item.h:54
void remove_item(item *op)
Definition: item.c:331
static const char *const apply_string[]
Definition: item.c:473
#define F_CURSED
Definition: newclient.h:262
void update_item_sort(item *it)
Definition: item.c:91
static item * map
Definition: item.c:28