]> icculus.org git repositories - btb/d2x.git/blob - main/powerup.c
more header fixes
[btb/d2x.git] / main / powerup.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14 /*
15  *
16  * Code for powerup objects.
17  *
18  */
19
20
21 #ifdef HAVE_CONFIG_H
22 #include <conf.h>
23 #endif
24
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <string.h>
28
29 #include "fix.h"
30 #include "vecmat.h"
31 #include "gr.h"
32 #include "3d.h"
33 #include "mono.h"
34 #include "error.h"
35 #include "inferno.h"
36 #include "key.h"
37
38 #ifdef EDITOR
39 #include "gr.h" //      for powerup outline drawing
40 #include "editor/editor.h"
41 #endif
42
43
44 int N_powerup_types = 0;
45 powerup_type_info Powerup_info[MAX_POWERUP_TYPES];
46
47 //process this powerup for this frame
48 void do_powerup_frame(object *obj)
49 {
50         fix fudge;
51         vclip_info *vci = &obj->rtype.vclip_info;
52         vclip *vc = &Vclip[vci->vclip_num];
53
54         fudge = (FrameTime * (OBJECT_NUMBER(obj)&3)) >> 4;
55         
56         vci->frametime -= FrameTime+fudge;
57         
58         while (vci->frametime < 0 ) {
59
60                 vci->frametime += vc->frame_time;
61                 
62                 if (OBJECT_NUMBER(obj)&1)
63                         vci->framenum--;
64                 else
65                         vci->framenum++;
66
67                 if (vci->framenum >= vc->num_frames)
68                         vci->framenum=0;
69
70                 if (vci->framenum < 0)
71                         vci->framenum = vc->num_frames-1;
72         }
73
74         if (obj->lifeleft <= 0) {
75                 object_create_explosion(obj->segnum, &obj->pos, F1_0*7/2, VCLIP_POWERUP_DISAPPEARANCE );
76
77                 if ( Vclip[VCLIP_POWERUP_DISAPPEARANCE].sound_num > -1 )
78                         digi_link_sound_to_object( Vclip[VCLIP_POWERUP_DISAPPEARANCE].sound_num, OBJECT_NUMBER(obj), 0, F1_0    );
79         }
80 }
81
82 #ifdef EDITOR
83 extern fix blob_vertices[];
84
85 //      blob_vertices has 3 vertices in it, 4th must be computed
86 void draw_blob_outline(void)
87 {
88         fix     v3x, v3y;
89
90         v3x = blob_vertices[4] - blob_vertices[2] + blob_vertices[0];
91         v3y = blob_vertices[5] - blob_vertices[3] + blob_vertices[1];
92
93         gr_setcolor(BM_XRGB(63, 63, 63));
94
95         mprintf((0, "[%7.3f %7.3f]  [%7.3f %7.3f]  [%7.3f %7.3f]\n", f2fl(blob_vertices[0]), f2fl(blob_vertices[1]), f2fl(blob_vertices[2]), f2fl(blob_vertices[3]), f2fl(blob_vertices[4]), f2fl(blob_vertices[5]) ));
96
97         gr_line(blob_vertices[0], blob_vertices[1], blob_vertices[2], blob_vertices[3]);
98         gr_line(blob_vertices[2], blob_vertices[3], blob_vertices[4], blob_vertices[5]);
99         gr_line(blob_vertices[4], blob_vertices[5], v3x, v3y);
100
101         gr_line(v3x, v3y, blob_vertices[0], blob_vertices[1]);
102 }
103 #endif
104
105 void draw_powerup(object *obj)
106 {
107         #ifdef EDITOR
108         blob_vertices[0] = 0x80000;
109         #endif
110
111         draw_object_blob(obj, Vclip[obj->rtype.vclip_info.vclip_num].frames[obj->rtype.vclip_info.framenum] );
112
113         #ifdef EDITOR
114         if ((Function_mode == FMODE_EDITOR) && (Cur_object_index == OBJECT_NUMBER(obj)))
115                 if (blob_vertices[0] != 0x80000)
116                         draw_blob_outline();
117         #endif
118
119 }
120
121 //void mprintf_powerup_info(void)
122 //{
123 //      int             i;
124 //mprintf((0, "Powerup: %s\n", text));
125 //for (i=0; i<5; i++) {
126 //      char    has_text[12];
127 //
128 //      if (Players[Player_num].primary_weapon_flags & (1 << i))
129 //              strcpy(has_text,"PRESENT");
130 //      else
131 //              strcpy(has_text,"NOPE   ");
132 //      has_text[8] = 0;
133 //
134 //      mprintf((0, "Weapon %i = %s, ammo = %6i, name = %s\n", i, has_text, Players[Player_num].primary_ammo[i], Primary_weapon_names[i]));
135 //}
136 //
137 //for (i=0; i<5; i++) {
138 //      char    has_text[12];
139 //
140 //      if (Players[Player_num].secondary_weapon_flags & (1 << i))
141 //              strcpy(has_text,"PRESENT");
142 //      else
143 //              strcpy(has_text,"NOPE   ");
144 //
145 //      mprintf((0, "Weapon %i = %s, ammo = %6i, name = %s\n", i, has_text, Players[Player_num].secondary_ammo[i], Secondary_weapon_names[i]));
146 //}
147 //}
148
149 void powerup_basic(int redadd, int greenadd, int blueadd, int score, char *format, ...)
150 {
151         char            text[120];
152         va_list args;
153
154         va_start(args, format );
155         vsprintf(text, format, args);
156         va_end(args);
157
158         PALETTE_FLASH_ADD(redadd,greenadd,blueadd);
159
160         HUD_init_message(text);
161
162         //mprintf_powerup_info();
163
164         add_points_to_score(score);
165
166 }
167
168 //#ifndef RELEASE
169 //      Give the megawow powerup!
170 void do_megawow_powerup(int quantity)
171 {
172         int i;
173
174         powerup_basic(30, 0, 30, 1, "MEGA-WOWIE-ZOWIE!");
175         Players[Player_num].primary_weapon_flags = 0xffff ^ HAS_FLAG(SUPER_LASER_INDEX);                //no super laser
176         Players[Player_num].secondary_weapon_flags = 0xffff;
177
178         for (i=0; i<MAX_PRIMARY_WEAPONS; i++)
179                 Players[Player_num].primary_ammo[i] = VULCAN_AMMO_MAX;
180
181         for (i=0; i<3; i++)
182                 Players[Player_num].secondary_ammo[i] = quantity;
183
184         for (i=3; i<MAX_SECONDARY_WEAPONS; i++)
185                 Players[Player_num].secondary_ammo[i] = quantity/5;
186
187         if (Newdemo_state == ND_STATE_RECORDING)
188                 newdemo_record_laser_level(Players[Player_num].laser_level, MAX_LASER_LEVEL);
189
190         Players[Player_num].energy = F1_0*200;
191         Players[Player_num].shields = F1_0*200;
192         Players[Player_num].flags |= PLAYER_FLAGS_QUAD_LASERS;
193         Players[Player_num].laser_level = MAX_SUPER_LASER_LEVEL;
194
195         if (Game_mode & GM_HOARD)
196                 Players[Player_num].secondary_ammo[PROXIMITY_INDEX] = 12;
197
198
199         update_laser_weapon_info();
200
201 }
202 //#endif
203
204 int pick_up_energy(void)
205 {
206         int     used=0;
207
208         if (Players[Player_num].energy < MAX_ENERGY) {
209                 fix boost;
210                 boost = 3*F1_0 + 3*F1_0*(NDL - Difficulty_level);
211                 if (Difficulty_level == 0)
212                         boost += boost/2;
213                 Players[Player_num].energy += boost;
214                 if (Players[Player_num].energy > MAX_ENERGY)
215                         Players[Player_num].energy = MAX_ENERGY;
216                 powerup_basic(15,15,7, ENERGY_SCORE, "%s %s %d",TXT_ENERGY,TXT_BOOSTED_TO,f2ir(Players[Player_num].energy));
217                 used=1;
218         } else
219                 HUD_init_message(TXT_MAXED_OUT,TXT_ENERGY);
220
221         return used;
222 }
223
224 int pick_up_vulcan_ammo(void)
225 {
226         int     used=0,max;
227
228         int     pwsave = Primary_weapon;                // Ugh, save selected primary weapon around the picking up of the ammo.  I apologize for this code.  Matthew A. Toschlog
229         if (pick_up_ammo(CLASS_PRIMARY, VULCAN_INDEX, VULCAN_AMMO_AMOUNT)) {
230                 powerup_basic(7, 14, 21, VULCAN_AMMO_SCORE, "%s!", TXT_VULCAN_AMMO);
231                 used = 1;
232         } else {
233                 max = Primary_ammo_max[VULCAN_INDEX];
234                 if (Players[Player_num].flags & PLAYER_FLAGS_AMMO_RACK)
235                         max *= 2;
236                 HUD_init_message("%s %d %s!",TXT_ALREADY_HAVE,f2i((unsigned) VULCAN_AMMO_SCALE * (unsigned) max),TXT_VULCAN_ROUNDS);
237                 used = 0;
238         }
239         Primary_weapon = pwsave;
240
241         return used;
242 }
243
244 extern void invalidate_escort_goal(void);
245 extern void check_to_use_primary(int);
246 extern void multi_send_got_flag (char);
247
248 cvar_t Headlight_active_default = { "HeadlightActive", "1", 1 }; // is headlight on when picked up?
249 extern int PlayerMessage;
250
251 //      returns true if powerup consumed
252 int do_powerup(object *obj)
253 {
254         int used=0;
255         int special_used=0;             //for when hitting vulcan cannon gets vulcan ammo
256         char temp_string[50];
257         int id=obj->id;
258
259         if ((Player_is_dead) || (ConsoleObject->type == OBJ_GHOST) || (Players[Player_num].shields < 0))
260                 return 0;
261
262         if (obj->ctype.powerup_info.creation_time > GameTime)           //gametime wrapped!
263                 obj->ctype.powerup_info.creation_time = 0;                              //allow player to pick up
264
265         if ((obj->ctype.powerup_info.flags & PF_SPAT_BY_PLAYER) && obj->ctype.powerup_info.creation_time>0 && GameTime<obj->ctype.powerup_info.creation_time+i2f(2))
266                 return 0;               //not enough time elapsed
267
268         PlayerMessage=0;        //      Prevent messages from going to HUD if -PlayerMessages switch is set
269
270         switch (obj->id) {
271                 case POW_EXTRA_LIFE:
272                         Players[Player_num].lives++;
273                         powerup_basic(15, 15, 15, 0, TXT_EXTRA_LIFE);
274                         used=1;
275                         break;
276                 case POW_ENERGY:
277                         used = pick_up_energy();
278                         break;
279                 case POW_SHIELD_BOOST:
280                         if (Players[Player_num].shields < MAX_SHIELDS) {
281                                 fix boost = 3*F1_0 + 3*F1_0*(NDL - Difficulty_level);
282                                 if (Difficulty_level == 0)
283                                         boost += boost/2;
284                                 Players[Player_num].shields += boost;
285                                 if (Players[Player_num].shields > MAX_SHIELDS)
286                                         Players[Player_num].shields = MAX_SHIELDS;
287                                 powerup_basic(0, 0, 15, SHIELD_SCORE, "%s %s %d",TXT_SHIELD,TXT_BOOSTED_TO,f2ir(Players[Player_num].shields));
288                                 used=1;
289                         } else
290                                 HUD_init_message(TXT_MAXED_OUT,TXT_SHIELD);
291                         break;
292                 case POW_LASER:
293                         if (Players[Player_num].laser_level >= MAX_LASER_LEVEL) {
294                                 //Players[Player_num].laser_level = MAX_LASER_LEVEL;
295                                 HUD_init_message(TXT_MAXED_OUT,TXT_LASER);
296                         } else {
297                                 if (Newdemo_state == ND_STATE_RECORDING)
298                                         newdemo_record_laser_level(Players[Player_num].laser_level, Players[Player_num].laser_level + 1);
299                                 Players[Player_num].laser_level++;
300                                 powerup_basic(10, 0, 10, LASER_SCORE, "%s %s %d",TXT_LASER,TXT_BOOSTED_TO, Players[Player_num].laser_level+1);
301                                 update_laser_weapon_info();
302                                 pick_up_primary (LASER_INDEX);
303                                 used=1;
304                         }
305                         if (!used && !(Game_mode & GM_MULTI) )
306                                 used = pick_up_energy();
307                         break;
308                 case POW_MISSILE_1:
309                         used=pick_up_secondary(CONCUSSION_INDEX,1);
310                         break;
311                 case POW_MISSILE_4:
312                         used=pick_up_secondary(CONCUSSION_INDEX,4);
313                         break;
314
315                 case POW_KEY_BLUE:
316                         if (Players[Player_num].flags & PLAYER_FLAGS_BLUE_KEY)
317                                 break;
318 #ifdef NETWORK
319                         multi_send_play_sound(Powerup_info[obj->id].hit_sound, F1_0);
320 #endif
321                         digi_play_sample( Powerup_info[obj->id].hit_sound, F1_0 );
322                         Players[Player_num].flags |= PLAYER_FLAGS_BLUE_KEY;
323                         powerup_basic(0, 0, 15, KEY_SCORE, "%s %s",TXT_BLUE,TXT_ACCESS_GRANTED);
324                         if (Game_mode & GM_MULTI)
325                                 used=0;
326                         else
327                                 used=1;
328                         invalidate_escort_goal();
329                         break;
330                 case POW_KEY_RED:
331                         if (Players[Player_num].flags & PLAYER_FLAGS_RED_KEY)
332                                 break;
333 #ifdef NETWORK
334                         multi_send_play_sound(Powerup_info[obj->id].hit_sound, F1_0);
335 #endif
336                         digi_play_sample( Powerup_info[obj->id].hit_sound, F1_0 );
337                         Players[Player_num].flags |= PLAYER_FLAGS_RED_KEY;
338                         powerup_basic(15, 0, 0, KEY_SCORE, "%s %s",TXT_RED,TXT_ACCESS_GRANTED);
339                         if (Game_mode & GM_MULTI)
340                                 used=0;
341                         else
342                                 used=1;
343                         invalidate_escort_goal();
344                         break;
345                 case POW_KEY_GOLD:
346                         if (Players[Player_num].flags & PLAYER_FLAGS_GOLD_KEY)
347                                 break;
348 #ifdef NETWORK
349                         multi_send_play_sound(Powerup_info[obj->id].hit_sound, F1_0);
350 #endif
351                         digi_play_sample( Powerup_info[obj->id].hit_sound, F1_0 );
352                         Players[Player_num].flags |= PLAYER_FLAGS_GOLD_KEY;
353                         powerup_basic(15, 15, 7, KEY_SCORE, "%s %s",TXT_YELLOW,TXT_ACCESS_GRANTED);
354                         if (Game_mode & GM_MULTI)
355                                 used=0;
356                         else
357                                 used=1;
358                         invalidate_escort_goal();
359                         break;
360                 case POW_QUAD_FIRE:
361                         if (!(Players[Player_num].flags & PLAYER_FLAGS_QUAD_LASERS)) {
362                                 Players[Player_num].flags |= PLAYER_FLAGS_QUAD_LASERS;
363                                 powerup_basic(15, 15, 7, QUAD_FIRE_SCORE, "%s!",TXT_QUAD_LASERS);
364                                 update_laser_weapon_info();
365                                 used=1;
366                         } else
367                                 HUD_init_message("%s %s!",TXT_ALREADY_HAVE,TXT_QUAD_LASERS);
368                         if (!used && !(Game_mode & GM_MULTI) )
369                                 used = pick_up_energy();
370                         break;
371
372                 case    POW_VULCAN_WEAPON:
373                 case    POW_GAUSS_WEAPON: {
374                         int ammo = obj->ctype.powerup_info.count;
375
376                         used = pick_up_primary((obj->id==POW_VULCAN_WEAPON)?VULCAN_INDEX:GAUSS_INDEX);
377
378                         //didn't get the weapon (because we already have it), but
379                         //maybe snag some of the ammo.  if single-player, grab all the ammo
380                         //and remove the powerup.  If multi-player take ammo in excess of
381                         //the amount in a powerup, and leave the rest.
382                         if (! used)
383                                 if ((Game_mode & GM_MULTI) )
384                                         ammo -= VULCAN_AMMO_AMOUNT;     //don't let take all ammo
385
386                         if (ammo > 0) {
387                                 int ammo_used;
388                                 ammo_used = pick_up_ammo(CLASS_PRIMARY, VULCAN_INDEX, ammo);
389                                 obj->ctype.powerup_info.count -= ammo_used;
390                                 if (!used && ammo_used) {
391                                         powerup_basic(7, 14, 21, VULCAN_AMMO_SCORE, "%s!", TXT_VULCAN_AMMO);
392                                         special_used = 1;
393                                         id = POW_VULCAN_AMMO;           //set new id for making sound at end of this function
394                                         if (obj->ctype.powerup_info.count == 0)
395                                                 used = 1;               //say used if all ammo taken
396                                 }
397                         }
398
399                         break;
400                 }
401
402                 case    POW_SPREADFIRE_WEAPON:
403                         used = pick_up_primary(SPREADFIRE_INDEX);
404                         if (!used && !(Game_mode & GM_MULTI) )
405                                 used = pick_up_energy();
406                         break;
407                 case    POW_PLASMA_WEAPON:
408                         used = pick_up_primary(PLASMA_INDEX);
409                         if (!used && !(Game_mode & GM_MULTI) )
410                                 used = pick_up_energy();
411                         break;
412                 case    POW_FUSION_WEAPON:
413                         used = pick_up_primary(FUSION_INDEX);
414                         if (!used && !(Game_mode & GM_MULTI) )
415                                 used = pick_up_energy();
416                         break;
417
418                 case    POW_HELIX_WEAPON:
419                         used = pick_up_primary(HELIX_INDEX);
420                         if (!used && !(Game_mode & GM_MULTI) )
421                                 used = pick_up_energy();
422                         break;
423
424                 case    POW_PHOENIX_WEAPON:
425                         used = pick_up_primary(PHOENIX_INDEX);
426                         if (!used && !(Game_mode & GM_MULTI) )
427                                 used = pick_up_energy();
428                         break;
429
430                 case    POW_OMEGA_WEAPON:
431                         used = pick_up_primary(OMEGA_INDEX);
432                         if (used)
433                                 Omega_charge = obj->ctype.powerup_info.count;
434                         if (!used && !(Game_mode & GM_MULTI) )
435                                 used = pick_up_energy();
436                         break;
437
438                 case    POW_PROXIMITY_WEAPON:
439                         used=pick_up_secondary(PROXIMITY_INDEX,4);
440                         break;
441                 case    POW_SMARTBOMB_WEAPON:
442                         used=pick_up_secondary(SMART_INDEX,1);
443                         break;
444                 case    POW_MEGA_WEAPON:
445                         used=pick_up_secondary(MEGA_INDEX,1);
446                         break;
447                 case    POW_SMISSILE1_1:
448                         used=pick_up_secondary(SMISSILE1_INDEX,1);
449                         break;
450                 case    POW_SMISSILE1_4:
451                         used=pick_up_secondary(SMISSILE1_INDEX,4);
452                         break;
453                 case    POW_GUIDED_MISSILE_1:
454                         used=pick_up_secondary(GUIDED_INDEX,1);
455                         break;
456                 case    POW_GUIDED_MISSILE_4:
457                         used=pick_up_secondary(GUIDED_INDEX,4);
458                         break;
459                 case    POW_SMART_MINE:
460                         used=pick_up_secondary(SMART_MINE_INDEX,4);
461                         break;
462                 case    POW_MERCURY_MISSILE_1:
463                         used=pick_up_secondary(SMISSILE4_INDEX,1);
464                         break;
465                 case    POW_MERCURY_MISSILE_4:
466                         used=pick_up_secondary(SMISSILE4_INDEX,4);
467                         break;
468                 case    POW_EARTHSHAKER_MISSILE:
469                         used=pick_up_secondary(SMISSILE5_INDEX,1);
470                         break;
471                 case    POW_VULCAN_AMMO:
472                         used = pick_up_vulcan_ammo();
473                         break;
474                 case    POW_HOMING_AMMO_1:
475                         used=pick_up_secondary(HOMING_INDEX,1);
476                         break;
477                 case    POW_HOMING_AMMO_4:
478                         used=pick_up_secondary(HOMING_INDEX,4);
479                         break;
480                 case    POW_CLOAK:
481                         if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) {
482                                 HUD_init_message("%s %s!",TXT_ALREADY_ARE,TXT_CLOAKED);
483                                 break;
484                         } else {
485                                 Players[Player_num].cloak_time = GameTime;      //      Not! changed by awareness events (like player fires laser).
486                                 Players[Player_num].flags |= PLAYER_FLAGS_CLOAKED;
487                                 ai_do_cloak_stuff();
488                                 #ifdef NETWORK
489                                 if (Game_mode & GM_MULTI)
490                                         multi_send_cloak();
491                                 #endif
492                                 powerup_basic(-10,-10,-10, CLOAK_SCORE, "%s!",TXT_CLOAKING_DEVICE);
493                                 used = 1;
494                                 break;
495                         }
496                 case    POW_INVULNERABILITY:
497                         if (Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE) {
498                                 HUD_init_message("%s %s!",TXT_ALREADY_ARE,TXT_INVULNERABLE);
499                                 break;
500                         } else {
501                                 Players[Player_num].invulnerable_time = GameTime;
502                                 Players[Player_num].flags |= PLAYER_FLAGS_INVULNERABLE;
503                                 powerup_basic(7, 14, 21, INVULNERABILITY_SCORE, "%s!",TXT_INVULNERABILITY);
504                                 used = 1;
505                                 break;
506                         }
507         #ifndef RELEASE
508                 case    POW_MEGAWOW:
509                         do_megawow_powerup(50);
510                         used = 1;
511                         break;
512         #endif
513
514                 case POW_FULL_MAP:
515                         if (Players[Player_num].flags & PLAYER_FLAGS_MAP_ALL) {
516                                 HUD_init_message("%s %s!",TXT_ALREADY_HAVE,"the FULL MAP");
517                                 if (!(Game_mode & GM_MULTI) )
518                                         used = pick_up_energy();
519                         } else {
520                                 Players[Player_num].flags |= PLAYER_FLAGS_MAP_ALL;
521                                 powerup_basic(15, 0, 15, 0, "FULL MAP!");
522                                 used=1;
523                         }
524                         break;
525
526                 case POW_CONVERTER:
527                         if (Players[Player_num].flags & PLAYER_FLAGS_CONVERTER) {
528                                 HUD_init_message("%s %s!",TXT_ALREADY_HAVE,"the Converter");
529                                 if (!(Game_mode & GM_MULTI) )
530                                         used = pick_up_energy();
531                         } else {
532                                 ubyte key;
533
534                                 Players[Player_num].flags |= PLAYER_FLAGS_CONVERTER;
535                                 if ((key = key_find_binding("+nrgshield"))) {
536                                         sprintf(temp_string, "Energy->Shield converter! (Press %s to use)", key_text[key]);
537                                         powerup_basic(15, 0, 15, 0, temp_string);
538                                 } else
539                                         powerup_basic(15, 0, 15, 0, "Energy -> shield converter!");
540
541                                 used=1;
542                         }
543                         break;
544
545                 case POW_SUPER_LASER:
546                         if (Players[Player_num].laser_level >= MAX_SUPER_LASER_LEVEL) {
547                                 Players[Player_num].laser_level = MAX_SUPER_LASER_LEVEL;
548                                 HUD_init_message("SUPER LASER MAXED OUT!");
549                         } else {
550                                 int old_level=Players[Player_num].laser_level;
551
552                                 if (Players[Player_num].laser_level <= MAX_LASER_LEVEL)
553                                         Players[Player_num].laser_level = MAX_LASER_LEVEL;
554                                 Players[Player_num].laser_level++;
555                                 if (Newdemo_state == ND_STATE_RECORDING)
556                                         newdemo_record_laser_level(old_level, Players[Player_num].laser_level);
557                                 powerup_basic(10, 0, 10, LASER_SCORE, "Super Boost to Laser level %d",Players[Player_num].laser_level+1);
558                                 update_laser_weapon_info();
559                                 if (Primary_weapon!=LASER_INDEX)
560                               check_to_use_primary (SUPER_LASER_INDEX);
561                                 used=1;
562                         }
563                         if (!used && !(Game_mode & GM_MULTI) )
564                                 used = pick_up_energy();
565                         break;
566
567                 case POW_AMMO_RACK:
568                         if (Players[Player_num].flags & PLAYER_FLAGS_AMMO_RACK) {
569                                 HUD_init_message("%s %s!",TXT_ALREADY_HAVE,"the Ammo rack");
570                                 if (!(Game_mode & GM_MULTI) )
571                                         used = pick_up_energy();
572                         }
573                         else {
574                                 Players[Player_num].flags |= PLAYER_FLAGS_AMMO_RACK;
575 #ifdef NETWORK
576                                 multi_send_play_sound(Powerup_info[obj->id].hit_sound, F1_0);
577 #endif
578                                 digi_play_sample( Powerup_info[obj->id].hit_sound, F1_0 );
579                                 powerup_basic(15, 0, 15, 0, "AMMO RACK!");
580                                 used=1;
581                         }
582                         break;
583
584                 case POW_AFTERBURNER:
585                         if (Players[Player_num].flags & PLAYER_FLAGS_AFTERBURNER) {
586                                 HUD_init_message("%s %s!",TXT_ALREADY_HAVE,"the Afterburner");
587                                 if (!(Game_mode & GM_MULTI) )
588                                         used = pick_up_energy();
589                         }
590                         else {
591                                 Players[Player_num].flags |= PLAYER_FLAGS_AFTERBURNER;
592 #ifdef NETWORK
593                                 multi_send_play_sound(Powerup_info[obj->id].hit_sound, F1_0);
594 #endif
595                                 digi_play_sample( Powerup_info[obj->id].hit_sound, F1_0 );
596                                 powerup_basic(15, 15, 15, 0, "AFTERBURNER!");
597                                 Afterburner_charge = f1_0;
598                                 used=1;
599                         }
600                         break;
601
602                 case POW_HEADLIGHT:
603                         if (Players[Player_num].flags & PLAYER_FLAGS_HEADLIGHT) {
604                                 HUD_init_message("%s %s!",TXT_ALREADY_HAVE,"the Headlight boost");
605                                 if (!(Game_mode & GM_MULTI) )
606                                         used = pick_up_energy();
607                         }
608                         else {
609                                 char msg[100];
610                                 Players[Player_num].flags |= PLAYER_FLAGS_HEADLIGHT;
611 #ifdef NETWORK
612                                 multi_send_play_sound(Powerup_info[obj->id].hit_sound, F1_0);
613 #endif
614                                 digi_play_sample( Powerup_info[obj->id].hit_sound, F1_0 );
615                                 sprintf(msg, "HEADLIGHT BOOST! (Headlight is %s)", Headlight_active_default.intval?"ON":"OFF");
616                                 powerup_basic(15, 0, 15, 0, msg );
617                                 if (Headlight_active_default.intval)
618                                         Players[Player_num].flags |= PLAYER_FLAGS_HEADLIGHT_ON;
619                                 used=1;
620 #ifdef NETWORK
621                            if (Game_mode & GM_MULTI)
622                                         multi_send_flags (Player_num);
623 #endif
624                         }
625                         break;
626
627 #ifdef NETWORK
628                 case POW_FLAG_BLUE:
629                         if (Game_mode & GM_CAPTURE)                     
630                                 if (get_team(Player_num) == TEAM_RED) {
631                                         powerup_basic(15, 0, 15, 0, "BLUE FLAG!");
632                                         Players[Player_num].flags |= PLAYER_FLAGS_FLAG;
633                                         used=1;
634                                         multi_send_got_flag (Player_num);
635                                 }
636                    break;
637
638                 case POW_HOARD_ORB:
639                         if (Game_mode & GM_HOARD)                       
640                                 if (Players[Player_num].secondary_ammo[PROXIMITY_INDEX]<12) {
641                                         powerup_basic(15, 0, 15, 0, "Orb!!!");
642                                         Players[Player_num].secondary_ammo[PROXIMITY_INDEX]++;
643                                         Players[Player_num].flags |= PLAYER_FLAGS_FLAG;
644                                         used=1;
645                                         multi_send_got_orb (Player_num);
646                                 }
647                   break;        
648
649                 case POW_FLAG_RED:
650                         if (Game_mode & GM_CAPTURE)                     
651                                 if (get_team(Player_num) == TEAM_BLUE) {
652                                         powerup_basic(15, 0, 15, 0, "RED FLAG!");
653                                         Players[Player_num].flags |= PLAYER_FLAGS_FLAG;
654                                         used=1;
655                                         multi_send_got_flag (Player_num);
656                                 }
657                    break;
658 #endif
659
660 //              case POW_HOARD_ORB:
661
662
663                 default:
664                         break;
665                 }
666
667 //always say used, until physics problem (getting stuck on unused powerup)
668 //is solved.  Note also the break statements above that are commented out
669 //!!    used=1;
670
671         if ((used || special_used) && Powerup_info[id].hit_sound  > -1 ) {
672                 #ifdef NETWORK
673                 if (Game_mode & GM_MULTI) // Added by Rob, take this out if it turns out to be not good for net games!
674                         multi_send_play_sound(Powerup_info[id].hit_sound, F1_0);
675                 #endif
676                 digi_play_sample( Powerup_info[id].hit_sound, F1_0 );
677                 detect_escort_goal_accomplished(OBJECT_NUMBER(obj));
678         }
679
680         PlayerMessage=1;
681
682         return used;
683
684 }
685
686 #ifndef FAST_FILE_IO
687 /*
688  * reads n powerup_type_info structs from a CFILE
689  */
690 extern int powerup_type_info_read_n(powerup_type_info *pti, int n, CFILE *fp)
691 {
692         int i;
693
694         for (i = 0; i < n; i++) {
695                 pti[i].vclip_num = cfile_read_int(fp);
696                 pti[i].hit_sound = cfile_read_int(fp);
697                 pti[i].size = cfile_read_fix(fp);
698                 pti[i].light = cfile_read_fix(fp);
699         }
700         return i;
701 }
702 #endif