Atrinik Server  4.0
anim.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
30 #include <global.h>
31 #include <object.h>
32 
33 Animations *animations = NULL;
34 int num_animations = 0, animations_allocated;
35 
39 void free_all_anim(void)
40 {
41  int i;
42 
43  if (animations) {
44  for (i = 0; i <= num_animations; i++) {
45  FREE_AND_CLEAR_HASH(animations[i].name);
46  efree(animations[i].faces);
47  }
48 
49  efree(animations);
50  }
51 }
52 
57 void init_anim(void)
58 {
59  char buf[MAX_BUF];
60  FILE *fp;
61  static int anim_init = 0;
62  int num_frames = 0, faces[MAX_ANIMATIONS], i;
63 
64  if (anim_init) {
65  return;
66  }
67 
68  animations_allocated = 9;
69  num_animations = 0;
70 
71  /* Make a default. New animations start at one, so if something
72  * thinks it is animated but hasn't set the animation_id properly,
73  * it will have a default value that should be pretty obvious. */
74  animations = emalloc(10 * sizeof(Animations));
75  /* set the name so we don't try to dereference null.
76  * Put # at start so it will be first in alphabetical
77  * order. */
78  animations[0].name = NULL;
79  FREE_AND_COPY_HASH(animations[0].name, "###none" );
80  animations[0].num_animations = 1;
81  animations[0].faces = emalloc(sizeof(Fontindex));
82  animations[0].faces[0] = 0;
83  animations[0].facings = 0;
84 
85  snprintf(buf, sizeof(buf), "%s/animations", settings.libpath);
86 
87  if ((fp = fopen(buf, "r")) == NULL) {
88  LOG(ERROR, "Can not open animations file %s.", buf);
89  exit(1);
90  }
91 
92  while (fgets(buf, MAX_BUF - 1, fp) != NULL) {
93  if (*buf == '#') {
94  continue;
95  }
96 
97  /* Kill the newline */
98  buf[strlen(buf) - 1] = '\0';
99 
100  if (!strncmp(buf, "anim ", 5)) {
101  if (num_frames) {
102  LOG(ERROR, "Didn't get a mina before %s.", buf);
103  exit(1);
104  }
105 
106  num_animations++;
107 
108  if (num_animations == animations_allocated) {
109  animations = erealloc(animations, sizeof(Animations) * (animations_allocated + 10));
110  animations_allocated += 10;
111  }
112 
113  animations[num_animations].name = NULL;
114  FREE_AND_COPY_HASH(animations[num_animations].name, buf + 5);
115  /* for bsearch */
116  animations[num_animations].num = num_animations;
117  animations[num_animations].facings = 1;
118  } else if (!strncmp(buf, "mina", 4)) {
119  animations[num_animations].faces = emalloc(sizeof(Fontindex) * num_frames);
120 
121  for (i = 0; i < num_frames; i++) {
122  animations[num_animations].faces[i] = faces[i];
123  }
124 
125  animations[num_animations].num_animations = num_frames;
126 
127  if (num_frames % animations[num_animations].facings) {
128  LOG(DEBUG, "Animation %s frame numbers (%d) is not a multiple of facings (%d)", STRING_SAFE(animations[num_animations].name), num_frames, animations[num_animations].facings);
129  }
130 
131  num_frames = 0;
132  } else if (!strncmp(buf, "facings", 7)) {
133  if (!(animations[num_animations].facings = atoi(buf + 7))) {
134  LOG(DEBUG, "Animation %s has 0 facings, line=%s", STRING_SAFE(animations[num_animations].name), buf);
135  animations[num_animations].facings = 1;
136  }
137 
138  if (animations[num_animations].facings != 9 && animations[num_animations].facings != 25) {
139  LOG(DEBUG, "Animation %s has invalid facings parameter (%d - allowed are 9 or 25 only).", STRING_SAFE(animations[num_animations].name), animations[num_animations].facings);
140  animations[num_animations].facings = 1;
141  }
142  } else {
143  if (!(faces[num_frames++] = find_face(buf, 0))) {
144  LOG(BUG, "Could not find face %s for animation %s", buf, STRING_SAFE(animations[num_animations].name));
145  }
146  }
147  }
148 
149  fclose(fp);
150 }
151 
163 static int anim_compare(const void *a, const void *b)
164 {
165  return strcmp(((const Animations *) a)->name, ((const Animations *) b)->name);
166 }
167 
176 int find_animation(const char *name)
177 {
178  Animations search, *match;
179 
180  search.name = (char *) name;
181 
182  match = bsearch(&search, animations, (num_animations + 1), sizeof(Animations), anim_compare);
183 
184  if (match) {
185  return match->num;
186  }
187 
188  LOG(BUG, "Unable to find animation %s", STRING_SAFE(name));
189  return 0;
190 }
191 
197 void animate_object(object *op)
198 {
199  if (op->animation_id == 0 || NUM_ANIMATIONS(op) == 0 || op->head != NULL) {
200  return;
201  }
202 
203  op->state += 1;
204 
205  /* If beyond drawable states, reset */
206  if (op->state >= NUM_ANIMATIONS(op) / NUM_FACINGS(op)) {
207  op->state = 0;
208  }
209 }
210 
216 void animate_turning(object *op)
217 {
218  SET_ANIMATION(op, ((NUM_ANIMATIONS(op) / NUM_FACINGS(op)) * op->direction) + op->state);
220 }
int find_face(const char *name, int error)
Definition: image.c:172
void animate_object(object *op)
Definition: anim.c:197
#define FREE_AND_COPY_HASH(_sv_, _nv_)
Definition: global.h:100
#define UP_OBJ_FACE
Definition: object.h:537
void init_anim(void)
Definition: anim.c:57
#define NUM_FACINGS(ob)
Definition: global.h:300
#define SET_ANIMATION(ob, newanim)
Definition: global.h:282
char libpath[MAX_BUF]
Definition: global.h:338
void object_update(object *op, int action)
Definition: object.c:1117
int8_t direction
Definition: object.h:350
uint8_t num_animations
Definition: face.h:70
uint16_t animation_id
Definition: object.h:322
void free_all_anim(void)
Definition: anim.c:39
shstr * name
Definition: face.h:61
uint8_t state
Definition: object.h:344
int find_animation(const char *name)
Definition: anim.c:176
uint8_t facings
Definition: face.h:76
static int anim_compare(const void *a, const void *b)
Definition: anim.c:163
struct settings_struct settings
Definition: init.c:55
uint16_t num
Definition: face.h:67
#define NUM_ANIMATIONS(ob)
Definition: global.h:298
void animate_turning(object *op)
Definition: anim.c:216
#define FREE_AND_CLEAR_HASH(_nv_)
Definition: global.h:130
struct obj * head
Definition: object.h:136
Fontindex * faces
Definition: face.h:64
#define STRING_SAFE(__string__)
Definition: global.h:260