Atrinik Client 2.5
gui/effects.c
Go to the documentation of this file.
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 
00033 static effect_struct *effects = NULL;
00035 static effect_struct *current_effect = NULL;
00037 static const char *overlay_cols[] = {"r", "g", "b", "a"};
00038 
00041 void effects_init()
00042 {
00043     FILE *fp;
00044     char buf[MAX_BUF], *cp;
00045     effect_struct *effect = NULL;
00046     effect_sprite_def *sprite_def = NULL;
00047     effect_overlay *overlay = NULL;
00048 
00049     /* Try to deinitialize all effects first. */
00050     effects_deinit();
00051 
00052     fp = server_file_open(SERVER_FILE_EFFECTS);
00053 
00054     if (!fp)
00055     {
00056         return;
00057     }
00058 
00059     /* Read the file... */
00060     while (fgets(buf, sizeof(buf) - 1, fp))
00061     {
00062         /* Ignore comments and blank lines. */
00063         if (buf[0] == '#' || buf[0] == '\n')
00064         {
00065             continue;
00066         }
00067 
00068         /* End a previous 'effect xxx' or 'sprite xxx' block. */
00069         if (!strcmp(buf, "end\n"))
00070         {
00071             /* Inside effect block. */
00072             if (effect)
00073             {
00074                 /* Inside sprite block. */
00075                 if (sprite_def)
00076                 {
00077                     /* Add this sprite to the linked list. */
00078                     sprite_def->next = effect->sprite_defs;
00079                     effect->sprite_defs = sprite_def;
00080                     /* Update total chance value. */
00081                     effect->chance_total += sprite_def->chance;
00082                     sprite_def = NULL;
00083                 }
00084                 /* Overlay block, just set it as the effect's overlay. */
00085                 else if (overlay)
00086                 {
00087                     effect->overlay = overlay;
00088                     overlay = NULL;
00089                 }
00090                 /* Inside effect block. */
00091                 else
00092                 {
00093                     /* Add this effect to the linked list of effects. */
00094                     effect->next = effects;
00095                     effects = effect;
00096                     effect = NULL;
00097                 }
00098             }
00099 
00100             continue;
00101         }
00102 
00103         cp = strrchr(buf, '\n');
00104 
00105         /* Eliminate newline. */
00106         if (cp)
00107         {
00108             *cp = '\0';
00109         }
00110 
00111         /* Parse definitions inside sprite block. */
00112         if (sprite_def)
00113         {
00114             if (!strncmp(buf, "chance ", 7))
00115             {
00116                 sprite_def->chance = atoi(buf + 7);
00117             }
00118             else if (!strncmp(buf, "weight ", 7))
00119             {
00120                 sprite_def->weight = atof(buf + 7);
00121             }
00122             else if (!strncmp(buf, "weight_mod ", 11))
00123             {
00124                 sprite_def->weight_mod = atof(buf + 11);
00125             }
00126             else if (!strncmp(buf, "delay ", 6))
00127             {
00128                 sprite_def->delay = atoi(buf + 6);
00129             }
00130             else if (!strncmp(buf, "wind ", 5))
00131             {
00132                 sprite_def->wind = atoi(buf + 5);
00133             }
00134             else if (!strncmp(buf, "wiggle ", 7))
00135             {
00136                 sprite_def->wiggle = atof(buf + 7);
00137             }
00138             else if (!strncmp(buf, "wind_mod ", 9))
00139             {
00140                 sprite_def->wind_mod = atof(buf + 9);
00141             }
00142             else if (!strncmp(buf, "x ", 2))
00143             {
00144                 sprite_def->x = atoi(buf + 2);
00145             }
00146             else if (!strncmp(buf, "y ", 2))
00147             {
00148                 sprite_def->y = atoi(buf + 2);
00149             }
00150             else if (!strncmp(buf, "xpos ", 5))
00151             {
00152                 sprite_def->xpos = atoi(buf + 5);
00153             }
00154             else if (!strncmp(buf, "ypos ", 5))
00155             {
00156                 sprite_def->ypos = atoi(buf + 5);
00157             }
00158             else if (!strncmp(buf, "reverse ", 8))
00159             {
00160                 sprite_def->reverse = atoi(buf + 8);
00161                 sprite_def->y_mod = -sprite_def->y_mod;
00162             }
00163             else if (!strncmp(buf, "y_rndm ", 7))
00164             {
00165                 sprite_def->y_rndm = atof(buf + 7);
00166             }
00167             else if (!strncmp(buf, "x_mod ", 6))
00168             {
00169                 sprite_def->x_mod = atof(buf + 6);
00170             }
00171             else if (!strncmp(buf, "y_mod ", 6))
00172             {
00173                 sprite_def->y_mod = atof(buf + 6);
00174             }
00175             else if (!strncmp(buf, "x_check_mod ", 12))
00176             {
00177                 sprite_def->x_check_mod = atoi(buf + 12);
00178             }
00179             else if (!strncmp(buf, "y_check_mod ", 12))
00180             {
00181                 sprite_def->y_check_mod = atoi(buf + 12);
00182             }
00183             else if (!strncmp(buf, "kill_sides ", 11))
00184             {
00185                 sprite_def->kill_side_left = sprite_def->kill_side_right = atoi(buf + 11);
00186             }
00187             else if (!strncmp(buf, "kill_side_left ", 15))
00188             {
00189                 sprite_def->kill_side_left = atoi(buf + 15);
00190             }
00191             else if (!strncmp(buf, "kill_side_right ", 16))
00192             {
00193                 sprite_def->kill_side_right = atoi(buf + 16);
00194             }
00195             else if (!strncmp(buf, "zoom ", 5))
00196             {
00197                 sprite_def->zoom = atoi(buf + 5);
00198             }
00199             else if (!strncmp(buf, "warp_sides ", 11))
00200             {
00201                 sprite_def->warp_sides = atoi(buf + 11);
00202             }
00203             else if (!strncmp(buf, "ttl ", 4))
00204             {
00205                 sprite_def->ttl = atoi(buf + 4);
00206             }
00207             else if (!strncmp(buf, "sound_file ", 11))
00208             {
00209                 strncpy(sprite_def->sound_file, buf + 11, sizeof(sprite_def->sound_file) - 1);
00210                 sprite_def->sound_file[sizeof(sprite_def->sound_file) - 1] = '\0';
00211             }
00212             else if (!strncmp(buf, "sound_volume ", 13))
00213             {
00214                 sprite_def->sound_volume = atoi(buf + 13);
00215             }
00216         }
00217         else if (!strcmp(buf, "overlay"))
00218         {
00219             size_t col;
00220 
00221             overlay = calloc(1, sizeof(effect_overlay));
00222 
00223             for (col = 0; col < arraysize(overlay_cols); col++)
00224             {
00225                 overlay->col[col].val = -1;
00226                 overlay->col[col].mod[4] = 1.0;
00227             }
00228         }
00229         else if (overlay)
00230         {
00231             size_t col;
00232 
00233             for (col = 0; col < arraysize(overlay_cols); col++)
00234             {
00235                 if (!strncmp(buf, overlay_cols[col], strlen(overlay_cols[col])))
00236                 {
00237                     if (!strncmp(buf + 1, "_rndm_min ", 10))
00238                     {
00239                         overlay->col[col].rndm_min = atoi(buf + 11);
00240                     }
00241                     else if (!strncmp(buf + 1, "_rndm_max ", 10))
00242                     {
00243                         overlay->col[col].rndm_max = atoi(buf + 11);
00244                     }
00245                     else if (!strncmp(buf + 1, "_mod1 ", 6))
00246                     {
00247                         overlay->col[col].mod[0] = atof(buf + 7);
00248                     }
00249                     else if (!strncmp(buf + 1, "_mod2 ", 6))
00250                     {
00251                         overlay->col[col].mod[1] = atof(buf + 7);
00252                     }
00253                     else if (!strncmp(buf + 1, "_mod3 ", 6))
00254                     {
00255                         overlay->col[col].mod[2] = atof(buf + 7);
00256                     }
00257                     else if (!strncmp(buf + 1, "_mod4 ", 6))
00258                     {
00259                         overlay->col[col].mod[3] = atof(buf + 7);
00260                     }
00261                     else if (!strncmp(buf + 1, "_mod5 ", 6))
00262                     {
00263                         overlay->col[col].mod[4] = atof(buf + 7);
00264                     }
00265                     else
00266                     {
00267                         overlay->col[col].val = atoi(buf + 2);
00268                     }
00269                 }
00270             }
00271         }
00272         /* Parse definitions inside effect block. */
00273         else if (effect)
00274         {
00275             if (!strncmp(buf, "wind_chance ", 12))
00276             {
00277                 effect->wind_chance = atof(buf + 12);
00278             }
00279             else if (!strncmp(buf, "sprite_chance ", 14))
00280             {
00281                 effect->sprite_chance = atof(buf + 14);
00282             }
00283             else if (!strncmp(buf, "delay ", 6))
00284             {
00285                 effect->delay = atoi(buf + 6);
00286             }
00287             else if (!strncmp(buf, "wind_blow_dir ", 14))
00288             {
00289                 effect->wind_blow_dir = atoi(buf + 14);
00290             }
00291             else if (!strncmp(buf, "max_sprites ", 12))
00292             {
00293                 effect->max_sprites = atoi(buf + 12);
00294             }
00295             else if (!strncmp(buf, "wind_mod ", 9))
00296             {
00297                 effect->wind_mod = atof(buf + 9);
00298             }
00299             else if (!strncmp(buf, "sprites_per_move ", 17))
00300             {
00301                 effect->sprites_per_move = atoi(buf + 17);
00302             }
00303             /* Start of sprite block. */
00304             else if (!strncmp(buf, "sprite ", 7))
00305             {
00306                 sprite_def = calloc(1, sizeof(*sprite_def));
00307                 /* Store the sprite ID and name. */
00308                 sprite_def->id = get_bmap_id(buf + 7);
00309                 sprite_def->name = strdup(buf + 7);
00310                 /* Initialize default values. */
00311                 sprite_def->chance = 1;
00312                 sprite_def->weight = 1.0;
00313                 sprite_def->weight_mod = 2.0;
00314                 sprite_def->wind = 1;
00315                 sprite_def->wiggle = 1.0;
00316                 sprite_def->wind_mod = 1.0;
00317                 sprite_def->x = -1;
00318                 sprite_def->y = -1;
00319                 sprite_def->reverse = 0;
00320                 sprite_def->y_rndm = 60.0;
00321                 sprite_def->x_mod = 1.0;
00322                 sprite_def->y_mod = 1.0;
00323                 sprite_def->x_check_mod = 1;
00324                 sprite_def->y_check_mod = 1;
00325                 sprite_def->kill_side_left = 1;
00326                 sprite_def->kill_side_right = 0;
00327                 sprite_def->zoom = 0;
00328                 sprite_def->warp_sides = 1;
00329                 sprite_def->ttl = 0;
00330                 sprite_def->sound_volume = 100;
00331             }
00332         }
00333         /* Start of effect block. */
00334         else if (!strncmp(buf, "effect ", 7))
00335         {
00336             effect = calloc(1, sizeof(effect_struct));
00337             /* Store the effect unique name. */
00338             strncpy(effect->name, buf + 7, sizeof(effect->name) - 1);
00339             effect->name[sizeof(effect->name) - 1] = '\0';
00340             /* Initialize default values. */
00341             effect->wind_chance = 0.98;
00342             effect->sprite_chance = 60.0;
00343             effect->wind_blow_dir = WIND_BLOW_RANDOM;
00344             effect->wind_mod = 1.0;
00345             effect->max_sprites = -1;
00346             effect->sprites_per_move = 1;
00347         }
00348     }
00349 
00350     /* Close the file. */
00351     fclose(fp);
00352 }
00353 
00356 void effects_deinit()
00357 {
00358     effect_struct *effect, *effect_next;
00359     effect_sprite_def *sprite_def, *sprite_def_next;
00360 
00361     /* Deinitialize all effects. */
00362     for (effect = effects; effect; effect = effect_next)
00363     {
00364         effect_next = effect->next;
00365 
00366         /* Deinitialize the effect's sprite definitions. */
00367         for (sprite_def = effect->sprite_defs; sprite_def; sprite_def = sprite_def_next)
00368         {
00369             sprite_def_next = sprite_def->next;
00370             effect_sprite_def_free(sprite_def);
00371         }
00372 
00373         /* Deinitialize the shown sprites and the actual effect. */
00374         effect_sprites_free(effect);
00375         effect_free(effect);
00376     }
00377 
00378     effects = current_effect = NULL;
00379 }
00380 
00384 void effects_reinit()
00385 {
00386     effect_struct *effect;
00387     effect_sprite_def *sprite_def;
00388 
00389     for (effect = effects; effect; effect = effect->next)
00390     {
00391         for (sprite_def = effect->sprite_defs; sprite_def; sprite_def = sprite_def->next)
00392         {
00393             sprite_def->id = get_bmap_id(sprite_def->name);
00394         }
00395     }
00396 }
00397 
00401 void effect_sprites_free(effect_struct *effect)
00402 {
00403     effect_sprite *tmp, *next;
00404 
00405     for (tmp = effect->sprites; tmp; tmp = next)
00406     {
00407         next = tmp->next;
00408         effect_sprite_free(tmp);
00409     }
00410 
00411     effect->sprites = effect->sprites_end = NULL;
00412 }
00413 
00417 void effect_free(effect_struct *effect)
00418 {
00419     if (effect->overlay)
00420     {
00421         free(effect->overlay);
00422     }
00423 
00424     free(effect);
00425 }
00426 
00430 void effect_sprite_def_free(effect_sprite_def *sprite_def)
00431 {
00432     free(sprite_def->name);
00433     free(sprite_def);
00434 }
00435 
00439 void effect_sprite_free(effect_sprite *sprite)
00440 {
00441     free(sprite);
00442 }
00443 
00447 void effect_sprite_remove(effect_sprite *sprite)
00448 {
00449     if (!sprite || !current_effect)
00450     {
00451         return;
00452     }
00453 
00454     if (sprite->prev)
00455     {
00456         sprite->prev->next = sprite->next;
00457     }
00458     else
00459     {
00460         current_effect->sprites = sprite->next;
00461     }
00462 
00463     if (sprite->next)
00464     {
00465         sprite->next->prev = sprite->prev;
00466     }
00467     else
00468     {
00469         current_effect->sprites_end = sprite->prev;
00470     }
00471 
00472     effect_sprite_free(sprite);
00473 }
00474 
00481 static effect_sprite *effect_sprite_create(effect_struct *effect)
00482 {
00483     int roll;
00484     effect_sprite_def *tmp;
00485     effect_sprite *sprite;
00486 
00487     if (!effect->sprite_defs)
00488     {
00489         return NULL;
00490     }
00491 
00492     /* Choose which sprite to use. */
00493     roll = rndm(1, effect->chance_total) - 1;
00494 
00495     for (tmp = effect->sprite_defs; tmp; tmp = tmp->next)
00496     {
00497         roll -= tmp->chance;
00498 
00499         if (roll < 0)
00500         {
00501             break;
00502         }
00503     }
00504 
00505     if (!tmp)
00506     {
00507         return NULL;
00508     }
00509 
00510     /* Allocate a new sprite. */
00511     sprite = calloc(1, sizeof(*sprite));
00512     sprite->def = tmp;
00513 
00514     /* Add it to the linked list. */
00515     if (!effect->sprites)
00516     {
00517         effect->sprites = effect->sprites_end = sprite;
00518     }
00519     else
00520     {
00521         effect->sprites_end->next = sprite;
00522         sprite->prev = effect->sprites_end;
00523         effect->sprites_end = sprite;
00524     }
00525 
00526     return sprite;
00527 }
00528 
00531 void effect_sprites_play()
00532 {
00533     effect_sprite *tmp, *next;
00534     int num_sprites = 0;
00535     int x_check, y_check;
00536     uint32 ticks;
00537 
00538     /* No current effect or not playing, quit. */
00539     if (!current_effect || GameStatus != GAME_STATUS_PLAY)
00540     {
00541         return;
00542     }
00543 
00544     ticks = SDL_GetTicks();
00545 
00546     for (tmp = current_effect->sprites; tmp; tmp = next)
00547     {
00548         next = tmp->next;
00549 
00550         if (!FaceList[tmp->def->id].sprite)
00551         {
00552             continue;
00553         }
00554 
00555         /* Check if the sprite should be removed due to ttl being up. */
00556         if (tmp->def->ttl && ticks - tmp->created_tick > tmp->def->ttl)
00557         {
00558             effect_sprite_remove(tmp);
00559             continue;
00560         }
00561 
00562         x_check = y_check = 0;
00563 
00564         if (tmp->def->x_check_mod)
00565         {
00566             x_check = FaceList[tmp->def->id].sprite->bitmap->w;
00567         }
00568 
00569         if (tmp->def->y_check_mod)
00570         {
00571             y_check = FaceList[tmp->def->id].sprite->bitmap->h;
00572         }
00573 
00574         if (tmp->def->warp_sides)
00575         {
00576             if (tmp->x + x_check < 0)
00577             {
00578                 tmp->x = cur_widget[MAP_ID]->wd;
00579                 continue;
00580             }
00581             else if (tmp->x - x_check > cur_widget[MAP_ID]->wd)
00582             {
00583                 tmp->x = -x_check;
00584                 continue;
00585             }
00586         }
00587 
00588         /* Off-screen? */
00589         if ((tmp->def->kill_side_left && tmp->x + x_check < 0) || (tmp->def->kill_side_right && tmp->x - x_check > cur_widget[MAP_ID]->ht) || tmp->y + y_check < 0 || tmp->y - y_check > cur_widget[MAP_ID]->ht)
00590         {
00591             effect_sprite_remove(tmp);
00592             continue;
00593         }
00594 
00595         /* Show the sprite. */
00596         sprite_blt_map(FaceList[tmp->def->id].sprite, tmp->x, tmp->y, NULL, NULL, 0, tmp->def->zoom, 0);
00597         num_sprites++;
00598 
00599         /* Move it if there is no delay configured or if enough time has passed. */
00600         if (!tmp->def->delay || !tmp->delay_ticks || ticks - tmp->delay_ticks > tmp->def->delay)
00601         {
00602             int ypos = tmp->def->weight * tmp->def->weight_mod;
00603 
00604             if (tmp->def->reverse)
00605             {
00606                 ypos = -ypos;
00607             }
00608 
00609             tmp->y += ypos;
00610             tmp->x += (-1.0 + 3.0 * RANDOM() / (RAND_MAX + 1.0)) * tmp->def->wiggle;
00611 
00612             /* Apply wind. */
00613             if (tmp->def->wind && current_effect->wind_blow_dir != WIND_BLOW_NONE)
00614             {
00615                 tmp->x += ((double) current_effect->wind / tmp->def->weight + tmp->def->weight * tmp->def->weight_mod * ((-1.0 + 2.0 * RANDOM() / (RAND_MAX + 1.0)) * tmp->def->wind_mod));
00616             }
00617 
00618             tmp->delay_ticks = ticks;
00619             map_redraw_flag = 1;
00620         }
00621     }
00622 
00623     /* Change wind direction... */
00624     if (current_effect->wind_blow_dir == WIND_BLOW_RANDOM && current_effect->wind_chance != 1.0 && (current_effect->wind_chance == 0.0 || RANDOM() / (RAND_MAX + 1.0) >= current_effect->wind_chance))
00625     {
00626         current_effect->wind += (-2.0 + 4.0 * RANDOM() / (RAND_MAX + 1.0)) * current_effect->wind_mod;
00627     }
00628 
00629     if (current_effect->wind_blow_dir == WIND_BLOW_LEFT)
00630     {
00631         current_effect->wind = -1.0 * current_effect->wind_mod;
00632     }
00633     else if (current_effect->wind_blow_dir == WIND_BLOW_RIGHT)
00634     {
00635         current_effect->wind = 1.0 * current_effect->wind_mod;
00636     }
00637 
00638     if ((current_effect->max_sprites == -1 || num_sprites < current_effect->max_sprites) && (!current_effect->delay || !current_effect->delay_ticks || ticks - current_effect->delay_ticks > current_effect->delay) && RANDOM() / (RAND_MAX + 1.0) >= (100.0 - current_effect->sprite_chance) / 100.0)
00639     {
00640         int i;
00641         effect_sprite *sprite;
00642 
00643         for (i = 0; i < current_effect->sprites_per_move; i++)
00644         {
00645             /* Add the sprite. */
00646             sprite = effect_sprite_create(current_effect);
00647 
00648             if (!sprite)
00649             {
00650                 return;
00651             }
00652 
00653             /* Invalid sprite. */
00654             if (sprite->def->id == -1 || !FaceList[sprite->def->id].sprite)
00655             {
00656                 LOG(llevInfo, "Invalid sprite ID %d\n", sprite->def->id);
00657                 effect_sprite_remove(sprite);
00658                 return;
00659             }
00660 
00661             if (sprite->def->x != -1)
00662             {
00663                 sprite->x = sprite->def->x;
00664             }
00665             else
00666             {
00667                 /* Calculate where to put the sprite. */
00668                 sprite->x = (double) cur_widget[MAP_ID]->wd * RANDOM() / (RAND_MAX + 1.0) * sprite->def->x_mod;
00669             }
00670 
00671             if (sprite->def->reverse)
00672             {
00673                 sprite->y = cur_widget[MAP_ID]->ht - FaceList[sprite->def->id].sprite->bitmap->h;
00674             }
00675             else if (sprite->def->y != -1)
00676             {
00677                 sprite->y = sprite->def->y;
00678             }
00679 
00680             sprite->y += sprite->def->y_rndm * (RANDOM() / (RAND_MAX + 1.0) * sprite->def->y_mod);
00681 
00682             sprite->x += sprite->def->xpos;
00683             sprite->y += sprite->def->ypos;
00684 
00685             if (sprite->def->sound_file[0] != '\0')
00686             {
00687                 sound_play_effect(sprite->def->sound_file, sprite->def->sound_volume);
00688             }
00689 
00690             sprite->created_tick = ticks;
00691             map_redraw_flag = 1;
00692         }
00693 
00694         current_effect->delay_ticks = ticks;
00695     }
00696 }
00697 
00703 int effect_start(const char *name)
00704 {
00705     effect_struct *tmp;
00706 
00707     /* Stop playing any effect. */
00708     if (!strcmp(name, "none"))
00709     {
00710         effect_stop();
00711         return 1;
00712     }
00713 
00714     /* Already playing the same effect? */
00715     if (current_effect && !strcmp(current_effect->name, name))
00716     {
00717         return 1;
00718     }
00719 
00720     /* Find the effect... */
00721     for (tmp = effects; tmp; tmp = tmp->next)
00722     {
00723         /* Found it? */
00724         if (!strcmp(tmp->name, name))
00725         {
00726             /* Stop current effect (if any) */
00727             effect_stop();
00728             /* Reset wind direction. */
00729             tmp->wind = 0;
00730             /* Load it up. */
00731             current_effect = tmp;
00732 
00733             /* Does this effect have an overlay? If so, we need to free
00734              * old dark levels, as they are rendered without the image
00735              * overlay. */
00736             if (current_effect->overlay)
00737             {
00738                 size_t i, dark;
00739 
00740                 for (i = 0; i < MAX_FACE_TILES; i++)
00741                 {
00742                     if (!FaceList[i].sprite)
00743                     {
00744                         continue;
00745                     }
00746 
00747                     if (FaceList[i].sprite->effect)
00748                     {
00749                         SDL_FreeSurface(FaceList[i].sprite->effect);
00750                         FaceList[i].sprite->effect = NULL;
00751                     }
00752 
00753                     /* Free all dark levels. */
00754                     for (dark = 0; dark < DARK_LEVELS; dark++)
00755                     {
00756                         if (FaceList[i].sprite->dark_level[dark])
00757                         {
00758                             SDL_FreeSurface(FaceList[i].sprite->dark_level[dark]);
00759                             FaceList[i].sprite->dark_level[dark] = NULL;
00760                         }
00761                     }
00762                 }
00763             }
00764 
00765             return 1;
00766         }
00767     }
00768 
00769     return 0;
00770 }
00771 
00775 void effect_debug(const char *type)
00776 {
00777     if (!strcmp(type, "num"))
00778     {
00779         uint32 num = 0;
00780         uint64 bytes;
00781         double kbytes;
00782         effect_sprite *tmp;
00783 
00784         if (!current_effect)
00785         {
00786             draw_info(COLOR_RED, "No effect is currently playing.");
00787             return;
00788         }
00789 
00790         for (tmp = current_effect->sprites; tmp; tmp = tmp->next)
00791         {
00792             num++;
00793         }
00794 
00795         bytes = ((uint64) sizeof(effect_sprite)) * num;
00796         kbytes = (double) bytes / 1024;
00797 
00798         draw_info_format(COLOR_WHITE, "Visible sprites: <green>%d</green> using <green>%"FMT64U"</green> bytes (<green>%2.2f</green> KB)", num, bytes, kbytes);
00799     }
00800     else if (!strcmp(type, "sizeof"))
00801     {
00802         draw_info(COLOR_WHITE, "Information about various data structures used by effects:\n");
00803         draw_info_format(COLOR_WHITE, "Size of a single sprite definition: <green>%"FMT64U"</green>", (uint64) sizeof(effect_sprite_def));
00804         draw_info_format(COLOR_WHITE, "Size of a single visible sprite: <green>%"FMT64U"</green>", (uint64) sizeof(effect_sprite));
00805         draw_info_format(COLOR_WHITE, "Size of a single effect structure: <green>%"FMT64U"</green>", (uint64) sizeof(effect_struct));
00806         draw_info_format(COLOR_WHITE, "Size of a single overlay: <green>%"FMT64U"</green>", (uint64) sizeof(effect_overlay));
00807     }
00808     else
00809     {
00810         draw_info_format(COLOR_RED, "No such debug option '%s'.", type);
00811     }
00812 }
00813 
00816 void effect_stop()
00817 {
00818     if (!current_effect)
00819     {
00820         return;
00821     }
00822 
00823     effect_sprites_free(current_effect);
00824     current_effect = NULL;
00825 }
00826 
00830 uint8 effect_has_overlay()
00831 {
00832     if (!current_effect)
00833     {
00834         return 0;
00835     }
00836 
00837     return current_effect->overlay ? 1 : 0;
00838 }
00839 
00843 void effect_scale(_Sprite *sprite)
00844 {
00845     int j, k, r, g, b, a, idx;
00846     Uint8 vals[4];
00847     SDL_Surface *temp = SDL_ConvertSurface(sprite->bitmap, FormatHolder->format, FormatHolder->flags);
00848 
00849     for (k = 0; k < temp->h; k++)
00850     {
00851         for (j = 0; j < temp->w; j++)
00852         {
00853             SDL_GetRGBA(getpixel(temp, j, k), temp->format, &vals[0], &vals[1], &vals[2], &vals[3]);
00854 
00855             idx = 0;
00856             EFFECT_SCALE_ADJUST(r, current_effect->overlay);
00857             EFFECT_SCALE_ADJUST(g, current_effect->overlay);
00858             EFFECT_SCALE_ADJUST(b, current_effect->overlay);
00859             EFFECT_SCALE_ADJUST(a, current_effect->overlay);
00860 
00861             putpixel(temp, j, k, SDL_MapRGBA(temp->format, r, g, b, a));
00862         }
00863     }
00864 
00865     sprite->effect = SDL_DisplayFormatAlpha(temp);
00866     SDL_FreeSurface(temp);
00867 }