Crossfire Server, Branches 1.12  R18729
anim.c
Go to the documentation of this file.
1 /*
2  * static char *rcsid_anim_c =
3  * "$Id: anim.c 11578 2009-02-23 22:02:27Z lalo $";
4  */
5 
6 /*
7  CrossFire, A Multiplayer game for X-windows
8 
9  Copyright (C) 2002-2003 Mark Wedel & Crossfire Development Team
10  Copyright (C) 1992 Frank Tore Johansen
11 
12  This program is free software; you can redistribute it and/or modify
13  it under the terms of the GNU General Public License as published by
14  the Free Software Foundation; either version 2 of the License, or
15  (at your option) any later version.
16 
17  This program is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  GNU General Public License for more details.
21 
22  You should have received a copy of the GNU General Public License
23  along with this program; if not, write to the Free Software
24  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 
26  The authors can be reached via e-mail at crossfire-devel@real-time.com
27 */
28 
34 #include <global.h>
35 #include <stdio.h>
36 #include <assert.h>
37 
41 void free_all_anim(void) {
42  int i;
43 
44  for (i = 0; i <= num_animations; i++) {
45  free_string(animations[i].name);
46  free(animations[i].faces);
47  }
48  free(animations);
49 }
50 
55 void init_anim(void) {
56  char buf[MAX_BUF];
57  FILE *fp;
58  int num_frames = 0, faces[MAX_ANIMATIONS], i;
59 
61  num_animations = 0;
62  /* Make a default. New animations start at one, so if something
63  * thinks it is animated but hasn't set the animation_id properly,
64  * it will have a default value that should be pretty obvious.
65  */
66  animations = malloc(10*sizeof(Animations));
67  /* set the name so we don't try to dereferance null.
68  * Put # at start so it will be first in alphabetical
69  * order.
70  */
71  animations[0].name = add_string("###none");
73  animations[0].faces = malloc(sizeof(Fontindex));
74  animations[0].faces[0] = 0;
75  animations[0].facings = 0;
76 
77  snprintf(buf, sizeof(buf), "%s/animations", settings.datadir);
78  LOG(llevDebug, "Reading animations from %s...\n", buf);
79  if ((fp = fopen(buf, "r")) == NULL) {
80  LOG(llevError, "Cannot open animations file %s: %s\n", buf, strerror_local(errno, buf, sizeof(buf)));
81  exit(-1);
82  }
83  while (fgets(buf, MAX_BUF-1, fp) != NULL) {
84  if (*buf == '#')
85  continue;
86  if (strlen(buf) == 0)
87  break;
88  /* Kill the newline */
89  buf[strlen(buf)-1] = '\0';
90  if (!strncmp(buf, "anim ", 5)) {
91  if (num_frames) {
92  LOG(llevError, "Didn't get a mina before %s\n", buf);
93  num_frames = 0;
94  }
97  animations = realloc(animations, sizeof(Animations)*(animations_allocated+10));
99  }
101  animations[num_animations].num = num_animations; /* for bsearch */
103  } else if (!strncmp(buf, "mina", 4)) {
104  animations[num_animations].faces = malloc(sizeof(Fontindex)*num_frames);
105  for (i = 0; i < num_frames; i++)
106  animations[num_animations].faces[i] = faces[i];
108  if (num_frames%animations[num_animations].facings) {
109  LOG(llevDebug, "Animation %s frame numbers (%d) is not a multiple of facings (%d)\n",
110  animations[num_animations].name, num_frames, animations[num_animations].facings);
111  }
112  num_frames = 0;
113  } else if (!strncmp(buf, "facings", 7)) {
114  if (!(animations[num_animations].facings = atoi(buf+7))) {
115  LOG(llevDebug, "Animation %s has 0 facings, line=%s\n",
116  animations[num_animations].name, buf);
118  }
119 
120  } else {
121  if (!(faces[num_frames++] = find_face(buf, 0)))
122  LOG(llevDebug, "Could not find face %s for animation %s\n",
123  buf, animations[num_animations].name);
124  }
125  }
126  fclose(fp);
127  LOG(llevDebug, "done. got (%d)\n", num_animations);
128 }
129 
134 static int anim_compare(const Animations *a, const Animations *b) {
135  return strcmp(a->name, b->name);
136 }
137 
146 int find_animation(const char *name) {
147  int face = try_find_animation(name);
148  if (!face)
149  LOG(llevError, "Unable to find animation %s\n", name);
150  return face;
151 }
152 
161 int try_find_animation(const char *name) {
162  Animations search, *match;
163 
164  search.name = name;
165 
166  match = (Animations *)bsearch(&search, animations, (num_animations+1), sizeof(Animations), (int (*)(const void *, const void *))anim_compare);
167 
168 
169  if (match)
170  return match->num;
171  return 0;
172 }
173 
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  dump_object(op, sb);
198  diff = stringbuffer_finish(sb);
199  LOG(llevError, 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  }
210 
211  /* If object is turning, then max animation state is half through the
212  * animations. Otherwise, we can use all the animations.
213  */
214  max_state = NUM_ANIMATIONS(op)/NUM_FACINGS(op);
215  base_state = 0;
216  /* at least in the older aniamtions that used is_turning, the first half
217  * of the animations were left facing, the second half right facing.
218  * Note in old the is_turning, it was set so that the animation for a monster
219  * was always towards the enemy - now it is whatever direction the monster
220  * is facing.
221  */
222  if (NUM_FACINGS(op) == 2) {
223  if (dir < 5)
224  base_state = 0;
225  else
226  base_state = NUM_ANIMATIONS(op)/2;
227  } else if (NUM_FACINGS(op) == 4) {
228  if (dir == 0)
229  base_state = 0;
230  else
231  base_state = ((dir-1)/2)*(NUM_ANIMATIONS(op)/4);
232  } else if (NUM_FACINGS(op) == 8) {
233  if (dir == 0)
234  base_state = 0;
235  else
236  base_state = (dir-1)*(NUM_ANIMATIONS(op)/8);
237  }
238 
239  /* If beyond drawable states, reset */
240  if (op->state >= max_state) {
241  op->state = 0;
242  if (op->temp_animation_id) {
243  op->temp_animation_id = 0;
244  /* op->last_anim = 0; */
245  /* update_object(op, UP_OBJ_FACE); */
246  animate_object(op, dir);
247  return;
248  }
249  }
250  SET_ANIMATION(op, op->state+base_state);
251 
252  if (op->face == blank_face)
253  op->invisible = 1;
254 
255  /* This block covers monsters (eg, pixies) which are supposed to
256  * cycle from visible to invisible and back to being visible.
257  * as such, disable it for players, as then players would become
258  * visible.
259  */
260  else if (op->type != PLAYER && QUERY_FLAG((&op->arch->clone), FLAG_ALIVE)) {
261  if (op->face->number == 0) {
262  op->invisible = 1;
263  CLEAR_FLAG(op, FLAG_ALIVE);
264  } else {
265  op->invisible = 0;
266  SET_FLAG(op, FLAG_ALIVE);
267  }
268  }
269 
270  if (op->more)
271  animate_object(op->more, dir);
272 
273  /* update_object will also recursively update all the pieces.
274  * as such, we call it last, and only call it for the head
275  * piece, and not for the other tail pieces.
276  */
277  if (!op->head && (oldface != op->face->number))
279 }
280 
289 void apply_anim_suffix(object *who, sstring suffix) {
290  int anim;
291  object *head, *orig;
292  char buf[MAX_BUF];
293 
294  assert(who);
295  assert(suffix);
296 
297  if (who->temp_animation_id != 0)
298  /* don't overlap animation, let the current one finish. */
299  return;
300 
301  if (who->head != NULL)
302  head = who->head;
303  else
304  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->temp_last_anim = 0;
313  head->last_anim = 0;
314  head->state = 0;
315  }
316  animate_object(orig, orig->facing);
317  }
318 }
#define UP_OBJ_FACE
Definition: object.h:356
void init_anim(void)
Definition: anim.c:55
#define SET_FLAG(xyz, p)
Definition: define.h:510
#define NUM_FACINGS(ob)
Definition: global.h:256
EXTERN int num_animations
Definition: global.h:242
const char * name
Definition: face.h:55
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.c:64
void free_string(sstring str)
Definition: shstr.c:272
#define SET_ANIMATION(ob, newanim)
Definition: global.h:247
object clone
Definition: object.h:326
sint16 invisible
Definition: object.h:211
uint8 last_anim
Definition: object.h:269
void update_object(object *op, int action)
Definition: object.c:1112
Fontindex * faces
Definition: face.h:59
uint8 temp_anim_speed
Definition: object.h:271
struct animations_struct Animations
#define PLAYER
Definition: define.h:113
uint16 number
Definition: face.h:43
uint8 facings
Definition: face.h:57
#define FLAG_ALIVE
Definition: define.h:526
uint16 num
Definition: face.h:58
#define MAX_ANIMATIONS
Definition: define.h:85
void dump_object(object *op, StringBuffer *sb)
Definition: object.c:372
void free_all_anim(void)
Definition: anim.c:41
uint8 temp_last_anim
Definition: object.h:272
uint16 temp_animation_id
Definition: object.h:270
int find_animation(const char *name)
Definition: anim.c:146
EXTERN Animations * animations
Definition: global.h:241
sint8 facing
Definition: object.h:186
int try_find_animation(const char *name)
Definition: anim.c:161
uint8 num_animations
Definition: face.h:56
#define QUERY_FLAG(xyz, p)
Definition: define.h:514
#define CLEAR_FLAG(xyz, p)
Definition: define.h:512
uint8 state
Definition: object.h:200
static int anim_compare(const Animations *a, const Animations *b)
Definition: anim.c:134
#define MAX_BUF
Definition: define.h:81
void animate_object(object *op, int dir)
Definition: anim.c:186
const char * sstring
Definition: global.h:84
const char * datadir
Definition: global.h:334
int snprintf(char *dest, int max, const char *format,...)
Definition: porting.c:498
sint8 direction
Definition: object.h:185
#define NUM_ANIMATIONS(ob)
Definition: global.h:255
New_Face * blank_face
Definition: image.c:66
struct archt * arch
Definition: object.h:263
struct Settings settings
Definition: init.c:48
EXTERN int animations_allocated
Definition: global.h:242
uint16 animation_id
Definition: object.h:267
sstring add_string(const char *str)
Definition: shstr.c:116
void apply_anim_suffix(object *who, sstring suffix)
Definition: anim.c:289
struct obj * head
Definition: object.h:154
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:63
char * strerror_local(int errnum, char *buf, size_t size)
Definition: porting.c:525
unsigned short Fontindex
Definition: global.h:86
New_Face * face
Definition: object.h:183
unsigned find_face(const char *name, unsigned error)
Definition: image.c:324
struct obj * more
Definition: object.h:153
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.c:78
uint8 type
Definition: object.h:189