#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;	}}