Logo Search packages:      
Sourcecode: lbreakout2 version File versions  Download package

extras.c

/***************************************************************************
                          extras.c  -  description
                             -------------------
    begin                : Sun Sep 9 2001
    copyright            : (C) 2001 by Michael Speck
    email                : kulkanie@gmx.net
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "../client/lbreakout.h"
#include "levels.h"
#include "paddle.h"
#include "bricks.h"
#include "balls.h"
#include "mathfuncs.h"
#include "extras.h"

extern int ball_w, ball_dia;
extern Game *cur_game;

/*
====================================================================
Locals
====================================================================
*/

/*
====================================================================
Public
====================================================================
*/

/*
====================================================================
Create new extra at position
====================================================================
*/
Extra *extra_create( int type, int x, int y, int dir )
{
      Extra *e = salloc( 1, sizeof( Extra ) );
      e->type = type;
      e->offset = type * BRICK_WIDTH;
      e->x = x; e->y = y;
      e->dir = dir;
      e->alpha = 0;
      return e;
}

/*
====================================================================
Use extra when paddle collected it
====================================================================
*/
void extra_use( Paddle *paddle, int extra_type )
{
      Ball  *b;
      int   i, j;

      if ( cur_game->diff->allow_maluses ) {
            while( extra_type == EX_RANDOM )
                  extra_type = rand() % (EX_NUMBER);
      } else {
            while ( extra_type == EX_RANDOM || extra_is_malus( extra_type ) )
                  extra_type = rand() % (EX_NUMBER);
      }

      /* store modification */
      i = cur_game->paddles[0]==paddle?0:1;
      if ( cur_game->mod.collected_extra_count[i] < MAX_MODS )
            cur_game->mod.collected_extras[i][cur_game->mod.collected_extra_count[i]++] = 
                  extra_type;
      /* statistics */
      paddle->extras_collected++;

      switch (extra_type) {
            case EX_SCORE200:
                  paddle->score += cur_game->diff->score_mod * 200 / 10;
                  break;
            case EX_SCORE500:
                  paddle->score += cur_game->diff->score_mod * 500 / 10;
                  break;
            case EX_SCORE1000:
                  paddle->score += cur_game->diff->score_mod * 1000 / 10;
                  break;
            case EX_SCORE2000:
                  paddle->score += cur_game->diff->score_mod * 2000 / 10;
                  break;
            case EX_SCORE5000:
                  paddle->score += cur_game->diff->score_mod * 5000 / 10;
                  break;
            case EX_SCORE10000:
                  paddle->score += cur_game->diff->score_mod * 10000 / 10;
                  break;
            case EX_GOLDSHOWER:
                  paddle->extra_time[EX_GOLDSHOWER] += TIME_GOLDSHOWER;
                  paddle->extra_active[EX_GOLDSHOWER] = 1;
                  break;
            case EX_LIFE:
                  /* adding life is handled by client */
                  break;
            case EX_SHORTEN:
                  paddle_init_resize( paddle, -1);
                  break;
            case EX_LENGTHEN:
                  paddle_init_resize( paddle, 1);
                  break;
            case EX_BALL:
                  b = ball_create(
                        paddle->x + (paddle->w - ball_w) / 2, 
                        paddle->y + ((paddle->type == PADDLE_TOP)?paddle->h:-ball_dia) );
                  b->paddle = paddle;
                  ball_set_random_angle( b, cur_game->ball_v );
                  b->get_target = 1;
                  list_add( cur_game->balls, b );
                  break;
            case EX_WALL:
                  paddle->extra_time[EX_WALL] += TIME_WALL;
                  if ( paddle->extra_active[EX_WALL] ) break;
                  paddle->extra_active[extra_type] = 1;
                  if ( paddle->wall_y == 0 ) {
                        for (i = 1; i < MAP_WIDTH - 1; i++) {
                              cur_game->bricks[i][0].type = MAP_WALL;
                              cur_game->bricks[i][0].id = 0;
                        }
                  }
                  else
                        for (i = 1; i < MAP_WIDTH - 1; i++) {
                              cur_game->bricks[i][MAP_HEIGHT - 1].type = MAP_WALL;
                              cur_game->bricks[i][MAP_HEIGHT - 1].id = 0;
                        }
                  paddle->wall_alpha = 0;
                  balls_check_targets( -1, 0 );
                  break;
            case EX_METAL:
                  cur_game->extra_time[EX_METAL] += TIME_METAL;
                  cur_game->extra_active[extra_type] = 1;
                  balls_set_type( BALL_METAL );
                  /* other ball extras are disabled */
                  if ( cur_game->extra_active[EX_EXPL_BALL] ) {
                        cur_game->extra_active[EX_EXPL_BALL] = 0;
                        cur_game->extra_time[EX_EXPL_BALL] = 0;
                  }
                  if ( cur_game->extra_active[EX_WEAK_BALL] ) {
                        cur_game->extra_active[EX_WEAK_BALL] = 0;
                        cur_game->extra_time[EX_WEAK_BALL] = 0;
                  }
                  break;
            case EX_FROZEN:
                  paddle->extra_time[EX_FROZEN] = TIME_FROZEN;
                  paddle->extra_active[extra_type] = 1;
                  paddle_freeze( paddle, 1 );
                  break;
            case EX_WEAPON:
                  paddle->extra_time[EX_WEAPON] += TIME_WEAPON;
                  paddle->extra_active[extra_type] = 1;
                  weapon_install( paddle, 1 );
                  break;
            case EX_SLIME:
                  paddle->extra_time[EX_SLIME] += TIME_SLIME;
                  paddle->extra_active[extra_type] = 1;
                  paddle_set_slime( paddle, 1 );
                  break;
            case EX_FAST:
                  if ( cur_game->extra_active[EX_SLOW] ) {
                        cur_game->extra_time[EX_SLOW] = 0;
                        cur_game->extra_active[EX_SLOW] = 0;
                  }
                  cur_game->extra_time[EX_FAST] += TIME_FAST;
                  cur_game->extra_active[extra_type] = 1;
                        cur_game->ball_v = cur_game->ball_v_max;
                        balls_set_velocity( cur_game->balls, cur_game->ball_v );
                  break;
            case EX_SLOW:
                  if ( cur_game->extra_active[EX_FAST] ) {
                        cur_game->extra_time[EX_FAST] = 0;
                        cur_game->extra_active[EX_FAST] = 0;
                  }
                  cur_game->extra_time[EX_SLOW] += TIME_SLOW;
                  cur_game->extra_active[extra_type] = 1;
                  cur_game->ball_v = cur_game->ball_v_min;
                        balls_set_velocity( cur_game->balls, cur_game->ball_v );
                  break;
            case EX_CHAOS:
                  cur_game->extra_time[EX_CHAOS] += TIME_CHAOS;
                  cur_game->extra_active[extra_type] = 1;
                  balls_set_chaos( 1 );
                  break;
            case EX_DARKNESS:
                  cur_game->extra_time[EX_DARKNESS] += TIME_DARKNESS;
                  cur_game->extra_active[extra_type] = 1;
                  break;
            case EX_GHOST_PADDLE:
                  paddle->extra_time[EX_GHOST_PADDLE] += TIME_GHOST_PADDLE;
                  paddle->extra_active[extra_type] = 1;
                  paddle_set_invis( paddle, 1 );
                  break;
            case EX_TIME_ADD:
                  for ( i = 0; i < EX_NUMBER; i++ )
                        if ( cur_game->extra_time[i] )
                              cur_game->extra_time[i] += 7000;
                  for ( i = 0; i < EX_NUMBER; i++ ) {
                        for ( j = 0; j < cur_game->paddle_count; j++ )
                              if ( cur_game->paddles[j]->extra_time[i] )
                                    cur_game->paddles[j]->extra_time[i] += 7000;
                  }
                  break;
            case EX_EXPL_BALL:
                  balls_set_type( BALL_EXPL );
                  cur_game->extra_time[EX_EXPL_BALL] += TIME_EXPL_BALL;
                  cur_game->extra_active[extra_type] = 1;
                  /* other ball extras are disabled */
                  if ( cur_game->extra_active[EX_METAL] ) {
                        cur_game->extra_active[EX_METAL] = 0;
                        cur_game->extra_time[EX_METAL] = 0;
                  }
                  if ( cur_game->extra_active[EX_WEAK_BALL] ) {
                        cur_game->extra_active[EX_WEAK_BALL] = 0;
                        cur_game->extra_time[EX_WEAK_BALL] = 0;
                  }
                  break;
            case EX_WEAK_BALL:
                  balls_set_type( BALL_WEAK );
                  cur_game->extra_time[EX_WEAK_BALL] += TIME_WEAK_BALL;
                  cur_game->extra_active[extra_type] = 1;
                  /* other ball extras are disabled */
                  if ( cur_game->extra_active[EX_METAL] ) {
                        cur_game->extra_active[EX_METAL] = 0;
                        cur_game->extra_time[EX_METAL] = 0;
                  }
                  if ( cur_game->extra_active[EX_EXPL_BALL] ) {
                        cur_game->extra_active[EX_EXPL_BALL] = 0;
                        cur_game->extra_time[EX_EXPL_BALL] = 0;
                  }
                  break;
            case EX_BONUS_MAGNET:
                  paddle_set_attract( paddle, ATTRACT_BONUS );
                  paddle->extra_time[EX_BONUS_MAGNET] += TIME_BONUS_MAGNET;
                  paddle->extra_active[extra_type] = 1;
                  if ( paddle->extra_active[EX_MALUS_MAGNET] ) {
                        paddle->extra_active[EX_MALUS_MAGNET] = 0;
                        paddle->extra_time[EX_MALUS_MAGNET] = 0;
                  }
                  break;
            case EX_MALUS_MAGNET:
                  paddle_set_attract( paddle, ATTRACT_MALUS );
                  paddle->extra_time[EX_MALUS_MAGNET] += TIME_MALUS_MAGNET;
                  paddle->extra_active[extra_type] = 1;
                  if ( paddle->extra_active[EX_BONUS_MAGNET] ) {
                        paddle->extra_active[EX_BONUS_MAGNET] = 0;
                        paddle->extra_time[EX_BONUS_MAGNET] = 0;
                  }
                  break;
            case EX_DISABLE:
                  /* set all active extra times to 1 so they will expire next
                     prog cycle */ 
                  for ( i = 0; i < EX_NUMBER; i++ )
                        if ( cur_game->extra_time[i] )
                              cur_game->extra_time[i] = 1;
                  for ( i = 0; i < EX_NUMBER; i++ ) {
                        for ( j = 0; j < cur_game->paddle_count; j++ )
                              if ( cur_game->paddles[j]->extra_time[i] )
                                    cur_game->paddles[j]->extra_time[i] = 1;
                  }
                  break;
            default:
                  /* it wasn't used so delete mod */
                  i = cur_game->paddles[0]==paddle?0:1;
                  cur_game->mod.collected_extra_count[i]--;
                  break;
                  
      }
}
/*
====================================================================
Update extras
====================================================================
*/
void extras_update( int ms )
{
      Extra       *ex;
      int i, j;
      int magnets;
      Paddle *magnet;

      /* check extra_time of limited extras */

      /* general extras */
      for ( i = 0; i < EX_NUMBER; i++ )
            if ( cur_game->extra_time[i] )
            if ( (cur_game->extra_time[i] -= ms) <= 0 ) {
                  cur_game->extra_time[i] = 0;
                  /* expired */
                  switch ( i ) {
                        case EX_EXPL_BALL:
                        case EX_WEAK_BALL:
                        case EX_METAL: 
                              balls_set_type( BALL_NORMAL ); 
                              break;
                        case EX_SLOW:
                        case EX_FAST:
                              cur_game->ball_v = cur_game->diff->v_start + 
                                    cur_game->diff->v_add * cur_game->speedup_level;
                                        balls_set_velocity( cur_game->balls, cur_game->ball_v );
                              break;
                        case EX_CHAOS:
                              balls_set_chaos( 0 );
                              break;
                  }
                  /* set deactivated */
                  cur_game->extra_active[i] = 0; 
            }

      /* paddlized extras */
      for ( j = 0; j < cur_game->paddle_count; j++ )
      for ( i = 0; i < EX_NUMBER; i++ )
            /* extra_time of wall is updated in wall_update() */
            if ( cur_game->paddles[j]->extra_time[i] && i != EX_WALL )
            if ( (cur_game->paddles[j]->extra_time[i] -= ms) <= 0 ) {
                  cur_game->paddles[j]->extra_time[i] = 0;
                  /* expired */
                  switch ( i ) {
                        case EX_SLIME:
                                paddle_set_slime( cur_game->paddles[j], 0 );
                              /* release all balls from paddle */
                              balls_detach_from_paddle( cur_game->paddles[j],
                                                  ((rand()%2==1)?-1:1) );
                              break;
                        case EX_WEAPON: weapon_install( cur_game->paddles[j], 0 ); break;
                        case EX_FROZEN:
                              paddle_freeze( cur_game->paddles[j], 0 );
                              break;
                        case EX_GHOST_PADDLE:
                              paddle_set_invis( cur_game->paddles[j], 0 );
                              break;
                        case EX_BONUS_MAGNET:
                        case EX_MALUS_MAGNET:
                              paddle_set_attract( cur_game->paddles[j], ATTRACT_NONE );
                              break;
                  }
                  /* set deactivated */
                  cur_game->paddles[j]->extra_active[i] = 0; /* wall is handled in wall_...() */
            }

      /* move extras and check if paddle was hit */
      list_reset( cur_game->extras );
      while ( ( ex = list_next( cur_game->extras ) ) ) {
            /* if only one paddle has a magnet active all extras will 
             * be attracted by this paddle else the extras 'dir' is used 
             */
            magnets = 0; magnet = 0;
            for ( i = 0; i < cur_game->paddle_count; i++ )
                  if ( paddle_check_attract( cur_game->paddles[i], ex->type ) ) {
                        magnets++;
                        magnet = cur_game->paddles[i]; /* last magnet */
                  }
            if ( magnets != 1 ) {
                  /* either no or more than one magnet so use default */
                  if ( ex->dir > 0 )
                        ex->y += 0.05 * ms;
                  else
                        ex->y -= 0.05 * ms;
            }
            else {
                  /* 'magnet' is the paddle that will attract this extra */
                  if ( magnet->type == PADDLE_TOP )
                        ex->y -= 0.05 * ms;
                  else
                        ex->y += 0.05 * ms;
                  if ( ex->x + ( BRICK_WIDTH >> 1 ) < magnet->x + ( magnet->w >> 1 ) ) {
                        ex->x += 0.05 * ms;
                        if ( ex->x + ( BRICK_WIDTH >> 1 ) > magnet->x + ( magnet->w >> 1 ) )
                              ex->x = magnet->x + ( magnet->w >> 1 ) - ( BRICK_WIDTH >> 1 );
                  }
                  else {
                        ex->x -= 0.05 * ms;
                        if ( ex->x + ( BRICK_WIDTH >> 1 ) < magnet->x + ( magnet->w >> 1 ) )
                              ex->x = magnet->x + ( magnet->w >> 1 ) - ( BRICK_WIDTH >> 1 );
                  }
            }
            /* if out of screen, kill this extra */
            if ( ex->y >= 480 || ex->y + BRICK_HEIGHT < 0 ) {
                  list_delete_current( cur_game->extras );
                  continue;
            }
            for ( j = 0; j < cur_game->paddle_count; j++ ) {
                  /* contact with paddle core ? */
                  if ( paddle_solid( cur_game->paddles[j] ) )
                  if ( ex->x + BRICK_WIDTH > cur_game->paddles[j]->x )
                  if ( ex->x < cur_game->paddles[j]->x + cur_game->paddles[j]->w - 1 )
                  if ( ex->y + BRICK_HEIGHT > cur_game->paddles[j]->y )
                  if ( ex->y < cur_game->paddles[j]->y + cur_game->paddles[j]->h ) {
                        /* any extra except EX_JOKER is simply used */
                        if ( ex->type != EX_JOKER ) {
                              extra_use( cur_game->paddles[j], ex->type );
                              list_delete_current( cur_game->extras );
                              break;
                        }
                        /* use EX_JOKER and work through all active extras */
                        /* the mod is only stored to play the sound */
                        if ( cur_game->mod.collected_extra_count[j] < MAX_MODS )
                              cur_game->mod.collected_extras[j][cur_game->mod.collected_extra_count[j]++] = EX_JOKER;
                        list_reset( cur_game->extras );
                        while ( ( ex = list_next( cur_game->extras ) ) ) {
                              if ( ex->type != EX_JOKER )
                              if ( ex->type != EX_SHORTEN )
                              if ( ex->type != EX_FROZEN )
                              if ( ex->type != EX_FAST )
                              if ( ex->type != EX_RANDOM )
                              if ( ex->type != EX_DARKNESS )
                              if ( ex->type != EX_GHOST_PADDLE )
                              if ( ex->type != EX_CHAOS )
                              if ( ex->type != EX_DISABLE )
                              if ( ex->type != EX_MALUS_MAGNET )
                              if ( ex->type != EX_WEAK_BALL ) {
                                    extra_use( cur_game->paddles[j], ex->type );
                                    extra_use( cur_game->paddles[j], ex->type );
                              }
                              list_delete_current( cur_game->extras );
                        }
                        break;
                  }
            }
      }
}

