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
00029
00030
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
00135
00136
00137
00138
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) {
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 {
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) {
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 (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
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
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
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
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
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
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);
01148 event = va_arg(args, object *);
01149
01151 cf_get_maps_directory(event->slaying, script, sizeof(script));
01152 va_end(args);
01153
01154
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 }