Crossfire Server, Trunk  R21524
anim.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
19 #include "global.h"
20 
21 #include <assert.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 static int animations_allocated = 0;
28 
32 void free_all_anim(void) {
33  int i;
34 
35  for (i = 0; i <= num_animations; i++) {
36  free_string(animations[i].name);
37  free(animations[i].faces);
38  }
39  free(animations);
40 }
41 
46 void init_anim(void) {
47  char buf[MAX_BUF];
48  FILE *fp;
49  int num_frames = 0, i;
50  const Face *faces[MAX_ANIMATIONS];
51  Animations *alloc_ptr; // Used to temporarily catch the result of realloc, in case of failure.
52 
54  num_animations = 0;
55  /* Make a default. New animations start at one, so if something
56  * thinks it is animated but hasn't set the animation_id properly,
57  * it will have a default value that should be pretty obvious.
58  */
59  animations = malloc(10*sizeof(Animations));
60  /* set the name so we don't try to dereferance null.
61  * Put # at start so it will be first in alphabetical
62  * order.
63  */
64  animations[0].name = add_string("###none");
66  animations[0].num = 0;
67  animations[0].faces = malloc(sizeof(Face*));
68  animations[0].faces[0] = find_face("bug.111", NULL);
69  animations[0].facings = 0;
70 
71  snprintf(buf, sizeof(buf), "%s/animations", settings.datadir);
72  if ((fp = fopen(buf, "r")) == NULL) {
73  LOG(llevError, "Cannot open animations file %s: %s\n", buf, strerror(errno));
74  exit(-1);
75  }
76  while (fgets(buf, MAX_BUF-1, fp) != NULL) {
77  if (*buf == '#')
78  continue;
79  if (strlen(buf) == 0)
80  break;
81  /* Kill the newline */
82  buf[strlen(buf)-1] = '\0';
83  if (!strncmp(buf, "anim ", 5)) {
84  if (num_frames) {
85  LOG(llevError, "Didn't get a mina before %s\n", buf);
86  num_frames = 0;
87  }
90  /*
91  * We will realloc fewer times if we take larger steps for the realloc size.
92  * This should prevent some copy operations during bootup, albeit at the expense of some RAM.
93  * Most implementations of variable-sized things double each realloc for balance between
94  * space and time efficiency.
95  * Since animations_allocated is one less than the actual amount,
96  * we aren't quite doubling the first allocation size.
97  * Nevertheless, we skip by larger after the first realloc.
98  * We should have enough animations for this to be worthwhile.
99  *
100  * While we are here, handle an allocation failure more gracefully than the inevitable segfault.
101  *
102  * Daniel Hawkins 2018-01-23
103  */
104  alloc_ptr = realloc(animations, sizeof(Animations)*(animations_allocated << 1));
105  if (alloc_ptr)
106  {
107  animations = alloc_ptr;
108  animations_allocated <<= 1;
109  }
110  else
111  {
112  LOG(llevError, "anim: animation array reallocation failed at size %d resizing to %d.\n",
114  // We will not have our animations, so terminate gracefully.
116  }
117  }
119  animations[num_animations].num = num_animations; /* for bsearch */
121  } else if (!strncmp(buf, "mina", 4)) {
122  assert(num_frames > 0);
123  animations[num_animations].faces = malloc(sizeof(Face*)*num_frames);
124  for (i = 0; i < num_frames; i++)
125  animations[num_animations].faces[i] = faces[i];
127  if (num_frames <= 1) {
128  LOG(llevDebug, "anim: %s has less then two faces\n",
129  animations[num_animations].name);
130  }
131  if (num_frames%animations[num_animations].facings) {
132  LOG(llevDebug, "anim: %s has %d frames: not a multiple of facings (%d)\n",
133  animations[num_animations].name, num_frames,
134  animations[num_animations].facings);
135  }
136  num_frames = 0;
137  } else if (!strncmp(buf, "facings", 7)) {
138  if (!(animations[num_animations].facings = atoi(buf+7))) {
139  LOG(llevDebug, "anim: %s has 0 facings (line %s)\n",
140  animations[num_animations].name, buf);
142  }
143  } else {
144  const Face *face = find_face(buf, NULL);
145  if (face == NULL) {
146  LOG(llevError, "Could not find face %s for animation %s\n",
147  buf, animations[num_animations].name);
148  face = find_face("bug.111", NULL);
149  }
150  faces[num_frames++] = face;
151  }
152  }
153  fclose(fp);
154  LOG(llevDebug, "anim: loaded %d animations\n", num_animations);
155 }
156 
161 static int anim_compare(const Animations *a, const Animations *b) {
162  return strcmp(a->name, b->name);
163 }
164 
173 const Animations *find_animation(const char *name) {
174  const Animations *anim = try_find_animation(name);
175  if (!anim)
176  LOG(llevError, "Unable to find animation %s\n", name);
177  return anim ? anim : &animations[0];
178 }
179 
188 const Animations *try_find_animation(const char *name) {
189  Animations search, *match;
190 
191  search.name = name;
192 
193  match = (Animations *)bsearch(&search, animations, (num_animations+1), sizeof(Animations), (int (*)(const void *, const void *))anim_compare);
194 
195  return match;
196 }
197 
212 void animate_object(object *op, int dir) {
213  int max_state; /* Max animation state object should be drawn in */
214  int base_state; /* starting index # to draw from */
215  int oldface = op->face->number;
216 
217  if (!op->animation || !NUM_ANIMATIONS(op)) {
218  StringBuffer *sb;
219  char *diff;
220 
221  LOG(llevError, "Object lacks animation.\n");
222  sb = stringbuffer_new();
223  object_dump(op, sb);
224  diff = stringbuffer_finish(sb);
225  LOG(llevError, "%s", diff);
226  free(diff);
227  return;
228  }
229 
230  if (op->head) {
231  dir = op->head->direction;
232 
233  if (NUM_ANIMATIONS(op) == NUM_ANIMATIONS(op->head))
234  op->state = op->head->state;
235  } else if (QUERY_FLAG(op, FLAG_IS_TURNABLE)) {
236  dir = op->direction;
237  }
238 
239  /* If object is turning, then max animation state is half through the
240  * animations. Otherwise, we can use all the animations.
241  */
242  max_state = NUM_ANIMATIONS(op)/NUM_FACINGS(op);
243  base_state = 0;
244  /* at least in the older aniamtions that used is_turning, the first half
245  * of the animations were left facing, the second half right facing.
246  * Note in old the is_turning, it was set so that the animation for a monster
247  * was always towards the enemy - now it is whatever direction the monster
248  * is facing.
249  */
250  if (NUM_FACINGS(op) == 2) {
251  if (dir < 5)
252  base_state = 0;
253  else
254  base_state = NUM_ANIMATIONS(op)/2;
255  } else if (NUM_FACINGS(op) == 4) {
256  if (dir == 0)
257  base_state = 0;
258  else
259  base_state = ((dir-1)/2)*(NUM_ANIMATIONS(op)/4);
260  } else if (NUM_FACINGS(op) == 8) {
261  if (dir == 0)
262  base_state = 0;
263  else
264  base_state = (dir-1)*(NUM_ANIMATIONS(op)/8);
265  } else if (QUERY_FLAG(op, FLAG_IS_TURNABLE)) {
266  base_state = (NUM_ANIMATIONS(op) / 9) * (dir);
267  max_state = NUM_ANIMATIONS(op) / 9;
268  }
269 
270  /* If beyond drawable states, reset */
271  if (op->state >= max_state) {
272  op->state = 0;
273  if (op->temp_animation) {
274  op->temp_animation = 0;
275  animate_object(op, dir);
276  return;
277  }
278  }
279  SET_ANIMATION(op, op->state+base_state);
280 
281  if (op->face == blank_face)
282  op->invisible = 1;
283 
284  /* This block covers monsters (eg, pixies) which are supposed to
285  * cycle from visible to invisible and back to being visible.
286  * as such, disable it for players, as then players would become
287  * visible.
288  */
289  else if (op->type != PLAYER && QUERY_FLAG((&op->arch->clone), FLAG_ALIVE)) {
290  if (op->face->number == 0) {
291  op->invisible = 1;
292  CLEAR_FLAG(op, FLAG_ALIVE);
293  } else {
294  op->invisible = 0;
295  SET_FLAG(op, FLAG_ALIVE);
296  }
297  }
298 
299  if (op->more)
300  animate_object(op->more, dir);
301 
302  /* object_update() will also recursively update all the pieces.
303  * as such, we call it last, and only call it for the head
304  * piece, and not for the other tail pieces.
305  */
306  if (!op->head && (oldface != op->face->number))
308 }
309 
318 void apply_anim_suffix(object *who, sstring suffix) {
319  const Animations *anim;
320  object *head, *orig;
321  char buf[MAX_BUF];
322 
323  assert(who);
324  assert(suffix);
325 
326  if (who->temp_animation)
327  /* don't overlap animation, let the current one finish. */
328  return;
329 
330  head = HEAD(who);
331  orig = head;
332  snprintf(buf, MAX_BUF, "%s_%s", (head->animation ? head->animation->name : ""), suffix);
333  anim = try_find_animation(buf);
334  if (anim) {
335  for (; head != NULL; head = head->more) {
336  head->temp_animation = anim;
337  head->temp_anim_speed = anim->num_animations / anim->facings;
338  head->last_anim = 0;
339  head->state = 0;
340  }
341  animate_object(orig, orig->facing);
342  }
343 }
344 
348 void dump_animations(void) {
349  int a;
350  fprintf(stderr, "id name faces\n");
351  for (a = 0; a < num_animations; a++) {
352  fprintf(stderr, "%5d %50s %5d\n", animations[a].num, animations[a].name, animations[a].num_animations);
353  }
354 }
#define UP_OBJ_FACE
Definition: object.h:519
void init_anim(void)
Definition: anim.c:46
#define SET_FLAG(xyz, p)
Definition: define.h:223
#define NUM_FACINGS(ob)
Definition: global.h:177
EXTERN int num_animations
Definition: global.h:162
const char * name
Definition: face.h:26
uint8_t last_anim
Definition: object.h:420
const Face * blank_face
Definition: image.c:39
void fatal(enum fatal_error err)
Definition: utils.c:597
Definition: face.h:14
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.c:57
void free_string(sstring str)
Definition: shstr.c:280
const Animations * try_find_animation(const char *name)
Definition: anim.c:188
#define SET_ANIMATION(ob, newanim)
Definition: global.h:167
object clone
Definition: object.h:472
int16_t invisible
Definition: object.h:361
const Animations * temp_animation
Definition: object.h:421
const Face ** faces
Definition: face.h:30
void object_update(object *op, int action)
Definition: object.c:1199
uint8_t temp_anim_speed
Definition: object.h:422
struct animations_struct Animations
void dump_animations(void)
Definition: anim.c:348
void object_dump(const object *op, StringBuffer *sb)
Definition: object.c:415
#define FLAG_ALIVE
Definition: define.h:230
#define MAX_ANIMATIONS
Definition: define.h:39
#define snprintf
Definition: win32.h:46
void free_all_anim(void)
Definition: anim.c:32
uint16_t num
Definition: face.h:29
uint8_t state
Definition: object.h:350
uint8_t num_animations
Definition: face.h:27
int8_t direction
Definition: object.h:335
static int animations_allocated
Definition: anim.c:27
EXTERN Animations * animations
Definition: global.h:161
uint16_t number
Definition: face.h:15
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
#define CLEAR_FLAG(xyz, p)
Definition: define.h:224
#define HEAD(op)
Definition: object.h:594
static int anim_compare(const Animations *a, const Animations *b)
Definition: anim.c:161
#define MAX_BUF
Definition: define.h:35
const Animations * animation
Definition: object.h:418
void animate_object(object *op, int dir)
Definition: anim.c:212
const char * sstring
Definition: global.h:40
Definition: object.h:107
const char * datadir
Definition: global.h:247
const Animations * find_animation(const char *name)
Definition: anim.c:173
#define NUM_ANIMATIONS(ob)
Definition: global.h:176
struct archt * arch
Definition: object.h:414
uint8_t type
Definition: object.h:339
struct Settings settings
Definition: init.c:39
sstring add_string(const char *str)
Definition: shstr.c:124
void apply_anim_suffix(object *who, sstring suffix)
Definition: anim.c:318
struct obj * head
Definition: object.h:296
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
const Face * find_face(const char *name, const Face *error)
Definition: image.c:316
const Face * face
Definition: object.h:332
int8_t facing
Definition: object.h:336
struct obj * more
Definition: object.h:295
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.c:76
uint8_t facings
Definition: face.h:28
#define FLAG_IS_TURNABLE
Definition: define.h:256