00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00034 #include <global.h>
00035 #include <stdio.h>
00036 #include <assert.h>
00037
00041 void free_all_anim(void) {
00042 int i;
00043
00044 for (i = 0; i <= num_animations; i++) {
00045 free_string(animations[i].name);
00046 free(animations[i].faces);
00047 }
00048 free(animations);
00049 }
00050
00055 void init_anim(void) {
00056 char buf[MAX_BUF];
00057 FILE *fp;
00058 int num_frames = 0, faces[MAX_ANIMATIONS], i;
00059
00060 animations_allocated = 9;
00061 num_animations = 0;
00062
00063
00064
00065
00066 animations = malloc(10*sizeof(Animations));
00067
00068
00069
00070
00071 animations[0].name = add_string("###none");
00072 animations[0].num_animations = 1;
00073 animations[0].faces = malloc(sizeof(Fontindex));
00074 animations[0].faces[0] = 0;
00075 animations[0].facings = 0;
00076
00077 snprintf(buf, sizeof(buf), "%s/animations", settings.datadir);
00078 LOG(llevDebug, "Reading animations from %s...\n", buf);
00079 if ((fp = fopen(buf, "r")) == NULL) {
00080 LOG(llevError, "Cannot open animations file %s: %s\n", buf, strerror_local(errno, buf, sizeof(buf)));
00081 exit(-1);
00082 }
00083 while (fgets(buf, MAX_BUF-1, fp) != NULL) {
00084 if (*buf == '#')
00085 continue;
00086 if (strlen(buf) == 0)
00087 break;
00088
00089 buf[strlen(buf)-1] = '\0';
00090 if (!strncmp(buf, "anim ", 5)) {
00091 if (num_frames) {
00092 LOG(llevError, "Didn't get a mina before %s\n", buf);
00093 num_frames = 0;
00094 }
00095 num_animations++;
00096 if (num_animations == animations_allocated) {
00097 animations = realloc(animations, sizeof(Animations)*(animations_allocated+10));
00098 animations_allocated += 10;
00099 }
00100 animations[num_animations].name = add_string(buf+5);
00101 animations[num_animations].num = num_animations;
00102 animations[num_animations].facings = 1;
00103 } else if (!strncmp(buf, "mina", 4)) {
00104 animations[num_animations].faces = malloc(sizeof(Fontindex)*num_frames);
00105 for (i = 0; i < num_frames; i++)
00106 animations[num_animations].faces[i] = faces[i];
00107 animations[num_animations].num_animations = num_frames;
00108 if (num_frames%animations[num_animations].facings) {
00109 LOG(llevDebug, "Animation %s frame numbers (%d) is not a multiple of facings (%d)\n",
00110 animations[num_animations].name, num_frames, animations[num_animations].facings);
00111 }
00112 num_frames = 0;
00113 } else if (!strncmp(buf, "facings", 7)) {
00114 if (!(animations[num_animations].facings = atoi(buf+7))) {
00115 LOG(llevDebug, "Animation %s has 0 facings, line=%s\n",
00116 animations[num_animations].name, buf);
00117 animations[num_animations].facings = 1;
00118 }
00119
00120 } else {
00121 if (!(faces[num_frames++] = find_face(buf, 0)))
00122 LOG(llevDebug, "Could not find face %s for animation %s\n",
00123 buf, animations[num_animations].name);
00124 }
00125 }
00126 fclose(fp);
00127 LOG(llevDebug, "done. got (%d)\n", num_animations);
00128 }
00129
00134 static int anim_compare(const Animations *a, const Animations *b) {
00135 return strcmp(a->name, b->name);
00136 }
00137
00146 int find_animation(const char *name) {
00147 int face = try_find_animation(name);
00148 if (!face)
00149 LOG(llevError, "Unable to find animation %s\n", name);
00150 return face;
00151 }
00152
00161 int try_find_animation(const char *name) {
00162 Animations search, *match;
00163
00164 search.name = name;
00165
00166 match = (Animations *)bsearch(&search, animations, (num_animations+1), sizeof(Animations), (int (*)(const void *, const void *))anim_compare);
00167
00168
00169 if (match)
00170 return match->num;
00171 return 0;
00172 }
00173
00186 void animate_object(object *op, int dir) {
00187 int max_state;
00188 int base_state;
00189 int oldface = op->face->number;
00190
00191 if (!op->animation_id || !NUM_ANIMATIONS(op)) {
00192 StringBuffer *sb;
00193 char *diff;
00194
00195 LOG(llevError, "Object lacks animation.\n");
00196 sb = stringbuffer_new();
00197 dump_object(op, sb);
00198 diff = stringbuffer_finish(sb);
00199 LOG(llevError, diff);
00200 free(diff);
00201 return;
00202 }
00203
00204 if (op->head) {
00205 dir = op->head->direction;
00206
00207 if (NUM_ANIMATIONS(op) == NUM_ANIMATIONS(op->head))
00208 op->state = op->head->state;
00209 }
00210
00211
00212
00213
00214 max_state = NUM_ANIMATIONS(op)/NUM_FACINGS(op);
00215 base_state = 0;
00216
00217
00218
00219
00220
00221
00222 if (NUM_FACINGS(op) == 2) {
00223 if (dir < 5)
00224 base_state = 0;
00225 else
00226 base_state = NUM_ANIMATIONS(op)/2;
00227 } else if (NUM_FACINGS(op) == 4) {
00228 if (dir == 0)
00229 base_state = 0;
00230 else
00231 base_state = ((dir-1)/2)*(NUM_ANIMATIONS(op)/4);
00232 } else if (NUM_FACINGS(op) == 8) {
00233 if (dir == 0)
00234 base_state = 0;
00235 else
00236 base_state = (dir-1)*(NUM_ANIMATIONS(op)/8);
00237 }
00238
00239
00240 if (op->state >= max_state) {
00241 op->state = 0;
00242 if (op->temp_animation_id) {
00243 op->temp_animation_id = 0;
00244
00245
00246 animate_object(op, dir);
00247 return;
00248 }
00249 }
00250 SET_ANIMATION(op, op->state+base_state);
00251
00252 if (op->face == blank_face)
00253 op->invisible = 1;
00254
00255
00256
00257
00258
00259
00260 else if (op->type != PLAYER && QUERY_FLAG((&op->arch->clone), FLAG_ALIVE)) {
00261 if (op->face->number == 0) {
00262 op->invisible = 1;
00263 CLEAR_FLAG(op, FLAG_ALIVE);
00264 } else {
00265 op->invisible = 0;
00266 SET_FLAG(op, FLAG_ALIVE);
00267 }
00268 }
00269
00270 if (op->more)
00271 animate_object(op->more, dir);
00272
00273
00274
00275
00276
00277 if (!op->head && (oldface != op->face->number))
00278 update_object(op, UP_OBJ_FACE);
00279 }
00280
00289 void apply_anim_suffix(object *who, sstring suffix) {
00290 int anim;
00291 object *head, *orig;
00292 char buf[MAX_BUF];
00293
00294 assert(who);
00295 assert(suffix);
00296
00297 if (who->temp_animation_id != 0)
00298
00299 return;
00300
00301 if (who->head != NULL)
00302 head = who->head;
00303 else
00304 head = who;
00305 orig = head;
00306 snprintf(buf, MAX_BUF, "%s_%s", animations[head->animation_id].name, suffix);
00307 anim = try_find_animation(buf);
00308 if (anim) {
00309 for (; head != NULL; head = head->more) {
00310 head->temp_animation_id = anim;
00311 head->temp_anim_speed = animations[anim].num_animations/animations[anim].facings;
00312 head->temp_last_anim = 0;
00313 head->last_anim = 0;
00314 head->state = 0;
00315 }
00316 animate_object(orig, orig->facing);
00317 }
00318 }