1 /***************************************************************************
2                           paddle.c  -  description
3                              -------------------
4     begin                : Fri Sep 7 2001
5     copyright            : (C) 2001 by Michael Speck
6     email                : kulkanie@gmx.net
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include "../client/lbreakout.h"
19 #include "shots.h"
20 #include "paddle.h"
21 
22 extern Game *cur_game;
23 int paddle_cw = 18, paddle_ch = 18; /* size of a paddle component */
24 
25 /*
26 ====================================================================
27 Create/delete a paddle. x is centered assuming a screen width of
28 640. ball_ammo is the number of additional balls paddle
29  may bring to game.
30 ====================================================================
31 */
paddle_create(int score,int type,int y,int size,int min_size,int max_size,int ball_ammo)32 Paddle* paddle_create(
33 	int score, int type, int y, int size, int min_size, int max_size, int ball_ammo )
34 {
35 	Paddle *paddle = salloc( 1, sizeof( Paddle ) );
36 	delay_set( &paddle->resize_delay, 40 );
37 	paddle->score = score;
38 	paddle->len = size;
39 	paddle->start_len = size;
40 	paddle->min_len = min_size;
41 	paddle->max_len = max_size;
42 	paddle->w = (paddle->len + 2) * paddle_cw;
43 	paddle->wanted_w = paddle->w;
44 	paddle->h = paddle_ch;
45 	paddle->y = y;
46 	paddle->type = type;
47 	if ( paddle->type == PADDLE_TOP )
48 		paddle->wall_y = 0;
49 	else
50 		paddle->wall_y = 480 - BRICK_HEIGHT;
51 	paddle->wall_alpha = 0;
52 	paddle->x = ((MAP_WIDTH * BRICK_WIDTH) - paddle->w) / 2; /* centered */
53 	paddle->cur_x = paddle->x;
54 	paddle->friction = 0.3;
55 	paddle->friction_delay = 0;
56 	/* reset weapon */
57 	paddle->weapon_ammo = PADDLE_WEAPON_AMMO;
58 	/* reset slime&frozen */
59 	paddle->slime = 0;
60 	paddle->frozen = 0;
61 	/* attract */
62 	paddle->attract = ATTRACT_NONE;
63 	/* no ivisiblivty */
64 	paddle->invis = 0;
65 	/* ammo */
66 	paddle->ball_ammo = ball_ammo;
67 	paddle->start_ball_ammo = ball_ammo;
68 	/* ammo display */
69 	paddle->ball_ammo_disp_y = 4;
70 	if ( paddle->type == PADDLE_BOTTOM )
71 		paddle->ball_ammo_disp_y += (MAP_HEIGHT-1)*BRICK_HEIGHT;
72 
73 	return paddle;
74 }
paddle_delete(Paddle * paddle)75 void paddle_delete( Paddle *paddle )
76 {
77 	if ( paddle ) free( paddle );
78 }
paddle_reset(Paddle * paddle)79 void paddle_reset( Paddle *paddle )
80 {
81 	/* bad hack, isn't it? */
82 	Paddle *new = paddle_create(
83 		0/*clear score*/, paddle->type, paddle->y, paddle->start_len,
84 		paddle->min_len, paddle->max_len, paddle->start_ball_ammo );
85 	*paddle = *new;
86 	paddle_delete( new );
87 }
88 
paddle_freeze(Paddle * paddle,int freeze)89 void paddle_freeze( Paddle *paddle, int freeze )
90 {
91 	paddle->frozen = freeze;
92 	/* Goddammit what a shitty hack!!! hope I never change input stuff
93 	   again. but who cares anyway? isn't this source all screwed up
94 	   already? so let's go on until chaos reigns!!! multiple exclamation
95 	   marks are a sure sign of a deseased mind, I read somewhere. This
96 	   is not true!!! I am NOT not mental!!! Hey, if you read this, drop
97 	   me a note. Just curious whether someone ever happened to do so. */
98 	SDL_GetRelativeMouseState( &freeze, &freeze );
99 }
paddle_set_slime(Paddle * paddle,int slime)100 void paddle_set_slime( Paddle *paddle, int slime )
101 {
102 	paddle->slime = slime;
103 }
paddle_slimy(Paddle * paddle)104 int paddle_slimy( Paddle *paddle )
105 {
106 	return paddle->slime;
107 }
108 
109 /*
110 ====================================================================
111 Set if paddle attracts boni/mali or none.
112 ====================================================================
113 */
paddle_set_attract(Paddle * paddle,int attract)114 void paddle_set_attract( Paddle *paddle, int attract )
115 {
116 	paddle->attract = attract;
117 	/* no graphical change yet */
118 }
paddle_attract_malus(Paddle * paddle)119 int paddle_attract_malus( Paddle *paddle )
120 {
121 	return ( paddle->attract == ATTRACT_MALUS );
122 }
paddle_attract_bonus(Paddle * paddle)123 int paddle_attract_bonus( Paddle *paddle )
124 {
125 	return ( paddle->attract == ATTRACT_BONUS );
126 }
paddle_check_attract(Paddle * paddle,int type)127 int paddle_check_attract( Paddle *paddle, int type )
128 {
129 	switch ( type ) {
130 		/* bonus */
131 		case EX_SCORE200:
132 		case EX_SCORE500:
133 		case EX_SCORE1000:
134 		case EX_SCORE2000:
135 		case EX_SCORE5000:
136 		case EX_SCORE10000:
137 		case EX_GOLDSHOWER:
138 		case EX_LENGTHEN:
139 		case EX_LIFE:
140 		case EX_SLIME:
141 		case EX_METAL:
142 		case EX_BALL:
143 		case EX_WALL:
144 		case EX_WEAPON:
145 		case EX_SLOW:
146 		case EX_JOKER:
147 		case EX_EXPL_BALL:
148 		case EX_BONUS_MAGNET:
149 			if ( paddle_attract_bonus( paddle ) )
150 				return 1;
151 			return 0;
152 			/* penalty */
153 		case EX_SHORTEN:
154 		case EX_FAST:
155 			/*
156 			   case EX_SPIN_RIGHT:
157 			   case EX_SPIN_LEFT:
158 			   */
159 		case EX_MALUS_MAGNET:
160 		case EX_WEAK_BALL:
161 		case EX_DARKNESS:
162 		case EX_GHOST_PADDLE:
163 		case EX_FROZEN:
164 			if ( paddle_attract_malus( paddle ) )
165 				return 1;
166 			return 0;
167 			/* neutral */
168 		case EX_DISABLE:
169 		case EX_CHAOS:
170 		case EX_TIME_ADD:
171 		case EX_RANDOM:
172 			return 0;
173 	}
174 	return 0;
175 }
176 
177 /*
178 ====================================================================
179 (De)activate ghostly behaviour: paddle is only seen when moved at
180 maximum 200ms before.
181 ====================================================================
182 */
paddle_set_invis(Paddle * paddle,int invis)183 void paddle_set_invis( Paddle *paddle, int invis )
184 {
185 	if ( invis ) paddle->invis_delay = PADDLE_INVIS_DELAY;
186 	paddle->invis = invis;
187 }
paddle_solid(Paddle * paddle)188 int  paddle_solid( Paddle *paddle )
189 {
190 	/* does paddle is visible? */
191 	if ( !paddle->invis ) return 1;
192 	if ( paddle->invis_delay ) return 1;
193 	return 0;
194 }
195 
196 /*
197 ====================================================================
198 Init paddle resize (the change between wanted_w and w MUST be
199 even (else the paddle shrinks til eternity)
200 ====================================================================
201 */
paddle_init_resize(Paddle * paddle,int c)202 int paddle_init_resize( Paddle *paddle, int c )
203 {
204 	/* resize possbile */
205 	if ( paddle->len + c > paddle->max_len || paddle->len + c < paddle->min_len )
206 		return 0;
207 	/* get wanted width */
208 	paddle->len += c;
209 	paddle->wanted_w = (paddle->len + 2) * paddle_cw;
210 	/* reset delay */
211 	delay_reset( &paddle->resize_delay );
212 	return 1;
213 }
214 /*
215 ====================================================================
216 Actually resize paddle and return the -1 for shrinkage and 1
217 for expansion.
218 ====================================================================
219 */
paddle_resize(Paddle * paddle,int ms)220 int paddle_resize( Paddle *paddle, int ms )
221 {
222 	if ( paddle->w == paddle->wanted_w ) return 0;
223 	if ( !delay_timed_out( &paddle->resize_delay, ms ) ) return 0;
224 	/* change size and position */
225 	if ( paddle->w < paddle->wanted_w ) {
226 		paddle->w += 2;
227 		paddle->cur_x -= 1;
228 		paddle->x = (int)paddle->cur_x;
229 		/* check range */
230 		if (paddle->x < BRICK_WIDTH)
231 			paddle->x = BRICK_WIDTH;
232 		if (paddle->x + paddle->w > 640 - BRICK_WIDTH)
233 			paddle->x = 640 - BRICK_WIDTH - paddle->w;
234 		return 1;
235 	}
236 	else {
237 		paddle->w -= 2;
238 		paddle->cur_x += 1;
239 		paddle->x = (int)paddle->cur_x;
240 		return -1;
241 	}
242 }
243 
244 /*
245 ====================================================================
246 Update paddle resize and fire weapon.
247 ====================================================================
248 */
paddle_update(Paddle * paddle,int ms)249 void paddle_update( Paddle *paddle, int ms )
250 {
251 	Ball *ball;
252 	int result;
253 
254 	/* invisiblity */
255     	if ( paddle->invis ) /* extra active */
256 	if ( paddle->invis_delay > 0 && (paddle->invis_delay-=ms) <= 0 )
257 		paddle->invis_delay = 0;
258 
259 	/* handle weapon */
260 	if ( paddle->weapon_inst ) {
261 		if ( paddle->fire_left || paddle->fire_right )
262 		if ( paddle->weapon_ammo > 0 )
263 		if ( (paddle->weapon_fire_delay-=ms) <= 0 ) {
264 			paddle->weapon_fire_delay = WEAPON_FIRE_RATE;
265 			shot_create( paddle );
266 			paddle->weapon_ammo--;
267 		}
268 	}
269 
270 	/* check for resize */
271 	if ( ( result = paddle_resize( paddle, ms ) ) ) {
272 		list_reset( cur_game->balls );
273 		while ( ( ball = list_next( cur_game->balls ) ) )
274 			/* adjust attached balls */
275 			if ( ball->attached && ball->paddle == paddle ) {
276 				if ( result < 0 ) {
277 					/* shrinked */
278 					if ( ball->cur.x > ( paddle->w >> 1 ) ) {
279 						ball->cur.x -= 2;
280 						ball->x = (int)ball->cur.x;
281 					}
282 				}
283 				else {
284 					/* expanded */
285 					if ( ball->cur.x > ( paddle->w >> 1 ) ) {
286 						ball->cur.x += 2;
287 						ball->x = (int)ball->cur.x;
288 					}
289 				}
290 			}
291 	}
292 }
293 /*
294 ====================================================================
295 De/Activate weapon
296 ====================================================================
297 */
weapon_install(Paddle * paddle,int install)298 void weapon_install( Paddle *paddle, int install )
299 {
300 	if ( install ) paddle->weapon_fire_delay = WEAPON_FIRE_RATE;
301 	paddle->weapon_inst = install;
302 }
303 
304