Crossfire Server, Trunk  1.75.0
cfanim.cpp
Go to the documentation of this file.
1 /*****************************************************************************/
2 /* Crossfire Animator v2.0a */
3 /* Contacts: yann.chachkoff@myrealbox.com, tchize@myrealbox.com */
4 /*****************************************************************************/
5 /* That code is placed under the GNU General Public Licence (GPL) */
6 /* */
7 /* (C) 2001 David Delbecq for the original code version. */
8 /*****************************************************************************/
9 /* CrossFire, A Multiplayer game for X-windows */
10 /* */
11 /* Copyright (C) 2000 Mark Wedel */
12 /* Copyright (C) 1992 Frank Tore Johansen */
13 /* */
14 /* This program is free software; you can redistribute it and/or modify */
15 /* it under the terms of the GNU General Public License as published by */
16 /* the Free Software Foundation; either version 2 of the License, or */
17 /* (at your option) any later version. */
18 /* */
19 /* This program is distributed in the hope that it will be useful, */
20 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
21 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
22 /* GNU General Public License for more details. */
23 /* */
24 /* You should have received a copy of the GNU General Public License */
25 /* along with this program; if not, write to the Free Software */
26 /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
27 /* */
28 /*****************************************************************************/
29 
30 /* First let's include the header file needed */
31 
32 #include <assert.h>
33 #include <stdarg.h>
34 #include <stdlib.h>
35 #include <string.h>
36 
37 #include "cfanim.h"
38 #include "svnversion.h"
39 
41 
42 static CFanimation *first_animation = NULL;
44 static int get_boolean(const char *strg, int *bl);
45 
51 static int get_dir_from_name(const char *name) {
52  if (!strcmp(name, "north"))
53  return 1;
54  if (!strcmp(name, "north_east"))
55  return 2;
56  if (!strcmp(name, "east"))
57  return 3;
58  if (!strcmp(name, "south_east"))
59  return 4;
60  if (!strcmp(name, "south"))
61  return 5;
62  if (!strcmp(name, "south_west"))
63  return 6;
64  if (!strcmp(name, "west"))
65  return 7;
66  if (!strcmp(name, "north_west"))
67  return 8;
68  return -1;
69 }
70 
71 static long int initmovement(const char *name, char *parameters, CFmovement *move_entity) {
72  int dir;
73  (void)parameters;
74 
75  dir = get_dir_from_name(name);
76  move_entity->parameters = NULL;
77  return dir;
78 }
79 
80 static anim_move_result runmovement(CFanimation *animation, long int id, void *parameters) {
81  object *op = animation->victim;
82  int dir = id;
83  (void)parameters;
84 
85  if (animation->verbose)
86  cf_log(llevDebug, "CFAnim: Moving in direction %ld\n", id);
87  if (op->type == PLAYER)
88  cf_player_move(op->contr, dir);
89  else
90  cf_object_move(op, dir, op);
91  return mr_finished;
92 }
93 
94 static long int initfire(const char *name, char *parameters, CFmovement *move_entity) {
95  int dir;
96  (void)parameters;
97 
98  dir = get_dir_from_name(&(name[5]));
99  move_entity->parameters = NULL;
100  return dir;
101 }
102 
104 static anim_move_result runfire(CFanimation *animation, long int id, void *parameters) {
105  (void)parameters;
106  if (animation->verbose)
107  cf_log(llevDebug, "CFAnim: Firing in direction %ld\n", id);
108  return mr_finished;
109 }
110 
111 static long int initturn(const char *name, char *parameters, CFmovement *move_entity) {
112  int dir;
113  (void)parameters;
114 
115  dir = get_dir_from_name(&(name[5]));
116  move_entity->parameters = NULL;
117  return dir;
118 }
119 
120 static anim_move_result runturn(CFanimation *animation, long int id, void *parameters) {
121  object *op = animation->victim;
122  int dir = id;
123  (void)parameters;
124  /*int face;*/
125 
126  if (animation->verbose)
127  cf_log(llevDebug, "CFAnim: Turning in direction %ld\n", id);
128  op->facing = dir;
130 /* cf_object_set_int_property(op, CFAPI_OBJECT_PROP_ANIMATION, face);*/
131  return mr_finished;
132 }
133 
134 static long int initcamera(const char *name, char *parameters, CFmovement *move_entity) {
135  int dir;
136  (void)parameters;
137 
138  dir = get_dir_from_name(&(name[7]));
139  move_entity->parameters = NULL;
140  return dir;
141 }
142 
144 static anim_move_result runcamera(CFanimation *animation, long int id, void *parameters) {
145  (void)parameters;
146  if (animation->verbose)
147  cf_log(llevDebug, "CFAnim: Moving the camera in direction %ld\n", id);
148  return mr_finished;
149  /*if (animation->victim->type == PLAYER)
150  hook_scroll_map(animation->victim, id);
151  else
152  printf("CFAnim: Not a player\n");
153  return 1;*/
154 }
155 
156 static long int initvisible(const char *name, char *parameters, CFmovement *move_entity) {
157  int result;
158  (void)name;
159  (void)move_entity;
160 
161  if (get_boolean(parameters, &result))
162  return result;
163  cf_log(llevError, "CFAnim: Error in animation - possible values for 'invisible' are 'yes' and 'no'\n");
164  return -1;
165 }
166 
167 static anim_move_result runvisible(CFanimation *animation, long int id, void *parameters) {
168  (void)parameters;
169  if (id == -1)
170  return mr_finished;
171  animation->invisible = id;
172  return mr_finished;
173 }
174 
175 static long int initwizard(const char *name, char *parameters, CFmovement *move_entity) {
176  int result;
177  (void)name;
178  (void)move_entity;
179 
180  if (get_boolean(parameters, &result))
181  return result;
182  cf_log(llevError, "CFAnim: Error in animation - possible values for 'wizard' are 'yes' and 'no'\n");
183  return mr_finished;
184 }
185 
186 static anim_move_result runwizard(CFanimation *animation, long int id, void *parameters) {
187  (void)parameters;
188  if (id == -1)
189  return mr_finished;
190  animation->wizard = id;
191  return mr_finished;
192 }
193 
194 static long int initsay(const char *name, char *parameters, CFmovement *move_entity) {
195  (void)name;
196  if (parameters)
197  move_entity->parameters = cf_strdup_local(parameters);
198  else
199  move_entity->parameters = NULL;
200  if (move_entity->parent->verbose)
201  cf_log(llevDebug, "CFAnim: init say: parameters: %s\n", parameters ? parameters : "null");
202  return 1;
203 }
204 
205 static anim_move_result runsay(CFanimation *animation, long int id, void *parameters) {
206  (void)id;
207  if (parameters) {
208  cf_object_say(animation->victim, static_cast<const char *>(parameters));
209  free(parameters);
210  } else
211  cf_log(llevError, "CFAnim: Error in animation: nothing to say with say function\n");
212  return mr_finished;
213 }
214 
215 static long int initapply(const char *name, char *parameters, CFmovement *move_entity) {
216  (void)name;
217  (void)parameters;
218  (void)move_entity;
219  return 1;
220 }
221 
222 static anim_move_result runapply(CFanimation *animation, long int id, void *parameters) {
223  object *current_container;
224  (void)id;
225  (void)parameters;
226 
227  if (animation->victim->type != PLAYER)
228  return mr_finished;
229  current_container = animation->victim->container;
230  animation->victim->container = NULL;
231  cf_object_apply_below(animation->victim);
232  animation->victim->container = current_container;
233  return mr_finished;
234 }
235 
236 static long int initapplyobject(const char *name, char *parameters, CFmovement *move_entity) {
237  (void)name;
238  move_entity->parameters = parameters ? (void*)cf_add_string(static_cast<sstring>(parameters)) : NULL;
239  return 1;
240 }
241 
242 static anim_move_result runapplyobject(CFanimation *animation, long int id, void *parameters) {
243  object *current;
244  int aflag;
245  (void)id;
246 
247  if (!parameters)
248  return mr_finished;
249  current = animation->victim->below;
250  FOR_OB_AND_BELOW_PREPARE(current) {
251  if (current->name == parameters)
252  break;
253  }
255  if (!current)
256  current = cf_object_find_by_name(animation->victim, static_cast<char *>(parameters));
257  if (!current) {
258  cf_free_string(static_cast<sstring>(parameters));
259  return mr_finished;
260  }
261  aflag = AP_APPLY;
262  cf_object_apply(animation->victim, current, aflag);
263  cf_free_string(static_cast<sstring>(parameters));
264  return mr_finished;
265 }
266 
267 static long int initdropobject(const char *name, char *parameters, CFmovement *move_entity) {
268  (void)name;
269  move_entity->parameters = parameters ?
270  (void *)cf_add_string(static_cast<sstring>(parameters)) : NULL;
271  return 1;
272 }
273 
274 static anim_move_result rundropobject(CFanimation *animation, long int id, void *parameters) {
275  object *what;
276  (void)id;
277  if (!parameters)
278  return mr_finished;
279  what = cf_object_find_by_name(animation->victim, static_cast<sstring>(parameters));
280  if (what != NULL)
281  cf_object_drop(what, animation->victim);
282  cf_free_string(static_cast<sstring>(parameters));
283  return mr_finished;
284 }
285 
286 static long int initpickup(const char *name, char *parameters, CFmovement *move_entity) {
287  (void)name;
288  (void)parameters;
289  (void)move_entity;
290  return 1;
291 }
292 
293 static anim_move_result runpickup(CFanimation *animation, long int id, void *parameters) {
294  object *current;
295  (void)id;
296  (void)parameters;
297 
298  current = animation->victim->below;
299  if (!current)
300  return mr_finished;
301  cf_object_pickup(animation->victim, current);
302  return mr_finished;
303 }
304 
305 static long int initpickupobject(const char *name, char *parameters, CFmovement *move_entity) {
306  (void)name;
307  move_entity->parameters = parameters ? (void*)cf_add_string(static_cast<sstring>(parameters)) : NULL;
308  return 1;
309 }
310 
311 static anim_move_result runpickupobject(CFanimation *animation, long int id, void *parameters) {
312  (void)id;
313  if (!parameters)
314  return mr_finished;
315  FOR_BELOW_PREPARE(animation->victim, current)
316  if (current->name == parameters) {
317  cf_object_pickup(animation->victim, current);
318  break;
319  }
321  cf_free_string(static_cast<sstring>(parameters));
322  return mr_finished;
323 }
324 
325 static long int initghosted(const char *name, char *parameters, CFmovement *move_entity) {
326  int result;
327  (void)name;
328  (void)move_entity;
329 
330  if (get_boolean(parameters, &result))
331  return result;
332  cf_log(llevError, "CFAnim: Error in animation: possible values for 'ghosted' are 'yes' and 'no'\n");
333  return -1;
334 }
335 
336 static anim_move_result runghosted(CFanimation *animation, long int id, void *parameters) {
337  object *corpse;
338 
339  if ((id && animation->ghosted)
340  || (!id && !animation->ghosted))
341  runghosted(animation, !id, parameters);
342  if (id) { /*Create a ghost/corpse pair*/
343  corpse = cf_object_clone(animation->victim, 1);
344  corpse->x = animation->victim->x;
345  corpse->y = animation->victim->y;
346  corpse->type = 0;
347  CLEAR_FLAG(corpse, FLAG_WIZ);
348  corpse->contr = NULL;
349  cf_map_insert_object_there(corpse, animation->victim->map, NULL, 0);
350  animation->wizard = 1;
351  animation->invisible = 1;
352  animation->corpse = corpse;
353  } else { /*Remove a corpse, make current player visible*/
354  animation->wizard = 0;
355  animation->invisible = 0;
356  cf_object_remove(animation->corpse);
358  animation->corpse = NULL;
359  animation->victim->invisible = 0;
360  cf_player_move(animation->victim->contr, 0);
361  }
362  animation->ghosted = id;
363  return mr_finished;
364 }
365 
367  char *mapname;
368  int mapx;
369  int mapy;
370 };
371 
372 static long int initteleport(const char *name, char *parameters, CFmovement *move_entity) {
373  char *mapname;
374  int mapx;
375  int mapy;
377  (void)name;
378 
379  move_entity->parameters = NULL;
380  cf_log(llevDebug, ".(%s)\n", parameters);
381  if (!parameters) {
382  cf_log(llevError, "CFAnim: Error - no parameters for teleport\n");
383  return 0;
384  }
385  mapname = strstr(parameters, " ");
386  cf_log(llevDebug, ".(%s)\n", parameters);
387  if (!mapname)
388  return 0;
389  *mapname = '\0';
390  mapx = atoi(parameters);
391  mapname++;
392  parameters = mapname;
393  assert(parameters != NULL);
394  cf_log(llevDebug, ".(%s)\n", parameters);
395  mapname = strstr(parameters, " ");
396  cf_log(llevDebug, ".\n");
397  if (!mapname)
398  return 0;
399  *mapname = '\0';
400  mapy = atoi(parameters);
401  mapname++;
402  if (mapname[0] == '\0')
403  return 0;
404  teleport = (teleport_params *)malloc(sizeof(teleport_params));
405  teleport->mapname = cf_strdup_local(mapname);
406  teleport->mapx = mapx;
407  teleport->mapy = mapy;
408  move_entity->parameters = teleport;
409  return 1;
410 }
411 
412 static anim_move_result runteleport(CFanimation *animation, long int id, void *parameters) {
413  teleport_params *teleport = (teleport_params *)parameters;
414  (void)id;
415 
416  if (!parameters)
417  return mr_finished;
418  cf_object_teleport(animation->victim, cf_map_get_map(teleport->mapname, 0), teleport->mapx, teleport->mapy);
419  free(parameters);
420  return mr_finished;
421 }
422 
423 static long int initnotice(const char *name, char *parameters, CFmovement *move_entity) {
424  (void)name;
425  move_entity->parameters = parameters ? cf_strdup_local(parameters) : NULL;
426  return 1;
427 }
428 static anim_move_result runnotice(CFanimation *animation, long int id, void *parameters) {
429  int val;
430  (void)id;
431 
432  val = NDI_NAVY|NDI_UNIQUE;
433 
434  cf_player_message(animation->victim, static_cast<char *>(parameters), val);
435  return mr_finished;
436 }
437 
438 static long int initstop(const char *name, char *parameters, CFmovement *move_entity) {
439  (void)name;
440  (void)parameters;
441  (void)move_entity;
442  return 1;
443 }
444 
446 static anim_move_result runstop(CFanimation *animation, long int id, void *parameters) {
447  (void)id;
448  (void)parameters;
449  if (animation->verbose)
450  cf_log(llevDebug, "CFAnim: stop encountered\n");
451  return mr_finished;
452 }
453 
455 struct param_moveto {
456  int x, y;
457 };
458 
459 static long int initmoveto(const char *name, char *parameters, CFmovement *move_entity) {
460  param_moveto *moveto;
461  int x, y;
462  (void)name;
463 
464  if (sscanf(parameters, "%d %d", &x, &y) != 2)
465  return 0;
466 
467  moveto = (param_moveto *)calloc(1, sizeof(param_moveto));
468  moveto->x = x;
469  moveto->y = y;
470  move_entity->parameters = moveto;
471 
472  return 1;
473 }
474 
475 static anim_move_result runmoveto(CFanimation *animation, long int id, void *parameters) {
476  int move;
477  param_moveto *dest = (param_moveto *)parameters;
478  (void)id;
479 
480  if (!dest)
481  return mr_finished;
482 
483  move = cf_object_move_to(animation->victim, dest->x, dest->y);
484 
485  if (animation->victim->x == dest->x && animation->victim->y == dest->y) {
486  free(parameters);
487  return mr_finished;
488  }
489 
490  if (move == 1)
491  return mr_again;
492 
493  return mr_finished;
494 }
495 
496 static long int initmessage(const char *name, char *parameters, CFmovement *move_entity) {
497  (void)name;
498  if (parameters)
499  move_entity->parameters = strdup(parameters);
500  else
501  move_entity->parameters = NULL;
502  return 1;
503 }
504 
505 static anim_move_result runmessage(CFanimation *animation, long int id, void *parameters) {
506  (void)id;
507  if (parameters && animation->victim->map) {
508  cf_map_message(animation->victim->map, (const char *)parameters, NDI_UNIQUE|NDI_GREEN);
509  free(parameters);
510  }
511 
512  return mr_finished;
513 }
514 
515 static long int inittrigger(const char *name, char *parameters, CFmovement *move_entity) {
516  long int connection;
517  (void)name;
518 
519  move_entity->parameters = NULL;
520  if (sscanf(parameters, "%ld", &connection) != 1 || connection <= 0) {
521  cf_log(llevError, "CFAnim: invalid connection %s\n", parameters);
522  return 0;
523  }
524  return connection;
525 }
526 
527 static anim_move_result runtrigger(CFanimation *animation, long int id, void *parameters) {
528  oblinkpt *olp;
529  mapstruct *map;
530  objectlink *ol = NULL;
531  (void)parameters;
532 
533  if (animation->victim == NULL || animation->victim->map == NULL) {
534  cf_log(llevError, "CFAnim: trigger for victim not on map or NULL.\n");
535  return mr_finished;
536  }
537 
538  map = animation->victim->map;
539 
540  /* locate objectlink for this connected value */
541  if (!map->buttons) {
542  cf_log(llevError, "Map %s called for trigger on connected %d but there ain't any button list for that map!\n", cf_map_get_sstring_property(map, CFAPI_MAP_PROP_PATH), id);
543  return mr_finished;
544  }
545  for (olp = map->buttons; olp; olp = olp->next) {
546  if (olp->value == id) {
547  ol = olp->link;
548  break;
549  }
550  }
551  if (ol == NULL) {
552  cf_log(llevError, "Map %s called for trigger on connected %d but there ain't any button list for that map!\n", cf_map_get_sstring_property(map, CFAPI_MAP_PROP_PATH), id);
553  return mr_finished;
554  }
555  /* run the object link */
556  cf_map_trigger_connected(ol, NULL, 1);
557 
558  return mr_finished;
559 }
560 
563  { "north", initmovement, runmovement },
564  { "north_east", initmovement, runmovement },
565  { "east", initmovement, runmovement },
566  { "south_east", initmovement, runmovement },
567  { "south", initmovement, runmovement },
568  { "south_west", initmovement, runmovement },
569  { "west", initmovement, runmovement },
570  { "north_west", initmovement, runmovement },
571  { "fire_north", initfire, runfire },
572  { "fire_north_east", initfire, runfire },
573  { "fire_east", initfire, runfire },
574  { "fire_south_east", initfire, runfire },
575  { "fire_south", initfire, runfire },
576  { "fire_south_west", initfire, runfire },
577  { "fire_west", initfire, runfire },
578  { "fire_north_west", initfire, runfire },
579  { "turn_north", initturn, runturn },
580  { "turn_north_east", initturn, runturn },
581  { "turn_east", initturn, runturn },
582  { "turn_south_east", initturn, runturn },
583  { "turn_south", initturn, runturn },
584  { "turn_south_west", initturn, runturn },
585  { "turn_west", initturn, runturn },
586  { "turn_north_west", initturn, runturn },
587  { "camera_north", initcamera, runcamera },
588  { "camera_north_east", initcamera, runcamera },
589  { "camera_east", initcamera, runcamera },
590  { "camera_south_east", initcamera, runcamera },
591  { "camera_south", initcamera, runcamera },
592  { "camera_south_west", initcamera, runcamera },
593  { "camera_west", initcamera, runcamera },
594  { "camera_north_west", initcamera, runcamera },
595  { "invisible", initvisible, runvisible },
596  { "wizard", initwizard, runwizard },
597  { "say", initsay, runsay },
598  { "apply", initapply, runapply },
599  { "apply_object", initapplyobject, runapplyobject },
600  { "drop_object", initdropobject, rundropobject },
601  { "pickup", initpickup, runpickup },
602  { "pickup_object", initpickupobject, runpickupobject },
603  { "ghosted", initghosted, runghosted },
604  { "teleport", initteleport, runteleport },
605  { "notice", initnotice, runnotice },
606  { "stop", initstop, runstop },
607  { "moveto", initmoveto, runmoveto },
608  { "message", initmessage, runmessage },
609  { "trigger", inittrigger, runtrigger }
610 };
611 
613 
614 static int ordered_commands = 0;
615 
616 static int compareAnims(const void *a, const void *b) {
617  return strcmp(((const CFanimationHook *)a)->name, ((const CFanimationHook *)b)->name);
618 }
619 
620 static void prepare_commands(void) {
622  ordered_commands = 1;
623 }
624 
626  CFanimationHook dummy;
627 
628  dummy.name = command;
629  if (!ordered_commands)
631  return (CFanimationHook *)bsearch(&dummy, animationbox, animationcount, sizeof(CFanimationHook), compareAnims);
632 }
633 
642 static CFmovement *parse_animation_block(char *buffer, size_t buffer_size, FILE *fichier, CFanimation *parent) {
643  CFmovement *first = NULL;
644  CFmovement *current = NULL;
645  CFmovement *next;
646  char *time;
647  char *name;
648  char *parameters;
649  int tick;
650  CFanimationHook *animationhook;
651 
652  if (parent->verbose)
653  cf_log(llevDebug, "CFAnim: In parse block for %s\n", buffer);
654  while (fgets(buffer, buffer_size, fichier)) {
655  if (buffer[0] == '[')
656  break;
657  if (buffer[0] == '#')
658  continue;
659  buffer[strlen(buffer)-strlen("\n")] = '\0';
660  while (buffer[strlen(buffer)-1] == ' ')
661  buffer[strlen(buffer)-1] = '\0';
662  if (strlen(buffer) <= 0)
663  continue;
664  time = buffer;
665 
666  name = strstr(buffer, " ");
667  if (!name)
668  continue;
669  *name = '\0';
670  name++;
671  while (*name == ' ')
672  name++;
673 
674  tick = atoi(time);
675  if (tick < 0)
676  continue;
677 
678  parameters = strstr(name, " ");
679  if (parameters) { /*Parameters may be nul*/
680  *parameters = '\0';
681  parameters++;
682  while (*parameters == ' ')
683  parameters++;
684  if (*parameters == '\0')
685  parameters = NULL;
686  }
687  animationhook = get_command(name);
688  if (!animationhook)
689  cf_log(llevError, "CFAnim: %s - Unknown animation command\n", name);
690  else if (parent->verbose) {
691  cf_log(llevDebug, "CFAnim: Parsed %s -> %p\n", name, animationhook);
692  }
693  if (!animationhook) {
694  if (parent->errors_allowed)
695  continue;
696  else
697  break;
698  }
699  next = (CFmovement *)malloc(sizeof(CFmovement));
700  if (!next)
701  continue;
702  next->parent = parent;
703  next->tick = tick;
704  next->next = NULL;
705  if (animationhook->funcinit)
706  next->id = animationhook->funcinit(name, parameters, next);
707  next->func = animationhook->funcrun;
708  if (current)
709  current->next = next;
710  else
711  first = next;
712  current = next;
713  }
714  return first;
715 }
716 
727 static int equality_split(char *buffer, char **variable, char **value) {
728  if (!strcmp(&buffer[strlen(buffer)-strlen("\n")], "\n"))
729  buffer[strlen(buffer)-strlen("\n")] = '\0';
730  *value = strstr(buffer, "=");
731  if (!*value)
732  return 0;
733  **value = '\0';
734  *variable = buffer;
735  (*value)++;
736  while ((strlen(*variable) > 0) && ((*variable)[strlen(*variable)-1] == ' '))
737  (*variable)[strlen(*variable)-1] = '\0';
738  while ((strlen(*value) > 0) && ((*value)[strlen(*value)-1] == ' '))
739  (*value)[strlen(*value)-1] = '\0';
740  while (**value == ' ')
741  (*value)++;
742  if ((**variable == '\0') || (**value == '\0'))
743  return 0;
744  return 1;
745 }
746 
758 static int get_boolean(const char *strg, int *bl) {
759  /*
760  * We're only parsing the first character, so we
761  * really don't need to call strncmp().
762  * Should future checks need to check multiple characters,
763  * strncmp() would be a good choice. For that reason,
764  * I won't optimize this down to a switch statement.
765  * It makes it clearer how to handle multi-character checks.
766  */
767  if (*strg == 'y')
768  *bl = 1;
769  else if (*strg == 'n')
770  *bl = 0;
771  else if (*strg == 'Y')
772  *bl = 1;
773  else if (*strg == 'N')
774  *bl = 0;
775  else if (*strg == '1')
776  *bl = 1;
777  else if (*strg == '0')
778  *bl = 0;
779  else
780  return 0;
781  return 1;
782 }
783 
789 static int is_animated_object(const object *ob) {
790  CFanimation *current;
791 
792  for (current = first_animation; current; current = current->nextanimation)
793  if (current->victim == ob) {
794  return 1;
795  }
796  return 0;
797 }
798 
804  CFanimation *anim;
805  CFanimation *current;
806 
807  anim = (CFanimation *)malloc(sizeof(CFanimation));
808  if (!anim)
809  return NULL;
810  anim->name = NULL;
811  anim->victim = NULL;
812  anim->event = NULL;
813  anim->nextmovement = NULL;
814  anim->nextanimation = NULL;
815  anim->delete_end = 0;
816  for (current = first_animation; (current && current->nextanimation); current = current->nextanimation)
817  ;
818  if (!current)
819  first_animation = anim;
820  else
821  current->nextanimation = anim;
822  return anim;
823 }
824 
825 static object *find_by_name(object *origin, const char *name) {
826  int x, y, w, h;
827  mapstruct *map;
828  const char *sname;
829 
830  sname = cf_find_string(name);
831  if (!sname)
832  return NULL;
833 
834  while (origin && !origin->map)
835  origin = origin->env;
836 
837  if (!origin || !origin->map)
838  return NULL;
839 
840  map = origin->map;
841 
842  w = cf_map_get_width(map);
843  h = cf_map_get_height(map);
844 
845  for (x = 0; x < w; x++) {
846  for (y = 0; y < h; y++) {
847  FOR_MAP_PREPARE(map, x, y, ob) {
848  if (/*cf_object_get_sstring_property(ob, CFAPI_OBJECT_PROP_NAME)*/ob->name == sname)
849  return ob;
850  } FOR_MAP_FINISH();
851  }
852  }
853 
854  return NULL;
855 }
856 
868 static int start_animation(object *who, object *activator, object *event, const char *file, const char *message) {
869  FILE *fichier;
870  char *name = NULL;
871  int victimtype = 0;
872  object *victim = NULL;
873  int unique = 0;
874  int always_delete = 0;
875  int delete_end = 0;
876  int parallel = 0;
877  int paralyzed = 1;
878  int invisible = 0;
879  int wizard = 0;
880  enum time_enum timetype = time_second;
881  int errors_allowed = 0;
882  int verbose = 0;
883  const char *animationitem = NULL;
884  char buffer[HUGE_BUF];
885  char *variable;
886  char *value;
887  int errors_found = 0;
888  CFanimation *current_anim;
889 
890  fichier = fopen(file, "r");
891  if (fichier == NULL) {
892  cf_log(llevDebug, "CFAnim: Unable to open %s\n", file);
893  return 0;
894  }
895  while (fgets(buffer, HUGE_BUF, fichier)) {
896  if (buffer[0] == '[')
897  break;
898  if (buffer[0] == '#')
899  continue;
900  if (!strcmp(buffer, "\n"))
901  continue;
902  errors_found = 1;
903  cf_log(llevError, "CFAnim: '%s' has an invalid syntax.\n", buffer);
904  }
905  if (feof(fichier)) {
906  fclose(fichier);
907  return 0;
908  }
909  if (strncmp(buffer, "[Config]", 8)) {
910  cf_log(llevError, "CFAnim: Fatal error in %s: [Config] must be the first group defined.\n", file);
911  fclose(fichier);
912  return 0;
913  }
914  while (fgets(buffer, HUGE_BUF, fichier)) {
915  if (buffer[0] == '[')
916  break;
917  if (buffer[0] == '#')
918  continue;
919  if (!strcmp(buffer, "\n"))
920  continue;
921  if (!equality_split(buffer, &variable, &value))
922  errors_found = 1;
923  else {
924  if (!strcmp(variable, "name")) {
925  if (*value == '"')
926  value++;
927  if (value[strlen(value)-1] == '"')
928  value[strlen(value)-1] = '\0';
929  name = cf_strdup_local(value);
930  } else if (!strcmp(variable, "victimtype")) {
931  if (!strcmp(value, "player"))
932  victimtype = 0;
933  else if (!strcmp(value, "object"))
934  victimtype = 1;
935  else if (!strcmp(value, "any"))
936  victimtype = 2;
937  else if (!strcmp(value, "byname"))
938  victimtype = 3;
939  else
940  errors_found = 1;
941  } else if (!strcmp(variable, "victim")) {
942  cf_log(llevDebug, "CFAnim: Setting victim to %s\n", value);
943  if (!strcmp(value, "who"))
944  victim = who;
945  else if (!strcmp(value, "activator"))
946  victim = activator;
947  else if (!strcmp(value, "who_owner"))
948  if (!who) {
949  errors_found = 1;
950  cf_log(llevError, "CFAnim: Warning: object \"who\" doesn't exist and you're victimized it's owner\n");
951  } else
952  victim = who->env;
953  else if (!strcmp(value, "activator_owner"))
954  if (!activator) {
955  errors_found = 1;
956  cf_log(llevError, "CFAnim: Warning: object \"activator\" doesn't exist and you're victimized it's owner\n");
957  } else
958  victim = activator->env;
959  else if (victimtype == 3) {
960  victim = find_by_name(who, value);
961  } else
962  errors_found = 1;
963  } else if (!strcmp(variable, "unique")) {
964  if (!get_boolean(value, &unique))
965  errors_found = 1;
966  } else if (!strcmp(variable, "always_delete")) {
967  if (!get_boolean(value, &always_delete))
968  errors_found = 1;
969  } else if (!strcmp(variable, "delete_event_end")) {
970  if (!get_boolean(value, &delete_end))
971  errors_found = 1;
972  } else if (!strcmp(variable, "parallel")) {
973  if (!get_boolean(value, &parallel))
974  errors_found = 1;
975  } else if (!strcmp(variable, "paralyzed")) {
976  if (!get_boolean(value, &paralyzed))
977  errors_found = 1;
978  } else if (!strcmp(variable, "invisible")) {
979  if (!get_boolean(value, &invisible))
980  errors_found = 1;
981  } else if (!strcmp(variable, "wizard")) {
982  if (!get_boolean(value, &wizard))
983  errors_found = 1;
984  } else if (!strcmp(variable, "errors_allowed")) {
985  if (!get_boolean(value, &errors_allowed))
986  errors_found = 1;
987  } else if (!strcmp(variable, "verbose")) {
988  if (!get_boolean(value, &verbose))
989  errors_found = 1;
990  } else if (!strcmp(variable, "time_representation")) {
991  if (!strcmp(value, "second"))
992  timetype = time_second;
993  else if (!strcmp(value, "tick"))
994  timetype = time_tick;
995  else
996  errors_found = 1;
997  } else if (!strcmp(variable, "animation")) {
998  animationitem = cf_add_string(value);
999  } else
1000  errors_found = 1;
1001  }
1002  }
1003 
1004  if (message && message[0] != '\0') {
1005  cf_free_string(animationitem);
1006  animationitem = cf_add_string(message);
1007  }
1008 
1009  if (buffer[0] == '\0') {
1010  if (animationitem)
1011  cf_free_string(animationitem);
1012  cf_log(llevError, "CFAnim: Errors occurred during the parsing of %s\n", file);
1013  fclose(fichier);
1014  return 0;
1015  }
1016  if (!animationitem) {
1017  cf_log(llevError, "CFAnim: no animation specified when using %s\n", file);
1018  fclose(fichier);
1019  return 0;
1020  }
1021  if (!victim) {
1022  if (animationitem)
1023  cf_free_string(animationitem);
1024  cf_log(llevError, "CFAnim: Fatal error - victim is NULL");
1025  fclose(fichier);
1026  return 0;
1027  }
1028  if (!(current_anim = create_animation())) {
1029  if (animationitem)
1030  cf_free_string(animationitem);
1031  cf_log(llevError, "CFAnim: Fatal error - Not enough memory.\n");
1032  fclose(fichier);
1033  return 0;
1034  }
1035  if (always_delete) {
1036  /*if (verbose) printf("CFAnim: Freeing event nr. %d for %s.\n", current_event, who->name);*/
1037  cf_object_remove(event);
1038  event = NULL;
1039  }
1040  if (((victim->type == PLAYER) && (victimtype == 1))
1041  || ((victim->type != PLAYER) && (victimtype == 0))
1042  || (errors_found && !errors_allowed)) {
1043  if (verbose)
1044  cf_log(llevError, "CFAnim: No correct victim found or errors found, aborting.\n");
1045  if (animationitem)
1046  cf_free_string(animationitem);
1047  free(current_anim);
1048  fclose(fichier);
1049  return 0;
1050  }
1051  if (unique && !always_delete) {
1052  /*if (verbose) printf("CFAnim: Freeing event nr. %d for %s.\n", current_event, who->name);*/
1053  cf_object_remove(event);
1054  event = NULL;
1055  }
1056  current_anim->name = name;
1057  current_anim->victim = victim;
1058  current_anim->event = event;
1059  current_anim->paralyze = paralyzed;
1060  current_anim->invisible = invisible;
1061  current_anim->wizard = wizard;
1062  current_anim->unique = unique;
1063  current_anim->delete_end = delete_end;
1064  current_anim->ghosted = 0;
1065  current_anim->corpse = NULL;
1066  current_anim->time_representation = timetype;
1067  current_anim->verbose = verbose;
1068  current_anim->tick_left = 0;
1069  current_anim->errors_allowed = errors_allowed;
1070 
1071  while (buffer[0] == '[') {
1072  while (strncmp(&buffer[1], animationitem, strlen(animationitem))) {
1073  while ((value = fgets(buffer, HUGE_BUF, fichier)) != NULL)
1074  if (buffer[0] == '[')
1075  break;
1076  if (value == NULL) {
1077  cf_log(llevError, "CFAnim: no matching animation %s in file.\n", animationitem);
1078  cf_free_string(animationitem);
1079  fclose(fichier);
1080  return 0;
1081  }
1082  }
1083  current_anim->nextmovement = parse_animation_block(buffer, HUGE_BUF, fichier, current_anim);
1084  if (current_anim->nextmovement)
1085  break;
1086  }
1087  fclose(fichier);
1088  return 1;
1089 }
1090 
1096 static void animate_one(CFanimation *animation, long int milliseconds) {
1097  CFmovement *current;
1098  int mult = 1;
1099  anim_move_result result;
1100 
1101  if (animation->time_representation == time_second) {
1102  animation->tick_left += milliseconds;
1103  mult = 1000;
1104  } else
1105  animation->tick_left++;
1106 
1107  if (animation->verbose)
1108  cf_log(llevDebug, "CFAnim: Ticking %s for %s. Tickleft is %ld\n", animation->name, animation->victim->name, animation->tick_left);
1109  if (animation->invisible)
1110  animation->victim->invisible = 10;
1111  if (animation->wizard && animation->victim->type == PLAYER) {
1112  /* setting FLAG_WIZ *on non player leads to issues, as many functions expect contr to not be NULL in this case. */
1113  if (animation->verbose)
1114  cf_log(llevDebug, "CFAnim: Setting wizard flags\n");
1115  cf_object_set_flag(animation->victim, FLAG_WIZPASS, 1);
1116  cf_object_set_flag(animation->victim, FLAG_WIZCAST, 1);
1117  cf_object_set_flag(animation->victim, FLAG_WIZ, 1);
1118  if (animation->verbose)
1119  cf_log(llevDebug, "CFAnim: Setting wizard flags done\n");
1120 
1121  }
1122  if (animation->paralyze)
1123  animation->victim->speed_left = -99999;
1124 
1125  cf_object_update(animation->victim, UP_OBJ_CHANGE);
1126 
1127  if (animation->nextmovement)
1128  while (animation->tick_left > animation->nextmovement->tick*mult) {
1129  animation->tick_left -= animation->nextmovement->tick*mult;
1130  result = animation->nextmovement->func(animation, animation->nextmovement->id, animation->nextmovement->parameters);
1131  if (result == mr_again)
1132  continue;
1133 
1134  current = animation->nextmovement;
1135  animation->nextmovement = animation->nextmovement->next;
1136  free(current);
1137  if (!animation->nextmovement)
1138  break;
1139  }
1140  cf_object_set_flag(animation->victim, FLAG_WIZPASS, 0);
1141  cf_object_set_flag(animation->victim, FLAG_WIZCAST, 0);
1142  cf_object_set_flag(animation->victim, FLAG_WIZ, 0);
1143 }
1144 
1149 long usec_elapsed(struct timespec first, struct timespec second) {
1150  time_t sec_elapsed = second.tv_sec - first.tv_sec;
1151  long nsec_elapsed = second.tv_nsec - first.tv_nsec;
1152  return (sec_elapsed * 1e6) + (nsec_elapsed / 1e3);
1153 }
1154 
1158 static void animate(void) {
1159  CFanimation *current;
1160  CFanimation *next;
1161  CFanimation *previous_anim = NULL;
1162  struct timespec now;
1163  static struct timespec yesterday;
1164  static int already_passed = 0;
1165  long int delta_milli;
1166 
1167  clock_gettime(CLOCK_MONOTONIC, &now);
1168  if (!already_passed) {
1169  already_passed = 1;
1170  yesterday = now;
1171  return;
1172  }
1173  delta_milli = usec_elapsed(yesterday, now) / 1e3;
1174  /*printf("Working for %ld milli seconds\n", delta_milli);*/
1175  yesterday = now;
1176  for (current = first_animation; current; current = current->nextanimation)
1177  animate_one(current, delta_milli);
1178  current = first_animation;
1179  while (current) {
1180  if (!current->nextmovement) {
1181  if (current->paralyze)
1182  current->victim->speed_left = current->victim->speed;
1183  next = current->nextanimation;
1184  if (first_animation == current)
1185  first_animation = next;
1186  else {
1187  previous_anim->nextanimation = next;
1188  }
1189  if (current->delete_end && current->event != NULL)
1190  cf_object_remove(current->event);
1191  free(current->name);
1192  free(current);
1193  current = next;
1194  } else {
1195  previous_anim = current;
1196  current = current->nextanimation;
1197  }
1198  }
1199 }
1200 
1201 extern "C"
1202 CF_PLUGIN int initPlugin(const char *iversion, f_plug_api gethooksptr) {
1203  (void)iversion;
1204  cf_init_plugin(gethooksptr);
1205  cf_log(llevDebug, "CFAnim 2.0a init\n");
1206 
1207  /* Place your initialization code here */
1208  return 0;
1209 }
1210 
1211 extern "C"
1213  va_list args;
1214  const char *propname;
1215  char *buf;
1216  int size;
1217 
1218  va_start(args, type);
1219  propname = va_arg(args, const char *);
1220 
1221  if (!strcmp(propname, "Identification")) {
1222  buf = va_arg(args, char *);
1223  size = va_arg(args, int);
1224  va_end(args);
1225  snprintf(buf, size, PLUGIN_NAME);
1226  return NULL;
1227  } else if (!strcmp(propname, "FullName")) {
1228  buf = va_arg(args, char *);
1229  size = va_arg(args, int);
1230  va_end(args);
1231  snprintf(buf, size, PLUGIN_VERSION);
1232  return NULL;
1233  }
1234  va_end(args);
1235  return NULL;
1236 }
1237 
1238 extern "C"
1240  (void)op;
1241  (void)params;
1242  return mr_finished;
1243 }
1244 
1245 extern "C"
1247  cf_log(llevDebug, "CFAnim 2.0a post init\n");
1248  /* Pick the global events you want to monitor from this plugin */
1250  return 0;
1251 }
1252 
1253 extern "C"
1255  va_list args;
1256  int rv = 0;
1257  int event_code;
1258 
1259  va_start(args, type);
1260  event_code = va_arg(args, int);
1261  assert(event_code == EVENT_CLOCK);
1262 
1263  animate();
1264 
1265  va_end(args);
1266 
1267  return rv;
1268 }
1269 
1270 extern "C"
1271 CF_PLUGIN int eventListener(int *type, ...) {
1272  int rv = 0;
1273  va_list args;
1274  char *buf, message[MAX_BUF], script[MAX_BUF];
1275  object *who, *activator/*, *third*/, *event;
1276  int query;
1277 
1278  va_start(args, type);
1279 
1280  who = va_arg(args, object *);
1281  activator = va_arg(args, object *);
1282  /*third =*/ va_arg(args, object *);
1283  buf = va_arg(args, char *);
1284 
1285  if (buf != NULL) {
1286  snprintf(message, sizeof(message), "%s", buf);
1287  } else {
1288  message[0] = '\0';
1289  }
1290 
1291  query = va_arg(args, int); /* 'fix', ignored */
1292  event = va_arg(args, object *);
1293 
1294  if (query == 1 && strcmp(message, "query_object_is_animated") == 0) {
1295  rv = is_animated_object(who);
1296  va_end(args);
1297  return rv;
1298  }
1299 
1301  cf_get_maps_directory(event->slaying, script, sizeof(script));
1302  va_end(args);
1303 
1304  /* Put your plugin action(s) here */
1305  if (activator != NULL) {
1306  cf_log(llevDebug, "CFAnim: %s called animator script %s\n", activator->name, script);
1307  } else if (who != NULL) {
1308  activator = who;
1309  cf_log(llevDebug, "CFAnim: %s called animator script %s\n", who->name, script);
1310  }
1311 
1312  rv = start_animation(who, activator, event, script, message);
1313 
1314  return rv;
1315 }
1316 
1317 extern "C"
1319  cf_log(llevDebug, "CFAnim 2.0a closing\n");
1320  return 0;
1321 }
CFanimationHook
Available animation move.
Definition: cfanim.h:88
mr_again
@ mr_again
Move should continue next time.
Definition: cfanim.h:47
animate_one
static void animate_one(CFanimation *animation, long int milliseconds)
Checks if an animation can execute one or more moves, and if so does them.
Definition: cfanim.cpp:1096
skills
Player Stats effect how well a character can survie and interact inside the crossfire world This section discusses the various what they and how they effect the player s actions Also in this section are the stat modifiers that specific classes professions bring Player and sps the current and maximum the Current and Maximum The Current Sp can go somewhat negative When Sp is negative not all spells can be and a more negative Sp makes spell casting less likey to succeed can affect Damage and how the characters as well as how often the character can attack this affects the prices when buying and selling items if this drops the player will start losing hit points wd Cleric or Dwarf sm Elf wd Fireborn ft Human ra Mage C Monk se Ninja hi Priest C Quetzalcoatl mw Swashbuckler si Thief st Viking ba Warrior or Wizard C Wraith C Class Prof Str Dex Con Wis Cha Int Pow Net Skills Enclosed are codes used for the skills above The ones in and fighting should all be pretty self explanatory For the other skills
Definition: stats.txt:126
PLAYER
@ PLAYER
Definition: object.h:112
initsay
static long int initsay(const char *name, char *parameters, CFmovement *move_entity)
Definition: cfanim.cpp:194
cf_log
void cf_log(LogLevel logLevel, const char *format,...)
Wrapper for LOG().
Definition: plugin_common.cpp:1541
cf_map_get_height
int cf_map_get_height(mapstruct *map)
Definition: plugin_common.cpp:1413
cf_add_string
sstring cf_add_string(const char *str)
Wrapper for add_string().
Definition: plugin_common.cpp:1176
FOR_MAP_FINISH
#define FOR_MAP_FINISH()
Finishes FOR_MAP_PREPARE().
Definition: define.h:714
cf_map_get_sstring_property
sstring cf_map_get_sstring_property(mapstruct *map, int propcode)
Definition: plugin_common.cpp:270
options
static struct Command_Line_Options options[]
Actual valid command line options.
Definition: init.cpp:393
llevError
@ llevError
Problems requiring server admin to fix.
Definition: logger.h:11
CFanimation::corpse
object * corpse
Definition: cfanim.h:80
cf_object_teleport
int cf_object_teleport(object *ob, mapstruct *map, int x, int y)
Definition: plugin_common.cpp:1369
C
Player Stats effect how well a character can survie and interact inside the crossfire world This section discusses the various what they and how they effect the player s actions Also in this section are the stat modifiers that specific classes professions bring Player and sps the current and maximum the Current and Maximum The Current Sp can go somewhat negative When Sp is negative not all spells can be and a more negative Sp makes spell casting less likey to succeed can affect Damage and how the characters as well as how often the character can attack this affects the prices when buying and selling items if this drops the player will start losing hit points wd Cleric or Dwarf sm Elf wd Fireborn ft Human ra Mage C Monk se Ninja hi Priest C Quetzalcoatl mw Swashbuckler si Thief st Viking ba Warrior or Wizard C Wraith C Class Prof Str Dex Con Wis Cha Int Pow Net Skills Enclosed are codes used for the skills above The ones in and fighting should all be pretty self explanatory For the other a brief description is for a more detailed look at the skills doc file Skill remove use magic items C
Definition: stats.txt:133
cf_object_apply_below
void cf_object_apply_below(object *pl)
Wrapper for apply_by_living_below().
Definition: plugin_common.cpp:553
player
One player.
Definition: player.h:107
runsay
static anim_move_result runsay(CFanimation *animation, long int id, void *parameters)
Definition: cfanim.cpp:205
time_enum
time_enum
Time units the animation can use.
Definition: cfanim.h:39
CFanimation::paralyze
int paralyze
Definition: cfanim.h:72
postInitPlugin
CF_PLUGIN int postInitPlugin(void)
The server calls this function to actually initialize the plugin here, after object handlers are regi...
Definition: cfanim.cpp:1246
command
same as sound ncom command like but with extra the client want tick commands so it knows animation timing the client wants to be informed of pickup mode changes Mode will be sent when the player successfully logs and afterward any time the value is but over many options have become defaults This documents those now obsolete client can handle the bit exp values that are now used values are sent as bit Setting this flag also means that skill exp will be and it will be sent in revised method as described in the stats command Value is an integer in string format else Deprecated client should presume all servers support this server will return FALSE Deprecated replaced with sound2 setup command
Definition: protocol.txt:461
time
same as sound ncom command like but with extra the client want tick commands so it knows animation timing the client wants to be informed of pickup mode changes Mode will be sent when the player successfully logs and afterward any time the value is but over time
Definition: protocol.txt:416
cfanim_runPluginCommand
CF_PLUGIN anim_move_result cfanim_runPluginCommand(object *op, char *params)
Definition: cfanim.cpp:1239
oblinkpt::next
oblinkpt * next
Next value in the list.
Definition: object.h:472
NDI_GREEN
#define NDI_GREEN
SeaGreen.
Definition: newclient.h:253
ZipGenius
Release notes for Crossfire This is see the Changelog file included with the software Major changes since but slower than players without that skill *weather system is hopefully fixed *misc bug fixes Once you have installed the you MUST download a map set point to where you installed Crossfire install Grab map set from official SourceForge page The following sets are at ZipGenius
Definition: Release_notes.txt:40
initapply
static long int initapply(const char *name, char *parameters, CFmovement *move_entity)
Definition: cfanim.cpp:215
prepare_commands
static void prepare_commands(void)
Definition: cfanim.cpp:620
ordered_commands
static int ordered_commands
Definition: cfanim.cpp:614
mapstruct::buttons
oblinkpt * buttons
Linked list of linked lists of buttons.
Definition: map.h:348
AP_APPLY
#define AP_APPLY
Item is to be applied.
Definition: define.h:558
runmoveto
static anim_move_result runmoveto(CFanimation *animation, long int id, void *parameters)
Definition: cfanim.cpp:475
initmoveto
static long int initmoveto(const char *name, char *parameters, CFmovement *move_entity)
Definition: cfanim.cpp:459
server
Release notes for Crossfire This is see the Changelog file included with the software Major changes since but slower than players without that skill *weather system is hopefully fixed *misc bug fixes Once you have installed the server
Definition: Release_notes.txt:25
runghosted
static anim_move_result runghosted(CFanimation *animation, long int id, void *parameters)
Definition: cfanim.cpp:336
cf_strdup_local
char * cf_strdup_local(const char *str)
Wrapper for strdup_local().
Definition: plugin_common.cpp:1465
initwizard
static long int initwizard(const char *name, char *parameters, CFmovement *move_entity)
Definition: cfanim.cpp:175
FOR_BELOW_PREPARE
#define FOR_BELOW_PREPARE(op_, it_)
Constructs a loop iterating over all objects below an object.
Definition: define.h:688
object::speed
float speed
Frequency of object 'moves' relative to server tick rate.
Definition: object.h:337
if
if(!(yy_init))
Definition: loader.cpp:36440
object::invisible
int16_t invisible
How much longer the object will be invis.
Definition: object.h:370
object::x
int16_t x
Definition: object.h:335
UP_OBJ_CHANGE
#define UP_OBJ_CHANGE
Object changed.
Definition: object.h:532
object::speed_left
float speed_left
How much speed is left to spend this round.
Definition: object.h:338
SVN_REV
#define SVN_REV
Definition: svnversion.h:2
runwizard
static anim_move_result runwizard(CFanimation *animation, long int id, void *parameters)
Definition: cfanim.cpp:186
object::map
struct mapstruct * map
Pointer to the map in which this object is present.
Definition: object.h:305
param_moveto
Destination for moveto command.
Definition: cfanim.cpp:455
cf_object_apply
int cf_object_apply(object *op, object *author, int flags)
Wrapper for apply_manual().
Definition: plugin_common.cpp:542
FLAG_WIZ
#define FLAG_WIZ
Object has special privilegies.
Definition: define.h:218
CFmovement::tick
int tick
Move duration, units depending on parent's time_representation.
Definition: cfanim.h:63
in
same as sound ncom command like but with extra the client want tick commands so it knows animation timing the client wants to be informed of pickup mode changes Mode will be sent when the player successfully logs in
Definition: protocol.txt:408
cf_object_move_to
int cf_object_move_to(object *op, int x, int y)
Wrapper for move_to().
Definition: plugin_common.cpp:630
cf_object_free_drop_inventory
void cf_object_free_drop_inventory(object *ob)
Wrapper for object_free_drop_inventory().
Definition: plugin_common.cpp:571
cf_find_string
sstring cf_find_string(const char *str)
Definition: plugin_common.cpp:1198
initnotice
static long int initnotice(const char *name, char *parameters, CFmovement *move_entity)
Definition: cfanim.cpp:423
you
TIPS on SURVIVING Crossfire is populated with a wealth of different monsters These monsters can have varying immunities and attack types In some of them can be quite a bit smarter than others It will be important for new players to learn the abilities of different monsters and learn just how much it will take to kill them This section discusses how monsters can interact with players Most monsters in the game are out to mindlessly kill and destroy the players These monsters will help boost a player s after he kills them When fighting a large amount of monsters in a single attempt to find a narrower hallway so that you are not being attacked from all sides Charging into a room full of Beholders for instance would not be open the door and fight them one at a time For there are several maps designed for them Find these areas and clear them out All throughout these a player can find signs and books which they can read by stepping onto them and hitting A to apply the book sign These messages will help the player to learn the system One more always keep an eye on your food If your food drops to your character will soon so BE CAREFUL ! NPCs Non Player Character are special monsters which have intelligence Players may be able to interact with these monsters to help solve puzzles and find items of interest To speak with a monster you suspect to be a simply move to an adjacent square to them and push the double ie Enter your and press< Return > You can also use say if you feel like typing a little extra Other NPCs may not speak to you
Definition: survival-guide.txt:37
NDI_NAVY
#define NDI_NAVY
Definition: newclient.h:248
oblinkpt
Used to link together several object links.
Definition: object.h:469
cf_object_pickup
int cf_object_pickup(object *op, object *what)
Definition: plugin_common.cpp:1453
cf_player_move
int cf_player_move(player *pl, int dir)
Definition: plugin_common.cpp:524
runteleport
static anim_move_result runteleport(CFanimation *animation, long int id, void *parameters)
Definition: cfanim.cpp:412
mr_finished
@ mr_finished
Move completed.
Definition: cfanim.h:46
initteleport
static long int initteleport(const char *name, char *parameters, CFmovement *move_entity)
Definition: cfanim.cpp:372
buf
StringBuffer * buf
Definition: readable.cpp:1564
get_boolean
static int get_boolean(const char *strg, int *bl)
This function gets a string containing [Y/y](es)/[N/n](o), 1/0 and set bl according to what's read if...
Definition: cfanim.cpp:758
find_by_name
static object * find_by_name(object *origin, const char *name)
Definition: cfanim.cpp:825
HUGE_BUF
#define HUGE_BUF
Used for messages - some can be quite long.
Definition: define.h:37
initvisible
static long int initvisible(const char *name, char *parameters, CFmovement *move_entity)
Definition: cfanim.cpp:156
rundropobject
static anim_move_result rundropobject(CFanimation *animation, long int id, void *parameters)
Definition: cfanim.cpp:274
CFanimation::tick_left
long int tick_left
Definition: cfanim.h:81
name
Plugin animator file specs[Config] name
Definition: animfiles.txt:4
FOR_BELOW_FINISH
#define FOR_BELOW_FINISH()
Finishes FOR_BELOW_PREPARE().
Definition: define.h:695
September
Release notes for Crossfire September
Definition: Release_notes.txt:1
CFmovement::id
long int id
Identifier, used for various things.
Definition: cfanim.h:62
object::y
int16_t y
Position in the map for this object.
Definition: object.h:335
Crossfire
TIPS on SURVIVING Crossfire is populated with a wealth of different monsters These monsters can have varying immunities and attack types In some of them can be quite a bit smarter than others It will be important for new players to learn the abilities of different monsters and learn just how much it will take to kill them This section discusses how monsters can interact with players Most monsters in the game are out to mindlessly kill and destroy the players These monsters will help boost a player s after he kills them When fighting a large amount of monsters in a single attempt to find a narrower hallway so that you are not being attacked from all sides Charging into a room full of Beholders for instance would not be open the door and fight them one at a time For there are several maps designed for them Find these areas and clear them out All throughout these a player can find signs and books which they can read by stepping onto them and hitting A to apply the book sign These messages will help the player to learn the system One more always keep an eye on your food If your food drops to your character will soon so BE CAREFUL ! NPCs Non Player Character are special monsters which have intelligence Players may be able to interact with these monsters to help solve puzzles and find items of interest To speak with a monster you suspect to be a simply move to an adjacent square to them and push the double ie Enter your and press< Return > You can also use say if you feel like typing a little extra Other NPCs may not speak to but display intelligence with their movement Some monsters can be and may attack the nearest of your enemies Others can be in that they follow you around and help you in your quest to kill enemies and find treasure SPECIAL ITEMS There are many special items which can be found in Crossfire
Definition: survival-guide.txt:45
initPlugin
CF_PLUGIN int initPlugin(const char *iversion, f_plug_api gethooksptr)
The server calls this function after loading the plugin.
Definition: cfanim.cpp:1202
CFanimationHook::funcrun
CFAnimRunFunc funcrun
Function to run the move.
Definition: cfanim.h:91
runtrigger
static anim_move_result runtrigger(CFanimation *animation, long int id, void *parameters)
Definition: cfanim.cpp:527
object::contr
struct player * contr
Pointer to the player which control this object.
Definition: object.h:284
maps
in that case they will be relative to whatever the PWD of the crossfire server process is You probably shouldn though Notes on Specific and settings file datadir Usually usr share crossfire Contains data that the server does not need to modify while such as the maps
Definition: server-directories.txt:45
teleport
int teleport(object *teleporter, uint8_t tele_type, object *user)
Teleport an item around a nearby random teleporter of specified type.
Definition: move.cpp:204
start_animation
static int start_animation(object *who, object *activator, object *event, const char *file, const char *message)
Create a new animation object according to file, option and activator (who)
Definition: cfanim.cpp:868
CFanimation::wizard
int wizard
Definition: cfanim.h:74
Windows
How to Install a Crossfire Server on Windows
Definition: INSTALL_WIN32.txt:5
files
the server will also quite happily load unpacked files as long as they have the right file which is convenient if you want to edit your maps and archetypes live It also contains a few files
Definition: server-directories.txt:52
oblinkpt::link
objectlink * link
Items for this value.
Definition: object.h:470
cf_object_say
void cf_object_say(object *op, const char *msg)
Definition: plugin_common.cpp:1058
CF_PLUGIN
#define CF_PLUGIN
Definition: plugin_common.h:38
initfire
static long int initfire(const char *name, char *parameters, CFmovement *move_entity)
Definition: cfanim.cpp:94
cf_map_insert_object_there
object * cf_map_insert_object_there(object *op, mapstruct *m, object *originator, int flag)
Wrapper for object_insert_in_map().
Definition: plugin_common.cpp:1324
f_plug_api
void(* f_plug_api)(int *type,...)
General API function.
Definition: plugin.h:79
is_animated_object
static int is_animated_object(const object *ob)
Is specified object currently being animated?
Definition: cfanim.cpp:789
SvnRevPlugin
CF_PLUGIN char SvnRevPlugin[]
Definition: cfanim.cpp:40
CFmovement::parameters
void * parameters
Parameters to the function.
Definition: cfanim.h:61
runpickup
static anim_move_result runpickup(CFanimation *animation, long int id, void *parameters)
Definition: cfanim.cpp:293
FOR_OB_AND_BELOW_FINISH
#define FOR_OB_AND_BELOW_FINISH()
Finishes FOR_OB_AND_BELOW_PREPARE().
Definition: define.h:738
oblinkpt::value
long value
Used as connected value in buttons/gates.
Definition: object.h:471
cf_init_plugin
int cf_init_plugin(f_plug_api getHooks)
Definition: plugin_common.cpp:146
object::below
object * below
Pointer to the object stacked below this one.
Definition: object.h:295
first_animation
static CFanimation * first_animation
Animations we're currently processing.
Definition: cfanim.cpp:42
PLUGIN_NAME
#define PLUGIN_NAME
Definition: cfanim.h:32
compareAnims
static int compareAnims(const void *a, const void *b)
Definition: cfanim.cpp:616
CFanimation::nextmovement
CFmovement * nextmovement
Definition: cfanim.h:83
CFanimation::errors_allowed
int errors_allowed
Definition: cfanim.h:78
get_dir_from_name
static int get_dir_from_name(const char *name)
Returns the direction from its name.
Definition: cfanim.cpp:51
runpickupobject
static anim_move_result runpickupobject(CFanimation *animation, long int id, void *parameters)
Definition: cfanim.cpp:311
time_tick
@ time_tick
One server tick.
Definition: cfanim.h:41
initmovement
static long int initmovement(const char *name, char *parameters, CFmovement *move_entity)
Definition: cfanim.cpp:71
equality_split
static int equality_split(char *buffer, char **variable, char **value)
This function take buffer with a value like "blabla= things" and extracts some things.
Definition: cfanim.cpp:727
object::type
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:348
cf_object_clone
object * cf_object_clone(object *op, int clonetype)
Clone an object.
Definition: plugin_common.cpp:683
message
TIPS on SURVIVING Crossfire is populated with a wealth of different monsters These monsters can have varying immunities and attack types In some of them can be quite a bit smarter than others It will be important for new players to learn the abilities of different monsters and learn just how much it will take to kill them This section discusses how monsters can interact with players Most monsters in the game are out to mindlessly kill and destroy the players These monsters will help boost a player s after he kills them When fighting a large amount of monsters in a single attempt to find a narrower hallway so that you are not being attacked from all sides Charging into a room full of Beholders for instance would not be open the door and fight them one at a time For there are several maps designed for them Find these areas and clear them out All throughout these a player can find signs and books which they can read by stepping onto them and hitting A to apply the book sign These messages will help the player to learn the system One more always keep an eye on your food If your food drops to your character will soon so BE CAREFUL ! NPCs Non Player Character are special monsters which have intelligence Players may be able to interact with these monsters to help solve puzzles and find items of interest To speak with a monster you suspect to be a simply move to an adjacent square to them and push the double ie Enter your message
Definition: survival-guide.txt:34
CFanimation::invisible
int invisible
Definition: cfanim.h:73
EVENT_CLOCK
#define EVENT_CLOCK
Global time event.
Definition: events.h:53
counterspell
void counterspell(object *op, int dir)
Nullifies spell effects.
Definition: spell_effect.cpp:2911
CFAPI_MAP_PROP_PATH
#define CFAPI_MAP_PROP_PATH
Definition: plugin.h:249
param_moveto::y
int y
Coordinates.
Definition: cfanim.cpp:456
CFanimation::unique
int unique
Definition: cfanim.h:75
spell
with a maximum of six This is not so if you are wearing plate you receive no benefit Armour is additive with all the supplementry forms of which means that it lasts until the next semi permanent spell effect is cast upon the character spell
Definition: tome-of-magic.txt:44
inittrigger
static long int inittrigger(const char *name, char *parameters, CFmovement *move_entity)
Definition: cfanim.cpp:515
CFanimation::verbose
int verbose
Definition: cfanim.h:76
effects
the faster the spell may be cast there are several other common only the caster may be affected by the spell The most common spell range is that of touch This denotes that the caster much touch the recipient of the spell in order to release the spell effects(as for "self", the caster may cast the spell on himself). A "special" range for missile spells indicates that the spell will last until it impacts an object(a PC
initmessage
static long int initmessage(const char *name, char *parameters, CFmovement *move_entity)
Definition: cfanim.cpp:496
http
Release notes for Crossfire This is see the Changelog file included with the software Major changes since but slower than players without that skill *weather system is hopefully fixed *misc bug fixes Once you have installed the you MUST download a map set point to where you installed Crossfire install Grab map set from official SourceForge page The following sets are at http
Definition: Release_notes.txt:40
cf_map_message
void cf_map_message(mapstruct *m, const char *msg, int color)
Partial wrapper for ext_info_map().
Definition: plugin_common.cpp:667
FOR_OB_AND_BELOW_PREPARE
#define FOR_OB_AND_BELOW_PREPARE(op_)
Constructs a loop iterating over an object and all objects below it in the same pile.
Definition: define.h:734
runnotice
static anim_move_result runnotice(CFanimation *animation, long int id, void *parameters)
Definition: cfanim.cpp:428
object::facing
int8_t facing
Object is oriented/facing that way.
Definition: object.h:345
cf_object_drop
void cf_object_drop(object *op, object *author)
Definition: plugin_common.cpp:1052
teleport_params
Definition: cfanim.cpp:366
CFmovement::next
CFmovement * next
Next move in the animation.
Definition: cfanim.h:64
Note
Release notes for Crossfire This is see the Changelog file included with the software Major changes since but slower than players without that skill *weather system is hopefully fixed *misc bug fixes Once you have installed the you MUST download a map set Note
Definition: Release_notes.txt:32
runmovement
static anim_move_result runmovement(CFanimation *animation, long int id, void *parameters)
Definition: cfanim.cpp:80
cf_free_string
void cf_free_string(sstring str)
Wrapper for free_string().
Definition: plugin_common.cpp:1191
anim_move_result
anim_move_result
Result of one animation move.
Definition: cfanim.h:45
MAX_BUF
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
cf_object_find_by_name
object * cf_object_find_by_name(const object *who, const char *name)
Wrapper for object_find_by_name().
Definition: plugin_common.cpp:605
initdropobject
static long int initdropobject(const char *name, char *parameters, CFmovement *move_entity)
Definition: cfanim.cpp:267
Also
Crossfire Protocol which is used between clients and servers to play Crossfire This documentation is intended primarily for client implementers This manual is the collective result of various authors compiled over the course of many most of the time several years after the actual code was written As such it will surely contain omit certain important and possibly make life miserable many working open source server and client implementations of this protocol are available Fixes and improvements to this documentation are welcome History the communications plan was set to be a text based system It was up to the server and client to parse these messages and determine what to do These messages were assumed to be line per message At a reasonably early stage of Eric Anderson wrote a then the data itself you could send many data and after the other end could decode these commands This works fairly but I think the creation of numerous sub packets has some performance hit Also
Definition: protocol.txt:36
initapplyobject
static long int initapplyobject(const char *name, char *parameters, CFmovement *move_entity)
Definition: cfanim.cpp:236
runapplyobject
static anim_move_result runapplyobject(CFanimation *animation, long int id, void *parameters)
Definition: cfanim.cpp:242
FOR_MAP_PREPARE
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Constructs a loop iterating over all objects of a map tile.
Definition: define.h:707
time_second
@ time_second
One second.
Definition: cfanim.h:40
CFanimation::time_representation
enum time_enum time_representation
Definition: cfanim.h:82
PLUGIN_VERSION
#define PLUGIN_VERSION
Definition: cfanim.h:33
cf_object_move
int cf_object_move(object *op, int dir, object *originator)
Definition: plugin_common.cpp:531
CFmovement::func
CFAnimRunFunc func
Function to run for this move.
Definition: cfanim.h:60
create_animation
static CFanimation * create_animation(void)
Create a new animation.
Definition: cfanim.cpp:803
cf_system_register_global_event
void cf_system_register_global_event(int event, const char *name, f_plug_event hook)
Definition: plugin_common.cpp:1111
this
How to Install a Crossfire Server on you must install a python script engine on your computer Python is the default script engine of Crossfire You can find the python engine you have only to install them The VisualC Crossfire settings are for but you habe then to change the pathes in the VC settings Go in Settings C and Settings Link and change the optional include and libs path to the new python installation path o except the maps ! You must download a map package and install them the share folder Its must look like this
Definition: INSTALL_WIN32.txt:26
getPluginProperty
CF_PLUGIN void * getPluginProperty(int *type,...)
The server calls this function to get information about the plugin, notably the name and version.
Definition: cfanim.cpp:1212
NDI_UNIQUE
#define NDI_UNIQUE
Print immediately, don't buffer.
Definition: newclient.h:266
object::slaying
sstring slaying
Which race to do double damage to.
Definition: object.h:327
object::name
sstring name
The name of the object, obviously...
Definition: object.h:319
players
std::vector< archetype * > players
Definition: player.cpp:502
eventListener
CF_PLUGIN int eventListener(int *type,...)
Handles an object-related event.
Definition: cfanim.cpp:1271
is
same as sound ncom command like but with extra the client want tick commands so it knows animation timing the client wants to be informed of pickup mode changes Mode will be sent when the player successfully logs and afterward any time the value is but over many options have become defaults This documents those now obsolete client can handle the bit exp values that are now used values are sent as bit Setting this flag also means that skill exp will be and it will be sent in revised method as described in the stats command Value is an integer in string format else Deprecated client should presume all servers support this server will return FALSE Deprecated replaced with sound2 setup but rather that the server was unable to complete the given protocol request the command(just the command name) that generated the failure. reason the server will only keep track of the latest mark sent The server will generally send a drawinfo command informing the but there is no easy way for the client to know what the marked item is(although, client knowing this is not strictly needed) inscribe ^^^^^^^^ C -> S:inscribe< version >< spell >< scroll > version::int8, version of inscribe command. The only supported value is 0. spell::int32, tag of spell object to write. scroll::int32, tag of the scroll to write the spell onto Write a spell on a scroll. Roughly equivalent to manually marking an item, readying the spell, and using the inscription skill. item2 ^^^^^ S->C:item2< location >< tag1 >< flags1 >< weight1 >< face1 >< name1 >< anim1 >< animspeed1 >< nrof1 >< type1 >< object2 >... Note that multiple items can be sent with a single item2 command - there is only 1 location for all items, so all items have to be in the same spot, but in the case of a players inventory, a single item2 with a large number of items can be sent. location::int32, Location of the object. A value of 0 is special, meaning the floor under the player. Any other value is a tag of where the object is, which may be the<< _player >> object or a container. tag::int32, tag for this object. The server will use this command to note that objects have moved locations, so the client should examine all objects it knows about for this tag - it should not assume this is a new item. flags::int32, Various flags on the item(curse, applied, etc) detailed in `newclient.h` weight::int32, The weight of a single one of these objects, in grams. The client will need to figure the total weight by multiplying by _nrof_. Note that for containers, weight will be the total weight(that of the container plus contents). Can be negative(not pick-able) face::int32, face number of a previously sent<< _face2 >> command. name::lstring, name of the object. Starting at SC 1024, this name is two strings, with a null separation. The first of these strings is the singular form, the second is the name to use for multiple(plural version) The first byte(length) is the length for both of these strings. This name information is just the information of what the object is called. It does not include how many of the items there are. anim::int16, animation sequence ID from a previous<< _anim >> command animspeed::int8, how often the object should be animated, in ticks(1 means it should be animated every tick). 1 byte limits this to once every 255 ticks, I can 't see anything being animated slower than that. nrof::int32, number of objects in this stack type::int16, client type, a numeric type ID to help the client sort similar items together. The client is free to ignore this. upditem ^^^^^^^ S->C:upditem< flag >< tag >< data > Update one field of an existing item. flag::int8, determines which field of the item to update(see the `UPD_` flags in `newclient.h`) tag::int32, tag of object data::depends on the _flag_, see the fields in the<< _item2 >> command Only one item can be updated with the upditem command. An item command should have been sent by the server before an upditem command is set. delitem ^^^^^^^ S->C:delitem< tag1 >[tag2]... Tells the client to delete items with the tag values. These items are considered gone from the game, so the client should delete all reference it has to them. tag::int32, tags of the items to delete. Multiple tags can be sent to delete multiple items, but as of this writing(Jan 2010), the server only ever sends a single tag delinv ^^^^^^ S->C delinv< tag > tag::int, tells the client to delete items carried in/by the object _tag_. If 0, delete all items on the space the character is standing on. This command only affects the inventory of the object. To fully delete a container object, a _delinv_ followed by a<< _delitem >> should be issued. Spells ~~~~~~ addspell ^^^^^^^^ S->C addspell< tag1 >< level1 >< casting time1 >< mana1 >< grace1 >< damage1 >< skill >< path1 >< name1 >< display name1 >< message1 >< usage information >< requirements >< spell2 .... > Tells the client to add the spell(s) listed to the list of spells the client knows about. This will be sent at login, and again whenever new spells are sent.[options="autowidth,header"]|===========================|Field|Description|< tag >(4 bytes - int)|The ID number for the spell item. This is going to be unique, for each spell and will be used to refer to it henceforth. The string form of this should also be appended to the cast/invoke commands in order to cast the spell.|< level >(2 bytes, signed int)|The level of the spell.|< casting time >(2 bytes, signed int)|The time it will take to cast the spell, in server ticks.|< mana >(2 bytes, signed int)|The mana cost to cast the spell(may be zero)|< grace >(2 bytes, signed int)|The grace cost to cast the spell(may be zero)|< damage >(2 bytes, signed int)|The current damage done by the spell. Note that the meaning of this number is to a large part spell dependent, what damage it actually does will depend on how the spell works.|< skill >(1 byte, unsigned int)|The skill that the spell uses to be cast, if zero, no skill is used in the casting of this spell. The numbers are the same as for requestinfo skill_info|< path >(4 bytes, unsigned int)|The path that the spell belongs to. The client should determine the effect of this by comparing these values to both the spell_paths requestinfo data and the stats info concerning attunement/repulsion, etc.|< face >(4 bytes, signed int)|The number of the face that corresponds to the spell, the client can request this facenumber if they want to show a graphical spell representation.|< name >(1(non-zero)|length byte, followed by that many bytes of ASCII text) This is a name to identify the spell, which the client can use for display purposes, it should/NOT/be used with the 'cast' command, whilst it might work, no such guarantee is made by the server. - Use tag instead.|< message >|(2 length bytes(which may be zero) followed by that many bytes of ASCII text) The description of the spell. Note that this has an extra length byte because the messages may well be longer than 256 bytes in length.|< usage information >(1 byte)|Only sent if 'spellmon 2' was setup by the client. Values are:- 0:spell needs no argument. - 1:spell needs the name of another spell. - 2:spell can use a freeform string argument. - 3:spell requires a freeform string argument.|< requirements >(1 byte of length, then that many bytes of ASCII text)|Only sent if 'spellmon 2' was setup by the client. If the spell required items to be cast, then this is the list of those items. Comma-separated, potential number of items, singular names(like the ingredients for alchemy).|===========================updspell ^^^^^^^^ S->C updspell< flags >< tag >< vals >+< flags > 1 byte binary. Values include in this update. Uses the UPD_SP_.. from 'newclient.h'< tag > 4 byte binary. Tag of the spell. This updates some spell(of tag) with new values. The flags are 1 byte and determine which values have been updated, and should be re-read. Not all fields may be updated by this command, only those that can be changed. If new fields are added in future, they will extend the flags bitmask and the order will remain the LSB order of the flags - that is, the value associated with bit 1 set is sent first, then bit 2, etc. The format of the values is same as the `addspell` command above. Only one spell can be updated with the `updspell` command. A spell command should have been sent by the server before an `updspell` command is set. delspell ^^^^^^^^ S->C delspell< tag >< tag > 4 byte binary data. Tells the client to remove its information about the spell. Tag is a 4 byte value, the same as the one sent when the spell was added. Knowledge/Quests ~~~~~~~~~~~~~~~~ addquest ^^^^^^^^ S->C addquest< code1 >< title >< face >< replay >< parent >< end >< step >< code2 >... Tells the client to add the quest(s) listed to the list of quests the player is doing. This will be sent at login, and again whenever new quests are started, if notifications is 1 or greater. code::int32, a unique quest ID title::l2string, the quest title face::int32, a face with a quest icon replay::int8, if 1, the quest is replayable, otherwise 0 parent::int32, quest ID of the parent quest, or 0 if this quest is a top-level quest end::int8, if 1, the quest is complete step::l2string, the description of the current quest step updquest ^^^^^^^^ S->C updquest< code >< end >< step >< code > -(4 bytes - unsigned int) The ID number for the quest item.< end >(1 byte, unsigned int) If 1, the quest was completed.< step >(2 bytes length, unsigned int, then string of specified length) The current step 's description, can be an empty string(length 0). This updates some quest(of tag) with new values, if notifications is 1 or greater. Only one quest can be updated with the `updquest` command. A `addquest` command should have been sent by the server before an `updquest` command is set with the same ID. addknowledge ^^^^^^^^^^^^ S->C addknowledge< code1 >< type >< title >< face >< code2 ... > Tells the client to add the knowledge item(s) listed to the list of things the player knows. This will be sent at login, and again whenever new knowledge is learnt, if 'notifications' is 2 or greater.< code > -(4 bytes - unsigned int) The ID number for the knowledge item. This is going to be unique, for each knowledge and will be used to refer to it henceforth. It is the same number the player sees with the 'knowledge' commands.< type >(2 bytes length, unsigned int, then string of specified length) The knowledge 's type, as defined in the knowledge_info reply.< title >(2 bytes length, unsigned int, then string of specified length) The knowledge title.< face >(4 bytes, signed int) The number of the face that corresponds to the knowledge item, which will be sent before this packet if needed. Player Object and Stats ~~~~~~~~~~~~~~~~~~~~~~~ player ^^^^^^ Identifies the player object to the client. S->C:player< tag >< weight >< face >< name > For field documentation, see the<< _item2 >> command. stats ^^^^^ S->C:stats< stat1 >< val1 >< stat2 >< val2 >... Update the given statistics. Multiple stats can be sent in one command. stat::int8, one of the `CS_STAT` values from `newclient.h` val::variable-length binary data depending on the _stat_. int16 except for the following fields:**weight limit:int32 **speed, weapon_sp:int32. This is a float converted to an integer by multiplying by `FLOAT_MULTI`. The client needs to divide by `FLOAT_MULTI` to get it back to a float. **range, title:lstring **experience:If `CS_STAT_EXP64` is sent, int64 experience value. 64 bit is the only option now - 32 bit exp is no longer sent. **skill experience:int64 **spellpaths:int32, only sent if `spellmon` is set in<< _setup >>. The `CS_STAT_RACE_xxx` and `CS_STAT_BASE_xxx` are only sent if `extended_stats` was used in setup. Image Information ~~~~~~~~~~~~~~~~~ anim ^^^^ S->C:anim< num >< flags >< face1 >< face2 >...< num > 2 byte binary data. animation number we are defining. The server will only send the anim command for a particular< num > once per run - the client needs to keep track what has been sent. On new runs, anim commands will be resent.< flags > 2 byte binary data. Currently unused, but is included because I think there may end up being cases were more about the animation than just the num and faces are needed.< face1 >... 2 byte binary data. This is the various faces that comprise the animation sequence. The number of faces can be determined by checking the length of the packet. These values correspond in the same way as all references to face do. This command informs the client of an animation sequence. The client is responsible for animating the objects in the inventory window, and upditem and other items command will refer to the animation number with num above. All values are 2 byte binary values. Note that how fast the object is animated is contained in the item commands. image2 ^^^^^^ S->C:image2< face >< set >< len >< data >< face > 4 byte binary data - face number.< set > 1 byte binary data. Which faceset the image belongs to.< len > 4 byte binary data. Length of face data.< data > Binary data - actual face(png) information. Sends a png version of an image to the client. face2 ^^^^^ S->C:face2< num >< setnum >< checksum >< name > num::int16, face number setnum::int8, the set that the face belongs to checksum::int32, checksum of face data name::string name of face Informs the client that image< num > of faceset< setnum > is associated with< name >. This is used when the client is caching images. In normal operation, when the server runs across a face that it hasn 't sent the client, it sends a png for that face. If the face mode is none, the server then sends this command. The client can then check to see if it might have cached this face, and if not, should then request it from the server. Note that the num to name mappings can change between server and different runs of the server. For this reason, this data needs to be sent each time it is run. The client should be able to load/determine what face to load via the name. These are not guaranteed to be the same across different runs of the game(however, in reality, they will only change on the one server if they make changes to the archetypes and rebuild.) Some face information will be sent from the server to the client before actually sending a face number. askface ^^^^^^^ C->S:askface< num >< num > string of integer value. Requests that the server send the client face< num >. The server will use values from setup to determine what faceset to send. smooth ^^^^^^ S->C:smooth< face >< smoothpic >< face > 2 byte binary data - face number< smoothpic > 2 byte binary data. Face to use for smoothing. This command informs the client on how to smooth an image. Following are the facenbr of the picture involved in the smoothing algorithm. See doc on smoothing on how to use them. The server will send this to the client just like it sends faces, but client can also make explicit requests. asksmooth ^^^^^^^^^ C->S:asksmooth< face >< face > string of integer value. Ask server to send a smooth sequence. Server will respond with a smooth command.< facenbr > is an integer telling server which face we want smooth information on. Map Update ~~~~~~~~~~ map2 ^^^^ This replaces the old `map` command. It is meant to be extensible and incorporate the ideas of the extended map info command. S->C map2< coord1 >[< type1 >[< data >]...]< coord2 >... coord::int16, consisting of, from MSB to LSB:*6 bits:_x_ coordinate *6 bits:_y_ coordinate **Both coordinates are offset by `MAP2_COORD_OFFSET`(currently 15) from their actual value on the client map, i.e.(14, 14) represents(-1, -1). **This is necessary because there may be effects noticeable to the player such as light sources that to outside the visible map. *4 bits:Type **0 tile data. One or more _type_ fields follow for this coordinate. **1 instructs the client to scroll the map by _x_ and _y_. This replaces the old<< _mapscroll >> command. The next _coord_ follows immediately. type::int8, present only if the previous _coord_ was for tile data. If it is equal to the termination byte 255, end data for the last _coord_. The next field should be a different _coord_. Otherwise, this consists of(from MSB to LSB):*3 bits:Number of bytes that follow, or(only for SC >=1030) 7. 0 indicates no additional bytes, i.e. all the relevant information is included in the type. For SC >=1030:If it is 7(all bits set), then the next byte contains a 1-byte length field that denotes the actual number of bytes that follow(and the 7 should be ignored). *5 bits:Type, which is one of:**0x0:Clear:Clear this tile because it is no longer visible. The client may opt to keep the data for rendering a fog of war. Length in this case should also be zero, as there is no data that follows. **0x1:Darkness:the following int8 contains tile darkness data. 0 is completely dark and 255 is fully lit. Note that 0 will never be sent - if the space is completely dark, players won 't be able to see it. **(SC >=1030) 0x2:Label, a textual label that describes the tile, e.g. a place name, sign label, or player name. This must be sent with the 3-bit length field set to 7(all bits set). The data consists of:< len >< subtype >< label > ***len:_int8_, actual length of message, including 1-byte subtype, 1-byte label prefix, and actual label text ***subtype:_int8_, extra data about the type of label. The client can use this to color the text or display it differently. ****0:None(clear labels from this tile, see below) ****1:Player ****2:Player in the same party ****3:DM ****4:NPC ****5:Sign ****6:Say message ****7:Chat message ***label:_lstring_, the label text. Note that the length prefix is still required even though it equals _len - 2_. Labels are not attached to any layer. Multiple labels may be present on one tile. All labels on a tile are sent at once within a coord block, i.e. if a client receives a label, it should first clear all existing labels on that tile. **0x3 - 0xf:Reserved for future extensions. **0x10 - 0x19:Image information. Layer 0x10 is the lowest, 0x19 is the highest. data::_N_ bytes of data, where _N_ is determined by the length bits in the previous _type_ field. For the encoding, see<< _layer_encoding >> below.=====Layer Encoding This encodes layer image data for one layer of one tile on the map. The encoding of this field depends on _N_:*2:< face > *3:< face >[< smooth >|< animspeed >] *4:< face >< animspeed >< smooth > face::int16, the face number or animation. - If 0, then this layer is no longer visible and the smooth and animation information should be cleared. - If the high bit is set, then this is an animation. The type of animation is denoted by the next two most significant bits:**0:Normal animation - start at first phase, etc. **1:Randomize - randomize the animation phase &timing. **2:Synchronize - this animation should be in the same phase as other animations with the same id. Used for things like oceans. - In the 3-byte encoding, a _smooth_ follows a regular face while a _animspeed_ follows an animation. smooth::int8, smoothing information animspeed::int8, How long, in ticks, between animations. 1 means it should be animated every tick. Like<< _item2 >>=====Notes Coordinates outside the viewable map may be sent. In these cases, it means that a big image that extends onto the viewable map is on that space. For big images, only the bottom right coordinate is sent - this is why it may be off the viewable coordinates. For such spaces, only the actual big image itself will be sent for that space. Note that all operations are considered updates to the space(eg, new image, new light level, etc). The exception would be the clear command, which means clear all data with the space. Note that while not used now, order of these subpackets is important. A clear(0x00) followed by other data should be parsed in that order - clear the data, then process the data. In contrast, sending data followed by a clear byte makes no sense. This functionality will likely be used in the future - for example, if 6 layers need to be cleared and the other 2 remain the same, it will be more efficient to send that clear byte followed by the 2 layers to redisplay instead of sending 6 layers with an empty face.. Relative to the map1/map1a commands, this is more bandwidth intensive - basically, an additional byte is needed for each piece of data sent. Thus, on a 25x25 map, if we presume 1.5 objects/space, this is an extra 940 bytes to send. OTOH, typically the entire map is not being sent - only those bits that change, so this may not be as costly as that. If the player is using smoothing, this may actually save bytes, as the redundant coordinates and type/length information does not need to be sent. With the map2 command, the mapextend command is deprecated and is not used. General design notes:For data types that vary in length because of optional data, the required data should be sent first, followed by optional data if appropriate. An example of this is the face information - we send the 2 face bytes first, then follow that with optional data(smoothing and/or animation data). This makes parsing on the client easier - basically, the client should be able to parse the data a byte(or pairing at a time). tick ^^^^ S->C:tick< tickno >< tickno > 4 byte binary data(unsigned) This just tells the client what the current tick is. Right now, the client only uses this to know when to animate the images that the client is responsible for animating. This will only be sent if negotiated with the setup command. newmap ^^^^^^ S->C:newmap This tells the client to clear the map state. Used when player is moving between maps to invalidate all map state information in the client. magicmap ^^^^^^^^ S->C:magicmap< width >< height >< px >< py >< data >< width >< height > string of integer values - width &height of magicmap< px >< py > string of integer values. Players position on magic map.< data > binary data - one byte per space. Low nibble contains color information, high nibble contains FACE_FLOOR and FACE_WALL(see newclient.h) to denote nature of object on that space. This string of data represents the space from left to right, then up to down. Sound ~~~~~ sound2 ^^^^^^ S->C:sound2< x >< y >< dir >< volume >< type >< action >< name > Plays a sound. See the 'doc/Developers/sound' document for more information. x, y::int8, location of the sound relative to the player dir::int8, direction the sound is moving, using the standard direction map(values 0 through 8). volume::int8, sound volume, limited between 1-100 type::int8, major sound type action::lstring, sound subtype name::lstring, name of the source of the sound, typically object name, but in the case of player generated sounds, will be the race of the player music ^^^^^ S->C:music< song > Change background music. This song data is set in a map property. song::string, name of sound to play, or "NONE" to stop any music from playing Miscellaneous ~~~~~~~~~~~~~ beat ^^^^(requires<< _setup >> `beat`) C->S:beat Inform the server that the client is still connected. lookat ^^^^^^ C->S:lookat< dx >< dy > Look at the given relative coordinate. dx, dy::int, a coordinate offset from the player object representing the position to look at.(0, 0) is the same tile as the player This is only a request to the server. A response will typically come back in drawinfo commands. requestinfo and replyinfo ^^^^^^^^^^^^^^^^^^^^^^^^^ This section describes the requestinfo and replyinfo commands. Because these commands may handle different types of data with different return formats, this section is formatted a bit differently to make it easier to read the different structures. C->S:requestinfo< info_type >[options] S->C:replyinfo< info_type >[options]< data >< info_type > is a string value, describing what information is wanted/sent[options] is string data - specific to the type of data.< data > is the actual data. The format of this data will vary based on what the info_type is. The requestinfo command is a general purpose way for the client to request some piece of data the server may have. The server still needs to be coded to respond to the specific info_type, but if the passed info_type is not supported, the server will still respond with the replyinfo, but with an empty data list. This mechanism allows the client to send requests for data and not need to do complicated checking if the server would understand the specific request - if the server understands it, the data gets sent back. If the server doesn 't understand it, the client gets no data, but does get the replyinfo so that it knows that the server does not support that particular aspect. Only one info_type is allowed for each requestinfo. If the client requests many pieces of information(say image sets available, spell listings, etc), it should send multiple requestinfos.[options] is specific to the info_type - it could be a range of values, or empty. Requestinfo requests will not change any data on the server - the setup command should be used for that. The requestinfo just requests data. Note that since the requests can be made before a player logs in, the requestinfo command will not generally support getting information related to the player object. As a general rule, the information returned is static - if the client makes a second requestinfo with same parameters during the same session, it will get the same data back. Thus, the client can safely cache the data instead of making multiple requests. There could be rare cases where information changes(eg, server admin is updating the new file), but these would be rare and generally are not something that needs to be designed for. .Supported Info Types[options="autowidth,header"]|===========================|Type|Description|image_info(no options)|Request basic image information the server has. The data is sent in text format - the replyinfo is newline terminated. Since the packet length is sent in the header, that is used to figure out the length of returned data. Line 1:The last image number the server has. Note that there is no image 0, so this also amounts to the number of images if you start counting from one. Line 2:checksum of all the image name information. This can basically be used to determine if the number to name mapping is the same, eg, if on server 1 the total is 123456, and the player goes to server 2 and the total is the same, we can say with a high degree of confidence that the name to number mappings are the name. If instead the numbers differ, we know we can 't rely on using the same mappings. Line 3+:The image set information the client has. The format is the same as the format in the image_info file, sans comments. The server will ignore any parameters the client sends. An example response:replyinfo image_info 3512 1169234 0:base:standard:0:32x32:none:The standard image set. 1:clsc:classic:0:32x32:none:Classic and new styling.|image_sums< start >< stop >|Request the image number to name(and checksum) values - in this way, the client can build all images before play starts and also request any missing images. The returned data is image_sums< start >< stop >< imagenum >< checksum >< faceset >< namelength >< name > There is an initial space after the stop value, but no spaces after that point. The< start > and< stop > values are ASCII text(same format as it is sent to the server in). The start and stop values are inclusive - thus, if the start is 0 and the stop is 100, 101 checksums will be set. imagenum is 16 bit binary data. checksum is 32 bit binary data. It contains the checksum for the image in the current selected set, and will use whatever fallback logic the imagesets specify. faceset is 8 bit binary data. It contains the actually selected faceset. namelength is 8 bit binary data. It is the length of the name field below, including the null terminator. name is character data. It is null terminated to make processing easier - in this way, the client doesn 't need to copy the data to make it null terminated. Note that due to possible OS system constraints on the maximum single write supported to a socket, the complete set can not be requested at once - instead, the images information should be requested in blocks of less than 1000. The server will not process a block larger than 1000 at a time. Smaller blocks may be desired if the client wants to try to reduce the potential lag caused. Multiple requests for all the information can be sent at once, as the server will buffer the response data, but constraints prevent the server from sending the entire data back in one replyinfo(one being that the data would be beyond 65535 bytes, so the length information in the packet would not be accurate.) If the client sends invalid data(stop is less than start, missing stop parameter, stop is beyond the number of images, or asking for more than 1000 at a time), the reply will just be an empty list. Note that the server will track that it has sent the face information for the requested images, and thus will not send it again(unless requested via requestinfo). Thus, this request should always do the right thing with the returned information.|exp_table|This requests the experience table(what exp is needed for each level) from the server. With this data, the client can easily display how much experience is needed for the different skills or total exp value for next level. Data format:< num_levels >:uint16 - max level/how many exp values follow.< level1 > ...< level num_levels >:uint64 - amount of exp needed for the level. Note that num_levels and the actual exp values are transmitted as binary values.|knowledge_info|This returns the list of knowledge types the server uses. One item per line, in the format:type:display name:face number:attempt 'type' and 'display name' are strings. 'attempt' is 0 if the knowledge type isn 't alchemy-like, 1 if it can be 'attempted'. The first line will always contain empty types and names, to indicate the face of the 'generic' type.|skill_info(empty or '1')|This returns the skill number to skill name mappings. In this way, new skills can be added in the server, and the client can use this new skill information with no changes to the code. All data below is in text format. If the additional value is empty then format is:stat number:skill name else format is stat number:skill name:face number Where stat number is the number that will be used to send that skill information. Example:141:lockpicking 142:hiding 143:smithery|skill_extra(optional level)|This returns extra information about skills, in a binary format. "level" should be 1 for the current version, and may be increased later when other information is added. For each skill, the following fields are sent:< skill number >:uint16, same value as returned by skill_info< description length >:uint16, length of the next field< skill description >:string, description of the skill. It may contain newlines The list ends when< skill number > is 0.|spell_paths|This returns a list of all spell paths in the game, along with the number associated with them. This should be used to parse spell_path data in the stats command. The number is a bitmask but is sent as a decimal value. All data is sent in text format. Format is:number:name eg 16:missiles|race_list|Returns the races players can choose. The names can be used to request more information with race_info. Reply format is:replyinfo race_list :race1:race2:...:racen Note that the names returned are archetype names, and thus not really suitable to display to the player.|race_info|Returns information about specified playable race(one from race_list above). Format is:name< namelen >< namedata > msg< desc len >< description > stats< statno1 >< adj1 >< statno2 >< adj2 >....0 choice< len >< choice name >< len >< choice description >< len >arch name< len >arch_desc(repeat arch) 0 name is the name that the player sees(data returned by race_list above is archetype name). It is a length prefixed string. stats is a literal string value, and what follows are binary statno and adjustment values. statno uses the CS_STAT value that is used by the stats command, and the type of adjustment matches that for stats(eg, if statno1 is a 32 bit type, a 32 bit type will be used here). Any/all of the CS_STAT types could be sent, but in general only a subset will be sent. The server will only send stats which are not zero, so the client should assume all stats that are not sent have a zero value. 0 is used for a statno to denote there are no more stats. description is a text description. It is length prefixed(2 bytes) to allow for possible expansion(with it having a known length, additional fields could be set to follow the description. NOTE:The length parameter here is unusual in that most strings use only an 8 bit length value, but for messages that would not be long enough, hence the 16 bit value. choice is a choice of values to present the player for character creation - it is a choice of one of many archetypes - it could be skill, ability, or potentially even choice of items. All of the field in the choice are 1 byte length prefixed, since they may contain spaces. An example values(where :would be the length value - :is used to improve readability):choice :race_choice_1:Choose a racial skill:skill_smithery:Smithery:skill_jeweler:jeweler0 When the client replies in the create player, it would include the choice name and archetype name, eg:choice race_choice_1 skill_smithery This makes it easier for the server to check the returned values - if it is a racial skill, it knows to check the race, if a class skill, it checks the class, etc. There is currently no way to do something like 'choose 2 out of 4 skills' - however, this could be done by using multiple choice(choice race_choice_1 ... choice race_choice_2 ...) For the choice command, all the passed values come in pairs - choice name/choice description, arch_name/arch_description Note that the race archetype name will be included in the replyinfo header, eg, 'replyinfo race_info dwarf_pl'. Note also that the order of the fields here is not fixed - the server could send them in 'stats, msg, name' order - the client should be able to handle any order. Note also that it is conceivable that the server will send multiple stats command if new stats are to be sent - in this way, the client can process as much as possible, and then stop processing once it gets something it does not understand.|class_list||class_info< class name >|The format of the data returned is exactly the same as for the race_.. command of the same name - the only difference is this is class information.|startingmap|Sends data about starting map choices to the client. Format is:< type >< length >< data >< type > is a single byte binary - the INFO_MAP values define this.< length > is a 2 byte binary - length of following data. This is two bytes because some of the string data that can be sent here will be beyond 255 that a single byte can handle.< data > is actual data - as of now, this is all text data(name, description, etc), but could potentially be binary data(face number) A single map info command will contain information on all the maps. Once the client gets an INFO_MAP_ARCH_NAME, all following map information that follows is for that map until the next INFO_MAP_ARCH_NAME is found or the end of the packet is reached.|newcharinfo|This sends information to the client for creating a new character through the 'createplayer' command. The information sent multiple length prefixed strings - each string corresponds to an entire line/variable set. The idea behind this is that new types/options for character creation can get added without needing to rewrite the entire protocol commands or increase the protocol version - the client requests this information and see if it understands all the data the server wants. If so, it can then create a character. While this setup looks fairly complicated, the simplest way for the client to handle it is to just make sure it understands all the variables present(ignoring type) and it gets all the ones it expects, and if it doesn 't, just throw up an error that client needs to be updated in order to create a character on that server. One reason for the extra complexity here(instead of just making a set of assumptions that are fixed in the protocol) is that lots of discussions have gone on about character creation changes, so this allows for many of them.< type >< variable name >< values > type is a single character which denotes the type of data that is in this line, currently values are:R:required - needed value in the createplayer command. O:optional - if not present in createplayer, server can fill in some default value. If a client does not understand an Optional type but understands all the other types, it could still create the character. V:values - this contains some values which are used in character creation but may not be sent back in the actual createplayer command. An example here is the number of points the player has to spend on stats - the client does not send that back, but rather sends the actual stat values during the createplayer command, but it needs this value to do so. I:Informational - some piece of information that the client should communicate to the player. An example here could be a requestinfo that is related to class or race choices for new characters - one may not want to put it in the news since it is only relevant for people creating new characters.< variable name > name of variable - race, class, map, etc are all possible names. The only constraint on name is that it can not contain any spaces. Short description of variables currently supported:points:How many total points the character has to spend - at current time these are just used for stats, but possible in future they could get used for other things. race, class:Notes that race and class information need to be sent to the server. This is a fixed assumption now, but if at some point someone wanted to remove either races or classes(or both) and reduce the number of choices, this provides a mechanism to do so. statrange:The minimum and maximum value for a stat. statname:The name of the different statistics. Like race &class above, this is a fixed assumption now, but if a stat was to get removed, or a new one added, this provides a mechanism for the client to know it. startingmap:Provide choice of starting maps for the player. List of maps is provided through the 'startingmap' requestinfo command.< values > value tends to be specific to the variable itself. In general, the client will need to be able to parse each required and value variable - if it is unable to do so, it is likely it will not be able to properly generate a character. requestinfo is used for some variables to note that a requestinfo protocol command should be used to retrieve additional data. Note that the client will have to have support for that requestinfo command, and still has know the actual mapping of variable name to requestinfo name. In the case of race and class, it would have to do the race_list/class_list, and when it gets the response from that would then have to know to do the race_info/class_info Below is a sample for first set of supported values(note in the actual protocol, each of these lines is prefixed by a single length byte). Note that all values should be considered case insensitive. Each line is also null terminated by the server. V points 200 V statrange 1 20 V statname Str Dex Con Wis Cha Int Pow R race requestinfo R class requestinfo Possible future extensions(these are provided as an example):V statpointcosts 0 1 2 3 4 .... :If different stat points have different costs(nonlinear) this can be used to return a list of the costs. Instead of values, this could also point to a requestinfo. O skill skill1 skill2 ... If at some point the player can choose some of the skills for their character, this would be used.|news/rules/motd|Send the news/rules/motd file information to the client. This is mainly useful as a way for the client to easily capture this information instead of getting it from drawinfo commands. This is most useful in that the client can more easily choose where to display this information. The sent data is null terminated to make string handling easier on the client.|===========================Deprecated Commands ~~~~~~~~~~~~~~~~~~~ These are no longer used in latest versions of the server and client, but a client that wants to play on older servers should continue to implement them. The reasons for them being deprecated is noted - in most cases it is because they have been replaced by a newer command, or have become de facto defaults. drawinfo ^^^^^^^^ S->C:drawinfo< color >< text > Tell the client to draw whatever text in color. Replaced with<< _drawextinfo >>. color::int, color code from `newclient.h` The client is free to do whatever it wants with the color information(which may very well mean ignore it.) text::string, the message toggleextendedtext ^^^^^^^^^^^^^^^^^^ C->S:toggleextendedtext< type >... Deprecated:Server will use<< _drawextinfo >> for all types, so requesting this type information is no longer needed. Ask the server to send extended text information for a given type. type is a list of decimal integers. ExtendedTextSet ^^^^^^^^^^^^^^^ S->C:ExtendedTextSet< type1 >< type2 > ....< typen > Deprecated:Server will use<< _drawextinfo >> for all types, so requesting this type information is no longer needed. Tell client what actually are the extended infos server may send to the client when this is needed. All those infos will be related to the map and send through mapextended command. Each string represent an info which is enabled. Look at toggleextendedinfos and drawextinfo for details. setfacemode ^^^^^^^^^^^ C->S:setfacemode< val > Deprecated:Only one facemode(PNG) is supported. Client uses setup to request caching(or not) This tells the server what type of display mode the client is using.< val > is a plaintext integer. 0=no faces, 1=bitmap, 2=xpm(pixmap). 3=png(added in CS version 1022) If the 5 'th bit is true(ie, 0x10 &val is true), that then informs the server that client is caching the images, and only send image names. toggleextendedinfos ^^^^^^^^^^^^^^^^^^^ C->S:toggleextendedinfos< string1 >< string2 > ....< stringn > Deprecated:Rolled into<< _map2 >> command, which is standard. Ask the server to send some additional information about the map. This command is followed by 1 or more strings. String are separated with spaces. Each string toggle an info. The server will respond with the command<< _ExtendedInfoSet >> telling client what actual extended infos will be send to the client. Valid extended infos are as follow:smooth send smoothlevel information to the client. ExtendedInfoSet ^^^^^^^^^^^^^^^ S->C:ExtendedInfoSet< string1 >< string2 > ....< stringn > Deprecated:Rolled into map2 protocol command, which is standard. Tell client what actually are the extended infos server may send to the client when this is needed. All those infos will be related to the map and send through mapextended command. Each string represent an info which is enabled. Look at toggleextendedinfos and mapextended for details. setsound ^^^^^^^^ C->S:setsound< val > Deprecated:Replaced with<< _setup >> options sound ^^^^^ S->C:sound< x >< y >< num >< type > Deprecated:Replaced by<< _sound2 >> map_scroll ^^^^^^^^^^ S->C:map_scroll< dx >< dy >< dx >< dy > string of integer value. This tells the client to scroll the map dx and dy direction. dx and dy will typically be -1, 0, or 1, depending on how the player moved.< dx > and< dy > are sent as plaintext. positive values are down and to the right respectively, negative values are opposite. No longer sent, as this data is part of<< _map2 >>. mapredraw ^^^^^^^^^ C->S:mapredraw Requests that the server resend the entire map to the client - can be useful if the client or client player knows that the map is out of date/corrupted. Note that the server is not required to honor this command, and currently just ignores it. Programming Notes ----------------- These are a few quick notes on how things work. Note that they really only apply to the code in the standard distribution, most of the direct i/o is handled by functions that are talked about. If writing a client from scratch, you will need to port this over(or write your own - it isn 't very complicated.) For the server and the C client, a SockList structure is used for basic data handling. Basically, this is just a structure that has an unsigned character buffer and a length field(which contains the length of data in the buffer, not the actual buffer length.) As a side note, when sending a packet, you can supply the length of the data and the sending routines will take care of sending the 2 bytes of length information. When getting a packet, these 2 bytes are at the start of the buffer and not removed. In the client, there is a file called newsocket.c - except for the SockList data type, it could probably be used by itself. The newsocket.c file contains some routines to pack ints, shorts, and single chars into SockList structs, as well as functions for the reverse. It also contains a function to send socklists, as well as read them. The Add??? functions increase the len field of the socklist, the Get??? functions do not change the pointer in anyway. Thus, to get an int and move the buffer, you do something like:int=GetIntString(data)
cf_map_trigger_connected
void cf_map_trigger_connected(objectlink *ol, object *cause, int state)
Wrapper for trigger_connected().
Definition: plugin_common.cpp:1037
CFanimation::ghosted
int ghosted
Definition: cfanim.h:77
Server
Release notes for Crossfire This is see the Changelog file included with the software Major changes since but slower than players without that skill *weather system is hopefully fixed *misc bug fixes Once you have installed the you MUST download a map set point to where you installed Crossfire Server
Definition: Release_notes.txt:32
runstop
static anim_move_result runstop(CFanimation *animation, long int id, void *parameters)
Definition: cfanim.cpp:446
mapstruct
This is a game-map.
Definition: map.h:320
cf_object_set_flag
void cf_object_set_flag(object *ob, int flag, int value)
Definition: plugin_common.cpp:1297
CFmovement
One move in an animation.
Definition: cfanim.h:58
object::env
object * env
Pointer to the object which is the environment.
Definition: object.h:301
sstring
const typedef char * sstring
Definition: sstring.h:2
CFmovement::parent
struct CFanimation * parent
Animation this move is linked to.
Definition: cfanim.h:59
animationcount
int animationcount
Definition: cfanim.cpp:612
initpickup
static long int initpickup(const char *name, char *parameters, CFmovement *move_entity)
Definition: cfanim.cpp:286
teleport_params::mapy
int mapy
Definition: cfanim.cpp:369
cfanim.h
closePlugin
CF_PLUGIN int closePlugin(void)
called before the plugin gets unloaded from memory.
Definition: cfanim.cpp:1318
objects
object * objects
Pointer to the list of used objects.
Definition: object.cpp:294
CFanimation::victim
object * victim
Definition: cfanim.h:70
buffer
if you malloc the data for the buffer
Definition: protocol.txt:2106
get_command
static CFanimationHook * get_command(char *command)
Definition: cfanim.cpp:625
cf_get_maps_directory
char * cf_get_maps_directory(const char *name, char *buf, int size)
Wrapper for create_pathname().
Definition: plugin_common.cpp:1078
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:370
CFanimation::nextanimation
CFanimation * nextanimation
Definition: cfanim.h:84
are
Player Stats effect how well a character can survie and interact inside the crossfire world This section discusses the various what they are
Definition: stats.txt:2
runturn
static anim_move_result runturn(CFanimation *animation, long int id, void *parameters)
Definition: cfanim.cpp:120
teleport_params::mapx
int mapx
Definition: cfanim.cpp:368
runapply
static anim_move_result runapply(CFanimation *animation, long int id, void *parameters)
Definition: cfanim.cpp:222
cfanim_globalEventListener
CF_PLUGIN int cfanim_globalEventListener(int *type,...)
Definition: cfanim.cpp:1254
FLAG_WIZCAST
#define FLAG_WIZCAST
The wizard can cast spells in no-magic area.
Definition: define.h:276
initstop
static long int initstop(const char *name, char *parameters, CFmovement *move_entity)
Definition: cfanim.cpp:438
runfire
static anim_move_result runfire(CFanimation *animation, long int id, void *parameters)
Definition: cfanim.cpp:104
runvisible
static anim_move_result runvisible(CFanimation *animation, long int id, void *parameters)
Definition: cfanim.cpp:167
initturn
static long int initturn(const char *name, char *parameters, CFmovement *move_entity)
Definition: cfanim.cpp:111
CFanimationHook::funcinit
CFAnimInitFunc funcinit
Function to process the parameters of the move.
Definition: cfanim.h:90
object::container
object * container
Current container being used.
Definition: object.h:299
param_moveto::x
int x
Definition: cfanim.cpp:456
a
Magical Runes Runes are magical inscriptions on the dungeon which cast a spell or detonate when something steps on them Flying objects don t detonate runes Beware ! Runes are invisible most of the time They are only visible occasionally ! There are several runes which are there are some special runes which may only be called with the invoke and people may apply it to read it Maybe useful for mazes ! This rune will not nor is it ordinarily invisible Partial Visibility of they ll be visible only part of the time They have a(your level/2) chance of being visible in any given round
CFanimation::event
object * event
Definition: cfanim.h:71
available
Release notes for Crossfire This is see the Changelog file included with the software Major changes since but slower than players without that skill *weather system is hopefully fixed *misc bug fixes Once you have installed the you MUST download a map set point to where you installed Crossfire install Grab map set from official SourceForge page The following sets are available
Definition: Release_notes.txt:38
cf_player_message
void cf_player_message(object *op, const char *txt, int flags)
Definition: plugin_common.cpp:787
initcamera
static long int initcamera(const char *name, char *parameters, CFmovement *move_entity)
Definition: cfanim.cpp:134
cf_map_get_map
mapstruct * cf_map_get_map(const char *name, int flags)
Wrapper for ready_map_name().
Definition: plugin_common.cpp:944
animate
static void animate(void)
Animates all currently running animations.
Definition: cfanim.cpp:1158
initpickupobject
static long int initpickupobject(const char *name, char *parameters, CFmovement *move_entity)
Definition: cfanim.cpp:305
to
Player Stats effect how well a character can survie and interact inside the crossfire world This section discusses the various what they and how they effect the player s actions Also in this section are the stat modifiers that specific classes professions bring Player and sps the current and maximum the Current and Maximum The Current Sp can go somewhat negative When Sp is negative not all spells can be and a more negative Sp makes spell casting less likey to succeed can affect Damage and how the characters as well as how often the character can attack this affects the prices when buying and selling items if this drops to
Definition: stats.txt:56
list
How to Install a Crossfire Server on you must install a python script engine on your computer Python is the default script engine of Crossfire You can find the python engine you have only to install them The VisualC Crossfire settings are for but you habe then to change the pathes in the VC settings Go in Settings C and Settings Link and change the optional include and libs path to the new python installation path o except the maps ! You must download a map package and install them the share folder Its must look like doubleclick on crossfire32 dsw There are projects in your libcross lib and plugin_python You need to compile all Easiest way is to select the plugin_python ReleaseLog as active this will compile all others too Then in Visual C press< F7 > to compile If you don t have an appropriate compiler you can try to get the the VC copies the crossfire32 exe in the crossfire folder and the plugin_python dll in the crossfire share plugins folder we will remove it when we get time for it o Last showing lots of weird write to the Crossfire mailing list
Definition: INSTALL_WIN32.txt:50
cf_object_update
void cf_object_update(object *op, int flags)
Definition: plugin_common.cpp:1447
it
if you malloc the data for the make sure to free it when done There is also the newclient h file which is shared between the client and server This file contains the definition of the as well as many defined values for constants of varying you will need to grab these constant values for yourself Many of the constants in this file are used in the protocol to denote types Image Caching ~ Image caching has been implemented on the with necessary server support to handle it This section will briefly describe how image caching works on the protocol as well as how the current client does it the client checks for an option denoting the image caching is desired If we initialize all the images to a default value this means we don t need to put special checks into the drawing code to see if we have an image we just draw the default we know what filename to store it as we request the server to do image caching This is done by or ing the cache directive to the image mode we want C when the server finds an image number that it has not send to the it sends us a name command information us the number to name and there is no space between that the and the name Such formating is difficult but the above example illustrates the data is sent The client then checks for the existence of the image locally It is up to the client to organize images and then splits them into sub directories based on the first letters in the above the file would be crossfire images CS CSword If the client does not have the image or otherwise needs a copy from the it then requests it
Definition: protocol.txt:2164
teleport_params::mapname
char * mapname
Definition: cfanim.cpp:367
version
Release notes for Crossfire This is see the Changelog file included with the software Major changes since version
Definition: Release_notes.txt:20
CFanimation
One full animation.
Definition: cfanim.h:68
svnversion.h
cf_object_remove
void cf_object_remove(object *op)
Wrapper for object_remove().
Definition: plugin_common.cpp:562
CFanimation::name
char * name
Definition: cfanim.h:69
FLAG_WIZPASS
#define FLAG_WIZPASS
The wizard can go through walls.
Definition: define.h:301
parse_animation_block
static CFmovement * parse_animation_block(char *buffer, size_t buffer_size, FILE *fichier, CFanimation *parent)
Parse an animation block in the animation file.
Definition: cfanim.cpp:642
set
*envar *is the environment if one that can also be used as an override If both the flag and the envar are set
Definition: server-directories.txt:12
cf_map_get_width
int cf_map_get_width(mapstruct *map)
Definition: plugin_common.cpp:1409
runcamera
static anim_move_result runcamera(CFanimation *animation, long int id, void *parameters)
Definition: cfanim.cpp:144
animationbox
CFanimationHook animationbox[]
Available animation commands.
Definition: cfanim.cpp:562
llevDebug
@ llevDebug
Only for debugging purposes.
Definition: logger.h:15
is_valid_types_gen.type
list type
Definition: is_valid_types_gen.py:25
variable
*envar *is the environment variable
Definition: server-directories.txt:9
face
in that case they will be relative to whatever the PWD of the crossfire server process is You probably shouldn though Notes on Specific and settings file datadir Usually usr share crossfire Contains data that the server does not need to modify while such as the etc A default install will pack the and treasurelist definitions into a single or trs file and the graphics into a face(metadata) and .tar(bitmaps) file
CFanimation::delete_end
int delete_end
Definition: cfanim.h:79
runmessage
static anim_move_result runmessage(CFanimation *animation, long int id, void *parameters)
Definition: cfanim.cpp:505
initghosted
static long int initghosted(const char *name, char *parameters, CFmovement *move_entity)
Definition: cfanim.cpp:325
CFanimationHook::name
const char * name
Name as it appears in the animation file.
Definition: cfanim.h:89
usec_elapsed
long usec_elapsed(struct timespec first, struct timespec second)
Return the number of microseconds between two timespec structures.
Definition: cfanim.cpp:1149