#include "WorldManager.h" #include "GameManager.h" void InitWorld(VWorld * world) { int theLevel; char levelName[16]; world->LevelValid = 0; world->Levels = (VLevel *) NewPtr(sizeof(VLevel) * NUMLEVELS); world->NumberOfLevels = NUMLEVELS; for (theLevel = 0; theLevel < NUMLEVELS; theLevel++) { sprintf(levelName, "Level %d", (theLevel + 1)); if (!LoadLevel(&world->Levels[theLevel], levelName, world)) { if (theLevel == 0) { SysBeep(1); BuildEmptyLevel(&world->Levels[0]); world->NumberOfLevels = 1; break; } else { world->NumberOfLevels = theLevel; break; } } } InitObject(&world->CrossHair); world->CrossHair.Position.x = 0.0; world->CrossHair.Position.y = 0.0; world->CrossHair.Position.z = -1.7; BuildCrossHairModel(&world->CrossHair.Model); InitObject(&world->Target); BuildTargetBoxModel(&world->Target.Model); world->Target.Billboard = true; StartLevel(world, 0); } void InitPlayer(VPlayer * p) { p->NumRockets = INITIALROCKETS; p->Shields = INITIALSHIELDS; p->HasTurbo = 0; p->HasMachineGun = 0; } void AddWeapon(VWorld * world, int Type) { VWeapon * theWeapon; Vector front; VObjectWrapper * theWObject; if((Type == WEAPONTYPEROCKET && world->Player.NumRockets > 0) || Type == WEAPONTYPEBULLET) { if(Type == WEAPONTYPEROCKET) world->Player.NumRockets--; theWeapon = (VWeapon *) NewPtr(sizeof(VWeapon)); if (theWeapon != NULL) { InitWeapon(theWeapon, Type); AllocateWObject(&theWObject); theWObject->w = theWeapon; theWObject->Type = VWEAPON; theWObject->next = world->Objects; if (world->Objects != NULL) world->Objects->previous = theWObject; world->Objects = theWObject; ForwardsVector(&world->Camera, 1, &front); StartWeapon(theWeapon, &world->Camera.Position, ((front.x * world->Physics.Momentum.x) + (front.y * world->Physics.Momentum.y) + (front.z * world->Physics.Momentum.z)), &front, &world->Camera.Up); } } } void CleanUpWorld(VWorld * world) { VObjectWrapper * theWObject; int theLevel; CleanUpObject(&world->CrossHair); while(world->Objects != NULL) { theWObject = world->Objects; world->Objects = theWObject->next; CleanUpWObject(theWObject); DisposePtr((Ptr) theWObject); } StopLevel(world); for (theLevel = 0; theLevel < world->NumberOfLevels; theLevel++) { CleanUpLevel(&world->Levels[theLevel]); } world->NumberOfLevels = 0; } void DrawCrossHair(VWorld * world) { glPushMatrix(); glLoadIdentity(); glDisable(GL_DEPTH_TEST); DrawObject(&world->CrossHair); glEnable(GL_DEPTH_TEST); glPopMatrix(); } void DrawWorld(VWorld * world, float interval) { VObjectWrapper * theWObject; VObject * object; Vector front; /* Fill with semi transparent background */ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glDepthMask(GL_FALSE); glColor4f(0.0, 0.0, 0.0, ALPHAFILL / interval); glBegin(GL_QUADS); glVertex3f(-10.0, 10.0, -2.0); glVertex3f(10.0, 10.0, -2.0); glVertex3f(10.0, -10.0, -2.0); glVertex3f(-10.0, -10.0, -2.0); glEnd(); glDepthMask(GL_TRUE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); ApplyCamera(&world->Camera); DrawLevel(&world->Level); for(theWObject = world->Objects; theWObject != NULL; theWObject = theWObject->next) { DrawWObject(theWObject); if(theWObject->target) { ForwardsVector(&world->Camera, 1, &front); WObjectObject(theWObject, &object); world->Target.Position = object->Position; glLineWidth(2.0); glDisable(GL_DEPTH_TEST); DrawObject(&world->Target); glLineWidth(1.0); glEnable(GL_DEPTH_TEST); } } if (world->Player.Shields > 0) { DrawCrossHair(world); DrawConsole(&world->Console, interval); } } /* Radius is NOT squared */ Boolean InBounds(VWorld * world, Vector * Pos, float Radius, Vector * wall) { #pragma unused (Radius) float RoomX, RoomY, RoomZ; RoomX = Pos->x / 40; RoomY = Pos->y / 40; RoomZ = Pos->z / 40; wall->x = 0; wall->y = 0; wall->z = 0; if((RoomX - (Radius / 40)) < 0 ) { wall->x = -1; wall->x = -1; return false; } else if ((RoomX + (Radius / 40) - 1) > world->Levels[0].SizeX - 1) { wall->x = 1; return false; } else if ((RoomY - (Radius / 40)) < 0) { wall->y = -1; return false; } else if ((RoomY + (Radius / 40) - 1) > world->Levels[0].SizeY - 1) { wall->y = 1; return false; } else if ((RoomZ - (Radius / 40)) < 0) { wall->z = -1; return false; } else if ((RoomZ + (Radius / 40) - 1) > world->Levels[0].SizeZ - 1) { wall->z = 1; return false; } else if(!world->Levels[0].Cells[((int)(RoomY + Radius/40) * (world->Levels[0].SizeX * world->Levels[0].SizeZ)) + ((int)RoomZ * world->Levels[0].SizeX) + (int)RoomX]) { wall->x = 1; return false; } else if(!world->Levels[0].Cells[((int)(RoomY - Radius/40) * (world->Levels[0].SizeX * world->Levels[0].SizeZ)) + ((int)RoomZ * world->Levels[0].SizeX) + (int)RoomX]) { wall->x = -1; return false; } else if(!world->Levels[0].Cells[((int)RoomY * (world->Levels[0].SizeX * world->Levels[0].SizeZ)) + ((int)(RoomZ + Radius/40) * world->Levels[0].SizeX) + (int)RoomX]) { wall->z = 1; return false; } else if(!world->Levels[0].Cells[((int)RoomY * (world->Levels[0].SizeX * world->Levels[0].SizeZ)) + ((int)(RoomZ - Radius/40) * world->Levels[0].SizeX) + (int)RoomX]) { wall->z = -1; return false; }else if(!world->Levels[0].Cells[((int)RoomY * (world->Levels[0].SizeX * world->Levels[0].SizeZ)) + ((int)RoomZ * world->Levels[0].SizeX) + (int)(RoomX + Radius/40)]) { wall->x = 1; return false; }else if(!world->Levels[0].Cells[((int)RoomY * (world->Levels[0].SizeX * world->Levels[0].SizeZ)) + ((int)RoomZ * world->Levels[0].SizeX) + (int)(RoomX - Radius/40)]) { wall->x = -1; return false; } return true; } static void IsGameOver(VWorld * w) { VObjectWrapper * theWObject; VObject * o; Boolean found; found = false; theWObject = w->Objects; while(theWObject != NULL) { WObjectObject(theWObject, &o); if(o) if(o->MustBeDestroyed && !(o->taggedForRemoval || theWObject->taggedForRemoval)) { found = true; break; } theWObject = theWObject->next; } if(!found) w->Finished = true; } void RunWorld(VWorld * world, float interval) { VObjectWrapper * theWObject; VObjectWrapper * obj; VObjectWrapper * next; VObjectWrapper * powerup; VObject * object; Vector front; Vector right; Vector wall; Boolean exploded; if((!InBounds(world, &world->Camera.Position, sqrt(PLAYERSHIPRADIUS), &wall)) && world->Player.Shields > 0) { if(wall.x) world->Physics.Momentum.x = -world->Physics.Momentum.x; else if(wall.y) world->Physics.Momentum.y = -world->Physics.Momentum.y; else if(wall.z) world->Physics.Momentum.z = -world->Physics.Momentum.z; DamagePlayer(world, VectorMagnitude(&world->Physics.Momentum) * 1000); } powerup = NULL; theWObject = world->Objects; while(theWObject != NULL) { next = theWObject->next; if(theWObject == NULL) break; RunWObject(theWObject, interval, world); exploded = false; if(theWObject->exploded == 1) { AllocateWObject(&obj); AllocateExplosion(obj); WObjectObject(theWObject, &object); if (object != NULL && object->PowerupType != POWERUPTYPENONE) { AllocateWObject(&powerup); AllocatePowerup(powerup); InitPowerup(powerup->p); SetupPowerup(powerup->p, object->PowerupType, object->PowerupAmount); powerup->p->Object.Position = object->Position; } switch(theWObject->Type) { case VOBJECT: InitExplosion(obj->ex, theWObject->o, 7); CleanUpObject(theWObject->o); DisposePtr((Ptr)theWObject->o); break; case VENEMY: InitExplosion(obj->ex, &theWObject->e->Object, 7); CleanUpEnemy(theWObject->e); DisposePtr((Ptr)theWObject->e); break; case VWEAPON: InitExplosion(obj->ex, &theWObject->w->Object, theWObject->explosionLevel); CleanUpWeapon(theWObject->w); DisposePtr((Ptr)theWObject->w); break; } exploded = true; } if(theWObject->exploded == 2) { AllocateWObject(&obj); AllocateExplosion(obj); switch(theWObject->Type) { case VOBJECT: InitExplosion(obj->ex, theWObject->o, 1); break; case VENEMY: InitExplosion(obj->ex, &theWObject->e->Object, 1); break; } world->Objects->previous = obj; obj->next = world->Objects; world->Objects = obj; theWObject->exploded = 0; } if(theWObject->taggedForRemoval) { WObjectObject(theWObject, &object); if(object) if(object->MustBeDestroyed) IsGameOver(world); if(theWObject->target) FindTarget(world); if(theWObject->next) theWObject->next->previous = theWObject->previous; if(theWObject->previous) theWObject->previous->next = theWObject->next; else world->Objects = world->Objects->next; DisposePtr((Ptr)theWObject); } if(exploded) { if(world->Objects) world->Objects->previous = obj; obj->next = world->Objects; world->Objects = obj; if(powerup) { if(world->Objects) world->Objects->previous = powerup; powerup->next = world->Objects; world->Objects = powerup; } } theWObject = next; } if (world->Player.Shields > 0) { ForwardsVector(&world->Camera, 1.0, &front); CrossProduct(&world->Camera.Up, &front, &right); RunPhysics(&world->Physics, &world->Camera.Position, &front, &right, &world->Camera.Up, interval); AddVector(&world->Camera.Position, &front, &world->Camera.Look); } } void DamagePlayer(VWorld * world, int amount) { world->Player.Shields -= amount; world->Camera.Shake = ((float) (amount * 2) / 5.0); if (world->Camera.Shake > 1.0) world->Camera.Shake = 1.0; if (world->Player.Shields <= 0) { VObjectWrapper * obj; VObject temp; world->Camera.Shake = 0.0; InitObject(&temp); BuildCockpitModel(&temp.Model); temp.Position = world->Camera.Position; AllocateWObject(&obj); AllocateExplosion(obj); InitExplosion(obj->ex, &temp, 10); CleanUpObject(&temp); if (world->Objects) world->Objects->previous = obj; obj->next = world->Objects; world->Objects = obj; } } void FindTarget(VWorld * w) { VObjectWrapper * theWObject; VObject * theObject; Boolean picked; theWObject = w->Objects; picked = false; while(theWObject != NULL) { if(theWObject->target) theWObject->target = false; if(!theWObject->picked && (theWObject->Type == VENEMY || theWObject->Type == VOBJECT) && !picked) { WObjectObject(theWObject, &theObject); if ((((theObject->Position.x - w->Camera.Position.x) * (theObject->Position.x - w->Camera.Position.x)) + ((theObject->Position.y - w->Camera.Position.y) * (theObject->Position.y - w->Camera.Position.y)) + ((theObject->Position.z - w->Camera.Position.z) * (theObject->Position.z - w->Camera.Position.z))) < MAXROCKETTARGETRANGE) { theWObject->picked = true; theWObject->target = true; picked = true; } } theWObject = theWObject->next; } if(!picked) { theWObject = w->Objects; while(theWObject != NULL) { if(theWObject->picked) theWObject->picked = false; if((theWObject->Type == VENEMY || theWObject->Type == VOBJECT) && !picked) { WObjectObject(theWObject, &theObject); if ((((theObject->Position.x - w->Camera.Position.x) * (theObject->Position.x - w->Camera.Position.x)) + ((theObject->Position.y - w->Camera.Position.y) * (theObject->Position.y - w->Camera.Position.y)) + ((theObject->Position.z - w->Camera.Position.z) * (theObject->Position.z - w->Camera.Position.z))) < MAXROCKETTARGETRANGE) { theWObject->picked = true; theWObject->target = true; picked = true; } } theWObject = theWObject->next; } } } void StartLevel(VWorld * world, int level) { char levelName[16]; InitCamera(&world->Camera); InitPlayer(&world->Player); world->CurrentLevel = level; CopyLevel(&world->Levels[level], &world->Level); world->LevelValid = 1; world->Camera.Position = world->Level.StartPos; world->Camera.Look = world->Camera.Position; switch (world->Level.Look) { case LEFT: world->Camera.Look.x -= 1.0; break; case RIGHT: world->Camera.Look.x += 1.0; break; case FORWARDS: world->Camera.Look.z -= 1.0; break; case BACKWARDS: default: world->Camera.Look.z += 1.0; break; } world->Objects = world->Level.Objects; world->Level.Objects = NULL; InitPhysics(&world->Physics); FindTarget(world); world->Finished = false; sprintf(levelName, "Level %d", (level + 1)); PushConsoleMessage(&world->Console, levelName); } void StopLevel(VWorld * world) { if (world->LevelValid) { CleanUpLevel(&world->Level); world->LevelValid = 0; } }