Crossfire Server, Branch 1.12
R12190
|
00001 /*****************************************************************************/ 00002 /* Crossfire Animator v2.0a */ 00003 /* Contacts: yann.chachkoff@myrealbox.com, tchize@myrealbox.com */ 00004 /*****************************************************************************/ 00005 /* That code is placed under the GNU General Public Licence (GPL) */ 00006 /* */ 00007 /* (C) 2001 David Delbecq for the original code version. */ 00008 /*****************************************************************************/ 00009 /* CrossFire, A Multiplayer game for X-windows */ 00010 /* */ 00011 /* Copyright (C) 2000 Mark Wedel */ 00012 /* Copyright (C) 1992 Frank Tore Johansen */ 00013 /* */ 00014 /* This program is free software; you can redistribute it and/or modify */ 00015 /* it under the terms of the GNU General Public License as published by */ 00016 /* the Free Software Foundation; either version 2 of the License, or */ 00017 /* (at your option) any later version. */ 00018 /* */ 00019 /* This program is distributed in the hope that it will be useful, */ 00020 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ 00021 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ 00022 /* GNU General Public License for more details. */ 00023 /* */ 00024 /* You should have received a copy of the GNU General Public License */ 00025 /* along with this program; if not, write to the Free Software */ 00026 /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 00027 /* */ 00028 /*****************************************************************************/ 00029 00030 /* First let's include the header file needed */ 00031 00032 #include <assert.h> 00033 #include <cfanim.h> 00034 #include <stdarg.h> 00035 00036 static CFanimation *first_animation = NULL; 00038 static int get_boolean(const char *strg, int *bl); 00039 00045 static int get_dir_from_name(const char *name) { 00046 if (!strcmp(name, "north")) 00047 return 1; 00048 if (!strcmp(name, "north_east")) 00049 return 2; 00050 if (!strcmp(name, "east")) 00051 return 3; 00052 if (!strcmp(name, "south_east")) 00053 return 4; 00054 if (!strcmp(name, "south")) 00055 return 5; 00056 if (!strcmp(name, "south_west")) 00057 return 6; 00058 if (!strcmp(name, "west")) 00059 return 7; 00060 if (!strcmp(name, "north_west")) 00061 return 8; 00062 return -1; 00063 } 00064 00065 static long int initmovement(const char *name, char *parameters, struct CFmovement_struct *move_entity) { 00066 int dir; 00067 00068 dir = get_dir_from_name(name); 00069 move_entity->parameters = NULL; 00070 return dir; 00071 } 00072 00073 static anim_move_result runmovement(struct CFanimation_struct *animation, long int id, void *parameters) { 00074 object *op = animation->victim; 00075 int dir = id; 00076 00077 if (animation->verbose) 00078 cf_log(llevDebug, "CFAnim: Moving in direction %ld\n", id); 00079 if (op->type == PLAYER) 00080 cf_player_move(op->contr, dir); 00081 else 00082 cf_object_move(op, dir, op); 00083 return mr_finished; 00084 } 00085 00086 static long int initfire(const char *name, char *parameters, struct CFmovement_struct *move_entity) { 00087 int dir; 00088 00089 dir = get_dir_from_name(&(name[5])); 00090 move_entity->parameters = NULL; 00091 return dir; 00092 } 00093 00095 static anim_move_result runfire(struct CFanimation_struct *animation, long int id, void *parameters) { 00096 if (animation->verbose) 00097 cf_log(llevDebug, "CFAnim: Firing in direction %ld\n", id); 00098 return mr_finished; 00099 } 00100 00101 static long int initturn(const char *name, char *parameters, struct CFmovement_struct *move_entity) { 00102 int dir; 00103 00104 dir = get_dir_from_name(&(name[5])); 00105 move_entity->parameters = NULL; 00106 return dir; 00107 } 00108 00109 static anim_move_result runturn(struct CFanimation_struct *animation, long int id, void *parameters) { 00110 object *op = animation->victim; 00111 int dir = id; 00112 int face; 00113 00114 if (animation->verbose) 00115 cf_log(llevDebug, "CFAnim: Turning in direction %ld\n", id); 00116 op->facing = dir; 00117 cf_object_set_int_property(op, CFAPI_OBJECT_PROP_ANIMATION, face); 00118 return mr_finished; 00119 } 00120 00121 static long int initcamera(const char *name, char *parameters, struct CFmovement_struct *move_entity) { 00122 int dir; 00123 00124 dir = get_dir_from_name(&(name[7])); 00125 move_entity->parameters = NULL; 00126 return dir; 00127 } 00128 00130 static anim_move_result runcamera(struct CFanimation_struct *animation, long int id, void *parameters) { 00131 if (animation->verbose) 00132 cf_log(llevDebug, "CFAnim: Moving the camera in direction %ld\n", id); 00133 return mr_finished; 00134 /*if (animation->victim->type == PLAYER) 00135 hook_scroll_map(animation->victim, id); 00136 else 00137 printf("CFAnim: Not a player\n"); 00138 return 1;*/ 00139 } 00140 00141 static long int initvisible(const char *name, char *parameters, struct CFmovement_struct *move_entity) { 00142 int result; 00143 00144 if (get_boolean(parameters, &result)) 00145 return result; 00146 cf_log(llevDebug, "CFAnim: Error in animation - possible values for 'invisible' are 'yes' and 'no'\n"); 00147 return -1; 00148 } 00149 00150 static anim_move_result runvisible(struct CFanimation_struct *animation, long int id, void *parameters) { 00151 if (id == -1) 00152 return mr_finished; 00153 animation->invisible = id; 00154 return mr_finished; 00155 } 00156 00157 static long int initwizard(const char *name, char *parameters, struct CFmovement_struct *move_entity) { 00158 int result; 00159 00160 if (get_boolean(parameters, &result)) 00161 return result; 00162 cf_log(llevDebug, "CFAnim: Error in animation - possible values for 'wizard' are 'yes' and 'no'\n"); 00163 return -1; 00164 } 00165 00166 static anim_move_result runwizard(struct CFanimation_struct *animation, long int id, void *parameters) { 00167 if (id == -1) 00168 return 1; 00169 animation->wizard = id; 00170 return mr_finished; 00171 } 00172 00173 static long int initsay(const char *name, char *parameters, struct CFmovement_struct *move_entity) { 00174 if (parameters) 00175 move_entity->parameters = cf_strdup_local(parameters); 00176 else 00177 move_entity->parameters = NULL; 00178 if (move_entity->parent->verbose) 00179 cf_log(llevDebug, "CFAnim: init say: parameters: %s\n", parameters ? parameters : "null"); 00180 return 1; 00181 } 00182 00183 static anim_move_result runsay(struct CFanimation_struct *animation, long int id, void *parameters) { 00184 if (parameters) { 00185 cf_object_say(animation->victim, parameters); 00186 free(parameters); 00187 } else 00188 cf_log(llevDebug, "CFAnim: Error in animation: nothing to say with say function\n"); 00189 return mr_finished; 00190 } 00191 00192 static long int initapply(const char *name, char *parameters, struct CFmovement_struct *move_entity) { 00193 return 1; 00194 } 00195 00196 static anim_move_result runapply(struct CFanimation_struct *animation, long int id, void *parameters) { 00197 object *current_container; 00198 00199 if (animation->victim->type != PLAYER) 00200 return mr_finished; 00201 current_container = animation->victim->container; 00202 animation->victim->container = NULL; 00203 cf_object_apply_below(animation->victim); 00204 animation->victim->container = current_container; 00205 return mr_finished; 00206 } 00207 00208 static long int initapplyobject(const char *name, char *parameters, struct CFmovement_struct *move_entity) { 00209 move_entity->parameters = parameters ? cf_add_string(parameters) : NULL; 00210 return 1; 00211 } 00212 00213 static anim_move_result runapplyobject(struct CFanimation_struct *animation, long int id, void *parameters) { 00214 object *current; 00215 int aflag; 00216 00217 if (!parameters) 00218 return mr_finished; 00219 for (current = animation->victim->below; current; current = current->below) 00220 if (current->name == parameters) 00221 break; 00222 if (!current) 00223 for (current = animation->victim->inv; current; current = current->below) 00224 if (current->name == parameters) 00225 break; 00226 if (!current) { 00227 cf_free_string(parameters); 00228 return mr_finished; 00229 } 00230 aflag = AP_APPLY; 00231 cf_object_apply(animation->victim, current, aflag); 00232 cf_free_string(parameters); 00233 return mr_finished; 00234 } 00235 00236 static long int initdropobject(const char *name, char *parameters, struct CFmovement_struct *move_entity) { 00237 move_entity->parameters = parameters ? cf_strdup_local(parameters) : NULL; 00238 return 1; 00239 } 00240 00241 static anim_move_result rundropobject(struct CFanimation_struct *animation, long int id, void *parameters) { 00242 if (!parameters) 00243 return mr_finished; 00244 cf_object_drop(animation->victim, parameters); 00245 cf_free_string(parameters); 00246 return mr_finished; 00247 } 00248 00249 static long int initpickup(const char *name, char *parameters, struct CFmovement_struct *move_entity) { 00250 return 1; 00251 } 00252 00253 static anim_move_result runpickup(struct CFanimation_struct *animation, long int id, void *parameters) { 00254 object *current; 00255 00256 current = animation->victim->below; 00257 if (!current) 00258 return mr_finished; 00259 cf_object_pickup(animation->victim, current); 00260 return mr_finished; 00261 } 00262 00263 static long int initpickupobject(const char *name, char *parameters, struct CFmovement_struct *move_entity) { 00264 move_entity->parameters = parameters ? cf_add_string(parameters) : NULL; 00265 return 1; 00266 } 00267 00268 static anim_move_result runpickupobject(struct CFanimation_struct *animation, long int id, void *parameters) { 00269 object *current; 00270 00271 if (!parameters) 00272 return mr_finished; 00273 for (current = animation->victim->below; current; current = current->below) 00274 if (current->name == parameters) 00275 break; 00276 if (current) 00277 cf_object_pickup(animation->victim, current); 00278 cf_free_string(parameters); 00279 return mr_finished; 00280 } 00281 00282 static long int initghosted(const char *name, char *parameters, struct CFmovement_struct *move_entity) { 00283 int result; 00284 00285 if (get_boolean(parameters, &result)) 00286 return result; 00287 cf_log(llevDebug, "CFAnim: Error in animation: possible values for 'ghosted' are 'yes' and 'no'\n"); 00288 return -1; 00289 } 00290 00291 static anim_move_result runghosted(struct CFanimation_struct *animation, long int id, void *parameters) { 00292 object *corpse; 00293 00294 if ((id && animation->ghosted) 00295 || (!id && !animation->ghosted)) 00296 runghosted(animation, !id, parameters); 00297 if (id) { /*Create a ghost/corpse pair*/ 00298 corpse = cf_object_clone(animation->victim, 1); 00299 corpse->x = animation->victim->x; 00300 corpse->y = animation->victim->y; 00301 corpse->type = 0; 00302 CLEAR_FLAG(corpse, FLAG_WIZ); 00303 corpse->contr = NULL; 00304 cf_map_insert_object_there(corpse, animation->victim->map, NULL, 0); 00305 animation->wizard = 1; 00306 animation->invisible = 1; 00307 animation->corpse = corpse; 00308 } else { /*Remove a corpse, make current player visible*/ 00309 animation->wizard = 0; 00310 animation->invisible = 0; 00311 cf_object_remove(animation->corpse); 00312 cf_object_free(animation->corpse); 00313 animation->corpse = NULL; 00314 animation->victim->invisible = 0; 00315 cf_player_move(animation->victim->contr, 0); 00316 } 00317 animation->ghosted = id; 00318 return mr_finished; 00319 } 00320 00321 typedef struct { 00322 char *mapname; 00323 int mapx; 00324 int mapy; 00325 } teleport_params; 00326 00327 static long int initteleport(const char *name, char *parameters, struct CFmovement_struct *move_entity) { 00328 char *mapname; 00329 int mapx; 00330 int mapy; 00331 teleport_params *teleport; 00332 00333 move_entity->parameters = NULL; 00334 cf_log(llevDebug, ".(%s)\n", parameters); 00335 if (!parameters) { 00336 cf_log(llevDebug, "CFAnim: Error - no parameters for teleport\n"); 00337 return 0; 00338 } 00339 mapname = strstr(parameters, " "); 00340 cf_log(llevDebug, ".(%s)\n", parameters); 00341 if (!mapname) 00342 return 0; 00343 *mapname = '\0'; 00344 mapx = atoi(parameters); 00345 mapname++; 00346 parameters = mapname; 00347 if (!parameters) { 00348 cf_log(llevDebug, "CFAnim: Error - not enough parameters for teleport\n"); 00349 return 0; 00350 } 00351 cf_log(llevDebug, ".(%s)\n", parameters); 00352 mapname = strstr(parameters, " "); 00353 cf_log(llevDebug, ".\n"); 00354 if (!mapname) 00355 return 0; 00356 *mapname = '\0'; 00357 mapy = atoi(parameters); 00358 mapname++; 00359 if (mapname[0] == '\0') 00360 return 0; 00361 teleport = (teleport_params *)malloc(sizeof(teleport_params)); 00362 teleport->mapname = cf_strdup_local(mapname); 00363 teleport->mapx = mapx; 00364 teleport->mapy = mapy; 00365 move_entity->parameters = teleport; 00366 return 1; 00367 } 00368 00369 static anim_move_result runteleport(struct CFanimation_struct *animation, long int id, void *parameters) { 00370 teleport_params *teleport = (teleport_params *)parameters; 00371 00372 if (!parameters) 00373 return mr_finished; 00374 cf_object_teleport(animation->victim, cf_map_get_map(teleport->mapname, 0), teleport->mapx, teleport->mapy); 00375 free(parameters); 00376 return mr_finished; 00377 } 00378 00379 static long int initnotice(const char *name, char *parameters, struct CFmovement_struct *move_entity) { 00380 move_entity->parameters = parameters ? cf_strdup_local(parameters) : NULL; 00381 return 1; 00382 } 00383 static anim_move_result runnotice(struct CFanimation_struct *animation, long int id, void *parameters) { 00384 int val; 00385 00386 val = NDI_NAVY|NDI_UNIQUE; 00387 00388 cf_player_message(animation->victim, parameters, val); 00389 return mr_finished; 00390 } 00391 00392 static long int initstop(const char *name, char *parameters, struct CFmovement_struct *move_entity) { 00393 return 1; 00394 } 00395 00397 static anim_move_result runstop(struct CFanimation_struct *animation, long int id, void *parameters) { 00398 if (animation->verbose) 00399 cf_log(llevDebug, "CFAnim: stop encountered\n"); 00400 return mr_finished; 00401 } 00402 00404 typedef struct { 00405 int x, y; 00406 } param_moveto; 00407 00408 static long int initmoveto(const char *name, char *parameters, struct CFmovement_struct *move_entity) { 00409 param_moveto *moveto; 00410 int x, y; 00411 00412 if (sscanf(parameters, "%d %d", &x, &y) != 2) 00413 return 0; 00414 00415 moveto = (param_moveto *)calloc(1, sizeof(param_moveto)); 00416 moveto->x = x; 00417 moveto->y = y; 00418 move_entity->parameters = moveto; 00419 00420 return 1; 00421 } 00422 00423 static anim_move_result runmoveto(struct CFanimation_struct *animation, long int id, void *parameters) { 00424 int move; 00425 param_moveto *dest = (param_moveto *)parameters; 00426 00427 if (!dest) 00428 return mr_finished; 00429 00430 move = cf_object_move_to(animation->victim, dest->x, dest->y); 00431 00432 if (animation->victim->x == dest->x && animation->victim->y == dest->y) { 00433 free(parameters); 00434 return mr_finished; 00435 } 00436 00437 if (move == 1) 00438 return mr_again; 00439 00440 return mr_finished; 00441 } 00442 00443 static long int initmessage(const char *name, char *parameters, struct CFmovement_struct *move_entity) { 00444 if (parameters) 00445 move_entity->parameters = strdup(parameters); 00446 else 00447 move_entity->parameters = NULL; 00448 return 1; 00449 } 00450 00451 static anim_move_result runmessage(struct CFanimation_struct *animation, long int id, void *parameters) { 00452 if (parameters && animation->victim->map) { 00453 cf_map_message(animation->victim->map, (const char *)parameters, NDI_UNIQUE|NDI_GREEN); 00454 free(parameters); 00455 } 00456 00457 return mr_finished; 00458 } 00459 00461 CFanimationHook animationbox[] = { 00462 { "north", initmovement, runmovement }, 00463 { "north_east", initmovement, runmovement }, 00464 { "east", initmovement, runmovement }, 00465 { "south_east", initmovement, runmovement }, 00466 { "south", initmovement, runmovement }, 00467 { "south_west", initmovement, runmovement }, 00468 { "west", initmovement, runmovement }, 00469 { "north_west", initmovement, runmovement }, 00470 { "fire_north", initfire, runfire }, 00471 { "fire_north_east", initfire, runfire }, 00472 { "fire_east", initfire, runfire }, 00473 { "fire_south_east", initfire, runfire }, 00474 { "fire_south", initfire, runfire }, 00475 { "fire_south_west", initfire, runfire }, 00476 { "fire_west", initfire, runfire }, 00477 { "fire_north_west", initfire, runfire }, 00478 { "turn_north", initturn, runturn }, 00479 { "turn_north_east", initturn, runturn }, 00480 { "turn_east", initturn, runturn }, 00481 { "turn_south_east", initturn, runturn }, 00482 { "turn_south", initturn, runturn }, 00483 { "turn_south_west", initturn, runturn }, 00484 { "turn_west", initturn, runturn }, 00485 { "turn_north_west", initturn, runturn }, 00486 { "camera_north", initcamera, runcamera }, 00487 { "camera_north_east", initcamera, runcamera }, 00488 { "camera_east", initcamera, runcamera }, 00489 { "camera_south_east", initcamera, runcamera }, 00490 { "camera_south", initcamera, runcamera }, 00491 { "camera_south_west", initcamera, runcamera }, 00492 { "camera_west", initcamera, runcamera }, 00493 { "camera_north_west", initcamera, runcamera }, 00494 { "invisible", initvisible, runvisible }, 00495 { "wizard", initwizard, runwizard }, 00496 { "say", initsay, runsay }, 00497 { "apply", initapply, runapply }, 00498 { "apply_object", initapplyobject, runapplyobject }, 00499 { "drop_object", initdropobject, rundropobject }, 00500 { "pickup", initpickup, runpickup }, 00501 { "pickup_object", initpickupobject, runpickupobject }, 00502 { "ghosted", initghosted, runghosted }, 00503 { "teleport", initteleport, runteleport }, 00504 { "notice", initnotice, runnotice }, 00505 { "stop", initstop, runstop }, 00506 { "moveto", initmoveto, runmoveto }, 00507 { "message", initmessage, runmessage } 00508 }; 00509 00510 int animationcount = sizeof(animationbox)/sizeof(CFanimationHook); 00511 00512 static int ordered_commands = 0; 00513 00514 static int compareAnims(const void *a, const void *b) { 00515 return strcmp(((const CFanimationHook *)a)->name, ((const CFanimationHook *)b)->name); 00516 } 00517 00518 static void prepare_commands(void) { 00519 qsort(animationbox, animationcount, sizeof(CFanimationHook), compareAnims); 00520 ordered_commands = 1; 00521 } 00522 00523 static CFanimationHook *get_command(char *command) { 00524 CFanimationHook dummy; 00525 00526 dummy.name = command; 00527 if (!ordered_commands) 00528 prepare_commands(); 00529 return (CFanimationHook *)bsearch(&dummy, animationbox, animationcount, sizeof(CFanimationHook), compareAnims); 00530 } 00531 00540 static CFmovement *parse_animation_block(char *buffer, size_t buffer_size, FILE *fichier, CFanimation *parent) { 00541 CFmovement *first = NULL; 00542 CFmovement *current = NULL; 00543 CFmovement *next; 00544 char *time; 00545 char *name; 00546 char *parameters; 00547 int tick; 00548 CFanimationHook *animationhook; 00549 00550 if (parent->verbose) 00551 cf_log(llevDebug, "CFAnim: In parse block for %s\n", buffer); 00552 while (fgets(buffer, buffer_size, fichier)) { 00553 if (buffer[0] == '[') 00554 break; 00555 if (buffer[0] == '#') 00556 continue; 00557 buffer[strlen(buffer)-strlen("\n")] = '\0'; 00558 while (buffer[strlen(buffer)-1] == ' ') 00559 buffer[strlen(buffer)-1] = '\0'; 00560 if (strlen(buffer) <= 0) 00561 continue; 00562 time = buffer; 00563 00564 name = strstr(buffer, " "); 00565 if (!name) 00566 continue; 00567 *name = '\0'; 00568 name++; 00569 while (*name == ' ') 00570 name++; 00571 00572 tick = atoi(time); 00573 if (tick < 0) 00574 continue; 00575 00576 parameters = strstr(name, " "); 00577 if (parameters) { /*Parameters may be nul*/ 00578 *parameters = '\0'; 00579 parameters++; 00580 while (*parameters == ' ') 00581 parameters++; 00582 if (*parameters == '\0') 00583 parameters = NULL; 00584 } 00585 animationhook = get_command(name); 00586 if (parent->verbose) { 00587 if (!animationhook) 00588 cf_log(llevDebug, "CFAnim: %s - Unknown animation command\n", name); 00589 else 00590 cf_log(llevDebug, "CFAnim: Parsed %s -> %p\n", name, animationhook); 00591 } 00592 if (!animationhook) { 00593 if (parent->errors_allowed) 00594 continue; 00595 else 00596 break; 00597 } 00598 next = (CFmovement *)malloc(sizeof(CFmovement)); 00599 if (!next) 00600 continue; 00601 next->parent = parent; 00602 next->tick = tick; 00603 next->next = NULL; 00604 if (animationhook->funcinit) 00605 next->id = animationhook->funcinit(name, parameters, next); 00606 next->func = animationhook->funcrun; 00607 if (current) 00608 current->next = next; 00609 else 00610 first = next; 00611 current = next; 00612 } 00613 return first; 00614 } 00615 00626 static int equality_split(char *buffer, char **variable, char **value) { 00627 if (!strcmp(&buffer[strlen(buffer)-strlen("\n")], "\n")) 00628 buffer[strlen(buffer)-strlen("\n")] = '\0'; 00629 *value = strstr(buffer, "="); 00630 if (!*value) 00631 return 0; 00632 **value = '\0'; 00633 *variable = buffer; 00634 (*value)++; 00635 while ((strlen(*variable) > 0) && ((*variable)[strlen(*variable)-1] == ' ')) 00636 (*variable)[strlen(*variable)-1] = '\0'; 00637 while ((strlen(*value) > 0) && ((*value)[strlen(*value)-1] == ' ')) 00638 (*value)[strlen(*value)-1] = '\0'; 00639 while (**value == ' ') 00640 (*value)++; 00641 if ((**variable == '\0') || (**value == '\0')) 00642 return 0; 00643 return 1; 00644 } 00645 00657 static int get_boolean(const char *strg, int *bl) { 00658 if (!strncmp(strg, "y", 1)) 00659 *bl = 1; 00660 else if (!strncmp(strg, "n", 1)) 00661 *bl = 0; 00662 else if (!strncmp(strg, "Y", 1)) 00663 *bl = 1; 00664 else if (!strncmp(strg, "N", 1)) 00665 *bl = 0; 00666 else if (!strncmp(strg, "1", 1)) 00667 *bl = 1; 00668 else if (!strncmp(strg, "0", 1)) 00669 *bl = 0; 00670 else 00671 return 0; 00672 return 1; 00673 } 00674 00680 static int is_animated_player(object *pl) { 00681 CFanimation *current; 00682 00683 for (current = first_animation; current; current++) 00684 if ((current->victim == pl) && (current->paralyze)) { 00685 if (current->verbose) 00686 cf_log(llevDebug, "CFAnim: Getting a command for a paralyzed player %s.\n", pl->name); 00687 return 1; 00688 } 00689 return 0; 00690 } 00691 00696 static CFanimation *create_animation(void) { 00697 CFanimation *new; 00698 CFanimation *current; 00699 00700 new = (CFanimation *)malloc(sizeof(CFanimation)); 00701 if (!new) 00702 return NULL; 00703 new->name = NULL; 00704 new->victim = NULL; 00705 new->nextmovement = NULL; 00706 new->nextanimation = NULL; 00707 for (current = first_animation; (current && current->nextanimation); current = current->nextanimation) 00708 ; 00709 if (!current) 00710 first_animation = new; 00711 else 00712 current->nextanimation = new; 00713 return new; 00714 } 00715 00716 static object *find_by_name(object *origin, const char *name) { 00717 int x, y, w, h; 00718 mapstruct *map; 00719 const char *sname; 00720 object *ob; 00721 00722 sname = cf_find_string(name); 00723 if (!sname) 00724 return NULL; 00725 00726 while (origin && !origin->map) 00727 origin = origin->env; 00728 00729 if (!origin || !origin->map) 00730 return NULL; 00731 00732 map = origin->map; 00733 00734 w = cf_map_get_width(map); 00735 h = cf_map_get_height(map); 00736 00737 for (x = 0; x < w; x++) { 00738 for (y = 0; y < h; y++) { 00739 for (ob = GET_MAP_OB(map, x, y); ob; ob = ob->above) { 00740 if (/*cf_object_get_sstring_property(ob, CFAPI_OBJECT_PROP_NAME)*/ob->name == sname) 00741 return ob; 00742 } 00743 } 00744 } 00745 00746 return NULL; 00747 } 00748 00760 static int start_animation(object *who, object *activator, object *event, const char *file, const char *message) { 00761 FILE *fichier; 00762 char *name = NULL; 00763 int victimtype = 0; 00764 object *victim = NULL; 00765 int unique = 0; 00766 int always_delete = 0; 00767 int parallel = 0; 00768 int paralyzed = 1; 00769 int invisible = 0; 00770 int wizard = 0; 00771 enum time_enum timetype; 00772 int errors_allowed = 0; 00773 int verbose = 0; 00774 const char *animationitem; 00775 char buffer[HUGE_BUF]; 00776 char *variable; 00777 char *value; 00778 int errors_found = 0; 00779 CFanimation *current_anim; 00780 00781 fichier = fopen(file, "r"); 00782 if (fichier == NULL) { 00783 cf_log(llevDebug, "CFAnim: Unable to open %s\n", file); 00784 return 0; 00785 } 00786 while (fgets(buffer, HUGE_BUF, fichier)) { 00787 if (buffer[0] == '[') 00788 break; 00789 if (buffer[0] == '#') 00790 continue; 00791 if (!strcmp(buffer, "\n")) 00792 continue; 00793 errors_found = 1; 00794 cf_log(llevDebug, "CFAnim: '%s' has an invalid syntax.\n", buffer); 00795 } 00796 if (feof(fichier)) 00797 return 0; 00798 if (strncmp(buffer, "[Config]", 8)) { 00799 cf_log(llevDebug, "CFAnim: Fatal error in %s: [Config] must be the first group defined.\n", file); 00800 return 0; 00801 } 00802 while (fgets(buffer, HUGE_BUF, fichier)) { 00803 if (buffer[0] == '[') 00804 break; 00805 if (buffer[0] == '#') 00806 continue; 00807 if (!strcmp(buffer, "\n")) 00808 continue; 00809 if (!equality_split(buffer, &variable, &value)) 00810 errors_found = 1; 00811 else { 00812 if (!strcmp(variable, "name")) { 00813 if (*value == '"') 00814 value++; 00815 if (value[strlen(value)-1] == '"') 00816 value[strlen(value)-1] = '\0'; 00817 name = cf_strdup_local(value); 00818 } else if (!strcmp(variable, "victimtype")) { 00819 if (!strcmp(value, "player")) 00820 victimtype = 0; 00821 else if (!strcmp(value, "object")) 00822 victimtype = 1; 00823 else if (!strcmp(value, "any")) 00824 victimtype = 2; 00825 else if (!strcmp(value, "byname")) 00826 victimtype = 3; 00827 else 00828 errors_found = 1; 00829 } else if (!strcmp(variable, "victim")) { 00830 cf_log(llevDebug, "CFAnim: Setting victim to %s\n", value); 00831 if (!strcmp(value, "who")) 00832 victim = who; 00833 else if (!strcmp(value, "activator")) 00834 victim = activator; 00835 else if (!strcmp(value, "who_owner")) 00836 if (!who) { 00837 errors_found = 1; 00838 cf_log(llevDebug, "CFAnim: Warning: object \"who\" doesn't exist and you're victimized it's owner\n"); 00839 } else 00840 victim = who->env; 00841 else if (!strcmp(value, "activator_owner")) 00842 if (!activator) { 00843 errors_found = 1; 00844 cf_log(llevDebug, "CFAnim: Warning: object \"activator\" doesn't exist and you're victimized it's owner\n"); 00845 } 00846 else 00847 victim = activator->env; 00848 else if (victimtype == 3) { 00849 victim = find_by_name(who, value); 00850 } else 00851 errors_found = 1; 00852 } else if (!strcmp(variable, "unique")) { 00853 if (!get_boolean(value, &unique)) 00854 errors_found = 1; 00855 } else if (!strcmp(variable, "always_delete")) { 00856 if (!get_boolean(value, &always_delete)) 00857 errors_found = 1; 00858 } else if (!strcmp(variable, "parallel")) { 00859 if (!get_boolean(value, ¶llel)) 00860 errors_found = 1; 00861 } else if (!strcmp(variable, "paralyzed")) { 00862 if (!get_boolean(value, ¶lyzed)) 00863 errors_found = 1; 00864 } else if (!strcmp(variable, "invisible")) { 00865 if (!get_boolean(value, &invisible)) 00866 errors_found = 1; 00867 } else if (!strcmp(variable, "wizard")) { 00868 if (!get_boolean(value, &wizard)) 00869 errors_found = 1; 00870 } else if (!strcmp(variable, "errors_allowed")) { 00871 if (!get_boolean(value, &errors_allowed)) 00872 errors_found = 1; 00873 } else if (!strcmp(variable, "verbose")) { 00874 if (!get_boolean(value, &verbose)) 00875 errors_found = 1; 00876 } else if (!strcmp(variable, "time_representation")) { 00877 if (!strcmp(value, "second")) 00878 timetype = time_second; 00879 else if (!strcmp(value, "tick")) 00880 timetype = time_tick; 00881 else 00882 errors_found = 1; 00883 } else if (!strcmp(variable, "animation")) { 00884 animationitem = cf_add_string(value); 00885 } else 00886 errors_found = 1; 00887 } 00888 } 00889 00890 if (message && message[0] != '\0') { 00891 cf_free_string(animationitem); 00892 animationitem = cf_add_string(message); 00893 } 00894 00895 if (buffer[0] == '\0') { 00896 if (animationitem) 00897 cf_free_string(animationitem); 00898 cf_log(llevDebug, "CFAnim: Errors occurred during the parsing of %s\n", file); 00899 return 0; 00900 } 00901 if (!victim) { 00902 if (animationitem) 00903 cf_free_string(animationitem); 00904 cf_log(llevDebug, "CFAnim: Fatal error - victim is NULL"); 00905 return 0; 00906 } 00907 if (!(current_anim = create_animation())) { 00908 if (animationitem) 00909 cf_free_string(animationitem); 00910 cf_log(llevDebug, "CFAnim: Fatal error - Not enough memory.\n"); 00911 return 0; 00912 } 00913 if (always_delete) { 00914 /*if (verbose) printf("CFAnim: Freeing event nr. %d for %s.\n", current_event, who->name);*/ 00915 cf_object_remove(event); 00916 } 00917 if (((victim->type == PLAYER) && (victimtype == 1)) 00918 || ((victim->type != PLAYER) && (victimtype == 0)) 00919 || (errors_found && !errors_allowed)) { 00920 if (verbose) 00921 cf_log(llevDebug, "CFAnim: No correct victim found or errors found, aborting.\n"); 00922 if (animationitem) 00923 cf_free_string(animationitem); 00924 return 0; 00925 } 00926 if (unique && !always_delete) { 00927 /*if (verbose) printf("CFAnim: Freeing event nr. %d for %s.\n", current_event, who->name);*/ 00928 cf_object_remove(event); 00929 } 00930 current_anim->name = name; 00931 current_anim->victim = victim; 00932 current_anim->paralyze = paralyzed; 00933 current_anim->invisible = invisible; 00934 current_anim->wizard = wizard; 00935 current_anim->unique = unique; 00936 current_anim->ghosted = 0; 00937 current_anim->corpse = NULL; 00938 current_anim->time_representation = timetype; 00939 current_anim->verbose = verbose; 00940 current_anim->tick_left = 0; 00941 current_anim->errors_allowed = errors_allowed; 00942 00943 while (buffer[0] == '[') { 00944 while (strncmp(&buffer[1], animationitem, strlen(animationitem))) { 00945 while ((value = fgets(buffer, HUGE_BUF, fichier)) != NULL) 00946 if (buffer[0] == '[') 00947 break; 00948 if (value == NULL) { 00949 cf_log(llevDebug, "CFAnim: no matching animation %s in file.\n", animationitem); 00950 cf_free_string(animationitem); 00951 return 0; 00952 } 00953 } 00954 current_anim->nextmovement = parse_animation_block(buffer, HUGE_BUF, fichier, current_anim); 00955 if (current_anim->nextmovement) 00956 break; 00957 } 00958 fclose(fichier); 00959 return 1; 00960 } 00961 00967 static void animate_one(CFanimation *animation, long int milliseconds) { 00968 CFmovement *current; 00969 int mult = 1; 00970 anim_move_result result; 00971 00972 if (animation->time_representation == time_second) { 00973 animation->tick_left += milliseconds; 00974 mult = 1000; 00975 } 00976 else 00977 animation->tick_left++; 00978 00979 if (animation->verbose) 00980 cf_log(llevDebug, "CFAnim: Ticking %s for %s. Tickleft is %ld\n", animation->name, animation->victim->name, animation->tick_left); 00981 if (animation->invisible) 00982 animation->victim->invisible = 10; 00983 if (animation->wizard && animation->victim->type == PLAYER) { 00984 /* setting FLAG_WIZ *on non player leads to issues, as many functions expect contr to not be NULL in this case. */ 00985 if (animation->verbose) 00986 cf_log(llevDebug, "CFAnim: Setting wizard flags\n"); 00987 cf_object_set_flag(animation->victim, FLAG_WIZPASS, 1); 00988 cf_object_set_flag(animation->victim, FLAG_WIZCAST, 1); 00989 cf_object_set_flag(animation->victim, FLAG_WIZ, 1); 00990 if (animation->verbose) 00991 cf_log(llevDebug, "CFAnim: Setting wizard flags done\n"); 00992 00993 } 00994 if (animation->paralyze) 00995 animation->victim->speed_left = -99999; 00996 00997 cf_object_update(animation->victim, UP_OBJ_CHANGE); 00998 00999 if (animation->nextmovement) 01000 while (animation->tick_left > animation->nextmovement->tick*mult) { 01001 animation->tick_left -= animation->nextmovement->tick*mult; 01002 result = animation->nextmovement->func(animation, animation->nextmovement->id, animation->nextmovement->parameters); 01003 if (result == mr_again) 01004 continue; 01005 01006 current = animation->nextmovement; 01007 animation->nextmovement = animation->nextmovement->next; 01008 free(current); 01009 if (!animation->nextmovement) 01010 break; 01011 } 01012 cf_object_set_flag(animation->victim, FLAG_WIZPASS, 0); 01013 cf_object_set_flag(animation->victim, FLAG_WIZCAST, 0); 01014 cf_object_set_flag(animation->victim, FLAG_WIZ, 0); 01015 } 01016 01020 static void animate(void) { 01021 CFanimation *current; 01022 CFanimation *next; 01023 CFanimation *previous_anim = NULL; 01024 struct timeval now; 01025 static struct timeval yesterday; 01026 static int already_passed = 0; 01027 long int delta_milli; 01028 01029 (void)GETTIMEOFDAY(&now); 01030 if (!already_passed) { 01031 already_passed = 1; 01032 memcpy(&yesterday, &now, sizeof(struct timeval)); 01033 return; 01034 } 01035 delta_milli = (now.tv_sec-yesterday.tv_sec)*1000+(now.tv_usec/1000-yesterday.tv_usec/1000); 01036 /*printf("Working for %ld milli seconds\n", delta_milli);*/ 01037 memcpy(&yesterday, &now, sizeof(struct timeval)); 01038 for (current = first_animation; current; current = current->nextanimation) 01039 animate_one(current, delta_milli); 01040 current = first_animation; 01041 while (current) { 01042 if (!current->nextmovement) { 01043 if (current->paralyze) 01044 current->victim->speed_left = current->victim->speed; 01045 next = current->nextanimation; 01046 if (first_animation == current) 01047 first_animation = next; 01048 else { 01049 previous_anim->nextanimation = next; 01050 } 01051 if (current->name) 01052 free(current->name); 01053 free(current); 01054 current = next; 01055 } else { 01056 previous_anim = current; 01057 current = current->nextanimation; 01058 } 01059 } 01060 } 01061 01068 CF_PLUGIN int initPlugin(const char *iversion, f_plug_api gethooksptr) { 01069 cf_init_plugin(gethooksptr); 01070 cf_log(llevDebug, "CFAnim 2.0a init\n"); 01071 01072 /* Place your initialization code here */ 01073 return 0; 01074 } 01075 01076 CF_PLUGIN void *getPluginProperty(int *type, ...) { 01077 va_list args; 01078 const char *propname; 01079 char *buf; 01080 int size; 01081 01082 va_start(args, type); 01083 propname = va_arg(args, const char *); 01084 01085 if (!strcmp(propname, "Identification")) { 01086 buf = va_arg(args, char *); 01087 size = va_arg(args, int); 01088 va_end(args); 01089 snprintf(buf, size, PLUGIN_NAME); 01090 return NULL; 01091 } else if (!strcmp(propname, "FullName")) { 01092 buf = va_arg(args, char *); 01093 size = va_arg(args, int); 01094 va_end(args); 01095 snprintf(buf, size, PLUGIN_VERSION); 01096 return NULL; 01097 } 01098 va_end(args); 01099 return NULL; 01100 } 01101 01102 CF_PLUGIN anim_move_result cfanim_runPluginCommand(object *op, char *params) { 01103 return -1; 01104 } 01105 01106 CF_PLUGIN int postInitPlugin(void) { 01107 cf_log(llevDebug, "CFAnim 2.0a post init\n"); 01108 /* Pick the global events you want to monitor from this plugin */ 01109 cf_system_register_global_event(EVENT_CLOCK, PLUGIN_NAME, cfanim_globalEventListener); 01110 return 0; 01111 } 01112 01113 CF_PLUGIN void *cfanim_globalEventListener(int *type, ...) { 01114 va_list args; 01115 static int rv = 0; 01116 int event_code; 01117 01118 va_start(args, type); 01119 event_code = va_arg(args, int); 01120 assert(event_code == EVENT_CLOCK); 01121 01122 animate(); 01123 01124 va_end(args); 01125 01126 return &rv; 01127 } 01128 01129 CF_PLUGIN void *eventListener(int *type, ...) { 01130 static int rv = 0; 01131 va_list args; 01132 char *buf, message[MAX_BUF], script[MAX_BUF]; 01133 object *who, *activator, *third, *event; 01134 01135 va_start(args, type); 01136 01137 who = va_arg(args, object *); 01138 activator = va_arg(args, object *); 01139 third = va_arg(args, object *); 01140 buf = va_arg(args, char *); 01141 01142 if (buf != NULL) 01143 strcpy(message, buf); 01144 else 01145 message[0] = '\0'; 01146 01147 va_arg(args, int); /* 'fix', ignored */ 01148 event = va_arg(args, object *); 01149 01151 cf_get_maps_directory(event->slaying, script, sizeof(script)); 01152 va_end(args); 01153 01154 /* Put your plugin action(s) here */ 01155 if (activator != NULL) { 01156 cf_log(llevDebug, "CFAnim: %s called animator script %s\n", activator->name, script); 01157 } else if (who != NULL) { 01158 activator = who; 01159 cf_log(llevDebug, "CFAnim: %s called animator script %s\n", who->name, script); 01160 } 01161 01162 rv = start_animation(who, activator, event, script, message); 01163 01164 return &rv; 01165 } 01166 01167 CF_PLUGIN int closePlugin(void) { 01168 cf_log(llevDebug, "CFAnim 2.0a closing\n"); 01169 return 0; 01170 }