|
Atrinik Server 2.5
|
00001 /************************************************************************ 00002 * Atrinik, a Multiplayer Online Role Playing Game * 00003 * * 00004 * Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team * 00005 * * 00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game) * 00007 * and Crossfire (Multiplayer game for X-windows). * 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 * This program is distributed in the hope that it will be useful, * 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00017 * GNU General Public License for more details. * 00018 * * 00019 * You should have received a copy of the GNU General Public License * 00020 * along with this program; if not, write to the Free Software * 00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 00022 * * 00023 * The author can be reached at admin@atrinik.org * 00024 ************************************************************************/ 00025 00030 #include <global.h> 00031 00034 void free_all_anim() 00035 { 00036 int i; 00037 00038 for (i = 0; i <= num_animations; i++) 00039 { 00040 FREE_AND_CLEAR_HASH(animations[i].name); 00041 free(animations[i].faces); 00042 } 00043 00044 free(animations); 00045 } 00046 00050 void init_anim() 00051 { 00052 char buf[MAX_BUF]; 00053 FILE *fp; 00054 static int anim_init = 0; 00055 int num_frames = 0, faces[MAX_ANIMATIONS], i; 00056 00057 if (anim_init) 00058 { 00059 return; 00060 } 00061 00062 animations_allocated = 9; 00063 num_animations = 0; 00064 00065 /* Make a default. New animations start at one, so if something 00066 * thinks it is animated but hasn't set the animation_id properly, 00067 * it will have a default value that should be pretty obvious. */ 00068 animations = malloc(10 * sizeof(Animations)); 00069 /* set the name so we don't try to dereference null. 00070 * Put # at start so it will be first in alphabetical 00071 * order. */ 00072 animations[0].name = NULL; 00073 FREE_AND_COPY_HASH(animations[0].name, "###none" ); 00074 animations[0].num_animations = 1; 00075 animations[0].faces = malloc(sizeof(Fontindex)); 00076 animations[0].faces[0] = 0; 00077 animations[0].facings = 0; 00078 00079 snprintf(buf, sizeof(buf), "%s/animations", settings.datadir); 00080 LOG(llevDebug, "Reading animations from %s...\n", buf); 00081 00082 if ((fp = fopen(buf, "r")) == NULL) 00083 { 00084 LOG(llevError, "Can not open animations file Filename=%s\n", buf); 00085 } 00086 00087 while (fgets(buf, MAX_BUF - 1, fp) != NULL) 00088 { 00089 if (*buf == '#') 00090 { 00091 continue; 00092 } 00093 00094 /* Kill the newline */ 00095 buf[strlen(buf) - 1] = '\0'; 00096 00097 if (!strncmp(buf, "anim ", 5)) 00098 { 00099 if (num_frames) 00100 { 00101 LOG(llevError, "Didn't get a mina before %s\n", buf); 00102 num_frames = 0; 00103 } 00104 00105 num_animations++; 00106 00107 if (num_animations == animations_allocated) 00108 { 00109 animations = realloc(animations, sizeof(Animations) * (animations_allocated + 10)); 00110 animations_allocated += 10; 00111 } 00112 00113 animations[num_animations].name = NULL; 00114 FREE_AND_COPY_HASH(animations[num_animations].name, buf + 5); 00115 /* for bsearch */ 00116 animations[num_animations].num = num_animations; 00117 animations[num_animations].facings = 1; 00118 } 00119 else if (!strncmp(buf, "mina", 4)) 00120 { 00121 animations[num_animations].faces = malloc(sizeof(Fontindex) * num_frames); 00122 00123 for (i = 0; i < num_frames; i++) 00124 { 00125 animations[num_animations].faces[i] = faces[i]; 00126 } 00127 00128 animations[num_animations].num_animations = num_frames; 00129 00130 if (num_frames % animations[num_animations].facings) 00131 { 00132 LOG(llevDebug, "Animation %s frame numbers (%d) is not a multiple of facings (%d)\n", STRING_SAFE(animations[num_animations].name), num_frames, animations[num_animations].facings); 00133 } 00134 00135 num_frames = 0; 00136 } 00137 else if (!strncmp(buf, "facings", 7)) 00138 { 00139 if (!(animations[num_animations].facings = atoi(buf + 7))) 00140 { 00141 LOG(llevDebug, "Animation %s has 0 facings, line=%s\n", STRING_SAFE(animations[num_animations].name), buf); 00142 animations[num_animations].facings = 1; 00143 } 00144 00145 if (animations[num_animations].facings != 9 && animations[num_animations].facings != 25) 00146 { 00147 LOG(llevDebug, "Animation %s has invalid facings parameter (%d - allowed are 9 or 25 only).", STRING_SAFE(animations[num_animations].name), animations[num_animations].facings); 00148 animations[num_animations].facings = 1; 00149 } 00150 } 00151 else 00152 { 00153 if (!(faces[num_frames++] = find_face(buf, 0))) 00154 { 00155 LOG(llevBug, "Could not find face %s for animation %s\n", buf, STRING_SAFE(animations[num_animations].name)); 00156 } 00157 } 00158 } 00159 00160 fclose(fp); 00161 00162 LOG(llevDebug, "done. (got %d)\n", num_animations); 00163 } 00164 00172 static int anim_compare(Animations *a, Animations *b) 00173 { 00174 return strcmp(a->name, b->name); 00175 } 00176 00182 int find_animation(char *name) 00183 { 00184 Animations search, *match; 00185 00186 search.name = name; 00187 00188 match = (Animations *) bsearch(&search, animations, (num_animations + 1), sizeof(Animations), (void *) (int (*)()) anim_compare); 00189 00190 if (match) 00191 { 00192 return match->num; 00193 } 00194 00195 LOG(llevBug, "Unable to find animation %s\n", STRING_SAFE(name)); 00196 return 0; 00197 } 00198 00204 void animate_object(object *op, int count) 00205 { 00206 int numfacing, numanim; 00207 /* Max animation state object should be drawn in */ 00208 int max_state; 00209 /* starting index # to draw from */ 00210 int base_state; 00211 int dir; 00212 00213 numanim = NUM_ANIMATIONS(op); 00214 numfacing = NUM_FACINGS(op); 00215 00216 if (!op->animation_id || !numanim || op->head) 00217 { 00218 #if 0 00219 /* ONLY activate for active debugging */ 00220 if (op->animation_id) 00221 LOG(llevBug,"Object %s (arch %s) lacks animation. (is tail: %s)\n", STRING_OBJ_NAME(op), STRING_OBJ_ARCH_NAME(op), op->head ? "yes" : "no"); 00222 #endif 00223 return; 00224 } 00225 00226 /* An animation is not only changed by anim_speed. 00227 * If we turn the object by a teleporter for example, the direction & facing can 00228 * change - outside the normal animation loop. 00229 * We have then to change the frame and not increase the state */ 00230 if ((!QUERY_FLAG(op, FLAG_SLEEP) && !QUERY_FLAG(op, FLAG_PARALYZED))) 00231 { 00232 op->state += count; 00233 } 00234 00235 if (!count) 00236 { 00237 if (op->type == PLAYER) 00238 { 00239 if (!CONTR(op)->anim_flags && op->anim_moving_dir == op->anim_moving_dir_last && op->anim_last_facing == op->anim_last_facing_last) 00240 { 00241 return; 00242 } 00243 } 00244 else 00245 { 00246 /* Object needs no update for moving */ 00247 if (op->anim_enemy_dir == op->anim_enemy_dir_last && op->anim_moving_dir == op->anim_moving_dir_last && op->anim_last_facing == op->anim_last_facing_last) 00248 { 00249 return; 00250 } 00251 } 00252 } 00253 00254 dir = op->direction; 00255 00256 /* If object is turning, then max animation state is half through the 00257 * animations. Otherwise, we can use all the animations. */ 00258 max_state= numanim / numfacing; 00259 base_state = 0; 00260 00261 /* 0: "stay" "non direction" face 00262 * 1-8: point of the compass the object is facing. */ 00263 if (numfacing == 9) 00264 { 00265 base_state = dir * (numanim / 9); 00266 00267 /* If beyond drawable states, reset */ 00268 if (op->state >= max_state) 00269 { 00270 op->state = 0; 00271 } 00272 } 00273 00274 /* that's the new extended animation: base_state is */ 00275 /* 0: that's the dying anim - "non direction" facing */ 00276 /* 1-8: guard/stand_still anim frames */ 00277 /* 9-16: move anim frames */ 00278 /* 17-24: close fight anim frames */ 00279 /* TODO: allow different number of faces in each frame */ 00280 else if (numfacing >= 25) 00281 { 00282 if (op->type == PLAYER) 00283 { 00284 /* Check flags - perhaps we have hit something in close fight */ 00285 if ((CONTR(op)->anim_flags & PLAYER_AFLAG_ADDFRAME || CONTR(op)->anim_flags & PLAYER_AFLAG_ENEMY) && !(CONTR(op)->anim_flags & PLAYER_AFLAG_FIGHT)) 00286 { 00287 /* Do swing animation, starting at frame 0 */ 00288 op->state = 0; 00289 00290 if (CONTR(op)->anim_flags & PLAYER_AFLAG_ENEMY) 00291 { 00292 /* So we do one more swing */ 00293 CONTR(op)->anim_flags |= PLAYER_AFLAG_ADDFRAME; 00294 /* So we do one swing */ 00295 CONTR(op)->anim_flags |= PLAYER_AFLAG_FIGHT; 00296 } 00297 else 00298 { 00299 /* Only do ADDFRAME if we are still fighting something */ 00300 if (op->enemy && is_melee_range(op, op->enemy)) 00301 { 00302 CONTR(op)->anim_flags |= PLAYER_AFLAG_FIGHT; 00303 } 00304 00305 /* We do our additional frame*/ 00306 CONTR(op)->anim_flags &=~PLAYER_AFLAG_ADDFRAME; 00307 } 00308 00309 /* Clear enemy, set fight */ 00310 CONTR(op)->anim_flags &=~PLAYER_AFLAG_ENEMY; 00311 } 00312 00313 /* Now setup the best animation for our action */ 00314 if (CONTR(op)->anim_flags & PLAYER_AFLAG_FIGHT) 00315 { 00316 op->anim_enemy_dir_last = op->anim_enemy_dir; 00317 00318 /* Test of moving when swing */ 00319 if (op->anim_moving_dir != -1) 00320 { 00321 /* Face in moving direction */ 00322 dir = op->anim_moving_dir; 00323 op->anim_moving_dir_last = op->anim_moving_dir; 00324 } 00325 else 00326 { 00327 /* Face to last direction we had done something */ 00328 if (op->anim_enemy_dir != -1) 00329 { 00330 dir = op->anim_enemy_dir; 00331 } 00332 else 00333 { 00334 dir = op->anim_last_facing; 00335 } 00336 } 00337 00338 /* If we have no idea where we faced, we face to enemy */ 00339 if (!dir || dir == -1) 00340 { 00341 dir = 4; 00342 } 00343 00344 op->anim_last_facing = dir; 00345 op->anim_last_facing_last = -1; 00346 dir += 16; 00347 } 00348 /* Test of moving */ 00349 else if (op->anim_moving_dir != -1) 00350 { 00351 /* Face in moving direction */ 00352 dir = op->anim_moving_dir; 00353 op->anim_moving_dir_last = op->anim_moving_dir; 00354 op->anim_enemy_dir_last = -1; 00355 00356 /* Same spot will be mapped to south dir */ 00357 if (!dir) 00358 { 00359 dir = 4; 00360 } 00361 00362 op->anim_last_facing = dir; 00363 op->anim_last_facing_last = -1; 00364 dir += 8; 00365 } 00366 /* If nothing to do: object is doing nothing. Use original facing */ 00367 else 00368 { 00369 /* Face to last direction we had done something */ 00370 if (op->anim_enemy_dir != -1) 00371 { 00372 dir = op->anim_enemy_dir; 00373 } 00374 else 00375 { 00376 dir = op->anim_last_facing; 00377 } 00378 00379 op->anim_last_facing_last = dir; 00380 00381 /* Same spot will be mapped to south dir */ 00382 if (!dir || dir == -1) 00383 { 00384 op->anim_last_facing = dir = 4; 00385 } 00386 } 00387 00388 base_state = dir * (numanim / numfacing); 00389 00390 /* If beyond drawable states, reset */ 00391 if (op->state >= max_state) 00392 { 00393 op->state = 0; 00394 /* Always clear fighting flag */ 00395 CONTR(op)->anim_flags &= ~PLAYER_AFLAG_FIGHT; 00396 } 00397 } 00398 /* Monster and non player animations */ 00399 else 00400 { 00401 /* Mob has targeted an enemy and faces him. When me move, we strafe sidewards */ 00402 if (op->anim_enemy_dir != -1 && (!QUERY_FLAG(op, FLAG_RUN_AWAY) && !QUERY_FLAG(op, FLAG_SCARED))) 00403 { 00404 /* Face to the enemy position */ 00405 dir = op->anim_enemy_dir; 00406 op->anim_enemy_dir_last = op->anim_enemy_dir; 00407 op->anim_moving_dir_last = -1; 00408 00409 /* Same spot will be mapped to south dir */ 00410 if (!dir) 00411 { 00412 dir = 4; 00413 } 00414 00415 op->anim_last_facing = dir; 00416 op->anim_last_facing_last = -1; 00417 dir += 16; 00418 } 00419 /* Test of moving */ 00420 else if (op->anim_moving_dir != -1) 00421 { 00422 /* Face in moving direction */ 00423 dir = op->anim_moving_dir; 00424 op->anim_moving_dir_last = op->anim_moving_dir; 00425 op->anim_enemy_dir_last = -1; 00426 00427 /* Same spot will be mapped to south dir */ 00428 if (!dir) 00429 { 00430 dir = 4; 00431 } 00432 00433 op->anim_last_facing = dir; 00434 op->anim_last_facing_last = -1; 00435 dir += 8; 00436 } 00437 else 00438 { 00439 /* Face to last direction we had done something */ 00440 dir = op->anim_last_facing; 00441 op->anim_last_facing_last = dir; 00442 00443 /* Same spot will be mapped to south dir */ 00444 if (!dir || dir == -1) 00445 { 00446 op->anim_last_facing = dir = 4; 00447 } 00448 } 00449 00450 base_state = dir * (numanim / numfacing); 00451 00452 /* If beyond drawable states, reset */ 00453 if (op->state >= max_state) 00454 { 00455 op->state = 0; 00456 } 00457 } 00458 } 00459 else 00460 { 00461 /* If beyond drawable states, reset */ 00462 if (op->state >= max_state) 00463 { 00464 op->state = 0; 00465 } 00466 } 00467 00468 SET_ANIMATION(op, op->state + base_state); 00469 00470 update_object(op, UP_OBJ_FACE); 00471 }
1.7.4