Crossfire Server, Trunk  R20513
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 
51  num_animations = 0;
52  /* Make a default. New animations start at one, so if something
53  * thinks it is animated but hasn't set the animation_id properly,
54  * it will have a default value that should be pretty obvious.
55  */
56  animations = malloc(10*sizeof(Animations));
57  /* set the name so we don't try to dereferance null.
58  * Put # at start so it will be first in alphabetical
59  * order.
60  */
61  animations[0].name = add_string("###none");
63  animations[0].faces = malloc(sizeof(New_Face*));
64  animations[0].faces[0] = &new_faces[find_face("bug.111", 0)];
65  animations[0].facings = 0;
66 
67  snprintf(buf, sizeof(buf), "%s/animations", settings.datadir);
68  if ((fp = fopen(buf, "r")) == NULL) {
69  LOG(llevError, "Cannot open animations file %s: %s\n", buf, strerror(errno));
70  exit(-1);
71  }
72  while (fgets(buf, MAX_BUF-1, fp) != NULL) {
73  if (*buf == '#')
74  continue;
75  if (strlen(buf) == 0)
76  break;
77  /* Kill the newline */
78  buf[strlen(buf)-1] = '\0';
79  if (!strncmp(buf, "anim ", 5)) {
80  if (num_frames) {
81  LOG(llevError, "Didn't get a mina before %s\n", buf);
82  num_frames = 0;
83  }
86  animations = realloc(animations, sizeof(Animations)*(animations_allocated+10));
88  }
90  animations[num_animations].num = num_animations; /* for bsearch */
92  } else if (!strncmp(buf, "mina", 4)) {
93  assert(num_frames > 0);
94  animations[num_animations].faces = malloc(sizeof(New_Face*)*num_frames);
95  for (i = 0; i < num_frames; i++)
96  animations[num_animations].faces[i] = faces[i];
98  if (num_frames <= 1) {
99  LOG(llevDebug, "anim: %s has less then two faces\n",
100  animations[num_animations].name);
101  }
102  if (num_frames%animations[num_animations].facings) {
103  LOG(llevDebug, "anim: %s has %d frames: not a multiple of facings (%d)\n",
104  animations[num_animations].name, num_frames,
105  animations[num_animations].facings);
106  }
107  num_frames = 0;
108  } else if (!strncmp(buf, "facings", 7)) {
109  if (!(animations[num_animations].facings = atoi(buf+7))) {
110  LOG(llevDebug, "anim: %s has 0 facings (line %s)\n",
111  animations[num_animations].name, buf);
113  }
114  } else {
115  unsigned face = find_face(buf, (unsigned)-1);
116  if (face == (unsigned)-1) {
117  LOG(llevError, "Could not find face %s for animation %s\n",
118  buf, animations[num_animations].name);
119  face = find_face("bug.111", 0);
120  }
121  faces[num_frames++] = &new_faces[face];
122  }
123  }
124  fclose(fp);
125  LOG(llevDebug, "anim: loaded %d animations\n", num_animations);
126 }
127 
132 static int anim_compare(const Animations *a, const Animations *b) {
133  return strcmp(a->name, b->name);
134 }
135 
144 int find_animation(const char *name) {
145  int face = try_find_animation(name);
146  if (!face)
147  LOG(llevError, "Unable to find animation %s\n", name);
148  return face;
149 }
150 
159 int try_find_animation(const char *name) {
160  Animations search, *match;
161 
162  search.name = name;
163 
164  match = (Animations *)bsearch(&search, animations, (num_animations+1), sizeof(Animations), (int (*)(const void *, const void *))anim_compare);
165 
166 
167  if (match)
168  return match->num;
169  return 0;
170 }
171 
186 void animate_object(object *op, int dir) {
187  int max_state; /* Max animation state object should be drawn in */
188  int base_state; /* starting index # to draw from */
189  int oldface = op->face->number;
190 
191  if (!op->animation_id || !NUM_ANIMATIONS(op)) {
192  StringBuffer *sb;
193  char *diff;
194 
195  LOG(llevError, "Object lacks animation.\n");
196  sb = stringbuffer_new();
197  object_dump(op, sb);
198  diff = stringbuffer_finish(sb);
199  LOG(llevError, "%s", diff);
200  free(diff);
201  return;
202  }
203 
204  if (op->head) {
205  dir = op->head->direction;
206 
207  if (NUM_ANIMATIONS(op) == NUM_ANIMATIONS(op->head))
208  op->state = op->head->state;
209  } else if (QUERY_FLAG(op, FLAG_IS_TURNABLE)) {
210  dir = op->direction;
211  }
212 
213  /* If object is turning, then max animation state is half through the
214  * animations. Otherwise, we can use all the animations.
215  */
216  max_state = NUM_ANIMATIONS(op)/NUM_FACINGS(op);
217  base_state = 0;
218  /* at least in the older aniamtions that used is_turning, the first half
219  * of the animations were left facing, the second half right facing.
220  * Note in old the is_turning, it was set so that the animation for a monster
221  * was always towards the enemy - now it is whatever direction the monster
222  * is facing.
223  */
224  if (NUM_FACINGS(op) == 2) {
225  if (dir < 5)
226  base_state = 0;
227  else
228  base_state = NUM_ANIMATIONS(op)/2;
229  } else if (NUM_FACINGS(op) == 4) {
230  if (dir == 0)
231  base_state = 0;
232  else
233  base_state = ((dir-1)/2)*(NUM_ANIMATIONS(op)/4);
234  } else if (NUM_FACINGS(op) == 8) {
235  if (dir == 0)
236  base_state = 0;
237  else
238  base_state = (dir-1)*(NUM_ANIMATIONS(op)/8);
239  } else if (QUERY_FLAG(op, FLAG_IS_TURNABLE)) {
240  base_state = (NUM_ANIMATIONS(op) / 9) * (dir);
241  max_state = NUM_ANIMATIONS(op) / 9;
242  }
243 
244  /* If beyond drawable states, reset */
245  if (op->state >= max_state) {
246  op->state = 0;
247  if (op->temp_animation_id) {
248  op->temp_animation_id = 0;
249  animate_object(op, dir);
250  return;
251  }
252  }
253  SET_ANIMATION(op, op->state+base_state);
254 
255  if (op->face == blank_face)
256  op->invisible = 1;
257 
258  /* This block covers monsters (eg, pixies) which are supposed to
259  * cycle from visible to invisible and back to being visible.
260  * as such, disable it for players, as then players would become
261  * visible.
262  */
263  else if (op->type != PLAYER && QUERY_FLAG((&op->arch->clone), FLAG_ALIVE)) {
264  if (op->face->number == 0) {
265  op->invisible = 1;
266  CLEAR_FLAG(op, FLAG_ALIVE);
267  } else {
268  op->invisible = 0;
269  SET_FLAG(op, FLAG_ALIVE);
270  }
271  }
272 
273  if (op->more)
274  animate_object(op->more, dir);
275 
276  /* object_update() will also recursively update all the pieces.
277  * as such, we call it last, and only call it for the head
278  * piece, and not for the other tail pieces.
279  */
280  if (!op->head && (oldface != op->face->number))
282 }
283 
292 void apply_anim_suffix(object *who, sstring suffix) {
293  int anim;
294  object *head, *orig;
295  char buf[MAX_BUF];
296 
297  assert(who);
298  assert(suffix);
299 
300  if (who->temp_animation_id != 0)
301  /* don't overlap animation, let the current one finish. */
302  return;
303 
304  head = HEAD(who);
305  orig = head;
306  snprintf(buf, MAX_BUF, "%s_%s", animations[head->animation_id].name, suffix);
307  anim = try_find_animation(buf);
308  if (anim) {
309  for (; head != NULL; head = head->more) {
310  head->temp_animation_id = anim;
312  head->last_anim = 0;
313  head->state = 0;
314  }
315  animate_object(orig, orig->facing);
316  }
317 }
318 
322 void dump_animations(void) {
323  int a;
324  fprintf(stderr, "id name faces\n");
325  for (a = 0; a < num_animations; a++) {
326  fprintf(stderr, "%5d %50s %5d\n", animations[a].num, animations[a].name, animations[a].num_animations);
327  }
328 }
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
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:322
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:144
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:159
#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:132
#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:186
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:292
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