-
Notifications
You must be signed in to change notification settings - Fork 0
/
weapon.cp
666 lines (591 loc) · 28.5 KB
/
weapon.cp
1
/****************************************************************************************//* WEAPON.CP *//****************************************************************************************//* (c) 1995 by Magnet Interactive Studios, inc. All rights reserved. *//****************************************************************************************//* Revision History: *//* 7/20/94 File first created. By Andrew Looney. *//* v1.0 8/5/94 First polished version. By Andrew Looney. *//* 8/8/94 Started making changes for next version. *//* v2.0 8/24/94 Seven level version burned onto CD-ROM. By Andrew Looney. *//* v2.1 8/29/94 Comments brought back up to date. By Andrew Looney. *//* v2.2 9/7/94 Sixteen level version. By Andrew Looney. *//* v2.3 9/23/94 Thirty level version burned onto CD-ROM. By Andrew Looney. *//* v2.4 10/19/94 Fifty level version. By Andrew Looney. *//* v2.5 10/31/94 Sixty level version burned onto CD-ROM. By Andrew Looney. *//* v3.0 10/31/94 Began switching over to real artwork. By Andrew Looney. *//* v3.1 11/11/94 COMDEX version. By Andrew Looney. *//* v3.2 12/2/94 Seventy-five level version. By Andrew Looney. *//* v3.3 12/14/94 Ack! Zombies! By Andrew Looney. *//* v3.4 12/23/94 Orange Meanies! By Andrew Looney. *//* v3.5 1/3/95 100 Levels! By Andrew Looney. *//* v3.6 1/5/95 101 Levels. By Andrew Looney. *//* v3.7 1/16/95 New, improved Brainy Seeker logic! By Andrew Looney. *//* v3.8 1/27/95 114 level version burned onto CD-ROM. By Andrew Looney. *//* v3.9 2/3/95 New CD-ROM burned for shipment to 3DO. By Andrew Looney. *//* v4.0 2/9/95 New CD-ROM featuring the big level grid. By Andrew Looney. *//* v4.1 2/22/95 New CD-ROM with rough draft of full interface. By Andrew Looney. *//* v4.2 3/17/95 The St. Patrick's Day Version. By Andrew Looney. *//* v4.3 3/20/95 The last version before the movies get added. By Andrew Looney. *//* v4.4 3/21/95 First version with movies integrated. By Andrew Looney. *//* v4.5 3/22/95 Second version with movies integrated. By Andrew Looney. *//* v4.6 3/27/95 Third version with movies integrated. By Andrew Looney. *//* v5.0 3/28/95 Newest version sent to QA. By Andrew Looney. *//* v5.1 3/28/95 Now, with Easter Eggs! By Andrew Looney. *//* v5.2 3/29/95 Could this be the final version? By Andrew Looney. *//* v5.3 3/30/95 OK, now maybe THIS is the final version! By Andrew Looney. *//* v5.4 4/3/95 Made a couple more minor changes. By Andrew Looney. *//****************************************************************************************//***************************** WHAT THIS SOFTWARE DOES ********************************** This function handles the firing of a weapon controlled by the dudemeyer, tracks the shots fired by that weapon, provides for their display to the screen, and handles the results that occur when those shots hit something. There are a fixed number of bullets that can be in play at one time (set by the defined symbol MAX_BULLETS). Each bullet has a direction and a state. The states a bullet can be in are: BULLET_INACTIVE: The bullet is not visible and can be fired BULLET_MOVING: The bullet is active but hasn't hit anything BULLET_EXPLODING: The bullet has struck a target*****************************************************************************************//***** regular includes *****/#include "graphics.h"#include "stdio.h"#include "stdlib.h"#include "mem.h"#include "types.h"#include "hardware.h"#include "event.h"#include "strings.h"#include "access.h"#include "UMemory.h"#include "Form3DO.h"#include "Init3DO.h"#include "Parse3DO.h"#include "Utils3DO.h"#include "audio.h"#include "music.h"/***** magnet includes *****/#include "icebreaker.h"#include "animation.h"#include "landscape.h"#include "solids.h"#include "weapon.h"#include "sounds.h"#include "seeker.h"#include "deadlist.h"/***** special c++ include (this must be last) *****/#include "CPlusSwiHack.h"/***** global variables *****/extern ScreenContext g_screen;extern int32 g_total_pyramids;/***** global class instantiations *****/extern solids population;extern seeker enemies;extern dead_list morgue;extern landscape pavement;/**************************** weapon::LoadArtwork ************************************* This function is intended for use only during the first initialization of theprogram. It loads a single copy of each artwork element that will be needed by thisclass, and stores pointers to these artwork elements in variables available to the class. Multiple copies of these artwork elements can then be created (and destroyed) simply by creating other pointers and setting them equal to the pointers initialized in this function. The artwork will remain in memory until the function ShutdownForExit() is called. The artwork files used by this function are provided via symbols defined in the overall application's header file. This function returns TRUE if the art was loaded successful, and FALSE if one or more art files could not be properly loaded.*****************************************************************************************/bool weapon::LoadArtwork (void){ if ((!(bullet_source[NORTH].LoadArtwork (FIREBALL_NORTH))) || (!(bullet_source[EAST].LoadArtwork (FIREBALL_EAST))) || (!(bullet_source[WEST].LoadArtwork (FIREBALL_WEST))) || (!(bullet_source[SOUTH].LoadArtwork (FIREBALL_SOUTH))) || (!(bullet_source[NORTHEAST].LoadArtwork (FIREBALL_NORTHEAST))) || (!(bullet_source[NORTHWEST].LoadArtwork (FIREBALL_NORTHWEST))) || (!(bullet_source[SOUTHEAST].LoadArtwork (FIREBALL_SOUTHEAST))) || (!(bullet_source[SOUTHWEST].LoadArtwork (FIREBALL_SOUTHWEST))) || (!(fireball_death.LoadArtwork (FIREBALL_DEATH_ANIM)))) { printf("weapon::LoadArtwork: Couldn't open fireball artwork.\n"); return(FALSE); } return(TRUE);}/************************** weapon::InitializeWeapon ********************************** This function handles all setup and initialization of variables that are used by this class. It is intended to be used repeatedly, at the start of each round of the game.*****************************************************************************************/void weapon::InitializeWeapon (void){ int32 i; for (i = 0; i < MAX_BULLETS; i++) { bullet[i].InitializeAnim (&bullet_source[0], STANDARD_FRAME_RATE); bullet_state[i] = BULLET_INACTIVE; } step_size = 5; /* this is how far we move the bullet during each movement */ /* phase before checking to see if it hit anything. */ speed = FIREBALL_SPEED >> 16;}/**************************** weapon::FireWeapon ************************************** This function looks through the supply of bullets to see if any are available. If it finds one in the BULLET_INACTIVE state, it changes that bullet's state to BULLET_MOVINGand sets the direction equal to the line of fire supplied in the parameter list. If no bullets are available, FALSE is returned.*****************************************************************************************/bool weapon::FireWeapon (int32 firing_direction){ int32 i; for (i = 0; i < MAX_BULLETS; i++) { if (bullet_state[i] == BULLET_INACTIVE) { PlaySoundEffect(SHOOT_SOUND); bullet[i].ChangeArt (&bullet_source[firing_direction]); CenterCelOnScreen(bullet[i].current_frame_ccb); bullet[i].Restart(); bullet_state[i] = BULLET_MOVING; bullet_direction[i] = firing_direction; return (TRUE); } } return (FALSE);}/**************************** weapon::DetectHit *************************************** This function uses the all-purpose collision detection function in the solids class to see if a bullet has struck a target. If the bullet didn't hit anything of consequence, then this function returns FALSE so that the bullet can continue on its way. If it did hit something, then that something will either be something that the bullet can destroy (in which case, this function carries out the object's destruction and sets the bullet's state to BULLET_EXPLODING) or it'll be something that is impervious to the bullet, in which case we declare that the bullet has fizzled and start up an animation of the bullet splattering but doing no damage.*****************************************************************************************/bool weapon::DetectHit (int32 bullet_number){ solid_object *obstruction; anisolid *animated_obstruction; obstruction = population.DetectCollision(bullet[bullet_number].current_frame_ccb, FIREBALL_COL_DETECT_X, FIREBALL_COL_DETECT_Y,TRUE); if ((obstruction == (solid_object *) NULL) || (obstruction->object_type == DEATH_SCENE) || (obstruction->object_type == BIRTH_SCENE)) return(FALSE); if (obstruction->object_type == DUDEMEYER) { printf("weapon::DetectHit returned with the dudemeyer! That shouldn't happen!\n"); return(FALSE); } /***** if it's a pyschedelic piece, change it to something else before going on *****/ if (obstruction->object_type == RAINBOW_PYRAMID) { population.EliminateAnimatedObject(obstruction); population.ResolveRainbowPyramid(obstruction); population.ChangeArt(obstruction->cel, (char) obstruction->object_type); } /***** custom destruction process for red pieces *****/ if ((obstruction->object_type == RED_PYRAMID)) { PlaySoundEffect(ZAP_SOUND); morgue.CreateDeathScene (&population.red_death, STANDARD_FRAME_RATE, obstruction->cel->ccb_XPos,obstruction->cel->ccb_YPos, PYRAMID_COL_DETECT_X, PYRAMID_COL_DETECT_Y,0); } /***** custom destruction process for concrete pieces *****/ if ((obstruction->object_type == CONCRETE_PYRAMID)) { bullet_state[bullet_number] = BULLET_EXPLODING; animated_obstruction = population.LocateAnimatedObject(obstruction); animated_obstruction->solid_anim.AdvanceFrame(); if (animated_obstruction->solid_anim.AnimComplete()) { PlaySoundEffect(CONCRETE_CRUMBLE_SOUND); morgue.CreateDeathScene (&population.concrete_death, STANDARD_FRAME_RATE, obstruction->cel->ccb_XPos, obstruction->cel->ccb_YPos, PYRAMID_COL_DETECT_X, PYRAMID_COL_DETECT_Y,0); population.EliminateObject(obstruction); g_total_pyramids--; return(TRUE); } morgue.CreateDeathScene (&population.concrete_puff[RandomNumber(0,2)], STANDARD_FRAME_RATE, obstruction->cel->ccb_XPos, obstruction->cel->ccb_YPos, PYRAMID_COL_DETECT_X, PYRAMID_COL_DETECT_Y,0); PlaySoundEffect(CONCRETE_CHIP_SOUND); return(TRUE); } /***** custom destruction process for purple pieces *****/ if ((obstruction->object_type == PURPLE_PYRAMID)) { PlaySoundEffect(PIT_RUMBLE_SOUND); pavement.TransformTile(FIND_CENTER_X(obstruction->cel), FIND_CENTER_Y(obstruction->cel), 0, 0, GB2PA_TILE); morgue.CreateDeathScene (&population.purple_death, STANDARD_FRAME_RATE, obstruction->cel->ccb_XPos,obstruction->cel->ccb_YPos, PYRAMID_COL_DETECT_X, PYRAMID_COL_DETECT_Y,0); } /***** generic destruction process either type of yellow piece *****/ if ((obstruction->object_type == YELLOW_SEEKER) || (obstruction->object_type == YELLOW_PYRAMID)) { PlaySoundEffect(ERODE_SOUND); morgue.CreateDeathScene (&enemies.yellow_death, STANDARD_FRAME_RATE, obstruction->cel->ccb_XPos,obstruction->cel->ccb_YPos, PYRAMID_COL_DETECT_X, PYRAMID_COL_DETECT_Y,0); } /***** generic destruction process either type of light blue piece *****/ if ((obstruction->object_type == LTBLUE_SEEKER) || (obstruction->object_type == LTBLUE_PYRAMID)) { PlaySoundEffect(LTBLUE_DEATH_SOUND); morgue.CreateDeathScene (&enemies.ltblue_death, STANDARD_FRAME_RATE, obstruction->cel->ccb_XPos,obstruction->cel->ccb_YPos, PYRAMID_COL_DETECT_X, PYRAMID_COL_DETECT_Y,0); } /***** generic destruction process either type of pink piece *****/ if ((obstruction->object_type == PINK_SEEKER) || (obstruction->object_type == PINK_PYRAMID)) { PlaySoundEffect(PINK_DEATH_SOUND); morgue.CreateDeathScene (&enemies.pink_death, STANDARD_FRAME_RATE, obstruction->cel->ccb_XPos,obstruction->cel->ccb_YPos, PYRAMID_COL_DETECT_X, PYRAMID_COL_DETECT_Y,0); } /***** destruction process for zombies *****/ if (obstruction->object_type == ZOMBIE) { bullet_state[bullet_number] = BULLET_EXPLODING; enemies.ShootZombie(obstruction); return(TRUE); } /***** generic destruction process for lurkers *****/ if ((obstruction->object_type == LURKER) || (obstruction->object_type == LURKER_PYRAMID)) { PlaySoundEffect(LURKER_DEATH_SOUND); if ((bullet_direction[bullet_number] == EAST) || (bullet_direction[bullet_number] == NORTHEAST)) morgue.CreateDeathScene (&enemies.lurker_death_w, STANDARD_FRAME_RATE, obstruction->cel->ccb_XPos,obstruction->cel->ccb_YPos, PYRAMID_COL_DETECT_X, PYRAMID_COL_DETECT_Y,0); if ((bullet_direction[bullet_number] == WEST) || (bullet_direction[bullet_number] == SOUTHWEST)) morgue.CreateDeathScene (&enemies.lurker_death_e, STANDARD_FRAME_RATE, obstruction->cel->ccb_XPos,obstruction->cel->ccb_YPos, PYRAMID_COL_DETECT_X, PYRAMID_COL_DETECT_Y,0); if ((bullet_direction[bullet_number] == NORTH) || (bullet_direction[bullet_number] == NORTHWEST)) morgue.CreateDeathScene (&enemies.lurker_death_s, STANDARD_FRAME_RATE, obstruction->cel->ccb_XPos,obstruction->cel->ccb_YPos, PYRAMID_COL_DETECT_X, PYRAMID_COL_DETECT_Y,0); if ((bullet_direction[bullet_number] == SOUTH) || (bullet_direction[bullet_number] == SOUTHEAST)) morgue.CreateDeathScene (&enemies.lurker_death_n, STANDARD_FRAME_RATE, obstruction->cel->ccb_XPos,obstruction->cel->ccb_YPos, PYRAMID_COL_DETECT_X, PYRAMID_COL_DETECT_Y,0); } /***** destruction process for meanies *****/ if ((obstruction->object_type == MEANY) || (obstruction->object_type == NASTY) || (obstruction->object_type == GRUMPY)) { bullet_state[bullet_number] = BULLET_EXPLODING; enemies.ShootSplitter(obstruction); return(TRUE); } /***** destruction process for dormant chameleons *****/ if (obstruction->object_type == DORMANT_CHAMELEON) { PlaySoundEffect(LIME_DEATH_SOUND); if ((bullet_direction[bullet_number] == EAST) || (bullet_direction[bullet_number] == NORTHEAST)) morgue.CreateDeathScene (&enemies.cham_death_w, STANDARD_FRAME_RATE, obstruction->cel->ccb_XPos,obstruction->cel->ccb_YPos, PYRAMID_COL_DETECT_X, PYRAMID_COL_DETECT_Y,0); if ((bullet_direction[bullet_number] == WEST) || (bullet_direction[bullet_number] == SOUTHWEST)) morgue.CreateDeathScene (&enemies.cham_death_e, STANDARD_FRAME_RATE, obstruction->cel->ccb_XPos,obstruction->cel->ccb_YPos, PYRAMID_COL_DETECT_X, PYRAMID_COL_DETECT_Y,0); if ((bullet_direction[bullet_number] == NORTH) || (bullet_direction[bullet_number] == NORTHWEST)) morgue.CreateDeathScene (&enemies.cham_death_s, STANDARD_FRAME_RATE, obstruction->cel->ccb_XPos,obstruction->cel->ccb_YPos, PYRAMID_COL_DETECT_X, PYRAMID_COL_DETECT_Y,0); if ((bullet_direction[bullet_number] == SOUTH) || (bullet_direction[bullet_number] == SOUTHEAST)) morgue.CreateDeathScene (&enemies.cham_death_n, STANDARD_FRAME_RATE, obstruction->cel->ccb_XPos,obstruction->cel->ccb_YPos, PYRAMID_COL_DETECT_X, PYRAMID_COL_DETECT_Y,0); } /***** destruction process for lime pieces, active, and semi-active chameleons *****/ if ((obstruction->object_type == LIME_SEEKER) || (obstruction->object_type == LIME_PYRAMID) || (obstruction->object_type == WAKING_CHAMELEON) || (obstruction->object_type == ACTIVE_CHAMELEON)) { PlaySoundEffect(LIME_DEATH_SOUND); if ((bullet_direction[bullet_number] == EAST) || (bullet_direction[bullet_number] == NORTHEAST)) morgue.CreateDeathScene (&enemies.lime_death_w, STANDARD_FRAME_RATE, obstruction->cel->ccb_XPos,obstruction->cel->ccb_YPos, PYRAMID_COL_DETECT_X, PYRAMID_COL_DETECT_Y,0); if ((bullet_direction[bullet_number] == WEST) || (bullet_direction[bullet_number] == SOUTHWEST)) morgue.CreateDeathScene (&enemies.lime_death_e, STANDARD_FRAME_RATE, obstruction->cel->ccb_XPos,obstruction->cel->ccb_YPos, PYRAMID_COL_DETECT_X, PYRAMID_COL_DETECT_Y,0); if ((bullet_direction[bullet_number] == NORTH) || (bullet_direction[bullet_number] == NORTHWEST)) morgue.CreateDeathScene (&enemies.lime_death_s, STANDARD_FRAME_RATE, obstruction->cel->ccb_XPos,obstruction->cel->ccb_YPos, PYRAMID_COL_DETECT_X, PYRAMID_COL_DETECT_Y,0); if ((bullet_direction[bullet_number] == SOUTH) || (bullet_direction[bullet_number] == SOUTHEAST)) morgue.CreateDeathScene (&enemies.lime_death_n, STANDARD_FRAME_RATE, obstruction->cel->ccb_XPos,obstruction->cel->ccb_YPos, PYRAMID_COL_DETECT_X, PYRAMID_COL_DETECT_Y,0); } /***** generic destruction process for all types of seekers *****/ if ((obstruction->object_type == LTBLUE_SEEKER) || (obstruction->object_type == PINK_SEEKER) || (obstruction->object_type == LIME_SEEKER) || (obstruction->object_type == LURKER) || (obstruction->object_type == DORMANT_CHAMELEON) || (obstruction->object_type == ACTIVE_CHAMELEON) || (obstruction->object_type == WAKING_CHAMELEON) || (obstruction->object_type == YELLOW_SEEKER)) { bullet_state[bullet_number] = BULLET_EXPLODING; enemies.SendHome(obstruction); return(TRUE); } /***** generic destruction process for all types of static pyramids *****/ if ((obstruction->object_type == YELLOW_PYRAMID) || (obstruction->object_type == LTBLUE_PYRAMID) || (obstruction->object_type == PINK_PYRAMID) || (obstruction->object_type == LIME_PYRAMID) || (obstruction->object_type == LURKER_PYRAMID) || (obstruction->object_type == RED_PYRAMID) || (obstruction->object_type == PURPLE_PYRAMID)) { bullet_state[bullet_number] = BULLET_EXPLODING; population.EliminateObject(obstruction); g_total_pyramids--; return(TRUE); } /***** if it didn't hit something we know how to destroy, then fireball fizzles *****/ PlaySoundEffect(SPLAT_SOUND); bullet_state[bullet_number] = BULLET_INACTIVE; morgue.CreateDeathScene (&fireball_death, STANDARD_FRAME_RATE, bullet[bullet_number].current_frame_ccb->ccb_XPos, bullet[bullet_number].current_frame_ccb->ccb_YPos, FIREBALL_COL_DETECT_X, FIREBALL_COL_DETECT_Y,0); if ((bullet_direction[bullet_number] == SOUTH) || (bullet_direction[bullet_number] == SOUTHWEST) || (bullet_direction[bullet_number] == SOUTHEAST)) morgue.AdjustPositionOfNewDeath(obstruction,TRUE); else morgue.AdjustPositionOfNewDeath(obstruction,FALSE); return(TRUE);}/*************************** weapon::MoveBullets ************************************** Depending on how fast the bullets move (which is determined by the variable speed) it may be possible for a bullet to miss a target it would have otherwise hit if you simply move it from where it is to where it will reach at it's current speed. Thus, we move the bullet along in smaller increments, doing collision detection at each step of the way, stopping as soon as we hit something. If a bullet disappears off the edge of the screen without hitting anything, we give up on it and set its value back to BULLET_INACTIVE.*****************************************************************************************/void weapon::MoveBullets (int32 x_change, int32 y_change){ int32 i,j; int32 diagonal_y; diagonal_y = ((step_size * 2) / 3) << 16; for (i = 0; i < MAX_BULLETS; i++) { if (bullet_state[i] != BULLET_INACTIVE) { bullet[i].current_frame_ccb->ccb_XPos += x_change; bullet[i].current_frame_ccb->ccb_YPos += y_change; for (j = step_size; j <= speed; j += step_size) { switch (bullet_direction[i]) { case NORTH: bullet[i].current_frame_ccb->ccb_YPos -= (step_size << 16); break; case SOUTH: bullet[i].current_frame_ccb->ccb_YPos += (step_size << 16); break; case EAST: bullet[i].current_frame_ccb->ccb_XPos += (step_size << 16); break; case WEST: bullet[i].current_frame_ccb->ccb_XPos -= (step_size << 16); break; case NORTHWEST: bullet[i].current_frame_ccb->ccb_XPos -= (step_size << 16); bullet[i].current_frame_ccb->ccb_YPos -= diagonal_y; break; case NORTHEAST: bullet[i].current_frame_ccb->ccb_XPos += (step_size << 16); bullet[i].current_frame_ccb->ccb_YPos -= diagonal_y; break; case SOUTHWEST: bullet[i].current_frame_ccb->ccb_XPos -= (step_size << 16); bullet[i].current_frame_ccb->ccb_YPos += diagonal_y; break; case SOUTHEAST: bullet[i].current_frame_ccb->ccb_XPos += (step_size << 16); bullet[i].current_frame_ccb->ccb_YPos += diagonal_y; break; } if (!(ObjectVisible(bullet[i].current_frame_ccb))) { bullet_state[i] = BULLET_INACTIVE; break; } if (bullet_state[i] == BULLET_MOVING) { if (DetectHit(i)) break; } } } }}/************************* weapon::DivineIntervention ********************************* Comments go here... this function is still in development.*****************************************************************************************/bool weapon::DivineIntervention (solid_object *potential_victim){ int32 i,j; int32 original_x; int32 original_y; solid_object *obstruction; bool return_value; int32 diagonal_y; diagonal_y = ((step_size * 2) / 3) << 16; return_value = FALSE; for (i = 0; i < MAX_BULLETS; i++) { if (bullet_state[i] == BULLET_MOVING) { original_x = bullet[i].current_frame_ccb->ccb_XPos; original_y = bullet[i].current_frame_ccb->ccb_YPos; for (j = step_size; j <= speed; j += step_size) { switch (bullet_direction[i]) { case NORTH: bullet[i].current_frame_ccb->ccb_YPos -= (step_size << 16); break; case SOUTH: bullet[i].current_frame_ccb->ccb_YPos += (step_size << 16); break; case EAST: bullet[i].current_frame_ccb->ccb_XPos += (step_size << 16); break; case WEST: bullet[i].current_frame_ccb->ccb_XPos -= (step_size << 16); break; case NORTHWEST: bullet[i].current_frame_ccb->ccb_XPos -= (step_size << 16); bullet[i].current_frame_ccb->ccb_YPos -= diagonal_y; break; case NORTHEAST: bullet[i].current_frame_ccb->ccb_XPos += (step_size << 16); bullet[i].current_frame_ccb->ccb_YPos -= diagonal_y; break; case SOUTHWEST: bullet[i].current_frame_ccb->ccb_XPos -= (step_size << 16); bullet[i].current_frame_ccb->ccb_YPos += diagonal_y; break; case SOUTHEAST: bullet[i].current_frame_ccb->ccb_XPos += (step_size << 16); bullet[i].current_frame_ccb->ccb_YPos += diagonal_y; break; } obstruction = population.DetectCollision(bullet[i].current_frame_ccb, FIREBALL_COL_DETECT_X,FIREBALL_COL_DETECT_Y,TRUE); if (obstruction == potential_victim) return_value = TRUE; } bullet[i].current_frame_ccb->ccb_XPos = original_x; bullet[i].current_frame_ccb->ccb_YPos = original_y; } } return(return_value);}/*************************** weapon::DrawBullets ************************************** This function draws all of the currently visible bullets by adding them into thesolids list just before the solids list is drawn to the screen (that's when this functionis supposed to be called). This function's companion routine, UndrawBullets, should becalled immediately after the solids list is drawn... it removes the bullets again, anddoes some other maintainance processing.*****************************************************************************************/void weapon::DrawBullets (void){ int32 i; for (i = 0; i < MAX_BULLETS; i++) { if (bullet_state[i] != BULLET_INACTIVE) { if (bullet_state[i] == BULLET_EXPLODING) { /* skip to last frame so that fireball tail disappears on impact: */ while (!(bullet[i].AnimComplete())) bullet[i].AdvanceFrame(); } if (!((bullet[i].current_frame_ccb->ccb_XPos >> 16 == 124) && (bullet[i].current_frame_ccb->ccb_YPos >> 16 == 102))) population.AddToList(bullet[i].current_frame_ccb, FIREBALL, 0, 0); } }}/************************** weapon::UndrawBullets ************************************** This function is called immediately after the solids list is drawn to the screen,which in turn is done just after calling this function's companion routine, DrawBullets.This function takes the bullets back off the list (we only put them there to get thebullets sorted properly for visual purposes... since we move them around so much, and since they have such sort lifespans, it's better not to have them on the list full time).This function also advances the frame and switches the state to inactive if the bulletis about to die.*****************************************************************************************/void weapon::UndrawBullets (void){ int32 i; for (i = 0; i < MAX_BULLETS; i++) { if (bullet_state[i] != BULLET_INACTIVE) { if (!((bullet[i].current_frame_ccb->ccb_XPos >> 16 == 124) && (bullet[i].current_frame_ccb->ccb_YPos >> 16 == 102))) population.EliminateObject(bullet[i].current_frame_ccb); bullet[i].AdvanceFrame(); } if (bullet_state[i] == BULLET_EXPLODING) bullet_state[i] = BULLET_INACTIVE; }}/*************************** weapon::StopBullets ************************************** Sometimes, a player can get killed by something that he was just shooting at, in sucha way that both the player and the dude that killed him are destroyed. This tends to makethe player feel ripped off: "But I shot him!" they shout. Therefore, we use this routineto turn off any bullets in the air when a player gets killed.*****************************************************************************************/void weapon::StopBullets (void){ int32 i; for (i = 0; i < MAX_BULLETS; i++) bullet_state[i] = BULLET_INACTIVE;}/************************* weapon::ShutdownForRestart ********************************* When a game ends, the player will either wish to quit or play again. In either case,this function should be called to surrender memory that was dynamically allocated duringthe game. Needless to say, it is particularly important that this function be calledafter every game; otherwise the memory that was used cannot be re-allocated.*****************************************************************************************/void weapon::ShutdownForRestart (void){ int32 i; for (i = 0; i < MAX_BULLETS; i++) bullet[i].ShutdownForRestart();}/************************** weapon::ShutdownForExit *********************************** This function deallocates memory that was reserved for storage of artwork elementsthat are used repeatedly over a sequence of many games. This function should be calledwhen (but only when) the program is about to be shutdown for good.*****************************************************************************************/void weapon::ShutdownForExit (void){ int32 i; for (i = 0; i < 8; i++) bullet_source[i].ShutdownForExit(); fireball_death.ShutdownForExit();}/***************************************** EOF ******************************************/