/* wall */
void walls_update( int ms )
{
      int i, j;

      for ( j = 0; j < cur_game->paddle_count; j++ )
            if ( cur_game->paddles[j]->extra_active[EX_WALL] ) {
                  if ( cur_game->paddles[j]->extra_time[EX_WALL] > 0 ) {
                        if ( (cur_game->paddles[j]->extra_time[EX_WALL] -= ms) < 0 )
                              cur_game->paddles[j]->extra_time[EX_WALL] = 0;
                        /* still appearing? */
                        if (cur_game->paddles[j]->wall_alpha < 255)
                        if ( (cur_game->paddles[j]->wall_alpha += 0.25 * ms) > 255 ) 
                              cur_game->paddles[j]->wall_alpha = 255;
                  }
                  else
                  if ( (cur_game->paddles[j]->wall_alpha -= 0.25 * ms) < 0 ) {
                        cur_game->paddles[j]->wall_alpha = 0;
                        cur_game->paddles[j]->extra_active[EX_WALL] = 0;
                        if ( cur_game->paddles[j]->wall_y == 0 )
                              for (i = 1; i < MAP_WIDTH - 1; i++) 
                                    cur_game->bricks[i][0].type = MAP_EMPTY;
                        else
                              for (i = 1; i < MAP_WIDTH - 1; i++) 
                                    cur_game->bricks[i][MAP_HEIGHT - 1].type = MAP_EMPTY;
                        balls_check_targets( -1, 0 );
                  }
            }
}

int extra_is_malus( int type )
{
      if ( type == EX_SHORTEN ) return 1;
      if ( type == EX_FROZEN ) return 1;
      if ( type == EX_FAST ) return 1;
      if ( type == EX_DARKNESS ) return 1;
      if ( type == EX_GHOST_PADDLE ) return 1;
      if ( type == EX_CHAOS ) return 1;
      if ( type == EX_DISABLE ) return 1;
      if ( type == EX_MALUS_MAGNET ) return 1;
      if ( type == EX_WEAK_BALL ) return 1;
      return 0;
}


Generated by  Doxygen 1.6.0   Back to index