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