Crossfire Server, Trunk  R20553
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].faces = malloc(sizeof(New_Face*));
65  animations[0].faces[0] = &new_faces[find_face("bug.111", 0)];
66  animations[0].facings = 0;
67 
68  snprintf(buf, sizeof(buf), "%s/animations", settings.datadir);
69  if ((fp = fopen(buf, "r")) == NULL) {
70  LOG(llevError, "Cannot open animations file %s: %s\n", buf, strerror(errno));
71  exit(-1);
72  }
73  while (fgets(buf, MAX_BUF-1, fp) != NULL) {
74  if (*buf == '#')
75  continue;
76  if (strlen(buf) == 0)
77  break;
78  /* Kill the newline */
79  buf[strlen(buf)-1] = '\0';
80  if (!strncmp(buf, "anim ", 5)) {
81  if (num_frames) {
82  LOG(llevError, "Didn't get a mina before %s\n", buf);
83  num_frames = 0;
84  }
87  /*
88  * We will realloc fewer times if we take larger steps for the realloc size.
89  * This should prevent some copy operations during bootup, albeit at the expense of some RAM.
90  * Most implementations of variable-sized things double each realloc for balance between
91  * space and time efficiency.
92  * Since animations_allocated is one less than the actual amount,
93  * we aren't quite doubling the first allocation size.
94  * Nevertheless, we skip by larger after the first realloc.
95  * We should have enough animations for this to be worthwhile.
96  *
97  * While we are here, handle an allocation failure more gracefully than the inevitable segfault.
98  *
99  * Daniel Hawkins 2018-01-23
100  */
101  alloc_ptr = realloc(animations, sizeof(Animations)*(animations_allocated << 1));
102  if (alloc_ptr)
103  {
104  animations = alloc_ptr;
105  animations_allocated <<= 1;
106  }
107  else
108  {
109  LOG(llevError, "anim: animation array reallocation failed at size %d resizing to %d.\n",
111  // We will not have our animations, so terminate gracefully.
113  }
114  }
116  animations[num_animations].num = num_animations; /* for bsearch */
118  } else if (!strncmp(buf, "mina", 4)) {
119  assert(num_frames > 0);
120  animations[num_animations].faces = malloc(sizeof(New_Face*)*num_frames);
121  for (i = 0; i < num_frames; i++)
122  animations[num_animations].faces[i] = faces[i];
124  if (num_frames <= 1) {
125  LOG(llevDebug, "anim: %s has less then two faces\n",
126  animations[num_animations].name);
127  }
128  if (num_frames%animations[num_animations].facings) {
129  LOG(llevDebug, "anim: %s has %d frames: not a multiple of facings (%d)\n",
130  animations[num_animations].name, num_frames,
131  animations[num_animations].facings);
132  }
133  num_frames = 0;
134  } else if (!strncmp(buf, "facings", 7)) {
135  if (!(animations[num_animations].facings = atoi(buf+7))) {
136  LOG(llevDebug, "anim: %s has 0 facings (line %s)\n",
137  animations[num_animations].name, buf);
139  }
140  } else {
141  unsigned face = find_face(buf, (unsigned)-1);
142  if (face == (unsigned)-1) {
143  LOG(llevError, "Could not find face %s for animation %s\n",
144  buf, animations[num_animations].name);
145  face = find_face("bug.111", 0);
146  }
147  faces[num_frames++] = &new_faces[face];
148  }
149  }
150  fclose(fp);
151  LOG(llevDebug, "anim: loaded %d animations\n", num_animations);
152 }
153 
158 static int anim_compare(const Animations *a, const Animations *b) {
159  return strcmp(a->name, b->name);
160 }
161 
170 int find_animation(const char *name) {
171  int face = try_find_animation(name);
172  if (!face)
173  LOG(llevError, "Unable to find animation %s\n", name);
174  return face;
175 }
176 
185 int try_find_animation(const char *name) {
186  Animations search, *match;
187 
188  search.name = name;
189 
190  match = (Animations *)bsearch(&search, animations, (num_animations+1), sizeof(Animations), (int (*)(const void *, const void *))anim_compare);
191 
192 
193  if (match)
194  return match->num;
195  return 0;
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_id || !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_id) {
274  op->temp_animation_id = 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  int anim;
320  object *head, *orig;
321  char buf[MAX_BUF];
322 
323  assert(who);
324  assert(suffix);
325 
326  if (who->temp_animation_id != 0)
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", animations[head->animation_id].name, suffix);
333  anim = try_find_animation(buf);
334  if (anim) {
335  for (; head != NULL; head = head->more) {
336  head->temp_animation_id = anim;
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 }
Error, serious thing.
Definition: logger.h:11
#define UP_OBJ_FACE
Only thing that changed was the face.
Definition: object.h:519
void init_anim(void)
Loads the lib/animations file.
Definition: anim.c:44
#define SET_FLAG(xyz, p)
Definition: define.h:223
#define NUM_FACINGS(ob)
Definition: global.h:180
New_Face * new_faces
Contains face information, with names, numbers, magicmap color and such.
Definition: image.c:33
uint16_t animation_id
An index into the animation array.
Definition: object.h:416
EXTERN int num_animations
Definition: global.h:166
const char * name
Name of the animation sequence.
Definition: face.h:27
uint8_t last_anim
Last sequence used to draw face.
Definition: object.h:418
void fatal(enum fatal_error err)
fatal() is meant to be called whenever a fatal signal is intercepted.
Definition: utils.c:596
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
Definition: stringbuffer.c:57
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
Definition: shstr.c:280
#define SET_ANIMATION(ob, newanim)
Definition: global.h:171
object clone
An object from which to do object_copy()
Definition: object.h:470
int16_t invisible
How much longer the object will be invis.
Definition: object.h:360
void object_update(object *op, int action)
object_update() updates the array which represents the map.
Definition: object.c:1239
uint8_t temp_anim_speed
Ticks between temporary animation-frames.
Definition: object.h:420
Global type definitions and header inclusions.
struct animations_struct Animations
This represents one animation.
uint16_t temp_animation_id
An index into the temporary animation array.
Definition: object.h:419
uint16_t number
This is the image id.
Definition: face.h:15
void dump_animations(void)
Dump all animations to stderr, for debugging purposes.
Definition: anim.c:348
void object_dump(const object *op, StringBuffer *sb)
Dumps an object.
Definition: object.c:394
#define FLAG_ALIVE
Object can fight (or be fought)
Definition: define.h:230
#define MAX_ANIMATIONS
Definition: define.h:39
#define snprintf
Definition: win32.h:46
void free_all_anim(void)
Clears all animation-related memory.
Definition: anim.c:30
uint16_t num
Where we are in the array.
Definition: face.h:30
uint8_t state
How the object was last drawn (animation)
Definition: object.h:349
This represents one animation.
Definition: face.h:26
uint8_t num_animations
How many different faces to animate, size of the faces array.
Definition: face.h:28
int8_t direction
Means the object is moving that way.
Definition: object.h:334
int find_animation(const char *name)
Finds the animation id that matches name.
Definition: anim.c:170
EXTERN Animations * animations
Definition: global.h:165
int try_find_animation(const char *name)
Tries to find the animation id that matches name, don&#39;t LOG() an error if not found.
Definition: anim.c:185
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
#define CLEAR_FLAG(xyz, p)
Definition: define.h:224
#define HEAD(op)
Returns the head part of an object.
Definition: object.h:594
static int anim_compare(const Animations *a, const Animations *b)
Utility function to compare 2 animations based on their name.
Definition: anim.c:158
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
void animate_object(object *op, int dir)
Updates the face-variable of an object.
Definition: anim.c:212
const char * sstring
Strings that should be manipulated through add_string() and free_string().
Definition: global.h:40
const New_Face ** faces
The actual faces for the animation.
Definition: face.h:31
See Player.
Definition: object.h:107
const char * datadir
Read only data files.
Definition: global.h:244
#define NUM_ANIMATIONS(ob)
Definition: global.h:179
New_Face * blank_face
Following can just as easily be pointers, but it is easier to keep them like this.
Definition: image.c:39
struct archt * arch
Pointer to archetype.
Definition: object.h:412
Only for debugging purposes.
Definition: logger.h:13
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:338
struct Settings settings
Server settings.
Definition: init.c:40
EXTERN int animations_allocated
Definition: global.h:166
sstring add_string(const char *str)
This will add &#39;str&#39; to the hash table.
Definition: shstr.c:124
New face structure - this enforces the notion that data is face by face only - you can not change the...
Definition: face.h:14
void apply_anim_suffix(object *who, sstring suffix)
Applies a compound animation to an object.
Definition: anim.c:318
struct obj * head
Points to the main object of a large body.
Definition: object.h:296
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.c:51
A buffer that will be expanded as content is added to it.
Definition: stringbuffer.c:25
const New_Face * face
Face with colors.
Definition: object.h:332
int8_t facing
Object is oriented/facing that way.
Definition: object.h:335
unsigned find_face(const char *name, unsigned error)
This returns an the face number of face &#39;name&#39;.
Definition: image.c:303
struct obj * more
Pointer to the rest of a large body of objects.
Definition: object.h:295
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
Definition: stringbuffer.c:76
uint8_t facings
How many facings (1,2,4,8).
Definition: face.h:29
#define FLAG_IS_TURNABLE
Object can change face with direction.
Definition: define.h:256