summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/AGL_DSp.cpp242
-rw-r--r--src/AGL_DSp.h41
-rw-r--r--src/Alerts.cpp93
-rw-r--r--src/Alerts.h44
-rw-r--r--src/Camera.cpp9
-rw-r--r--src/Camera.h29
-rw-r--r--src/Constants.h136
-rw-r--r--src/Decals.cpp375
-rw-r--r--src/Decals.h59
-rw-r--r--src/Files.cpp173
-rw-r--r--src/Files.h113
-rw-r--r--src/Fog.cpp54
-rw-r--r--src/Fog.h28
-rw-r--r--src/Frustum.cpp246
-rw-r--r--src/Frustum.h14
-rw-r--r--src/Game.h230
-rw-r--r--src/GameDraw.cpp1770
-rw-r--r--src/GameInitDispose.cpp4235
-rw-r--r--src/GameLoop.cpp573
-rw-r--r--src/GameTick.cpp4957
-rw-r--r--src/Globals.cpp89
-rw-r--r--src/MacInput.cpp46
-rw-r--r--src/MacInput.h105
-rw-r--r--src/Main.cpp64
-rw-r--r--src/Maths.cpp24
-rw-r--r--src/Maths.h11
-rw-r--r--src/Models.cpp341
-rw-r--r--src/Models.h66
-rw-r--r--src/Person.cpp1045
-rw-r--r--src/Person.h157
-rw-r--r--src/PhysicsMath.h1432
-rw-r--r--src/Quaternions.cpp747
-rw-r--r--src/Quaternions.h94
-rw-r--r--src/SConstruct10
-rw-r--r--src/Serialize.cpp107
-rw-r--r--src/Serialize.h13
-rw-r--r--src/Skeleton.cpp817
-rw-r--r--src/Skeleton.h156
-rw-r--r--src/Sprites.cpp331
-rw-r--r--src/Sprites.h94
-rw-r--r--src/Support.cpp386
-rw-r--r--src/Support.h60
-rw-r--r--src/TGALoader.cpp83
-rw-r--r--src/TGALoader.h36
-rw-r--r--src/Text.cpp68
-rw-r--r--src/Text.h32
-rw-r--r--src/Textures.cpp73
-rw-r--r--src/Textures.h14
-rw-r--r--src/Timer.cpp28
-rw-r--r--src/Timer.h18
50 files changed, 19968 insertions, 0 deletions
diff --git a/src/AGL_DSp.cpp b/src/AGL_DSp.cpp
new file mode 100644
index 0000000..eace870
--- /dev/null
+++ b/src/AGL_DSp.cpp
@@ -0,0 +1,242 @@
+/**> HEADER FILES <**/
+#include "AGL_DSp.h"
+#include "Alerts.h"
+
+
+/**> GLOBAL VARIABLES <**/
+DSpContextAttributes	gDSpContextAttributes;	// Global DrawSprocket context attributes
+DSpContextReference		gDSpContext;			// The global DrawSprocket context
+AGLContext				gOpenGLContext;			// The global OpenGL (AGL) context
+
+
+/********************> ToolboxInit() <*****/
+void		ToolboxInit( void )
+{
+	
+	MaxApplZone();
+	
+	InitGraf( &qd.thePort );
+	InitFonts();
+	InitWindows();
+	InitMenus();
+	TEInit();
+	InitDialogs( 0L );
+	InitCursor();
+	
+}
+
+/********************> HasAppearance() <*****/
+Boolean 	HasAppearance( void )
+{
+	
+	OSErr    error;
+	SInt32   response;
+	Boolean  appearancePresent    = false;
+	Boolean  appearance101present = false;
+	Boolean  appearance110present = false;
+	Boolean  inCompatibilityMode  = false;
+	
+	error = Gestalt( gestaltAppearanceAttr, &response );
+	
+	// If Gestalt returns no error and the bit in response represented by the constant
+	// gestaltAppearanceExists is set, proceed, otherwise exit with an error message.
+	
+	if ( error == noErr && ( BitTst( &response, 31 - gestaltAppearanceExists ) ) )
+	{
+		// At least Version 1.0 is present.  Set a flag.
+		appearancePresent = true;
+		
+		// If the bit in response represented by the constant gestaltAppearanceCompatMode
+		// is set, system-wide Appearance is off.  The result of this check will be
+		// relevant only where Versions 1.0 through 1.0.3 are present.
+		if( BitTst( &response, 31 - gestaltAppearanceCompatMode ) )
+			inCompatibilityMode = true;
+		
+		// Call Gestalt again with the gestaltAppearanceVersion selector.
+		Gestalt( gestaltAppearanceVersion, &response );
+		
+		// If the low order word in response is 0x0101, Version 1.0.1, 1.0.2, or 1.0.3 is
+		// present. If the low order word in response is 0x0110, Version 1.1 is available.
+		if( response == 0x00000101 )
+			appearance101present = true;
+		else if( response == 0x00000110 )
+			appearance110present = true;
+	}
+	/*else
+	{
+		StopAlert( kNoAppearanceAlert, nil );
+		ExitToShell();
+	}*/
+	
+	// Register this app as an Appearance Client
+	//RegisterAppearanceClient();
+	
+	return appearancePresent;
+	
+}
+
+/********************> SetupScreen() <*****/
+CGrafPtr	SetupScreen( int width, int height )
+{
+	
+	OSStatus theError;
+	CGrafPtr theFrontBuffer;
+	
+	// Start DrawSprocket
+	theError = DSpStartup();
+	if( theError )
+		FatalErrorAlert( kErr_DSpStartupFailed, theError );
+	
+	// Set the Context Attributes
+	gDSpContextAttributes.displayWidth = width;
+	gDSpContextAttributes.displayHeight = height;
+	gDSpContextAttributes.colorNeeds = kDSpColorNeeds_Require;
+	gDSpContextAttributes.displayDepthMask = kDSpDepthMask_32;
+	gDSpContextAttributes.backBufferDepthMask = kDSpDepthMask_32;
+	gDSpContextAttributes.displayBestDepth = 32;
+	gDSpContextAttributes.backBufferBestDepth = 32;
+	gDSpContextAttributes.pageCount = 1;
+	
+	// Find the best context for our attributes
+	theError = DSpFindBestContext( &gDSpContextAttributes, &gDSpContext );
+	if( theError != noErr )
+		FatalErrorAlert( kErr_DSpFindBestContextFailed, theError ); // This function is in my Alerts.cpp
+	
+	// Reserve that context
+	theError = DSpContext_Reserve( gDSpContext, &gDSpContextAttributes );
+	if( theError != noErr )
+		FatalErrorAlert( kErr_DSpContext_ReserveFailed, theError );
+	
+	// Fade out
+	theError = DSpContext_FadeGammaOut( NULL, NULL );	
+	if( theError != noErr )
+		FatalErrorAlert( kErr_DSpFadeFailed, theError );
+	
+	// Activate the context
+	theError = DSpContext_SetState( gDSpContext, kDSpContextState_Active );
+	if( theError != noErr )
+	{
+		// Fade back in the display before dying
+		theError = DSpContext_FadeGammaIn( NULL, NULL );
+		
+		// Now do the fatal error alert
+		FatalErrorAlert( kErr_ActivateContextFailed, theError );
+	}
+	
+	// Fade in
+	theError = DSpContext_FadeGammaIn( NULL, NULL );
+	if( theError != noErr )
+		FatalErrorAlert( kErr_DSpFadeFailed, theError );
+		
+	// Create a window to draw in
+	CreateWindow( theFrontBuffer, width, height );
+	
+	return theFrontBuffer;
+	
+}
+
+/********************> CreateWindow() <*****/
+void		CreateWindow( CGrafPtr &theFrontBuffer, int width, int height )
+{
+	
+	Rect			rect;
+	AuxWinHandle	awh;
+	CTabHandle		theColorTable;
+	OSErr			error;
+	RGBColor 		backColor = { 0xFFFF, 0xFFFF, 0xFFFF };
+	RGBColor 		foreColor = { 0x0000, 0x0000, 0x0000 };
+	
+	// Set the window rect
+	rect.top = rect.left = 0;
+	DSpContext_LocalToGlobal( gDSpContext, ( Point* )&rect );
+	rect.right = rect.left + width;
+	rect.bottom = rect.top + height;
+	
+	// Create a new color window
+	theFrontBuffer = ( CGrafPtr )NewCWindow( NULL, &rect, "\p", 0, plainDBox, kMoveToFront, 0, 0 );
+	
+	// set the content color of the window to black to avoid a white flash when the window appears.		
+	if ( GetAuxWin( ( WindowPtr )theFrontBuffer, &awh ) )
+	{
+		theColorTable = ( **awh ).awCTable;
+		error = HandToHand( ( Handle* )&theColorTable );
+		if ( error )
+			DebugStr( "\pOut of memory!" );
+			
+		( **theColorTable ).ctTable[wContentColor].rgb.red = 0;
+		( **theColorTable ).ctTable[wContentColor].rgb.green = 0;
+		( **theColorTable ).ctTable[wContentColor].rgb.blue = 0;
+		
+		CTabChanged( theColorTable );
+		
+		// the color table will be disposed by the window manager when the window is disposed
+		SetWinColor( ( WindowPtr )theFrontBuffer, ( WCTabHandle )theColorTable );
+	}
+	
+	// Show the window
+	ShowWindow( ( GrafPtr )theFrontBuffer );
+	SetPort( ( GrafPtr )theFrontBuffer );
+	
+	// Set current pen colors
+	RGBForeColor( &foreColor );
+	RGBBackColor( &backColor );
+	
+}
+
+/********************> ShutdownScreen() <*****/
+void		ShutdownScreen( CGrafPtr theFrontBuffer )
+{
+	
+	DSpContext_FadeGammaOut( NULL, NULL );
+	DisposeWindow( ( WindowPtr )theFrontBuffer );
+	DSpContext_SetState( gDSpContext, kDSpContextState_Inactive );
+	DSpContext_FadeGammaIn( NULL, NULL );
+	DSpContext_Release( gDSpContext );
+	DSpShutdown();
+	
+}
+
+/********************> SetupAGL() <*****/
+AGLContext	SetupAGL( AGLDrawable window )
+{
+	GLint          attrib[] = { AGL_RGBA, AGL_DEPTH_SIZE, 24, AGL_DOUBLEBUFFER, AGL_NONE };
+	AGLPixelFormat format;
+	AGLContext     context;
+	GLboolean      ok;
+
+	// Choose an rgb pixel format
+	format = aglChoosePixelFormat( NULL, 0, attrib );
+	if ( format == NULL )
+		return NULL;
+
+	// Create an AGL context
+	context = aglCreateContext( format, NULL );
+	if ( context == NULL )
+		return NULL;
+
+	// Attach the window to the context
+	ok = aglSetDrawable( context, window );
+	if ( !ok )
+		return NULL;
+	
+	// Make the context the current context
+	ok = aglSetCurrentContext( context );
+	if ( !ok )
+		return NULL;
+
+	// The pixel format is no longer needed so get rid of it
+	aglDestroyPixelFormat( format );
+
+	return context;
+	
+}
+
+/********************> CleanupAGL() <*****/
+void		CleanupAGL( AGLContext context )
+{
+	
+	aglSetCurrentContext( NULL );
+	aglSetDrawable( context, NULL );
+	aglDestroyContext( context );
+	
+}
diff --git a/src/AGL_DSp.h b/src/AGL_DSp.h
new file mode 100644
index 0000000..4c1d531
--- /dev/null
+++ b/src/AGL_DSp.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#ifndef _AGL_DSP_H_
+#define _AGL_DSP_H_
+
+
+/**> HEADER FILES <**/
+#include <stdlib.h>			// ANSI C cross platform headers
+#include <stdio.h>
+#include <DrawSprocket.h>	// DrawSprocket
+#include <agl.h>			// Apple's OpenGL
+#include <glu.h>			// Used for setting perspective and making objects
+#include <tk.h>				// Used for loading images
+
+
+/**> CONSTANT DECLARATIONS <**/
+#define	kMoveToFront		kFirstWindowOfClass
+
+// Screen Dimensions
+#define SCREEN_WIDTH		640
+#define SCREEN_HEIGHT		480
+
+
+/**> GLOBAL VARIABLES <**/
+extern DSpContextAttributes		gDSpContextAttributes;	// Global DrawSprocket context attributes
+extern DSpContextReference		gDSpContext;			// The global DrawSprocket context
+extern AGLContext				gOpenGLContext;			// The global OpenGL (AGL) context
+														// Note: These are actually defined in AGL_DSp.cpp
+
+
+/**> FUNCTION PROTOTYPES <**/
+void		ToolboxInit( void );
+Boolean 	HasAppearance( void );
+CGrafPtr	SetupScreen( int width, int height );
+void		CreateWindow( CGrafPtr &theFrontBuffer, int width, int height );
+void		ShutdownScreen( CGrafPtr theFrontBuffer );
+AGLContext	SetupAGL( AGLDrawable window );
+void		CleanupAGL( AGLContext context );
+
+
+#endif
\ No newline at end of file
diff --git a/src/Alerts.cpp b/src/Alerts.cpp
new file mode 100644
index 0000000..acfefae
--- /dev/null
+++ b/src/Alerts.cpp
@@ -0,0 +1,93 @@
+/**> HEADER FILES <**/
+#include "Alerts.h"
+
+
+/********************> SelectResolution() <*****/
+int		SelectResolution( void )
+{
+	
+	DialogPtr	dialog;
+	Boolean		dialogDone = false;
+	short		itemHit, itemType;
+	Handle		okItem;
+	Handle		resolutionItem;
+	Rect		itemRect;
+	int			selectionNum;
+	
+	// Load the dialog
+	dialog = GetNewDialog( kResID_DLOG_SelectResolution, nil, kMoveToFront );
+	
+	// Display the dialog
+	ShowWindow( dialog );
+	SetPort( dialog );
+	
+	// Load dialog items
+	SetDialogDefaultItem( dialog, iOK );
+	SetDialogTracksCursor( dialog, true );
+	GetDialogItem( dialog, iOK, &itemType, &okItem, &itemRect );
+	GetDialogItem( dialog, iResolutionPopUp, &itemType, &resolutionItem, &itemRect );
+	
+	// Set item values
+	SetControlValue( ( ControlHandle )resolutionItem, i640x480 );
+	
+	
+	while ( !dialogDone )
+	{
+		
+		ModalDialog( nil, &itemHit );
+		
+		switch( itemHit )
+		{
+			case iOK:
+				dialogDone = true;
+				// Get the item number selected int the popup
+				selectionNum = GetControlValue( ( ControlHandle )resolutionItem );
+				break;
+			case iResolutionPopUp:
+				// We don't actually need to do anything here
+				break;
+		}
+		
+	}
+	
+	DisposeDialog( dialog );
+
+	// Return the item selected in the popup menu
+	return selectionNum;
+}
+
+/********************> MessageAlert() <*****/
+void	MessageAlert( unsigned char *theMessage )
+{
+	
+	// Set parameter ^0 to our message (I could set up to three, but for simplicity's sake I won't)
+	ParamText( ( unsigned char * )theMessage, NULL, NULL, NULL );
+	
+	// Do the Alert
+	NoteAlert( kResID_ALRT_MessageAlert, nil );
+	
+}
+
+/********************> FatalErrorAlert() <*****/
+void	FatalErrorAlert( UInt16 errorNum, OSErr osError )
+{
+	
+	Str15				errNumStr;
+	Str255				mainMessage;
+	
+	// Convert the OSErr to a string
+	NumToString( osError, errNumStr );
+	
+	// Get the error description (inErrorDesc) from the STR# resource
+	GetIndString( mainMessage, kResID_STRn_ErrorStrings, errorNum );
+	
+	// Set the parameters (^0 and ^1) in the ALRT to our error messages
+	ParamText( mainMessage, errNumStr, NULL, NULL );
+	
+	// Do the alert (which now has our messages in it)
+	StopAlert( kResID_ALRT_ErrorAlert, NULL );
+	
+	// Quit
+	exit( EXIT_SUCCESS );
+	
+}
diff --git a/src/Alerts.h b/src/Alerts.h
new file mode 100644
index 0000000..5db7938
--- /dev/null
+++ b/src/Alerts.h
@@ -0,0 +1,44 @@
+#ifndef _MYALERTS_H_
+#define _MYALERTS_H_
+
+
+/**> HEADER FILES <**/
+#include <string.h>
+#include <stdlib.h>
+
+
+/**> CONSTANT DECLARATIONS <**/
+#define	kMoveToFront		kFirstWindowOfClass
+// Alerts
+#define	kResID_ALRT_MessageAlert		128
+#define	kResID_ALRT_ErrorAlert			129
+// Dialogs
+#define	kResID_DLOG_SelectResolution	130
+#define	iOK								1
+#define	iResolutionPopUp				2
+// Menus
+#define	mResolution						128
+#define	i640x480						1
+#define	i800x600						2
+#define	i1024x768						3
+// String resources
+#define	kResID_STRn_ErrorStrings		128
+// Misc
+#define kInsignificantConstant7454955	0
+
+// Error numbers	
+#define	kErr_DSpFindBestContextFailed	1
+#define	kErr_DSpContext_ReserveFailed	2
+#define	kErr_ActivateContextFailed		3
+#define	kErr_DSpStartupFailed			4
+#define	kErr_DSpFadeFailed				5
+#define	kErr_AGLContext_CreationFailed	6
+
+
+/**> FUNCTION PROTOTYPES <**/
+int		SelectResolution( void );
+void	MessageAlert( unsigned char *theMessage );
+void	FatalErrorAlert( UInt16 errorNum, OSErr osError );
+
+
+#endif
\ No newline at end of file
diff --git a/src/Camera.cpp b/src/Camera.cpp
new file mode 100644
index 0000000..950c12d
--- /dev/null
+++ b/src/Camera.cpp
@@ -0,0 +1,9 @@
+/**> HEADER FILES <**/
+#include "Camera.h"
+
+
+void Camera::Apply()
+{
+	glTranslatef(-position.x,-position.y,-position.z);
+}
+
diff --git a/src/Camera.h b/src/Camera.h
new file mode 100644
index 0000000..a31055f
--- /dev/null
+++ b/src/Camera.h
@@ -0,0 +1,29 @@
+#ifndef _CAMERA_H_
+#define _CAMERA_H_
+
+
+/**> HEADER FILES <**/
+#ifdef OS9 
+#include <gl.h>
+#else
+#include <GL/gl.h>
+#endif
+
+#include "Quaternions.h"
+
+class Camera
+{
+	public:
+		XYZ position;
+		XYZ oldposition;
+		XYZ targetoffset;
+		
+	 	float rotation, rotation2;
+	 	float oldrotation, oldrotation2;
+	 	float oldoldrotation, oldoldrotation2;
+	 	float visrotation,  visrotation2;
+		void Apply();
+};
+
+#endif
+
diff --git a/src/Constants.h b/src/Constants.h
new file mode 100644
index 0000000..76c67de
--- /dev/null
+++ b/src/Constants.h
@@ -0,0 +1,136 @@
+#ifndef _CONSTANTS_H_
+#define _CONSTANTS_H_
+
+#define max_joints 50
+#define max_frames 50
+#define max_muscles 100
+#define gravity -25
+
+#define bullethole 0
+#define crater 1
+#define bloodpool 2
+
+#define idleanim 0
+#define joganim 1
+#define pistolaimanim 2
+#define walkanim 3
+#define rifleholdanim 4
+#define rifleaimanim 5
+#define assaultrifleaimanim 6
+#define crouchanim 7
+#define headpainanim 8
+#define chestpainanim 9
+#define stomachpainanim 10
+#define rightarmpainanim 11
+#define leftarmpainanim 12
+#define rightlegpainanim 13
+#define leftlegpainanim 14
+#define riflehitanim 15
+#define grenadeaimanim 16
+#define grenadechargeanim 17
+#define grenadethrowanim 18
+#define zombieeatanim 19
+#define zombiejoganim 20
+#define zombiewalkanim 21
+#define getupfrontanim 22
+#define getupbackanim 23
+#define lyinganim 24
+#define diveanim 25
+#define throwanim 26
+#define thrownanim 27
+
+#define nogun 0
+#define sniperrifle 1
+#define assaultrifle 2
+#define handgun1 3
+#define handgun2 4
+#define grenade 5
+#define knife 6
+#define shotgun 7
+
+#define sniperriflemodel 0
+#define assaultriflemodel 1
+#define handgunbasemodel 2
+#define handgunslidemodel 3
+#define handgun2basemodel 4
+#define handgun2slidemodel 5
+#define grenadebasemodel 6
+#define grenadepinmodel 7
+#define grenadespoonmodel 8
+#define knifemodel 9
+#define shotgunmodel 10
+
+#define visionsound 0
+#define soulinsound 1
+#define souloutsound 2
+#define footstepsound 3
+#define bodylandsound 8
+#define headlandsound 9
+#define riflesound 10
+#define bodyhitsound 11
+#define wallhitsound 12
+#define machinegunsound 13
+#define nearbulletsound 14
+#define headwhacksound 15
+#define headshotsound 16
+#define reloadsound 17
+#define clicksound 18
+#define pistol1sound 19
+#define pistol2sound 20
+#define pinpullsound 21
+#define pinreplacesound 22
+#define grenadethrowsound 23
+#define bouncesound 24
+#define bounce2sound 25
+#define explosionsound 26
+#define bodywhacksound 27
+#define rainsound 28
+#define losesound 29
+#define disguisekillsound 30
+#define knifeslashsound 31
+#define shotgunsound 32
+#define mainmenusong 33
+#define shootsong 34
+#define knifesong 35
+#define zombiesong 36
+
+#define sunny_environment 0
+#define foggy_environment 1
+#define snowy_environment 2
+#define rainy_environment 3
+#define firey_environment 4
+#define night_environment 5
+
+#define randomshoot_type 0
+#define zombie_type 1
+#define soldiers_type 2
+#define snipers_type 3
+#define stabber_type 4
+
+#define shotdelayamount 3
+
+#define fleshtone1 240/255
+#define fleshtone2 183/255
+#define fleshtone3 132/255
+
+#define headmodel 0
+#define chestmodel 1
+#define abdomenmodel 2
+#define upperarmmodel 3
+#define lowerarmmodel 4
+#define handmodel 5
+#define upperlegmodel 6
+#define lowerlegmodel 7
+#define footmodel 8
+
+#define policecostume 0
+#define bodyguardcostume 1
+#define casualcostumes 2
+#define vipcostume 6
+
+#define numcasual 4
+
+#define soundscalefactordefault 10
+
+#endif
+
diff --git a/src/Decals.cpp b/src/Decals.cpp
new file mode 100644
index 0000000..3cebb4c
--- /dev/null
+++ b/src/Decals.cpp
@@ -0,0 +1,375 @@
+#include "Decals.h"
+#include "Textures.h"
+
+extern double multiplier;
+extern bool slomo;
+extern Fog fog;
+extern bool blood;
+extern float fogcolorr;
+extern float fogcolorg;
+extern float fogcolorb;
+//Functions
+extern float sinefluct;
+extern int environment;
+extern Model gunmodels[10];
+extern Camera camera;
+extern float precipitationhorz;
+extern float precipitationvert;
+extern float precipitationdensity;
+extern float snowdelay;
+
+int Decals::MakeDecal(int atype, XYZ location, float size, XYZ normal, int poly, Model *model, XYZ move, float rotation){
+	int major=0;
+	float normalv[3];
+	XYZ right;
+	XYZ up;
+	XYZ nothing;
+	XYZ axis[3];
+	XYZ temp;
+	
+	nothing=0;
+	
+	axis[0].x=1;
+	axis[1].y=1;
+	axis[2].z=1;
+	
+	normalv[0]=abs(normal.x);
+	normalv[1]=abs(normal.y);
+	normalv[2]=abs(normal.z);
+	
+	
+	if(normalv[1]>normalv[major])major=1;
+	if(normalv[2]>normalv[major])major=2;
+	
+	if (normalv[0] == 1 || normalv[1] == 1 || normalv[2] == 1)
+	{
+	if ((major == 0 && normal.x > 0) || major == 1){
+		right=0;
+		right.z=-1;}
+	else if (major == 0){
+		right=0;
+		right.z=1;}
+    else {
+        right=0;
+		right.x=normal.z;}
+   	}
+   	else
+    	CrossProduct(axis[major], normal, &right);
+   
+    CrossProduct(normal, right, &up);
+    Normalise(&up); 
+    Normalise(&right);
+	
+	float count;
+	float count2;
+	float countinc=1/size;
+	if(countinc<.01)countinc=.01;
+	if(countinc>.2)countinc=.2;
+	float normaloffset=.02;
+	int good;
+	
+	numpoints[howmanydecals]=0;
+    points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing - right - up) * (size/3) /*+ normal/100*/;
+    texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = 0;
+    texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = 0;
+    if((move.x==0&&move.z==0&&rotation==0)||
+    LineFacetd(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25, model->vertex[model->Triangles[poly].vertex[0]], model->vertex[model->Triangles[poly].vertex[1]], model->vertex[model->Triangles[poly].vertex[2]],normal,&temp)
+    )numpoints[howmanydecals]++;
+    else {
+    	good=-1;
+    	count=1-countinc;
+    	while(good==-1&&count>-1){
+    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = 0;
+    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = .5-count/2;
+    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing - right - up*count) * (size/3);
+    		count-=countinc;
+    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
+    	}
+    	if(good!=-1)numpoints[howmanydecals]++;
+    	good=-1;
+    	count=1-countinc;
+    	while(good==-1&&count>-1){
+    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = .5-count/2;
+    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = 0;
+    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing - right*count - up) * (size/3);
+    		count-=countinc;
+    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
+    	}
+    	if(good!=-1)numpoints[howmanydecals]++;
+    	if(good==-1){
+    		good=-1;
+	    	count2=1-countinc;
+	    	while(good==-1&&count2>-1){
+	    		count=1-countinc;
+		    	while(good==-1&&count>-1){
+		    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = .5-count2/2;
+		    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = .5-count/2;
+		    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing - right*count2 - up*count) * (size/3);
+		    		count-=countinc;
+		    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
+		    	}
+		    	count2-=countinc;
+		    }
+	    	if(good!=-1)numpoints[howmanydecals]++;
+    	}
+    }
+    
+    points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing + right - up) * (size/3) /*+ normal/100*/;
+    texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = 1;
+    texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = 0;
+    if((move.x==0&&move.y==0&&move.z==0&&rotation==0)||
+    LineFacetd(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25, model->vertex[model->Triangles[poly].vertex[0]], model->vertex[model->Triangles[poly].vertex[1]], model->vertex[model->Triangles[poly].vertex[2]],normal,&temp)
+    )numpoints[howmanydecals]++;
+    else {
+    	good=-1;
+    	count=1-countinc;
+    	while(good==-1&&count>-1){
+    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = .5+count/2;
+    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = 0;
+    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing + right*count - up) * (size/3);
+    		count-=countinc;
+    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
+    	}
+    	if(good!=-1)numpoints[howmanydecals]++;
+    	good=-1;
+    	count=1-countinc;
+    	while(good==-1&&count>-1){
+    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = 1;
+    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = .5-count/2;
+    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing + right - up*count) * (size/3);
+    		count-=countinc;
+    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
+    	}
+    	if(good!=-1)numpoints[howmanydecals]++;
+    	if(good==-1){
+    		good=-1;
+	    	count2=1-countinc;
+	    	while(good==-1&&count2>-1){
+	    		count=1-countinc;
+		    	while(good==-1&&count>-1){
+		    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = .5+count2/2;
+		    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = .5-count/2;
+		    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing + right*count2 - up*count) * (size/3);
+		    		count-=countinc;
+		    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
+		    	}
+		    	count2-=countinc;
+		    }
+	    	if(good!=-1)numpoints[howmanydecals]++;
+    	}
+    }
+    
+    points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing + right + up) * (size/3) /*+ normal/100*/;
+    texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = 1;
+    texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = 1;
+    if((move.x==0&&move.y==0&&move.z==0&&rotation==0)||
+    LineFacetd(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25, model->vertex[model->Triangles[poly].vertex[0]], model->vertex[model->Triangles[poly].vertex[1]], model->vertex[model->Triangles[poly].vertex[2]],normal,&temp)
+    )numpoints[howmanydecals]++;
+    else {
+    	good=-1;
+    	count=1-countinc;
+    	while(good==-1&&count>-1){
+    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = 1;
+    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = .5+count/2;
+    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing + right + up*count) * (size/3);
+    		count-=countinc;
+    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
+    	}
+    	if(good!=-1)numpoints[howmanydecals]++;
+    	good=-1;
+    	count=1-countinc;
+    	while(good==-1&&count>-1){
+    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = .5+count/2;
+    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = 1;
+    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing + right*count + up) * (size/3);
+    		count-=countinc;
+    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
+    	}
+    	if(good!=-1)numpoints[howmanydecals]++;
+    	if(good==-1){
+    		good=-1;
+	    	count2=1-countinc;
+	    	while(good==-1&&count2>-1){
+	    		count=1-countinc;
+		    	while(good==-1&&count>-1){
+		    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = .5+count2/2;
+		    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = .5+count/2;
+		    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing + right*count2 + up*count) * (size/3);
+		    		count-=countinc;
+		    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
+		    	}
+		    	count2-=countinc;
+		    }
+	    	if(good!=-1)numpoints[howmanydecals]++;
+    	}
+    }
+    
+    points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing - right + up) * (size/3) /*+ normal/100*/;
+	texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = 0;
+    texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = 1;
+    if((move.x==0&&move.y==0&&move.z==0&&rotation==0)||
+    LineFacetd(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25, model->vertex[model->Triangles[poly].vertex[0]], model->vertex[model->Triangles[poly].vertex[1]], model->vertex[model->Triangles[poly].vertex[2]],normal,&temp)
+    )numpoints[howmanydecals]++;
+    else {
+    	good=-1;
+    	count=1-countinc;
+    	while(good==-1&&count>-1){
+    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = .5-count/2;
+    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = 1;
+    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing - right*count + up) * (size/3);
+    		count-=countinc;
+    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
+    	}
+    	if(good!=-1)numpoints[howmanydecals]++;
+    	good=-1;
+    	count=1-countinc;
+    	while(good==-1&&count>-1){
+    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = 0;
+    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = .5+count/2;
+    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing - right + up*count) * (size/3);
+    		count-=countinc;
+    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
+    	}
+    	if(good!=-1)numpoints[howmanydecals]++;
+    	if(good==-1){
+    		good=-1;
+	    	count2=1-countinc;
+	    	while(good==-1&&count2>-1){
+	    		count=1-countinc;
+		    	while(good==-1&&count>-1){
+		    		texcoordsx[howmanydecals*8+numpoints[howmanydecals]] = .5-count2/2;
+		    		texcoordsy[howmanydecals*8+numpoints[howmanydecals]] = .5+count/2;
+		    		points[howmanydecals*8+numpoints[howmanydecals]] = location + (nothing - right*count2 + up*count) * (size/3);
+		    		count-=countinc;
+		    		good=model->LineCheck2(points[howmanydecals*8+numpoints[howmanydecals]]+normal/25,points[howmanydecals*8+numpoints[howmanydecals]]-normal/25,&temp,move,rotation);
+		    	}
+		    	count2-=countinc;
+		    }
+	    	if(good!=-1)numpoints[howmanydecals]++;
+    	}
+    }
+    for(int i=0;i<numpoints[howmanydecals];i++){
+    	 points[howmanydecals*8+i] += normal*normaloffset;
+    }
+    
+    type[howmanydecals]=atype;
+	alivetime[howmanydecals]=0;
+	if(howmanydecals<maxdecals){howmanydecals++;}
+
+	return 0;
+}
+
+int Decals::DeleteDecal(int which){
+	if(which>=0){
+		numpoints[which]=numpoints[howmanydecals-1];
+		alivetime[which]=alivetime[howmanydecals-1];
+		type[which]=type[howmanydecals-1];
+		for(int i=0;i<numpoints[which];i++){
+			points[which*8+i] = points[howmanydecals*8-8+i];
+		    texcoordsx[which*8+i] = texcoordsx[howmanydecals*8-8+i];
+		    texcoordsy[which*8+i] = texcoordsy[howmanydecals*8-8+i];
+	    }
+		if(howmanydecals>0){howmanydecals--;}
+	}
+	
+	return 0;
+}
+
+void Decals::LoadBulletHoleTexture(char *fileName)
+{
+	bulletholetextureptr = loadTexture(fileName);
+}
+
+void Decals::LoadBloodTexture(char *fileName, int which)
+{
+	bloodtextureptr[which] = loadTexture(fileName);
+}
+
+void Decals::LoadCraterTexture(char *fileName)
+{
+	cratertextureptr = loadTexture(fileName);
+}
+
+void Decals::DoStuff()
+{
+	for(int i=0;i<howmanydecals;i++){
+		alivetime[i]+=multiplier;
+		if(alivetime[i]>10&&(type[i]==bullethole||type[i]==crater))DeleteDecal(i);
+		if(alivetime[i]>20&&(type[i]==bloodpool))DeleteDecal(i);
+	}
+}
+
+void Decals::draw()
+{
+	glAlphaFunc(GL_GREATER, 0.01);
+	
+	float bloodpoolspeed=1;
+	
+	glDepthFunc(GL_LEQUAL);
+	glEnable(GL_BLEND);
+	glEnable(GL_CULL_FACE);
+	glEnable(GL_TEXTURE_2D);
+	glEnable(GL_LIGHTING);
+	glDepthMask(0);
+	glAlphaFunc(GL_GREATER, 0.01);
+	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
+	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
+	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+	glEnable(GL_POLYGON_OFFSET_FILL);
+	for(int i=0;i<howmanydecals;i++){
+		if(type[i]==bullethole)glBindTexture(GL_TEXTURE_2D, bulletholetextureptr);
+		if(type[i]==crater)glBindTexture(GL_TEXTURE_2D, cratertextureptr);
+		if(type[i]!=bloodpool)glColor4f(1,1,1,10-alivetime[i]);
+		
+		if(type[i]==bloodpool&&alivetime[i]<bloodpoolspeed*.2)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[0]);
+		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*.2&&alivetime[i]<bloodpoolspeed*.4)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[1]);
+		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*.4&&alivetime[i]<bloodpoolspeed*.6)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[2]);
+		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*.6&&alivetime[i]<bloodpoolspeed*.8)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[3]);
+		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*.8&&alivetime[i]<bloodpoolspeed*1)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[4]);
+		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*1&&alivetime[i]<bloodpoolspeed*1.2)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[5]);
+		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*1.2&&alivetime[i]<bloodpoolspeed*1.4)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[6]);
+		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*1.4&&alivetime[i]<bloodpoolspeed*1.6)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[7]);
+		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*1.6&&alivetime[i]<bloodpoolspeed*1.8)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[8]);
+		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*1.8&&alivetime[i]<bloodpoolspeed*2.0)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[9]);
+		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*2.0)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[10]);
+		if(type[i]==bloodpool&&alivetime[i]<bloodpoolspeed*2.0)glColor4f(1,1,1,1.5-(alivetime[i]*5/bloodpoolspeed-(int)(alivetime[i]*5/bloodpoolspeed)));
+		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*2.0)glColor4f(1,1,1,20-alivetime[i]);
+		
+		glPushMatrix();
+		glBegin(GL_TRIANGLE_FAN);
+			for(int j=0;j<numpoints[i];j++){
+			 glTexCoord2f(texcoordsx[i*8+j], texcoordsy[i*8+j]); glVertex3f(points[i*8+j].x,points[i*8+j].y,points[i*8+j].z);
+			}
+		glEnd();
+		glPopMatrix();
+		
+		if(type[i]==bloodpool&&alivetime[i]<bloodpoolspeed*2.0){
+			if(type[i]==bloodpool&&alivetime[i]<bloodpoolspeed*.2)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[1]);
+		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*.2&&alivetime[i]<bloodpoolspeed*.4)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[2]);
+		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*.4&&alivetime[i]<bloodpoolspeed*.6)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[3]);
+		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*.6&&alivetime[i]<bloodpoolspeed*.8)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[4]);
+		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*.8&&alivetime[i]<bloodpoolspeed*1)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[5]);
+		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*1&&alivetime[i]<bloodpoolspeed*1.2)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[6]);
+		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*1.2&&alivetime[i]<bloodpoolspeed*1.4)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[7]);
+		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*1.4&&alivetime[i]<bloodpoolspeed*1.6)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[8]);
+		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*1.6&&alivetime[i]<bloodpoolspeed*1.8)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[9]);
+		if(type[i]==bloodpool&&alivetime[i]>=bloodpoolspeed*1.8&&alivetime[i]<bloodpoolspeed*2.0)glBindTexture(GL_TEXTURE_2D, bloodtextureptr[10]);
+		if(type[i]==bloodpool)glColor4f(1,1,1,alivetime[i]*5/bloodpoolspeed-(int)(alivetime[i]*5/bloodpoolspeed));
+			
+			glPushMatrix();
+			glBegin(GL_TRIANGLE_FAN);
+				for(int j=0;j<numpoints[i];j++){
+				 glTexCoord2f(texcoordsx[i*8+j], texcoordsy[i*8+j]); glVertex3f(points[i*8+j].x,points[i*8+j].y,points[i*8+j].z);
+				}
+			glEnd();
+			glPopMatrix();
+		}
+	}
+	glDepthMask(1);
+	glDisable(GL_TEXTURE_2D);
+	glColor4f(1,1,1,1);
+	glEnable(GL_CULL_FACE);
+	glDisable(GL_POLYGON_OFFSET_FILL);
+	glDepthFunc(GL_LEQUAL);
+}
+
diff --git a/src/Decals.h b/src/Decals.h
new file mode 100644
index 0000000..127a6d2
--- /dev/null
+++ b/src/Decals.h
@@ -0,0 +1,59 @@
+#ifndef _DECALS_H_
+#define _DECALS_H_
+
+#include "Quaternions.h"
+#ifdef OS9 
+#include <gl.h>
+#include <glu.h>
+#include "glut.h"
+#else
+///ZWARNING
+///#include <GL/glut.h>
+///GLUT REMOVED.
+#endif
+#include "Files.h"
+#include "Quaternions.h"
+#include "Camera.h"
+#include "Models.h"
+#include "Fog.h"
+//
+// Model Structures
+//
+
+#define maxdecals 120
+
+class Decals{
+	public:
+				GLuint 				bulletholetextureptr;
+				GLuint 				cratertextureptr;
+				GLuint 				bloodtextureptr[11];
+				
+				int howmanydecals;
+				
+				int type[maxdecals];
+				
+				XYZ points[8*maxdecals];
+				int numpoints[maxdecals];
+				float texcoordsx[8*maxdecals];
+				float texcoordsy[8*maxdecals];
+				float alivetime[maxdecals];
+				
+				void draw();
+				
+				int DeleteDecal(int which);
+				int MakeDecal(int atype, XYZ location, float size, XYZ normal, int poly, Model *model, XYZ move, float rotation);
+				
+				void DoStuff();
+				void LoadBulletHoleTexture(char *fileName);
+				void LoadCraterTexture(char *fileName);
+				void LoadBloodTexture(char *fileName, int which);
+				
+				~Decals() {
+					glDeleteTextures( 1, (const GLuint *)bulletholetextureptr );
+					glDeleteTextures( 1, (const GLuint *)cratertextureptr );
+					glDeleteTextures( 11, (const GLuint *)bloodtextureptr );
+				};
+};
+
+#endif
+
diff --git a/src/Files.cpp b/src/Files.cpp
new file mode 100644
index 0000000..dd55c52
--- /dev/null
+++ b/src/Files.cpp
@@ -0,0 +1,173 @@
+#include "Files.h"
+
+short Files::OpenFile(Str255 Name)
+{
+	short volume;
+	char filename[33];
+	short tFile;
+	tFile=-1;
+  Point      ptOrigin = { 0, 0 };
+  volume = 0;
+  sprintf (filename, "%s", Name);
+  SetVol( nil, volume );
+  CtoPstr( filename );
+  FSOpen( (Pstr) filename, volume,&tFile );
+  PtoCstr( (Pstr) filename );
+  sFile=tFile;
+  return( tFile );
+}
+
+short Files::OpenNewFile( SFReply *psfReply,
+                          OSType  osTypeCreator,
+                          OSType  osTypeType )
+{
+  sFile = 0;
+  OSErr osErr;
+  
+  SetVol( nil, psfReply->vRefNum );
+  osErr = Create( psfReply->fName, psfReply->vRefNum, osTypeCreator, osTypeType );
+    
+  if ( osErr == dupFNErr )
+  {
+    FSDelete( psfReply->fName, psfReply->vRefNum );
+    Create( psfReply->fName, psfReply->vRefNum, osTypeCreator, osTypeType );
+  }
+    
+   FSOpen( psfReply->fName, psfReply->vRefNum, &sFile );
+
+  return( sFile );
+}
+
+
+short Files::PromptForSaveAS( short   sPromptID,
+                              short   sNameID,
+                              Str255  str255NamePrompt,
+                              OSType  osTypeCreator,
+                              OSType  osTypeType,
+                              SFReply *psfReply )
+{
+  Str255  str255Prompt;
+  Str255  str255Name;
+  sFile = 0;
+  Point   ptOrigin = { 0, 0 };
+  
+  GetIndString( str255Prompt, FILE_STRINGS, sPromptID );
+
+  if ( !str255NamePrompt )
+    GetIndString( str255Name, FILE_STRINGS, sNameID );
+
+  else
+    memcpy( str255Name, str255NamePrompt, *str255NamePrompt + 1 );
+    
+  SFPutFile( ptOrigin, str255Prompt, str255Name, nil, psfReply );
+  
+  if ( psfReply->good )
+  {
+    sFile = OpenNewFile( psfReply, osTypeCreator, osTypeType );
+  }
+
+  return( sFile );
+}
+
+short Files::OpenSavedGame(Str255 Name)
+{
+  Point      ptOrigin = { 0, 0 };
+  sSavedGameVolume = 0;
+  sprintf (szSavedGameName, "%s", Name);
+  SetVol( nil, sSavedGameVolume );
+  CtoPstr( szSavedGameName );
+  FSOpen( (Pstr) szSavedGameName, sSavedGameVolume,&sFile );
+  PtoCstr( (Pstr) szSavedGameName );
+  return( sFile );
+}
+
+short Files::OpenFileDialog()
+{
+  Point      ptOrigin = { 0, 0 };
+ sFile = 0;
+  SFReply    sfReply;
+  SFTypeList sfTypeList = { 'DMAP', '\p', '\p', '\p' };
+    SFGetFile( ptOrigin, "\p", nil, 1, sfTypeList, nil, &sfReply );
+    
+    if ( sfReply.good )
+    {
+      PtoCstr( sfReply.fName );
+      strcpy( szSavedGameName, (Cstr) sfReply.fName );
+    }
+
+  if ( sfReply.good )
+  {
+    sSavedGameVolume = sfReply.vRefNum;
+    SetVol( nil, sSavedGameVolume );
+
+    CtoPstr( szSavedGameName );
+    
+   FSOpen( (Pstr) szSavedGameName, sSavedGameVolume,&sFile );
+
+    PtoCstr( (Pstr) szSavedGameName );
+  }
+
+  return( sFile );
+}
+
+void Files::StartSave()
+{
+  int 			x,y;
+  SFReply       sfReply;
+  sFile = 0;
+  long          lSize;
+  long          lLongSize = sizeof( long );
+   
+    CtoPstr( szSavedGameName );
+
+    sFile = PromptForSaveAS( SAVE_GAME_STRING, 0, (Pstr)szSavedGameName,'DAVD', 'DMAP', &sfReply );
+
+    PtoCstr((Pstr) szSavedGameName );
+
+    if ( sFile )
+    {
+      sSavedGameVolume = sfReply.vRefNum;
+      PtoCstr( sfReply.fName );
+      strcpy( szSavedGameName, (Cstr)sfReply.fName );
+    }
+
+  else
+  {
+    sfReply.vRefNum = sSavedGameVolume;
+    strcpy( (Cstr) sfReply.fName,  szSavedGameName );
+    CtoPstr( (Cstr)sfReply.fName );
+
+    sFile = OpenNewFile( &sfReply, 'GLF2', 'SKLT' );
+  }
+ 
+}
+
+void Files::EndSave()
+{
+  int 			x,y;
+  SFReply       sfReply;
+  long          lSize;
+  long          lLongSize = sizeof( long );
+   
+    if ( sFile )
+    FSClose( sFile );
+
+}
+
+void Files::StartLoad()
+{
+  Boolean     bLoaded = false;
+  long        lSize;
+  long        lLongSize = sizeof( long );
+ 
+  int x,y,kl;
+  sFile=OpenFileDialog();
+ 
+}
+
+void Files::EndLoad()
+{
+  
+  if (sFile)
+  FSClose( sFile );
+}
\ No newline at end of file
diff --git a/src/Files.h b/src/Files.h
new file mode 100644
index 0000000..35f4b6e
--- /dev/null
+++ b/src/Files.h
@@ -0,0 +1,113 @@
+#ifndef _FILES_H_
+#define _FILES_H_
+
+#include <stdio.h>
+#include <stdlib.h>			// Header File For Standard functions
+#include <stdio.h>			// Header File For Standard Input/Output
+#include <string.h>
+#include <ctype.h>
+#include <cstdarg>
+#include <cmath>
+#include <iostream>
+#include <fstream>
+#ifdef OS9 
+#include "gl.h"				// Header File For The OpenGL32 Library
+#include "glu.h"			// Header File For The GLu32 Library
+#include "tk.h"				// Header File For The Glaux Library
+#else
+#include <GL/gl.h>
+#include <GL/glu.h>
+#endif
+#ifdef OS9 
+#include <Sound.h>
+#include <Resources.h>
+#include "AGL_DSp.h"		// Header for OpenGL and DrawSprocket Functions
+#include "Alerts.h"			// Header for Dialogs and alerts for this application
+#endif
+#include "MacInput.h"		// Header for Special Mac Input functions
+#ifdef OS9 
+#include "glm.h"
+#include <TextUtils.h>
+#endif
+
+#include "Support.h"
+
+#define FILE_STRINGS              130
+#define Pstr unsigned char *
+#define Cstr char *
+
+#define FILE_ERROR_ALERT          138
+#define OLD_SAVE_VERSION          139
+#define UNREADABLE_SCORES_ALERT   140
+
+#define SAVE_WARNING_ID           132
+#define PB_SAVE                     1
+#define PB_CANCEL                   2
+#define PB_DONT_SAVE                3
+
+#define FILE_ERROR_STRINGS        129
+#define FILE_ERROR_PREFIX           1
+#define FILE_ERROR_SUFFIX           2
+
+#define SAVE_WARNING_STRINGS      132
+
+#define FILE_STRINGS              130
+#define SAVE_GAME_STRING            1
+#define SAVE_SCORES_STRING          2
+#define SCORES_NAME_STRING          3
+#define SAVE_JOURNAL_STRING         4
+#define JOURNAL_NAME_STRING         5
+#define UNTITLED_STRING             6
+#define SAVE_FORM_STRING            7
+#define FORM_NAME_STRING            8
+
+#define REGISTRATION_FORM         136
+
+#define FILE_NAME_SIZE             32
+#define ERROR_LENGTH               80
+
+/**> Files Opening <**/
+class Files
+{
+	public:
+		char          szSavedGameName[FILE_NAME_SIZE + 1];
+		short         sSavedGameVolume;
+#ifdef OS9 
+		SFReply    sfReply;
+		Boolean       bGameSaved;
+#endif
+#ifdef OS9 
+		short sFile;
+#else
+		int sFile;
+#endif
+
+#ifdef OS9 
+		short OpenFile(Str255 Name);
+#else
+		int OpenFile(Str255 Name);
+		Files() : sFile(-1) { } 
+#endif
+
+#ifdef OS9 
+		short PromptForSaveAS( short   sPromptID,
+                              short   sNameID,
+                              Str255  str255NamePrompt,
+                              OSType  osTypeCreator,
+                              OSType  osTypeType,
+                              SFReply *psfReply );
+	        short OpenNewFile( SFReply *psfReply, OSType  osTypeCreator, OSType  osTypeType );
+#endif
+		short OpenSavedGame(Str255 Name);
+		short OpenFileDialog();
+		void LoadNamedMap(Str255 Name);
+		void LoadGame(Str255 Name, int animnum);
+
+		void LoadMap();
+		void StartSave();
+		void EndSave();
+		void StartLoad();
+		void EndLoad();
+};
+	
+#endif
diff --git a/src/Fog.cpp b/src/Fog.cpp
new file mode 100644
index 0000000..21ca229
--- /dev/null
+++ b/src/Fog.cpp
@@ -0,0 +1,54 @@
+/**> HEADER FILES <**/
+#include "Fog.h"
+
+void Fog::SetFog(float colorR, float colorG, float colorB, float fStart, float fEnd, float Density)
+{
+	fogColor[0]=colorR;
+	fogColor[1]=colorG;
+	fogColor[2]=colorB;
+	fogColor[3]=1;
+	fogStart=fStart;
+	fogEnd=fEnd;
+	fogDensity=Density;
+	fogMode=GL_LINEAR;
+
+	glFogi(GL_FOG_MODE,fogMode);
+	glFogfv(GL_FOG_COLOR,fogColor);
+	glFogf(GL_FOG_DENSITY,fogDensity);
+	glFogi(GL_FOG_HINT,GL_DONT_CARE);
+	glFogi(GL_FOG_START,fogStart);
+	glFogi(GL_FOG_END,fogEnd);
+	
+	glEnable(GL_FOG);
+}
+
+void Fog::TempFog(float colorR, float colorG, float colorB)
+{
+	GLfloat tempfogColor[4];
+	tempfogColor[0]=colorR;
+	tempfogColor[1]=colorG;
+	tempfogColor[2]=colorB;
+	tempfogColor[3]=1;
+
+	glFogi(GL_FOG_MODE,fogMode);
+	glFogfv(GL_FOG_COLOR,tempfogColor);
+	glFogf(GL_FOG_DENSITY,fogDensity);
+	glFogi(GL_FOG_HINT,GL_DONT_CARE);
+	glFogi(GL_FOG_START,fogStart);
+	glFogi(GL_FOG_END,fogEnd);
+	
+	glEnable(GL_FOG);
+}
+
+void Fog::ResetFog()
+{
+	glFogi(GL_FOG_MODE,fogMode);
+	glFogfv(GL_FOG_COLOR,fogColor);
+	glFogf(GL_FOG_DENSITY,fogDensity);
+	glFogi(GL_FOG_HINT,GL_DONT_CARE);
+	glFogi(GL_FOG_START,fogStart);
+	glFogi(GL_FOG_END,fogEnd);
+	
+	glEnable(GL_FOG);
+}
+
diff --git a/src/Fog.h b/src/Fog.h
new file mode 100644
index 0000000..a7e0c25
--- /dev/null
+++ b/src/Fog.h
@@ -0,0 +1,28 @@
+#ifndef _FOG_H_
+#define _FOG_H_
+
+
+/**> HEADER FILES <**/
+#ifdef OS9 
+#include <gl.h>
+#else
+#include <GL/gl.h>
+#endif
+#include "Quaternions.h"
+
+
+class Fog{
+	public:
+		GLfloat fogColor[4];
+		GLint fogMode;
+		GLfloat fogDensity;
+		GLfloat fogStart;
+		GLfloat fogEnd;
+		
+		void SetFog(float colorR, float colorG, float colorB, float fStart, float fEnd, float fogDensity);
+		void TempFog(float colorR, float colorG, float colorB);
+		void ResetFog();
+};
+
+#endif
+
diff --git a/src/Frustum.cpp b/src/Frustum.cpp
new file mode 100644
index 0000000..0e617b8
--- /dev/null
+++ b/src/Frustum.cpp
@@ -0,0 +1,246 @@
+#include <cmath>
+#ifdef OS9 
+#include "gl.h"
+#else
+#include <GL/gl.h>
+#endif
+
+#include "Frustum.h"
+
+void FRUSTUM::
+	GetFrustum() {
+	float projmatrix[16];
+	float mvmatrix[16];
+	float clip[16];
+	float t;
+	
+	glGetFloatv(GL_PROJECTION_MATRIX, projmatrix);
+	glGetFloatv(GL_MODELVIEW_MATRIX, mvmatrix);
+	
+	// Combine the matrices
+	clip[0]	= mvmatrix[0] * projmatrix[0] + mvmatrix[1] * projmatrix[4] + mvmatrix[2] * projmatrix[8] + mvmatrix[3] * projmatrix[12];
+	clip[1] = mvmatrix[0] * projmatrix[1] + mvmatrix[1] * projmatrix[5] + mvmatrix[2] * projmatrix[9] + mvmatrix[3] * projmatrix[13];
+	clip[2] = mvmatrix[0] * projmatrix[2] + mvmatrix[1] * projmatrix[6] + mvmatrix[2] * projmatrix[10] + mvmatrix[3] * projmatrix[14];
+	clip[3] = mvmatrix[0] * projmatrix[3] + mvmatrix[1] * projmatrix[7] + mvmatrix[2] * projmatrix[11] + mvmatrix[3] * projmatrix[15];
+	
+	clip[4] = mvmatrix[4] * projmatrix[0] + mvmatrix[5] * projmatrix[4] + mvmatrix[6] * projmatrix[8] + mvmatrix[7] * projmatrix[12];
+	clip[5] = mvmatrix[4] * projmatrix[1] + mvmatrix[5] * projmatrix[5] + mvmatrix[6] * projmatrix[9] + mvmatrix[7] * projmatrix[13];
+	clip[6] = mvmatrix[4] * projmatrix[2] + mvmatrix[5] * projmatrix[6] + mvmatrix[6] * projmatrix[10] + mvmatrix[7] * projmatrix[14];
+	clip[7] = mvmatrix[4] * projmatrix[3] + mvmatrix[5] * projmatrix[7] + mvmatrix[6] * projmatrix[11] + mvmatrix[7] * projmatrix[15];
+	
+	clip[8] = mvmatrix[8] * projmatrix[0] + mvmatrix[9] * projmatrix[4] + mvmatrix[10] * projmatrix[8] + mvmatrix[11] * projmatrix[12];
+	clip[9] = mvmatrix[8] * projmatrix[1] + mvmatrix[9] * projmatrix[5] + mvmatrix[10] * projmatrix[9] + mvmatrix[11] * projmatrix[13];
+	clip[10] = mvmatrix[8] * projmatrix[2] + mvmatrix[9] * projmatrix[6] + mvmatrix[10] * projmatrix[10] + mvmatrix[11] * projmatrix[14];
+	clip[11] = mvmatrix[8] * projmatrix[3] + mvmatrix[9] * projmatrix[7] + mvmatrix[10] * projmatrix[11] + mvmatrix[11] * projmatrix[15];
+	
+	clip[12] = mvmatrix[12] * projmatrix[0] + mvmatrix[13] * projmatrix[4] + mvmatrix[14] * projmatrix[8] + mvmatrix[15] * projmatrix[12];
+	clip[13] = mvmatrix[12] * projmatrix[1] + mvmatrix[13] * projmatrix[5] + mvmatrix[14] * projmatrix[9] + mvmatrix[15] * projmatrix[13];
+	clip[14] = mvmatrix[12] * projmatrix[2] + mvmatrix[13] * projmatrix[6] + mvmatrix[14] * projmatrix[10] + mvmatrix[15] * projmatrix[14];
+	clip[15] = mvmatrix[12] * projmatrix[3] + mvmatrix[13] * projmatrix[7] + mvmatrix[14] * projmatrix[11] + mvmatrix[15] * projmatrix[15];
+	
+	// Right plane
+	frustum[0][0] = clip[3] - clip[0];
+	frustum[0][1] = clip[7] - clip[4];
+	frustum[0][2] = clip[11] - clip[8];
+	frustum[0][3] = clip[15] - clip[12];
+	
+	// Left plane
+	frustum[1][0] = clip[3] + clip[0];
+	frustum[1][1] = clip[7] + clip[4];
+	frustum[1][2] = clip[11] + clip[8];
+	frustum[1][3] = clip[15] + clip[12];
+	
+	// Bottom plane
+	frustum[2][0] = clip[3] + clip[1];
+	frustum[2][1] = clip[7] + clip[5];
+	frustum[2][2] = clip[11] + clip[9];
+	frustum[2][3] = clip[15] + clip[13];
+	
+	// Top plane
+	frustum[3][0] = clip[3] - clip[1];
+	frustum[3][1] = clip[7] - clip[5];
+	frustum[3][2] = clip[11] - clip[9];
+	frustum[3][3] = clip[15] - clip[13];
+	
+	// Far plane
+	frustum[4][0] = clip[3] - clip[2];
+	frustum[4][1] = clip[7] - clip[6];
+	frustum[4][2] = clip[11] - clip[10];
+	frustum[4][3] = clip[15] - clip[14];
+	
+	// Near plane
+	frustum[5][0] = clip[3] + clip[2];
+	frustum[5][1] = clip[7] + clip[6];
+	frustum[5][2] = clip[11] + clip[10];
+	frustum[5][3] = clip[15] + clip[14];
+
+	/* normalize the right plane */
+	t = sqrt(frustum[0][0]*frustum[0][0] 
+		+ frustum[0][1]*frustum[0][1] 
+		+ frustum[0][2]*frustum[0][2]);
+	frustum[0][0] /= t;
+	frustum[0][1] /= t;
+	frustum[0][2] /= t;
+	frustum[0][3] /= t;
+		
+	/* calculate left plane */
+	frustum[1][0] = clip[ 3] + clip[ 0];
+	frustum[1][1] = clip[ 7] + clip[ 4];
+	frustum[1][2] = clip[11] + clip[ 8];
+	frustum[1][3] = clip[15] + clip[12];
+
+	/* normalize the left plane */
+	t = sqrt(frustum[1][0]*frustum[1][0] 
+		+ frustum[1][1]*frustum[1][1] 
+		+ frustum[1][2]*frustum[1][2]);
+	frustum[1][0] /= t;
+	frustum[1][1] /= t;
+	frustum[1][2] /= t;
+	frustum[1][3] /= t;
+	
+	/* calculate the bottom plane */
+	frustum[2][0] = clip[ 3] + clip[ 1];
+	frustum[2][1] = clip[ 7] + clip[ 5];
+	frustum[2][2] = clip[11] + clip[ 9];
+	frustum[2][3] = clip[15] + clip[13];
+
+	/* normalize the bottom plane */
+	t = sqrt(frustum[2][0]*frustum[2][0] 
+		+ frustum[2][1]*frustum[2][1] 
+		+ frustum[2][2]*frustum[2][2]);
+	frustum[2][0] /= t;
+	frustum[2][1] /= t;
+	frustum[2][2] /= t;
+	frustum[2][3] /= t;
+	
+	/* calculate the top plane */
+	frustum[3][0] = clip[ 3] - clip[ 1];
+	frustum[3][1] = clip[ 7] - clip[ 5];
+	frustum[3][2] = clip[11] - clip[ 9];
+	frustum[3][3] = clip[15] - clip[13];
+	
+	/* normalize the top plane */
+	t = sqrt(frustum[3][0]*frustum[3][0] 
+		+ frustum[3][1]*frustum[3][1] 
+		+ frustum[3][2]*frustum[3][2]);
+	frustum[3][0] /= t;
+	frustum[3][1] /= t;
+	frustum[3][2] /= t;
+	frustum[3][3] /= t;
+	
+	/* calculate the far plane */
+	frustum[4][0] = clip[ 3] - clip[ 2];
+	frustum[4][1] = clip[ 7] - clip[ 6];
+	frustum[4][2] = clip[11] - clip[10];
+	frustum[4][3] = clip[15] - clip[14];
+	
+	/* normalize the far plane */
+	t = sqrt(frustum[4][0]*frustum[4][0] 
+		+ frustum[4][1]*frustum[4][1] 
+		+ frustum[4][2]*frustum[4][2]);
+	frustum[4][0] /= t;
+	frustum[4][1] /= t;
+	frustum[4][2] /= t;
+	frustum[4][3] /= t;
+	
+	/* calculate the near plane */
+	frustum[5][0] = clip[ 3] + clip[ 2];
+	frustum[5][1] = clip[ 7] + clip[ 6];
+	frustum[5][2] = clip[11] + clip[10];
+	frustum[5][3] = clip[15] + clip[14];
+	
+	/* normalize the near plane */
+	t = sqrt(frustum[5][0]*frustum[5][0] 
+		+ frustum[5][1]*frustum[5][1] 
+		+ frustum[5][2]*frustum[5][2]);
+	frustum[5][0] /= t;
+	frustum[5][1] /= t;
+	frustum[5][2] /= t;
+	frustum[5][3] /= t;
+
+}
+
+int FRUSTUM::
+	CubeInFrustum(float x, float y, float z, float size) {
+	int c, c2;
+	
+	c2 = 0;
+	for(int i=0; i<6; i++) {
+		c=0;
+		if(frustum[i][0] * (x-size) + frustum[i][1] * (y-size) + frustum[i][2] * (z-size) + frustum[i][3] > 0)
+			c++;
+		if(frustum[i][0] * (x+size) + frustum[i][1] * (y-size) + frustum[i][2] * (z-size) + frustum[i][3] > 0)
+			c++;
+		if(frustum[i][0] * (x-size) + frustum[i][1] * (y+size) + frustum[i][2] * (z-size) + frustum[i][3] > 0)
+			c++;
+		if(frustum[i][0] * (x+size) + frustum[i][1] * (y+size) + frustum[i][2] * (z-size) + frustum[i][3] > 0)
+			c++;
+		if(frustum[i][0] * (x-size) + frustum[i][1] * (y-size) + frustum[i][2] * (z+size) + frustum[i][3] > 0)
+			c++;
+		if(frustum[i][0] * (x+size) + frustum[i][1] * (y-size) + frustum[i][2] * (z+size) + frustum[i][3] > 0)
+			c++;
+		if(frustum[i][0] * (x-size) + frustum[i][1] * (y+size) + frustum[i][2] * (z+size) + frustum[i][3] > 0)
+			c++;
+		if(frustum[i][0] * (x+size) + frustum[i][1] * (y+size) + frustum[i][2] * (z+size) + frustum[i][3] > 0)
+			c++;
+		if(c==0)
+			return 0;
+		if(c==8)
+			c2++;
+	}
+	if(c2>=6)
+		return 2;
+	else
+		return 1;
+}
+
+int FRUSTUM::
+	CubeInFrustum(float x, float y, float z, float size, float height) {
+	int c, c2;
+
+	c2 = 0;	
+	for(int i=0; i<6; i++) {
+		c=0;
+		if(frustum[i][0] * (x-size) + frustum[i][1] * (y-height) + frustum[i][2] * (z-size) + frustum[i][3] > 0)
+			c++;
+		if(frustum[i][0] * (x+size) + frustum[i][1] * (y-height) + frustum[i][2] * (z-size) + frustum[i][3] > 0)
+			c++;
+		if(frustum[i][0] * (x-size) + frustum[i][1] * (y+height) + frustum[i][2] * (z-size) + frustum[i][3] > 0)
+			c++;
+		if(frustum[i][0] * (x+size) + frustum[i][1] * (y+height) + frustum[i][2] * (z-size) + frustum[i][3] > 0)
+			c++;
+		if(frustum[i][0] * (x-size) + frustum[i][1] * (y-height) + frustum[i][2] * (z+size) + frustum[i][3] > 0)
+			c++;
+		if(frustum[i][0] * (x+size) + frustum[i][1] * (y-height) + frustum[i][2] * (z+size) + frustum[i][3] > 0)
+			c++;
+		if(frustum[i][0] * (x-size) + frustum[i][1] * (y+height) + frustum[i][2] * (z+size) + frustum[i][3] > 0)
+			c++;
+		if(frustum[i][0] * (x+size) + frustum[i][1] * (y+height) + frustum[i][2] * (z+size) + frustum[i][3] > 0)
+			c++;
+		if(c==0)
+			return 0;
+		if(c==8)
+			c2++;
+	}
+	if(c2>=6)
+		return 2;
+	else
+		return 1;
+}
+
+int FRUSTUM::
+	SphereInFrustum(float x, float y, float z, float radius) {
+	int  c2;
+
+	c2 = 0;	
+	for(int i=0; i<6; i++) {
+		if(frustum[i][0] * x + frustum[i][1] * y + frustum[i][2] * z + frustum[i][3] > -1*radius)
+			c2++;
+		else
+			return 0;
+	}
+	if(c2>=6)
+		return 2;
+	else
+		return 1;
+}
diff --git a/src/Frustum.h b/src/Frustum.h
new file mode 100644
index 0000000..1680226
--- /dev/null
+++ b/src/Frustum.h
@@ -0,0 +1,14 @@
+#ifndef FRUSTUM_H
+#define FRUSTUM_H
+
+class FRUSTUM {
+	public:
+		float frustum[6][4];
+		void GetFrustum();
+		int CubeInFrustum(float, float, float, float);
+		int CubeInFrustum(float, float, float, float, float);
+		int SphereInFrustum(float, float, float, float);
+};
+
+#endif
+
diff --git a/src/Game.h b/src/Game.h
new file mode 100644
index 0000000..e7d5b53
--- /dev/null
+++ b/src/Game.h
@@ -0,0 +1,230 @@
+#ifndef _GAME_H_
+#define _GAME_H_
+
+#ifdef OS9 
+#include <gl.h>
+#include <glu.h>
+#include <tk.h>
+#else
+#include <GL/gl.h>
+#include <GL/glu.h>
+#endif
+#include <stdlib.h>			
+#include <stdio.h>			
+#include <string.h>
+#include <ctype.h>
+#ifdef OS9 
+#include <Sound.h>
+#include <Resources.h>		
+#endif
+#include <cstdarg>
+#ifdef OS9 
+#include <glm.h>
+#include <TextUtils.h>
+#endif
+#ifndef OS9 
+#include <SDL/SDL.h>
+#endif
+#ifdef OS9 
+#include "alut.h"
+#else
+#include <AL/al.h>
+#include <AL/alut.h>
+#endif
+#include "Timer.h"	
+#ifdef OS9 
+#include "AGL_DSp.h"	
+#endif
+#include "MacInput.h"
+#include "Quaternions.h"
+#include "Camera.h"
+#include "Skeleton.h"
+#include "Files.h"
+#include "Models.h"
+#include "Text.h"
+#include "Fog.h"
+#include "Frustum.h"
+#include "Sprites.h"
+#include "Person.h"
+#include "Decals.h"
+
+#define num_blocks 100
+#define block_spacing 360
+#define max_people 90
+#define max_people_block 20
+
+
+class Game			 							
+{
+	public:
+		//Eventloop
+  		Boolean	gQuit;
+		float gamespeed;
+		double multiplier2,multiplier3,multiplier4,multiplier5,end,start,timetaken,framespersecond;
+		timer theTimer;	
+		float sps;
+		int maxfps;
+#ifdef OS9 
+		AGLContext gOpenGLContext;
+		CGrafPtr	theScreen;
+#endif
+		//Graphics
+		int screenwidth,screenheight;
+		float viewdistance;
+		
+		//GL functions
+		GLvoid ReSizeGLScene(float fov, float near);
+		int DrawGLScene(void);
+		int InitGL(void);
+		void LoadingScreen(float percent);
+		
+		//Game Functions
+		void	HandleKeyDown( char theChar );
+#ifdef OS9 
+		void	DoEvent( EventRecord *event );
+#endif
+		void	EventLoop( void );
+		void 	Tick();
+		void 	Splat(int k);
+		void 	InitGame();
+		void 	Dispose();
+		
+		//Mouse
+		Point mouseloc;
+		Point oldmouseloc;
+
+		float mouserotation,mouserotation2;
+		float oldmouserotation,oldmouserotation2;
+		float mousesensitivity;
+		float usermousesensitivity;
+		
+		//keyboard
+		
+		bool tabkeydown;
+		
+		//Project Specific
+		int cityrotation[num_blocks][num_blocks];
+		int citytype[num_blocks][num_blocks];
+		int citypeoplenum[num_blocks][num_blocks];
+		bool drawn[num_blocks][num_blocks];
+		int onblockx,onblocky;
+		bool cubetest;
+		bool disttest;
+		bool oldbutton;
+		
+		bool initialized;
+		
+		float flashamount;
+		float flashr,flashg,flashb;
+		
+		int enemystate;
+		
+		int cycle;
+		
+		bool whacked;
+		
+		float losedelay;
+		
+		XYZ bodycoords;
+		
+		FRUSTUM frustum;
+		Model blocks[4];
+		Model blockwalls[4];
+		Model blockcollide[4];
+		Model blocksimplecollide[4];
+		Model blockroofs[4];
+		Model blockocclude;
+		Model sidewalkcollide;
+		Model street;
+		Model Bigstreet;
+		Model path;
+		Model blocksimple;
+		XYZ boundingpoints[8];
+		Files files;
+		Text text;
+		int goodkills;
+		int badkills;
+		int civkills;
+		int machinegunsoundloop;
+		
+		bool lasersight;
+		bool debug;
+		bool vblsync;
+		
+		bool blur;
+		bool blurness;
+		
+		bool paused;
+		
+		int mainmenu;
+		
+		bool reloadtoggle;
+		
+		bool aimtoggle;
+
+		Point olddrawmouse;
+	
+		XYZ vipgoal;
+		
+		XYZ aimer[2];
+		
+		double eqn[4];
+		
+		float oldrot,oldrot2;
+		
+		XYZ lastshot[2];
+		bool zoom;
+		bool oldzoom;
+		
+		int numpeople;
+		float spawndelay;
+		
+		bool customlevels;
+		
+		bool musictoggle;
+		
+		float psychicpower;
+		
+		int type;
+	
+		bool slomokeydown;
+		
+		int mouseoverbutton;
+		int oldmouseoverbutton;
+		
+		Person person[max_people];
+		
+		GLuint 				personspritetextureptr;
+		GLuint 				deadpersonspritetextureptr;
+		GLuint 				scopetextureptr;
+		GLuint 				flaretextureptr;
+		
+		bool killedinnocent;
+		bool gameinprogress;
+		bool beatgame;
+		bool mainmenuness;
+		int murderer;
+		float timeremaining;
+		int whichsong;
+		int oldscore;
+		int highscore;
+		int score;
+		int mission;
+		int nummissions;
+		int numpossibleguns;
+		int possiblegun[6];
+		int evilprobability;
+		float difficulty;
+		bool azertykeyboard;
+		bool oldvisionkey;
+		
+		~Game() {
+			glDeleteTextures( 1, (const GLuint *)personspritetextureptr );
+			glDeleteTextures( 1, (const GLuint *)deadpersonspritetextureptr );
+			glDeleteTextures( 1, (const GLuint *)scopetextureptr );
+			glDeleteTextures( 1, (const GLuint *)flaretextureptr );
+		}
+		
+};
+
+#endif
diff --git a/src/GameDraw.cpp b/src/GameDraw.cpp
new file mode 100644
index 0000000..c79d87e
--- /dev/null
+++ b/src/GameDraw.cpp
@@ -0,0 +1,1770 @@
+#include "Game.h"	
+
+extern int thirdperson;
+
+extern double multiplier;
+
+extern int nocolors;
+
+extern int visions;
+
+extern unsigned int gSourceID[100];
+
+extern unsigned int gSampleSet[100];
+
+extern Camera camera;
+
+extern Sprites sprites;
+
+extern float camerashake;
+
+extern Fog fog;
+
+extern float fogcolorr;
+
+extern float fogcolorg;
+
+extern float fogcolorb;
+
+extern float sinefluct;
+
+extern float sinefluctprog;
+
+extern int environment;
+
+extern Decals decals;
+
+/*********************> DrawGLScene() <*****/
+
+int Game::DrawGLScene(void)									
+
+{	
+
+	//Main menu
+
+	if(mainmenu==1){
+
+		//Setup fast sine fluctuation
+
+		sinefluct=sin(sinefluctprog);
+
+		sinefluctprog+=multiplier*1.5;
+
+		
+
+		glLoadIdentity();
+
+		glClearColor(0,0,0,1);
+
+		glDisable(GL_CLIP_PLANE0);
+
+		glDisable(GL_FOG);
+
+		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+		
+
+		//"Black Shades"
+
+		glDisable(GL_TEXTURE_2D);
+
+		glDisable(GL_DEPTH_TEST);							// Disables Depth Testing
+
+		glDisable(GL_CULL_FACE);
+
+		glDisable(GL_LIGHTING);
+
+		glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+
+		glDepthMask(0);
+
+		glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
+
+		glPushMatrix();										// Store The Projection Matrix
+
+		glLoadIdentity();									// Reset The Projection Matrix
+
+		glOrtho(0,640,0,480,-100,100);						// Set Up An Ortho Screen
+
+		glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
+
+		//Draw smoke
+
+		glPushMatrix();										// Store The Modelview Matrix
+
+			glLoadIdentity();								// Reset The Modelview Matrix
+
+			glTranslatef(60+sinefluct*40,335-sinefluct*9,0);
+
+			glScalef(500-sinefluct*80,70+sinefluct*18,1);
+
+			glTranslatef(.5,.5,0);
+
+			glScalef(.5,.5,1);
+
+			glRotatef(sinefluctprog*50,0,0,1);
+
+			glEnable(GL_TEXTURE_2D);
+
+			glBindTexture(GL_TEXTURE_2D,  sprites.smoketextureptr);
+
+			glEnable(GL_BLEND);
+
+			glColor4f(1,1,1,.4+sinefluct/8);
+
+			glBegin(GL_TRIANGLES);
+
+				glTexCoord2f(1.0f, 1.0f); glVertex3f( 1, 1, 0.0f);
+
+				glTexCoord2f(0.0f, 1.0f); glVertex3f(-1, 1, 0.0f);
+
+				glTexCoord2f(1.0f, 0.0f); glVertex3f( 1,-1, 0.0f);
+
+				glTexCoord2f(0.0f, 0.0f); glVertex3f(-1,-1, 0.0f);
+
+				glTexCoord2f(1.0f, 0.0f); glVertex3f( 1, -1, 0.0f);
+
+				glTexCoord2f(0.0f, 1.0f); glVertex3f(-1, 1, 0.0f);
+
+			glEnd();
+
+		glPopMatrix();
+
+		glPushMatrix();										// Store The Modelview Matrix
+
+			glLoadIdentity();								// Reset The Modelview Matrix
+
+			glTranslatef(60+sinefluct*40,335-sinefluct*9,0);
+
+			glScalef(530-sinefluct*80,50+sinefluct*18,1);
+
+			glTranslatef(.5,.5,0);
+
+			glScalef(.5,.5,1);
+
+			glRotatef(-sinefluctprog*50,0,0,1);
+
+			glEnable(GL_TEXTURE_2D);
+
+			glBindTexture(GL_TEXTURE_2D,  sprites.smoketextureptr);
+
+			glEnable(GL_BLEND);
+
+			glColor4f(1,1,1,.4-sinefluct/8);
+
+			glBegin(GL_TRIANGLES);
+
+				glTexCoord2f(1.0f, 1.0f); glVertex3f( 1, 1, 0.0f);
+
+				glTexCoord2f(0.0f, 1.0f); glVertex3f(-1, 1, 0.0f);
+
+				glTexCoord2f(1.0f, 0.0f); glVertex3f( 1,-1, 0.0f);
+
+				glTexCoord2f(0.0f, 0.0f); glVertex3f(-1,-1, 0.0f);
+
+				glTexCoord2f(1.0f, 0.0f); glVertex3f( 1, -1, 0.0f);
+
+				glTexCoord2f(0.0f, 1.0f); glVertex3f(-1, 1, 0.0f);
+
+			glEnd();
+
+		glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
+
+		glPopMatrix();										// Restore The Old Projection Matrix
+
+		glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
+
+		glPopMatrix();										// Restore The Old Projection Matrix
+
+		glDepthMask(1);
+
+		
+
+		//Text
+
+		
+
+		glEnable(GL_TEXTURE_2D);
+
+		glColor4f(0,0,0,1);
+
+		static char string[256]="";
+
+		sprintf (string, "Black Shades");
+
+		text.glPrint(100,175,string,1,2,640,480);
+
+		
+
+		//"New Game"
+
+		glDisable(GL_TEXTURE_2D);
+
+		glDisable(GL_DEPTH_TEST);							// Disables Depth Testing
+
+		glDisable(GL_CULL_FACE);
+
+		glDisable(GL_LIGHTING);
+
+		glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+
+		glDepthMask(0);
+
+		glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
+
+		glPushMatrix();										// Store The Projection Matrix
+
+		glLoadIdentity();									// Reset The Projection Matrix
+
+		glOrtho(0,640,0,480,-100,100);						// Set Up An Ortho Screen
+
+		glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
+
+		//Draw smoke
+
+		glPushMatrix();										// Store The Modelview Matrix
+
+			glLoadIdentity();								// Reset The Modelview Matrix
+
+			glTranslatef(120-sinefluct*40,235+sinefluct*9,0);
+
+			glScalef(440+sinefluct*80,70-sinefluct*18,1);
+
+			glTranslatef(.5,.5,0);
+
+			glScalef(.5,.5,1);
+
+			glRotatef(sinefluctprog*50,0,0,1);
+
+			glEnable(GL_TEXTURE_2D);
+
+			if(mouseoverbutton!=1)glBindTexture(GL_TEXTURE_2D,  sprites.smoketextureptr);
+
+			if(mouseoverbutton==1)glBindTexture(GL_TEXTURE_2D,  flaretextureptr);
+
+			glEnable(GL_BLEND);
+
+			glColor4f(1,0,0,.5+sinefluct/6);
+
+			glBegin(GL_TRIANGLES);
+
+				glTexCoord2f(1.0f, 1.0f); glVertex3f( 1, 1, 0.0f);
+
+				glTexCoord2f(0.0f, 1.0f); glVertex3f(-1, 1, 0.0f);
+
+				glTexCoord2f(1.0f, 0.0f); glVertex3f( 1,-1, 0.0f);
+
+				glTexCoord2f(0.0f, 0.0f); glVertex3f(-1,-1, 0.0f);
+
+				glTexCoord2f(1.0f, 0.0f); glVertex3f( 1, -1, 0.0f);
+
+				glTexCoord2f(0.0f, 1.0f); glVertex3f(-1, 1, 0.0f);
+
+			glEnd();
+
+		glPopMatrix();
+
+		glPushMatrix();										// Store The Modelview Matrix
+
+			glLoadIdentity();								// Reset The Modelview Matrix
+
+			glTranslatef(120-sinefluct*40,235+sinefluct*9,0);
+
+			glScalef(460+sinefluct*80,50-sinefluct*18,1);
+
+			glTranslatef(.5,.5,0);
+
+			glScalef(.5,.5,1);
+
+			glRotatef(-sinefluctprog*50,0,0,1);
+
+			glEnable(GL_TEXTURE_2D);
+
+			if(mouseoverbutton!=1)glBindTexture(GL_TEXTURE_2D,  sprites.smoketextureptr);
+
+			if(mouseoverbutton==1)glBindTexture(GL_TEXTURE_2D,  flaretextureptr);
+
+			glEnable(GL_BLEND);
+
+			glColor4f(1,0,0,.5-sinefluct/6);
+
+			glBegin(GL_TRIANGLES);
+
+				glTexCoord2f(1.0f, 1.0f); glVertex3f( 1, 1, 0.0f);
+
+				glTexCoord2f(0.0f, 1.0f); glVertex3f(-1, 1, 0.0f);
+
+				glTexCoord2f(1.0f, 0.0f); glVertex3f( 1,-1, 0.0f);
+
+				glTexCoord2f(0.0f, 0.0f); glVertex3f(-1,-1, 0.0f);
+
+				glTexCoord2f(1.0f, 0.0f); glVertex3f( 1, -1, 0.0f);
+
+				glTexCoord2f(0.0f, 1.0f); glVertex3f(-1, 1, 0.0f);
+
+			glEnd();
+
+		glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
+
+		glPopMatrix();										// Restore The Old Projection Matrix
+
+		glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
+
+		glPopMatrix();										// Restore The Old Projection Matrix
+
+		glDepthMask(1);
+
+		
+
+		//Text
+
+		
+
+		glEnable(GL_TEXTURE_2D);
+
+		glColor4f(0,0,0,1);
+
+		if(!gameinprogress)sprintf (string, "New Game");
+
+		if(gameinprogress)sprintf (string, "Resume Game");
+
+		text.glPrint(190-gameinprogress*10,170,string,1,1.5,640,480);
+
+		
+
+		//"Quit"
+
+		glDisable(GL_TEXTURE_2D);
+
+		glDisable(GL_DEPTH_TEST);							// Disables Depth Testing
+
+		glDisable(GL_CULL_FACE);
+
+		glDisable(GL_LIGHTING);
+
+		glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+
+		glDepthMask(0);
+
+		glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
+
+		glPushMatrix();										// Store The Projection Matrix
+
+		glLoadIdentity();									// Reset The Projection Matrix
+
+		glOrtho(0,640,0,480,-100,100);						// Set Up An Ortho Screen
+
+		glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
+
+		//Draw smoke
+
+		glPushMatrix();										// Store The Modelview Matrix
+
+			glLoadIdentity();								// Reset The Modelview Matrix
+
+			glTranslatef(120-sinefluct*40,112+sinefluct*9,0);
+
+			glScalef(440+sinefluct*80,70-sinefluct*18,1);
+
+			glTranslatef(.5,.5,0);
+
+			glScalef(.5,.5,1);
+
+			glRotatef(sinefluctprog*50,0,0,1);
+
+			glEnable(GL_TEXTURE_2D);
+
+			if(mouseoverbutton!=2)glBindTexture(GL_TEXTURE_2D,  sprites.smoketextureptr);
+
+			if(mouseoverbutton==2)glBindTexture(GL_TEXTURE_2D,  flaretextureptr);
+
+			glEnable(GL_BLEND);
+
+			glColor4f(1,0,0,.5+sinefluct/6);
+
+			glBegin(GL_TRIANGLES);
+
+				glTexCoord2f(1.0f, 1.0f); glVertex3f( 1, 1, 0.0f);
+
+				glTexCoord2f(0.0f, 1.0f); glVertex3f(-1, 1, 0.0f);
+
+				glTexCoord2f(1.0f, 0.0f); glVertex3f( 1,-1, 0.0f);
+
+				glTexCoord2f(0.0f, 0.0f); glVertex3f(-1,-1, 0.0f);
+
+				glTexCoord2f(1.0f, 0.0f); glVertex3f( 1, -1, 0.0f);
+
+				glTexCoord2f(0.0f, 1.0f); glVertex3f(-1, 1, 0.0f);
+
+			glEnd();
+
+		glPopMatrix();
+
+		glPushMatrix();										// Store The Modelview Matrix
+
+			glLoadIdentity();								// Reset The Modelview Matrix
+
+			glTranslatef(120-sinefluct*40,112+sinefluct*9,0);
+
+			glScalef(460+sinefluct*80,50-sinefluct*18,1);
+
+			glTranslatef(.5,.5,0);
+
+			glScalef(.5,.5,1);
+
+			glRotatef(-sinefluctprog*50,0,0,1);
+
+			glEnable(GL_TEXTURE_2D);
+
+			if(mouseoverbutton!=2)glBindTexture(GL_TEXTURE_2D,  sprites.smoketextureptr);
+
+			if(mouseoverbutton==2)glBindTexture(GL_TEXTURE_2D,  flaretextureptr);
+
+			glEnable(GL_BLEND);
+
+			glColor4f(1,0,0,.5-sinefluct/6);
+
+			glBegin(GL_TRIANGLES);
+
+				glTexCoord2f(1.0f, 1.0f); glVertex3f( 1, 1, 0.0f);
+
+				glTexCoord2f(0.0f, 1.0f); glVertex3f(-1, 1, 0.0f);
+
+				glTexCoord2f(1.0f, 0.0f); glVertex3f( 1,-1, 0.0f);
+
+				glTexCoord2f(0.0f, 0.0f); glVertex3f(-1,-1, 0.0f);
+
+				glTexCoord2f(1.0f, 0.0f); glVertex3f( 1, -1, 0.0f);
+
+				glTexCoord2f(0.0f, 1.0f); glVertex3f(-1, 1, 0.0f);
+
+			glEnd();
+
+		glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
+
+		glPopMatrix();										// Restore The Old Projection Matrix
+
+		glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
+
+		glPopMatrix();										// Restore The Old Projection Matrix
+
+		glDepthMask(1);
+
+		
+
+		//Text
+
+		
+
+		glEnable(GL_TEXTURE_2D);
+
+		glColor4f(0,0,0,1);
+
+		if(!gameinprogress)sprintf (string, "Quit");
+
+		if(gameinprogress)sprintf (string, "End Game");
+
+		text.glPrint(197-gameinprogress*15,87,string,1,1.5,640,480);
+
+		
+
+		//High score
+
+		glColor4f(.5+sinefluct/5,0,0,1);
+
+		if(!beatgame)sprintf (string, "High Score:  %d", highscore);
+
+		if(beatgame)sprintf (string, "High Score:  %d *COMPLETED* Please vote for Black Shades at iDevGames.com!", highscore);
+
+		text.glPrint(0,0,string,1,.8,640,480);
+
+		
+
+		//Mandatory udg text
+
+		glColor4f(.3-sinefluct/20,.3-sinefluct/20,.3-sinefluct/20,1);
+
+		sprintf (string, "uDevGame 2002 Entry - Visit iDevGames.com for more games!");
+
+		text.glPrint(500,750,string,1,.6,640,480);
+
+		
+
+		
+		//Mouse (draw)
+
+		glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
+
+		glPushMatrix();										// Store The Projection Matrix
+
+		glLoadIdentity();									// Reset The Projection Matrix
+
+		glOrtho(0,screenwidth,0,screenheight,-100,100);						// Set Up An Ortho Screen
+
+		glMatrixMode(GL_MODELVIEW);			
+
+		glDisable(GL_TEXTURE_2D);
+
+
+		Point mouseloc;
+
+		GetMouse(&mouseloc);
+
+		mouseloc.v=screenheight-mouseloc.v;
+		
+
+		glColor4f(.1,0,0,1);
+
+		
+
+		float size=5;
+
+		
+
+		glBegin(GL_TRIANGLES);
+
+			glVertex3f(mouseloc.h,mouseloc.v,0);
+
+			glVertex3f(mouseloc.h+2*size,mouseloc.v-2*size,0);
+
+			glVertex3f(mouseloc.h+.5*size,mouseloc.v-2*size,0);
+
+		glEnd();
+
+		
+
+		glColor4f(1,0,0,1);
+
+		
+
+		glBegin(GL_QUADS);
+
+			glVertex3f(olddrawmouse.h,olddrawmouse.v,0);
+
+			glVertex3f(mouseloc.h,mouseloc.v,0);
+
+			glVertex3f(mouseloc.h+2*size,mouseloc.v-2*size,0);
+
+			glVertex3f(olddrawmouse.h+2*size,olddrawmouse.v-2*size,0);
+
+			
+
+			glVertex3f(olddrawmouse.h,olddrawmouse.v,0);
+
+			glVertex3f(mouseloc.h,mouseloc.v,0);
+
+			glVertex3f(mouseloc.h+.5*size,mouseloc.v-2*size,0);
+
+			glVertex3f(olddrawmouse.h+.5*size,olddrawmouse.v-2*size,0);
+
+			
+
+			glVertex3f(olddrawmouse.h+2*size,olddrawmouse.v-2*size,0);
+
+			glVertex3f(mouseloc.h+2*size,mouseloc.v-2*size,0);
+
+			glVertex3f(mouseloc.h+.5*size,mouseloc.v-2*size,0);
+
+			glVertex3f(olddrawmouse.h+.5*size,olddrawmouse.v-2*size,0);
+
+		glEnd();
+
+		glPopMatrix();
+
+		
+		olddrawmouse=mouseloc;
+		
+
+		//Flash
+
+		if(flashamount>0){
+
+			if(flashamount>1)flashamount=1;
+
+			flashamount-=multiplier;
+
+			if(flashamount<0)flashamount=0;
+
+			glDisable(GL_DEPTH_TEST);							// Disables Depth Testing
+
+			glDisable(GL_CULL_FACE);
+
+			glDisable(GL_LIGHTING);
+
+			glDepthMask(0);
+
+			glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
+
+			glPushMatrix();										// Store The Projection Matrix
+
+			glLoadIdentity();									// Reset The Projection Matrix
+
+			glOrtho(0,screenwidth,0,screenheight,-100,100);						// Set Up An Ortho Screen
+
+			glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
+
+			glPushMatrix();										// Store The Modelview Matrix
+
+			glLoadIdentity();								// Reset The Modelview Matrix
+
+			glScalef(screenwidth,screenheight,1);
+
+			glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+
+			glEnable(GL_BLEND);
+
+			glColor4f(flashr,flashg,flashb,flashamount);
+
+			glBegin(GL_QUADS);
+
+				glVertex3f(0,		0, 	 0.0f);
+
+				glVertex3f(256,	0, 	 0.0f);
+
+				glVertex3f(256,	256, 0.0f);
+
+				glVertex3f(0, 	256, 0.0f);
+
+			glEnd();
+
+			glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
+
+			glPopMatrix();										// Restore The Old Projection Matrix
+
+			glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
+
+			glPopMatrix();										// Restore The Old Projection Matrix
+
+			glEnable(GL_DEPTH_TEST);							// Enables Depth Testing
+
+			glEnable(GL_CULL_FACE);
+
+			glDisable(GL_BLEND);
+
+			glDepthMask(1);
+
+		}	
+
+	}
+
+	//If in-game
+
+	if(mainmenu!=1){
+
+		//If flashing to fix menu bug, go back to menu after a frame
+
+		if(mainmenu==2)mainmenu=1;
+
+		glLoadIdentity();
+
+		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+		glEnable(GL_DEPTH_TEST);
+
+		glDisable(GL_CLIP_PLANE0);
+
+		//Visions
+
+		sinefluct=sin(sinefluctprog);
+
+		sinefluctprog+=multiplier*3;
+
+		if(visions==0){
+
+			//environment light
+
+			if(environment==sunny_environment){
+
+				viewdistance=2000;	
+
+				fogcolorr=.5;
+
+				fogcolorg=.5;
+
+				fogcolorb=.8;
+
+				fog.SetFog(fogcolorr,fogcolorg,fogcolorb,0,viewdistance*.8,.1);
+
+			}
+
+			if(environment==foggy_environment){
+
+				viewdistance=500;	
+
+				fogcolorr=.5;
+
+				fogcolorg=.5;
+
+				fogcolorb=.5;
+
+				fog.SetFog(fogcolorr,fogcolorg,fogcolorb,0,viewdistance*.8,.2);
+
+			}
+
+			if(environment==night_environment){
+
+				viewdistance=500;	
+
+				fogcolorr=.15;
+
+				fogcolorg=.15;
+
+				fogcolorb=.3;
+
+				fog.SetFog(fogcolorr,fogcolorg,fogcolorb,0,viewdistance*.8,.2);
+
+			}
+
+			if(environment==snowy_environment){
+
+				viewdistance=800;	
+
+				fogcolorr=.5;
+
+				fogcolorg=.5;
+
+				fogcolorb=.5;
+
+				fog.SetFog(fogcolorr,fogcolorg,fogcolorb,0,viewdistance*.8,.2);
+
+			}
+
+			if(environment==rainy_environment){
+
+				viewdistance=700;	
+
+				fogcolorr=.3;
+
+				fogcolorg=.3;
+
+				fogcolorb=.3;
+
+				fog.SetFog(fogcolorr,fogcolorg,fogcolorb,0,viewdistance*.8,.2);
+
+			}
+
+			if(environment==firey_environment){
+
+				viewdistance=600;	
+
+				fogcolorr=.3;
+
+				fogcolorg=.1;
+
+				fogcolorb=0;
+
+				fog.SetFog(fogcolorr,fogcolorg,fogcolorb,0,viewdistance*.8,.2);
+
+			}
+
+			glClearColor(fogcolorr,fogcolorg,fogcolorb,1);
+
+			
+
+			if(environment==sunny_environment){
+
+				GLfloat LightAmbient[]=	{ fogcolorr/4, fogcolorg/4, fogcolorb/4, 1.0f};
+
+				GLfloat LightDiffuse[]=	{ fogcolorr*1.6, fogcolorg*1.6, fogcolorr*1.6, 1.0f };
+
+				glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient);		
+
+				glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);	
+
+			}
+
+			if(environment!=sunny_environment){
+
+				GLfloat LightAmbient[]=	{ fogcolorr*.8, fogcolorg*.8, fogcolorb*.8, 1.0f};
+
+				GLfloat LightDiffuse[]=	{ fogcolorr*.8, fogcolorg*.8, fogcolorr*.8, 1.0f };
+
+				glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient);		
+
+				glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);	
+
+			}			
+
+				
+
+			glEnable(GL_LIGHT0);	
+
+			
+
+			//Change fov if zooming with scope
+
+			if(!zoom)ReSizeGLScene(90,.1);
+
+			if(zoom)ReSizeGLScene(10,.6);
+
+			nocolors=0;
+
+		}
+
+		
+
+		if(visions==1){
+
+			//light
+
+			GLfloat LightAmbient[]=		{ 0, 0, 0, 1.0f};
+
+			GLfloat LightDiffuse[]=		{ .1+sinefluct/5, 0, 0, 1.0f };
+
+			
+
+			glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient);		
+
+			glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);		
+
+			glEnable(GL_LIGHT0);	
+
+			
+
+			fogcolorr=(sinefluct/4+.5);
+
+			fogcolorg=0;
+
+			fogcolorb=0;
+
+			fog.SetFog(fogcolorr,fogcolorg,fogcolorb,0,viewdistance*.8*.5*(sinefluct/4+.3),sinefluct/3+.7);
+
+			glClearColor(fogcolorr,fogcolorg,fogcolorb,1);
+
+			ReSizeGLScene(120-sinefluct*20,.3);
+
+			glRotatef(sinefluct*10,0,0,.1);
+
+			nocolors=1;
+
+			//Pitch higher if moving for effect
+
+			if(person[0].currentanimation==idleanim)alSourcef(gSourceID[visionsound], AL_PITCH, 1);
+
+			if(person[0].currentanimation!=idleanim)alSourcef(gSourceID[visionsound], AL_PITCH, 2);
+
+		}
+
+		
+
+		//Camera
+
+		float bluramount=.1*blurness;
+
+		blur=1-blur;
+
+		//Set rotation/position
+
+		if(thirdperson)glTranslatef(camera.targetoffset.x,camera.targetoffset.y,camera.targetoffset.z);
+
+		if(thirdperson!=2&&(person[0].skeleton.free!=1||thirdperson!=0)){
+
+			glRotatef(camera.visrotation2+-bluramount/2+(float)blur*bluramount,1,0,0);
+
+			glRotatef(camera.visrotation+-bluramount/2+(float)blur*bluramount,0,1,0);
+
+		}
+
+		if(thirdperson==0&&person[0].skeleton.free==1){
+
+			glRotatef(person[0].skeleton.joints[(person[0].skeleton.jointlabels[head])].rotate3,0,1,0);
+
+			glRotatef(180-(person[0].skeleton.joints[(person[0].skeleton.jointlabels[head])].rotate2+90),0,0,1);
+
+			glRotatef(person[0].skeleton.joints[(person[0].skeleton.jointlabels[head])].rotate1+90,0,1,0);
+
+		}
+
+		if(thirdperson==2){
+
+			glRotatef(oldrot2+-bluramount/2+(float)blur*bluramount,1,0,0);
+
+			glRotatef(oldrot+-bluramount/2+(float)blur*bluramount,0,1,0);
+
+		}
+
+		//Shake camera if grenade explosion
+
+		if(camerashake>0){
+
+			if(!(person[0].aiming<1||person[0].whichgun==grenade||thirdperson)){
+
+				camerashake=0;
+
+			}
+
+			glTranslatef((float)(Random()%100)/100*camerashake,(float)(Random()%100)/100*camerashake,(float)(Random()%100)/100*camerashake);
+
+		}
+
+		camera.Apply();
+
+		
+
+		glPushMatrix();
+
+			glClipPlane(GL_CLIP_PLANE0, eqn);
+
+			glDisable(GL_CLIP_PLANE0);
+
+		glPopMatrix();
+
+		
+
+		frustum.GetFrustum();
+
+
+
+		GLfloat LightPosition[]=	{ -.5, 1, -.8, 0.0f };
+
+		glLightfv(GL_LIGHT0, GL_POSITION, LightPosition);
+
+		
+
+		glDisable(GL_TEXTURE_2D);
+
+		glEnable(GL_FOG);
+
+		glEnable(GL_COLOR_MATERIAL);
+
+		glEnable(GL_CULL_FACE);
+
+		glDepthMask(1);
+
+				
+
+		//Draw street
+
+		glPushMatrix();
+
+			glDepthMask(0);
+
+			glDisable(GL_DEPTH_TEST);
+
+			glEnable(GL_LIGHTING);
+
+			glTranslatef(camera.position.x,0,camera.position.z);
+
+			glScalef(viewdistance*5/100,1,viewdistance*5/100);
+
+			if(visions==0)street.draw(.22,.22,.22);
+
+			if(visions==1)street.draw(0,0,0);
+
+			glEnable(GL_DEPTH_TEST);
+
+			glDepthMask(1);
+
+		glPopMatrix();
+
+		
+
+		if(visions==0)glEnable(GL_LIGHTING);
+
+		if(visions==1)glDisable(GL_LIGHTING);
+
+		
+
+		//Draw blocks
+
+		glEnable(GL_BLEND);
+
+		XYZ move2;
+
+		XYZ move;
+
+		int beginx,endx;
+
+		int beginz,endz;
+
+		int beginoccludex,endoccludex;
+
+		int beginoccludez,endoccludez;
+
+		int distsquared;
+
+		
+
+		//Only nearby blocks
+
+		beginx=(camera.position.x-viewdistance+block_spacing/2)/block_spacing-2;
+
+		if(beginx<0)beginx=0;
+
+		beginz=(camera.position.z-viewdistance+block_spacing/2)/block_spacing-2;
+
+		if(beginz<0)beginz=0;
+
+		
+
+		endx=(camera.position.x+viewdistance+block_spacing/2)/block_spacing+2;
+
+		if(endx>num_blocks-1)endx=num_blocks-1;
+
+		endz=(camera.position.z+viewdistance+block_spacing/2)/block_spacing+2;
+
+		if(endz>num_blocks-1)endz=num_blocks-1;
+
+		
+
+		bool draw;
+
+		int numfail;
+
+		int whichtri;
+
+		XYZ collpoint;
+
+		
+
+		for(int i=beginx;i<=endx;i++){
+
+			for(int j=beginz;j<=endz;j++){
+
+				drawn[i][j]=1;
+
+			}
+
+		}
+
+		
+
+		if(beginx<endx&&beginz<endz)
+
+		for(int i=beginx;i<=endx;i++){
+
+			for(int j=beginz;j<=endz;j++){
+
+				draw=1;
+
+				//Only draw if visible
+
+				distsquared=((i)*block_spacing-camera.position.x)*((i)*block_spacing-camera.position.x)+((j)*block_spacing-camera.position.z)*((j)*block_spacing-camera.position.z);
+
+				if(distsquared>(viewdistance*viewdistance+block_spacing*block_spacing	))draw=0;
+
+				if(draw&&citytype[i][j]!=3&&!frustum.CubeInFrustum((i)*block_spacing,0,(j)*block_spacing,block_spacing))draw=0;
+
+				if(draw&&citytype[i][j]!=3&&!frustum.SphereInFrustum(blocks[citytype[i][j]].boundingspherecenter.x+(i)*block_spacing,blocks[citytype[i][j]].boundingspherecenter.y,blocks[citytype[i][j]].boundingspherecenter.z+(j)*block_spacing,blocks[citytype[i][j]].boundingsphereradius))draw=0;
+
+				if(draw){
+
+					glPushMatrix();
+
+						glTranslatef(i*block_spacing,0,j*block_spacing);
+
+						glRotatef(cityrotation[i][j]*90,0,1,0);
+
+						blocks[citytype[i][j]].draw();
+
+					glPopMatrix();
+
+				}
+
+				if(!draw){
+
+					move.y=0;
+
+					move.x=i*block_spacing;
+
+					move.z=j*block_spacing;
+
+					if(findDistancefast(move,camera.position)<300000)drawn[i][j]=0;
+
+				}
+
+			}
+
+		}
+
+		
+
+		//Decals
+
+		decals.draw();
+
+		
+
+		//Occluding blocks
+
+		beginx=(camera.position.x+block_spacing/2)/block_spacing-2;
+
+		if(beginx<0)beginx=0;
+
+		beginz=(camera.position.z+block_spacing/2)/block_spacing-2;
+
+		if(beginz<0)beginz=0;
+
+		
+
+		endx=(camera.position.x+block_spacing/2)/block_spacing+2;
+
+		if(endx>num_blocks-1)endx=num_blocks-1;
+
+		endz=(camera.position.z+block_spacing/2)/block_spacing+2;
+
+		if(endz>num_blocks-1)endz=num_blocks-1;
+
+		
+
+		float M[16];
+
+		XYZ drawpoint;
+
+		float size=20;
+
+		
+
+		//Draw people
+
+		if(visions==1)fog.SetFog(fogcolorr,fogcolorg,fogcolorb,0,viewdistance*.8*.5*(-sinefluct/4+.3),-sinefluct/3+.7);
+
+		glColor4f(1,1,1,1);
+
+		glEnable(GL_COLOR_MATERIAL);
+
+		glEnable(GL_BLEND);
+
+		for(int i=0;i<numpeople;i++){
+
+		
+
+			draw=1;
+
+			if(person[i].skeleton.free<1){
+
+				if(person[i].whichblockx>=0&&person[i].whichblockx<num_blocks&&person[i].whichblocky>=0&&person[i].whichblocky<num_blocks){
+
+					if(!drawn[person[i].whichblockx][person[i].whichblocky])draw=0;
+
+				}else draw=0;
+
+				if(draw)
+
+				if(!frustum.CubeInFrustum(person[i].playercoords.x,person[i].playercoords.y,person[i].playercoords.z,5))draw=0;
+
+				if(draw)
+
+				if(findDistancefast(person[i].playercoords,camera.position)>1000000)draw=0;
+
+				if(draw)
+
+				for(int j=beginx;j<=endx;j++){
+
+					for(int k=beginz;k<=endz;k++){
+
+						if(draw){
+
+							move.y=0;
+
+							move.x=j*block_spacing;
+
+							move.z=k*block_spacing;
+
+							if(findDistancefast(move,camera.position)<100000){
+
+								whichtri=blockocclude.LineCheck2(camera.position,person[i].playercoords,&collpoint,move,0);
+
+								if(whichtri!=-1)draw=0;
+
+							}
+
+						}
+
+					}
+
+				}
+
+				if(draw){
+
+					move.y=0;
+
+					move.x=person[i].whichblockx*block_spacing;
+
+					move.z=person[i].whichblocky*block_spacing;
+
+					whichtri=blockocclude.LineCheck2(camera.position,person[i].playercoords,&collpoint,move,0);
+
+					if(whichtri!=-1)draw=0;
+
+				}
+
+				if(i==0)draw=1;
+
+			}
+
+			if(person[i].skeleton.free==1){
+
+				if(draw)
+
+				if(!person[i].skeleton.broken&&!frustum.CubeInFrustum(person[i].averageloc.x,person[i].averageloc.y,person[i].averageloc.z,5))draw=0;
+
+				if(draw)
+
+				if(findDistancefast(person[i].averageloc,camera.position)>1000000)draw=0;
+
+				if(draw)
+
+				if(person[i].skeleton.joints[0].position.y<-2)draw=0;
+
+				for(int j=beginx;j<=endx;j++){
+
+					for(int k=beginz;k<=endz;k++){
+
+						if(draw){
+
+							move.y=0;
+
+							move.x=j*block_spacing;
+
+							move.z=k*block_spacing;
+
+							if(findDistancefast(move,camera.position)<100000){
+
+								whichtri=blockocclude.LineCheck2(camera.position,person[i].averageloc,&collpoint,move,0);
+
+								if(whichtri!=-1)draw=0;
+
+							}
+
+						}
+
+					}
+
+				}
+
+				if(draw){
+
+					move.y=0;
+
+					move.x=person[i].whichblockx*block_spacing;
+
+					move.z=person[i].whichblocky*block_spacing;
+
+					whichtri=blockocclude.LineCheck2(camera.position,person[i].averageloc,&collpoint,move,0);
+
+					if(whichtri!=-1)draw=0;
+
+				}
+
+				if(i==0)draw=1;
+
+			}
+
+			if(draw&&person[i].existing==1){
+
+				if((findDistancefast(person[i].playercoords,camera.position)<100000+zoom*3000000&&person[i].skeleton.free<1)||(findDistancefast(person[i].averageloc,camera.position)<100000+zoom*3000000&&person[i].skeleton.free>=1)){
+
+					glPushMatrix();
+
+						if(person[i].skeleton.free==0){
+
+							glTranslatef(person[i].playercoords.x,person[i].playercoords.y,person[i].playercoords.z);
+
+							glRotatef(person[i].playerrotation,0,1,0);					
+
+							if(i!=0||visions==0)person[i].DoAnimations(i);
+
+							if(i==0&&visions==1)person[i].DoAnimationslite(i);
+
+						}
+
+						if(visions==1)nocolors=1;
+
+						if(visions==1&&person[i].type==eviltype)nocolors=2;
+
+						if(visions==1&&person[i].type==viptype)nocolors=3;
+
+						if(!(visions==1&&i==0)&&!(zoom==1&&i==0))person[i].DrawSkeleton(i);
+
+					glPopMatrix();
+
+				}
+
+				else{
+
+					glPushMatrix();
+
+						if(person[i].skeleton.free<1)person[i].DoAnimationslite(i);
+
+						glColor4f(1,1,1,1);
+
+						glEnable(GL_BLEND);
+
+						glDisable(GL_CULL_FACE);
+
+						glEnable(GL_TEXTURE_2D);
+
+						glDisable(GL_LIGHTING);
+
+						glDepthMask(0);
+
+						glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+
+						if(person[i].skeleton.free<1){
+
+							glBindTexture(GL_TEXTURE_2D, personspritetextureptr);
+
+							glTranslatef(person[i].playercoords.x,person[i].playercoords.y+size/2*.3,person[i].playercoords.z);
+
+						}
+
+						if(person[i].skeleton.free==1){
+
+							glBindTexture(GL_TEXTURE_2D, deadpersonspritetextureptr);
+
+							glTranslatef(person[i].averageloc.x,person[i].averageloc.y+size/2*.3,person[i].averageloc.z);
+
+						}
+
+						glGetFloatv(GL_MODELVIEW_MATRIX,M);
+
+						drawpoint.x=M[12];
+
+						drawpoint.y=M[13];
+
+						drawpoint.z=M[14];
+
+						glLoadIdentity();
+
+						glTranslatef(drawpoint.x, drawpoint.y, drawpoint.z);
+
+						glBegin(GL_TRIANGLES);
+
+							glTexCoord2f(1.0f, 1.0f); glVertex3f( .3f*size, .3f*size, 0.0f);
+
+							glTexCoord2f(0.0f, 1.0f); glVertex3f(-.3f*size, .3f*size, 0.0f);
+
+							glTexCoord2f(1.0f, 0.0f); glVertex3f( .3f*size,-.3f*size, 0.0f);
+
+							glTexCoord2f(0.0f, 0.0f); glVertex3f(-.3f*size,-.3f*size, 0.0f);
+
+							glTexCoord2f(1.0f, 0.0f); glVertex3f( .3f*size, -.3f*size, 0.0f);
+
+							glTexCoord2f(0.0f, 1.0f); glVertex3f(-.3f*size, .3f*size, 0.0f);
+
+						glEnd();
+
+					glPopMatrix();
+
+					glDepthMask(1);
+
+					glDisable(GL_TEXTURE_2D);
+
+					glEnable(GL_CULL_FACE);
+
+					if(visions!=1)glEnable(GL_LIGHTING);
+
+				}
+
+			}
+
+			if(person[i].skeleton.free<1&&!draw)person[i].DoAnimationslite(i);
+
+						
+
+			if(!person[i].existing)
+
+				if(!draw||findDistancefast(person[i].playercoords,camera.position)>10000){person[i].existing=1;}
+
+		}
+
+		glDisable(GL_COLOR_MATERIAL);
+
+		glDisable(GL_BLEND);
+
+		
+
+		//Attacker psychicness 
+
+		for(int i=0;i<numpeople;i++){
+
+			if(person[i].killtarget>-1&&person[i].killtargetvisible&&person[i].skeleton.free==0&&person[person[i].killtarget].skeleton.free==0){
+
+				sprites.MakeSprite(bulletinstant, (shotdelayamount/difficulty-person[i].shotdelay)/shotdelayamount/difficulty/2, 1, person[i].shotdelay/shotdelayamount/difficulty, person[i].shotdelay/shotdelayamount/difficulty, DoRotation(person[i].skeleton.joints[person[i].skeleton.jointlabels[lefthand]].position,0,person[i].playerrotation,0)+person[i].playercoords, person[person[i].killtarget].skeleton.joints[person[person[i].killtarget].skeleton.jointlabels[abdomen]].position+person[person[i].killtarget].playercoords, person[i].shotdelay*2);
+
+			}
+
+			if(person[i].killtarget>-1&&person[i].killtargetvisible&&person[i].skeleton.free==0&&person[person[i].killtarget].skeleton.free!=0){
+
+				sprites.MakeSprite(bulletinstant, (shotdelayamount/difficulty-person[i].shotdelay)/shotdelayamount/difficulty/2, 1, person[i].shotdelay/shotdelayamount/difficulty, person[i].shotdelay/shotdelayamount/difficulty, DoRotation(person[i].skeleton.joints[person[i].skeleton.jointlabels[lefthand]].position,0,person[i].playerrotation,0)+person[i].playercoords, person[person[i].killtarget].skeleton.joints[person[person[i].killtarget].skeleton.jointlabels[abdomen]].position, person[i].shotdelay*2);
+
+			}
+
+		}
+
+		
+
+		//Sprites
+
+		glEnable(GL_CLIP_PLANE0);
+
+		sprites.draw();
+
+		
+
+		glDisable(GL_CLIP_PLANE0);
+
+
+
+		glDisable(GL_FOG);
+
+		//Zoom
+
+		glAlphaFunc(GL_GREATER, 0.01);
+
+		
+
+		if(zoom){
+
+			glDisable(GL_DEPTH_TEST);							// Disables Depth Testing
+
+			glDisable(GL_CULL_FACE);
+
+			glDisable(GL_LIGHTING);
+
+			glDepthMask(0);
+
+			glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
+
+			glPushMatrix();										// Store The Projection Matrix
+
+			glLoadIdentity();									// Reset The Projection Matrix
+
+			glOrtho(0,screenwidth,0,screenheight,-100,100);						// Set Up An Ortho Screen
+
+			glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
+
+			glPushMatrix();										// Store The Modelview Matrix
+
+			glLoadIdentity();								// Reset The Modelview Matrix
+
+			glScalef(screenwidth,screenheight,1);
+
+			glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+
+			glEnable(GL_BLEND);
+
+			glEnable(GL_TEXTURE_2D);
+
+			glColor4f(.5,.5,.5,1);
+
+			glBindTexture(GL_TEXTURE_2D, scopetextureptr);
+
+			glBegin(GL_QUADS);
+
+				glTexCoord2f(0,0);
+
+				glVertex3f(0,		0, 	 0.0f);
+
+				glTexCoord2f(1,0);
+
+				glVertex3f(1,	0, 	 0.0f);
+
+				glTexCoord2f(1,1);
+
+				glVertex3f(1,	1, 0.0f);
+
+				glTexCoord2f(0,1);
+
+				glVertex3f(0, 	1, 0.0f);
+
+			glEnd();
+
+			glDisable(GL_TEXTURE_2D);
+
+			glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
+
+			glPopMatrix();										// Restore The Old Projection Matrix
+
+			glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
+
+			glPopMatrix();										// Restore The Old Projection Matrix
+
+			glEnable(GL_DEPTH_TEST);							// Enables Depth Testing
+
+			glEnable(GL_CULL_FACE);
+
+			glDisable(GL_BLEND);
+
+			glDepthMask(1);
+
+		}	
+
+		
+
+		//Flash
+
+		if(flashamount>0){
+
+			if(flashamount>1)flashamount=1;
+
+			flashamount-=multiplier;
+
+			if(flashamount<0)flashamount=0;
+
+			glDisable(GL_DEPTH_TEST);							// Disables Depth Testing
+
+			glDisable(GL_CULL_FACE);
+
+			glDisable(GL_LIGHTING);
+
+			glDepthMask(0);
+
+			glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
+
+			glPushMatrix();										// Store The Projection Matrix
+
+			glLoadIdentity();									// Reset The Projection Matrix
+
+			glOrtho(0,screenwidth,0,screenheight,-100,100);						// Set Up An Ortho Screen
+
+			glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
+
+			glPushMatrix();										// Store The Modelview Matrix
+
+			glLoadIdentity();								// Reset The Modelview Matrix
+
+			glScalef(screenwidth,screenheight,1);
+
+			glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+
+			glEnable(GL_BLEND);
+
+			glColor4f(flashr,flashg,flashb,flashamount);
+
+			glBegin(GL_QUADS);
+
+				glVertex3f(0,		0, 	 0.0f);
+
+				glVertex3f(256,	0, 	 0.0f);
+
+				glVertex3f(256,	256, 0.0f);
+
+				glVertex3f(0, 	256, 0.0f);
+
+			glEnd();
+
+			glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
+
+			glPopMatrix();										// Restore The Old Projection Matrix
+
+			glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
+
+			glPopMatrix();										// Restore The Old Projection Matrix
+
+			glEnable(GL_DEPTH_TEST);							// Enables Depth Testing
+
+			glEnable(GL_CULL_FACE);
+
+			glDisable(GL_BLEND);
+
+			glDepthMask(1);
+
+		}	
+
+		if(person[0].skeleton.free>0&&thirdperson!=2){
+
+			glDisable(GL_DEPTH_TEST);							// Disables Depth Testing
+
+			glDisable(GL_CULL_FACE);
+
+			glDisable(GL_LIGHTING);
+
+			glDepthMask(0);
+
+			glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
+
+			glPushMatrix();										// Store The Projection Matrix
+
+			glLoadIdentity();									// Reset The Projection Matrix
+
+			glOrtho(0,screenwidth,0,screenheight,-100,100);						// Set Up An Ortho Screen
+
+			glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
+
+			glPushMatrix();										// Store The Modelview Matrix
+
+			glLoadIdentity();								// Reset The Modelview Matrix
+
+			glScalef(screenwidth,screenheight,1);
+
+			glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+
+			glEnable(GL_BLEND);
+
+			glColor4f(0,0,0,1-person[0].longdead);
+
+			glBegin(GL_QUADS);
+
+				glVertex3f(0,		0, 	 0.0f);
+
+				glVertex3f(256,	0, 	 0.0f);
+
+				glVertex3f(256,	256, 0.0f);
+
+				glVertex3f(0, 	256, 0.0f);
+
+			glEnd();
+
+			glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
+
+			glPopMatrix();										// Restore The Old Projection Matrix
+
+			glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
+
+			glPopMatrix();										// Restore The Old Projection Matrix
+
+			glEnable(GL_DEPTH_TEST);							// Enables Depth Testing
+
+			glEnable(GL_CULL_FACE);
+
+			glDisable(GL_BLEND);
+
+			glDepthMask(1);
+
+		}	
+
+		
+
+		//Text
+
+		glEnable(GL_TEXTURE_2D);
+
+		glColor4f(1,1,1,1);
+
+		static char string[256]="";
+
+		if(!debug){
+
+		if(person[0].whichgun==nogun)sprintf (string, "UNARMED");
+
+		if(person[0].whichgun==knife)sprintf (string, "KNIFE");
+
+		if(person[0].whichgun==assaultrifle)sprintf (string, "ASSAULT RIFLE");
+
+		if(person[0].whichgun==shotgun)sprintf (string, "SHOTGUN");
+
+		if(person[0].whichgun==sniperrifle)sprintf (string, "SNIPER RIFLE");
+
+		if(person[0].whichgun==grenade)sprintf (string, "HAND GRENADE");
+
+		if(person[0].whichgun==handgun1)sprintf (string, "MAGNUM");
+
+		if(person[0].whichgun==handgun2)sprintf (string, "HANDGUN");
+
+		text.glPrint(10,90,string,1,.8,640,480);
+
+		if(person[0].whichgun!=nogun&&person[0].whichgun!=knife&&person[0].whichgun!=grenade){
+
+			glColor4f(0,1,0,1);
+
+			sprintf (string, "Magazines");
+
+			text.glPrint(10,30,string,0,.8,640,480);
+
+			glColor4f(1,1,1,1);
+
+			sprintf (string, "0%d",(int)person[0].reloads[person[0].whichgun]);
+
+			text.glPrint(10,10,string,1,1,640,480);
+
+			if(person[0].ammo>=0){
+
+				glColor4f(0,1,0,1);
+
+				sprintf (string, "Ammo");
+
+				text.glPrint(10,65,string,0,.8,640,480);
+
+				glColor4f(1,1,1,1);
+
+				if(person[0].ammo>=10)sprintf (string, "%d",(int)person[0].ammo);
+
+				if(person[0].ammo<10)sprintf (string, "0%d",(int)person[0].ammo);
+
+				text.glPrint(10,40,string,1,1,640,480);
+
+			}
+
+		}
+
+		if(person[0].whichgun==grenade){
+
+			sprintf (string, "Grenades Left:  %d",(int)person[0].reloads[person[0].whichgun]+1);
+
+			text.glPrint(10,20,string,0,.8,640,480);
+
+		}
+
+		glColor4f(1,1,0,1);
+
+		sprintf (string, "Score");
+
+		text.glPrint(725,575,string,0,.8,640,480);
+
+		glColor4f(1,1,1,1);
+
+		sprintf (string, "%d", score);
+
+		text.glPrint(580,440,string,1,1,640,480);
+
+		
+
+		glColor4f(1,1,0,1);
+
+		sprintf (string, "Time Remaining");
+
+		text.glPrint(50,575,string,0,.8,640,480);
+
+		glColor4f(1,1,1,1);
+
+		if((int)timeremaining%60>=10)sprintf (string, "%d:%d", (int)(timeremaining/60),(int)timeremaining%60);
+
+		if((int)timeremaining%60<10)sprintf (string, "%d:0%d", (int)(timeremaining/60),(int)timeremaining%60);
+
+		text.glPrint(72.5,440,string,1,1,640,480);
+
+		}
+
+		
+
+		if(debug){
+
+		sprintf (string, "The framespersecond is %d out of maximum %d.",(int)framespersecond+1,maxfps);
+
+		text.glPrint(10,30,string,0,.8,screenwidth,screenheight);
+
+		if(enemystate==0)sprintf (string, "Enemies are in random assassination mode.");
+
+		if(enemystate==1)sprintf (string, "Enemies are in passive mode.");
+
+		if(enemystate==2)sprintf (string, "Enemies are in DIE!!!! mode.");
+
+		text.glPrint(10,20,string,0,.8,screenwidth,screenheight);
+
+		sprintf (string, "You have pointlessly shot or beaten %d unarmed civilians.",civkills);
+
+		text.glPrint(10,60,string,0,.8,screenwidth,screenheight);
+
+		sprintf (string, "You have incapacitated %d assassins.",goodkills);
+
+		text.glPrint(10,70,string,0,.8,screenwidth,screenheight);
+
+		sprintf (string, "You have allowed %d successful murders.",badkills);
+
+		text.glPrint(10,80,string,0,.8,screenwidth,screenheight);
+
+		}
+
+		/*
+		sprintf (string, "");
+
+		text.glPrint(10,80,string,0,.8,screenwidth,screenheight);
+		*/	
+
+	}
+
+	return 1;
+}
+
diff --git a/src/GameInitDispose.cpp b/src/GameInitDispose.cpp
new file mode 100644
index 0000000..7f22344
--- /dev/null
+++ b/src/GameInitDispose.cpp
@@ -0,0 +1,4235 @@
+#include <ctype.h>
+#include "Textures.h"
+
+#ifndef OS9 
+#include <time.h>
+#endif
+
+#include "Game.h"	
+
+
+extern unsigned int gSourceID[100];
+
+extern unsigned int gSampleSet[100];
+
+extern Camera camera;
+
+extern Skeleton testskeleton;
+
+extern Sprites sprites;
+
+extern Decals decals;
+
+/*********************> InitGame()<*****/
+
+extern Model skeletonmodels[10];
+
+extern Model gunmodels[10];
+
+extern Costume costume[10];
+
+extern Animation animation[30];
+
+extern int visions;
+
+extern float rad2deg;
+
+extern Fog fog;
+
+extern bool blood;
+
+extern float fogcolorr;
+
+extern float fogcolorg;
+
+extern float fogcolorb;
+
+extern int environment;
+
+extern float precipitationhorz;
+
+extern float precipitationvert;
+
+extern float precipitationdensity;
+
+extern float soundscalefactor;
+
+extern int slomo;
+
+
+
+extern int forwardskey;
+
+extern int backwardskey;
+
+extern int leftkey;
+
+extern int rightkey;
+
+extern int aimkey;
+
+extern int psychicaimkey;
+
+extern int psychickey;
+
+
+
+void LoadSounds(bool musictoggle);
+
+void LoadSounds(bool musictoggle)
+
+{
+	char *pBuffer1;
+
+	long lBuffer1Len;
+
+	ALenum formatBuffer1;
+
+	ALsizei freqBuffer1;
+	
+	Str255 sFileName;
+
+	short fRefNum;
+
+	SInt16 iNumSources, iNumSampleSets;
+
+	// EAX test
+
+	unsigned long ulEAXVal;
+
+	long lGlobalReverb;
+
+	
+
+	// initialize OpenAL
+
+	alutInit(NULL, 0);
+
+	
+
+	
+
+	// load up some audio data...
+
+	// generate ten OpenAL sample sets and two sources
+
+	iNumSources = 37;
+
+	iNumSampleSets = 37;
+
+	alGenSources(iNumSources, &gSourceID[0]);
+
+	alGenBuffers(iNumSampleSets, &gSampleSet[0]);
+
+#ifdef NOOGG	
+	alutLoadWAVFile((char *)":Data:Sounds:underwater.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[visionsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[visionsound], AL_BUFFER, gSampleSet[visionsound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:soulin.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[soulinsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[soulinsound], AL_BUFFER, gSampleSet[soulinsound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:soulout.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[souloutsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[souloutsound], AL_BUFFER, gSampleSet[souloutsound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:footstep1.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[footstepsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[footstepsound], AL_BUFFER, gSampleSet[footstepsound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:footstep2.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[footstepsound+1], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[footstepsound+1], AL_BUFFER, gSampleSet[footstepsound+1]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:footstep3.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[footstepsound+2], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[footstepsound+2], AL_BUFFER, gSampleSet[footstepsound+2]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:footstep4.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[footstepsound+3], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[footstepsound+3], AL_BUFFER, gSampleSet[footstepsound+3]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:footstep5.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[footstepsound+4], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[footstepsound+4], AL_BUFFER, gSampleSet[footstepsound+4]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:bodyland.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[bodylandsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[bodylandsound], AL_BUFFER, gSampleSet[bodylandsound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	alutLoadWAVFile((char *)":Data:Sounds:headland.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[headlandsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[headlandsound], AL_BUFFER, gSampleSet[headlandsound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:sniperrifle.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[riflesound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[riflesound], AL_BUFFER, gSampleSet[riflesound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:BodyHit.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[bodyhitsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[bodyhitsound], AL_BUFFER, gSampleSet[bodyhitsound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	alutLoadWAVFile((char *)":Data:Sounds:WallHit.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[wallhitsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[wallhitsound], AL_BUFFER, gSampleSet[wallhitsound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:machinegun.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[machinegunsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[machinegunsound], AL_BUFFER, gSampleSet[machinegunsound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:Nearbullet.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[nearbulletsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[nearbulletsound], AL_BUFFER, gSampleSet[nearbulletsound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:riflewhack.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[headwhacksound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[headwhacksound], AL_BUFFER, gSampleSet[headwhacksound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	alutLoadWAVFile((char *)":Data:Sounds:headshot.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[headshotsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[headshotsound], AL_BUFFER, gSampleSet[headshotsound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:reload.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[reloadsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[reloadsound], AL_BUFFER, gSampleSet[reloadsound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:click.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[clicksound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[clicksound], AL_BUFFER, gSampleSet[clicksound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:SW.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[pistol1sound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[pistol1sound], AL_BUFFER, gSampleSet[pistol1sound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:glock.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[pistol2sound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[pistol2sound], AL_BUFFER, gSampleSet[pistol2sound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:pinpull.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[pinpullsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[pinpullsound], AL_BUFFER, gSampleSet[pinpullsound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:pinreplace.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[pinreplacesound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[pinreplacesound], AL_BUFFER, gSampleSet[pinreplacesound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:handlerelease.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[grenadethrowsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[grenadethrowsound], AL_BUFFER, gSampleSet[grenadethrowsound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:bounce.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[bouncesound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[bouncesound], AL_BUFFER, gSampleSet[bouncesound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:bounce2.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[bounce2sound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[bounce2sound], AL_BUFFER, gSampleSet[bounce2sound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:explosion.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[explosionsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[explosionsound], AL_BUFFER, gSampleSet[explosionsound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	alutLoadWAVFile((char *)":Data:Sounds:headland.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[bodywhacksound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[bodywhacksound], AL_BUFFER, gSampleSet[bodywhacksound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	alutLoadWAVFile((char *)":Data:Sounds:rain.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[rainsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[rainsound], AL_BUFFER, gSampleSet[rainsound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	alutLoadWAVFile((char *)":Data:Sounds:Lose.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[losesound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[losesound], AL_BUFFER, gSampleSet[losesound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	alutLoadWAVFile((char *)":Data:Sounds:Disguisekill.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[disguisekillsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[disguisekillsound], AL_BUFFER, gSampleSet[disguisekillsound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	alutLoadWAVFile((char *)":Data:Sounds:knifeslash.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[knifeslashsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[knifeslashsound], AL_BUFFER, gSampleSet[knifeslashsound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	alutLoadWAVFile((char *)":Data:Sounds:shotgun.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[shotgunsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[shotgunsound], AL_BUFFER, gSampleSet[shotgunsound]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	if(musictoggle){
+
+	alutLoadWAVFile((char *)":Data:Sounds:mainmenusong.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[mainmenusong], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[mainmenusong], AL_BUFFER, gSampleSet[mainmenusong]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	alutLoadWAVFile((char *)":Data:Sounds:shootsong.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[shootsong], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[shootsong], AL_BUFFER, gSampleSet[shootsong]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	alutLoadWAVFile((char *)":Data:Sounds:zombiesong.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[zombiesong], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[zombiesong], AL_BUFFER, gSampleSet[zombiesong]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	alutLoadWAVFile((char *)":Data:Sounds:knifesong.wav",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[knifesong], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[knifesong], AL_BUFFER, gSampleSet[knifesong]);
+
+	alutUnloadWAV(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	}
+#else
+	LoadOGG_CFH((char *)":Data:Sounds:underwater.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[visionsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[visionsound], AL_BUFFER, gSampleSet[visionsound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:soulin.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[soulinsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[soulinsound], AL_BUFFER, gSampleSet[soulinsound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:soulout.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[souloutsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[souloutsound], AL_BUFFER, gSampleSet[souloutsound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:footstep1.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[footstepsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[footstepsound], AL_BUFFER, gSampleSet[footstepsound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1); 
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:footstep2.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[footstepsound+1], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[footstepsound+1], AL_BUFFER, gSampleSet[footstepsound+1]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:footstep3.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[footstepsound+2], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[footstepsound+2], AL_BUFFER, gSampleSet[footstepsound+2]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:footstep4.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[footstepsound+3], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[footstepsound+3], AL_BUFFER, gSampleSet[footstepsound+3]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:footstep5.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[footstepsound+4], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[footstepsound+4], AL_BUFFER, gSampleSet[footstepsound+4]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:bodyland.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[bodylandsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[bodylandsound], AL_BUFFER, gSampleSet[bodylandsound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	LoadOGG_CFH((char *)":Data:Sounds:headland.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[headlandsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[headlandsound], AL_BUFFER, gSampleSet[headlandsound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:sniperrifle.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[riflesound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[riflesound], AL_BUFFER, gSampleSet[riflesound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:BodyHit.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[bodyhitsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[bodyhitsound], AL_BUFFER, gSampleSet[bodyhitsound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	LoadOGG_CFH((char *)":Data:Sounds:WallHit.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[wallhitsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[wallhitsound], AL_BUFFER, gSampleSet[wallhitsound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:machinegun.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[machinegunsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[machinegunsound], AL_BUFFER, gSampleSet[machinegunsound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:Nearbullet.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[nearbulletsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[nearbulletsound], AL_BUFFER, gSampleSet[nearbulletsound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:riflewhack.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[headwhacksound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[headwhacksound], AL_BUFFER, gSampleSet[headwhacksound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	LoadOGG_CFH((char *)":Data:Sounds:headshot.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[headshotsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[headshotsound], AL_BUFFER, gSampleSet[headshotsound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:reload.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[reloadsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[reloadsound], AL_BUFFER, gSampleSet[reloadsound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:click.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[clicksound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[clicksound], AL_BUFFER, gSampleSet[clicksound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:SW.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[pistol1sound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[pistol1sound], AL_BUFFER, gSampleSet[pistol1sound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:glock.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[pistol2sound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[pistol2sound], AL_BUFFER, gSampleSet[pistol2sound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:pinpull.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[pinpullsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[pinpullsound], AL_BUFFER, gSampleSet[pinpullsound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:pinreplace.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[pinreplacesound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[pinreplacesound], AL_BUFFER, gSampleSet[pinreplacesound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:handlerelease.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[grenadethrowsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[grenadethrowsound], AL_BUFFER, gSampleSet[grenadethrowsound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:bounce.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[bouncesound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[bouncesound], AL_BUFFER, gSampleSet[bouncesound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:bounce2.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[bounce2sound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[bounce2sound], AL_BUFFER, gSampleSet[bounce2sound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:explosion.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[explosionsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[explosionsound], AL_BUFFER, gSampleSet[explosionsound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	
+
+	LoadOGG_CFH((char *)":Data:Sounds:headland.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[bodywhacksound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[bodywhacksound], AL_BUFFER, gSampleSet[bodywhacksound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	LoadOGG_CFH((char *)":Data:Sounds:rain.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[rainsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[rainsound], AL_BUFFER, gSampleSet[rainsound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	LoadOGG_CFH((char *)":Data:Sounds:Lose.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[losesound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[losesound], AL_BUFFER, gSampleSet[losesound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	LoadOGG_CFH((char *)":Data:Sounds:Disguisekill.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[disguisekillsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[disguisekillsound], AL_BUFFER, gSampleSet[disguisekillsound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	LoadOGG_CFH((char *)":Data:Sounds:knifeslash.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[knifeslashsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[knifeslashsound], AL_BUFFER, gSampleSet[knifeslashsound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	LoadOGG_CFH((char *)":Data:Sounds:shotgun.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[shotgunsound], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[shotgunsound], AL_BUFFER, gSampleSet[shotgunsound]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	if(musictoggle){
+
+	LoadOGG_CFH((char *)":Data:Sounds:mainmenusong.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[mainmenusong], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[mainmenusong], AL_BUFFER, gSampleSet[mainmenusong]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	LoadOGG_CFH((char *)":Data:Sounds:shootsong.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[shootsong], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[shootsong], AL_BUFFER, gSampleSet[shootsong]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	LoadOGG_CFH((char *)":Data:Sounds:zombiesong.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[zombiesong], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[zombiesong], AL_BUFFER, gSampleSet[zombiesong]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+
+
+	LoadOGG_CFH((char *)":Data:Sounds:knifesong.ogg",&formatBuffer1, (void **) &pBuffer1,(unsigned int *)&lBuffer1Len,&freqBuffer1);
+
+	alBufferData(gSampleSet[knifesong], formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	alSourcei(gSourceID[knifesong], AL_BUFFER, gSampleSet[knifesong]);
+
+	FreeOGG(formatBuffer1, pBuffer1, lBuffer1Len, freqBuffer1);
+
+	}
+
+
+#endif
+
+
+	float gLoc[3];
+
+	
+
+	gLoc[0]=0;
+
+	gLoc[1]=0;
+
+	gLoc[2]=0;
+
+	
+
+	alSourcefv(gSourceID[visionsound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[visionsound], AL_LOOPING, 1);
+
+	alSourcef(gSourceID[visionsound], AL_MIN_GAIN, 1);
+
+	
+
+	alSourcefv(gSourceID[soulinsound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[soulinsound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[soulinsound], AL_MIN_GAIN, 1);
+
+	
+
+	alSourcefv(gSourceID[souloutsound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[souloutsound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[souloutsound], AL_MIN_GAIN, 1);
+
+	
+
+	for(int i=0;i<5;i++){
+
+		alSourcefv(gSourceID[footstepsound+i], AL_POSITION, gLoc);
+
+		alSourcei(gSourceID[footstepsound+i], AL_LOOPING, 0);
+
+		alSourcef(gSourceID[footstepsound+i], AL_MIN_GAIN, 0);
+
+	}	
+
+	
+
+	alSourcefv(gSourceID[bodylandsound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[bodylandsound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[bodylandsound], AL_MIN_GAIN, 0);
+
+	
+
+	alSourcefv(gSourceID[headlandsound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[headlandsound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[headlandsound], AL_MIN_GAIN, 0);
+
+	
+
+	alSourcefv(gSourceID[riflesound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[riflesound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[riflesound], AL_MIN_GAIN, 0);
+
+	
+
+	alSourcefv(gSourceID[bodyhitsound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[bodyhitsound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[bodyhitsound], AL_MIN_GAIN, .1);
+
+	
+
+	alSourcefv(gSourceID[wallhitsound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[wallhitsound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[wallhitsound], AL_MIN_GAIN, 0);
+
+	alSourcef(gSourceID[wallhitsound], AL_MAX_GAIN, .6);
+
+	
+
+	alSourcefv(gSourceID[machinegunsound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[machinegunsound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[machinegunsound], AL_MIN_GAIN,0);
+
+	
+
+	alSourcefv(gSourceID[nearbulletsound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[nearbulletsound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[nearbulletsound], AL_MIN_GAIN,0);
+
+	
+
+	alSourcefv(gSourceID[headwhacksound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[headwhacksound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[headwhacksound], AL_MIN_GAIN,0);
+
+	
+
+	alSourcefv(gSourceID[headshotsound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[headshotsound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[headshotsound], AL_MIN_GAIN, 0);
+
+	
+
+	alSourcefv(gSourceID[reloadsound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[reloadsound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[reloadsound], AL_MIN_GAIN, 0);
+
+	
+
+	alSourcefv(gSourceID[clicksound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[clicksound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[clicksound], AL_MIN_GAIN, 0);
+
+	
+
+	alSourcefv(gSourceID[pistol1sound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[pistol1sound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[pistol1sound], AL_MIN_GAIN, 0);
+
+	
+
+	alSourcefv(gSourceID[pistol2sound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[pistol2sound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[pistol2sound], AL_MIN_GAIN, 0);
+
+	
+
+	alSourcefv(gSourceID[pinpullsound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[pinpullsound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[pinpullsound], AL_MIN_GAIN,0);
+
+	
+
+	alSourcefv(gSourceID[pinreplacesound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[pinreplacesound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[pinreplacesound], AL_MIN_GAIN,0);
+
+	
+
+	alSourcefv(gSourceID[grenadethrowsound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[grenadethrowsound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[grenadethrowsound], AL_MIN_GAIN,0);
+
+	
+
+	alSourcefv(gSourceID[bouncesound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[bouncesound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[bouncesound], AL_MIN_GAIN,0);
+
+	
+
+	alSourcefv(gSourceID[bounce2sound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[bounce2sound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[bounce2sound], AL_MIN_GAIN,0);
+
+	
+
+	alSourcefv(gSourceID[explosionsound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[explosionsound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[explosionsound], AL_MIN_GAIN,0);
+
+
+
+	alSourcefv(gSourceID[bodywhacksound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[bodywhacksound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[bodywhacksound], AL_MIN_GAIN, 0);
+
+	
+
+	alSourcefv(gSourceID[rainsound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[rainsound], AL_LOOPING, 1);
+
+	alSourcef(gSourceID[rainsound], AL_MIN_GAIN, .3);
+
+	
+
+	alSourcefv(gSourceID[losesound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[losesound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[losesound], AL_MIN_GAIN, 1);
+
+	
+
+	alSourcefv(gSourceID[disguisekillsound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[disguisekillsound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[disguisekillsound], AL_MIN_GAIN, 1);
+
+	
+
+	alSourcefv(gSourceID[knifeslashsound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[knifeslashsound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[knifeslashsound], AL_MIN_GAIN,0);
+
+	
+
+	alSourcefv(gSourceID[shotgunsound], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[shotgunsound], AL_LOOPING, 0);
+
+	alSourcef(gSourceID[shotgunsound], AL_MIN_GAIN, 0);
+
+	
+
+	alSourcefv(gSourceID[knifesong], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[knifesong], AL_LOOPING, 1);
+
+	alSourcef(gSourceID[knifesong], AL_MIN_GAIN, 1);
+
+	
+
+	alSourcefv(gSourceID[mainmenusong], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[mainmenusong], AL_LOOPING, 1);
+
+	alSourcef(gSourceID[mainmenusong], AL_MIN_GAIN, 1);
+
+	
+
+	alSourcefv(gSourceID[zombiesong], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[zombiesong], AL_LOOPING, 1);
+
+	alSourcef(gSourceID[zombiesong], AL_MIN_GAIN, 1);
+
+	
+
+	alSourcefv(gSourceID[shootsong], AL_POSITION, gLoc);
+
+	alSourcei(gSourceID[shootsong], AL_LOOPING, 1);
+
+	alSourcef(gSourceID[shootsong], AL_MIN_GAIN, 1);
+
+	
+
+	
+
+}
+
+
+
+void Game::LoadingScreen(float percent)										
+
+{
+
+	float size=1;
+
+	glLoadIdentity();
+
+	//Clear to black
+
+	glClearColor(0,0,0,1);
+
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+	
+
+	//Background
+
+	
+
+	glDisable(GL_TEXTURE_2D);
+
+	glDisable(GL_DEPTH_TEST);							// Disables Depth Testing
+
+	glDisable(GL_CULL_FACE);
+
+	glDisable(GL_LIGHTING);
+
+	glDepthMask(0);
+
+	glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
+
+	glPushMatrix();										// Store The Projection Matrix
+
+	glLoadIdentity();									// Reset The Projection Matrix
+
+	glOrtho(0,640,0,480,-100,100);						// Set Up An Ortho Screen
+
+	glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
+
+	glPushMatrix();										// Store The Modelview Matrix
+
+	for(int i=19;i>=0;i--){
+
+		glLoadIdentity();								// Reset The Modelview Matrix
+
+		glTranslatef(120-i*1,190-i*1,0);
+
+		glScalef(400+i*2,30+i*2,1);
+
+		glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+
+		glEnable(GL_BLEND);
+
+		if(i)glColor4f(1-(float)i/20-percent/100,1-(float)i/20-percent/100,1-(float)i/20-percent/100,1);
+
+		if(!i)glColor4f(0,0,0,1);
+
+		glBegin(GL_QUADS);
+
+			glVertex3f(0,		0, 	 0.0f);
+
+			glVertex3f(1,	0, 	 0.0f);
+
+			glVertex3f(1,	1, 0.0f);
+
+			glVertex3f(0, 	1, 0.0f);
+
+		glEnd();
+
+	}
+
+	glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
+
+	glPopMatrix();										// Restore The Old Projection Matrix
+
+	glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
+
+	glPopMatrix();										// Restore The Old Projection Matrix
+
+	glDisable(GL_BLEND);
+
+	glDepthMask(1);
+
+	
+
+	//Progress
+
+	
+
+	glDisable(GL_DEPTH_TEST);							// Disables Depth Testing
+
+	glDisable(GL_CULL_FACE);
+
+	glDisable(GL_LIGHTING);
+
+	glDisable(GL_TEXTURE_2D);
+
+	glDepthMask(0);
+
+	glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
+
+	glPushMatrix();										// Store The Projection Matrix
+
+	glLoadIdentity();									// Reset The Projection Matrix
+
+	glOrtho(0,640,0,480,-100,100);						// Set Up An Ortho Screen
+
+	glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
+
+	glPushMatrix();										// Store The Modelview Matrix
+
+	for(int i=19;i>=0;i--){
+
+		glLoadIdentity();								// Reset The Modelview Matrix
+
+		glTranslatef(120,190,0);
+
+		if(4*percent+i*2<400)glScalef(4*percent+i*2,30,1);
+
+		if(4*percent+i*2>=400)glScalef(400,30,1);
+
+		glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+
+		glEnable(GL_BLEND);
+
+		glColor4f(1,0,0,.1);
+
+		glBegin(GL_QUADS);
+
+			glVertex3f(0,		0, 	 0.0f);
+
+			glVertex3f(1,	0, 	 0.0f);
+
+			glVertex3f(1,	1, 0.0f);
+
+			glVertex3f(0, 	1, 0.0f);
+
+		glEnd();
+
+	}
+
+	glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
+
+	glPopMatrix();										// Restore The Old Projection Matrix
+
+	glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
+
+	glPopMatrix();										// Restore The Old Projection Matrix
+
+	glDisable(GL_BLEND);
+
+	glDepthMask(1);
+
+	
+
+	//Text
+
+	
+
+	glEnable(GL_TEXTURE_2D);
+
+	glColor4f(.6-.6*percent/100,0,0,1);
+
+	static char string[256]="";
+
+	sprintf (string, "LOADING...");
+
+	text.glPrint(280,195,string,1,1,640,480);
+
+	
+
+	
+#ifdef OS9 
+	aglSwapBuffers( gOpenGLContext );
+#else
+	SDL_GL_SwapBuffers( );
+#endif
+
+}
+
+
+
+void LoadPersonSpriteTexture(char *fileName, GLuint *textureid);
+
+void LoadPersonSpriteTexture(char *fileName, GLuint *textureid)
+
+{
+	*textureid = loadTexture(fileName);
+	glBindTexture(GL_TEXTURE_2D, *textureid);
+	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+}
+
+
+
+void Game::InitGame()										
+
+{
+
+	//Setup loading screen
+
+	float loadingscreenamount=0;
+
+	float loadingscreenamounttotal=200;
+
+	if(initialized)loadingscreenamounttotal=20;
+
+	
+
+	if(!initialized)LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+	
+
+	//Set up rain and snow
+
+	precipitationhorz=60;
+
+	precipitationvert=40;
+
+	precipitationdensity=25;
+
+	
+
+	//Bodyguard stats
+
+	person[0].playercoords=camera.position;
+
+	person[0].oldplayercoords=person[0].playercoords;
+
+	person[0].type=playertype;
+
+	person[0].existing=1;
+
+	for(int i=0;i<10;i++){
+
+		person[0].reloads[i]=0;
+
+	}
+
+	
+
+	//Level setup
+
+	killedinnocent=0; //Haven't shot any civilians yet...
+
+	
+
+	if(customlevels){ //Load custom levels
+
+		nummissions=1; //Default level in case of load failure
+
+		type=randomshoot_type;
+
+		possiblegun[0]=handgun1;
+
+		possiblegun[1]=handgun2;
+
+		possiblegun[2]=shotgun;
+
+		numpossibleguns=3;
+
+		evilprobability=6;
+
+		person[0].whichgun=knife;
+
+		person[0].reloads[person[0].whichgun]=6;	
+
+		if(!gameinprogress)score=0;
+
+		timeremaining=50;
+
+		difficulty=.8;
+
+		ifstream ipstream("Data/customlevels.txt");
+
+	    if(!ipstream) {
+
+	        customlevels=0;
+
+	    }
+
+		if(ipstream){
+
+			ipstream.ignore(256,'\n');//ignore descriptive text
+
+		    ipstream >> nummissions;
+
+		    for(int j=0;j<mission+1;j++){
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream >> type;
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream >> environment;		
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream >> numpossibleguns;
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream.ignore(256,'\n');
+
+		    for(int i=0;i<numpossibleguns;i++){
+
+		    ipstream >> possiblegun[i];
+
+		    }
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream >> evilprobability;
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream >> person[0].whichgun;
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream >> person[0].reloads[person[0].whichgun];
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream >> timeremaining;
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream >> difficulty;
+
+		    ipstream.ignore(256,'\n');
+
+		    }
+
+		    ipstream.close();
+
+		}
+
+	}
+
+	
+
+	if(!customlevels){ //Setup hardcoded default levels
+
+	if(mission==0){		
+
+		environment=sunny_environment;
+
+		type=randomshoot_type;
+
+		possiblegun[0]=handgun1;
+
+		possiblegun[1]=handgun2;
+
+		possiblegun[2]=shotgun;
+
+		numpossibleguns=3;
+
+		evilprobability=6;
+
+		person[0].whichgun=assaultrifle;
+
+		person[0].reloads[person[0].whichgun]=6;	
+
+		if(!gameinprogress)score=0;
+
+		timeremaining=50;
+
+		difficulty=.6;
+
+	}
+
+	if(mission==1){		
+
+		environment=snowy_environment;
+
+		type=randomshoot_type;
+
+		possiblegun[0]=knife;
+
+		possiblegun[1]=assaultrifle;
+
+		numpossibleguns=2;
+
+		evilprobability=5;
+
+		person[0].whichgun=handgun2;
+
+		person[0].reloads[person[0].whichgun]=3;	
+
+		if(!gameinprogress)score=0;
+
+		timeremaining=40;
+
+		difficulty=.6;
+
+	}
+
+	if(mission==2){		
+
+		environment=foggy_environment;
+
+		type=randomshoot_type;
+
+		possiblegun[0]=sniperrifle;
+
+		numpossibleguns=1;
+
+		evilprobability=5;
+
+		person[0].whichgun=sniperrifle;
+
+		person[0].reloads[person[0].whichgun]=4;	
+
+		if(!gameinprogress)score=0;
+
+		timeremaining=50;
+
+		difficulty=0.9;
+
+	}
+
+	if(mission==3){		
+
+		environment=firey_environment;
+
+		type=zombie_type;
+
+		numpossibleguns=0;
+
+		evilprobability=5;
+
+		person[0].whichgun=shotgun;
+
+		person[0].reloads[person[0].whichgun]=5;	
+
+		if(!gameinprogress)score=0;
+
+		timeremaining=35;
+
+		difficulty=.7;
+
+	}
+
+	if(mission==4){	
+
+		environment=snowy_environment;
+
+		type=randomshoot_type;
+
+		possiblegun[0]=sniperrifle;
+
+		possiblegun[1]=assaultrifle;
+
+		numpossibleguns=2;
+
+		evilprobability=5;
+
+		person[0].whichgun=grenade;
+
+		person[0].reloads[person[0].whichgun]=20;	
+
+		if(!gameinprogress)score=0;
+
+		timeremaining=30;
+
+		difficulty=.5;
+
+	}
+
+	if(mission==5){	
+
+		environment=rainy_environment;
+
+		type=randomshoot_type;
+
+		possiblegun[0]=handgun1;
+
+		possiblegun[1]=shotgun;
+
+		possiblegun[2]=assaultrifle;
+
+		numpossibleguns=3;
+
+		evilprobability=6;
+
+		person[0].whichgun=knife;
+
+		person[0].reloads[person[0].whichgun]=3;	
+
+		if(!gameinprogress)score=0;
+
+		timeremaining=40;
+
+		difficulty=.8;
+
+	}
+
+	if(mission==6){		
+
+		environment=night_environment;
+
+		type=randomshoot_type;
+
+		possiblegun[1]=handgun1;
+
+		possiblegun[2]=handgun2;
+
+		possiblegun[3]=shotgun;
+
+		numpossibleguns=3;
+
+		evilprobability=5;
+
+		person[0].whichgun=handgun1;
+
+		person[0].reloads[person[0].whichgun]=4;	
+
+		if(!gameinprogress)score=0;
+
+		timeremaining=30;
+
+		difficulty=1;
+
+	}
+
+	if(mission==7){		
+
+		environment=firey_environment;
+
+		type=zombie_type;
+
+		person[0].whichgun=assaultrifle;
+
+		person[0].reloads[person[0].whichgun]=5;	
+
+		if(!gameinprogress)score=0;
+
+		timeremaining=30;
+
+		difficulty=1;
+
+	}
+
+	if(mission==8){		
+
+		environment=rainy_environment;
+
+		type=randomshoot_type;
+
+		possiblegun[0]=handgun1;
+
+		possiblegun[1]=handgun2;
+
+		possiblegun[2]=shotgun;
+
+		possiblegun[3]=sniperrifle;
+
+		possiblegun[4]=assaultrifle;
+
+		numpossibleguns=5;
+
+		evilprobability=5;
+
+		person[0].whichgun=nogun;
+
+		person[0].reloads[person[0].whichgun]=3;	
+
+		if(!gameinprogress)score=0;
+
+		timeremaining=40;
+
+		difficulty=.8;
+
+	}
+
+	if(mission==9){		
+
+		environment=snowy_environment;
+
+		type=randomshoot_type;
+
+		possiblegun[0]=knife;
+
+		possiblegun[1]=handgun1;
+
+		possiblegun[2]=handgun2;
+
+		possiblegun[3]=shotgun;
+
+		possiblegun[4]=sniperrifle;
+
+		possiblegun[5]=assaultrifle;
+
+		numpossibleguns=6;
+
+		evilprobability=4;
+
+		person[0].whichgun=handgun1;
+
+		person[0].reloads[person[0].whichgun]=3;	
+
+		if(!gameinprogress)score=0;
+
+		timeremaining=90;
+
+		difficulty=1;
+
+	}
+
+	if(mission==10){		
+
+		environment=night_environment;
+
+		type=randomshoot_type;
+
+		possiblegun[0]=sniperrifle;
+
+		numpossibleguns=1;
+
+		evilprobability=5;
+
+		person[0].whichgun=sniperrifle;
+
+		person[0].reloads[person[0].whichgun]=4;	
+
+		if(!gameinprogress)score=0;
+
+		timeremaining=30;
+
+		difficulty=1.3;
+
+	}
+
+	if(mission==11){		
+
+		environment=sunny_environment;
+
+		type=randomshoot_type;
+
+		possiblegun[0]=knife;
+
+		possiblegun[1]=sniperrifle;
+
+		numpossibleguns=2;
+
+		evilprobability=4;
+
+		person[0].whichgun=knife;
+
+		if(!gameinprogress)score=0;
+
+		timeremaining=30;
+
+		difficulty=1.5;
+
+	}
+
+	if(mission==12){		
+
+		environment=firey_environment;
+
+		type=zombie_type;
+
+		possiblegun[0]=knife;
+
+		possiblegun[1]=sniperrifle;
+
+		person[0].whichgun=handgun2;
+
+		person[0].reloads[person[0].whichgun]=10;	
+
+		if(!gameinprogress)score=0;
+
+		timeremaining=60;
+
+		difficulty=1.5;
+
+	}
+
+	
+
+	nummissions=13;
+
+	}
+
+	
+
+	//Setup fast radian to degree conversion
+
+	rad2deg= 56.54866776;
+
+	visions=0;
+
+	
+
+	//Setup bounding cylinder model
+
+	float boundingscale=3;
+
+	
+
+	if(!initialized){		
+
+		boundingpoints[0]=0;
+
+		boundingpoints[0].z=boundingscale;
+
+		boundingpoints[0].y=0;
+
+		for(int i=1;i<8;i++){
+
+			boundingpoints[i]=DoRotation(boundingpoints[0],0,i*360/7,0);
+
+		}
+
+	}
+
+	civkills=0;
+
+	badkills=0;
+
+	goodkills=0;
+
+	enemystate=2;
+
+	
+
+	if(!initialized){	
+
+		if(!azertykeyboard){
+
+			forwardskey=MAC_W_KEY;
+
+			backwardskey=MAC_S_KEY;
+
+			leftkey=MAC_A_KEY;
+
+			rightkey=MAC_D_KEY;
+
+			aimkey=MAC_Q_KEY;
+
+			psychicaimkey=MAC_E_KEY;
+
+			psychickey=MAC_Z_KEY;
+
+		}
+
+	
+
+		if(azertykeyboard){
+
+			forwardskey=MAC_Z_KEY;
+
+			backwardskey=MAC_S_KEY;
+
+			leftkey=MAC_Q_KEY;
+
+			rightkey=MAC_D_KEY;
+
+			aimkey=MAC_A_KEY;
+
+			psychicaimkey=MAC_E_KEY;
+
+			psychickey=MAC_W_KEY;
+
+		}
+
+	
+
+		soundscalefactor=soundscalefactordefault; //Setup sound falloff
+
+	
+
+		gQuit=false;
+
+		
+
+		//Sounds
+
+		LoadSounds(musictoggle);
+
+		//Play correct song
+
+		if(environment==rainy_environment)alSourcePlay(gSourceID[rainsound]);
+
+		if(environment!=rainy_environment)alSourcePause(gSourceID[rainsound]);
+
+		alSourceStop(gSourceID[whichsong]);
+
+		alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 0);
+
+		alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 0);
+
+		whichsong=mainmenusong;
+
+		alSourceStop(gSourceID[whichsong]);
+
+		alSourcef(gSourceID[whichsong], AL_PITCH, 1);
+
+		alSourcePlay(gSourceID[whichsong]);
+
+		alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 1);
+
+		alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 1);	
+
+	}
+
+	
+
+	loadingscreenamount+=5;
+
+	if(!initialized)LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+	
+
+	//Setup random seed
+
+#ifdef OS9 
+	qd.randSeed = TickCount();
+#else
+	srand(time(NULL));
+#endif
+
+	gamespeed=1;
+
+	
+
+	//Setup camera
+
+	camera.position=0;
+
+	camera.position.x=num_blocks/2*block_spacing+block_spacing/2;
+
+	camera.position.z=num_blocks/2*block_spacing+block_spacing/2;
+
+	camera.position.y=30;
+
+	camera.oldposition=camera.position;
+
+	numpeople=1;
+
+	
+
+	//Setup path to walk around blocks
+
+	path.load((unsigned char *)":Data:Models:path.solid");
+
+	path.Rotate(90,0,0);
+
+	path.Scale(.8,.8,.8);
+
+	path.CalculateNormals();
+
+	
+
+	loadingscreenamount+=5;
+
+	if(!initialized)LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+	
+
+	person[0].speedmult=1.3;
+
+	
+
+	//Add vip	
+
+	person[numpeople].playerrotation=0;
+
+	
+
+	person[numpeople].whichcostume=vipcostume; 
+
+	
+
+	person[numpeople].whichblockx=((person[0].playercoords.x+block_spacing/2)/block_spacing);
+
+	person[numpeople].whichblocky=((person[0].playercoords.x+block_spacing/2)/block_spacing);
+
+	
+
+	person[numpeople].pathnum=-1;
+
+	person[numpeople].oldpathnum=-1;
+
+	person[numpeople].oldoldpathnum=-1;
+
+	person[numpeople].oldoldoldpathnum=-1;
+
+	while(person[numpeople].pathnum<0||person[numpeople].pathnum>=path.vertexNum||person[numpeople].pathnum==1){
+
+		person[numpeople].pathnum=Random()%path.vertexNum;
+
+	}
+
+	person[numpeople].pathtarget.x=path.vertex[person[numpeople].pathnum].x;
+
+	person[numpeople].pathtarget.z=path.vertex[person[numpeople].pathnum].z;			
+
+	person[numpeople].pathsize=.98+float(abs(Random()%20))/400;
+
+	person[numpeople].pathtarget*=person[numpeople].pathsize;
+
+	person[numpeople].pathtarget.x+=person[numpeople].whichblockx*block_spacing;
+
+	person[numpeople].pathtarget.z+=person[numpeople].whichblocky*block_spacing;
+
+	
+
+	
+
+	person[numpeople].playercoords=person[numpeople].pathtarget;
+
+	person[numpeople].oldplayercoords=person[numpeople].playercoords;
+
+	
+
+	person[0].playercoords=person[numpeople].playercoords;
+
+	person[0].playercoords.x+=1;
+
+	person[0].playercoords.z+=1;
+
+	person[0].oldplayercoords=person[0].playercoords;
+
+	
+
+	person[numpeople].skeleton.free=0;
+
+	
+
+	person[numpeople].targetanimation=walkanim;
+
+	person[numpeople].speed=1;
+
+	person[numpeople].existing=0;
+
+	person[numpeople].speedmult=1;
+
+	if(type==zombie_type)person[numpeople].speedmult=.8;
+
+	person[numpeople].health=100;	
+
+	person[numpeople].playerrotation2=0;//20;
+
+	
+
+	person[numpeople].lastdistancevictim=200000;
+
+	
+
+	if(person[numpeople].skeleton.broken)person[numpeople].skeleton.Load((char *)":Data:Skeleton:Basic Figure");
+
+	
+
+	person[numpeople].type=viptype;
+
+	person[numpeople].whichgun=nogun; person[numpeople].aiming=0; person[numpeople].killtarget=-1;
+
+	person[numpeople].existing=1;
+
+	
+
+	citypeoplenum[person[numpeople].whichblockx][person[numpeople].whichblocky]++;
+
+	numpeople++;
+
+	spawndelay=.1;
+
+	
+
+	XYZ vipdistance;
+
+	vipdistance=0;
+
+	vipdistance.x=10000000;
+
+	vipgoal=person[1].playercoords+DoRotation(vipdistance,0,Random()%360,0);
+
+	
+
+	//Setup block models	
+
+	if(!initialized){
+
+		blocks[0].load((unsigned char *)":Data:Models:Block1.solid");
+
+		blocks[0].Rotate(90,0,0);
+
+		blocks[0].Scale(.8,.8,.8);
+
+		blocks[0].CalculateNormals();
+
+		
+
+		blocks[1].load((unsigned char *)":Data:Models:Block2.solid");
+
+		blocks[1].Rotate(90,0,0);
+
+		blocks[1].Scale(.8,.8,.8);
+
+		blocks[1].CalculateNormals();
+
+		
+
+		loadingscreenamount+=5;
+
+		if(!initialized)LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+		
+
+		blocks[2].load((unsigned char *)":Data:Models:Block3.solid");
+
+		blocks[2].Rotate(90,0,0);
+
+		blocks[2].Scale(.8,.8,.8);
+
+		blocks[2].CalculateNormals();
+
+		
+
+		blocks[3].load((unsigned char *)":Data:Models:Block4.solid");
+
+		blocks[3].Rotate(90,0,0);
+
+		blocks[3].Scale(.8,.8,.8);
+
+		blocks[3].CalculateNormals();
+
+		
+
+		loadingscreenamount+=5;
+
+		if(!initialized)LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+	
+
+		sidewalkcollide.load((unsigned char *)":Data:Models:Lowheightcollide.solid");
+
+		sidewalkcollide.Rotate(90,0,0);
+
+		sidewalkcollide.Scale(.8,.8,.8);
+
+		sidewalkcollide.CalculateNormals();
+
+		
+
+		blockwalls[0].load((unsigned char *)":Data:Models:Block1collide.solid");
+
+		blockwalls[0].Rotate(90,0,0);
+
+		blockwalls[0].Scale(.8,.75,.8);
+
+		blockwalls[0].CalculateNormals();
+
+		
+
+		blockwalls[1].load((unsigned char *)":Data:Models:Block2collide.solid");
+
+		blockwalls[1].Rotate(90,0,0);
+
+		blockwalls[1].Scale(.8,.75,.8);
+
+		blockwalls[1].CalculateNormals();
+
+		
+
+		blockwalls[2].load((unsigned char *)":Data:Models:Block3collide.solid");
+
+		blockwalls[2].Rotate(90,0,0);
+
+		blockwalls[2].Scale(.8,.75,.8);
+
+		blockwalls[2].CalculateNormals();
+
+		
+
+		blockwalls[3].load((unsigned char *)":Data:Models:Block4collide.solid");
+
+		blockwalls[3].Rotate(90,0,0);
+
+		blockwalls[3].Scale(.8,.75,.8);
+
+		blockwalls[3].CalculateNormals();
+
+		
+
+		loadingscreenamount+=5;
+
+		if(!initialized)LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+		
+
+		blockroofs[0].load((unsigned char *)":Data:Models:Highblock1collide.solid");
+
+		blockroofs[0].Rotate(90,0,0);
+
+		blockroofs[0].Scale(.8,.8,.8);
+
+		blockroofs[0].CalculateNormals();
+
+		
+
+		blockroofs[1].load((unsigned char *)":Data:Models:Highblock2collide.solid");
+
+		blockroofs[1].Rotate(90,0,0);
+
+		blockroofs[1].Scale(.8,.8,.8);
+
+		blockroofs[1].CalculateNormals();
+
+		
+
+		blockroofs[2].load((unsigned char *)":Data:Models:Highblock3collide.solid");
+
+		blockroofs[2].Rotate(90,0,0);
+
+		blockroofs[2].Scale(.8,.8,.8);
+
+		blockroofs[2].CalculateNormals();
+
+		
+
+		blockroofs[3].load((unsigned char *)":Data:Models:Highblock4collide.solid");
+
+		blockroofs[3].Rotate(90,0,0);
+
+		blockroofs[3].Scale(.8,.8,.8);
+
+		blockroofs[3].CalculateNormals();
+
+		
+
+		blockcollide[0].load((unsigned char *)":Data:Models:block1complete.solid");
+
+		blockcollide[0].Rotate(90,0,0);
+
+		blockcollide[0].Scale(.8,.8,.8);
+
+		blockcollide[0].CalculateNormals();
+
+		
+
+		blockcollide[1].load((unsigned char *)":Data:Models:block2complete.solid");
+
+		blockcollide[1].Rotate(90,0,0);
+
+		blockcollide[1].Scale(.8,.8,.8);
+
+		blockcollide[1].CalculateNormals();
+
+		
+
+		blockcollide[2].load((unsigned char *)":Data:Models:block3complete.solid");
+
+		blockcollide[2].Rotate(90,0,0);
+
+		blockcollide[2].Scale(.8,.8,.8);
+
+		blockcollide[2].CalculateNormals();
+
+		
+
+		blockcollide[3].load((unsigned char *)":Data:Models:block4complete.solid");
+
+		blockcollide[3].Rotate(90,0,0);
+
+		blockcollide[3].Scale(.8,.8,.8);
+
+		blockcollide[3].CalculateNormals();
+
+		
+
+		loadingscreenamount+=5;
+
+		if(!initialized)LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+	
+
+		
+
+		blocksimplecollide[0].load((unsigned char *)":Data:Models:lowsimplecollide1.solid");
+
+		blocksimplecollide[0].Rotate(90,0,0);
+
+		blocksimplecollide[0].Scale(.8,.8,.8);
+
+		blocksimplecollide[0].CalculateNormals();
+
+		
+
+		blocksimplecollide[1].load((unsigned char *)":Data:Models:lowsimplecollide2.solid");
+
+		blocksimplecollide[1].Rotate(90,0,0);
+
+		blocksimplecollide[1].Scale(.8,.8,.8);
+
+		blocksimplecollide[1].CalculateNormals();
+
+		
+
+		blocksimplecollide[2].load((unsigned char *)":Data:Models:lowsimplecollide3.solid");
+
+		blocksimplecollide[2].Rotate(90,0,0);
+
+		blocksimplecollide[2].Scale(.8,.8,.8);
+
+		blocksimplecollide[2].CalculateNormals();
+
+		
+
+		blocksimplecollide[3].load((unsigned char *)":Data:Models:lowsimplecollide4.solid");
+
+		blocksimplecollide[3].Rotate(90,0,0);
+
+		blocksimplecollide[3].Scale(.8,.8,.8);
+
+		blocksimplecollide[3].CalculateNormals();
+
+		
+
+		loadingscreenamount+=5;
+
+		if(!initialized)LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+	
+
+		blockocclude.load((unsigned char *)":Data:Models:blockocclude.solid");
+
+		blockocclude.Rotate(90,0,0);
+
+		blockocclude.Scale(.8,.8,.8);
+
+		blockocclude.CalculateNormals();
+
+
+
+		blocksimple.load((unsigned char *)":Data:Models:blocksimple.solid");
+
+		blocksimple.Rotate(90,0,0);
+
+		blocksimple.Scale(.8,2,.8);
+
+		blocksimple.CalculateNormals();
+
+
+
+		street.load((unsigned char *)":Data:Models:streetsubdivided2.solid");
+
+		street.Rotate(90,0,0);
+
+		street.Scale(.01,.01,.01);
+
+		street.CalculateNormals();
+
+		
+
+		Bigstreet=street;
+
+		Bigstreet.Scale(10000,10000,10000);
+
+		
+
+		loadingscreenamount+=5;
+
+		if(!initialized)LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+	
+
+		path.load((unsigned char *)":Data:Models:path.solid");
+
+		path.Rotate(90,0,0);
+
+		path.Scale(.8,.8,.8);
+
+		path.CalculateNormals();
+
+	
+
+		//Fix block radius
+
+		for(int i=0;i<4;i++){
+
+			blocks[i].boundingspherecenter.x=0;
+
+			blocks[i].boundingspherecenter.z=0;
+
+			blocks[i].boundingsphereradius=0;
+
+			for(int x=0;i<blocks[x].vertexNum;x++){
+
+				if(findDistancefast(blocks[i].boundingspherecenter,blocks[i].vertex[x])>blocks[i].boundingsphereradius)blocks[i].boundingsphereradius=findDistancefast(blocks[i].boundingspherecenter,blocks[i].vertex[x]);
+
+			}
+
+			blocks[i].boundingsphereradius=sqrt(blocks[i].boundingsphereradius);
+
+		}
+
+	}	
+
+	mousesensitivity=1;
+
+	
+
+	//init city block rotations
+
+	for(int i=0;i<num_blocks;i++){
+
+		for(int j=0;j<num_blocks;j++){
+
+			cityrotation[i][j]=Random()%4;
+
+			citytype[i][j]=Random()%4;
+
+			citypeoplenum[i][j]=0;
+
+			if(citytype[i][j]<0)citytype[i][j]=0;
+
+			if(citytype[i][j]>3)citytype[i][j]=3;
+
+		}
+
+	}
+
+
+
+		if(!initialized){
+
+		//Load player model
+
+		skeletonmodels[0].load((unsigned char *)":Data:Models:Head.solid");
+
+		skeletonmodels[0].Rotate(90,0,0);
+
+		skeletonmodels[0].Scale(.02,.02,.02);
+
+		skeletonmodels[0].CalculateNormals();
+
+		
+
+		skeletonmodels[1].load((unsigned char *)":Data:Models:Chest.solid");
+
+		skeletonmodels[1].Rotate(90,0,0);
+
+		skeletonmodels[1].Scale(.02,.02,.02);
+
+		skeletonmodels[1].CalculateNormals();
+
+		
+
+		skeletonmodels[2].load((unsigned char *)":Data:Models:Abdomen.solid");
+
+		skeletonmodels[2].Rotate(90,0,0);
+
+		skeletonmodels[2].Scale(.02,.02,.02);
+
+		skeletonmodels[2].CalculateNormals();
+
+		
+
+		skeletonmodels[3].load((unsigned char *)":Data:Models:Upper arm.solid");
+
+		skeletonmodels[3].Rotate(90,0,0);
+
+		skeletonmodels[3].Scale(.02,.02,.02);
+
+		skeletonmodels[3].CalculateNormals();
+
+		
+
+		skeletonmodels[4].load((unsigned char *)":Data:Models:Lower arm.solid");
+
+		skeletonmodels[4].Rotate(90,0,0);
+
+		skeletonmodels[4].Scale(.02,.02,.02);
+
+		skeletonmodels[4].CalculateNormals();
+
+		
+
+		skeletonmodels[5].load((unsigned char *)":Data:Models:Hand.solid");
+
+		skeletonmodels[5].Rotate(90,0,0);
+
+		skeletonmodels[5].Scale(.02,.02,.02);
+
+		skeletonmodels[5].CalculateNormals();
+
+		
+
+		skeletonmodels[6].load((unsigned char *)":Data:Models:Upper leg.solid");
+
+		skeletonmodels[6].Rotate(90,0,0);
+
+		skeletonmodels[6].Scale(.02,.02,.02);
+
+		skeletonmodels[6].CalculateNormals();
+
+		
+
+		skeletonmodels[7].load((unsigned char *)":Data:Models:Lower leg.solid");
+
+		skeletonmodels[7].Rotate(90,0,0);
+
+		skeletonmodels[7].Scale(.02,.02,.02);
+
+		skeletonmodels[7].CalculateNormals();
+
+		
+
+		skeletonmodels[8].load((unsigned char *)":Data:Models:Foot.solid");
+
+		skeletonmodels[8].Rotate(90,0,0);
+
+		skeletonmodels[8].Scale(.02,.02,.02);
+
+		skeletonmodels[8].CalculateNormals();
+
+		
+
+		skeletonmodels[9].load((unsigned char *)":Data:Models:Shades.solid");
+
+		skeletonmodels[9].Rotate(90,0,0);
+
+		skeletonmodels[9].Scale(.02,.02,.02);
+
+		skeletonmodels[9].CalculateNormals();
+
+		
+
+		//Load gun models
+
+		loadingscreenamount+=5;
+
+		if(!initialized)LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+	
+
+		gunmodels[sniperriflemodel].load((unsigned char *)":Data:Models:sniperrifle.solid");
+
+		gunmodels[sniperriflemodel].Rotate(0,0,90);
+
+		gunmodels[sniperriflemodel].Scale(.001,.001,.001);
+
+		gunmodels[sniperriflemodel].CalculateNormals();
+
+		
+
+		gunmodels[assaultriflemodel].load((unsigned char *)":Data:Models:assaultrifle.solid");
+
+		gunmodels[assaultriflemodel].Rotate(0,0,90);
+
+		gunmodels[assaultriflemodel].Scale(.01,.01,.01);
+
+		gunmodels[assaultriflemodel].CalculateNormals();
+
+		
+
+		gunmodels[handgunbasemodel].load((unsigned char *)":Data:Models:Handgunbase.solid");
+
+		gunmodels[handgunbasemodel].Rotate(0,0,90);
+
+		gunmodels[handgunbasemodel].Rotate(180,0,0);
+
+		gunmodels[handgunbasemodel].Scale(.014,.014,.014);
+
+		gunmodels[handgunbasemodel].CalculateNormals();
+
+		gunmodels[handgunbasemodel].MultColor(.6);
+
+		loadingscreenamount+=5;
+
+		if(!initialized)LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+	
+
+		gunmodels[handgunslidemodel].load((unsigned char *)":Data:Models:Handgunslide.solid");
+
+		gunmodels[handgunslidemodel].Rotate(0,0,90);
+
+		gunmodels[handgunslidemodel].Rotate(180,0,0);
+
+		gunmodels[handgunslidemodel].Scale(.014,.014,.014);
+
+		gunmodels[handgunslidemodel].CalculateNormals();
+
+		gunmodels[handgunslidemodel].MultColor(.6);
+
+		
+
+		gunmodels[handgun2basemodel].load((unsigned char *)":Data:Models:glockbase.solid");
+
+		gunmodels[handgun2basemodel].Rotate(0,0,90);
+
+		gunmodels[handgun2basemodel].Rotate(180,0,0);
+
+		gunmodels[handgun2basemodel].Scale(.014,.014,.014);
+
+		gunmodels[handgun2basemodel].CalculateNormals();
+
+		gunmodels[handgun2basemodel].MultColor(.6);
+
+		
+
+		gunmodels[handgun2slidemodel].load((unsigned char *)":Data:Models:glockslide.solid");
+
+		gunmodels[handgun2slidemodel].Rotate(0,0,90);
+
+		gunmodels[handgun2slidemodel].Rotate(180,0,0);
+
+		gunmodels[handgun2slidemodel].Scale(.014,.014,.014);
+
+		gunmodels[handgun2slidemodel].CalculateNormals();
+
+		gunmodels[handgun2slidemodel].MultColor(.6);
+
+		loadingscreenamount+=5;
+
+		if(!initialized)LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+	
+
+		gunmodels[grenadebasemodel].load((unsigned char *)":Data:Models:grenadebase.solid");
+
+		gunmodels[grenadebasemodel].Rotate(0,0,90);
+
+		gunmodels[grenadebasemodel].Rotate(180,0,0);
+
+		gunmodels[grenadebasemodel].Scale(.014,.014,.014);
+
+		gunmodels[grenadebasemodel].CalculateNormals();
+
+		
+
+		gunmodels[grenadepinmodel].load((unsigned char *)":Data:Models:grenadepin.solid");
+
+		gunmodels[grenadepinmodel].Rotate(0,0,90);
+
+		gunmodels[grenadepinmodel].Rotate(180,0,0);
+
+		gunmodels[grenadepinmodel].Scale(.014,.014,.014);
+
+		gunmodels[grenadepinmodel].CalculateNormals();
+
+		
+
+		gunmodels[grenadespoonmodel].load((unsigned char *)":Data:Models:grenadespoon.solid");
+
+		gunmodels[grenadespoonmodel].Rotate(0,0,90);
+
+		gunmodels[grenadespoonmodel].Rotate(180,0,0);
+
+		gunmodels[grenadespoonmodel].Scale(.014,.014,.014);
+
+		gunmodels[grenadespoonmodel].CalculateNormals();
+
+		
+
+		gunmodels[knifemodel].load((unsigned char *)":Data:Models:Knife.solid");
+
+		gunmodels[knifemodel].Rotate(0,0,90);
+
+		gunmodels[knifemodel].Rotate(180,0,0);
+
+		gunmodels[knifemodel].Scale(.014,.014,.014);
+
+		gunmodels[knifemodel].CalculateNormals();
+
+		
+
+		gunmodels[shotgunmodel].load((unsigned char *)":Data:Models:shotgun.solid");
+
+		gunmodels[shotgunmodel].Rotate(0,0,90);
+
+		gunmodels[shotgunmodel].Scale(.001,.001,.001);
+
+		gunmodels[shotgunmodel].CalculateNormals();
+
+		gunmodels[shotgunmodel].MultColor(.6);
+
+		}
+
+		
+
+		loadingscreenamount+=5;
+
+		if(!initialized)LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+	
+
+		//Setup costumes
+
+		float headcolor[3];
+
+		float footcolor[3];
+
+		float handcolor[3];
+
+		float topcolor[3];
+
+		float bottomcolor[3];
+
+		//Police
+
+		headcolor[0]=(float)240/255;
+
+		headcolor[1]=(float)183/255;
+
+		headcolor[2]=(float)132/255;
+
+		
+
+		footcolor[0]=(float)119/255;
+
+		footcolor[1]=(float)68/255;
+
+		footcolor[2]=(float)18/255;
+
+		
+
+		handcolor[0]=(float)240/255;
+
+		handcolor[1]=(float)183/255;
+
+		handcolor[2]=(float)132/255;
+
+		
+
+		topcolor[0]=(float)14/255;
+
+		topcolor[1]=(float)18/255;
+
+		topcolor[2]=(float)195/255;
+
+		
+
+		bottomcolor[0]=(float)14/255;
+
+		bottomcolor[1]=(float)18/255;
+
+		bottomcolor[2]=(float)195/255;
+
+		
+
+		//Greenish skin if zombies
+
+		if(type==zombie_type){
+
+			headcolor[0]=(float)223/255;
+
+			headcolor[1]=(float)243/255;
+
+			headcolor[2]=(float)197/255;
+
+			
+
+			handcolor[0]=(float)223/255;
+
+			handcolor[1]=(float)243/255;
+
+			handcolor[2]=(float)197/255;
+
+		}
+
+		
+
+		costume[policecostume].headcolor[0]=headcolor[0];
+
+		costume[policecostume].headcolor[1]=headcolor[1];
+
+		costume[policecostume].headcolor[2]=headcolor[2];
+
+		
+
+		costume[policecostume].handcolor[0]=handcolor[0];
+
+		costume[policecostume].handcolor[1]=handcolor[1];
+
+		costume[policecostume].handcolor[2]=handcolor[2];
+
+		
+
+		costume[policecostume].chestcolor[0]=topcolor[0];
+
+		costume[policecostume].chestcolor[1]=topcolor[1];
+
+		costume[policecostume].chestcolor[2]=topcolor[2];
+
+		
+
+		costume[policecostume].abdomencolor[0]=topcolor[0];
+
+		costume[policecostume].abdomencolor[1]=topcolor[1];
+
+		costume[policecostume].abdomencolor[2]=topcolor[2];
+
+		
+
+		costume[policecostume].upperarmcolor[0]=topcolor[0];
+
+		costume[policecostume].upperarmcolor[1]=topcolor[1];
+
+		costume[policecostume].upperarmcolor[2]=topcolor[2];
+
+		
+
+		costume[policecostume].lowerarmcolor[0]=topcolor[0];
+
+		costume[policecostume].lowerarmcolor[1]=topcolor[1];
+
+		costume[policecostume].lowerarmcolor[2]=topcolor[2];
+
+		
+
+		costume[policecostume].upperlegcolor[0]=bottomcolor[0];
+
+		costume[policecostume].upperlegcolor[1]=bottomcolor[1];
+
+		costume[policecostume].upperlegcolor[2]=bottomcolor[2];
+
+		
+
+		costume[policecostume].lowerlegcolor[0]=bottomcolor[0];
+
+		costume[policecostume].lowerlegcolor[1]=bottomcolor[1];
+
+		costume[policecostume].lowerlegcolor[2]=bottomcolor[2];
+
+		
+
+		costume[policecostume].footcolor[0]=footcolor[0];
+
+		costume[policecostume].footcolor[1]=footcolor[1];
+
+		costume[policecostume].footcolor[2]=footcolor[2];
+
+		
+
+		//casual
+
+		topcolor[0]=(float)14/255;
+
+		topcolor[1]=(float)200/255;
+
+		topcolor[2]=(float)30/255;
+
+		
+
+		bottomcolor[0]=(float)14/255;
+
+		bottomcolor[1]=(float)18/255;
+
+		bottomcolor[2]=(float)195/255;
+
+		
+
+		costume[casualcostumes].headcolor[0]=headcolor[0];
+
+		costume[casualcostumes].headcolor[1]=headcolor[1];
+
+		costume[casualcostumes].headcolor[2]=headcolor[2];
+
+		
+
+		costume[casualcostumes].handcolor[0]=handcolor[0];
+
+		costume[casualcostumes].handcolor[1]=handcolor[1];
+
+		costume[casualcostumes].handcolor[2]=handcolor[2];
+
+		
+
+		costume[casualcostumes].chestcolor[0]=topcolor[0];
+
+		costume[casualcostumes].chestcolor[1]=topcolor[1];
+
+		costume[casualcostumes].chestcolor[2]=topcolor[2];
+
+		
+
+		costume[casualcostumes].abdomencolor[0]=topcolor[0];
+
+		costume[casualcostumes].abdomencolor[1]=topcolor[1];
+
+		costume[casualcostumes].abdomencolor[2]=topcolor[2];
+
+		
+
+		costume[casualcostumes].upperarmcolor[0]=topcolor[0];
+
+		costume[casualcostumes].upperarmcolor[1]=topcolor[1];
+
+		costume[casualcostumes].upperarmcolor[2]=topcolor[2];
+
+		
+
+		costume[casualcostumes].lowerarmcolor[0]=handcolor[0];
+
+		costume[casualcostumes].lowerarmcolor[1]=handcolor[1];
+
+		costume[casualcostumes].lowerarmcolor[2]=handcolor[2];
+
+		
+
+		costume[casualcostumes].upperlegcolor[0]=bottomcolor[0];
+
+		costume[casualcostumes].upperlegcolor[1]=bottomcolor[1];
+
+		costume[casualcostumes].upperlegcolor[2]=bottomcolor[2];
+
+		
+
+		costume[casualcostumes].lowerlegcolor[0]=bottomcolor[0];
+
+		costume[casualcostumes].lowerlegcolor[1]=bottomcolor[1];
+
+		costume[casualcostumes].lowerlegcolor[2]=bottomcolor[2];
+
+		
+
+		costume[casualcostumes].footcolor[0]=footcolor[0];
+
+		costume[casualcostumes].footcolor[1]=footcolor[1];
+
+		costume[casualcostumes].footcolor[2]=footcolor[2];
+
+		
+
+		//casual 2
+
+		topcolor[0]=(float)140/255;
+
+		topcolor[1]=(float)55/255;
+
+		topcolor[2]=(float)4/255;
+
+		
+
+		bottomcolor[0]=(float)14/255;
+
+		bottomcolor[1]=(float)18/255;
+
+		bottomcolor[2]=(float)135/255;
+
+		
+
+		costume[casualcostumes+1].headcolor[0]=headcolor[0];
+
+		costume[casualcostumes+1].headcolor[1]=headcolor[1];
+
+		costume[casualcostumes+1].headcolor[2]=headcolor[2];
+
+		
+
+		costume[casualcostumes+1].handcolor[0]=handcolor[0];
+
+		costume[casualcostumes+1].handcolor[1]=handcolor[1];
+
+		costume[casualcostumes+1].handcolor[2]=handcolor[2];
+
+		
+
+		costume[casualcostumes+1].chestcolor[0]=topcolor[0];
+
+		costume[casualcostumes+1].chestcolor[1]=topcolor[1];
+
+		costume[casualcostumes+1].chestcolor[2]=topcolor[2];
+
+		
+
+		costume[casualcostumes+1].abdomencolor[0]=topcolor[0];
+
+		costume[casualcostumes+1].abdomencolor[1]=topcolor[1];
+
+		costume[casualcostumes+1].abdomencolor[2]=topcolor[2];
+
+		
+
+		costume[casualcostumes+1].upperarmcolor[0]=topcolor[0];
+
+		costume[casualcostumes+1].upperarmcolor[1]=topcolor[1];
+
+		costume[casualcostumes+1].upperarmcolor[2]=topcolor[2];
+
+		
+
+		costume[casualcostumes+1].lowerarmcolor[0]=topcolor[0];
+
+		costume[casualcostumes+1].lowerarmcolor[1]=topcolor[1];
+
+		costume[casualcostumes+1].lowerarmcolor[2]=topcolor[2];
+
+		
+
+		costume[casualcostumes+1].upperlegcolor[0]=bottomcolor[0];
+
+		costume[casualcostumes+1].upperlegcolor[1]=bottomcolor[1];
+
+		costume[casualcostumes+1].upperlegcolor[2]=bottomcolor[2];
+
+		
+
+		costume[casualcostumes+1].lowerlegcolor[0]=bottomcolor[0];
+
+		costume[casualcostumes+1].lowerlegcolor[1]=bottomcolor[1];
+
+		costume[casualcostumes+1].lowerlegcolor[2]=bottomcolor[2];
+
+		
+
+		costume[casualcostumes+1].footcolor[0]=footcolor[0];
+
+		costume[casualcostumes+1].footcolor[1]=footcolor[1];
+
+		costume[casualcostumes+1].footcolor[2]=footcolor[2];
+
+		
+
+		//casual 3
+
+		topcolor[0]=(float)134/255;
+
+		topcolor[1]=(float)80/255;
+
+		topcolor[2]=(float)3/255;
+
+		
+
+		bottomcolor[0]=(float)30/255;
+
+		bottomcolor[1]=(float)30/255;
+
+		bottomcolor[2]=(float)30/255;
+
+		
+
+		footcolor[0]=(float)20/255;
+
+		footcolor[1]=(float)20/255;
+
+		footcolor[2]=(float)20/255;
+
+		
+
+		
+
+		costume[casualcostumes+2].headcolor[0]=headcolor[0];
+
+		costume[casualcostumes+2].headcolor[1]=headcolor[1];
+
+		costume[casualcostumes+2].headcolor[2]=headcolor[2];
+
+		
+
+		costume[casualcostumes+2].handcolor[0]=handcolor[0];
+
+		costume[casualcostumes+2].handcolor[1]=handcolor[1];
+
+		costume[casualcostumes+2].handcolor[2]=handcolor[2];
+
+		
+
+		costume[casualcostumes+2].chestcolor[0]=topcolor[0];
+
+		costume[casualcostumes+2].chestcolor[1]=topcolor[1];
+
+		costume[casualcostumes+2].chestcolor[2]=topcolor[2];
+
+		
+
+		costume[casualcostumes+2].abdomencolor[0]=topcolor[0];
+
+		costume[casualcostumes+2].abdomencolor[1]=topcolor[1];
+
+		costume[casualcostumes+2].abdomencolor[2]=topcolor[2];
+
+		
+
+		costume[casualcostumes+2].upperarmcolor[0]=topcolor[0];
+
+		costume[casualcostumes+2].upperarmcolor[1]=topcolor[1];
+
+		costume[casualcostumes+2].upperarmcolor[2]=topcolor[2];
+
+		
+
+		costume[casualcostumes+2].lowerarmcolor[0]=topcolor[0];
+
+		costume[casualcostumes+2].lowerarmcolor[1]=topcolor[1];
+
+		costume[casualcostumes+2].lowerarmcolor[2]=topcolor[2];
+
+		
+
+		costume[casualcostumes+2].upperlegcolor[0]=bottomcolor[0];
+
+		costume[casualcostumes+2].upperlegcolor[1]=bottomcolor[1];
+
+		costume[casualcostumes+2].upperlegcolor[2]=bottomcolor[2];
+
+		
+
+		costume[casualcostumes+2].lowerlegcolor[0]=bottomcolor[0];
+
+		costume[casualcostumes+2].lowerlegcolor[1]=bottomcolor[1];
+
+		costume[casualcostumes+2].lowerlegcolor[2]=bottomcolor[2];
+
+		
+
+		costume[casualcostumes+2].footcolor[0]=footcolor[0];
+
+		costume[casualcostumes+2].footcolor[1]=footcolor[1];
+
+		costume[casualcostumes+2].footcolor[2]=footcolor[2];
+
+		
+
+		//casual 4
+
+		topcolor[0]=(float)228/255;
+
+		topcolor[1]=(float)220/255;
+
+		topcolor[2]=(float)0/255;
+
+		
+
+		bottomcolor[0]=(float)20/255;
+
+		bottomcolor[1]=(float)20/255;
+
+		bottomcolor[2]=(float)20/255;
+
+		
+
+		footcolor[0]=(float)119/255;
+
+		footcolor[1]=(float)68/255;
+
+		footcolor[2]=(float)18/255;
+
+		
+
+		costume[casualcostumes+3].headcolor[0]=headcolor[0];
+
+		costume[casualcostumes+3].headcolor[1]=headcolor[1];
+
+		costume[casualcostumes+3].headcolor[2]=headcolor[2];
+
+		
+
+		costume[casualcostumes+3].handcolor[0]=handcolor[0];
+
+		costume[casualcostumes+3].handcolor[1]=handcolor[1];
+
+		costume[casualcostumes+3].handcolor[2]=handcolor[2];
+
+		
+
+		costume[casualcostumes+3].chestcolor[0]=topcolor[0];
+
+		costume[casualcostumes+3].chestcolor[1]=topcolor[1];
+
+		costume[casualcostumes+3].chestcolor[2]=topcolor[2];
+
+		
+
+		costume[casualcostumes+3].abdomencolor[0]=topcolor[0];
+
+		costume[casualcostumes+3].abdomencolor[1]=topcolor[1];
+
+		costume[casualcostumes+3].abdomencolor[2]=topcolor[2];
+
+		
+
+		costume[casualcostumes+3].upperarmcolor[0]=topcolor[0];
+
+		costume[casualcostumes+3].upperarmcolor[1]=topcolor[1];
+
+		costume[casualcostumes+3].upperarmcolor[2]=topcolor[2];
+
+		
+
+		costume[casualcostumes+3].lowerarmcolor[0]=handcolor[0];
+
+		costume[casualcostumes+3].lowerarmcolor[1]=handcolor[1];
+
+		costume[casualcostumes+3].lowerarmcolor[2]=handcolor[2];
+
+		
+
+		costume[casualcostumes+3].upperlegcolor[0]=bottomcolor[0];
+
+		costume[casualcostumes+3].upperlegcolor[1]=bottomcolor[1];
+
+		costume[casualcostumes+3].upperlegcolor[2]=bottomcolor[2];
+
+		
+
+		costume[casualcostumes+3].lowerlegcolor[0]=bottomcolor[0];
+
+		costume[casualcostumes+3].lowerlegcolor[1]=bottomcolor[1];
+
+		costume[casualcostumes+3].lowerlegcolor[2]=bottomcolor[2];
+
+		
+
+		costume[casualcostumes+3].footcolor[0]=footcolor[0];
+
+		costume[casualcostumes+3].footcolor[1]=footcolor[1];
+
+		costume[casualcostumes+3].footcolor[2]=footcolor[2];
+
+	
+
+		if(!initialized){
+
+		//vip
+
+		topcolor[0]=(float)235/255;
+
+		topcolor[1]=(float)235/255;
+
+		topcolor[2]=(float)235/255;
+
+		
+
+		bottomcolor[0]=(float)200/255;
+
+		bottomcolor[1]=(float)200/255;
+
+		bottomcolor[2]=(float)200/255;
+
+		
+
+		footcolor[0]=(float)119/255;
+
+		footcolor[1]=(float)68/255;
+
+		footcolor[2]=(float)18/255;
+
+		
+
+		headcolor[0]=(float)240/255;
+
+		headcolor[1]=(float)183/255;
+
+		headcolor[2]=(float)132/255;
+
+		
+
+		footcolor[0]=(float)119/255;
+
+		footcolor[1]=(float)68/255;
+
+		footcolor[2]=(float)18/255;
+
+		
+
+		handcolor[0]=(float)240/255;
+
+		handcolor[1]=(float)183/255;
+
+		handcolor[2]=(float)132/255;
+
+		
+
+		costume[vipcostume].headcolor[0]=headcolor[0];
+
+		costume[vipcostume].headcolor[1]=headcolor[1];
+
+		costume[vipcostume].headcolor[2]=headcolor[2];
+
+		
+
+		costume[vipcostume].handcolor[0]=handcolor[0];
+
+		costume[vipcostume].handcolor[1]=handcolor[1];
+
+		costume[vipcostume].handcolor[2]=handcolor[2];
+
+		
+
+		costume[vipcostume].chestcolor[0]=topcolor[0];
+
+		costume[vipcostume].chestcolor[1]=topcolor[1];
+
+		costume[vipcostume].chestcolor[2]=topcolor[2];
+
+		
+
+		costume[vipcostume].abdomencolor[0]=topcolor[0];
+
+		costume[vipcostume].abdomencolor[1]=topcolor[1];
+
+		costume[vipcostume].abdomencolor[2]=topcolor[2];
+
+		
+
+		costume[vipcostume].upperarmcolor[0]=topcolor[0];
+
+		costume[vipcostume].upperarmcolor[1]=topcolor[1];
+
+		costume[vipcostume].upperarmcolor[2]=topcolor[2];
+
+		
+
+		costume[vipcostume].lowerarmcolor[0]=topcolor[0];
+
+		costume[vipcostume].lowerarmcolor[1]=topcolor[1];
+
+		costume[vipcostume].lowerarmcolor[2]=topcolor[2];
+
+		
+
+		costume[vipcostume].upperlegcolor[0]=bottomcolor[0];
+
+		costume[vipcostume].upperlegcolor[1]=bottomcolor[1];
+
+		costume[vipcostume].upperlegcolor[2]=bottomcolor[2];
+
+		
+
+		costume[vipcostume].lowerlegcolor[0]=bottomcolor[0];
+
+		costume[vipcostume].lowerlegcolor[1]=bottomcolor[1];
+
+		costume[vipcostume].lowerlegcolor[2]=bottomcolor[2];
+
+		
+
+		costume[vipcostume].footcolor[0]=footcolor[0];
+
+		costume[vipcostume].footcolor[1]=footcolor[1];
+
+		costume[vipcostume].footcolor[2]=footcolor[2];
+
+		
+
+		//Bodyguard
+
+		topcolor[0]=(float)50/255;
+
+		topcolor[1]=(float)50/255;
+
+		topcolor[2]=(float)50/255;
+
+		
+
+		bottomcolor[0]=(float)30/255;
+
+		bottomcolor[1]=(float)30/255;
+
+		bottomcolor[2]=(float)30/255;
+
+		
+
+		footcolor[0]=(float)20/255;
+
+		footcolor[1]=(float)20/255;
+
+		footcolor[2]=(float)20/255;
+
+		
+
+		costume[bodyguardcostume].headcolor[0]=headcolor[0];
+
+		costume[bodyguardcostume].headcolor[1]=headcolor[1];
+
+		costume[bodyguardcostume].headcolor[2]=headcolor[2];
+
+		
+
+		costume[bodyguardcostume].handcolor[0]=handcolor[0];
+
+		costume[bodyguardcostume].handcolor[1]=handcolor[1];
+
+		costume[bodyguardcostume].handcolor[2]=handcolor[2];
+
+		
+
+		costume[bodyguardcostume].chestcolor[0]=topcolor[0];
+
+		costume[bodyguardcostume].chestcolor[1]=topcolor[1];
+
+		costume[bodyguardcostume].chestcolor[2]=topcolor[2];
+
+		
+
+		costume[bodyguardcostume].abdomencolor[0]=topcolor[0];
+
+		costume[bodyguardcostume].abdomencolor[1]=topcolor[1];
+
+		costume[bodyguardcostume].abdomencolor[2]=topcolor[2];
+
+		
+
+		costume[bodyguardcostume].upperarmcolor[0]=topcolor[0];
+
+		costume[bodyguardcostume].upperarmcolor[1]=topcolor[1];
+
+		costume[bodyguardcostume].upperarmcolor[2]=topcolor[2];
+
+		
+
+		costume[bodyguardcostume].lowerarmcolor[0]=topcolor[0];
+
+		costume[bodyguardcostume].lowerarmcolor[1]=topcolor[1];
+
+		costume[bodyguardcostume].lowerarmcolor[2]=topcolor[2];
+
+		
+
+		costume[bodyguardcostume].upperlegcolor[0]=bottomcolor[0];
+
+		costume[bodyguardcostume].upperlegcolor[1]=bottomcolor[1];
+
+		costume[bodyguardcostume].upperlegcolor[2]=bottomcolor[2];
+
+		
+
+		costume[bodyguardcostume].lowerlegcolor[0]=bottomcolor[0];
+
+		costume[bodyguardcostume].lowerlegcolor[1]=bottomcolor[1];
+
+		costume[bodyguardcostume].lowerlegcolor[2]=bottomcolor[2];
+
+		
+
+		costume[bodyguardcostume].footcolor[0]=footcolor[0];
+
+		costume[bodyguardcostume].footcolor[1]=footcolor[1];
+
+		costume[bodyguardcostume].footcolor[2]=footcolor[2];
+
+		
+
+		//Load animations
+
+		loadingscreenamount+=5;
+
+		if(!initialized)LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+	
+
+		testskeleton.Load((char *)":Data:Skeleton:Basic Figure");
+
+		animation[idleanim].Load((char *)":Data:Animations:Breathe");
+
+		animation[joganim].Load((char *)":Data:Animations:Run");
+
+		animation[pistolaimanim].Load((char *)":Data:Animations:PistolAim");
+
+		loadingscreenamount+=5;
+
+		if(!initialized)LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+		animation[walkanim].Load((char *)":Data:Animations:Walk");
+
+		animation[rifleholdanim].Load((char *)":Data:Animations:Riflehold");
+
+		animation[rifleaimanim].Load((char *)":Data:Animations:Rifleaim");
+
+		animation[assaultrifleaimanim].Load((char *)":Data:Animations:AssaultRifleaim");
+
+		animation[crouchanim].Load((char *)":Data:Animations:Crouch");
+
+		loadingscreenamount+=5;
+
+		if(!initialized)LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+		animation[headpainanim].Load((char *)":Data:Animations:Headshot");
+
+		animation[chestpainanim].Load((char *)":Data:Animations:Chestshot");
+
+		animation[stomachpainanim].Load((char *)":Data:Animations:Stomachshot");
+
+		animation[rightarmpainanim].Load((char *)":Data:Animations:Rightarmshot");
+
+		animation[leftarmpainanim].Load((char *)":Data:Animations:Leftarmshot");
+
+		loadingscreenamount+=5;
+
+		if(!initialized)LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+		animation[rightlegpainanim].Load((char *)":Data:Animations:Rightlegshot");
+
+		animation[leftlegpainanim].Load((char *)":Data:Animations:Leftlegshot");
+
+		animation[riflehitanim].Load((char *)":Data:Animations:Riflehit");
+
+		animation[grenadeaimanim].Load((char *)":Data:Animations:grenadeaim");
+
+		animation[grenadechargeanim].Load((char *)":Data:Animations:grenadecharge");
+
+		loadingscreenamount+=5;
+
+		if(!initialized)LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+		animation[grenadethrowanim].Load((char *)":Data:Animations:grenadethrow");
+
+		animation[zombieeatanim].Load((char *)":Data:Animations:Zombiemunch");
+
+		animation[zombiejoganim].Load((char *)":Data:Animations:ZombieRun");
+
+		animation[zombiewalkanim].Load((char *)":Data:Animations:Zombiewalk");
+
+		loadingscreenamount+=5;
+
+		if(!initialized)LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+		animation[getupfrontanim].Load((char *)":Data:Animations:Getupfromfront");
+
+		animation[getupbackanim].Load((char *)":Data:Animations:Getupfromback",180);
+
+		animation[diveanim].Load((char *)":Data:Animations:Dive");
+
+		animation[throwanim].Load((char *)":Data:Animations:Aikidothrow");
+
+		animation[thrownanim].Load((char *)":Data:Animations:Aikidothrown");
+
+	}
+
+	
+
+	//Setup people
+
+	for(int i=0;i<max_people;i++){
+
+		if(i==0){
+
+			person[i].whichcostume=bodyguardcostume;
+
+		}		
+
+		
+
+		if(i>1){
+
+			person[i].whichcostume=casualcostumes+abs(Random())%numcasual;
+
+		}	
+
+		//person[i].firstlongdead=0;
+
+		person[i].dead=0;
+
+		person[i].health=100;
+
+		person[i].skeleton.free=0;
+
+		person[i].ammo=0;
+
+		person[i].velocity=0;
+
+		//Load skeleton structure
+
+		if(!initialized)person[i].skeleton.Load((char *)":Data:Skeleton:Basic Figure");
+
+		
+
+		if(i%5==0){
+
+			loadingscreenamount+=5;
+
+			if(!initialized)LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+		}
+
+	}
+
+	
+
+	loadingscreenamount+=5;
+
+	if(!initialized)LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+	
+
+	if(initialized)person[0].skeleton.Load((char *)":Data:Skeleton:Basic Figure");
+
+	
+
+	person[0].attackframe=-1;
+
+	
+
+	spawndelay=0;
+
+
+
+	fog.SetFog(fogcolorr,fogcolorg,fogcolorb,0,viewdistance*.8,.1);
+
+	
+
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+	
+
+	
+
+	//light
+
+	GLfloat LightAmbient[]=		{ .3, .3, .3, 1.0f};
+
+	GLfloat LightDiffuse[]=		{ 1, 1, 1, 1.0f };
+
+	
+
+	glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient);		
+
+	glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);		
+
+	glEnable(GL_LIGHT0);	
+
+	
+
+	loadingscreenamount+=5;
+
+	
+
+	//Load some textures
+
+	if(!initialized){
+
+		LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+		
+
+		
+
+		LoadPersonSpriteTexture(":Data:Textures:Personsprite.png",&personspritetextureptr);
+
+		LoadPersonSpriteTexture(":Data:Textures:DeadPersonsprite.png",&deadpersonspritetextureptr);
+
+		LoadPersonSpriteTexture(":Data:Textures:Scope.png",&scopetextureptr);
+
+		LoadPersonSpriteTexture(":Data:Textures:Flare.png",&flaretextureptr);
+
+		
+
+		sprites.LoadFlareTexture(":Data:Textures:HitFlash.png");
+
+		sprites.LoadMuzzleFlareTexture(":Data:Textures:MuzzleFlash.png");
+
+		sprites.LoadSmokeTexture(":Data:Textures:Smoke.png");
+
+		sprites.LoadBloodTexture(":Data:Textures:Blood.png");
+
+		sprites.LoadRainTexture(":Data:Textures:rain.png");
+
+		sprites.LoadSnowTexture(":Data:Textures:snow.png");
+
+		decals.LoadBulletHoleTexture(":Data:Textures:BulletHole.png");
+
+		decals.LoadCraterTexture(":Data:Textures:Crater.png");
+
+		decals.LoadBloodTexture(":Data:Textures:Blood:Blood1.png",0);
+
+		decals.LoadBloodTexture(":Data:Textures:Blood:Blood2.png",1);
+
+		decals.LoadBloodTexture(":Data:Textures:Blood:Blood3.png",2);
+
+		decals.LoadBloodTexture(":Data:Textures:Blood:Blood4.png",3);
+
+		decals.LoadBloodTexture(":Data:Textures:Blood:Blood5.png",4);
+
+		decals.LoadBloodTexture(":Data:Textures:Blood:Blood6.png",5);
+
+		decals.LoadBloodTexture(":Data:Textures:Blood:Blood7.png",6);
+
+		decals.LoadBloodTexture(":Data:Textures:Blood:Blood8.png",7);
+
+		decals.LoadBloodTexture(":Data:Textures:Blood:Blood9.png",8);
+
+		decals.LoadBloodTexture(":Data:Textures:Blood:Blood10.png",9);
+
+		decals.LoadBloodTexture(":Data:Textures:Blood:Blood11.png",10);
+
+	}
+
+		
+
+	//Setup clip plane equation
+
+	eqn[0]=0;
+
+	eqn[1]=1;
+
+	eqn[2]=0;
+
+	eqn[3]=0;
+
+	
+
+	glClearColor(fogcolorr,fogcolorg,fogcolorb,1);
+
+
+
+	if(!initialized)InitMouse();
+
+	
+
+	//Draw city one frame to fix evil menu bug
+
+	if(!initialized)mainmenu=2;
+
+	
+
+	if(!initialized){
+
+		LoadingScreen(loadingscreenamount/loadingscreenamounttotal*100);
+
+		flashamount=1;
+
+		flashr=1;flashg=1;flashb=1;
+
+		alSourcePlay(gSourceID[soulinsound]);
+
+	}
+
+	
+
+	initialized=1;
+
+	
+
+	loadingscreenamount+=5;
+
+	
+
+	//Sync to refresh rate
+
+	if(vblsync){	
+
+		GLint swapInt = 1;
+
+#ifdef OS9 
+ 	   	aglSetInteger(gOpenGLContext, AGL_SWAP_INTERVAL, &swapInt);
+#else
+ 
+#endif
+
+
+               
+
+	}
+
+	/*
+
+	for(int i=0;i<sprites.howmanysprites;i++){
+
+		sprites.DeleteSprite(0);
+
+	}
+
+	
+
+	for(int i=0;i<decals.howmanydecals;i++){
+
+		decals.DeleteDecal(0);
+
+	}*/
+
+	decals.howmanydecals=0;
+
+	sprites.howmanysprites=0;
+
+	
+
+	losedelay=1;
+
+		
+
+	oldscore=score;
+
+}
+
+
+
+/*********************> InitGL() <*****/
+
+
+
+
+
+int Game::InitGL(void)										
+
+{
+
+	//Config
+
+	if(!initialized){
+
+		//Default config in case config is not found	
+#ifdef OS9 
+		HideCursor();
+#else
+		STUB_FUNCTION;
+#endif
+
+		screenwidth = 640;
+
+		screenheight = 480;
+
+		usermousesensitivity=.7;
+
+		debug=0;
+
+		vblsync=1;
+
+		blood = 1;
+
+		blurness = 0;
+
+		mainmenuness=1;
+
+	    customlevels=0;
+
+	    musictoggle=1;
+
+		
+
+		//If no config, write one
+
+		ifstream ipstream("config.txt");
+
+	    if(!ipstream) {
+
+	        ofstream opstream("config.txt"); 
+
+	        opstream << "Screenwidth:\n";
+
+	        opstream << screenwidth;
+
+	        opstream << "\nScreenheight:\n";
+
+		    opstream << screenheight;
+
+		    opstream << "\nMouse sensitivity:\n";
+
+		    opstream << usermousesensitivity;
+
+		    opstream << "\nShow fps and other info:\n";
+
+		    opstream << debug;
+
+		    opstream << "\nVBL sync:\n";
+
+		    opstream << vblsync;
+
+		    opstream << "\nBlood:\n";
+
+		    opstream << blood;
+
+		    opstream << "\nBlur:\n";
+
+		    opstream << blurness;
+
+			opstream << "\nMain Menu:\n";
+
+		    opstream << mainmenuness;
+
+		    opstream << "\nCustom levels:\n";
+
+		    opstream << customlevels;
+
+			opstream << "\nMusic:\n";
+
+		    opstream << musictoggle;
+
+			opstream << "\azerty keyboard:\n";
+
+		    opstream << azertykeyboard;
+
+			opstream.close();
+
+	    }
+
+	    //Read config
+
+		if(ipstream){
+
+			ipstream.ignore(256,'\n');
+
+		    ipstream >> screenwidth;
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream >> screenheight;
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream >> usermousesensitivity;
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream >> debug;
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream >> vblsync;
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream >> blood;
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream >> blurness;
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream >> mainmenuness;
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream >> customlevels;
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream >> musictoggle;
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream >> azertykeyboard;
+
+		    ipstream.close();
+
+		}
+
+		
+
+		//Read high score
+#ifdef OS9 
+		ifstream ipstream2(":Data:Highscore");
+#else
+		/* TODO */
+		ifstream ipstream2("Data/Highscore");
+#endif
+	    if(!ipstream2) {
+
+	    	highscore=0;
+
+	        beatgame=0;
+
+#ifdef OS9 
+	        ofstream opstream(":Data:Highscore"); 
+#else
+		/* TODO */
+		ofstream opstream("Data/Highscore");
+#endif
+	        opstream << highscore;
+
+			opstream << "\n";
+
+	        opstream << beatgame;
+
+			opstream.close();
+
+	    }
+
+		if(ipstream2){
+
+		    ipstream2 >> highscore;
+
+		    ipstream.ignore(256,'\n');
+
+		    ipstream2 >> beatgame;
+
+		    ipstream2.close();
+
+		}
+
+		
+
+		sps=40;
+
+		maxfps=90;
+
+		
+
+		disttest=1;
+
+		cubetest=1;
+
+	}
+
+
+
+	//Setup screen
+#ifdef OS9 
+	if(screenwidth<640||screenheight<480)
+
+		theScreen = SetupScreen( 640, 480 );
+
+	else
+
+		theScreen = SetupScreen( screenwidth, screenheight );
+
+
+
+	gOpenGLContext = SetupAGL( ( AGLDrawable )theScreen );
+
+	if ( !gOpenGLContext )
+
+		return;
+#else
+        if (SDL_Init(SDL_INIT_VIDEO) == -1) {
+		fprintf(stderr, "SDL Init Video failed: %s\n", SDL_GetError());
+		exit(EXIT_FAILURE);
+        }
+        
+	atexit(SDL_Quit);
+
+	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
+        SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
+        SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
+        SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
+        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+	if(screenwidth<640||screenheight<480) {
+#ifdef FULLSCREEN 
+		if (SDL_SetVideoMode(640, 480, 0, SDL_OPENGL | SDL_FULLSCREEN) == NULL) {
+#else
+		if (SDL_SetVideoMode(640, 480, 0, SDL_OPENGL) == NULL) {
+#endif
+			fprintf(stderr, "(OpenGL) SDL SetVideoMode failed: %s\n", SDL_GetError());
+			exit(EXIT_FAILURE);
+		}
+	} else {
+#ifdef FULLSCREEN
+		if (SDL_SetVideoMode(screenwidth, screenheight, 0, SDL_OPENGL | SDL_FULLSCREEN) == NULL) {
+#else
+		if (SDL_SetVideoMode(screenwidth, screenheight, 0, SDL_OPENGL) == NULL) {
+#endif
+			fprintf(stderr, "(OpenGL) SDL SetVideoMode failed: %s\n", SDL_GetError());
+			exit(EXIT_FAILURE);
+		}
+	}
+	
+	SDL_WM_SetCaption("Black Shades", "Black Shades");
+	
+	SDL_EnableUNICODE(1); /* toggle it to ON */
+
+#ifdef FULLSCREEN
+	SDL_WM_GrabInput(SDL_GRAB_ON);
+	SDL_ShowCursor(0);
+#endif
+
+#endif
+		
+
+	text.LoadFontTexture(":Data:Textures:Font.png");
+
+	text.BuildFont();
+
+	glAlphaFunc(GL_GREATER, 0.01);
+
+	glDepthFunc(GL_LESS);
+
+	
+
+	glPolygonOffset(-8,0);
+
+	glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
+
+	
+
+	return TRUE;
+
+}
+
+
+
+//***************> Dispose() <******/
+
+void Game::Dispose()										
+
+{
+#ifdef OS9 
+	CleanupAGL( gOpenGLContext );
+
+	ShutdownScreen( theScreen );
+
+	ShowCursor();
+#endif
+	
+
+	//Delete sound sources
+
+	alDeleteSources(100, gSourceID);
+
+
+
+}
+
+
+
+//***************> ResizeGLScene() <******/
+
+GLvoid Game::ReSizeGLScene(float fov, float near)		
+
+{
+
+	if (screenheight==0)										
+
+	{
+
+		screenheight=1;									
+
+	}
+
+
+
+	glViewport(0,0,screenwidth,screenheight);						
+
+
+
+	glMatrixMode(GL_PROJECTION);						
+
+	glLoadIdentity();								
+
+
+
+	gluPerspective(fov,(GLfloat)screenwidth/(GLfloat)screenheight,near,viewdistance);
+
+
+
+	glMatrixMode(GL_MODELVIEW);							
+
+	glLoadIdentity();									
+
+}
+
diff --git a/src/GameLoop.cpp b/src/GameLoop.cpp
new file mode 100644
index 0000000..8a72b4b
--- /dev/null
+++ b/src/GameLoop.cpp
@@ -0,0 +1,573 @@
+#include "Game.h"	
+
+
+
+extern double multiplier;
+
+extern int visions;
+
+extern unsigned int gSourceID[100];
+
+extern unsigned int gSampleSet[100];
+
+extern Camera camera;
+
+extern float rad2deg;
+
+extern Fog fog;
+
+extern int environment;
+
+extern int slomo;
+
+/********************> HandleKeyDown() <*****/
+
+void	Game::HandleKeyDown( char theChar )
+
+{
+
+	XYZ facing;
+
+	
+
+	if(!mainmenu){
+
+	switch( theChar )
+
+	{
+
+		case 'l': 
+		        if(!lasersight==1){lasersight=1;}else{lasersight=0;} 
+			
+			break;
+
+		case 'k':
+
+			if(debug)timeremaining=0;
+
+			break;
+
+		
+
+		case 'b':
+
+			if(debug){
+
+			alSourcePlay(gSourceID[soulinsound]);
+
+			if(!slomo)slomo=1;
+
+			else slomo=0;}
+
+			if(slomo){
+
+				alSourcef(gSourceID[knifesong], AL_PITCH, (ALfloat)(.5));
+
+				alSourcef(gSourceID[shootsong], AL_PITCH, (ALfloat)(.5));
+
+				alSourcef(gSourceID[zombiesong], AL_PITCH, (ALfloat)(.5));
+
+			}
+
+			if(!slomo){
+
+				alSourcef(gSourceID[knifesong], AL_PITCH, (ALfloat)(1));
+
+				alSourcef(gSourceID[shootsong], AL_PITCH, (ALfloat)(1));
+
+				alSourcef(gSourceID[zombiesong], AL_PITCH, (ALfloat)(1));
+
+			}
+
+			break;
+
+		case 'B':
+
+			if(debug){
+
+			alSourcePlay(gSourceID[soulinsound]);
+
+			paused=1-paused;}
+
+			break;
+
+		case 'f':
+
+			if(debug){
+
+			alSourcePlay(gSourceID[souloutsound]);
+
+			//Facing
+
+			facing=0;
+
+			facing.z=-1;
+
+			
+
+			facing=DoRotation(facing,-camera.rotation2,0,0);
+
+			facing=DoRotation(facing,0,0-camera.rotation,0);
+
+			for(int i=1;i<numpeople;i++){				
+
+				if(person[i].skeleton.free!=1){
+
+				if(findDistancefast(person[i].playercoords,person[0].playercoords)<1000){
+
+				person[i].skeleton.free=1;
+
+				person[i].longdead=1;
+
+				for(int j=0;j<person[i].skeleton.num_joints;j++){
+
+					person[i].skeleton.joints[j].position=DoRotation(person[i].skeleton.joints[j].position,0,person[i].playerrotation,0);
+
+					person[i].skeleton.joints[j].position+=person[i].playercoords;
+
+					person[i].skeleton.joints[j].realoldposition=person[i].skeleton.joints[j].position;
+
+					person[i].skeleton.joints[j].velocity=DoRotation(person[i].skeleton.joints[j].velocity,0,person[i].playerrotation,0);
+
+					person[i].skeleton.joints[j].velocity+=person[i].velocity;
+
+					person[i].skeleton.joints[j].velocity+=facing*50;
+
+					person[i].skeleton.joints[j].velocity.x+=abs(Random()%20)-10;
+
+					person[i].skeleton.joints[j].velocity.y+=abs(Random()%20)-10;
+
+					person[i].skeleton.joints[j].velocity.z+=abs(Random()%20)-10;
+
+				}}}
+
+			}}
+
+			break;
+
+		case 'X':
+
+			if(debug){
+
+			if(person[0].grenphase==0){
+
+				person[0].ammo=-1;
+
+				person[0].whichgun++;
+
+				person[0].grenphase=0;
+
+				person[0].reloads[person[0].whichgun]=3;
+
+				if(person[0].whichgun>7)person[0].whichgun=0;
+
+			}}
+
+			break;
+
+	}
+
+	}
+
+}
+
+
+
+/********************> DoEvent() <*****/
+
+#ifdef OS9 
+void	Game::DoEvent( EventRecord *event )
+
+{
+
+	
+
+	char	theChar;
+
+	
+
+	switch ( event->what )
+
+	{
+
+		case keyDown:
+
+		case autoKey:
+
+			theChar = event->message & charCodeMask;	// Get the letter of the key pressed from the event message
+
+			HandleKeyDown( theChar );					// Only some key presses are handled here because it is slower and less responsive
+
+			break;
+
+	}
+
+	
+
+	
+
+}
+#endif
+
+#ifndef OS9 
+static int mapinit = 0;
+static int sdlkeymap[SDLK_LAST];
+
+static unsigned char ourkeys[16];
+
+static void init_sdlkeymap()
+{
+	int i;
+	
+	for (i = 0; i < SDLK_LAST; i++) {
+		sdlkeymap[i] = -1;
+	}
+	
+	sdlkeymap[SDLK_1] = MAC_1_KEY;
+	sdlkeymap[SDLK_2] = MAC_2_KEY;
+	sdlkeymap[SDLK_3] = MAC_3_KEY;
+	sdlkeymap[SDLK_4] = MAC_4_KEY;
+	sdlkeymap[SDLK_5] = MAC_5_KEY;
+	sdlkeymap[SDLK_6] = MAC_6_KEY;
+	sdlkeymap[SDLK_7] = MAC_7_KEY;
+	sdlkeymap[SDLK_8] = MAC_8_KEY;
+	sdlkeymap[SDLK_9] = MAC_9_KEY;
+	sdlkeymap[SDLK_0] = MAC_0_KEY;
+	sdlkeymap[SDLK_KP1] = MAC_NUMPAD_1_KEY;
+	sdlkeymap[SDLK_KP2] = MAC_NUMPAD_2_KEY;
+	sdlkeymap[SDLK_KP3] = MAC_NUMPAD_3_KEY;
+	sdlkeymap[SDLK_KP4] = MAC_NUMPAD_4_KEY;
+	sdlkeymap[SDLK_KP5] = MAC_NUMPAD_5_KEY;
+	sdlkeymap[SDLK_KP6] = MAC_NUMPAD_6_KEY;
+	sdlkeymap[SDLK_KP7] = MAC_NUMPAD_7_KEY;
+	sdlkeymap[SDLK_KP8] = MAC_NUMPAD_8_KEY;
+	sdlkeymap[SDLK_KP9] = MAC_NUMPAD_9_KEY;
+	sdlkeymap[SDLK_KP0] = MAC_NUMPAD_0_KEY;
+	sdlkeymap[SDLK_a] = MAC_A_KEY;
+	sdlkeymap[SDLK_b] = MAC_B_KEY;
+	sdlkeymap[SDLK_c] = MAC_C_KEY;
+	sdlkeymap[SDLK_d] = MAC_D_KEY;
+	sdlkeymap[SDLK_e] = MAC_E_KEY;
+	sdlkeymap[SDLK_f] = MAC_F_KEY;
+	sdlkeymap[SDLK_g] = MAC_G_KEY;
+	sdlkeymap[SDLK_h] = MAC_H_KEY;
+	sdlkeymap[SDLK_i] = MAC_I_KEY;
+	sdlkeymap[SDLK_j] = MAC_J_KEY;
+	sdlkeymap[SDLK_k] = MAC_K_KEY;
+	sdlkeymap[SDLK_l] = MAC_L_KEY;
+	sdlkeymap[SDLK_m] = MAC_M_KEY;
+	sdlkeymap[SDLK_n] = MAC_N_KEY;
+	sdlkeymap[SDLK_o] = MAC_O_KEY;
+	sdlkeymap[SDLK_p] = MAC_P_KEY;
+	sdlkeymap[SDLK_q] = MAC_Q_KEY;
+	sdlkeymap[SDLK_r] = MAC_R_KEY;
+	sdlkeymap[SDLK_s] = MAC_S_KEY;
+	sdlkeymap[SDLK_t] = MAC_T_KEY;
+	sdlkeymap[SDLK_u] = MAC_U_KEY;
+	sdlkeymap[SDLK_v] = MAC_V_KEY;
+	sdlkeymap[SDLK_w] = MAC_W_KEY;
+	sdlkeymap[SDLK_x] = MAC_X_KEY;
+	sdlkeymap[SDLK_y] = MAC_Y_KEY;
+	sdlkeymap[SDLK_z] = MAC_Z_KEY;
+	sdlkeymap[SDLK_F1] = MAC_F1_KEY;
+	sdlkeymap[SDLK_F2] = MAC_F2_KEY;
+	sdlkeymap[SDLK_F3] = MAC_F3_KEY;
+	sdlkeymap[SDLK_F4] = MAC_F4_KEY;
+	sdlkeymap[SDLK_F5] = MAC_F5_KEY;
+	sdlkeymap[SDLK_F6] = MAC_F6_KEY;
+	sdlkeymap[SDLK_F7] = MAC_F7_KEY;
+	sdlkeymap[SDLK_F8] = MAC_F8_KEY;
+	sdlkeymap[SDLK_F9] = MAC_F9_KEY;
+	sdlkeymap[SDLK_F10] = MAC_F10_KEY;
+	sdlkeymap[SDLK_F11] = MAC_F11_KEY;
+	sdlkeymap[SDLK_F12] = MAC_F12_KEY;
+	sdlkeymap[SDLK_RETURN] = MAC_RETURN_KEY;
+	sdlkeymap[SDLK_KP_ENTER] = MAC_ENTER_KEY;
+	sdlkeymap[SDLK_TAB] = MAC_TAB_KEY;
+	sdlkeymap[SDLK_SPACE] = MAC_SPACE_KEY;
+	sdlkeymap[SDLK_BACKSPACE] = MAC_DELETE_KEY;
+	sdlkeymap[SDLK_ESCAPE] = MAC_ESCAPE_KEY;
+	sdlkeymap[SDLK_LCTRL] = MAC_CONTROL_KEY;
+	sdlkeymap[SDLK_RCTRL] = MAC_CONTROL_KEY;
+	sdlkeymap[SDLK_LSHIFT] = MAC_SHIFT_KEY;
+	sdlkeymap[SDLK_RSHIFT] = MAC_SHIFT_KEY;
+	sdlkeymap[SDLK_CAPSLOCK] = MAC_CAPS_LOCK_KEY;
+	sdlkeymap[SDLK_LALT] = MAC_OPTION_KEY;
+	sdlkeymap[SDLK_RALT] = MAC_OPTION_KEY;
+	sdlkeymap[SDLK_PAGEUP] = MAC_PAGE_UP_KEY;
+	sdlkeymap[SDLK_PAGEDOWN] = MAC_PAGE_DOWN_KEY;
+	sdlkeymap[SDLK_INSERT] = MAC_INSERT_KEY;
+	sdlkeymap[SDLK_DELETE] = MAC_DEL_KEY;
+	sdlkeymap[SDLK_HOME] = MAC_HOME_KEY;
+	sdlkeymap[SDLK_END] = MAC_END_KEY;
+	sdlkeymap[SDLK_LEFTBRACKET] = MAC_LEFT_BRACKET_KEY;
+	sdlkeymap[SDLK_RIGHTBRACKET] = MAC_RIGHT_BRACKET_KEY;
+	sdlkeymap[SDLK_UP] = MAC_ARROW_UP_KEY;
+	sdlkeymap[SDLK_DOWN] = MAC_ARROW_DOWN_KEY;
+	sdlkeymap[SDLK_LEFT] = MAC_ARROW_LEFT_KEY;
+	sdlkeymap[SDLK_RIGHT] = MAC_ARROW_RIGHT_KEY;
+	
+	mapinit = 1;
+}
+
+void GetKeys(unsigned long *keys)
+{
+	/* this is just weird */
+	memcpy(keys, ourkeys, sizeof(ourkeys));
+}
+
+static void DoSDLKey(Game *g, SDL_Event *event)
+{
+	int press = (event->type == SDL_KEYDOWN) ? 1 : 0;
+	int mackey;
+	int index;
+	int mask;
+	
+
+	if (mapinit == 0) {
+		init_sdlkeymap();
+	}
+	
+	mackey = sdlkeymap[event->key.keysym.sym];
+	
+	if (mackey != -1) {
+		index = mackey / 8;
+		mask = 1 << (mackey % 8);
+		
+		if (press) {
+			ourkeys[index] |= mask;
+		} else {
+			ourkeys[index] &= ~mask;
+		}
+	}
+	
+	if (event->key.keysym.unicode && 
+		!(event->key.keysym.unicode & 0xFF80)) {
+	
+		/* hey, at least it was aleady public */
+		g->HandleKeyDown(event->key.keysym.unicode);
+	}
+	
+	
+}
+
+static void ProcessSDLEvents(Game *g)
+{
+	SDL_Event event;
+	
+	if (SDL_PollEvent(&event)) {
+		do {
+			switch(event.type) {
+				case SDL_KEYDOWN:
+				if (event.key.keysym.sym == SDLK_RETURN &&
+					event.key.keysym.mod & KMOD_ALT)
+				{
+					SDL_WM_ToggleFullScreen (SDL_GetVideoSurface ());
+					break;
+				}
+				if (event.key.keysym.sym == SDLK_g &&
+					event.key.keysym.mod & KMOD_CTRL)
+				{
+					if (SDL_WM_GrabInput (SDL_GRAB_QUERY) == SDL_GRAB_OFF)
+					{
+						SDL_WM_GrabInput (SDL_GRAB_ON);
+						SDL_ShowCursor (SDL_DISABLE);
+					}
+					else
+					{
+						SDL_WM_GrabInput (SDL_GRAB_OFF);
+						SDL_ShowCursor (SDL_ENABLE);
+					}
+					break;
+				}
+				case SDL_KEYUP:
+					DoSDLKey(g, &event);
+					break;
+				case SDL_QUIT:
+					exit(0);
+			}
+		} while (SDL_PollEvent(&event));
+	}
+}	
+
+#endif
+
+/********************> EventLoop() <*****/
+
+void	Game::EventLoop( void )
+
+{
+
+#ifdef OS9 
+	EventRecord		event;
+#endif
+
+	unsigned char	theKeyMap[16];
+
+	int colaccuracy,i;
+
+	GLfloat oldmult;
+
+	gQuit = false;
+
+	while ( gQuit == false )
+
+	{
+
+#ifdef OS9 
+		if ( GetNextEvent( everyEvent, &event ) )
+
+			DoEvent( &event );
+#else
+		ProcessSDLEvents(this);
+#endif
+		
+
+		start=TimerGetTime(&theTimer);
+
+		
+
+		colaccuracy=sps/framespersecond+1;
+
+		if(colaccuracy>sps){colaccuracy=sps;}
+
+		
+
+		oldmult=multiplier;
+
+		multiplier/=colaccuracy;
+
+		for(i=0;i<(int)(colaccuracy+.5);i++){
+
+			Tick();
+
+		}
+
+		multiplier=oldmult;
+
+		
+
+		if ( DrawGLScene())
+
+#ifdef OS9 
+			aglSwapBuffers( gOpenGLContext );
+#else
+                        SDL_GL_SwapBuffers();
+#endif
+
+		else
+
+			gQuit = true;
+
+		oldmult=multiplier;	
+
+		
+
+		end=TimerGetTime(&theTimer);
+
+		timetaken=end-start;
+
+		framespersecond=600000000/timetaken;
+
+		while(framespersecond>maxfps){
+
+			end=TimerGetTime(&theTimer);
+
+			timetaken=end-start;
+
+			framespersecond=600000000/timetaken;
+
+		}
+
+		multiplier5=multiplier4;
+
+		multiplier4=multiplier3;
+
+		multiplier3=multiplier2;
+
+		multiplier2=1/framespersecond;
+
+		multiplier=(multiplier2+multiplier3+multiplier4+multiplier5)/4;
+
+		if(multiplier>1)multiplier=1;
+
+		if(multiplier<.00001)multiplier=.00001;
+
+		if(visions==1&&mainmenu==0)multiplier/=3;
+
+		if(slomo)multiplier*=.2;
+
+		if(paused)multiplier=0;
+
+		GetKeys( ( unsigned long * )theKeyMap );
+
+		if ( IsKeyDown( theKeyMap, MAC_COMMAND_KEY )&&IsKeyDown( theKeyMap, MAC_Q_KEY )){
+
+			gQuit = true;
+
+			if(score>highscore){
+
+				highscore=score;
+
+#ifdef OS9 
+				ofstream opstream(":Data:Highscore"); 
+#else
+				/* TODO */
+				ofstream opstream("Data/Highscore");
+#endif
+
+		        opstream << highscore;
+
+				opstream << "\n";
+
+	        	opstream << beatgame;
+
+				opstream.close();
+
+			}
+
+		}
+
+		if ( IsKeyDown( theKeyMap, MAC_ESCAPE_KEY )){
+
+			alSourcePause(gSourceID[rainsound]);
+
+		
+
+			mainmenu=1;
+
+			alSourcePlay(gSourceID[souloutsound]);
+
+			flashamount=1;
+
+			flashr=1;flashg=1;flashb=1;
+
+			alSourceStop(gSourceID[visionsound]);
+
+			whichsong=mainmenusong;
+
+			alSourceStop(gSourceID[knifesong]);
+
+			alSourceStop(gSourceID[shootsong]);
+
+			alSourceStop(gSourceID[zombiesong]);
+
+			alSourceStop(gSourceID[mainmenusong]);
+
+			alSourcef(gSourceID[knifesong], AL_MIN_GAIN, 0);
+
+			alSourcef(gSourceID[shootsong], AL_MIN_GAIN, 0);
+
+			alSourcef(gSourceID[zombiesong], AL_MIN_GAIN, 0);
+
+			alSourcef(gSourceID[mainmenusong], AL_MIN_GAIN, 0);
+
+			alSourcePlay(gSourceID[whichsong]);
+
+			alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 1);
+
+		}
+
+	}
+
+}
diff --git a/src/GameTick.cpp b/src/GameTick.cpp
new file mode 100644
index 0000000..ce597df
--- /dev/null
+++ b/src/GameTick.cpp
@@ -0,0 +1,4957 @@
+#include "Game.h"	
+
+
+
+extern double multiplier;
+
+extern int thirdperson;
+
+extern int visions;
+
+extern Sprites sprites;
+
+
+
+extern unsigned int gSourceID[100];
+
+extern unsigned int gSampleSet[100];
+
+extern Camera camera;
+
+extern float camerashake;
+
+extern Fog fog;
+
+extern int environment;
+
+extern float precipitationhorz;
+
+extern float precipitationvert;
+
+extern float snowdelay;
+
+extern float precipitationdensity;
+
+extern float soundscalefactor;
+
+extern int slomo;
+
+
+
+extern int forwardskey;
+
+extern int backwardskey;
+
+extern int leftkey;
+
+extern int rightkey;
+
+extern int aimkey;
+
+extern int psychicaimkey;
+
+extern int psychickey;
+
+
+
+extern Decals decals;
+
+/********************> Tick() <*****/
+
+#define maxfallvel 40
+
+
+
+void Game::Splat(int k){
+
+	if(k!=0||visions==0){
+
+		person[k].health=0;
+
+		person[k].DoAnimations(k);
+
+		person[k].skeleton.offset=0;
+
+		person[k].skeleton.free=1;
+
+		person[k].longdead=1;
+
+
+
+		person[k].bleeding=1;
+
+		person[k].bleeddelay=1;
+
+		person[k].bjoint1=&person[k].skeleton.joints[person[k].skeleton.jointlabels[head]];
+
+		person[k].bjoint2=&person[k].skeleton.joints[person[k].skeleton.jointlabels[neck]];
+
+		
+
+		for(int j=0;j<person[k].skeleton.num_joints;j++){
+
+			person[k].skeleton.joints[j].position+=person[k].skeleton.joints[j].offset;
+
+			person[k].skeleton.joints[j].position=DoRotation(person[k].skeleton.joints[j].position,0,person[k].playerrotation,0);
+
+			person[k].skeleton.joints[j].position+=person[k].playercoords;
+
+			person[k].skeleton.joints[j].realoldposition=person[k].skeleton.joints[j].position;
+
+			person[k].skeleton.joints[j].velocity=0;
+
+			person[k].skeleton.joints[j].velocity.y+=person[k].velocity.y;
+
+		}
+
+		
+
+		float gLoc[3];
+
+		gLoc[0]=person[k].skeleton.joints[person[k].skeleton.jointlabels[head]].position.x/soundscalefactor;
+
+		gLoc[1]=person[k].skeleton.joints[person[k].skeleton.jointlabels[head]].position.y/soundscalefactor;
+
+		gLoc[2]=person[k].skeleton.joints[person[k].skeleton.jointlabels[head]].position.z/soundscalefactor;
+
+		alSourcefv(gSourceID[headwhacksound], AL_POSITION, gLoc);
+
+		alSourcePlay(gSourceID[headwhacksound]);
+
+	}	
+
+}
+
+
+
+void 	Game::Tick(){
+
+	if(mainmenu){
+
+		
+
+		unsigned char	theKeyMap[16];
+
+		GetKeys( ( unsigned long * )theKeyMap );
+
+		
+
+		if(IsKeyDown(theKeyMap, MAC_SPACE_KEY)){
+
+			mainmenu=0;
+
+		}
+
+		
+
+		GetMouse(&mouseloc);
+
+		float mousex=mouseloc.h;
+
+		float mousey=mouseloc.v;
+
+		mousex=(float)mouseloc.h*640/screenwidth;
+
+		mousey=480-(float)mouseloc.v*480/screenheight;
+		
+
+		oldmouseoverbutton=mouseoverbutton;
+
+		mouseoverbutton=0;
+
+		if(mousex>120&&mousex<560&&mousey>235&&mousey<305){
+
+			mouseoverbutton=1;
+
+		}
+
+		if(mousex>120&&mousex<560&&mousey>112&&mousey<182){
+
+			mouseoverbutton=2;
+
+		}
+
+		if((Button()&&mouseoverbutton==1&&!gameinprogress&&!oldbutton)||!mainmenuness){
+
+			if(environment==rainy_environment)alSourcePlay(gSourceID[rainsound]);
+
+			if(environment!=rainy_environment)alSourcePause(gSourceID[rainsound]);
+
+			alSourceStop(gSourceID[whichsong]);
+
+			alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 0);
+
+			alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 0);
+
+			if(person[0].whichgun==knife)whichsong=knifesong;
+
+			if(person[0].whichgun!=knife)whichsong=shootsong;
+
+			if(type==zombie_type)whichsong=zombiesong;
+
+			alSourcef(gSourceID[whichsong], AL_PITCH, 1);
+
+			alSourcePlay(gSourceID[whichsong]);
+
+			alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 1);
+
+			alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 1);
+
+			flashamount=1;
+
+			flashr=1;flashg=1;flashb=1;
+
+			mainmenu=0;
+
+			alSourcePlay(gSourceID[soulinsound]);
+
+			mission=0;
+
+			InitGame();
+
+			gameinprogress=1;
+
+		}
+
+		if((Button()&&mouseoverbutton==1&&gameinprogress&&!oldbutton)||!mainmenuness){
+
+			flashamount=1;
+
+			flashr=1;flashg=1;flashb=1;
+
+			mainmenu=0;
+
+			MoveMouse(oldmouseloc.h,oldmouseloc.v,&mouseloc);
+
+			//if(!visions){
+
+				if(environment==rainy_environment)alSourcePlay(gSourceID[rainsound]);
+
+				if(environment!=rainy_environment)alSourcePause(gSourceID[rainsound]);
+
+				alSourceStop(gSourceID[whichsong]);
+
+				alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 0);
+
+				alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 0);
+
+				if(person[0].whichgun==knife)whichsong=knifesong;
+
+				if(person[0].whichgun!=knife)whichsong=shootsong;
+
+				if(type==zombie_type)whichsong=zombiesong;
+
+				alSourcePlay(gSourceID[whichsong]);
+
+				alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 1);
+
+				alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 1);
+
+			//}
+
+			alSourcePlay(gSourceID[soulinsound]);
+
+			if(visions)alSourcePlay(gSourceID[visionsound]);
+
+		}
+
+		if(Button()&&mouseoverbutton==2&&!gameinprogress&&!oldbutton){
+
+			flashamount=1;
+
+			flashr=1;flashg=0;flashb=0;
+
+			alSourcePlay(gSourceID[losesound]);
+
+			gQuit = true;
+
+			if(score>highscore){
+
+				highscore=score;
+
+#ifdef OS9 
+				ofstream opstream(":Data:Highscore"); 
+#else
+				/* TODO */
+				ofstream opstream("Data/Highscore");
+#endif
+		        opstream << highscore;
+
+				opstream << "\n";
+
+	        	opstream << beatgame;
+
+				opstream.close();
+
+			}
+
+		}
+
+		if(Button()&&mouseoverbutton==2&&gameinprogress&&!oldbutton){
+
+			flashamount=1;
+
+			flashr=1;flashg=1;flashb=1;
+
+			alSourcePlay(gSourceID[losesound]);
+
+			gameinprogress=0;
+
+			if(score>highscore){
+
+				highscore=score;
+
+#ifdef OS9 
+				 ofstream opstream(":Data:Highscore"); 
+#else
+				/* TODO */
+				ofstream opstream("Data/Highscore");
+#endif
+		        opstream << highscore;
+
+				opstream << "\n";
+
+	        	opstream << beatgame;
+
+				opstream.close();
+
+			}
+
+		}
+
+		
+
+		if(Button())oldbutton=1;
+
+		if(!Button())oldbutton=0;
+
+	}
+
+	if(!mainmenu){
+
+		
+
+		
+
+		XYZ facing;
+
+		XYZ flatfacing;
+
+		float speed=10;
+
+		
+
+		if(person[1].health<=0||person[0].health<=0||killedinnocent){
+
+			losedelay-=multiplier/6;
+
+		}
+
+		
+
+		if(person[1].health>0&&person[0].health>0&&!killedinnocent)timeremaining-=multiplier*25/40;
+
+		if(timeremaining<=0){
+
+			flashamount=1;
+
+			flashr=0;flashg=1;flashb=0;
+
+			mission++;
+
+			alSourcePlay(gSourceID[souloutsound]);
+
+			score+=100+(mission*50);
+
+			if(mission>=nummissions){
+
+				beatgame=1;
+
+				mainmenu=1;
+
+				gameinprogress=0;
+
+				alSourcePause(gSourceID[rainsound]);
+
+		
+
+				alSourceStop(gSourceID[visionsound]);
+
+				alSourceStop(gSourceID[whichsong]);
+
+				alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 0);
+
+				alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 0);
+
+				whichsong=mainmenusong;
+
+				alSourceStop(gSourceID[whichsong]);
+
+				alSourcef(gSourceID[whichsong], AL_PITCH, 1);
+
+				alSourcePlay(gSourceID[whichsong]);
+
+				alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 1);
+
+				alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 1);
+
+				if(score>highscore){
+
+					highscore=score;
+
+#ifdef OS9 
+					 ofstream opstream(":Data:Highscore"); 
+#else
+					/* TODO */
+					ofstream opstream("Data/Highscore");
+#endif
+			        opstream << highscore;
+
+					opstream << "\n";
+
+	        		opstream << beatgame;
+
+					opstream.close();
+
+				}
+
+			}
+
+			if(!mainmenu){
+
+				InitGame();
+
+				if(environment==rainy_environment)alSourcePlay(gSourceID[rainsound]);
+
+				if(environment!=rainy_environment)alSourcePause(gSourceID[rainsound]);
+
+				alSourceStop(gSourceID[visionsound]);
+
+				alSourceStop(gSourceID[whichsong]);
+
+				if(person[0].whichgun==knife)whichsong=knifesong;
+
+				if(person[0].whichgun!=knife)whichsong=shootsong;
+
+				if(type==zombie_type)whichsong=zombiesong;
+
+				alSourcef(gSourceID[whichsong], AL_PITCH, 1);
+
+				alSourcePlay(gSourceID[whichsong]);
+
+				alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 1);
+
+				alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 1);
+
+			}
+
+		}
+
+		if(losedelay<=0){
+
+			flashamount=1;
+
+			flashr=0;flashg=0;flashb=0;
+
+			if(person[murderer].health>0)score=oldscore-200;
+
+			if(person[murderer].health<=0)score=oldscore-100;
+
+			InitGame();
+
+			alSourceStop(gSourceID[whichsong]);
+
+			if(person[0].whichgun==knife)whichsong=knifesong;
+
+			if(person[0].whichgun!=knife)whichsong=shootsong;
+
+			if(type==zombie_type)whichsong=zombiesong;
+
+			alSourcef(gSourceID[whichsong], AL_PITCH, 1);
+
+			alSourcePlay(gSourceID[whichsong]);
+
+			alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 1);
+
+			alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 1);
+
+			alSourcePlay(gSourceID[soulinsound]);
+
+		}
+
+		
+
+		unsigned char	theKeyMap[16];
+
+		GetKeys( ( unsigned long * )theKeyMap );
+
+		
+
+		//Sprites
+
+		sprites.DoStuff();
+
+		
+
+		//Decals
+
+		decals.DoStuff();
+
+		
+
+		//Facing
+
+		facing=0;
+
+		facing.z=-1;
+
+		
+
+		facing=DoRotation(facing,-camera.rotation2,0,0);
+
+		facing=DoRotation(facing,0,0-camera.rotation,0);
+
+		
+
+		flatfacing=facing;
+
+		flatfacing.y=0;
+
+		Normalise(&flatfacing);
+
+		
+
+		if(IsKeyDown(theKeyMap, psychickey)&&!oldvisionkey){
+
+			oldvisionkey=1;
+
+			visions++;
+
+			if(visions==2)visions=0;
+
+			if(visions==0){
+
+				float rad2deg=56.54866776;
+
+				flashamount=1;
+
+				flashr=1;flashg=1;flashb=1;
+
+				
+
+				if(person[0].playercoords.x!=bodycoords.x||person[0].playercoords.z!=bodycoords.z){
+
+					XYZ towards;
+
+					towards=person[0].playercoords-bodycoords;
+
+					Normalise(&towards);
+
+					camera.rotation=-asin(0-towards.x);
+
+					camera.rotation*=360/6.28;
+
+					if(towards.z>0)camera.rotation=180-camera.rotation;
+
+					camera.visrotation=camera.rotation;
+
+					camera.oldrotation=camera.rotation;
+
+					camera.oldoldrotation=camera.rotation;
+
+				}
+
+				
+
+				person[0].playercoords=bodycoords; 
+
+				person[0].oldplayercoords=bodycoords;
+
+				person[0].velocity=0;
+
+				alSourcePlay(gSourceID[soulinsound]);
+
+				alSourceStop(gSourceID[visionsound]);				
+
+				alSourcef(gSourceID[knifesong], AL_PITCH, (ALfloat)(1));
+
+				alSourcef(gSourceID[shootsong], AL_PITCH, (ALfloat)(1));
+
+				alSourcef(gSourceID[zombiesong], AL_PITCH, (ALfloat)(1));
+
+			}
+
+			if(visions==1){
+
+				alSourceStop(gSourceID[visionsound]);
+
+				flashamount=1;
+
+				flashr=1;flashg=0;flashb=0;
+
+				bodycoords=person[0].oldplayercoords;
+
+				alSourcePlay(gSourceID[souloutsound]);
+
+				alSourcef(gSourceID[knifesong], AL_PITCH, (ALfloat)(.5));
+
+				alSourcef(gSourceID[shootsong], AL_PITCH, (ALfloat)(.5));
+
+				alSourcef(gSourceID[zombiesong], AL_PITCH, (ALfloat)(.5));
+
+				alSourcePlay(gSourceID[visionsound]);
+
+			}
+
+		}
+
+		if(!IsKeyDown(theKeyMap, psychickey)){
+
+			oldvisionkey=0;
+
+		}
+
+		
+
+		if(IsKeyDown(theKeyMap, MAC_TAB_KEY)&&!tabkeydown&&debug){
+
+			thirdperson++;
+
+			if(thirdperson>2)thirdperson=0;
+
+			tabkeydown=1;
+
+		}
+
+		
+
+		if(!IsKeyDown(theKeyMap, MAC_TAB_KEY))
+
+			tabkeydown=0;
+
+		
+
+		if(IsKeyDown(theKeyMap, aimkey)&&!aimtoggle){
+
+			person[0].aiming=1-person[0].aiming;
+
+			aimtoggle=1;
+
+		}
+
+		
+
+		if(!IsKeyDown(theKeyMap, aimkey))
+
+			aimtoggle=0;
+
+		
+
+		if(IsKeyDown(theKeyMap, MAC_R_KEY)&&!reloadtoggle){
+
+			if(person[0].reloads[person[0].whichgun]>0&&person[0].reloading<=0)person[0].ammo=-1;
+
+			reloadtoggle=1;
+
+		}
+
+		
+
+		if(!IsKeyDown(theKeyMap, MAC_R_KEY))
+
+			reloadtoggle=0;
+
+		
+
+		if(IsKeyDown(theKeyMap, psychicaimkey)&&!slomokeydown&&slomo==0){
+
+			alSourcePlay(gSourceID[souloutsound]);
+
+			slomo=2;
+
+			flashamount=.5;
+
+			flashr=1;flashg=0;flashb=0;
+
+			slomokeydown=1;
+
+			score-=20;
+
+			alSourcef(gSourceID[knifesong], AL_PITCH, (ALfloat)(.5));
+
+			alSourcef(gSourceID[shootsong], AL_PITCH, (ALfloat)(.5));
+
+			alSourcef(gSourceID[zombiesong], AL_PITCH, (ALfloat)(.5));
+
+		}
+
+		
+
+		if(!IsKeyDown(theKeyMap, psychicaimkey))
+
+			slomokeydown=0;
+
+			
+
+		//Mouse look
+
+		
+
+		if((person[0].aimamount<=0&&person[0].targetanimation!=crouchanim)){
+
+			camera.rotation=camera.visrotation;
+
+			camera.rotation2=camera.visrotation2;
+
+			mousesensitivity=usermousesensitivity;
+
+		}
+
+		if(person[0].aimamount>=1&&zoom==0){
+
+			mousesensitivity=usermousesensitivity*.8;
+
+		}
+
+		if(slomo==2){
+
+			mousesensitivity*=.6;
+
+		}
+
+#if 0	// DDOI
+		GetMouse(&mouseloc);
+
+		if (mouseloc.h>600){MoveMouse(mouseloc.h-500,mouseloc.v,&mouseloc);}
+
+		if (mouseloc.h<100){MoveMouse(mouseloc.h+500,mouseloc.v,&mouseloc);}
+
+		GetMouse(&mouseloc);
+
+		if (mouseloc.v>400){MoveMouse(mouseloc.h,mouseloc.v-300,&mouseloc);}
+
+		if (mouseloc.v<100){MoveMouse(mouseloc.h,mouseloc.v+300,&mouseloc);}
+
+		GetMouse(&mouseloc);
+
+#else
+		GetMouseRel(&mouseloc);
+#endif
+
+		
+
+#if 0	// DDOI
+		oldmouserotation=(oldmouseloc.h/1.3888)*mousesensitivity;
+
+		oldmouserotation2=(oldmouseloc.v/1.3888)*mousesensitivity;
+#endif
+
+		mouserotation=(mouseloc.h/1.3888)*mousesensitivity;
+
+		mouserotation2=(mouseloc.v/1.3888)*mousesensitivity;
+
+		
+
+#if 0	// DDOI
+		if(abs(oldmouseloc.h-mouseloc.h)<400)camera.rotation+=mouserotation-oldmouserotation;
+
+		if(abs(oldmouseloc.v-mouseloc.v)<200)camera.rotation2+=mouserotation2-oldmouserotation2;
+
+		if(mouseloc.h-oldmouseloc.h>400)camera.rotation+=mouserotation-oldmouserotation-(500/1.3888*mousesensitivity);
+
+		if(mouseloc.h-oldmouseloc.h<-400)camera.rotation+=mouserotation-oldmouserotation+(500/1.3888*mousesensitivity);
+
+		if(mouseloc.v-oldmouseloc.v>200)camera.rotation2+=mouserotation2-oldmouserotation2-(300/1.3888*mousesensitivity);
+
+		if(mouseloc.v-oldmouseloc.v<-200)camera.rotation2+=mouserotation2-oldmouserotation2+(300/1.3888*mousesensitivity);
+#else
+		if(abs(mouseloc.h)<400)camera.rotation+=mouserotation;
+		if(abs(mouseloc.v)<200)camera.rotation2+=mouserotation2;
+		if(mouseloc.h>400)camera.rotation+=mouserotation-(500/1.3888*mousesensitivity);
+		if(mouseloc.h<-400)camera.rotation+=mouserotation+(500/1.3888*mousesensitivity);
+
+		if(mouseloc.v>200)camera.rotation2+=mouserotation2-(300/1.3888*mousesensitivity);
+
+		if(mouseloc.v<-200)camera.rotation2+=mouserotation2+(300/1.3888*mousesensitivity);
+#endif
+
+		
+
+		if(camera.rotation2>89){camera.rotation2=89;}
+
+		if(camera.rotation2<-89){camera.rotation2=-89;}
+
+		
+
+		//Smooth
+
+		camera.rotation=(camera.oldoldrotation+((camera.rotation-camera.oldoldrotation)*.7+(camera.oldrotation-camera.oldoldrotation)*.3));
+
+		camera.rotation2=(camera.oldoldrotation2+((camera.rotation2-camera.oldoldrotation2)*.7+(camera.oldrotation2-camera.oldoldrotation2)*.3));
+
+		
+
+		if(camera.visrotation<camera.rotation-7)camera.visrotation=camera.rotation-7;
+
+		if(camera.visrotation>camera.rotation+7)camera.visrotation=camera.rotation+7;
+
+		if(camera.visrotation2<camera.rotation2-15)camera.visrotation2=camera.rotation2-15;
+
+		if(camera.visrotation2>camera.rotation2+15)camera.visrotation2=camera.rotation2+15;
+
+		
+
+		if(zoom||person[0].aimamount<=0||person[0].whichgun==nogun||visions||person[0].whichgun==grenade||person[0].whichgun==knife){
+
+			camera.visrotation=camera.rotation;
+
+			camera.visrotation2=camera.rotation2;
+
+		}
+
+		oldzoom=zoom;
+
+		
+
+		camera.oldoldrotation=camera.oldrotation;
+
+		camera.oldoldrotation2=camera.oldrotation2;
+
+		camera.oldrotation=camera.rotation;
+
+		camera.oldrotation2=camera.rotation2;
+
+		
+
+		//Check collision with buildings
+
+		
+
+		int beginx,endx;
+
+		int beginz,endz;
+
+		int distsquared;
+
+		XYZ collpoint;
+
+		XYZ move;
+
+		float howmuchintersect;
+
+		int whichtri;
+
+		float olddist;
+
+		XYZ nothing;
+
+		XYZ underpoint;
+
+		XYZ overpoint;
+
+		int pointnum;
+
+		float depth;
+
+		XYZ normalrotated;
+
+		XYZ pointrotated;
+
+		bool inblock;
+
+		
+
+		
+
+		person[0].playerrotation=180-camera.rotation;
+
+		
+
+		//Check people collisions
+
+		for(int k=0;k<numpeople;k++){
+			// SBF - backing up the old coordinates makes
+			// the most sense here.
+			person[k].oldplayercoords=person[k].playercoords;
+			
+			person[k].DoStuff(k);
+
+			if(person[k].skeleton.free<1){
+
+			if(1==1){
+
+			person[k].onground=0;
+
+			overpoint=person[k].playercoords;
+
+			overpoint.y+=3000;
+
+			underpoint=person[k].playercoords;
+
+			underpoint.y-=3000;
+
+			
+
+			beginx=(person[k].playercoords.x+block_spacing/2)/block_spacing;
+
+			if(beginx<0)beginx=0;
+
+			beginz=(person[k].playercoords.z+block_spacing/2)/block_spacing;
+
+			if(beginz<0)beginz=0;
+
+			
+
+			endx=(person[k].playercoords.x+block_spacing/2)/block_spacing+1;
+
+			if(endx>num_blocks-1)endx=num_blocks-1;
+
+			endz=(person[k].playercoords.z+block_spacing/2)/block_spacing+1;
+
+			if(endz>num_blocks-1)endz=num_blocks-1;
+
+			
+
+			if(k!=0){
+				/* TODO: huh? */
+				beginx==person[k].whichblockx;
+
+				beginz==person[k].whichblocky;
+
+				endx==person[k].whichblockx;
+
+				endz==person[k].whichblocky;
+
+			}
+
+			
+
+			if(beginx<=endx&&beginz<=endz)
+
+			for(int i=beginx;i<=endx;i++)
+
+				for(int j=beginz;j<=endz;j++){
+
+					inblock=0;
+
+					//Ground collision
+
+					move=0;
+
+					move.x=i*block_spacing;
+
+					move.z=j*block_spacing;
+
+					whichtri=sidewalkcollide.LineCheck2(overpoint,underpoint,&collpoint,move,cityrotation[i][j]*90);
+
+					if(whichtri!=-1&&person[k].playercoords.y<=collpoint.y&&person[k].velocity.y<=0){
+
+						person[k].playercoords.y=collpoint.y;
+
+						person[k].onground=1;
+
+						if(person[k].velocity.y<-maxfallvel)Splat(k);
+
+						else person[k].velocity.y=0;
+
+					}
+
+					if(whichtri!=-1){
+
+						inblock=1;
+
+						if(k==0){onblockx=i;onblocky=j;}
+
+					}
+
+					//Wall collision
+
+					if(k==0){
+
+						if(inblock){
+
+							for(int l=0;l<8;l++){
+
+								move=0;
+
+								move.x=i*block_spacing;
+
+								move.z=j*block_spacing;
+
+								whichtri=blockwalls[citytype[i][j]].LineCheck3(person[k].oldplayercoords+boundingpoints[l],person[k].playercoords+boundingpoints[l],&collpoint,move,cityrotation[i][j]*90,&depth);
+
+								if(whichtri!=-1){
+
+									normalrotated=DoRotation(blockwalls[citytype[i][j]].normals[whichtri],0,cityrotation[i][j]*90,0);
+
+									person[k].playercoords+=normalrotated*(-(dotproduct(normalrotated,person[k].playercoords-person[k].oldplayercoords))-depth);
+
+								}
+
+							}
+
+							for(int l=0;l<8;l++){
+
+								pointnum=k+1;
+
+								if(pointnum>3)pointnum=0;
+
+								move=0;
+
+								move.x=i*block_spacing;
+
+								move.z=j*block_spacing;
+
+								whichtri=blockwalls[citytype[i][j]].LineCheck3(person[k].playercoords+boundingpoints[l],person[k].playercoords+boundingpoints[pointnum],&collpoint,move,cityrotation[i][j]*90,&depth);
+
+								if(whichtri!=-1){
+
+									normalrotated=DoRotation(blockwalls[citytype[i][j]].normals[whichtri],0,cityrotation[i][j]*90,0);
+
+									person[k].playercoords+=normalrotated;
+
+								}
+
+							}
+
+						}
+
+						//Roof collision
+
+						if(inblock&&person[k].playercoords.y>30){
+
+							if(!person[k].onground){
+
+								move=0;
+
+								move.x=i*block_spacing;
+
+								move.z=j*block_spacing;
+
+								whichtri=blockroofs[citytype[i][j]].LineCheck2(overpoint,underpoint,&collpoint,move,cityrotation[i][j]*90);
+
+								if(whichtri!=-1&&person[k].playercoords.y<=collpoint.y&&person[k].velocity.y<=0){
+
+									person[k].playercoords.y=collpoint.y;
+
+									person[k].onground=1;
+
+									if(person[k].velocity.y<-maxfallvel)Splat(k);
+
+									else person[k].velocity.y=0;
+
+								}
+
+								if(whichtri!=-1)inblock=1;
+
+							}
+
+						}
+
+					}
+
+				}
+
+			if(person[k].playercoords.y<=0){
+
+				person[k].onground=1;
+
+				person[k].playercoords.y=0;
+
+				if(person[k].velocity.y<-maxfallvel)Splat(k);
+
+				else person[k].velocity.y=0;
+
+				if(k==0)onblockx=-1;onblocky=-1;
+
+			}
+
+			// SBF - this is definately in the wrong spot!
+			//person[k].oldplayercoords=person[k].playercoords;
+
+			}
+
+			}
+
+		}
+
+		
+
+		if(IsKeyDown( theKeyMap, MAC_SPACE_KEY )){
+
+			if(visions==0&&person[0].targetanimation==joganim&&person[0].currentanimation==joganim&&person[0].backwardsanim==0&&person[0].playerrotation==person[0].playerlowrotation){
+
+				person[0].targetanimation=diveanim;
+
+				person[0].targetframe=0;
+
+				person[0].target=0;
+
+				person[0].aimamount=0;
+
+			}
+
+		}
+
+		
+
+		//Camera
+
+		camera.oldposition=camera.position;
+
+		camera.targetoffset=0;
+
+		camera.targetoffset.z=-5;
+
+		
+
+		
+
+		//Spawn people
+
+		spawndelay-=multiplier;
+
+		int blockspawnx,blockspawny;
+
+		blockspawnx=0;
+
+		blockspawny=0;
+
+		int cyclenum;
+
+		cyclenum=0;
+
+		while((citypeoplenum[blockspawnx][blockspawny]>=max_people_block&&cyclenum<10)||blockspawnx==0){
+
+			blockspawnx=((person[0].playercoords.x+block_spacing/2)/block_spacing)+Random()%2;
+
+			blockspawny=((person[0].playercoords.z+block_spacing/2)/block_spacing)+Random()%2;
+
+			cyclenum++;
+
+		}
+
+		if(cyclenum<10){	
+
+		if(spawndelay<0&&numpeople<max_people){
+
+			if(type==randomshoot_type){
+
+				if(abs(Random()%evilprobability)==0)person[numpeople].type=eviltype;
+
+				else person[numpeople].type=civiliantype;
+
+			}
+
+			if(type==zombie_type){
+
+				person[numpeople].type=zombietype;
+
+			}
+
+		
+
+			if(person[numpeople].type!=civiliantype&&blockspawnx==person[1].whichblockx&&blockspawny==person[1].whichblocky){
+
+				while((citypeoplenum[blockspawnx][blockspawny]>=max_people_block&&cyclenum<10)||blockspawnx==0||(blockspawnx==person[1].whichblockx&&blockspawny==person[1].whichblocky)){
+
+					blockspawnx=((person[0].playercoords.x+block_spacing/2)/block_spacing)+Random()%2;
+
+					blockspawny=((person[0].playercoords.z+block_spacing/2)/block_spacing)+Random()%2;
+
+					cyclenum++;
+
+				}
+
+			}
+
+					
+
+			person[numpeople].playerrotation=0;
+
+			
+
+			person[numpeople].whichcostume=casualcostumes+abs(Random())%numcasual;
+
+			
+
+			person[numpeople].whichblockx=blockspawnx;
+
+			person[numpeople].whichblocky=blockspawny;
+
+			
+
+			person[numpeople].pathnum=-1;
+
+			person[numpeople].oldpathnum=-1;
+
+			person[numpeople].oldoldpathnum=-1;
+
+			person[numpeople].oldoldoldpathnum=-1;
+
+			while(person[numpeople].pathnum<0||person[numpeople].pathnum>=path.vertexNum||person[numpeople].pathnum==1){
+
+				person[numpeople].pathnum=Random()%path.vertexNum;
+
+			}
+
+			person[numpeople].pathtarget.x=path.vertex[person[numpeople].pathnum].x;
+
+			person[numpeople].pathtarget.z=path.vertex[person[numpeople].pathnum].z;			
+
+			person[numpeople].pathsize=.98+float(abs(Random()%20))/400;
+
+			person[numpeople].pathtarget*=person[numpeople].pathsize;
+
+			person[numpeople].pathtarget.x+=person[numpeople].whichblockx*block_spacing;
+
+			person[numpeople].pathtarget.z+=person[numpeople].whichblocky*block_spacing;
+
+			
+
+			
+
+			person[numpeople].playercoords=person[numpeople].pathtarget;
+
+			person[numpeople].oldplayercoords=person[numpeople].playercoords;
+
+			person[numpeople].skeleton.free=0;
+
+			
+
+			person[numpeople].targetanimation=walkanim;
+
+			if(person[numpeople].type==zombietype)person[numpeople].targetanimation=zombiewalkanim;
+
+			person[numpeople].speed=1;
+
+			person[numpeople].existing=0;
+
+			person[numpeople].speedmult=.8+float(abs(Random()%20))/50;
+
+			person[numpeople].health=100;	
+
+			person[numpeople].maxhealth=100;	
+
+			person[numpeople].playerrotation2=0;
+
+			
+
+			person[numpeople].lastdistancevictim=200000;
+
+			
+
+			if(person[numpeople].skeleton.broken)person[numpeople].skeleton.Load((char *)":Data:Skeleton:Basic Figure");
+
+			
+
+			if(numpeople==1)person[numpeople].type=viptype;
+
+				
+
+			person[numpeople].killtarget=-1;
+
+			
+
+			if(person[numpeople].type==eviltype){person[numpeople].existing=1; person[numpeople].pathsize=1.04; person[numpeople].whichgun=nogun; person[numpeople].aiming=1; person[numpeople].killtarget=-1; person[numpeople].speedmult=1+.3*difficulty;}
+
+			if(person[numpeople].type==zombietype){person[numpeople].existing=1; person[numpeople].pathsize=1.04; person[numpeople].whichgun=nogun; person[numpeople].aiming=0; person[numpeople].killtarget=-1; person[numpeople].speedmult=0.7+.2*difficulty;}
+
+			else {person[numpeople].whichgun=nogun; person[numpeople].aiming=0; person[numpeople].killtarget=-1;}
+
+			
+
+			if(person[numpeople].type==viptype){person[numpeople].existing=1;}
+
+			
+
+			
+
+			if(enemystate==2)person[numpeople].killtarget=1;
+
+			
+
+			numpeople++;
+
+			citypeoplenum[blockspawnx][blockspawny]++;
+
+			spawndelay=.1;
+
+		}
+
+		if(spawndelay<0&&numpeople>=max_people){
+
+			if(cycle>=max_people)cycle=0;
+
+			cyclenum=0;
+
+			while(cyclenum<max_people&&(person[cycle].type==playertype||person[cycle].type==viptype||(abs(person[cycle].whichblockx-((person[0].playercoords.x+block_spacing/2)/block_spacing))<2&&abs(person[cycle].whichblocky-((person[0].playercoords.z+block_spacing/2)/block_spacing))<2))){
+
+				cycle++;
+
+				cyclenum++;
+
+				if(cycle>=max_people)cycle=0;
+
+			}
+
+			if(cycle<max_people&&cyclenum<max_people){
+
+				if(type==randomshoot_type){
+
+					if(abs(Random()%evilprobability)==0)person[cycle].type=eviltype;
+
+					else person[cycle].type=civiliantype;
+
+				}
+
+				if(type==zombie_type){
+
+					person[cycle].type=zombietype;
+
+				}
+
+				if(person[cycle].type!=civiliantype&&blockspawnx==person[1].whichblockx&&blockspawny==person[1].whichblocky){
+
+					while((citypeoplenum[blockspawnx][blockspawny]>=max_people_block&&cyclenum<10)||blockspawnx==0||(blockspawnx==person[1].whichblockx&&blockspawny==person[1].whichblocky)){
+
+						blockspawnx=((person[0].playercoords.x+block_spacing/2)/block_spacing)+Random()%2;
+
+						blockspawny=((person[0].playercoords.z+block_spacing/2)/block_spacing)+Random()%2;
+
+						cyclenum++;
+
+					}
+
+				}
+
+				person[cycle].playerrotation=0;
+
+				
+
+				person[cycle].whichcostume=casualcostumes+abs(Random())%numcasual;
+
+				
+
+				citypeoplenum[person[cycle].whichblockx][person[cycle].whichblocky]--;
+
+				person[cycle].whichblockx=blockspawnx;
+
+				person[cycle].whichblocky=blockspawny;
+
+				
+
+				person[cycle].pathnum=-1;
+
+				person[cycle].oldpathnum=-1;
+
+				person[cycle].oldoldpathnum=-1;
+
+				person[cycle].oldoldoldpathnum=-1;
+
+				while(person[cycle].pathnum<0||person[cycle].pathnum>=path.vertexNum||person[cycle].pathnum==1){
+
+					person[cycle].pathnum=Random()%path.vertexNum;
+
+				}
+
+				person[cycle].pathtarget.x=path.vertex[person[cycle].pathnum].x;
+
+				person[cycle].pathtarget.z=path.vertex[person[cycle].pathnum].z;			
+
+				person[cycle].pathsize=.98+float(abs(Random()%20))/400;
+
+				person[cycle].pathtarget*=person[cycle].pathsize;
+
+				person[cycle].pathtarget.x+=person[cycle].whichblockx*block_spacing;
+
+				person[cycle].pathtarget.z+=person[cycle].whichblocky*block_spacing;
+
+				
+
+				person[cycle].playercoords=person[cycle].pathtarget;
+
+				person[cycle].oldplayercoords=person[cycle].playercoords;
+
+				person[cycle].skeleton.free=0;
+
+				
+
+				person[cycle].targetanimation=walkanim;
+
+				if(person[cycle].type==zombietype)person[cycle].targetanimation=zombiewalkanim;
+
+				person[cycle].speed=1;
+
+				person[cycle].existing=0;
+
+				person[cycle].speedmult=.8+float(abs(Random()%20))/50;
+
+				person[cycle].health=100;
+
+				person[cycle].maxhealth=100;
+
+				person[cycle].playerrotation2=0;
+
+						
+
+				if(person[cycle].skeleton.broken)person[cycle].skeleton.Load((char *)":Data:Skeleton:Basic Figure");
+
+							
+
+				if(enemystate==1)person[cycle].killtarget=-1;
+
+				
+
+				if(person[cycle].type==eviltype){person[cycle].existing=1;  person[cycle].pathsize=1.04; person[cycle].whichgun=nogun; person[cycle].aiming=1; person[cycle].killtarget=-1; person[cycle].speedmult=1+.3*difficulty;}
+
+				if(person[cycle].type==zombietype){person[cycle].existing=1; person[cycle].pathsize=1.04; person[cycle].whichgun=nogun; person[cycle].aiming=0; person[cycle].killtarget=-1; person[cycle].speedmult=.7+.2*difficulty;}
+
+				else {person[cycle].whichgun=nogun; person[cycle].aiming=0; person[cycle].killtarget=-1;}
+
+			
+
+				person[cycle].lastdistancevictim=200000;
+
+			
+
+				if(enemystate==2)person[cycle].killtarget=1;
+
+			
+
+				if(numpeople<max_people)numpeople++;
+
+				citypeoplenum[blockspawnx][blockspawny]++;
+
+				cycle++;
+
+				
+
+				spawndelay=.1;
+
+			}
+
+		}}
+
+		
+
+		XYZ towards;
+
+		XYZ finaltarget;
+
+		XYZ blah;
+
+		int closesttarget = 0;
+
+		float leastdistance = 0.0;
+
+		
+
+		
+
+		XYZ bleedloc;
+
+		XYZ vel;
+
+		
+
+		float tooclose;
+
+		float toofar;
+
+		
+
+		//People
+
+		for(int i=0;i<numpeople;i++){
+
+			if(person[i].health<0&&person[i].longdead<0&&person[i].firstlongdead==0){
+
+				if(person[i].type!=zombietype){
+
+					overpoint=person[i].skeleton.joints[person[i].skeleton.jointlabels[abdomen]].position;
+
+					overpoint.y+=3000;
+
+					underpoint=person[i].skeleton.joints[person[i].skeleton.jointlabels[abdomen]].position;
+
+					underpoint.y-=3000;
+
+					move=0;
+
+					move.x=person[i].whichblockx*block_spacing;
+
+					move.z=person[i].whichblocky*block_spacing;
+
+					XYZ temp;
+
+					whichtri=sidewalkcollide.LineCheck2(overpoint,underpoint,&temp,move,cityrotation[person[i].whichblockx][person[i].whichblocky]*90);
+
+					XYZ normish;
+
+					normish=0;
+
+					normish.y=1;
+
+					if(whichtri>=0){
+
+						decals.MakeDecal(bloodpool,temp,12,normish, whichtri, &sidewalkcollide, move, cityrotation[person[i].whichblockx][person[i].whichblocky]*90);
+
+					}
+
+					if(whichtri==-1){
+
+						temp=person[i].skeleton.joints[person[i].skeleton.jointlabels[abdomen]].position;
+
+						temp.y=-.5;
+
+						move=0;
+
+						decals.MakeDecal(bloodpool,temp,12,normish, 0, &sidewalkcollide, move, 0);
+
+					}
+
+					person[i].firstlongdead=1;
+
+				}
+
+			}
+
+			if(person[i].health<100&&person[i].type!=zombietype){
+
+			 		person[i].health-=multiplier*120;
+
+			}
+
+			if(person[i].health<100&&person[i].type==zombietype){
+
+			 		person[i].health+=multiplier*10;
+
+			 		if(person[i].health>person[i].maxhealth)person[i].health=person[i].maxhealth;
+
+			}
+
+			if(person[i].health<100&&person[i].type==zombietype&&person[i].skeleton.free==1){
+
+			 		person[i].health+=multiplier*10;
+
+			 		if(person[i].health>person[i].maxhealth)person[i].health=person[i].maxhealth;
+
+			}
+
+			if(person[i].health<40&&person[i].type==zombietype){
+
+			 		person[i].speedmult-=multiplier/20;
+
+			 		if(person[i].speedmult<.6){
+
+						person[i].speedmult=.6;
+
+						person[i].killtarget=-1;
+
+					}
+
+			}
+
+			if(person[i].health>=40&&person[i].type==zombietype){
+
+			 		person[i].speedmult+=multiplier/40;
+
+			 		if(person[i].speedmult>.7+difficulty*.2){
+
+						person[i].speedmult=.7+difficulty*.2;
+
+						person[i].killtarget=1;
+
+					}
+
+			}
+
+			
+
+			if(person[i].maxhealth<100&&person[i].type==zombietype){
+
+			 		person[i].maxhealth+=multiplier*2;
+
+			 		if(person[i].maxhealth>100)person[i].maxhealth=100;
+
+			}
+
+			if(person[i].bleeding>0){
+
+				person[i].bleeding-=multiplier;
+
+				person[i].bleeddelay-=multiplier*10;
+
+				if(person[i].bleeddelay<=0){
+
+					person[i].bleeddelay=1;
+
+					if(person[i].skeleton.free==0){
+
+						bleedloc=DoRotation((person[i].bjoint1->position+person[i].bjoint2->position)/2,0,person[i].playerrotation,0)+person[i].playercoords;
+
+					}
+
+					if(person[i].skeleton.free>0){
+
+						bleedloc=(person[i].bjoint1->position+person[i].bjoint2->position)/2;
+
+					}
+
+					vel=0;
+
+					sprites.MakeSprite(bloodspritedown, .6, 1, .2, .2,bleedloc, vel, 3*person[i].bleeding);
+
+				}
+
+			}
+
+			if(person[i].skeleton.free==0){
+
+				//Gun
+
+				if(person[i].type==playertype||person[i].type==eviltype){
+
+					if(i==0){
+
+						if(person[i].whichgun==shotgun)person[i].recoil-=multiplier*4;
+
+					 	if(person[i].whichgun==sniperrifle)person[i].recoil-=multiplier*2;
+
+					 	if(person[i].whichgun==handgun1)person[i].recoil-=multiplier*5;
+
+					 	if(person[i].whichgun==handgun2)person[i].recoil-=multiplier*5;
+
+					 	if(person[i].whichgun==assaultrifle)person[i].recoil-=multiplier*10;
+
+				 	}
+
+				 	if(i!=0){
+
+						if(person[i].whichgun==shotgun)person[i].recoil-=multiplier*1;
+
+					 	if(person[i].whichgun==sniperrifle)person[i].recoil-=multiplier*1;
+
+					 	if(person[i].whichgun==handgun1)person[i].recoil-=multiplier*2;
+
+					 	if(person[i].whichgun==handgun2)person[i].recoil-=multiplier*2;
+
+					 	if(person[i].whichgun==assaultrifle)person[i].recoil-=multiplier*10;
+
+				 	}
+
+				 	if(person[i].recoil<0)person[i].recoil=0;
+
+					if(i==0){
+
+						if(zoom){
+
+							mousesensitivity=.05*usermousesensitivity;
+
+							if(person[i].targetanimation!=crouchanim||person[i].currentanimation!=crouchanim||person[i].aiming<1){
+
+								zoom=0;
+
+							}
+
+							if(visions==1)zoom=0;
+
+						}
+
+						if(person[i].currentanimation==crouchanim&&person[i].targetanimation==crouchanim&&person[i].aiming>=1&&person[i].whichgun==sniperrifle){
+
+							zoom=1;
+
+							if(zoom&&!oldzoom)camera.rotation2-=6;
+
+						}
+
+						if(!zoom)mousesensitivity=1*usermousesensitivity;
+
+						if(person[i].whichgun!=sniperrifle)zoom=0;
+
+					}
+
+				}
+
+				//Zombie eat
+
+				if(i>0&&person[person[i].killtarget].eaten==i&&person[i].targetanimation==zombieeatanim){
+
+			 		person[person[i].killtarget].skeleton.joints[person[person[i].killtarget].skeleton.jointlabels[head]].locked=1;
+
+			 		person[person[i].killtarget].skeleton.joints[person[person[i].killtarget].skeleton.jointlabels[rightshoulder]].locked=1;
+
+				 	for(int k=0;k<2;k++){
+
+			 			person[person[i].killtarget].skeleton.joints[person[person[i].killtarget].skeleton.jointlabels[head]].position=DoRotation(person[i].skeleton.joints[person[i].skeleton.jointlabels[righthand]].position,0,person[i].playerrotation,0)+person[i].playercoords;
+
+				 		person[person[i].killtarget].skeleton.joints[person[person[i].killtarget].skeleton.jointlabels[head]].velocity=0;
+
+				 		person[person[i].killtarget].skeleton.joints[person[person[i].killtarget].skeleton.jointlabels[rightshoulder]].position=DoRotation(person[i].skeleton.joints[person[i].skeleton.jointlabels[lefthand]].position,0,person[i].playerrotation,0)+person[i].playercoords;
+
+				 		person[person[i].killtarget].skeleton.joints[person[person[i].killtarget].skeleton.jointlabels[rightshoulder]].velocity=0;
+
+				 		person[person[i].killtarget].skeleton.DoConstraints();
+
+						person[person[i].killtarget].skeleton.DoConstraints(&blocksimplecollide[citytype[person[i].whichblockx][person[i].whichblocky]],&move,cityrotation[person[i].whichblockx][person[i].whichblocky]*90);
+
+					}
+
+					person[person[i].killtarget].skeleton.joints[person[person[i].killtarget].skeleton.jointlabels[head]].locked=0;
+
+			 		person[person[i].killtarget].skeleton.joints[person[person[i].killtarget].skeleton.jointlabels[rightshoulder]].locked=0;
+
+				 		
+
+			 		person[person[i].killtarget].longdead=1;
+
+			 	}
+
+				
+
+				if(i>0&&enemystate!=1&&person[i].type==zombietype&&person[i].speedmult>.7){
+
+					if(findDistancefast(person[i].playercoords,person[1].playercoords)<20000)person[i].killtarget=1;
+
+					else person[i].killtarget=-1;
+
+				}
+
+				if(i>0&&enemystate!=1&&person[i].type==zombietype&&person[i].speedmult<.7){
+
+					person[i].killtarget=-1;
+
+				}
+
+				
+
+				bool realcheck = false;
+
+				//Pathfinding
+			 	if(i>0&&person[i].targetanimation!=getupfrontanim&&person[i].targetanimation!=thrownanim&&person[i].targetanimation!=getupbackanim&&person[i].currentanimation!=getupfrontanim&&person[i].currentanimation!=getupbackanim){
+
+			 		person[i].pathcheckdelay-=multiplier;
+
+					// Realcheck tells us
+					// a) we've got close to the end of our path or
+					// b) we're moving away from our target
+			 		realcheck=(abs(person[i].playercoords.x-person[i].pathtarget.x)<1&&abs(person[i].playercoords.z-person[i].pathtarget.z)<1)
+					  ||findDistancefast(person[i].playercoords,person[i].pathtarget)>findDistancefast(person[i].oldplayercoords,person[i].pathtarget);
+			 		
+					if(person[i].targetanimation==idleanim&&person[i].killtargetvisible==0){
+
+						person[i].targetanimation=walkanim;
+
+						if(person[i].type==zombietype)person[i].targetanimation=zombiewalkanim;
+
+						realcheck=1;
+
+					}
+
+					if((realcheck||((person[i].killtarget>-1&&person[i].type!=civiliantype)&&person[i].pathcheckdelay<=0)||person[i].killtargetvisible)){
+
+				 		person[i].pathcheckdelay=1.2;
+
+				 		if((person[i].killtarget==-1||person[i].type==civiliantype)&&!person[i].running){
+
+					 		person[i].killtargetvisible=0;
+
+					 		leastdistance=2000000;
+
+					 		for(int j=0;j<path.vertexNum;j++){
+
+					 			person[i].pathtarget.x=path.vertex[j].x;
+
+								person[i].pathtarget.z=path.vertex[j].z;		
+
+								person[i].pathtarget.y=path.vertex[j].y;		
+
+								person[i].pathtarget*=person[i].pathsize;
+
+								person[i].pathtarget.x+=person[i].whichblockx*block_spacing;
+
+								person[i].pathtarget.z+=person[i].whichblocky*block_spacing;
+
+								if(findDistancefast(person[i].playercoords,person[i].pathtarget)<leastdistance&&j!=1&&j!=person[i].oldpathnum&&j!=person[i].oldoldpathnum&&j!=person[i].oldoldoldpathnum){
+
+									leastdistance=findDistancefast(person[i].playercoords,person[i].pathtarget);
+
+									closesttarget=j;
+
+								}	
+
+					 		}
+
+					 		if(closesttarget>=0&&closesttarget<path.vertexNum){
+
+						 		person[i].oldoldoldpathnum=person[i].oldoldpathnum;
+
+						 		person[i].oldoldpathnum=person[i].oldpathnum;
+
+						 		person[i].oldpathnum=person[i].pathnum;
+
+						 		person[i].pathnum=closesttarget;
+
+								person[i].pathtarget.x=path.vertex[person[i].pathnum].x;
+
+								person[i].pathtarget.z=path.vertex[person[i].pathnum].z;		
+
+								person[i].pathtarget*=person[i].pathsize;
+
+								person[i].pathtarget.x+=person[i].whichblockx*block_spacing;
+
+								person[i].pathtarget.z+=person[i].whichblocky*block_spacing;
+
+							}
+
+						}
+
+						if(person[i].running&&realcheck){
+
+							person[i].killtargetvisible=0;
+
+							person[i].targetanimation=joganim;
+
+							//Dead target?
+
+							if(person[person[i].killtarget].health<=0){
+
+							 	person[i].running=0;
+
+							 }
+
+							 person[i].killtarget=1;
+
+							 
+
+							 //If pathfind
+
+							if(realcheck){
+
+					 		leastdistance=2000000;
+
+					 		person[i].lastdistancevictim=0;
+
+					 		closesttarget=-1;
+
+					 		//Check best path
+
+					 		closesttarget=person[i].pathnum;
+
+					 		//Check other blocks?
+
+					 		if ((closesttarget==person[i].pathnum)){
+
+					 			beginx=person[i].whichblockx-2;
+
+								if(beginx<0)beginx=0;
+
+								beginz=person[i].whichblocky-2;
+
+								if(beginz<0)beginz=0;
+
+								
+
+								endx=person[i].whichblockx+2;
+
+								if(endx>num_blocks-1)endx=num_blocks-1;
+
+								endz=person[i].whichblocky+2;
+
+								if(endz>num_blocks-1)endz=num_blocks-1;
+
+								
+
+								leastdistance=2000000;
+
+					 			for(int l=beginx;l<=endx;l++){
+
+									for(int m=beginx;m<=endx;m++){
+
+								 		for(int j=0;j<path.vertexNum;j++){
+
+								 			person[i].pathtarget.x=path.vertex[j].x;
+
+											person[i].pathtarget.y=path.vertex[j].y;
+
+											person[i].pathtarget.z=path.vertex[j].z;		
+
+											person[i].pathtarget*=person[i].pathsize;
+
+											person[i].pathtarget.x+=l*block_spacing;
+
+											person[i].pathtarget.z+=m*block_spacing;
+
+											if(findDistancefast(person[i].playercoords,person[i].pathtarget)<leastdistance&&findDistancefast(person[i].pathtarget,person[person[i].killtarget].playercoords)>findDistancefast(person[i].playercoords,person[person[i].killtarget].playercoords)&&j!=1&&blocksimple.LineCheck2(person[i].playercoords,person[i].pathtarget,&blah,move,cityrotation[person[i].whichblockx][person[i].whichblocky])==-1&&blocksimple.LineCheck2(person[i].playercoords,person[i].pathtarget,&blah,move,cityrotation[l][m])==-1){
+
+												person[i].lastdistancevictim=findDistancefast(person[i].pathtarget,person[person[i].killtarget].playercoords);
+
+												leastdistance=findDistancefast(person[i].playercoords,person[i].pathtarget);
+
+												closesttarget=j;
+
+												finaltarget=person[i].pathtarget;
+
+												person[i].whichblockx=l;
+
+												person[i].whichblocky=m;
+
+					 						}
+
+								 		}
+
+								 		}
+
+								 	}
+
+								 }
+
+					  		if(closesttarget!=-1){
+
+								person[i].pathnum=closesttarget;
+
+								person[i].pathtarget=finaltarget;
+
+							}
+
+							}
+
+						}
+
+						//Assassin
+
+						if((person[i].killtarget>-1&&person[i].type!=civiliantype)&&!person[i].running){
+
+							//Dead target?
+
+							if(person[person[i].killtarget].health<=0&&person[i].type==eviltype){
+
+							 	person[i].playerrotation2=0;
+
+							 	person[i].whichgun=nogun;
+
+							 	person[i].targetanimation=walkanim;
+
+							 	person[i].lastdistancevictim=200000;
+
+							 	person[i].pathnum=-1;
+
+							 	enemystate=1;
+
+							 	person[i].killtarget=-1;
+
+							 	realcheck=1;
+
+							 }
+
+							 if(person[i].type==zombietype&&person[person[i].killtarget].health<=0){
+
+								if(person[person[i].killtarget].eaten!=i){
+
+									person[i].playerrotation2=0;
+
+							 		person[i].targetanimation=zombiewalkanim;
+
+							 		person[i].lastdistancevictim=200000;
+
+							 		person[i].pathnum=-1;
+
+							 		realcheck=1;
+
+							 		person[i].killtarget=-1;
+
+							 	}
+
+							 	if(person[person[i].killtarget].eaten==i&&person[i].targetanimation!=zombieeatanim){
+
+							 		person[i].targetanimation=zombieeatanim;
+
+									person[i].targetframe=0;
+
+									person[i].target=0;
+
+							 	}
+
+							 	enemystate=1;
+
+							 }
+
+							 if(person[person[i].killtarget].health>0){
+
+							 if(person[person[i].killtarget].skeleton.free){
+
+							 	person[person[i].killtarget].playercoords=person[person[i].killtarget].averageloc;
+
+							 }
+
+							 
+
+							 //If pathfind
+
+							if(realcheck){
+
+					 		leastdistance=2000000;
+
+					 		person[i].lastdistancevictim=2000000;
+
+					 		closesttarget=-1;
+
+					 		//Check best path
+
+					 		for(int j=0;j<path.vertexNum;j++){
+
+					 			person[i].pathtarget.x=path.vertex[j].x;
+
+								person[i].pathtarget.z=path.vertex[j].z;		
+
+								person[i].pathtarget.y=path.vertex[j].y;		
+
+								person[i].pathtarget*=person[i].pathsize;
+
+								person[i].pathtarget.x+=person[i].whichblockx*block_spacing;
+
+								person[i].pathtarget.z+=person[i].whichblocky*block_spacing;
+
+								if(findDistancefast(person[i].playercoords,person[i].pathtarget)<leastdistance&&findDistancefast(person[i].pathtarget,person[person[i].killtarget].playercoords)<person[i].lastdistancevictim&&j!=1&&blocksimple.LineCheck2(person[i].playercoords,person[i].pathtarget,&blah,move,cityrotation[person[i].whichblockx][person[i].whichblocky])==-1){
+
+									leastdistance=findDistancefast(person[i].playercoords,person[i].pathtarget);
+
+									person[i].lastdistancevictim=findDistancefast(person[i].pathtarget,person[person[i].killtarget].playercoords);
+
+									closesttarget=j;
+
+									finaltarget=person[i].pathtarget;
+
+								}	
+
+					 		}
+
+					 		leastdistance=2000000;
+
+					 		for(int j=0;j<path.vertexNum;j++){
+
+					 			person[i].pathtarget.x=path.vertex[j].x;
+
+								person[i].pathtarget.z=path.vertex[j].z;		
+
+								person[i].pathtarget.y=path.vertex[j].y;		
+
+								person[i].pathtarget*=person[i].pathsize;
+
+								person[i].pathtarget.x+=person[i].whichblockx*block_spacing;
+
+								person[i].pathtarget.z+=person[i].whichblocky*block_spacing;
+
+								if(findDistancefast(person[i].playercoords,person[i].pathtarget)<leastdistance&&findDistancefast(person[i].pathtarget,person[person[i].killtarget].playercoords)<person[i].lastdistancevictim&&j!=1&&blocksimple.LineCheck2(person[i].playercoords,person[i].pathtarget,&blah,move,cityrotation[person[i].whichblockx][person[i].whichblocky])==-1){
+
+									leastdistance=findDistancefast(person[i].playercoords,person[i].pathtarget);
+
+									person[i].lastdistancevictim=findDistancefast(person[i].pathtarget,person[person[i].killtarget].playercoords);
+
+									closesttarget=j;
+
+									finaltarget=person[i].pathtarget;
+
+								}	
+
+					 		}
+
+					 		//Check other blocks?
+
+					 		if((closesttarget==person[i].pathnum)||closesttarget==-1){
+
+					 			beginx=person[i].whichblockx-2;
+
+								if(beginx<0)beginx=0;
+
+								beginz=person[i].whichblocky-2;
+
+								if(beginz<0)beginz=0;
+
+								
+
+								endx=person[i].whichblockx+2;
+
+								if(endx>num_blocks-1)endx=num_blocks-1;
+
+								endz=person[i].whichblocky+2;
+
+								if(endz>num_blocks-1)endz=num_blocks-1;
+
+								
+
+								leastdistance=2000000;
+
+					 			for(int l=beginx;l<=endx;l++){
+
+									for(int m=beginx;m<=endx;m++){
+
+								 		if(l!=person[i].whichblockx||m!=person[i].whichblocky){
+
+								 		for(int j=0;j<path.vertexNum;j++){
+
+								 			person[i].pathtarget.x=path.vertex[j].x;
+
+											person[i].pathtarget.y=path.vertex[j].y;
+
+											person[i].pathtarget.z=path.vertex[j].z;		
+
+											person[i].pathtarget*=person[i].pathsize;
+
+											person[i].pathtarget.x+=l*block_spacing;
+
+											person[i].pathtarget.z+=m*block_spacing;
+
+											if(findDistancefast(person[i].playercoords,person[i].pathtarget)<leastdistance&&findDistancefast(person[i].pathtarget,person[person[i].killtarget].playercoords)<findDistancefast(person[i].playercoords,person[person[i].killtarget].playercoords)&&j!=1&&blocksimple.LineCheck2(person[i].playercoords,person[i].pathtarget,&blah,move,cityrotation[l][m])==-1&&blocksimple.LineCheck2(person[i].playercoords,person[i].pathtarget,&blah,move,cityrotation[person[i].whichblockx][person[i].whichblocky])==-1){
+
+												leastdistance=findDistancefast(person[i].playercoords,person[i].pathtarget);
+
+												closesttarget=j;
+
+												finaltarget=person[i].pathtarget;
+
+												person[i].whichblockx=l;
+
+												person[i].whichblocky=m;
+
+					 						}
+
+								 		}
+
+								 		}
+
+								 	}
+
+								 }
+
+					 		}
+
+					 		if(closesttarget!=-1){
+
+					 			person[i].onpath=1;
+
+								person[i].pathnum=closesttarget;
+
+								person[i].pathtarget=finaltarget;
+
+							}
+
+							}
+
+							//Check killtargetvisible
+
+							person[i].killtargetvisible=1;
+
+							if(person[person[i].killtarget].health<=0)person[i].killtargetvisible=0;
+
+							if(closesttarget!=-1&&findDistancefast(person[i].playercoords, person[person[i].killtarget].playercoords)>30000)person[i].killtargetvisible=0;
+
+					 		if(person[i].killtarget==0&&visions==1)person[i].killtargetvisible=0;
+
+					 		if(person[i].killtargetvisible){
+
+						 		beginx=person[i].whichblockx-2;
+
+								if(beginx<0)beginx=0;
+
+								beginz=person[i].whichblocky-2;
+
+								if(beginz<0)beginz=0;
+
+								
+
+								endx=person[i].whichblockx+2;
+
+								if(endx>num_blocks-1)endx=num_blocks-1;
+
+								endz=person[i].whichblocky+2;
+
+								if(endz>num_blocks-1)endz=num_blocks-1;
+
+								
+
+						 		for(int l=beginx;l<=endx;l++){
+
+									for(int m=beginx;m<=endx;m++){
+
+								 		move.x=l*block_spacing;
+
+										move.z=m*block_spacing;
+
+										move.y=-3;
+
+										if(person[i].killtargetvisible){
+
+									 		if(blocksimple.LineCheck2(person[i].playercoords,person[person[i].killtarget].playercoords,&blah,move,cityrotation[l][m])!=-1)
+
+				 							{
+
+				 								person[i].killtargetvisible=0;
+
+				 							}
+
+				 						}
+
+								 	}
+
+								 }
+
+								}
+
+								if(person[i].type==eviltype){
+
+									 if(!person[i].killtargetvisible&&person[i].targetanimation==idleanim){
+
+									 	person[i].targetanimation=joganim;
+
+									 }
+
+									 if(!person[i].killtargetvisible){
+
+									 	person[i].aiming=0;
+
+									 }
+
+									 if(person[i].killtargetvisible){
+
+									 	person[i].onpath=0;
+
+									 	person[i].lastdistancevictim=200000;
+
+									 	person[i].pathnum=-1;
+
+									 	if(person[i].whichgun==nogun){
+
+									 		person[i].whichgun=possiblegun[abs(Random()%numpossibleguns)];
+
+									 		person[i].reloads[person[i].whichgun]=1;
+
+									 		if(person[i].whichgun==knife)person[i].speedmult=.8+.5*difficulty;
+
+									 	}
+
+									 	if(person[i].aiming==0)person[i].shotdelay=shotdelayamount/difficulty;
+
+									 	person[i].aiming=1;
+
+									 	if(person[i].reloading>0)person[i].aiming=0;
+
+									 	if(person[i].whichgun==handgun1||person[i].whichgun==handgun2)person[i].playerrotation2=-10;
+
+									 	if(person[i].whichgun==assaultrifle||person[i].whichgun==sniperrifle||person[i].whichgun==shotgun)person[i].playerrotation2=20;
+
+									 	tooclose=1300;
+
+									 	toofar=3000;
+
+									 	if(person[i].whichgun==shotgun){
+
+									 		tooclose=1400;
+
+									 		toofar=5000;
+
+									 	}
+
+									 	if(person[i].whichgun==assaultrifle){
+
+									 		tooclose=5000;
+
+									 		toofar=9000;
+
+									 	}
+
+									 	if(person[i].whichgun==sniperrifle){
+
+									 		tooclose=10000;
+
+									 		toofar=20000;
+
+									 	}
+
+									 	if(person[i].whichgun==knife){
+
+									 		tooclose=20;
+
+									 		toofar=20000;
+
+									 	}
+
+									 	if(findDistancefast(person[i].playercoords, person[person[i].killtarget].playercoords)>toofar)
+
+										 	person[i].targetanimation=joganim;
+
+									 	if((findDistancefast(person[i].playercoords, person[person[i].killtarget].playercoords)<=tooclose&&person[person[i].killtarget].skeleton.free==0)||(tooclose>200&&findDistancefast(person[i].playercoords, person[person[i].killtarget].playercoords)<=200)||(tooclose<=200&&findDistancefast(person[i].playercoords, person[person[i].killtarget].playercoords)<tooclose)){
+
+									 		if(person[i].targetanimation!=idleanim){
+
+										 		person[i].targetanimation=idleanim;
+
+												person[i].targetframe=0;
+
+												person[i].target=0;
+
+											}
+
+											if(person[i].whichgun==knife&&person[person[i].killtarget].health==100){
+
+												murderer=i;
+
+												person[i].attacktarget=0;
+
+												person[i].attackframe=0;
+
+												float gLoc[3];
+
+												gLoc[0]=(camera.position.x+((person[i].playercoords.x+flatfacing.x)-camera.position.x)/2)/soundscalefactor;
+
+												gLoc[1]=(camera.position.y+((person[i].playercoords.y+flatfacing.y)-camera.position.y)/2)/soundscalefactor;
+
+												gLoc[2]=(camera.position.z+((person[i].playercoords.z+flatfacing.z)-camera.position.z)/2)/soundscalefactor;
+
+												if(person[person[i].killtarget].type!=zombietype)
+
+												{
+
+													alSourcefv(gSourceID[knifeslashsound], AL_POSITION, gLoc);
+
+													alSourcePlay(gSourceID[knifeslashsound]);
+
+													person[person[i].killtarget].bjoint1=&person[person[i].killtarget].skeleton.joints[person[person[i].killtarget].skeleton.jointlabels[neck]];
+
+													person[person[i].killtarget].bjoint2=&person[person[i].killtarget].skeleton.joints[person[person[i].killtarget].skeleton.jointlabels[neck]];
+
+													person[person[i].killtarget].bleeding=1;
+
+													person[person[i].killtarget].bleeddelay=1;
+
+													person[person[i].killtarget].health-=20;
+
+													person[person[i].killtarget].targetanimation=chestpainanim;
+
+													person[person[i].killtarget].targetframe=0;
+
+													person[person[i].killtarget].target=0;
+
+													person[person[i].killtarget].longdead=1;
+
+												}
+
+											}
+
+										}
+
+									 	finaltarget=person[person[i].killtarget].playercoords;
+
+									 }
+
+								}
+
+								if(person[i].type==zombietype&&person[person[i].killtarget].health>0){
+
+									 if(!person[i].killtargetvisible&&person[i].targetanimation==idleanim){
+
+									 	person[i].targetanimation=zombiejoganim;
+
+									 }
+
+									 if(!person[i].killtargetvisible){
+
+									 	person[i].aiming=0;
+
+									 }
+
+									 if(person[i].killtargetvisible){
+
+									 	person[i].onpath=0;
+
+									 	person[i].lastdistancevictim=200000;
+
+									 	person[i].pathnum=-1;
+
+									 	if(person[i].aiming==0)person[i].shotdelay=shotdelayamount/difficulty;
+
+									 	if(findDistancefast(person[i].playercoords, person[person[i].killtarget].playercoords)>20||person[i].targetanimation!=idleanim)
+
+										 	person[i].targetanimation=zombiejoganim;
+
+									 	if(findDistancefast(person[i].playercoords, person[person[i].killtarget].playercoords)<=20){
+
+									 		murderer=i;
+
+									 		person[person[i].killtarget].health=0;
+
+									 		person[person[i].killtarget].eaten=i;
+
+										}
+
+									 	finaltarget=person[person[i].killtarget].playercoords;
+
+									 }
+
+								}
+
+							 if(person[i].killtargetvisible||realcheck)person[i].pathtarget=finaltarget;
+
+							 if(realcheck)person[i].lastdistancevictim=findDistancefast(person[i].pathtarget,person[person[i].killtarget].playercoords);	 
+
+							}
+
+						}
+
+						
+
+						if(person[i].targetanimation!=zombieeatanim||person[i].type!=zombietype){
+
+							towards=person[i].playercoords-person[i].pathtarget;
+
+							Normalise(&towards);
+
+							person[i].playerrotation=asin(0-towards.x)*360/6.28;
+
+							if(towards.z>0)person[i].playerrotation=180-person[i].playerrotation;
+
+						}
+
+					}
+
+			 	}
+
+			 	person[i].whichblockx=((person[i].playercoords.x+block_spacing/2)/block_spacing);
+
+			 	person[i].whichblocky=((person[i].playercoords.z+block_spacing/2)/block_spacing);
+
+			 					
+
+				if(!person[i].onground)person[i].velocity.y+=multiplier*gravity;
+
+			 	if(!person[i].onground&&(i!=0||visions!=1))person[i].playercoords+=person[i].velocity*multiplier;
+
+			 	//Death by bleeding/shock
+
+		 		if(person[i].health<=0){
+
+		 			person[i].skeleton.offset=0;
+
+					person[i].skeleton.free=1;
+
+					person[i].longdead=1;
+
+					for(int j=0;j<person[i].skeleton.num_joints;j++){
+
+						person[i].skeleton.joints[j].position+=person[i].skeleton.joints[j].offset;
+
+						person[i].skeleton.joints[j].position=DoRotation(person[i].skeleton.joints[j].position,0,person[i].playerrotation,0);
+
+						person[i].skeleton.joints[j].position+=person[i].playercoords;
+
+						person[i].skeleton.joints[j].realoldposition=person[i].skeleton.joints[j].position;
+
+						person[i].skeleton.joints[j].velocity=DoRotation(person[i].skeleton.joints[j].velocity,0,person[i].playerrotation,0);
+
+						person[i].skeleton.joints[j].velocity+=person[i].velocity;
+
+						person[i].skeleton.joints[j].velocity+=person[i].facing*4;
+
+					}
+
+				}
+
+			 }
+
+		 	//Rag doll
+
+			if(person[i].skeleton.free==1&&person[i].longdead>0){
+
+				person[i].whichblockx=((person[i].skeleton.joints[0].position.x+block_spacing/2)/block_spacing);
+
+				person[i].whichblocky=((person[i].skeleton.joints[0].position.z+block_spacing/2)/block_spacing);
+
+				move=0;
+
+				move.x=person[i].whichblockx*block_spacing;
+
+				move.z=person[i].whichblocky*block_spacing;
+
+				person[i].skeleton.DoGravity();
+
+				if(person[i].averageloc.y<=50)person[i].skeleton.DoConstraints(&blocksimplecollide[citytype[person[i].whichblockx][person[i].whichblocky]],&move,cityrotation[person[i].whichblockx][person[i].whichblocky]*90);
+
+				if(person[i].averageloc.y>50)person[i].skeleton.DoConstraints(&blockcollide[citytype[person[i].whichblockx][person[i].whichblocky]],&move,cityrotation[person[i].whichblockx][person[i].whichblocky]*90);
+
+				person[i].oldaverageloc=person[i].averageloc;
+
+				person[i].averageloc=0;
+
+				for(int j=0;j<person[i].skeleton.num_joints;j++){
+
+					person[i].averageloc+=person[i].skeleton.joints[j].position;
+
+				}
+
+				person[i].averageloc/=person[i].skeleton.num_joints;
+
+				person[i].playercoords=person[i].averageloc;
+
+				if(person[i].longdead<multiplier/2&&person[i].longdead>0)person[i].DrawSkeleton(i);
+
+				if(findDistancefast(person[i].averageloc,person[i].oldaverageloc)<.2*multiplier)person[i].longdead-=multiplier/2;
+
+			}
+
+			if(person[i].skeleton.free==1&&person[i].longdead<=0&&person[i].health>0&&person[i].longdead!=-1){
+
+				person[i].longdead=1;
+
+				person[i].skeleton.free=0;
+
+				person[i].currentanimation=lyinganim;
+
+				person[i].target=0;
+
+				person[i].targetframe=0;
+
+				//Get up from front or back?
+
+				if(person[i].skeleton.forward.y>0)
+
+				person[i].targetanimation=getupfrontanim;
+
+				else
+
+				person[i].targetanimation=getupbackanim;
+
+				//Find playercoords
+
+				person[i].playercoords=person[i].averageloc;
+
+				for(int j=0;j<person[i].skeleton.num_joints;j++){
+
+					if(person[i].skeleton.joints[j].position.y>person[i].playercoords.y)person[i].playercoords.y=person[i].skeleton.joints[j].position.y;
+
+				}
+
+				//Find orientation
+
+				XYZ firsttop=person[i].skeleton.joints[person[i].skeleton.jointlabels[neck]].position-person[i].skeleton.joints[person[i].skeleton.jointlabels[groin]].position;
+
+			 	Normalise(&firsttop);
+
+				person[i].playerrotation=acos(0-firsttop.z);
+
+				person[i].playerrotation*=360/6.28;
+
+				if(0>firsttop.x)person[i].playerrotation=360-person[i].playerrotation;
+
+				person[i].playerrotation*=-1;
+
+				person[i].playervelocity=0;
+
+				if(person[i].targetanimation==getupfrontanim)person[i].playerrotation+=180;
+
+				for(int j=0;j<person[i].skeleton.num_joints;j++){
+
+					person[i].tempanimation.position[j][0]=person[i].skeleton.joints[j].position-person[i].playercoords;
+
+					person[i].tempanimation.position[j][0]=DoRotation(person[i].tempanimation.position[j][0],0,-person[i].playerrotation,0);
+
+				}
+
+			}
+
+		}
+
+		
+
+		//Grenade
+
+		if(Button()&&person[0].whichgun==grenade&&person[0].ammo>0&&person[0].reloading<=0&&person[0].attackframe<0&&person[0].targetanimation!=crouchanim){
+
+			if(person[0].grenphase==0){
+
+				XYZ soundsource=DoRotation(person[0].skeleton.joints[person[0].skeleton.jointlabels[righthand]].position,0,person[0].playerrotation,0)+person[0].playercoords;
+
+				float gLoc[3];
+
+				gLoc[0]=soundsource.x/soundscalefactor;
+
+				gLoc[1]=soundsource.y/soundscalefactor;
+
+				gLoc[2]=soundsource.z/soundscalefactor;
+
+				alSourcefv(gSourceID[pinpullsound], AL_POSITION, gLoc);
+
+				alSourcePlay(gSourceID[pinpullsound]);
+
+				person[0].grenphase=1;
+
+			}
+
+		}
+
+		if((!Button())&&person[0].whichgun==grenade){
+
+			if(person[0].grenphase==1){
+
+				person[0].grenphase=0;
+
+				person[0].attackframe=0;
+
+				person[0].attacktarget=0;
+
+				person[0].killtarget=0;
+
+			}
+
+		}
+
+		if(person[0].targetanimation==crouchanim){
+
+			if(person[0].grenphase==1){
+
+				person[0].grenphase=0;
+
+				XYZ soundsource=DoRotation(person[0].skeleton.joints[person[0].skeleton.jointlabels[righthand]].position,0,person[0].playerrotation,0)+person[0].playercoords;
+
+				float gLoc[3];
+
+				gLoc[0]=soundsource.x/soundscalefactor;
+
+				gLoc[1]=soundsource.y/soundscalefactor;
+
+				gLoc[2]=soundsource.z/soundscalefactor;
+
+				alSourcefv(gSourceID[pinreplacesound], AL_POSITION, gLoc);
+
+				alSourcePlay(gSourceID[pinreplacesound]);
+
+			}
+
+		}
+
+		
+
+		//Get gun
+
+		int temp;
+
+		int temp2;
+
+		bool switched=0;
+
+		if(Button()&&!oldbutton&&(person[0].aiming==0||person[0].whichgun==grenade||person[0].whichgun==nogun||person[0].whichgun==knife)&&person[0].currentanimation==crouchanim){
+
+			for(int i=0;i<max_people;i++){
+
+				if(!switched&&person[i].skeleton.free==1&&findDistancefast(person[0].playercoords,person[i].averageloc)<200){
+
+					float gLoc[3];
+
+					gLoc[0]=person[0].playercoords.x/soundscalefactor;
+
+					gLoc[1]=person[0].playercoords.y/soundscalefactor;
+
+					gLoc[2]=person[0].playercoords.z/soundscalefactor;
+
+
+
+					alSourcefv(gSourceID[clicksound], AL_POSITION, gLoc);
+
+					alSourcePlay(gSourceID[clicksound]);
+
+
+
+					temp=person[0].whichgun;
+
+					temp2=person[0].ammo;
+
+					person[0].whichgun=person[i].whichgun;
+
+					person[0].ammo=person[i].ammo;
+
+					person[i].whichgun=temp;
+
+					person[i].ammo=temp2;
+
+					person[0].aiming=1;
+
+					person[0].aimamount=0;
+
+					
+
+					switched=1;
+
+				}
+
+			}
+
+		}
+
+		
+
+		//Throw
+
+		if(Button()&&person[0].attackframe<0&&((person[0].whichgun==nogun||person[0].aiming==0)&&person[0].whichgun!=knife)&&person[0].currentanimation!=crouchanim&&person[0].targetanimation!=crouchanim&&person[0].targetanimation!=throwanim&&visions==0){
+
+			if(person[0].targetanimation==idleanim||person[0].targetanimation==walkanim){
+
+				bool attacking=0;
+
+				person[0].killtarget=-1;
+
+				float closedistance=-1;
+
+				for(int i=1;i<numpeople;i++){				
+
+					if(person[i].skeleton.free<1&&(person[i].whichgun!=nogun)&&findDistancefast(person[i].playercoords,person[0].playercoords+flatfacing)<12){
+
+						attacking=1;
+
+						if(person[0].killtarget==-1||findDistancefast(person[i].playercoords,person[0].playercoords)<closedistance){
+
+							person[0].killtarget=i;
+
+							closedistance=findDistancefast(person[i].playercoords,person[0].playercoords);
+
+						}
+
+					}
+
+				}
+
+				if(attacking){
+
+					score+=150;
+
+					person[0].aiming=1;
+
+					person[0].whichgun=person[person[0].killtarget].whichgun;
+
+					person[0].ammo=person[person[0].killtarget].ammo;
+
+					person[person[0].killtarget].whichgun=nogun;
+
+					person[person[0].killtarget].killtarget=-1;
+
+					person[0].targetframe=0;
+
+					person[0].targetanimation=throwanim;
+
+					person[0].target=1;
+
+					person[0].speed=1;
+
+					person[person[0].killtarget].targetframe=0;
+
+					person[person[0].killtarget].targetanimation=thrownanim;
+
+					person[person[0].killtarget].target=1;
+
+					person[person[0].killtarget].playercoords=person[0].playercoords;
+
+					person[person[0].killtarget].playerrotation=person[0].playerrotation;
+
+					person[person[0].killtarget].speed=person[0].speed;
+
+					person[person[0].killtarget].speedmult=1;
+
+				}
+
+			}
+
+		}
+
+		
+
+		//Gun whacking
+
+		if(Button()&&(person[0].aiming==0||person[0].ammo<=0||person[0].whichgun==nogun||person[0].whichgun==knife||person[0].targetanimation==joganim)&&person[0].currentanimation!=crouchanim&&person[0].targetanimation!=throwanim&&person[0].whichgun!=grenade&&person[0].targetanimation!=crouchanim&&visions==0){
+
+			if(person[0].attackframe==-1||person[person[0].killtarget].skeleton.free==1){
+
+				bool attacking=0;
+
+				person[0].killtarget=-1;
+
+				float closedistance=-1;
+
+				for(int i=1;i<numpeople;i++){				
+
+					if(person[i].existing&&person[i].type!=viptype&&person[i].skeleton.free<1&&findDistancefast(person[i].playercoords,person[0].playercoords+flatfacing)<12+(person[0].whichgun==knife)*10){
+
+						if(person[0].killtarget==-1||findDistancefast(person[i].playercoords,person[0].playercoords)<closedistance){
+
+							attacking=1;
+
+							person[0].killtarget=i;
+
+							closedistance=findDistancefast(person[i].playercoords,person[0].playercoords);
+
+						}
+
+					}
+
+				}
+
+				if(attacking){
+
+					person[0].attacktarget=0;
+
+					person[0].attackframe=0;
+
+				}
+
+				whacked=0;
+
+			}
+
+		}
+
+		
+
+		XYZ velocity;
+
+		
+
+		if(person[0].attackframe>1||(person[0].attackframe>=0&&person[0].currentanimation==joganim)){
+
+			if(person[person[0].killtarget].skeleton.free<1&&person[0].killtarget!=0&&(person[0].aiming<1||person[0].whichgun==nogun||person[0].whichgun==knife||person[0].targetanimation==joganim)){
+
+				float gLoc[3];
+
+				gLoc[0]=(camera.position.x+((person[0].playercoords.x+flatfacing.x)-camera.position.x)/2)/soundscalefactor;
+
+				gLoc[1]=(camera.position.y+((person[0].playercoords.y+flatfacing.y)-camera.position.y)/2)/soundscalefactor;
+
+				gLoc[2]=(camera.position.z+((person[0].playercoords.z+flatfacing.z)-camera.position.z)/2)/soundscalefactor;
+
+				if(person[person[0].killtarget].type!=zombietype)
+
+				{
+
+					if(person[0].whichgun!=knife){
+
+						alSourcefv(gSourceID[headwhacksound], AL_POSITION, gLoc);
+
+						alSourcePlay(gSourceID[headwhacksound]);
+
+					}
+
+					if(person[0].whichgun==knife){
+
+						alSourcefv(gSourceID[knifeslashsound], AL_POSITION, gLoc);
+
+						alSourcePlay(gSourceID[knifeslashsound]);
+
+						person[person[0].killtarget].bjoint1=&person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]];
+
+						person[person[0].killtarget].bjoint2=&person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]];
+
+						person[person[0].killtarget].bleeding=1;
+
+						person[person[0].killtarget].bleeddelay=1;
+
+						person[0].bjoint1=&person[0].skeleton.joints[person[0].skeleton.jointlabels[righthand]];
+
+						person[0].bjoint2=&person[0].skeleton.joints[person[0].skeleton.jointlabels[righthand]];
+
+						person[0].bleeding=1;
+
+						person[0].bleeddelay=1;
+
+						velocity=DoRotation(flatfacing,0,70,0)*50+person[0].velocity*2;
+
+						velocity.y+=30;
+
+						sprites.MakeSprite(bloodspritedown, .8, 1, .2, .2,DoRotation(person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]].position,0,person[person[0].killtarget].playerrotation,0)+person[person[0].killtarget].playercoords, velocity*.3, 2);
+
+						sprites.MakeSprite(bloodspritedown, .8, 1, .2, .2,DoRotation(person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]].position,0,person[person[0].killtarget].playerrotation,0)+person[person[0].killtarget].playercoords, velocity*.2, 3);
+
+						sprites.MakeSprite(bloodspritedown, .8, 1, .2, .2,DoRotation(person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]].position,0,person[person[0].killtarget].playerrotation,0)+person[person[0].killtarget].playercoords, velocity*.1, 4);					
+
+					}
+
+					person[person[0].killtarget].health-=100;
+
+					person[person[0].killtarget].skeleton.free=1;
+
+					person[person[0].killtarget].longdead=1;
+
+					for(int j=0;j<person[person[0].killtarget].skeleton.num_joints;j++){
+
+						person[person[0].killtarget].skeleton.joints[j].position=DoRotation(person[person[0].killtarget].skeleton.joints[j].position,0,person[person[0].killtarget].playerrotation,0);
+
+						person[person[0].killtarget].skeleton.joints[j].position+=person[person[0].killtarget].playercoords;
+
+						person[person[0].killtarget].skeleton.joints[j].realoldposition=person[person[0].killtarget].skeleton.joints[j].position;
+
+						person[person[0].killtarget].skeleton.joints[j].velocity=person[person[0].killtarget].velocity;
+
+						person[person[0].killtarget].skeleton.joints[j].velocity.x+=abs(Random()%10)-5;
+
+						person[person[0].killtarget].skeleton.joints[j].velocity.y+=abs(Random()%10)-5;
+
+						person[person[0].killtarget].skeleton.joints[j].velocity.z+=abs(Random()%10)-5;
+
+					}
+
+					if(person[0].whichgun!=knife){
+
+						person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[head]].velocity+=DoRotation(flatfacing,0,40,0)*50;
+
+						person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[head]].velocity+=person[0].velocity*2;
+
+					}
+
+				}
+
+				else
+
+				{
+
+					if(whacked==0){
+
+						whacked=1;
+
+						if(person[0].whichgun!=knife){
+
+							alSourcefv(gSourceID[headwhacksound], AL_POSITION, gLoc);
+
+							alSourcePlay(gSourceID[headwhacksound]);
+
+						}
+
+						if(person[0].whichgun==knife){
+
+							alSourcefv(gSourceID[knifeslashsound], AL_POSITION, gLoc);
+
+							alSourcePlay(gSourceID[knifeslashsound]);
+
+							person[person[0].killtarget].bjoint1=&person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]];
+
+							person[person[0].killtarget].bjoint2=&person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]];
+
+							person[person[0].killtarget].bleeding=1;
+
+							person[person[0].killtarget].bleeddelay=1;
+
+							person[0].bjoint1=&person[0].skeleton.joints[person[0].skeleton.jointlabels[righthand]];
+
+							person[0].bjoint2=&person[0].skeleton.joints[person[0].skeleton.jointlabels[righthand]];
+
+							person[0].bleeding=1;
+
+							person[0].bleeddelay=1;
+
+							velocity=DoRotation(flatfacing,0,70,0)*50+person[0].velocity*2;
+
+							velocity.y+=30;
+
+							sprites.MakeSprite(bloodspritedown, .8, 1, .2, .2,DoRotation(person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]].position,0,person[person[0].killtarget].playerrotation,0)+person[person[0].killtarget].playercoords, velocity*.3, 2);
+
+							sprites.MakeSprite(bloodspritedown, .8, 1, .2, .2,DoRotation(person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]].position,0,person[person[0].killtarget].playerrotation,0)+person[person[0].killtarget].playercoords, velocity*.2, 3);
+
+							sprites.MakeSprite(bloodspritedown, .8, 1, .2, .2,DoRotation(person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]].position,0,person[person[0].killtarget].playerrotation,0)+person[person[0].killtarget].playercoords, velocity*.1, 4);					
+
+						}
+
+						person[person[0].killtarget].health-=200;
+
+						person[person[0].killtarget].maxhealth-=20;
+
+						person[person[0].killtarget].skeleton.free=1;
+
+						person[person[0].killtarget].longdead=1;
+
+						for(int j=0;j<person[person[0].killtarget].skeleton.num_joints;j++){
+
+							person[person[0].killtarget].skeleton.joints[j].position=DoRotation(person[person[0].killtarget].skeleton.joints[j].position,0,person[person[0].killtarget].playerrotation,0);
+
+							person[person[0].killtarget].skeleton.joints[j].position+=person[person[0].killtarget].playercoords;
+
+							person[person[0].killtarget].skeleton.joints[j].realoldposition=person[person[0].killtarget].skeleton.joints[j].position;
+
+							person[person[0].killtarget].skeleton.joints[j].velocity=person[person[0].killtarget].velocity;
+
+							person[person[0].killtarget].skeleton.joints[j].velocity.x+=abs(Random()%10)-5;
+
+							person[person[0].killtarget].skeleton.joints[j].velocity.y+=abs(Random()%10)-5;
+
+							person[person[0].killtarget].skeleton.joints[j].velocity.z+=abs(Random()%10)-5;
+
+						}
+
+						if(person[0].whichgun!=knife){
+
+							person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[head]].velocity+=DoRotation(flatfacing,0,40,0)*50;
+
+							person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[head]].velocity+=person[0].velocity*2;
+
+						}
+
+					}
+
+				}
+
+			}
+
+		}
+
+		
+
+		//Tackle
+
+		if(person[0].currentanimation==diveanim&&visions==0){
+
+			for(int i=1;i<numpeople;i++){				
+
+				if(person[i].skeleton.free<1&&findDistancefast(person[i].playercoords,person[0].playercoords+flatfacing)<22){
+
+					float gLoc[3];
+
+					gLoc[0]=(camera.position.x+((person[0].playercoords.x+flatfacing.x)-camera.position.x)/2)/soundscalefactor;
+
+					gLoc[1]=(camera.position.y+((person[0].playercoords.y+flatfacing.y)-camera.position.y)/2)/soundscalefactor;
+
+					gLoc[2]=(camera.position.z+((person[0].playercoords.z+flatfacing.z)-camera.position.z)/2)/soundscalefactor;
+
+					alSourcefv(gSourceID[headwhacksound], AL_POSITION, gLoc);
+
+					alSourcePlay(gSourceID[headwhacksound]);
+
+					person[i].skeleton.free=1;
+
+					person[i].longdead=1;
+
+					for(int j=0;j<person[i].skeleton.num_joints;j++){
+
+						person[i].skeleton.joints[j].position=DoRotation(person[i].skeleton.joints[j].position,0,person[i].playerrotation,0);
+
+						person[i].skeleton.joints[j].position+=person[i].playercoords;
+
+						person[i].skeleton.joints[j].realoldposition=person[i].skeleton.joints[j].position;
+
+						person[i].skeleton.joints[j].velocity=person[0].velocity;
+
+						person[i].skeleton.joints[j].velocity.y=-10;
+
+						person[i].skeleton.joints[j].velocity.x+=abs(Random()%10)-5;
+
+						person[i].skeleton.joints[j].velocity.y+=abs(Random()%10)-5;
+
+						person[i].skeleton.joints[j].velocity.z+=abs(Random()%10)-5;
+
+					}
+
+				}
+
+			}
+
+		}
+
+		
+
+		//Fire/wing
+
+		XYZ wallhit;
+
+		XYZ start;
+
+		XYZ finalwallhit;
+
+		bool firing;
+
+		float inaccuracy = 0.0;
+
+		int numshots;
+
+		XYZ hitnorm;
+
+		XYZ hitmove;
+
+		int hitpoly=0;
+
+		float hitrotation = 0.0f;
+
+		Model *model = NULL;
+
+		for(int j=0;j<numpeople;j++){
+
+			if(person[j].type==playertype||person[j].type==eviltype){
+
+			firing=0;
+
+			if(person[j].ammo>0&&person[j].reloading<=0&&person[j].targetanimation!=joganim){
+
+				if(Button()&&!oldbutton&&j==0)firing=1;
+
+				if(j!=0)firing=0;
+
+				if(j!=0&&person[j].whichgun!=nogun&&person[j].whichgun!=knife&&person[j].killtargetvisible&&person[j].shotdelay<0)firing=1;
+
+				if(j!=0&&person[j].whichgun!=nogun&&person[j].whichgun!=knife&&person[j].killtargetvisible&&person[j].shotdelay>0)person[j].shotdelay-=multiplier*.9;
+
+				if(person[j].skeleton.free==1||person[j].targetanimation==getupfrontanim||person[j].targetanimation==getupbackanim)person[j].shotdelay=shotdelayamount/difficulty;
+
+				if(j!=0&&person[j].whichgun!=nogun&&person[j].whichgun!=knife&&person[j].killtargetvisible)person[j].aiming=1;
+
+				if(person[0].whichgun!=assaultrifle)oldbutton=1;
+
+			}
+
+			if(person[j].ammo==0&&person[j].reloads[person[j].whichgun]>0){
+
+				person[j].ammo=-1;
+
+				person[j].aiming=0;
+
+				firing=0;
+
+			}
+
+			if(person[0].ammo<=0&&Button()&&!oldbutton&&person[0].targetanimation!=joganim&&person[0].whichgun!=nogun&&person[0].whichgun!=knife&&person[0].whichgun!=grenade&&person[0].aiming){
+
+				oldbutton=1;
+
+				float gLoc[3];
+
+				gLoc[0]=person[0].playercoords.x/soundscalefactor;
+
+				gLoc[1]=person[0].playercoords.y/soundscalefactor;
+
+				gLoc[2]=person[0].playercoords.z/soundscalefactor;
+
+
+
+				alSourcefv(gSourceID[clicksound], AL_POSITION, gLoc);
+
+				alSourcePlay(gSourceID[clicksound]);
+
+			}
+
+			if(j==0&&visions==1&&firing){
+
+				firing=0;
+
+				alSourcePlay(gSourceID[soulinsound]);
+
+			}
+
+			if(person[j].aimamount<1)firing=0;
+
+			if(firing){
+
+				if(person[j].whichgun==handgun1||person[j].whichgun==handgun2)inaccuracy=8;
+
+				if(person[j].whichgun==assaultrifle)inaccuracy=6;
+
+				if(person[j].whichgun==sniperrifle)inaccuracy=2;
+
+				if(person[j].whichgun==shotgun)inaccuracy=6;
+
+				if(person[person[j].killtarget].skeleton.free==1)inaccuracy*=3;
+
+
+
+				person[j].shotdelay=shotdelayamount/difficulty;
+
+				if(person[j].aiming>=1&&person[j].recoil<=0){
+
+					//Firing
+
+					person[j].litup=1;
+
+					person[j].recoil=1;
+
+					XYZ end, aim, oldend;
+
+					HitStruct hitstruct,temphitstruct;
+
+					float olddistance = 0.0f;
+
+					float distance = 0.0f;
+
+					float totalarea = 0.0f;
+
+					int whichhit=-1;
+
+					if(person[j].whichgun==shotgun)numshots=7;
+
+					if(person[j].whichgun!=shotgun)numshots=1;
+
+					if(person[j].whichgun!=grenade)person[j].ammo--;
+
+					for(int p=0;p<numshots;p++){
+
+					if(!zoom||j!=0){
+
+						if(person[j].whichgun==assaultrifle)aim=DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[lefthand])].position-person[j].skeleton.joints[(person[j].skeleton.jointlabels[righthand])].position,0,person[j].playerrotation-2.5,0);
+
+						if(person[j].whichgun==sniperrifle)aim=DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[lefthand])].position-person[j].skeleton.joints[(person[j].skeleton.jointlabels[righthand])].position,0,person[j].playerrotation+4,0);
+
+						if(person[j].whichgun==shotgun)aim=DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[lefthand])].position-person[j].skeleton.joints[(person[j].skeleton.jointlabels[righthand])].position,2+(float)(Random()%1000)/500,0,0);
+
+						if(person[j].whichgun==shotgun)aim=DoRotation(aim,0,person[j].playerrotation-1+(float)(Random()%1000)/500,0);
+
+						if(person[j].whichgun==handgun1&&!thirdperson&&j==0)aim=DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[righthand])].position-(person[j].skeleton.joints[person[j].skeleton.jointlabels[head]].position*.65+person[j].skeleton.joints[person[j].skeleton.jointlabels[neck]].position*.35),0,person[j].playerrotation-.9,0);
+
+						if(person[j].whichgun==handgun1&&(thirdperson||j!=0))aim=DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[righthand])].position-(person[j].skeleton.joints[person[j].skeleton.jointlabels[head]].position*.35+person[j].skeleton.joints[person[j].skeleton.jointlabels[neck]].position*.65),0,person[j].playerrotation-.9,0);
+
+						if(person[j].whichgun==handgun2&&!thirdperson&&j==0)aim=DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[righthand])].position-(person[j].skeleton.joints[person[j].skeleton.jointlabels[head]].position*.65+person[j].skeleton.joints[person[j].skeleton.jointlabels[neck]].position*.35),0,person[j].playerrotation-.9,0);
+
+						if(person[j].whichgun==handgun2&&(thirdperson||j!=0))aim=DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[righthand])].position-(person[j].skeleton.joints[person[j].skeleton.jointlabels[head]].position*.35+person[j].skeleton.joints[person[j].skeleton.jointlabels[neck]].position*.65),0,person[j].playerrotation-.9,0);
+
+						if(j!=0&&person[person[j].killtarget].skeleton.free==0)aim=(DoRotation(person[person[j].killtarget].skeleton.joints[person[person[j].killtarget].skeleton.jointlabels[abdomen]].position,0,person[person[j].killtarget].playerrotation,0)+person[person[j].killtarget].playercoords)-(DoRotation(person[j].skeleton.joints[person[j].skeleton.jointlabels[lefthand]].position,0,person[j].playerrotation,0)+person[j].playercoords);
+
+						if(j!=0&&person[person[j].killtarget].skeleton.free!=0)aim=person[person[j].killtarget].skeleton.joints[person[person[j].killtarget].skeleton.jointlabels[abdomen]].position-(DoRotation(person[j].skeleton.joints[person[j].skeleton.jointlabels[lefthand]].position,0,person[j].playerrotation,0)+person[j].playercoords);
+
+						if(j!=0)aim=DoRotation(DoRotation(DoRotation(aim,0,-person[j].playerrotation,0),(float)(abs(Random()%2000))/2000*inaccuracy-inaccuracy/2,(float)(abs(Random()%2000))/2000*inaccuracy-inaccuracy/2,0),0,person[j].playerrotation,0);
+
+					}
+
+					if(zoom&&j==0){
+
+						start=camera.position;
+
+						aim=facing;
+
+					}
+
+					Normalise(&aim);
+
+					if(person[j].whichgun==sniperrifle){
+
+						start=person[j].playercoords+DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[lefthand])].position,0,person[j].playerrotation,0);
+
+						float gLoc[3];
+
+						
+
+						start-=DoRotation(DoRotation(DoRotation(aim,0,-person[j].playerrotation,0),90,0,0),0,person[j].playerrotation,0)*.35;
+
+						
+
+						gLoc[0]=(camera.position.x+(start.x-camera.position.x)/4)/soundscalefactor;
+
+						gLoc[1]=(camera.position.y+(start.y-camera.position.y)/4)/soundscalefactor;
+
+						gLoc[2]=(camera.position.z+(start.z-camera.position.z)/4)/soundscalefactor;
+
+						alSourcefv(gSourceID[riflesound], AL_POSITION, gLoc);
+
+						alSourcePlay(gSourceID[riflesound]);
+
+						if(j==0){
+
+							if(person[j].currentanimation!=crouchanim)camera.rotation2-=7;
+
+							if(person[j].currentanimation==crouchanim)camera.rotation2-=3;
+
+						}
+
+					}
+
+					if(person[j].whichgun==shotgun){
+
+						start=person[j].playercoords+DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[lefthand])].position,0,person[j].playerrotation,0);
+
+						float gLoc[3];
+
+						
+
+						start-=DoRotation(DoRotation(DoRotation(aim,0,-person[j].playerrotation,0),90,0,0),0,person[j].playerrotation,0)*.35;
+
+						
+
+						if(p==numshots-1){
+
+						gLoc[0]=(camera.position.x+(start.x-camera.position.x)/4)/soundscalefactor;
+
+						gLoc[1]=(camera.position.y+(start.y-camera.position.y)/4)/soundscalefactor;
+
+						gLoc[2]=(camera.position.z+(start.z-camera.position.z)/4)/soundscalefactor;
+
+						alSourcefv(gSourceID[shotgunsound], AL_POSITION, gLoc);
+
+						alSourcePlay(gSourceID[shotgunsound]);
+
+						if(j==0){
+
+							if(person[j].currentanimation!=crouchanim)camera.rotation2-=7;
+
+							if(person[j].currentanimation==crouchanim)camera.rotation2-=3;
+
+						}
+
+						}
+
+					}
+
+					if(person[j].whichgun==handgun1){
+
+						start=person[j].playercoords+DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[rightwrist])].position,0,person[j].playerrotation,0);
+
+						start-=DoRotation(DoRotation(DoRotation(aim,0,-person[j].playerrotation,0),90,0,0),0,person[j].playerrotation,0)*.55;
+
+						
+
+						float gLoc[3];
+
+						
+
+						gLoc[0]=(camera.position.x+(start.x-camera.position.x)/4)/soundscalefactor;
+
+						gLoc[1]=(camera.position.y+(start.y-camera.position.y)/4)/soundscalefactor;
+
+						gLoc[2]=(camera.position.z+(start.z-camera.position.z)/4)/soundscalefactor;
+
+						alSourcefv(gSourceID[pistol1sound], AL_POSITION, gLoc);
+
+						alSourcePlay(gSourceID[pistol1sound]);
+
+						if(j==0){
+
+							if(person[j].currentanimation!=crouchanim)camera.rotation2-=6;
+
+							if(person[j].currentanimation==crouchanim)camera.rotation2-=4;
+
+						}
+
+					}
+
+					if(person[j].whichgun==handgun2){
+
+						start=person[j].playercoords+DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[rightwrist])].position,0,person[j].playerrotation,0);
+
+						start-=DoRotation(DoRotation(DoRotation(aim,0,-person[j].playerrotation,0),90,0,0),0,person[j].playerrotation,0)*.55;
+
+						
+
+						float gLoc[3];
+
+						
+
+						gLoc[0]=(camera.position.x+(start.x-camera.position.x)/4)/soundscalefactor;
+
+						gLoc[1]=(camera.position.y+(start.y-camera.position.y)/4)/soundscalefactor;
+
+						gLoc[2]=(camera.position.z+(start.z-camera.position.z)/4)/soundscalefactor;
+
+						alSourcefv(gSourceID[pistol2sound], AL_POSITION, gLoc);
+
+						alSourcePlay(gSourceID[pistol2sound]);
+
+						if(j==0){
+
+							if(person[j].currentanimation!=crouchanim)camera.rotation2-=5;
+
+							if(person[j].currentanimation==crouchanim)camera.rotation2-=3;
+
+						}
+
+					}
+
+					if(person[j].whichgun==assaultrifle){
+
+						start=person[j].playercoords+DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[lefthand])].position,0,person[j].playerrotation,0);
+
+						start-=DoRotation(DoRotation(DoRotation(aim,0,-person[j].playerrotation,0),90,0,0),0,person[j].playerrotation,0)*.25;
+
+						
+
+						float gLoc[3];
+
+						gLoc[0]=(camera.position.x+(start.x-camera.position.x)/4)/soundscalefactor;
+
+						gLoc[1]=(camera.position.y+(start.y-camera.position.y)/4)/soundscalefactor;
+
+						gLoc[2]=(camera.position.z+(start.z-camera.position.z)/4)/soundscalefactor;
+
+						alSourcefv(gSourceID[machinegunsound], AL_POSITION, gLoc);
+
+						alSourcePlay(gSourceID[machinegunsound]);
+
+						if(j==0){
+
+							if(person[j].currentanimation!=crouchanim){
+
+								camera.rotation2-=2.3;
+
+								camera.rotation+=(float)(Random()%100)/50;
+
+							}
+
+							if(person[j].currentanimation==crouchanim){
+
+								camera.rotation2-=1.5;
+
+								camera.rotation+=(float)(Random()%100)/60;
+
+							}
+
+						}
+
+					}
+
+					end=start+aim*1000;
+
+					if(debug){
+
+					if(IsKeyDown(theKeyMap, MAC_G_KEY)&&j==0){
+
+						sprites.MakeSprite(grenadesprite, 1, 1, 1, 1, start, aim*200, 1.01);
+
+					}
+
+					}
+
+					if(!IsKeyDown(theKeyMap, MAC_G_KEY)||j!=0||!debug){
+
+					int bulletstrength=1;
+
+					int firstpass=-1;
+
+					bool penetrate;
+
+					for(int m=0;m<bulletstrength;m++){
+
+						//People
+
+						whichhit=-1;
+
+						for(int i=0;i<numpeople;i++){
+
+							if(i!=j&&i!=firstpass&&person[i].existing){
+
+								temphitstruct=person[i].BulletCollideWithPlayer(i, start, end);	
+
+								if(temphitstruct.collision){
+
+									distance=findDistancefast(start,temphitstruct.hitlocation);
+
+									if(distance<olddistance||whichhit==-1){
+
+										end=temphitstruct.hitlocation;
+
+										olddistance=distance;
+
+										hitstruct=temphitstruct;
+
+										whichhit=i;
+
+									}
+
+								}
+
+							}
+
+						}
+
+						//Blocks
+
+						wallhit=0;
+
+						beginx=(person[j].playercoords.x+block_spacing/2)/block_spacing-3;
+
+						if(beginx<0)beginx=0;
+
+						beginz=(person[j].playercoords.z+block_spacing/2)/block_spacing-3;
+
+						if(beginz<0)beginz=0;
+
+						
+
+						endx=(person[j].playercoords.x+block_spacing/2)/block_spacing+3;
+
+						if(endx>num_blocks-1)endx=num_blocks-1;
+
+						endz=(person[j].playercoords.z+block_spacing/2)/block_spacing+3;
+
+						if(endz>num_blocks-1)endz=num_blocks-1;
+
+						
+
+						if(beginx<endx&&beginz<endz)
+
+						finalwallhit=0;
+
+						for(int i=beginx;i<=endx;i++)
+
+							for(int j=beginz;j<=endz;j++){
+
+								move=0;
+
+								move.x=i*block_spacing;
+
+								move.z=j*block_spacing;
+
+								whichtri=blocks[citytype[i][j]].LineCheck2(start,end,&wallhit,move,cityrotation[i][j]*90);
+
+								if(whichtri!=-1){
+
+									whichhit=-1;
+
+									end=wallhit;
+
+									finalwallhit=wallhit;
+
+									hitnorm=DoRotation(blocks[citytype[i][j]].normals[whichtri],0,cityrotation[i][j]*90,0);
+
+									hitmove=move;
+
+									hitrotation=cityrotation[i][j]*90;
+
+									hitpoly=whichtri;
+
+									model=&blocks[citytype[i][j]];
+
+									if(j==0&&blocks[citytype[i][j]].normals[whichtri].y>.9)bulletstrength=2;
+
+								}
+
+							}
+
+						wallhit=0;
+
+						wallhit.x=camera.position.x;
+
+						wallhit.z=camera.position.z;
+
+						whichtri=Bigstreet.LineCheck2(start,end,&wallhit,wallhit,0);
+
+						if(whichtri!=-1){
+
+							end.y-=.5;
+
+							end=wallhit;
+
+							finalwallhit=wallhit;
+
+							bulletstrength=2;
+
+							hitnorm=0;
+
+							hitnorm.y=1;
+
+							hitmove=0;
+
+							hitrotation=0;
+
+						}
+
+						if(m==0){
+
+							if(j==0&&slomo==2){
+
+								soundscalefactor=soundscalefactordefault;
+
+								alSourceStop(gSourceID[whichsong]);
+
+								alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 0);
+
+								alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 0);
+
+								if(person[0].whichgun==knife)whichsong=knifesong;
+
+								if(person[0].whichgun!=knife)whichsong=shootsong;
+
+								if(type==zombie_type)whichsong=zombiesong;
+
+								alSourcef(gSourceID[whichsong], AL_PITCH, 1);
+
+								alSourcePlay(gSourceID[whichsong]);
+
+								alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 1);
+
+								alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 1);
+
+								slomo=0;
+
+								if(whichhit==-1)alSourcePlay(gSourceID[disguisekillsound]);
+
+								flashamount=.5;
+
+								flashr=1;flashg=1;flashb=1;
+
+							}
+
+						}
+
+						//Impact
+
+						oldend=end;
+
+						//with person
+
+						if(whichhit!=-1&&whichhit!=firstpass){
+
+							if(j==0)person[whichhit].dead=1;
+
+							if(whichhit==1){
+
+								murderer=j;
+
+							}
+
+							if(person[whichhit].health==100&&j==0){
+
+								if(person[whichhit].type==civiliantype)civkills++;
+
+								if(person[whichhit].type==eviltype)goodkills++;
+
+							}
+
+							if(person[whichhit].health==100&&j!=0){
+
+								badkills++;
+
+							}
+
+							//penetrate
+
+								penetrate=abs(Random()%2)==1;
+
+								if(numshots>1)penetrate=0;
+
+								if(penetrate){bulletstrength=2;
+
+								firstpass=whichhit;
+
+								end=start+aim*1000;}
+
+							if(person[j].whichgun==assaultrifle)person[whichhit].health-=20;
+
+							if(person[j].whichgun==assaultrifle&&person[whichhit].type==zombietype)person[whichhit].health-=60;
+
+							if(person[j].whichgun==handgun1){
+
+								if(person[whichhit].type!=zombietype)person[whichhit].health-=100;
+
+								if(person[whichhit].type==zombietype)person[whichhit].health-=100;
+
+								person[whichhit].DoAnimations(whichhit);
+
+							}
+
+							if(person[j].whichgun==handgun2)person[whichhit].health-=20;
+
+							if(person[j].whichgun==handgun2&&person[whichhit].type==zombietype)person[whichhit].health-=60;
+
+							if(person[j].whichgun==sniperrifle&&m!=0)person[whichhit].health-=30;
+
+							if(person[j].whichgun==shotgun)person[whichhit].health-=60;
+
+							if(person[j].whichgun==sniperrifle&&m==0){
+
+								if(person[whichhit].type!=zombietype)person[whichhit].health-=100;
+
+								if(person[whichhit].type==zombietype)person[whichhit].health-=120;
+
+								person[whichhit].DoAnimations(whichhit);
+
+							}
+
+							if(hitstruct.joint1->modelnum==headmodel&&person[whichhit].type!=zombietype){
+
+								person[whichhit].health-=60;
+
+							}
+
+							if(person[whichhit].type==zombietype)person[whichhit].speedmult-=.05;
+
+							if(person[whichhit].type==zombietype)person[whichhit].maxhealth-=10;
+
+							if(whichhit==0){
+
+								bulletstrength=1;
+
+								person[0].health=100;
+
+								flashr=0;
+
+								flashg=0;
+
+								flashb=0;
+
+								flashamount=1;
+
+								float gLoc[3];
+
+								gLoc[0]=hitstruct.hitlocation.x/soundscalefactor;
+
+								gLoc[1]=hitstruct.hitlocation.y/soundscalefactor;
+
+								gLoc[2]=hitstruct.hitlocation.z/soundscalefactor;
+
+								alSourcefv(gSourceID[bodywhacksound], AL_POSITION, gLoc);
+
+								alSourcePlay(gSourceID[bodywhacksound]);
+
+							}
+
+							person[whichhit].longdead=1;
+
+							
+
+							if(person[whichhit].health<=0){
+
+								person[whichhit].skeleton.offset=0;
+
+								if(person[whichhit].skeleton.free!=1){
+
+									person[whichhit].skeleton.free=1;
+
+									totalarea=0;
+
+									for(int j=0;j<person[whichhit].skeleton.num_joints;j++){
+
+										person[whichhit].skeleton.joints[j].position=DoRotation(person[whichhit].skeleton.joints[j].position,0,person[whichhit].playerrotation,0);
+
+										person[whichhit].skeleton.joints[j].position+=person[whichhit].playercoords;
+
+										person[whichhit].skeleton.joints[j].realoldposition=person[whichhit].skeleton.joints[j].position;
+
+										person[whichhit].skeleton.joints[j].velocity=person[whichhit].velocity;
+
+										person[whichhit].skeleton.joints[j].velocity.x+=(float)(abs(Random()%20)-10)/2;
+
+										person[whichhit].skeleton.joints[j].velocity.y+=(float)(abs(Random()%20)-10)/2;
+
+										person[whichhit].skeleton.joints[j].velocity.z+=(float)(abs(Random()%20)-10)/2;
+
+									}
+
+								}
+
+								for(int j=0;j<person[whichhit].skeleton.num_joints;j++){
+
+									if(findDistancefast(person[whichhit].skeleton.joints[j].position,hitstruct.hitlocation)<200){
+
+										totalarea+=(200/findDistancefast(person[whichhit].skeleton.joints[j].position,hitstruct.hitlocation));
+
+									}
+
+								}
+
+								for(int j=0;j<person[whichhit].skeleton.num_joints;j++){
+
+									if(findDistancefast(person[whichhit].skeleton.joints[j].position,hitstruct.hitlocation)<200){
+
+										person[whichhit].skeleton.joints[j].velocity+=aim*((200/findDistancefast(person[whichhit].skeleton.joints[j].position,hitstruct.hitlocation))/totalarea*200);
+
+									}
+
+								}
+
+							}
+
+							if(person[whichhit].health>0){
+
+								if(person[whichhit].killtargetvisible==0&&person[whichhit].type!=zombietype&&person[whichhit].currentanimation!=getupfrontanim&person[whichhit].currentanimation!=getupbackanim){
+
+									if(hitstruct.joint1->modelnum==headmodel)person[whichhit].targetanimation=headpainanim;
+
+									if(hitstruct.joint1->modelnum==chestmodel)person[whichhit].targetanimation=chestpainanim;
+
+									if(hitstruct.joint1->modelnum==abdomenmodel)person[whichhit].targetanimation=stomachpainanim;
+
+									if(hitstruct.joint1->label==rightelbow||hitstruct.joint1->label==rightshoulder||hitstruct.joint1->label==rightwrist||hitstruct.joint1->label==righthand)person[whichhit].targetanimation=rightarmpainanim;
+
+									if(hitstruct.joint1->label==leftelbow||hitstruct.joint1->label==leftshoulder||hitstruct.joint1->label==leftwrist||hitstruct.joint1->label==lefthand)person[whichhit].targetanimation=leftarmpainanim;
+
+									if(hitstruct.joint1->label==rightknee||hitstruct.joint1->label==righthip||hitstruct.joint1->label==rightankle||hitstruct.joint1->label==rightfoot)person[whichhit].targetanimation=rightlegpainanim;
+
+									if(hitstruct.joint1->label==leftknee||hitstruct.joint1->label==lefthip||hitstruct.joint1->label==leftankle||hitstruct.joint1->label==leftfoot)person[whichhit].targetanimation=leftlegpainanim;
+
+									person[whichhit].targetframe=0;
+
+									person[whichhit].target=0;
+
+								}
+
+								person[whichhit].skeleton.offset=1;
+
+								for(int j=0;j<person[whichhit].skeleton.num_joints;j++){
+
+									if(findDistancefast(DoRotation(person[whichhit].skeleton.joints[j].position,0,person[whichhit].playerrotation,0)+person[whichhit].playercoords,hitstruct.hitlocation)<200){
+
+										totalarea+=(200/findDistancefast(DoRotation(person[whichhit].skeleton.joints[j].position,0,person[whichhit].playerrotation,0)+person[whichhit].playercoords,hitstruct.hitlocation));
+
+									}
+
+								}
+
+								float offsetlength;
+
+								for(int j=0;j<person[whichhit].skeleton.num_joints;j++){
+
+									if(findDistancefast(DoRotation(person[whichhit].skeleton.joints[j].position,0,person[whichhit].playerrotation,0)+person[whichhit].playercoords,hitstruct.hitlocation)<200){
+
+										person[whichhit].skeleton.joints[j].offset+=DoRotation(aim*((200/findDistancefast(DoRotation(person[whichhit].skeleton.joints[j].position,0,person[whichhit].playerrotation,0)+person[whichhit].playercoords,hitstruct.hitlocation))/totalarea*10),0,-person[whichhit].playerrotation,0);
+
+									}
+
+									offsetlength=findLengthfast(person[whichhit].skeleton.joints[j].offset);
+
+									if(offsetlength>36){
+
+										Normalise(&person[whichhit].skeleton.joints[j].offset);
+
+										person[whichhit].skeleton.joints[j].offset*=6;
+
+									}
+
+								}
+
+							}
+
+							if(hitstruct.joint1->modelnum==headmodel&&person[whichhit].health<=0){
+
+								for(int j=0;j<person[whichhit].skeleton.num_joints;j++){
+
+									if(&person[whichhit].skeleton.joints[j]==hitstruct.joint1||&person[whichhit].skeleton.joints[j]==hitstruct.joint2){
+
+										if(j!=person[whichhit].skeleton.jointlabels[abdomen]&&j!=person[whichhit].skeleton.jointlabels[groin]&&j!=person[whichhit].skeleton.jointlabels[neck]){
+
+											sprites.MakeSprite(bloodspritedown, .8, 1, .2, .2,person[whichhit].skeleton.joints[j].position, person[whichhit].skeleton.joints[j].velocity/3, 9);
+
+											sprites.MakeSprite(bloodspritedown, .8, 1, .2, .2,person[whichhit].skeleton.joints[j].position, DoRotation(person[whichhit].skeleton.joints[j].velocity/3,Random()%360,Random()%360,0)/5, 5);
+
+											sprites.MakeSprite(bloodspritedown, .8, 1, .2, .2,person[whichhit].skeleton.joints[j].position, DoRotation(person[whichhit].skeleton.joints[j].velocity/3,Random()%360,Random()%360,0)/5, 5);
+
+											sprites.MakeSprite(bloodspritedown, .8, 1, .2, .2,person[whichhit].skeleton.joints[j].position, DoRotation(person[whichhit].skeleton.joints[j].velocity/3,Random()%360,Random()%360,0)/5, 5);
+
+											sprites.MakeSprite(bloodspritedown, .8, 1, .2, .2,person[whichhit].skeleton.joints[j].position, DoRotation(person[whichhit].skeleton.joints[j].velocity/3,Random()%360,Random()%360,0)/5, 5);
+
+											person[whichhit].skeleton.DeleteJoint(j);
+
+											person[whichhit].skeleton.broken=1;
+
+											person[whichhit].health=-10000;
+
+											person[whichhit].skeleton.joints[j].existing=0;
+
+											if(person[whichhit].type==zombietype)score+=300;
+
+										}
+
+									}
+
+								}
+
+							}
+
+							
+
+							XYZ velocity;
+
+							velocity=aim*-8;
+
+							//blood
+
+							if(!hitstruct.joint1->modelnum==headmodel){
+
+							if(person[j].whichgun==sniperrifle)sprites.MakeSprite(bloodspritenoup, 1, 1, 0, 0, hitstruct.hitlocation, velocity*0, 5);
+
+							if(person[j].whichgun==sniperrifle&&penetrate)sprites.MakeSprite(bloodspritenoup, 1, 1, 0, 0, hitstruct.hitlocation, velocity*-3, 7);
+
+							if(person[j].whichgun==shotgun)sprites.MakeSprite(bloodspritenoup, 1, 1, 0, 0, hitstruct.hitlocation, velocity*0, 5);
+
+							if(person[j].whichgun==shotgun&&penetrate)sprites.MakeSprite(bloodspritenoup, 1, 1, 0, 0, hitstruct.hitlocation, velocity*-3, 7);
+
+							if(person[j].whichgun==assaultrifle)sprites.MakeSprite(bloodspritenoup, 1, 1, 0, 0, hitstruct.hitlocation, velocity*0, 3);
+
+							if(person[j].whichgun==assaultrifle&&penetrate)sprites.MakeSprite(bloodspritenoup, 1, 1, 0, 0, hitstruct.hitlocation, velocity*-3, 7);
+
+							if(person[j].whichgun==handgun1)sprites.MakeSprite(bloodspritenoup, 1, 1, 0, 0, hitstruct.hitlocation, velocity*0, 3);
+
+							if(person[j].whichgun==handgun1&&penetrate)sprites.MakeSprite(bloodspritenoup, 1, 1, 0, 0, hitstruct.hitlocation, velocity*-3, 4);
+
+							if(person[j].whichgun==handgun2)sprites.MakeSprite(bloodspritenoup, 1, 1, 0, 0, hitstruct.hitlocation, velocity*0, 3);
+
+							if(person[j].whichgun==handgun2&&penetrate)sprites.MakeSprite(bloodspritenoup, 1, 1, 0, 0, hitstruct.hitlocation, velocity*-3, 4);
+
+							}else{
+
+								sprites.MakeSprite(bloodspritenoup, 1, 1, .2, .2, hitstruct.hitlocation, velocity*0, 6);
+
+								sprites.MakeSprite(bloodspritenoup, 1, 1, .5, .5, hitstruct.hitlocation, velocity*-2, 7);
+
+								sprites.MakeSprite(bloodspritenoup, 1, 1, .2, .2, hitstruct.hitlocation, velocity*-3, 10);
+
+							}
+
+							
+
+							person[whichhit].bjoint1=hitstruct.joint1;
+
+							person[whichhit].bjoint2=hitstruct.joint2;
+
+							person[whichhit].bleeding=1;
+
+							person[whichhit].bleeddelay=1;
+
+							float gLoc[3];
+
+							gLoc[0]=(camera.position.x+(hitstruct.hitlocation.x-camera.position.x)/4)/soundscalefactor;
+
+							gLoc[1]=(camera.position.y+(hitstruct.hitlocation.y-camera.position.y)/4)/soundscalefactor;
+
+							gLoc[2]=(camera.position.z+(hitstruct.hitlocation.z-camera.position.z)/4)/soundscalefactor;
+
+							if(!hitstruct.joint1->modelnum==headmodel){
+
+								if(!thirdperson)alSourcef(gSourceID[bodyhitsound], AL_MIN_GAIN, 1);
+
+								if(thirdperson)alSourcef(gSourceID[bodyhitsound], AL_MIN_GAIN, .1);
+
+								alSourcefv(gSourceID[bodyhitsound], AL_POSITION, gLoc);
+
+								alSourcePlay(gSourceID[bodyhitsound]);
+
+							}
+
+							if(hitstruct.joint1->modelnum==headmodel){
+
+								if(!thirdperson)alSourcef(gSourceID[headshotsound], AL_MIN_GAIN, 1);
+
+								if(thirdperson)alSourcef(gSourceID[headshotsound], AL_MIN_GAIN, .1);
+
+								alSourcefv(gSourceID[headshotsound], AL_POSITION, gLoc);
+
+								alSourcePlay(gSourceID[headshotsound]);
+
+							}
+
+						}//with wall
+
+						if(oldend==finalwallhit){
+
+							decals.MakeDecal(bullethole, finalwallhit,.7,hitnorm, hitpoly, model, hitmove, hitrotation);
+
+							XYZ velocity;
+
+							velocity=aim*-4;
+
+							velocity=hitnorm*3;
+
+							if(person[j].whichgun==sniperrifle){
+
+								sprites.MakeSprite(smokesprite, .4, 1, 1, 1, finalwallhit, velocity, 10);
+
+								sprites.MakeSprite(muzzleflashsprite, 1, 1, 1, 1, finalwallhit, velocity, 2);
+
+							}
+
+							if(person[j].whichgun==shotgun){
+
+								sprites.MakeSprite(smokesprite, .4, 1, 1, 1, finalwallhit, velocity, 5);
+
+								sprites.MakeSprite(muzzleflashsprite, 1, 1, 1, 1, finalwallhit, velocity, .8);
+
+							}
+
+							if(person[j].whichgun==assaultrifle){
+
+								sprites.MakeSprite(smokesprite, .4, 1, 1, 1, finalwallhit, velocity, 6);
+
+								sprites.MakeSprite(muzzleflashsprite, 1, 1, 1, 1, finalwallhit, velocity, 1);
+
+							}
+
+							if(person[j].whichgun==handgun1){
+
+								sprites.MakeSprite(smokesprite, .4, 1, 1, 1, finalwallhit, velocity, 6);
+
+								sprites.MakeSprite(muzzleflashsprite, 1, 1, 1, 1, finalwallhit, velocity, 1);
+
+							}
+
+							if(person[j].whichgun==handgun2){
+
+								sprites.MakeSprite(smokesprite, .4, 1, 1, 1, finalwallhit, velocity, 6);
+
+								sprites.MakeSprite(muzzleflashsprite, 1, 1, 1, 1, finalwallhit, velocity, 1);
+
+							}
+
+							float gLoc[3];
+
+							gLoc[0]=finalwallhit.x/soundscalefactor;
+
+							gLoc[1]=finalwallhit.y/soundscalefactor;
+
+							gLoc[2]=finalwallhit.z/soundscalefactor;
+
+							alSourcefv(gSourceID[wallhitsound], AL_POSITION, gLoc);
+
+							alSourcePlay(gSourceID[wallhitsound]);
+
+						}
+
+						lastshot[0]=start;
+
+						lastshot[1]=oldend;
+
+						velocity=aim*8;
+
+						if(person[j].whichgun!=sniperrifle&&person[j].whichgun!=shotgun&&p==numshots-1)sprites.MakeSprite(smokesprite, .3, 1, 1, 1, start+aim*1.5, velocity, 3);
+
+						if(person[j].whichgun==shotgun&&p==numshots-1)sprites.MakeSprite(smokesprite, .4, 1, 1, 1, start+aim*1.5, velocity, 5);
+
+						if(person[j].whichgun==sniperrifle&&!zoom)sprites.MakeSprite(smokesprite, .3, 1, 1, 1, start+aim*2.2, velocity, 4);
+
+						if(j!=0||zoom==0)sprites.MakeSprite(bullet, .07, 1, 1, .7, lastshot[0]+aim*1, lastshot[1], .2);
+
+						//Nearby bullet whoosh		
+
+						long dot_ta,dot_tb;
+
+						XYZ *a,*b,*c,nearest;
+
+						a=&lastshot[0];
+
+						*a+=aim*1;
+
+						b=&lastshot[1];
+
+						c=&camera.position;
+
+						nearest=0;
+
+						dot_ta = (c->x - a->x)*(b->x - a->x) + (c->y - a->y)*(b->y - a->y) + (c->z - a->z)*(b->z - a->z);
+
+						dot_tb = (c->x - b->x)*(a->x - b->x) + (c->y - b->y)*(a->y - b->y) + (c->z - b->z)*(a->z - b->z);
+
+						if (!dot_ta <= 0&&!dot_tb <= 0){
+
+						
+
+								nearest.x = a->x + ((b->x - a->x) * dot_ta)/(dot_ta + dot_tb);
+
+								nearest.y = a->y + ((b->y - a->y) * dot_ta)/(dot_ta +dot_tb);
+
+								nearest.z = a->z + ((b->z - a->z) * dot_ta)/(dot_ta +dot_tb);
+
+							}
+
+						
+
+						if(nearest.x){
+
+							if(findDistancefast(nearest,camera.position)<10&&(thirdperson==2||j!=0)){
+
+								float gLoc[3];
+
+								
+
+								gLoc[0]=(camera.position.x+(nearest.x-camera.position.x))/soundscalefactor;
+
+								gLoc[1]=(camera.position.y+(nearest.y-camera.position.y))/soundscalefactor;
+
+								gLoc[2]=(camera.position.z+(nearest.z-camera.position.z))/soundscalefactor;
+
+								alSourcefv(gSourceID[nearbulletsound], AL_POSITION, gLoc);
+
+								alSourcePlay(gSourceID[nearbulletsound]);
+
+							}
+
+						}
+
+					}
+
+				}
+
+				}
+
+				}
+
+			}
+
+			}
+
+		}
+
+		
+
+		if(!Button())oldbutton=0;
+
+		
+
+		if(lasersight&&person[0].whichgun!=grenade){
+
+		for(int j=0;j<numpeople;j++){
+
+			if(person[j].type==playertype){
+
+				if(person[j].aiming>=1){
+
+					//Firing
+
+					XYZ end, aim, oldend;
+
+					HitStruct hitstruct,temphitstruct;
+
+					float olddistance;
+
+					float distance;
+
+					int whichhit=-1;
+
+					if(!zoom||j!=0){
+
+						if(person[j].whichgun==assaultrifle)aim=DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[lefthand])].position-person[j].skeleton.joints[(person[j].skeleton.jointlabels[righthand])].position,0,person[j].playerrotation-2.5,0);
+
+						if(person[j].whichgun==sniperrifle)aim=DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[lefthand])].position-person[j].skeleton.joints[(person[j].skeleton.jointlabels[righthand])].position,0,person[j].playerrotation+4,0);
+
+						if(person[j].whichgun==shotgun)aim=DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[lefthand])].position-person[j].skeleton.joints[(person[j].skeleton.jointlabels[righthand])].position,0,person[j].playerrotation+4,0);
+
+						if(person[j].whichgun==handgun1&&!thirdperson&&j==0)aim=DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[righthand])].position-(person[j].skeleton.joints[person[j].skeleton.jointlabels[head]].position*.65+person[j].skeleton.joints[person[j].skeleton.jointlabels[neck]].position*.35),0,person[j].playerrotation-.9,0);
+
+						if(person[j].whichgun==handgun1&&(thirdperson||j!=0))aim=DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[righthand])].position-(person[j].skeleton.joints[person[j].skeleton.jointlabels[head]].position*.35+person[j].skeleton.joints[person[j].skeleton.jointlabels[neck]].position*.65),0,person[j].playerrotation-.9,0);
+
+						if(person[j].whichgun==handgun2&&!thirdperson&&j==0)aim=DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[righthand])].position-(person[j].skeleton.joints[person[j].skeleton.jointlabels[head]].position*.65+person[j].skeleton.joints[person[j].skeleton.jointlabels[neck]].position*.35),0,person[j].playerrotation-.9,0);
+
+						if(person[j].whichgun==handgun2&&(thirdperson||j!=0))aim=DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[righthand])].position-(person[j].skeleton.joints[person[j].skeleton.jointlabels[head]].position*.35+person[j].skeleton.joints[person[j].skeleton.jointlabels[neck]].position*.65),0,person[j].playerrotation-.9,0);
+
+					}
+
+					if(zoom&&j==0){
+
+						start=camera.position;
+
+						aim=facing;
+
+					}
+
+					Normalise(&aim);
+
+					if(person[j].whichgun==sniperrifle){
+
+						start=person[j].playercoords+DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[lefthand])].position,0,person[j].playerrotation,0);
+
+						start-=DoRotation(DoRotation(DoRotation(aim,0,-person[j].playerrotation,0),90,0,0),0,person[j].playerrotation,0)*(0-.4);
+
+					}
+
+					if(person[j].whichgun==shotgun){
+
+						start=person[j].playercoords+DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[lefthand])].position,0,person[j].playerrotation,0);
+
+						start-=DoRotation(DoRotation(DoRotation(aim,0,-person[j].playerrotation,0),90,0,0),0,person[j].playerrotation,0)*(0-.4);
+
+					}
+
+					if(person[j].whichgun==handgun1){
+
+						start=person[j].playercoords+DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[rightwrist])].position,0,person[j].playerrotation,0);
+
+						start-=DoRotation(DoRotation(DoRotation(aim,0,-person[j].playerrotation,0),90,0,0),0,person[j].playerrotation,0)*(.55-.4);
+
+					}
+
+					if(person[j].whichgun==handgun2){
+
+						start=person[j].playercoords+DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[rightwrist])].position,0,person[j].playerrotation,0);
+
+						start-=DoRotation(DoRotation(DoRotation(aim,0,-person[j].playerrotation,0),90,0,0),0,person[j].playerrotation,0)*(.55-.4);
+
+					}
+
+					if(person[j].whichgun==assaultrifle){
+
+						start=person[j].playercoords+DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[lefthand])].position,0,person[j].playerrotation,0);
+
+						start-=DoRotation(DoRotation(DoRotation(aim,0,-person[j].playerrotation,0),90,0,0),0,person[j].playerrotation,0)*(.25-.4);
+
+					}
+
+					end=start+aim*1000;
+
+					//Blocks
+
+					wallhit=0;
+
+					beginx=(person[j].playercoords.x+block_spacing/2)/block_spacing-2;
+
+					if(beginx<0)beginx=0;
+
+					beginz=(person[j].playercoords.z+block_spacing/2)/block_spacing-2;
+
+					if(beginz<0)beginz=0;
+
+					
+
+					endx=(person[j].playercoords.x+block_spacing/2)/block_spacing+2;
+
+					if(endx>num_blocks-1)endx=num_blocks-1;
+
+					endz=(person[j].playercoords.z+block_spacing/2)/block_spacing+2;
+
+					if(endz>num_blocks-1)endz=num_blocks-1;
+
+					
+
+					if(beginx<endx&&beginz<endz)
+
+					finalwallhit=0;
+
+					for(int i=beginx;i<=endx;i++)
+
+						for(int j=beginz;j<=endz;j++){
+
+							move=0;
+
+							move.x=i*block_spacing;
+
+							move.z=j*block_spacing;
+
+							whichtri=blocks[citytype[i][j]].LineCheck2(start,end,&wallhit,move,cityrotation[i][j]*90);
+
+							if(whichtri!=-1){
+
+								end=wallhit;
+
+								finalwallhit=wallhit;
+
+							}
+
+						}
+
+					wallhit=0;
+
+					wallhit.x=camera.position.x;
+
+					wallhit.z=camera.position.z;
+
+					whichtri=Bigstreet.LineCheck2(start,end,&wallhit,wallhit,0);
+
+					if(whichtri!=-1){
+
+						end=wallhit;
+
+						finalwallhit=wallhit;
+
+					}
+
+					//People
+
+					whichhit=-1;
+
+					for(int i=0;i<numpeople;i++){
+
+						if(i!=j&&findDistancefast(person[j].playercoords,person[i].playercoords)<20000){
+
+							temphitstruct=person[i].BulletCollideWithPlayer(i, start, end);	
+
+							if(temphitstruct.collision){
+
+								distance=findDistancefast(start,temphitstruct.hitlocation);
+
+								if(distance<olddistance||whichhit==-1){
+
+									end=temphitstruct.hitlocation;
+
+									olddistance=distance;
+
+									hitstruct=temphitstruct;
+
+									whichhit=i;
+
+								}
+
+							}
+
+						}
+
+					}
+
+					aimer[0]=start;
+
+					aimer[1]=end;
+
+					sprites.MakeSprite(bulletinstant, .4, 1, 0, 0, aimer[0], aimer[1], .2);
+
+					
+
+				}
+
+			}
+
+		}
+
+		}
+
+		
+
+		//Snow
+
+		snowdelay-=multiplier;
+
+		while(snowdelay<0&&environment==snowy_environment){
+
+			snowdelay+=1/precipitationdensity*2;
+
+			velocity=0;
+
+			velocity.y=-5;
+
+			start=camera.position;
+
+			start.y+=precipitationvert;
+
+			start.x+=Random()%(int)precipitationhorz;
+
+			start.z+=Random()%(int)precipitationhorz;
+
+			sprites.MakeSprite(snowsprite, 1, 1, 1, 1, start, velocity, 1.01);
+
+		}
+
+		while(snowdelay<0&&environment==rainy_environment){
+
+			snowdelay+=1/precipitationdensity/4;
+
+			velocity=0;
+
+			velocity.y=-100;
+
+			start=camera.position;
+
+			start.y+=precipitationvert;
+
+			start.x+=Random()%(int)precipitationhorz*.5;
+
+			start.z+=Random()%(int)precipitationhorz*.5;
+
+			sprites.MakeSprite(rainsprite, .5, 1, 1, 1, start, velocity, 2.00);
+
+		}			
+
+		
+
+		//Grenade collision
+
+		int wherex,wherey,whichsound,severwhat;
+
+		bool impact;
+
+		for(int i=0;i<sprites.howmanysprites;i++){
+
+			if(sprites.type[i]==grenadesprite||sprites.type[i]==spoonsprite||sprites.type[i]==pinsprite){
+
+				impact=0;
+
+				if(sprites.type[i]!=grenadesprite){
+
+					sprites.brightness[i]-=multiplier*.2;
+
+				}
+
+						
+
+				if(findLengthfast(sprites.velocity[i])>0){
+
+					wherex=(sprites.location[i].x+block_spacing/2)/block_spacing;
+
+					wherey=(sprites.location[i].z+block_spacing/2)/block_spacing;
+
+					move=0;
+
+					move.x=wherex*block_spacing;
+
+					move.z=wherey*block_spacing;
+
+					whichtri=blocks[citytype[wherex][wherey]].LineCheck2(sprites.oldlocation[i],sprites.location[i],&wallhit,move,cityrotation[wherex][wherey]*90);
+
+					if(whichtri!=-1){
+
+						impact=1;
+
+						normalrotated=DoRotation(blocks[citytype[wherex][wherey]].normals[whichtri],0,cityrotation[wherex][wherey]*90,0);
+
+						if(sprites.size[i]>1)decals.MakeDecal(crater, wallhit,9,normalrotated, whichtri, &blocks[citytype[wherex][wherey]], move, cityrotation[wherex][wherey]*90);
+
+						sprites.location[i]=wallhit+normalrotated*.02;
+
+						ReflectVector(&sprites.velocity[i],&normalrotated);
+
+						sprites.velocity[i]*=.3;
+
+						if(sprites.type[i]==grenadesprite){
+
+							float gLoc[3];
+
+							gLoc[0]=(((sprites.location[i].x)-camera.position.x)/findLengthfast(sprites.velocity[i])*5+camera.position.x)/soundscalefactor;
+
+							gLoc[1]=(((sprites.location[i].y)-camera.position.y)/findLengthfast(sprites.velocity[i])*5+camera.position.y)/soundscalefactor;
+
+							gLoc[2]=(((sprites.location[i].z)-camera.position.z)/findLengthfast(sprites.velocity[i])*5+camera.position.z)/soundscalefactor;
+
+							whichsound=abs(Random()%2);
+
+							alSourcefv(gSourceID[bouncesound+whichsound], AL_POSITION, gLoc);
+
+							if(sprites.size[i]<=1)alSourcePlay(gSourceID[bouncesound+whichsound]);			
+
+						}
+
+						if(findLengthfast(sprites.velocity[i])<=10)sprites.velocity[i]=0;
+
+					}
+
+					if(sprites.location[i].y<0){
+
+						impact=1;
+
+						sprites.velocity[i].y*=-1;
+
+						sprites.velocity[i]*=.3;
+
+						sprites.location[i].y=0;
+
+						if(sprites.type[i]==grenadesprite){
+
+							if(sprites.size[i]>1){
+
+								move=0;
+
+								sprites.location[i].y=-.5;
+
+								XYZ normish;
+
+								normish=0;
+
+								normish.y=1;
+
+								decals.MakeDecal(crater, sprites.location[i],9,normish, 0, &blocks[citytype[wherex][wherey]], move, 0);
+
+							}
+
+							float gLoc[3];
+
+							gLoc[0]=(((sprites.location[i].x)-camera.position.x)/findLengthfast(sprites.velocity[i])*5+camera.position.x)/soundscalefactor;
+
+							gLoc[1]=(((sprites.location[i].y)-camera.position.y)/findLengthfast(sprites.velocity[i])*5+camera.position.y)/soundscalefactor;
+
+							gLoc[2]=(((sprites.location[i].z)-camera.position.z)/findLengthfast(sprites.velocity[i])*5+camera.position.z)/soundscalefactor;
+
+							whichsound=abs(Random()%2);
+
+							alSourcefv(gSourceID[bouncesound+whichsound], AL_POSITION, gLoc);
+
+							if(sprites.size[i]<=1)alSourcePlay(gSourceID[bouncesound+whichsound]);			
+
+						}
+
+						if(findLengthfast(sprites.velocity[i])<=10)sprites.velocity[i]=0;
+
+					}
+
+					if(sprites.type[i]==grenadesprite&&findLengthfast(sprites.velocity[i])>20){
+
+						HitStruct hitstruct;
+
+						for(int j=0;j<numpeople;j++){
+
+							if((j!=0||sprites.brightness[i]<.9)&&person[j].existing){
+
+								hitstruct=person[j].BulletCollideWithPlayer(j, sprites.oldlocation[i], sprites.location[i]);	
+
+								if(hitstruct.collision){
+
+									impact=1;
+
+									sprites.location[i]=hitstruct.hitlocation;
+
+									float gLoc[3];
+
+									gLoc[0]=(((sprites.location[i].x)-camera.position.x)/findLengthfast(sprites.velocity[i])*5+camera.position.x)/soundscalefactor;
+
+									gLoc[1]=(((sprites.location[i].y)-camera.position.y)/findLengthfast(sprites.velocity[i])*5+camera.position.y)/soundscalefactor;
+
+									gLoc[2]=(((sprites.location[i].z)-camera.position.z)/findLengthfast(sprites.velocity[i])*5+camera.position.z)/soundscalefactor;
+
+									if(person[j].skeleton.free<1){
+
+									if((hitstruct.joint1->label==head||hitstruct.joint2->label==head)&&person[j].type!=zombietype){
+
+										alSourcefv(gSourceID[headwhacksound], AL_POSITION, gLoc);
+
+										if(sprites.size[i]<=1)alSourcePlay(gSourceID[headwhacksound]);
+
+										person[j].skeleton.free=1;
+
+										person[j].longdead=1;
+
+										for(int k=0;k<person[j].skeleton.num_joints;k++){
+
+											person[j].skeleton.joints[k].position=DoRotation(person[j].skeleton.joints[k].position,0,person[j].playerrotation,0);
+
+											person[j].skeleton.joints[k].position+=person[j].playercoords;
+
+											person[j].skeleton.joints[k].realoldposition=person[j].skeleton.joints[k].position;
+
+											person[j].skeleton.joints[k].velocity=person[j].velocity;
+
+											person[j].skeleton.joints[k].velocity.x+=abs(Random()%10)-5;
+
+											person[j].skeleton.joints[k].velocity.y+=abs(Random()%10)-5;
+
+											person[j].skeleton.joints[k].velocity.z+=abs(Random()%10)-5;
+
+										}
+
+										hitstruct.joint1->velocity+=sprites.velocity[i];
+
+										hitstruct.joint2->velocity+=sprites.velocity[i];
+
+										if(person[j].type==civiliantype)civkills++;
+
+										if(person[j].type==eviltype)goodkills++;
+
+									}else{
+
+										float totalarea;
+
+										alSourcefv(gSourceID[bodywhacksound], AL_POSITION, gLoc);
+
+										if(sprites.size[i]<=1)alSourcePlay(gSourceID[bodywhacksound]);
+
+										person[j].skeleton.offset=1;
+
+										for(int k=0;k<person[j].skeleton.num_joints;k++){
+
+											if(findDistancefast(DoRotation(person[j].skeleton.joints[k].position,0,person[j].playerrotation,0)+person[j].playercoords,hitstruct.hitlocation)<200){
+
+												totalarea+=(200/findDistancefast(DoRotation(person[j].skeleton.joints[k].position,0,person[j].playerrotation,0)+person[j].playercoords,hitstruct.hitlocation));
+
+											}
+
+										}
+
+										float offsetlength;
+
+										for(int k=0;k<person[j].skeleton.num_joints;k++){
+
+											if(findDistancefast(DoRotation(person[j].skeleton.joints[k].position,0,person[j].playerrotation,0)+person[j].playercoords,hitstruct.hitlocation)<200){
+
+												person[j].skeleton.joints[k].offset+=DoRotation(sprites.velocity[i]*.1*((200/findDistancefast(DoRotation(person[j].skeleton.joints[k].position,0,person[j].playerrotation,0)+person[j].playercoords,hitstruct.hitlocation))/totalarea*10),0,-person[j].playerrotation,0);
+
+											}
+
+											offsetlength=findLengthfast(person[j].skeleton.joints[k].offset);
+
+											if(offsetlength>9){
+
+												Normalise(&person[j].skeleton.joints[k].offset);
+
+												person[j].skeleton.joints[k].offset*=3;
+
+											}
+
+										}
+
+									}}
+
+									sprites.velocity[i]*=-.3;
+
+								}
+
+							}
+
+						}
+
+					}
+
+					sprites.oldlocation[i]=sprites.location[i];
+
+				}
+
+				//Explode
+
+				if(sprites.type[i]==grenadesprite){
+
+					sprites.brightness[i]-=multiplier*.3;
+
+					if(sprites.brightness[i]<=0||(impact&&sprites.size[i]>1)){
+
+						sprites.brightness[i]=0;
+
+						sprites.MakeSprite(smokesprite, 1, 1, 1, 1, sprites.location[i], facing*0, 60);
+
+						sprites.MakeSprite(muzzleflashsprite, 1, 1, 1, 1, sprites.location[i], facing*0, 9);
+
+						float gLoc[3];
+
+						gLoc[0]=(((sprites.location[i].x)-camera.position.x)/3+camera.position.x)/soundscalefactor;
+
+						gLoc[1]=(((sprites.location[i].y)-camera.position.y)/3+camera.position.y)/soundscalefactor;
+
+						gLoc[2]=(((sprites.location[i].z)-camera.position.z)/3+camera.position.z)/soundscalefactor;
+
+						alSourcefv(gSourceID[explosionsound], AL_POSITION, gLoc);
+
+						alSourcePlay(gSourceID[explosionsound]);
+
+						XYZ relation;
+
+						camerashake=1-findDistance(person[0].playercoords,sprites.location[i])/200;
+
+						//if(!sprites.size[i]>1){
+
+							overpoint=sprites.location[i];
+
+							overpoint.y+=3000;
+
+							underpoint=sprites.location[i];
+
+							underpoint.y-=3000;
+
+							move=0;
+
+							wherex=(sprites.location[i].x+block_spacing/2)/block_spacing;
+
+							wherey=(sprites.location[i].z+block_spacing/2)/block_spacing;
+
+							move.x=wherex*block_spacing;
+
+							move.z=wherey*block_spacing;
+
+							XYZ temp;
+
+							whichtri=sidewalkcollide.LineCheck2(overpoint,underpoint,&temp,move,cityrotation[wherex][wherey]*90);
+
+							XYZ normish;
+
+							normish=0;
+
+							normish.y=1;
+
+							if(whichtri>=0){
+
+								decals.MakeDecal(crater, sprites.location[i],9,normish, 0, &sidewalkcollide, move, cityrotation[wherex][wherey]*90);
+
+							}
+
+							if(whichtri==-1){
+
+								temp=sprites.location[i];
+
+								temp.y=-.5;
+
+								move=0;
+
+								decals.MakeDecal(crater, sprites.location[i],9,normish, 0, &sidewalkcollide, move, 0);
+
+							}
+
+						//}
+
+						for(int k=0;k<numpeople;k++){		
+
+							if(person[k].existing&&(person[k].longdead!=-1||person[k].skeleton.free<1)){		
+
+							if((findDistancefast(person[k].playercoords,sprites.location[i])<700&&person[k].skeleton.free<1)||(findDistancefast(person[k].averageloc,sprites.location[i])<700&&person[k].skeleton.free>=1)){
+
+							if(person[k].skeleton.free!=1){
+
+							if(person[k].type==civiliantype)civkills++;
+
+							if(person[k].type==eviltype)goodkills++;
+
+							person[k].skeleton.free=1;
+
+							person[k].killtargetvisible=0;
+
+							if((findDistancefast(person[k].playercoords,sprites.location[i])<600&&person[k].skeleton.free<1)||(findDistancefast(person[k].averageloc,sprites.location[i])<600&&person[k].skeleton.free>=1)||person[k].type==playertype){
+
+								person[k].health-=100;
+
+								person[k].bleeding=1;
+
+							}
+
+							person[k].DoAnimations(k);
+
+							person[k].longdead=1;
+
+							
+
+							person[k].bleeddelay=1;
+
+							person[k].bjoint1=&person[k].skeleton.joints[person[k].skeleton.jointlabels[head]];
+
+							person[k].bjoint2=&person[k].skeleton.joints[person[k].skeleton.jointlabels[neck]];
+
+							
+
+							
+
+							for(int j=0;j<person[k].skeleton.num_joints;j++){
+
+								person[k].skeleton.joints[j].position=DoRotation(person[k].skeleton.joints[j].position,0,person[k].playerrotation,0);
+
+								person[k].skeleton.joints[j].position+=person[k].playercoords;
+
+								person[k].skeleton.joints[j].realoldposition=person[k].skeleton.joints[j].position;
+
+								person[k].skeleton.joints[j].velocity=DoRotation(person[k].skeleton.joints[j].velocity,0,person[k].playerrotation,0);
+
+								person[k].skeleton.joints[j].velocity+=person[k].velocity;
+
+								person[k].skeleton.joints[j].velocity.x+=abs(Random()%20)-10;
+
+								person[k].skeleton.joints[j].velocity.y+=abs(Random()%20)-10;
+
+								person[k].skeleton.joints[j].velocity.z+=abs(Random()%20)-10;
+
+							}}
+
+							for(int j=0;j<person[k].skeleton.num_joints;j++){
+
+								relation=person[k].skeleton.joints[j].position-sprites.location[i];
+
+								Normalise(&relation);
+
+								if(findDistance(person[k].skeleton.joints[j].position,sprites.location[i])>1)person[k].skeleton.joints[j].velocity+=relation/findDistance(person[k].skeleton.joints[j].position,sprites.location[i])*300;
+
+								else person[k].skeleton.joints[j].velocity+=relation*300;
+
+							}
+
+							person[k].longdead=1;
+
+							for(int j=0;j<person[k].skeleton.num_joints;j++){
+
+								//Sever stuff
+
+								if(findLengthfast(person[k].skeleton.joints[j].velocity)>1500&&person[k].skeleton.joints[j].existing==1&&abs(Random()%3)!=1){
+
+									sprites.MakeSprite(bloodspritedown, .8, 1, .2, .2,person[k].skeleton.joints[j].position, person[k].skeleton.joints[j].velocity/3, 9);
+
+									person[k].skeleton.DeleteJoint(j);
+
+									person[k].skeleton.broken=2;
+
+									person[k].health=-10000;
+
+									person[k].skeleton.joints[j].existing=0;
+
+								}
+
+							}
+
+							}
+
+							}
+
+						}
+
+									
+
+					}
+
+				}
+
+			}
+
+		}
+
+		
+
+		//camera shake
+
+		camerashake-=multiplier;
+
+		if(camerashake<0)camerashake=0;
+
+		
+
+		//camera position
+
+		XYZ average;
+
+		if(!zoom)average=person[0].skeleton.joints[(person[0].skeleton.jointlabels[head])].position*(person[0].aimamount/2+.5)+person[0].skeleton.joints[(person[0].skeleton.jointlabels[neck])].position*((1-person[0].aimamount)/2);
+
+		if(zoom)average=person[0].skeleton.joints[(person[0].skeleton.jointlabels[righthand])].position;
+
+		
+
+		if(person[0].skeleton.free==0&&thirdperson!=2)camera.position=person[0].playercoords+DoRotation(average,0,person[0].playerrotation,0);
+
+		if(person[0].skeleton.free==1&&thirdperson!=2)camera.position=average;
+
+		
+
+		//Restraints
+
+		if(camera.position.y<.1)camera.position.y=.1;
+
+		
+
+		if(thirdperson!=2){
+
+			oldrot=camera.visrotation;
+
+			oldrot2=camera.visrotation2;
+
+		}
+
+		
+
+		//Kill count
+
+		for(int i=0;i<numpeople;i++){
+
+			if(person[i].oldhealth>0&&person[i].health<=0){
+
+				if(i==1)alSourcePlay(gSourceID[losesound]);	
+
+				if(person[i].type==civiliantype){
+
+					alSourcePlay(gSourceID[disguisekillsound]);
+
+					score-=300;	
+
+				}
+
+				if(person[i].type==eviltype){
+
+					alSourcePlay(gSourceID[soulinsound]);	
+
+					score+=75;
+
+					if(person[i].whichgun==knife)score+=50;
+
+				}
+
+				person[i].firstlongdead=0;
+
+			}
+
+			person[i].oldhealth=person[i].health;
+
+		}
+
+		
+
+		if(slomo==2){
+
+			psychicpower-=multiplier*15;
+
+			if(psychicpower<0){
+
+				soundscalefactor=soundscalefactordefault;
+
+				alSourceStop(gSourceID[whichsong]);
+
+				alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 0);
+
+				alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 0);
+
+				if(person[0].whichgun==knife)whichsong=knifesong;
+
+				if(person[0].whichgun!=knife)whichsong=shootsong;
+
+				if(type==zombie_type)whichsong=zombiesong;
+
+				alSourcef(gSourceID[whichsong], AL_PITCH, 1);
+
+				alSourcePlay(gSourceID[whichsong]);
+
+				alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 1);
+
+				alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 1);
+
+				slomo=0;
+
+				alSourcePlay(gSourceID[soulinsound]);
+
+				psychicpower=0;
+
+				flashamount=.5;
+
+				flashr=1;flashg=1;flashb=1;
+
+			}
+
+		}
+
+		psychicpower+=multiplier*5;
+
+		if(psychicpower>10)psychicpower=10;
+
+		
+
+		//3d sound
+
+		ALint tempInt;
+
+		float gLoc[3];
+
+		gLoc[0]=camera.position.x/soundscalefactor;
+
+		gLoc[1]=camera.position.y/soundscalefactor;
+
+		gLoc[2]=camera.position.z/soundscalefactor;
+
+		//Set listener position
+
+		alListenerfv(AL_POSITION, gLoc);
+
+		
+
+		//Set orientation with forward and up vectors
+
+		XYZ upvector;
+
+		upvector=0;
+
+		upvector.z=-1;
+
+		
+
+		upvector=DoRotation(upvector,-camera.rotation2+90,0,0);
+
+		upvector=DoRotation(upvector,0,0-camera.rotation,0);
+
+		
+
+		float ori[6];
+
+	   	ori[0] = -facing.x;
+
+	   	ori[1] = facing.y;
+
+	   	ori[2] = facing.z;
+
+	   	ori[3] = -upvector.x;
+
+	   	ori[4] = upvector.y;
+
+	   	ori[5] = upvector.z;
+
+		alListenerfv(AL_ORIENTATION, ori);
+
+		
+
+		if(person[0].currentanimation==throwanim||person[0].currentanimation==diveanim||paused){
+
+			MoveMouse(oldmouseloc.h,oldmouseloc.v,&mouseloc);
+
+			GetMouse(&mouseloc);
+
+		}
+
+		oldmouseloc=mouseloc;
+
+		
+
+		if(score<0)score=0;
+
+	}
+
+}
diff --git a/src/Globals.cpp b/src/Globals.cpp
new file mode 100644
index 0000000..fa18cfe
--- /dev/null
+++ b/src/Globals.cpp
@@ -0,0 +1,89 @@
+#include "Quaternions.h"
+#include "Constants.h"
+#include "Models.h"
+#include "Person.h"
+#include "Game.h"
+
+float sinefluct;
+float sinefluctprog;
+
+double multiplier=0;
+
+unsigned int gSourceID[100]; // hundred source IDs
+unsigned int gSampleSet[100]; // hundred sample set ID numbers
+
+float precipitationhorz;
+float precipitationvert;
+float precipitationdensity;
+
+int environment;
+
+float soundscalefactor;
+int slomo;
+
+Animation animation[30];
+Model skeletonmodels[10];
+Model gunmodels[11];
+Costume costume[10];
+Sprites sprites;
+Decals decals;
+int thirdperson;
+int nocolors;
+int visions;
+Camera camera;
+float rad2deg;
+Skeleton testskeleton;
+
+float snowdelay;
+
+float camerashake;
+
+Fog fog;
+
+int forwardskey;
+int backwardskey;
+int leftkey;
+int rightkey;
+int aimkey;
+int psychicaimkey;
+int psychickey;
+
+bool blood;
+
+float fogcolorr;
+float fogcolorg;
+float fogcolorb;
+
+float d;
+float a1,a2,a3;
+float total,denom,mu;
+XYZ n,pa1,pa2,pa3;
+
+float u0, u1, u2;
+float v0, v1, v2;
+float a, b;
+int i, j;
+bool bInter;
+float pointv[3];
+float p1v[3];
+float p2v[3];
+float p3v[3];
+float normalv[3];
+
+XYZ vel;
+XYZ midp;
+XYZ newpoint1,newpoint2;
+
+float oldlength;
+float relaxlength;
+
+float friction;
+int numrepeats;
+float groundlevel;
+float offset;
+XYZ impact;
+XYZ overpoint;
+XYZ underpoint;
+int whichtri;
+XYZ normalrotated;
+bool groundish;
diff --git a/src/MacInput.cpp b/src/MacInput.cpp
new file mode 100644
index 0000000..512200d
--- /dev/null
+++ b/src/MacInput.cpp
@@ -0,0 +1,46 @@
+/**> HEADER FILES <**/
+#include "MacInput.h"
+
+/**> Mouse Stuff <**/
+#ifdef OS9 
+CursorDevicePtr	theCursor;
+#endif
+
+/********************> IsKeyDown() <*****/
+Boolean	IsKeyDown( unsigned char *keyMap, unsigned short theKey )
+{
+	long	keyMapIndex;
+	Boolean	isKeyDown;
+	short	bitToCheck;
+	
+	// Calculate the key map index
+	keyMapIndex = keyMap[theKey/8];
+	
+	// Calculate the individual bit to check
+	bitToCheck = theKey%8;
+	
+	// Check the status of the key
+	isKeyDown = ( keyMapIndex >> bitToCheck ) & 0x01;
+	
+	// Return the status of the key
+	return isKeyDown;
+	
+}
+
+#ifdef OS9 
+void 	InitMouse()
+{
+	CursorDeviceNewDevice( &theCursor ); //Mouse
+}
+
+void 	MoveMouse(int xcoord, int ycoord, Point *mouseloc)
+{
+	CursorDeviceMoveTo( theCursor, xcoord, ycoord);
+	GetMouse(mouseloc);
+}
+
+void DisposeMouse()
+{
+	CursorDeviceDisposeDevice( theCursor );//Mouse
+}
+#endif
diff --git a/src/MacInput.h b/src/MacInput.h
new file mode 100644
index 0000000..0c741aa
--- /dev/null
+++ b/src/MacInput.h
@@ -0,0 +1,105 @@
+#ifndef _MACINPUT_H_
+#define _MACINPUT_H_
+
+/**> HEADER FILES <**/
+#include <stdlib.h>
+#include <stdio.h>
+#ifdef OS9 
+#include <CursorDevices.h> //Mouse
+#endif
+
+#include "Support.h"
+
+/**> CONSTANT DECLARATIONS <**/
+// Mac Keyboard Codes
+#define	MAC_1_KEY				0x12
+#define	MAC_2_KEY				0x13
+#define	MAC_3_KEY				0x14
+#define	MAC_4_KEY				0x15
+#define	MAC_5_KEY				0x17
+#define	MAC_6_KEY				0x16
+#define	MAC_7_KEY				0x1A
+#define	MAC_8_KEY				0x1C
+#define	MAC_9_KEY				0x19
+#define	MAC_0_KEY				0x1D
+#define	MAC_NUMPAD_1_KEY		0x53
+#define	MAC_NUMPAD_2_KEY		0x54
+#define	MAC_NUMPAD_3_KEY		0x55
+#define	MAC_NUMPAD_4_KEY		0x56
+#define	MAC_NUMPAD_5_KEY		0x57
+#define	MAC_NUMPAD_6_KEY		0x58
+#define	MAC_NUMPAD_7_KEY		0x59
+#define	MAC_NUMPAD_8_KEY		0x5B
+#define	MAC_NUMPAD_9_KEY		0x5C
+#define	MAC_NUMPAD_0_KEY		0x52
+#define	MAC_A_KEY				0x00
+#define	MAC_B_KEY				0x0B
+#define	MAC_C_KEY				0x08
+#define	MAC_D_KEY				0x02
+#define	MAC_E_KEY				0x0E
+#define	MAC_F_KEY				0x03
+#define	MAC_G_KEY				0x05
+#define	MAC_H_KEY				0x04
+#define	MAC_I_KEY				0x22
+#define	MAC_J_KEY				0x26
+#define	MAC_K_KEY				0x28
+#define	MAC_L_KEY				0x25
+#define	MAC_M_KEY				0x2E
+#define	MAC_N_KEY				0x2D
+#define	MAC_O_KEY				0x1F
+#define	MAC_P_KEY				0x23
+#define	MAC_Q_KEY				0x0C
+#define	MAC_R_KEY				0x0F
+#define	MAC_S_KEY				0x01
+#define	MAC_T_KEY				0x11
+#define	MAC_U_KEY				0x20
+#define	MAC_V_KEY				0x09
+#define	MAC_W_KEY				0x0D
+#define	MAC_X_KEY				0x07
+#define	MAC_Y_KEY				0x10
+#define	MAC_Z_KEY				0x06
+#define	MAC_F1_KEY				0x7A
+#define	MAC_F2_KEY				0x78
+#define	MAC_F3_KEY				0x63
+#define	MAC_F4_KEY				0x76
+#define	MAC_F5_KEY				0x60
+#define	MAC_F6_KEY				0x61
+#define	MAC_F7_KEY				0x62
+#define	MAC_F8_KEY				0x64
+#define	MAC_F9_KEY				0x65
+#define	MAC_F10_KEY				0x6D
+#define	MAC_F11_KEY				0x67
+#define	MAC_F12_KEY				0x6F
+#define	MAC_RETURN_KEY			0x24
+#define	MAC_ENTER_KEY			0x4C
+#define	MAC_TAB_KEY				0x30
+#define	MAC_SPACE_KEY			0x31
+#define	MAC_DELETE_KEY			0x33
+#define	MAC_ESCAPE_KEY			0x35
+#define	MAC_COMMAND_KEY			0x37
+#define	MAC_SHIFT_KEY			0x38
+#define	MAC_CAPS_LOCK_KEY		0x39
+#define	MAC_OPTION_KEY			0x3A
+#define	MAC_CONTROL_KEY			0x3B
+#define	MAC_PAGE_UP_KEY			0x74
+#define	MAC_PAGE_DOWN_KEY		0x79
+#define	MAC_INSERT_KEY			0x72
+#define	MAC_DEL_KEY				0x75
+#define	MAC_HOME_KEY			0x73
+#define	MAC_END_KEY				0x77
+#define	MAC_LEFT_BRACKET_KEY	0x21
+#define	MAC_RIGHT_BRACKET_KEY	0x1E
+#define	MAC_ARROW_UP_KEY		0x7E
+#define	MAC_ARROW_DOWN_KEY		0x7D
+#define	MAC_ARROW_LEFT_KEY		0x7B
+#define	MAC_ARROW_RIGHT_KEY		0x7C
+
+
+/**> FUNCTION PROTOTYPES <**/
+Boolean	IsKeyDown( unsigned char *keyMap, unsigned short theKey );
+void 	InitMouse();
+void 	MoveMouse(int xcoord, int ycoord, Point *mouseloc);
+void 	RefreshMouse(Point *mouseloc);
+void 	DisposeMouse();
+
+#endif
diff --git a/src/Main.cpp b/src/Main.cpp
new file mode 100644
index 0000000..2c8f381
--- /dev/null
+++ b/src/Main.cpp
@@ -0,0 +1,64 @@
+/********************> Headers <*****/
+
+#include "Game.h"
+
+
+
+/********************> Globals <*****/
+
+
+
+Game game;
+
+
+
+/********************> main() <*****/
+
+int 	main( int argc, char *argv[] )
+
+	{
+
+	
+#ifdef OS9 
+	ToolboxInit();
+
+	
+
+	if ( HasAppearance() )
+
+		RegisterAppearanceClient();
+#endif
+	
+
+
+
+	game.InitGL();
+
+	
+
+	game.InitGame();
+
+	
+
+	game.EventLoop();
+
+	
+
+	game.Dispose();
+
+	
+#ifdef OS9 
+	if ( HasAppearance() )
+
+		UnregisterAppearanceClient();
+
+	
+
+	FlushEvents( everyEvent, 0 );
+
+	ExitToShell();
+#endif
+	
+
+}
+
diff --git a/src/Maths.cpp b/src/Maths.cpp
new file mode 100644
index 0000000..58e769a
--- /dev/null
+++ b/src/Maths.cpp
@@ -0,0 +1,24 @@
+/**> HEADER FILES <**/
+#include "Maths.h"
+
+double fast_sqrt (register double arg)
+{	
+#ifdef OS9 
+	// Can replace with slower return std::sqrt(arg);
+	register double result;
+
+	if (arg == 0.0) return 0.0;
+	
+	asm {
+		frsqrte		result,arg			// Calculate Square root
+	}	
+	
+	// Newton Rhapson iterations.
+	result = result + 0.5 * result * (1.0 - arg * result * result);
+	result = result + 0.5 * result * (1.0 - arg * result * result);
+	
+	return result * arg;
+#else
+	return sqrt(arg);
+#endif
+}
diff --git a/src/Maths.h b/src/Maths.h
new file mode 100644
index 0000000..d9a8f61
--- /dev/null
+++ b/src/Maths.h
@@ -0,0 +1,11 @@
+#ifndef _MATHS_H_
+#define _MATHS_H_
+
+
+/**> HEADER FILES <**/
+#include <cmath>
+
+double fast_sqrt (register double arg);
+
+#endif
+
diff --git a/src/Models.cpp b/src/Models.cpp
new file mode 100644
index 0000000..8caefd8
--- /dev/null
+++ b/src/Models.cpp
@@ -0,0 +1,341 @@
+#include "Models.h"
+
+#include "Serialize.h"
+
+//Functions
+void Model::UpdateVertexArray(){
+	int i;
+	for(i=0;i<TriangleNum;i++){
+		vArray[i*27+0]=vertex[Triangles[i].vertex[0]].x;
+		vArray[i*27+1]=vertex[Triangles[i].vertex[0]].y;
+		vArray[i*27+2]=vertex[Triangles[i].vertex[0]].z;
+		vArray[i*27+3]=normals[i].x;
+		vArray[i*27+4]=normals[i].y;
+		vArray[i*27+5]=normals[i].z;
+		vArray[i*27+6]=Triangles[i].r;
+		vArray[i*27+7]=Triangles[i].g;
+		vArray[i*27+8]=Triangles[i].b;
+		
+		vArray[i*27+9]=vertex[Triangles[i].vertex[1]].x;
+		vArray[i*27+10]=vertex[Triangles[i].vertex[1]].y;
+		vArray[i*27+11]=vertex[Triangles[i].vertex[1]].z;
+		vArray[i*27+12]=normals[i].x;
+		vArray[i*27+13]=normals[i].y;
+		vArray[i*27+14]=normals[i].z;
+		vArray[i*27+15]=Triangles[i].r;
+		vArray[i*27+16]=Triangles[i].g;
+		vArray[i*27+17]=Triangles[i].b;
+		
+		vArray[i*27+18]=vertex[Triangles[i].vertex[2]].x;
+		vArray[i*27+19]=vertex[Triangles[i].vertex[2]].y;
+		vArray[i*27+20]=vertex[Triangles[i].vertex[2]].z;
+		vArray[i*27+21]=normals[i].x;
+		vArray[i*27+22]=normals[i].y;
+		vArray[i*27+23]=normals[i].z;
+		vArray[i*27+24]=Triangles[i].r;
+		vArray[i*27+25]=Triangles[i].g;
+		vArray[i*27+26]=Triangles[i].b;
+	}
+	
+	XYZ average;
+	int howmany;
+	average=0;
+	howmany=0;
+	boundingboxmin=20000;
+	boundingboxmax=-20000;
+	for(int i=0;i<vertexNum;i++){
+		howmany++;
+		average=average+vertex[i];
+		if(vertex[i].x<boundingboxmin.x)boundingboxmin.x=vertex[i].x;
+		if(vertex[i].y<boundingboxmin.y)boundingboxmin.y=vertex[i].y;
+		if(vertex[i].z<boundingboxmin.z)boundingboxmin.z=vertex[i].z;
+		if(vertex[i].x>boundingboxmax.x)boundingboxmax.x=vertex[i].x;
+		if(vertex[i].y>boundingboxmax.y)boundingboxmax.y=vertex[i].y;
+		if(vertex[i].z>boundingboxmax.z)boundingboxmax.z=vertex[i].z;
+	}
+	average=average/howmany;
+	boundingspherecenter=average;
+	boundingsphereradius=0;
+	for(int i=0;i<vertexNum;i++){
+		if(findDistancefast(average,vertex[i])>boundingsphereradius)boundingsphereradius=findDistancefast(average,vertex[i]);
+	}
+	boundingsphereradius=fast_sqrt(boundingsphereradius);
+}
+
+bool Model::load(Str255 Name)
+{
+	short				tfile;
+	long				err;
+	Files file;
+	
+	tfile=file.OpenFile(Name);
+	SetFPos(tfile,fsFromStart,0);
+
+		// read model settings
+	
+	err=ReadShort(tfile,1,&vertexNum);
+	err=ReadShort(tfile,1,&TriangleNum);
+	
+		// read the model data
+	
+	err=ReadXYZ(tfile,vertexNum,vertex);
+	err=ReadTexturedTriangle(tfile,TriangleNum,Triangles);
+
+	FSClose(tfile);
+		
+	UpdateVertexArray();
+	
+	XYZ average;
+	int howmany;
+	average=0;
+	howmany=0;
+	for(int i=0;i<vertexNum;i++){
+		howmany++;
+		average=average+vertex[i];
+	}
+	average=average/howmany;
+	boundingspherecenter=average;
+	boundingsphereradius=0;
+	for(int i=0;i<vertexNum;i++){
+		if(findDistancefast(average,vertex[i])>boundingsphereradius)boundingsphereradius=findDistancefast(average,vertex[i]);
+	}
+	boundingsphereradius=fast_sqrt(boundingsphereradius);
+	
+	return 1;
+}
+
+void Model::Scale(float xscale,float yscale,float zscale)
+{
+	int i;
+	for(i=0; i<vertexNum; i++){
+		vertex[i].x*=xscale;
+		vertex[i].y*=yscale;
+		vertex[i].z*=zscale;
+	}
+	UpdateVertexArray();
+}
+
+void Model::MultColor(float howmuch)
+{
+	int i;
+	for(i=0; i<TriangleNum; i++){
+		Triangles[i].r*=howmuch;
+		Triangles[i].g*=howmuch;
+		Triangles[i].b*=howmuch;
+	}
+	UpdateVertexArray();
+}
+
+void Model::ScaleNormals(float xscale,float yscale,float zscale)
+{
+	int i;
+	for(i=0; i<vertexNum; i++){
+		normals[i].x*=xscale;
+		normals[i].y*=yscale;
+		normals[i].z*=zscale;
+	}
+	UpdateVertexArray();
+}
+
+void Model::Translate(float xtrans,float ytrans,float ztrans)
+{
+	int i;
+	for(i=0; i<vertexNum; i++){
+		vertex[i].x+=xtrans;
+		vertex[i].y+=ytrans;
+		vertex[i].z+=ztrans;
+	}
+	UpdateVertexArray();
+}
+
+void Model::Rotate(float xang,float yang,float zang)
+{
+	int i;
+	for(i=0; i<vertexNum; i++){
+		vertex[i]=DoRotation(vertex[i],xang,yang,zang);
+	}
+	UpdateVertexArray();
+}
+
+
+void Model::CalculateNormals()
+{
+	int i;
+	for(i=0;i<TriangleNum;i++){
+		CrossProduct(vertex[Triangles[i].vertex[1]]-vertex[Triangles[i].vertex[0]],vertex[Triangles[i].vertex[2]]-vertex[Triangles[i].vertex[0]],&normals[i]);
+		Normalise(&normals[i]);
+	}
+	UpdateVertexArray();
+}
+
+extern int nocolors;
+void Model::draw()
+{
+	if(!nocolors){
+	glEnableClientState(GL_VERTEX_ARRAY);
+	glEnableClientState(GL_NORMAL_ARRAY);
+	glEnableClientState(GL_COLOR_ARRAY);
+	glVertexPointer(3, GL_FLOAT, 9*sizeof(GLfloat),&vArray[0]);
+	glNormalPointer(GL_FLOAT, 9*sizeof(GLfloat),&vArray[3]);
+	glColorPointer(3,GL_FLOAT, 9*sizeof(GLfloat),&vArray[6]);
+	glDrawArrays(GL_TRIANGLES, 0, TriangleNum*3);
+	}
+	if(nocolors){
+		glColor4f(0,0,0,1);
+		glEnableClientState(GL_VERTEX_ARRAY);
+		glEnableClientState(GL_NORMAL_ARRAY);
+		glDisableClientState(GL_COLOR_ARRAY);
+		glVertexPointer(3, GL_FLOAT, 9*sizeof(GLfloat),&vArray[0]);
+		glNormalPointer(GL_FLOAT, 9*sizeof(GLfloat),&vArray[3]);
+		glDrawArrays(GL_TRIANGLES, 0, TriangleNum*3);
+	}
+}
+
+
+void Model::draw(float r, float g, float b)
+{
+	if(!nocolors)glColor4f(r,g,b,1);
+	if(nocolors==1)glColor4f(0,0,0,1);
+	if(nocolors==2)glColor4f(1,0,0,1);
+	if(nocolors==3)glColor4f(0,0,1,1);
+	glEnableClientState(GL_VERTEX_ARRAY);
+	glEnableClientState(GL_NORMAL_ARRAY);
+	glDisableClientState(GL_COLOR_ARRAY);
+	glVertexPointer(3, GL_FLOAT, 9*sizeof(GLfloat),&vArray[0]);
+	glNormalPointer(GL_FLOAT, 9*sizeof(GLfloat),&vArray[3]);
+	glDrawArrays(GL_TRIANGLES, 0, TriangleNum*3);
+}
+
+void Model::draw(float r, float g, float b, float o)
+{
+	if(!nocolors)glColor4f(r,g,b,o);
+	if(nocolors==1)glColor4f(0,0,0,1);
+	if(nocolors==2)glColor4f(1,0,0,1);
+	if(nocolors==3)glColor4f(1,1,1,1);
+	glEnableClientState(GL_VERTEX_ARRAY);
+	glEnableClientState(GL_NORMAL_ARRAY);
+	glDisableClientState(GL_COLOR_ARRAY);
+	glVertexPointer(3, GL_FLOAT, 9*sizeof(GLfloat),&vArray[0]);
+	glNormalPointer(GL_FLOAT, 9*sizeof(GLfloat),&vArray[3]);
+	glDrawArrays(GL_TRIANGLES, 0, TriangleNum*3);
+}
+
+void Model::draw(float r, float g, float b, float x, float y, float z)
+{
+	if(!nocolors)glColor4f(r,g,b,1);
+	if(nocolors==1)glColor4f(0,0,0,1);
+	if(nocolors==2)glColor4f(1,0,0,1);
+	if(nocolors==3)glColor4f(1,1,1,1);
+	glNormal3f(x,y,z);
+	glEnableClientState(GL_VERTEX_ARRAY);
+	glDisableClientState(GL_NORMAL_ARRAY);
+	glDisableClientState(GL_COLOR_ARRAY);
+	glVertexPointer(3, GL_FLOAT, 9*sizeof(GLfloat),&vArray[0]);
+	glDrawArrays(GL_TRIANGLES, 0, TriangleNum*3);
+}
+
+
+int Model::LineCheck(XYZ p1,XYZ p2, XYZ *p)
+{
+  	int j;
+	float distance;
+	float olddistance=9999999.0;
+	int intersecting=0;
+	int firstintersecting=-1;
+	XYZ point;
+	if(sphere_line_intersection(p1.x,p1.y,p1.z,
+								p2.x,p2.y,p2.z,
+								boundingspherecenter.x,boundingspherecenter.y,boundingspherecenter.z,
+								boundingsphereradius))
+	for (j=0;j<TriangleNum;j++){
+		intersecting=LineFacetd(p1,p2,vertex[Triangles[j].vertex[0]],vertex[Triangles[j].vertex[1]],vertex[Triangles[j].vertex[2]],normals[j],&point);
+		if (intersecting == 0) continue;
+		distance=(point.x-p1.x)*(point.x-p1.x)+(point.y-p1.y)*(point.y-p1.y)+(point.z-p1.z)*(point.z-p1.z);
+		if((distance<olddistance||firstintersecting==-1)&&intersecting){olddistance=distance; firstintersecting=j; *p=point;}
+	}
+	return firstintersecting;
+}
+
+int Model::LineCheck2(XYZ p1,XYZ p2, XYZ *p, XYZ move, float rotate)
+{
+  	int j;
+	float distance;
+	float olddistance=9999999.0;
+	int intersecting=0;
+	int firstintersecting=-1;
+	XYZ point;
+	p1=p1-move;
+	p2=p2-move;
+	if(rotate)p1=DoRotation(p1,0,-rotate,0);
+	if(rotate)p2=DoRotation(p2,0,-rotate,0);
+	if(sphere_line_intersection(p1.x,p1.y,p1.z,
+								p2.x,p2.y,p2.z,
+								boundingspherecenter.x,boundingspherecenter.y,boundingspherecenter.z,
+								boundingsphereradius))
+	for (j=0;j<TriangleNum;j++){
+		intersecting=LineFacetd(p1,p2,vertex[Triangles[j].vertex[0]],vertex[Triangles[j].vertex[1]],vertex[Triangles[j].vertex[2]],normals[j],&point);
+		if (intersecting == 0) continue;
+		distance=(point.x-p1.x)*(point.x-p1.x)+(point.y-p1.y)*(point.y-p1.y)+(point.z-p1.z)*(point.z-p1.z);
+		if((distance<olddistance||firstintersecting==-1)&&intersecting){olddistance=distance; firstintersecting=j; *p=point;}
+	}
+	
+	if(rotate)*p=DoRotation(*p,0,rotate,0);
+	*p=*p+move;
+	return firstintersecting;
+}
+
+int Model::LineCheck2(XYZ *p1,XYZ *p2, XYZ *p, XYZ *move, float *rotate)
+{
+  	int j;
+	float distance;
+	float olddistance=9999999.0;
+	int intersecting=0;
+	int firstintersecting=-1;
+	XYZ point;
+	*p1=*p1-*move;
+	*p2=*p2-*move;
+	if(*rotate)*p1=DoRotation(*p1,0,-*rotate,0);
+	if(*rotate)*p2=DoRotation(*p2,0,-*rotate,0);
+	if(sphere_line_intersection(p1->x,p1->y,p1->z,
+								p2->x,p2->y,p2->z,
+								boundingspherecenter.x,boundingspherecenter.y,boundingspherecenter.z,
+								boundingsphereradius))
+	for (j=0;j<TriangleNum;j++){
+		intersecting=LineFacetd(p1,p2,&vertex[Triangles[j].vertex[0]],&vertex[Triangles[j].vertex[1]],&vertex[Triangles[j].vertex[2]],&normals[j],&point);
+		if (intersecting == 0) continue;
+		distance=(point.x-p1->x)*(point.x-p1->x)+(point.y-p1->y)*(point.y-p1->y)+(point.z-p1->z)*(point.z-p1->z);
+		if((distance<olddistance||firstintersecting==-1)&&intersecting){olddistance=distance; firstintersecting=j; *p=point;}
+	}
+	
+	if(*rotate)*p=DoRotation(*p,0,*rotate,0);
+	*p=*p+*move;
+	return firstintersecting;
+}
+
+int Model::LineCheck3(XYZ p1,XYZ p2, XYZ *p, XYZ move, float rotate, float *d)
+{
+  	int j;
+	float distance;
+	float olddistance=9999999.0;
+	int intersecting=0;
+	int firstintersecting=-1;
+	XYZ point;
+	p1=p1-move;
+	p2=p2-move;
+	p1=DoRotation(p1,0,-rotate,0);
+	p2=DoRotation(p2,0,-rotate,0);
+	if(sphere_line_intersection(p1.x,p1.y,p1.z,
+								p2.x,p2.y,p2.z,
+								boundingspherecenter.x,boundingspherecenter.y,boundingspherecenter.z,
+								boundingsphereradius))
+	for (j=0;j<TriangleNum;j++){
+		intersecting=LineFacetd(p1,p2,vertex[Triangles[j].vertex[0]],vertex[Triangles[j].vertex[1]],vertex[Triangles[j].vertex[2]],normals[j],&point);
+		if (intersecting == 0) continue;
+		distance=(point.x-p1.x)*(point.x-p1.x)+(point.y-p1.y)*(point.y-p1.y)+(point.z-p1.z)*(point.z-p1.z);
+		if((distance<olddistance||firstintersecting==-1)&&intersecting){olddistance=distance; firstintersecting=j; *p=point;}
+	}
+	*d=intersecting;
+	*p=DoRotation(*p,0,rotate,0);
+	*p=*p+move;
+	return firstintersecting;
+}
diff --git a/src/Models.h b/src/Models.h
new file mode 100644
index 0000000..e49b8f1
--- /dev/null
+++ b/src/Models.h
@@ -0,0 +1,66 @@
+#ifndef _MODELS_H_
+#define _MODELS_H_
+
+/**> Model Loading <**/
+//
+// Model Maximums
+//
+#include "Quaternions.h"
+#ifdef OS9 
+#include <gl.h>
+#include <glu.h>
+#else
+#include <GL/gl.h>
+#include <GL/glu.h>
+#endif
+#include "Files.h"
+#include "Constants.h"
+
+#define max_textured_triangle		400		// maximum number of texture-filled triangles in a model
+#define max_model_vertex			max_textured_triangle*3		// maximum number of vertexs
+
+
+//
+// Model Structures
+//
+					
+class TexturedTriangle{
+	public:
+				short			vertex[3];
+				float r,g,b;
+};
+
+class Model{
+	public:
+				short	vertexNum,TriangleNum;
+				
+				XYZ					vertex[max_model_vertex];
+				XYZ					normals[max_textured_triangle];
+				TexturedTriangle	Triangles[max_textured_triangle];
+				GLfloat 			vArray[max_textured_triangle*27];
+				
+				XYZ boundingspherecenter;
+				float boundingsphereradius;
+				int LineCheck(XYZ p1,XYZ p2, XYZ *p);
+				int LineCheck2(XYZ p1,XYZ p2, XYZ *p,XYZ move,float rotate);
+				int LineCheck2(XYZ *p1,XYZ *p2, XYZ *p,XYZ *move,float *rotate);
+				int LineCheck3(XYZ p1,XYZ p2, XYZ *p,XYZ move,float rotate,float *d);
+				
+				void UpdateVertexArray();
+				bool load(Str255 Name);
+				void Scale(float xscale,float yscale,float zscale);
+				void ScaleNormals(float xscale,float yscale,float zscale);
+				void Translate(float xtrans,float ytrans,float ztrans);
+				void CalculateNormals();
+				void draw();
+				void draw(float r,float g,float b);
+				void draw(float r,float g,float b, float o);
+				void draw(float r,float g,float b, float x, float y, float z);
+				void Rotate(float xang,float yang,float zang);
+				void MultColor(float howmuch);
+				
+				XYZ boundingboxmin,boundingboxmax;
+};
+
+#endif
+
diff --git a/src/Person.cpp b/src/Person.cpp
new file mode 100644
index 0000000..43aa873
--- /dev/null
+++ b/src/Person.cpp
@@ -0,0 +1,1045 @@
+/**> HEADER FILES <**/
+#include "Person.h"
+
+extern double multiplier;
+extern unsigned int gSourceID[100];
+extern unsigned int gSampleSet[100];
+extern Animation animation[30];
+extern int thirdperson;
+extern int visions;
+extern Camera camera;
+extern float rad2deg;
+extern Model gunmodels[10];
+extern Model skeletonmodels[10];
+extern Sprites sprites;
+extern float soundscalefactor;
+extern int slomo;
+
+extern int forwardskey;
+extern int backwardskey;
+extern int leftkey;
+extern int rightkey;
+extern int aimkey;
+extern int psychicaimkey;
+extern int psychickey;
+
+HitStruct 	Person::BulletCollideWithPlayer(int who, XYZ start, XYZ end){
+	float damage=20;
+	XYZ tempbulletloc[2];
+	XYZ collisionpoint;
+	XYZ sparkpos;
+	GLfloat M[16];
+	int collide;
+	float howfar;
+	XYZ average;
+	XYZ facing;
+	int howmany;
+	float distancemax;
+	HitStruct hitstruct;
+	hitstruct.collision=0;
+	//Make bounding sphere
+	average=0;
+	howmany=0;
+	for(int j=0;j<skeleton.num_joints;j++){
+		average.x=average.x+skeleton.joints[j].position.x;
+		average.y=average.y+skeleton.joints[j].position.y;
+		average.z=average.z+skeleton.joints[j].position.z;
+		howmany++;
+	}
+	average=average/howmany;
+	distancemax=0;
+	for(int j=0;j<skeleton.num_joints;j++){
+		if(findDistancefast(average,skeleton.joints[j].position)>distancemax){
+			distancemax=findDistancefast(average,skeleton.joints[j].position);
+		}
+	}
+	distancemax=fast_sqrt(distancemax);
+	//Collide with player
+	if(skeleton.free<1){
+		start=start-playercoords;
+		end=end-playercoords;
+		if(playerrotation)start=DoRotation(start,0,-playerrotation,0);
+		if(playerrotation)end=DoRotation(end,0,-playerrotation,0);
+	}
+	tempbulletloc[0]=start;
+	tempbulletloc[1]=end;
+	if(sphere_line_intersection(tempbulletloc[0].x,tempbulletloc[0].y,tempbulletloc[0].z,
+								tempbulletloc[1].x,tempbulletloc[1].y,tempbulletloc[1].z,
+								average.x, average.y, average.z, distancemax)){
+	for(int j=0;j<skeleton.num_joints;j++){
+		if(skeleton.joints[j].hasparent&&skeleton.joints[j].visible){
+			tempbulletloc[0]=start;
+			tempbulletloc[1]=end;
+			glPushMatrix();
+				glLoadIdentity();
+				glScalef(1,1/skeleton.joints[j].length,1);
+				glRotatef(skeleton.joints[j].rotate2-90,0,0,1);
+				glRotatef(skeleton.joints[j].rotate1-90,0,1,0);
+				glTranslatef(	(-(skeleton.joints[j].position.x+skeleton.joints[j].parent->position.x)/2),
+								(-(skeleton.joints[j].position.y+skeleton.joints[j].parent->position.y)/2),
+								(-(skeleton.joints[j].position.z+skeleton.joints[j].parent->position.z)/2));
+				glTranslatef(tempbulletloc[0].x,tempbulletloc[0].y,tempbulletloc[0].z);
+				glGetFloatv(GL_MODELVIEW_MATRIX,M);
+				tempbulletloc[0].x=M[12];
+				tempbulletloc[0].y=M[13];
+				tempbulletloc[0].z=M[14];
+			glPopMatrix();
+			glPushMatrix();
+				glLoadIdentity();
+				glScalef(1,1/skeleton.joints[j].length,1);
+				glRotatef(skeleton.joints[j].rotate2-90,0,0,1);
+				glRotatef(skeleton.joints[j].rotate1-90,0,1,0);
+				glTranslatef(	(-(skeleton.joints[j].position.x+skeleton.joints[j].parent->position.x)/2),
+								(-(skeleton.joints[j].position.y+skeleton.joints[j].parent->position.y)/2),
+								(-(skeleton.joints[j].position.z+skeleton.joints[j].parent->position.z)/2));
+				glTranslatef(tempbulletloc[1].x,tempbulletloc[1].y,tempbulletloc[1].z);
+				glGetFloatv(GL_MODELVIEW_MATRIX,M);
+				tempbulletloc[1].x=M[12];
+				tempbulletloc[1].y=M[13];
+				tempbulletloc[1].z=M[14];
+			glPopMatrix();
+			collide=skeletonmodels[skeleton.joints[j].modelnum].LineCheck(tempbulletloc[0],tempbulletloc[1],&collisionpoint);
+			if(collide!=-1)
+			{
+				glPushMatrix();
+					glLoadIdentity();
+					glTranslatef(	(skeleton.joints[j].position.x+skeleton.joints[j].parent->position.x)/2,
+									(skeleton.joints[j].position.y+skeleton.joints[j].parent->position.y)/2,
+									(skeleton.joints[j].position.z+skeleton.joints[j].parent->position.z)/2);
+					glRotatef(-skeleton.joints[j].rotate1+90,0,1,0);
+					glRotatef(-skeleton.joints[j].rotate2+90,0,0,1);
+					glScalef(1,skeleton.joints[j].length,1);
+					glTranslatef(collisionpoint.x,collisionpoint.y,collisionpoint.z);
+					glGetFloatv(GL_MODELVIEW_MATRIX,M);
+					collisionpoint.x=M[12];
+					collisionpoint.y=M[13];
+					collisionpoint.z=M[14];
+				glPopMatrix();
+				hitstruct.collision=1;
+				hitstruct.hitlocation=collisionpoint;
+				hitstruct.joint1=&skeleton.joints[j];
+				hitstruct.joint2=skeleton.joints[j].parent;
+			}
+		}
+	}
+	for(int j=0;j<skeleton.num_muscles;j++){
+		if(skeleton.muscles[j].visible){
+			tempbulletloc[0]=start;
+			tempbulletloc[1]=end;
+			glPushMatrix();
+				glLoadIdentity();
+				glScalef(1,1/skeleton.muscles[j].length,1);
+				glRotatef(skeleton.muscles[j].rotate3,0,1,0);
+				glRotatef(skeleton.muscles[j].rotate2-90,0,0,1);
+				glRotatef(skeleton.muscles[j].rotate1-90,0,1,0);
+				glTranslatef(	(-(skeleton.muscles[j].parent1->position.x+skeleton.muscles[j].parent2->position.x)/2),
+								(-(skeleton.muscles[j].parent1->position.y+skeleton.muscles[j].parent2->position.y)/2),
+								(-(skeleton.muscles[j].parent1->position.z+skeleton.muscles[j].parent2->position.z)/2));
+
+				glTranslatef(tempbulletloc[0].x,tempbulletloc[0].y,tempbulletloc[0].z);
+				glGetFloatv(GL_MODELVIEW_MATRIX,M);
+				tempbulletloc[0].x=M[12];
+				tempbulletloc[0].y=M[13];
+				tempbulletloc[0].z=M[14];
+			glPopMatrix();
+			glPushMatrix();
+				glLoadIdentity();
+				glScalef(1,1/skeleton.muscles[j].length,1);
+				glRotatef(skeleton.muscles[j].rotate3,0,1,0);
+				glRotatef(skeleton.muscles[j].rotate2-90,0,0,1);
+				glRotatef(skeleton.muscles[j].rotate1-90,0,1,0);
+				
+				glTranslatef(	(-(skeleton.muscles[j].parent1->position.x+skeleton.muscles[j].parent2->position.x)/2),
+								(-(skeleton.muscles[j].parent1->position.y+skeleton.muscles[j].parent2->position.y)/2),
+								(-(skeleton.muscles[j].parent1->position.z+skeleton.muscles[j].parent2->position.z)/2));
+				glTranslatef(tempbulletloc[1].x,tempbulletloc[1].y,tempbulletloc[1].z);
+				glGetFloatv(GL_MODELVIEW_MATRIX,M);
+				tempbulletloc[1].x=M[12];
+				tempbulletloc[1].y=M[13];
+				tempbulletloc[1].z=M[14];
+			glPopMatrix();
+			collide=skeletonmodels[skeleton.muscles[j].parent1->modelnum].LineCheck(tempbulletloc[0],tempbulletloc[1],&collisionpoint);
+			if(collide!=-1)
+			{
+				glPushMatrix();
+					glLoadIdentity();
+					glTranslatef(	(skeleton.muscles[j].parent1->position.x+skeleton.muscles[j].parent2->position.x)/2,
+									(skeleton.muscles[j].parent1->position.y+skeleton.muscles[j].parent2->position.y)/2,
+									(skeleton.muscles[j].parent1->position.z+skeleton.muscles[j].parent2->position.z)/2);
+					glRotatef(-skeleton.muscles[j].rotate1+90,0,1,0);
+					glRotatef(-skeleton.muscles[j].rotate2+90,0,0,1);
+					glRotatef(-skeleton.muscles[j].rotate3,0,1,0);
+					glScalef(1,findDistance(skeleton.muscles[j].parent1->position,skeleton.muscles[j].parent2->position),1);
+					glTranslatef(collisionpoint.x,collisionpoint.y,collisionpoint.z);
+					glGetFloatv(GL_MODELVIEW_MATRIX,M);
+					collisionpoint.x=M[12];
+					collisionpoint.y=M[13];
+					collisionpoint.z=M[14];
+				glPopMatrix();
+				hitstruct.collision=1;
+				hitstruct.hitlocation=collisionpoint;
+				hitstruct.joint1=skeleton.muscles[j].parent1;
+				hitstruct.joint2=skeleton.muscles[j].parent2;
+			}
+		}
+	}
+	}
+	if(skeleton.free<1){
+		if(playerrotation)hitstruct.hitlocation=DoRotation(hitstruct.hitlocation,0,playerrotation,0);
+		hitstruct.hitlocation=hitstruct.hitlocation+playercoords;
+	}
+	return hitstruct;
+}
+
+extern float camerashake;
+extern int cycle;
+void 	Person::DoAnimations(int who){	
+	
+	if(target>1&&!skeleton.free){
+		//Footstep sounds
+		if(who==0&&slomo==0&&(targetanimation==joganim||targetanimation==walkanim)&&(targetframe==0||targetframe==8)&&visions==0&&(onground||abs(velocity.y)<1)){
+			int whichsound;
+			float gLoc[3];
+			gLoc[0]=playercoords.x/soundscalefactor;
+			gLoc[1]=playercoords.y/soundscalefactor;
+			gLoc[2]=playercoords.z/soundscalefactor;
+			whichsound=footstepsound+abs(Random())%5;
+			alSourcefv(gSourceID[whichsound], AL_POSITION, gLoc);
+			alSourcePlay(gSourceID[whichsound]);
+		}
+		if(targetanimation==zombieeatanim&&(targetframe==3)){
+			int whichsound;
+			float gLoc[3];
+			XYZ soundpoint=(DoRotation(skeleton.joints[skeleton.jointlabels[head]].position,0,playerrotation,0)+playercoords);
+			gLoc[0]=soundpoint.x/soundscalefactor;
+			gLoc[1]=soundpoint.y/soundscalefactor;
+			gLoc[2]=soundpoint.z/soundscalefactor;
+			alSourcefv(gSourceID[bodyhitsound], AL_POSITION, gLoc);
+			alSourcePlay(gSourceID[bodyhitsound]);
+			bleeding=1;
+			bleeddelay=1;
+			bjoint1=&skeleton.joints[skeleton.jointlabels[head]];
+			bjoint2=&skeleton.joints[skeleton.jointlabels[neck]];
+		}
+		targetframe=currentframe;
+		currentanimation=targetanimation;
+		if(!backwardsanim){targetframe++;
+		if(targetframe>animation[currentanimation].numframes-1)targetframe=0;}
+		if(backwardsanim){targetframe--;
+		if(targetframe<0)targetframe=animation[currentanimation].numframes-1;}
+		target=0;
+		if((currentanimation==getupfrontanim||currentanimation==getupbackanim)&&targetframe==0){
+			targetanimation=idleanim;
+		}
+		if(targetanimation==diveanim&&currentanimation==diveanim&&targetframe==0){
+			targetanimation=getupfrontanim;
+			float gLoc[3];
+			XYZ soundpoint=(DoRotation(skeleton.joints[skeleton.jointlabels[head]].position,0,playerrotation,0)+playercoords);
+			gLoc[0]=soundpoint.x/soundscalefactor;
+			gLoc[1]=soundpoint.y/soundscalefactor;
+			gLoc[2]=soundpoint.z/soundscalefactor;
+			alSourcefv(gSourceID[bodywhacksound], AL_POSITION, gLoc);
+			alSourcePlay(gSourceID[bodywhacksound]);
+		}
+		if(currentanimation==throwanim&&targetframe==0){
+			targetanimation=idleanim;
+		}
+		if(currentanimation==thrownanim&&targetframe==0){
+			skeleton.offset=0;
+			skeleton.free=1;
+			longdead=1;
+			for(int j=0;j<skeleton.num_joints;j++){
+				skeleton.joints[j].position+=skeleton.joints[j].offset;
+				skeleton.joints[j].position=DoRotation(skeleton.joints[j].position,0,playerrotation,0);
+				skeleton.joints[j].position+=playercoords;
+				skeleton.joints[j].realoldposition=skeleton.joints[j].position;
+				skeleton.joints[j].velocity=DoRotation(skeleton.joints[j].velocity,0,playerrotation,0);
+			}
+		}
+	}
+	
+	if(!skeleton.free){
+		if(currentanimation!=lyinganim){
+			if(animation[targetanimation].speed[currentframe]>animation[currentanimation].speed[currentframe])
+				target+=multiplier*animation[targetanimation].speed[currentframe]*speed;
+			if(animation[targetanimation].speed[currentframe]<=animation[currentanimation].speed[currentframe])
+				target+=multiplier*animation[currentanimation].speed[currentframe]*speed;
+		}
+		if(currentanimation==lyinganim){
+			target+=multiplier*animation[targetanimation].speed[targetframe]*speed;
+		}		
+		if(((currentanimation==crouchanim)&&(targetanimation!=crouchanim))||((currentanimation!=crouchanim)&&(targetanimation==crouchanim)))target+=multiplier*animation[crouchanim].speed[0]*2;
+		if(currentanimation==idleanim&&targetanimation==idleanim)target-=multiplier*animation[idleanim].speed[0]/2;
+		
+		if(target>1)currentframe=targetframe;
+		
+		for(int i=0;i<skeleton.num_joints;i++){
+			if(currentanimation!=lyinganim){
+				skeleton.joints[i].velocity=((animation[currentanimation].position[i][currentframe]*(1-target)+animation[targetanimation].position[i][targetframe]*(target))-(skeleton.joints[i].position))/multiplier;
+				skeleton.joints[i].position=animation[currentanimation].position[i][currentframe]*(1-target)+animation[targetanimation].position[i][targetframe]*(target);
+				if(skeleton.joints[i].hasparent&&skeleton.joints[i].visible)
+				{
+					skeleton.joints[i].rotate1=animation[currentanimation].rotate1[i][currentframe]*(1-target)+animation[targetanimation].rotate1[i][targetframe]*(target);
+					skeleton.joints[i].rotate2=animation[currentanimation].rotate2[i][currentframe]*(1-target)+animation[targetanimation].rotate2[i][targetframe]*(target);
+					skeleton.joints[i].rotate3=animation[currentanimation].rotate3[i][currentframe]*(1-target)+animation[targetanimation].rotate3[i][targetframe]*(target);
+				}
+				if(skeleton.muscles[i].visible)
+				{
+					skeleton.muscles[i].rotate1=animation[currentanimation].mrotate1[i][currentframe]*(1-target)+animation[targetanimation].mrotate1[i][targetframe]*(target);
+					skeleton.muscles[i].rotate2=animation[currentanimation].mrotate2[i][currentframe]*(1-target)+animation[targetanimation].mrotate2[i][targetframe]*(target);
+					skeleton.muscles[i].rotate3=animation[currentanimation].mrotate3[i][currentframe]*(1-target)+animation[targetanimation].mrotate3[i][targetframe]*(target);
+				}
+			}
+			if(currentanimation==lyinganim){
+				skeleton.joints[i].velocity=((tempanimation.position[i][0]*(1-target)+animation[targetanimation].position[i][targetframe]*(target))-(skeleton.joints[i].position))/multiplier;
+				skeleton.joints[i].position=tempanimation.position[i][0]*(1-target)+animation[targetanimation].position[i][targetframe]*(target);
+			}
+		}
+	}
+	
+	//Look up+down
+	if(!skeleton.free&&(whichgun!=nogun||who==0)&&health==100&&currentanimation!=lyinganim&&currentanimation!=getupfrontanim&&currentanimation!=getupbackanim&&currentanimation!=diveanim&&targetanimation!=diveanim&&targetanimation!=throwanim&&targetanimation!=thrownanim){		
+		XYZ facing;
+		XYZ facingdown;
+		XYZ facinghalf;
+		XYZ facingright;
+		int oldanimation=currentanimation;
+		if(who==0){
+			playerrotation2=camera.rotation2;
+			//Facing
+			facing=0;
+			facing.z=1;
+			
+			facinghalf=DoRotation(facing,playerrotation2/2,0,0);
+			facinghalf=DoRotation(facinghalf,0,-7,0);
+			facing=DoRotation(facing,playerrotation2,0,0);
+			facingright=DoRotation(facing,0,-90,0);
+			facingdown=DoRotation(facing,90,0,0);
+		}
+		if(who!=0){
+			//Facing
+			facing=0;
+			facing.z=1;
+			
+			facinghalf=DoRotation(facing,playerrotation2/2,0,0);
+			facinghalf=DoRotation(facinghalf,0,-7,0);
+			facing=DoRotation(facing,playerrotation2,0,0);
+			facingright=DoRotation(facing,0,-90,0);
+			facingdown=DoRotation(facing,90,0,0);
+		}
+		XYZ rotatearound;
+		XYZ oldpos;	
+		if(whichgun==sniperrifle){
+			for(int i=0;i<skeleton.num_joints;i++){
+				if(skeleton.joints[i].label!=righthand&&skeleton.joints[i].label!=rightelbow&&skeleton.joints[i].label!=rightwrist&&skeleton.joints[i].label!=lefthand&&skeleton.joints[i].label!=leftelbow&&skeleton.joints[i].label!=leftwrist){
+				}else{
+					skeleton.joints[i].position=animation[rifleholdanim].position[i][0];
+					if(currentanimation==crouchanim||targetanimation==crouchanim)skeleton.joints[i].position-=(animation[idleanim].position[skeleton.jointlabels[neck]][0]-skeleton.joints[skeleton.jointlabels[neck]].position);
+				}
+			}
+		}
+		if(whichgun==shotgun){
+			for(int i=0;i<skeleton.num_joints;i++){
+				if(skeleton.joints[i].label!=righthand&&skeleton.joints[i].label!=rightelbow&&skeleton.joints[i].label!=rightwrist&&skeleton.joints[i].label!=lefthand&&skeleton.joints[i].label!=leftelbow&&skeleton.joints[i].label!=leftwrist){
+				}else{
+					skeleton.joints[i].position=animation[rifleholdanim].position[i][0];
+					if(currentanimation==crouchanim||targetanimation==crouchanim)skeleton.joints[i].position-=(animation[idleanim].position[skeleton.jointlabels[neck]][0]-skeleton.joints[skeleton.jointlabels[neck]].position);
+				}
+			}
+		}	
+		if(whichgun==assaultrifle){
+			for(int i=0;i<skeleton.num_joints;i++){
+				if(skeleton.joints[i].label!=righthand&&skeleton.joints[i].label!=rightelbow&&skeleton.joints[i].label!=rightwrist&&skeleton.joints[i].label!=lefthand&&skeleton.joints[i].label!=leftelbow&&skeleton.joints[i].label!=leftwrist){
+				}else{
+					skeleton.joints[i].position=animation[rifleholdanim].position[i][0];
+					if(currentanimation==crouchanim||targetanimation==crouchanim)skeleton.joints[i].position-=(animation[idleanim].position[skeleton.jointlabels[neck]][0]-skeleton.joints[skeleton.jointlabels[neck]].position);
+				}
+			}
+		}	
+		if((aiming||aimamount>0||whichgun==grenade)&&whichgun!=nogun){
+			if(aiming&&targetanimation!=joganim){
+				if(aimamount<1)aimamount+=multiplier*4;
+				if(aimamount>1)aimamount=1;
+			}
+			if(!aiming||targetanimation==joganim){
+				if(aimamount>0)aimamount-=multiplier*4;
+				if(aimamount<0)aimamount=0;
+			}
+			if(grenphase==1){
+				if(grenamount<1)grenamount+=multiplier*4;
+				if(grenamount>1)grenamount=1;
+			}
+			if(grenphase==0){
+				if(grenamount>0)grenamount-=multiplier*4;
+				if(grenamount<0)grenamount=0;
+			}
+			rotatearound=skeleton.joints[skeleton.jointlabels[neck]].position;
+			for(int i=0;i<skeleton.num_joints;i++){
+				if(skeleton.joints[i].label!=righthand&&skeleton.joints[i].label!=rightelbow&&skeleton.joints[i].label!=rightwrist&&skeleton.joints[i].label!=lefthand&&skeleton.joints[i].label!=leftelbow&&skeleton.joints[i].label!=leftwrist){
+				}else{
+					if(whichgun==sniperrifle){
+						oldpos=skeleton.joints[i].position;
+						skeleton.joints[i].position=animation[rifleaimanim].position[i][0];
+						if(currentanimation==crouchanim||targetanimation==crouchanim){
+							skeleton.joints[i].position-=(animation[idleanim].position[skeleton.jointlabels[neck]][0]-skeleton.joints[skeleton.jointlabels[neck]].position);
+						}
+						skeleton.joints[i].position+=facingright*0.1;
+						skeleton.joints[i].position=rotatearound+DoRotation(skeleton.joints[i].position-rotatearound,(playerrotation2/2-10)*aimamount,0,0);
+						skeleton.joints[i].position=skeleton.joints[i].position*(aimamount)+oldpos*(1-aimamount);
+					}
+					if(whichgun==shotgun){
+						oldpos=skeleton.joints[i].position;
+						skeleton.joints[i].position=animation[assaultrifleaimanim].position[i][0];
+						if(currentanimation==crouchanim||targetanimation==crouchanim)skeleton.joints[i].position-=(animation[idleanim].position[skeleton.jointlabels[neck]][0]-skeleton.joints[skeleton.jointlabels[neck]].position);
+						skeleton.joints[i].position=rotatearound+DoRotation(skeleton.joints[i].position-rotatearound,(playerrotation2/2)*aimamount,0,0);
+						if(currentanimation==crouchanim||targetanimation==crouchanim)skeleton.joints[i].position+=facingdown*.2;
+						else skeleton.joints[i].position-=facingdown*.02;
+						if(skeleton.joints[i].label==righthand)skeleton.joints[i].position=skeleton.joints[skeleton.jointlabels[lefthand]].position-facinghalf*2;
+						skeleton.joints[i].position=skeleton.joints[i].position*(aimamount)+oldpos*(1-aimamount);
+					}
+					if(whichgun==assaultrifle){
+						oldpos=skeleton.joints[i].position;
+						skeleton.joints[i].position=animation[assaultrifleaimanim].position[i][0];
+						if(currentanimation==crouchanim||targetanimation==crouchanim)skeleton.joints[i].position-=(animation[idleanim].position[skeleton.jointlabels[neck]][0]-skeleton.joints[skeleton.jointlabels[neck]].position);
+						skeleton.joints[i].position=rotatearound+DoRotation(skeleton.joints[i].position-rotatearound,(playerrotation2/2)*aimamount,0,0);
+						if(currentanimation==crouchanim||targetanimation==crouchanim)skeleton.joints[i].position+=facingdown*.2;
+						else skeleton.joints[i].position-=facingdown*.02;
+						if(skeleton.joints[i].label==righthand)skeleton.joints[i].position=skeleton.joints[skeleton.jointlabels[lefthand]].position-facinghalf*2;
+						skeleton.joints[i].position=skeleton.joints[i].position*(aimamount)+oldpos*(1-aimamount);
+					}
+					if(whichgun==handgun1){
+						oldpos=skeleton.joints[i].position;
+						skeleton.joints[i].position=animation[pistolaimanim].position[i][0];
+						if(currentanimation==crouchanim||targetanimation==crouchanim)skeleton.joints[i].position-=(animation[idleanim].position[skeleton.jointlabels[neck]][0]-skeleton.joints[skeleton.jointlabels[neck]].position);
+						skeleton.joints[i].position=rotatearound+DoRotation(skeleton.joints[i].position-rotatearound,(playerrotation2/2)*aimamount,0,0);
+						if(currentanimation==crouchanim||targetanimation==crouchanim){skeleton.joints[i].position+=facingright*.15;skeleton.joints[i].position+=facingdown*.3;}
+						else skeleton.joints[i].position-=facingdown*.1;
+						skeleton.joints[i].position=skeleton.joints[i].position*(aimamount)+oldpos*(1-aimamount);
+					}
+					if(whichgun==handgun2){
+						oldpos=skeleton.joints[i].position;
+						skeleton.joints[i].position=animation[pistolaimanim].position[i][0];
+						if(currentanimation==crouchanim||targetanimation==crouchanim)skeleton.joints[i].position-=(animation[idleanim].position[skeleton.jointlabels[neck]][0]-skeleton.joints[skeleton.jointlabels[neck]].position);
+						skeleton.joints[i].position=rotatearound+DoRotation(skeleton.joints[i].position-rotatearound,(playerrotation2/2)*aimamount,0,0);
+						if(currentanimation==crouchanim||targetanimation==crouchanim){skeleton.joints[i].position+=facingright*.15;skeleton.joints[i].position+=facingdown*.3;}
+						else skeleton.joints[i].position-=facingdown*.1;
+						skeleton.joints[i].position=skeleton.joints[i].position*(aimamount)+oldpos*(1-aimamount);
+					}
+					if(whichgun==grenade){
+						aimamount=1;
+						oldpos=skeleton.joints[i].position;
+						skeleton.joints[i].position=animation[grenadeaimanim].position[i][0];
+						if(currentanimation==crouchanim||targetanimation==crouchanim)skeleton.joints[i].position-=(animation[idleanim].position[skeleton.jointlabels[neck]][0]-skeleton.joints[skeleton.jointlabels[neck]].position);
+						skeleton.joints[i].position=skeleton.joints[i].position*(aimamount)+oldpos*(1-aimamount);
+					}
+					if(whichgun==grenade&&grenamount>0){
+						oldpos=skeleton.joints[i].position;
+						skeleton.joints[i].position=animation[grenadechargeanim].position[i][0];
+						if(currentanimation==crouchanim||targetanimation==crouchanim)skeleton.joints[i].position-=(animation[idleanim].position[skeleton.jointlabels[neck]][0]-skeleton.joints[skeleton.jointlabels[neck]].position);
+						skeleton.joints[i].position=skeleton.joints[i].position*(grenamount)+oldpos*(1-grenamount);
+					}
+					if(thirdperson||who!=0)skeleton.joints[i].position+=facingdown*.4;
+					if(currentanimation!=crouchanim)skeleton.joints[i].position-=facinghalf*recoil*.35;
+					if(currentanimation==crouchanim)skeleton.joints[i].position-=facinghalf*recoil*.1;
+				}
+			}
+		}
+		//Whack
+		if(attackframe>-1&&whichgun!=grenade){
+			for(int i=0;i<skeleton.num_joints;i++){
+				if(!skeleton.joints[i].lower){
+					if(attackframe==animation[riflehitanim].numframes)skeleton.joints[i].position=skeleton.joints[i].position*(attacktarget)+animation[riflehitanim].position[i][attackframe-1]*(1-attacktarget);
+					if(attackframe>0&&attackframe<animation[riflehitanim].numframes)skeleton.joints[i].position=animation[riflehitanim].position[i][attackframe-1]*(1-attacktarget)+animation[riflehitanim].position[i][attackframe]*(attacktarget);
+					if(attackframe==0)skeleton.joints[i].position=skeleton.joints[i].position*(1-attacktarget)+animation[riflehitanim].position[i][attackframe]*(attacktarget);
+				}
+			}
+			if(attackframe==0)attacktarget+=multiplier*animation[riflehitanim].speed[attackframe]*2;
+			if(attackframe>0)attacktarget+=multiplier*animation[riflehitanim].speed[attackframe-1]*2;
+			if(attacktarget>1){
+				attacktarget=0;
+				attackframe++;
+				if(attackframe>animation[riflehitanim].numframes)attackframe=-1;
+			}
+		}
+		//Throw grenade
+		if(attackframe>-1&&whichgun==grenade&&ammo>0){
+			for(int i=0;i<skeleton.num_joints;i++){
+				if(!skeleton.joints[i].lower){
+					if(attackframe==animation[grenadethrowanim].numframes)skeleton.joints[i].position=skeleton.joints[i].position*(attacktarget)+animation[grenadethrowanim].position[i][attackframe-1]*(1-attacktarget);
+					if(attackframe>0&&attackframe<animation[grenadethrowanim].numframes)skeleton.joints[i].position=animation[grenadethrowanim].position[i][attackframe-1]*(1-attacktarget)+animation[grenadethrowanim].position[i][attackframe]*(attacktarget);
+					if(attackframe==0)skeleton.joints[i].position=skeleton.joints[i].position*(1-attacktarget)+animation[grenadethrowanim].position[i][attackframe]*(attacktarget);
+				}
+			}
+			if(attackframe==0)attacktarget+=multiplier*animation[grenadethrowanim].speed[attackframe]*2;
+			if(attackframe>0)attacktarget+=multiplier*animation[grenadethrowanim].speed[attackframe-1]*2;
+			if(attacktarget>1){
+				attacktarget=0;
+				attackframe++;
+				if(attackframe>animation[grenadethrowanim].numframes){
+					attackframe=-1;
+				}
+				if(attackframe==animation[grenadethrowanim].numframes-1&&ammo>0){
+					ammo=-1;
+					sprites.MakeSprite(grenadesprite, 1, 1, 1, 1, DoRotation(skeleton.joints[skeleton.jointlabels[righthand]].position,0,playerrotation,0)+playercoords, DoRotation(facing,0,playerrotation,0)*30+velocity, 1);
+					sprites.MakeSprite(spoonsprite, 1, 1, 1, 1, DoRotation(skeleton.joints[skeleton.jointlabels[righthand]].position,0,playerrotation,0)+playercoords, DoRotation(facing,0,playerrotation,0)*10+velocity, 1);
+					sprites.MakeSprite(pinsprite, 1, 1, 1, 1, DoRotation(skeleton.joints[skeleton.jointlabels[lefthand]].position,0,playerrotation,0)+playercoords, facing*.1+velocity, 1);
+					XYZ soundsource=DoRotation(skeleton.joints[skeleton.jointlabels[righthand]].position,0,playerrotation,0)+playercoords;
+					float gLoc[3];
+					gLoc[0]=soundsource.x/soundscalefactor;
+					gLoc[1]=soundsource.y/soundscalefactor;
+					gLoc[2]=soundsource.z/soundscalefactor;
+					alSourcefv(gSourceID[grenadethrowsound], AL_POSITION, gLoc);
+					alSourcePlay(gSourceID[grenadethrowsound]);
+				}
+			}
+		}
+		
+		rotatearound=skeleton.joints[skeleton.jointlabels[abdomen]].position;
+		if(who==0)
+		for(int i=0;i<skeleton.num_joints;i++){
+		 	if(skeleton.joints[i].lower==0)
+		 		skeleton.joints[i].position=rotatearound+DoRotation(skeleton.joints[i].position-rotatearound,playerrotation2/2,0,0);
+		}
+		if(who==0)
+		for(int i=0;i<skeleton.num_joints;i++){
+		 	if(skeleton.joints[i].lower==1&&skeleton.joints[i].label!=groin)
+		 		skeleton.joints[i].position=DoRotation(skeleton.joints[i].position,0,playerlowrotation-playerrotation,0);
+		}
+		//head facing
+		if(who==0){
+		rotatearound=skeleton.joints[skeleton.jointlabels[neck]].position;
+		skeleton.joints[skeleton.jointlabels[head]].position=rotatearound+DoRotation(skeleton.joints[skeleton.jointlabels[head]].position-rotatearound,playerrotation2/2,0,0);
+		}
+		
+		skeleton.DoConstraints();
+		
+		//Reload
+		if(whichgun!=nogun&&whichgun!=knife){
+			if(reloading>0){
+				aiming=0;
+				reloading-=multiplier;
+			}
+			if(ammo<0&&reloads[whichgun]>0&&reloading<=0){
+				if(whichgun!=grenade){
+					float gLoc[3];
+					ALint tempint;
+					gLoc[0]=playercoords.x/soundscalefactor;
+					gLoc[1]=playercoords.y/soundscalefactor;
+					gLoc[2]=playercoords.z/soundscalefactor;
+#ifdef DEBIAN_NEEDS_TO_UPDATE_THEIR_OPENAL					
+					alGetSourceiv(gSourceID[reloadsound], AL_SOURCE_STATE, &tempint);
+#else					
+					alGetSourcei(gSourceID[reloadsound], AL_SOURCE_STATE, &tempint);
+#endif
+
+					if (tempint != AL_PLAYING){
+						alSourcefv(gSourceID[reloadsound], AL_POSITION, gLoc);
+						alSourcePlay(gSourceID[reloadsound]);
+					}
+				}
+				reloading=3;
+				aiming=0;
+				if(whichgun==sniperrifle)ammo=5;
+				if(whichgun==assaultrifle)ammo=25;
+				if(whichgun==handgun1)ammo=12;
+				if(whichgun==handgun2)ammo=16;
+				if(whichgun==grenade){ammo=1; reloading=1;}
+				if(whichgun==shotgun)ammo=6;
+				reloads[whichgun]--;
+			}
+			if(reloads[whichgun]==0&&whichgun==grenade&&ammo<=0){
+				whichgun=nogun;	
+			}
+			if(reloading<0){
+				reloading=0;
+				aiming=1;
+			}
+		}
+	}
+}
+
+void 	Person::DoAnimationslite(int who){
+	
+	int oldanimation=currentanimation;
+	if(target>1&&!skeleton.free){
+		//Footstep sounds
+		if(who==0&&(targetanimation==joganim||targetanimation==walkanim)&&(targetframe==0||targetframe==8)&&visions==0&&(onground||abs(velocity.y)<1)){
+			int whichsound;
+			float gLoc[3];
+			gLoc[0]=playercoords.x/soundscalefactor;
+			gLoc[1]=playercoords.y/soundscalefactor;
+			gLoc[2]=playercoords.z/soundscalefactor;
+			whichsound=footstepsound+abs(Random())%5;
+			alSourcefv(gSourceID[whichsound], AL_POSITION, gLoc);
+			alSourcePlay(gSourceID[whichsound]);
+		}
+		if(targetanimation==zombieeatanim&&(targetframe==3)){
+			int whichsound;
+			float gLoc[3];
+			XYZ soundpoint=(DoRotation(skeleton.joints[skeleton.jointlabels[head]].position,0,playerrotation,0)+playercoords);
+			gLoc[0]=soundpoint.x/soundscalefactor;
+			gLoc[1]=soundpoint.y/soundscalefactor;
+			gLoc[2]=soundpoint.z/soundscalefactor;
+			alSourcefv(gSourceID[bodyhitsound], AL_POSITION, gLoc);
+			alSourcePlay(gSourceID[bodyhitsound]);
+			bleeding=1;
+			bleeddelay=1;
+			bjoint1=&skeleton.joints[skeleton.jointlabels[head]];
+			bjoint2=&skeleton.joints[skeleton.jointlabels[neck]];
+		}
+		targetframe=currentframe;
+		currentanimation=targetanimation;
+		if(!backwardsanim){targetframe++;
+		if(targetframe>animation[currentanimation].numframes-1)targetframe=0;}
+		if(backwardsanim){targetframe--;
+		if(targetframe<0)targetframe=animation[currentanimation].numframes-1;}
+		target=0;
+		if((currentanimation==getupfrontanim||currentanimation==getupbackanim)&&targetframe==0){
+			targetanimation=idleanim;
+		}
+	}
+	
+	if(!skeleton.free){
+		if(currentanimation!=lyinganim){
+			if(animation[targetanimation].speed[currentframe]>animation[currentanimation].speed[currentframe])
+				target+=multiplier*animation[targetanimation].speed[currentframe]*speed;
+			if(animation[targetanimation].speed[currentframe]<=animation[currentanimation].speed[currentframe])
+				target+=multiplier*animation[currentanimation].speed[currentframe]*speed;
+		}
+		if(currentanimation==lyinganim){
+			target+=multiplier*animation[targetanimation].speed[targetframe]*speed;
+		}		
+		if(((currentanimation==crouchanim)&&(targetanimation!=crouchanim))||((currentanimation!=crouchanim)&&(targetanimation==crouchanim)))target+=multiplier*animation[crouchanim].speed[0]*2;
+		if(currentanimation==idleanim&&targetanimation==idleanim)target-=multiplier*animation[idleanim].speed[0]/2;
+		
+		if(target>1)currentframe=targetframe;
+	}
+}
+
+void 	Person::DoStuff(int who){
+	int moveanim;
+
+	if((targetanimation!=idleanim&&targetanimation!=crouchanim)||visions==1)playerlowrotation=playerrotation;
+	if(targetanimation!=crouchanim&&currentanimation!=crouchanim){
+		if(playerrotation>playerlowrotation+50){playerlowrotation=playerrotation-50; targetanimation=walkanim; targetframe=0; target=0;}
+		if(playerrotation<playerlowrotation-50){playerlowrotation=playerrotation+50; targetanimation=walkanim; targetframe=0; target=0;}
+	}
+	if(targetanimation==crouchanim||currentanimation==crouchanim){
+		if(playerrotation>playerlowrotation+70){playerrotation=playerlowrotation+70;}
+		if(playerrotation<playerlowrotation-70){playerrotation=playerlowrotation-70;}
+	}
+	if(who==0)camera.rotation=180-playerrotation;
+	
+	if(who!=0&&visions==0){
+		if(targetanimation!=walkanim&&targetanimation!=zombiewalkanim)speed=1.0*speedmult;
+		if(targetanimation==walkanim||targetanimation==zombiewalkanim)speed=1.8*speedmult;
+		playerlowrotation=playerrotation;
+	}
+	
+	//Do controls
+	if(who==0&&targetanimation!=diveanim&&targetanimation!=throwanim&&targetanimation!=thrownanim&&currentanimation!=diveanim&&currentanimation!=getupfrontanim){
+		backwardsanim=0;
+		if(visions==1)speed=40;
+		if(visions==0&&targetanimation==joganim)speed=2.2;
+		if(visions==0&&targetanimation!=joganim)speed=1.3;
+		if(visions==0&&targetanimation==walkanim)speed=2.5;
+		unsigned char	theKeyMap[16];
+		GetKeys( ( unsigned long * )theKeyMap );
+		
+		if(IsKeyDown( theKeyMap, MAC_SHIFT_KEY )||visions==1){
+			moveanim=joganim;
+		}else{
+			moveanim=walkanim;
+		}
+		if(IsKeyDown( theKeyMap, MAC_CONTROL_KEY )&&currentanimation==idleanim&&targetanimation==idleanim){
+			targetanimation=crouchanim;
+			target=0;
+		}
+		if(!IsKeyDown( theKeyMap, MAC_CONTROL_KEY )&&currentanimation==crouchanim&&targetanimation==crouchanim){
+			targetanimation=idleanim;
+			target=0;
+		}
+		if((onground||(who==0&&visions==1))&&currentanimation!=crouchanim){
+			if ( IsKeyDown( theKeyMap, forwardskey )&&!( IsKeyDown( theKeyMap, backwardskey ))){
+				if(targetanimation!=moveanim)targetframe=0;
+				targetanimation=moveanim;		
+			}
+			if ( IsKeyDown( theKeyMap, rightkey )&&!( IsKeyDown( theKeyMap, leftkey ))){
+				if(targetanimation!=moveanim)targetframe=0;
+				targetanimation=moveanim;
+				playerlowrotation-=90;
+				if(IsKeyDown( theKeyMap, forwardskey ))playerlowrotation+=45;
+				if(IsKeyDown( theKeyMap, backwardskey ))playerlowrotation-=235;
+			}
+			if ( IsKeyDown( theKeyMap, leftkey )&&!( IsKeyDown( theKeyMap, rightkey ))){
+				if(targetanimation!=moveanim)targetframe=0;
+				targetanimation=moveanim;
+				playerlowrotation+=90;
+				if(IsKeyDown( theKeyMap, forwardskey ))playerlowrotation-=45;
+				if(IsKeyDown( theKeyMap, backwardskey ))playerlowrotation+=235;
+			}
+			if ( IsKeyDown( theKeyMap, backwardskey )){
+				if(targetanimation!=moveanim)targetframe=0;
+				targetanimation=moveanim;
+				backwardsanim=1;
+			}
+		}
+		//air control
+		if(!onground){
+			float oldplayerrotation=playerrotation;
+			if ( IsKeyDown( theKeyMap, forwardskey )&&!( IsKeyDown( theKeyMap, backwardskey ))){
+				facing=0;
+				facing.z=1;		
+				facing=DoRotation(facing,0,playerrotation,0);
+				velocity=velocity+facing*multiplier*4;
+			}
+			if ( IsKeyDown( theKeyMap, rightkey )&&!( IsKeyDown( theKeyMap, leftkey ))){
+				playerrotation-=90;
+				if(IsKeyDown( theKeyMap, forwardskey ))playerrotation+=45;
+				if(IsKeyDown( theKeyMap, backwardskey ))playerrotation-=45;
+				facing=0;
+				facing.z=1;		
+				facing=DoRotation(facing,0,playerrotation,0);
+				velocity=velocity+facing*multiplier*4;
+			}
+			if ( IsKeyDown( theKeyMap, leftkey )&&!( IsKeyDown( theKeyMap, rightkey ))){
+				playerrotation+=90;
+				if(IsKeyDown( theKeyMap, forwardskey ))playerrotation-=45;
+				if(IsKeyDown( theKeyMap, backwardskey ))playerrotation+=45;
+				facing=0;
+				facing.z=1;		
+				facing=DoRotation(facing,0,playerrotation,0);
+				velocity=velocity+facing*multiplier*4;
+			}
+			if ( IsKeyDown( theKeyMap, backwardskey )&&!IsKeyDown( theKeyMap, forwardskey )&&!IsKeyDown( theKeyMap, leftkey )&&!IsKeyDown( theKeyMap, rightkey )){
+				playerrotation+=180;
+				facing=0;
+				facing.z=1;		
+				facing=DoRotation(facing,0,playerrotation,0);
+				velocity=velocity+facing*multiplier*4;
+			}
+			playerrotation=oldplayerrotation;
+		}
+		if(!IsKeyDown( theKeyMap, forwardskey )&&!IsKeyDown( theKeyMap, leftkey )&&!IsKeyDown( theKeyMap, rightkey )&&!IsKeyDown( theKeyMap, backwardskey )&&(targetanimation==joganim||targetanimation==walkanim)){
+			if(!(targetanimation==walkanim&&(targetframe==0||targetframe==2))){
+				targetanimation=idleanim;
+				targetframe=0;
+				target=0;
+			}
+		}
+	}
+	
+	
+	facing=0;
+	facing.z=1;
+	
+	facing=DoRotation(facing,0,playerlowrotation,0);
+	if(backwardsanim)facing*=-1;
+	
+	if(onground){
+		velocity=0;
+	}
+	if(((currentanimation==joganim||currentanimation==zombiejoganim||currentanimation==diveanim)&&onground)||(who==0&&visions==1&&((currentanimation==joganim||currentanimation==walkanim||currentanimation==diveanim)||(currentanimation==zombiejoganim||currentanimation==zombiewalkanim)))){
+		playercoords+=facing*multiplier*15*speed;
+		velocity.x=facing.x*15*speed;
+		velocity.z=facing.z*15*speed;
+	}
+	if((currentanimation==walkanim||currentanimation==zombiewalkanim)&&onground&&(who!=0||visions==0)){
+		playercoords+=facing*multiplier*4*speed;
+		velocity.x=facing.x*4*speed;
+		velocity.z=facing.z*4*speed;
+	}
+}
+
+void Person::FindRotationGun(XYZ start, XYZ target)
+{
+	XYZ temppoint1,temppoint2,tempforward;
+	float distance;
+	
+	temppoint1=start;
+	temppoint2=target;
+	distance=findDistance(temppoint1,temppoint2);
+	gunrotate2=asin((temppoint1.y-temppoint2.y)/distance)*rad2deg;
+	temppoint1.y=0;
+	temppoint2.y=0;
+	gunrotate1=acos((temppoint1.z-temppoint2.z)/findDistance(temppoint1,temppoint2))*rad2deg;
+	if(temppoint1.x>temppoint2.x)gunrotate1=360-gunrotate1;
+	tempforward=target-start;
+	tempforward=DoRotation(tempforward,-90,0,0);
+	tempforward=DoRotation(tempforward,0,gunrotate1-90,0);
+	tempforward=DoRotation(tempforward,0,0,gunrotate2-90);
+	tempforward.y=0;
+	Normalise(&tempforward);
+	gunrotate3=acos(0-tempforward.z)*rad2deg;
+	if(0>tempforward.x)gunrotate3=360-gunrotate3;
+}
+
+extern Model skeletonmodels[10];
+extern Costume costume[2];
+int Person::DrawSkeleton(int who){
+	GLfloat M[16];
+	//Guns
+	if(whichgun==sniperrifle){
+		FindRotationGun(skeleton.joints[skeleton.jointlabels[righthand]].position,skeleton.joints[skeleton.jointlabels[lefthand]].position);
+		glPushMatrix();
+				glTranslatef(	skeleton.joints[skeleton.jointlabels[righthand]].position.x,
+								skeleton.joints[skeleton.jointlabels[righthand]].position.y,
+								skeleton.joints[skeleton.jointlabels[righthand]].position.z);
+				glRotatef(-gunrotate1+90,0,1,0);
+				glRotatef(-gunrotate2+90,0,0,1);
+				glRotatef(-gunrotate3,0,1,0);
+				gunmodels[sniperriflemodel].draw();
+			glPopMatrix();
+	}
+	
+	if(whichgun==shotgun){
+		FindRotationGun(skeleton.joints[skeleton.jointlabels[righthand]].position,skeleton.joints[skeleton.jointlabels[lefthand]].position);
+		glPushMatrix();
+				glTranslatef(	skeleton.joints[skeleton.jointlabels[righthand]].position.x,
+								skeleton.joints[skeleton.jointlabels[righthand]].position.y,
+								skeleton.joints[skeleton.jointlabels[righthand]].position.z);
+				glRotatef(2,1,0,0);
+				glRotatef(-gunrotate1+90+1,0,1,0);
+				glRotatef(-gunrotate2+90,0,0,1);
+				glRotatef(-gunrotate3,0,1,0);
+				glTranslatef(0,-.4,0);
+				gunmodels[shotgunmodel].draw();
+			glPopMatrix();
+	}
+	
+	if(whichgun==assaultrifle){
+		FindRotationGun(skeleton.joints[skeleton.jointlabels[righthand]].position,skeleton.joints[skeleton.jointlabels[lefthand]].position);
+		glPushMatrix();
+				glTranslatef(	skeleton.joints[skeleton.jointlabels[righthand]].position.x,
+								skeleton.joints[skeleton.jointlabels[righthand]].position.y,
+								skeleton.joints[skeleton.jointlabels[righthand]].position.z);
+				glRotatef(-gunrotate1+90,0,1,0);
+				glRotatef(-gunrotate2+90,0,0,1);
+				glRotatef(-gunrotate3,0,1,0);
+				gunmodels[assaultriflemodel].draw();
+			glPopMatrix();
+	}
+	
+	if(whichgun==handgun1){
+		if(!thirdperson&&who==0)FindRotationGun(skeleton.joints[skeleton.jointlabels[righthand]].position,(skeleton.joints[skeleton.jointlabels[head]].position*.65+skeleton.joints[skeleton.jointlabels[neck]].position*.35));
+		if(thirdperson||who!=0)FindRotationGun(skeleton.joints[skeleton.jointlabels[righthand]].position,(skeleton.joints[skeleton.jointlabels[head]].position*.35+skeleton.joints[skeleton.jointlabels[neck]].position*.65));
+		glPushMatrix();
+				glTranslatef(	skeleton.joints[skeleton.jointlabels[righthand]].position.x,
+								skeleton.joints[skeleton.jointlabels[righthand]].position.y,
+								skeleton.joints[skeleton.jointlabels[righthand]].position.z);
+				glRotatef(-gunrotate1+90-1.5,0,1,0);
+				glRotatef(-gunrotate2+90,0,0,1);
+				glRotatef(-gunrotate3,0,1,0);
+				glTranslatef(0,0,.15);
+				gunmodels[handgunbasemodel].draw();
+				glTranslatef(0,-recoil*.3,0);
+				gunmodels[handgunslidemodel].draw();
+			glPopMatrix();
+	}
+	
+	if(whichgun==handgun2){
+		if(!thirdperson&&who==0)FindRotationGun(skeleton.joints[skeleton.jointlabels[righthand]].position,(skeleton.joints[skeleton.jointlabels[head]].position*.65+skeleton.joints[skeleton.jointlabels[neck]].position*.35));
+		if(thirdperson||who!=0)FindRotationGun(skeleton.joints[skeleton.jointlabels[righthand]].position,(skeleton.joints[skeleton.jointlabels[head]].position*.35+skeleton.joints[skeleton.jointlabels[neck]].position*.65));
+		glPushMatrix();
+				glTranslatef(	skeleton.joints[skeleton.jointlabels[righthand]].position.x,
+								skeleton.joints[skeleton.jointlabels[righthand]].position.y,
+								skeleton.joints[skeleton.jointlabels[righthand]].position.z);
+				glRotatef(-gunrotate1+90-1.5,0,1,0);
+				glRotatef(-gunrotate2+90,0,0,1);
+				glRotatef(-gunrotate3,0,1,0);
+				glTranslatef(0,0,.15);
+				gunmodels[handgun2basemodel].draw();
+				glTranslatef(0,-recoil*.3,0);
+				gunmodels[handgun2slidemodel].draw();
+			glPopMatrix();
+	}
+	
+	if(whichgun==grenade){
+		glPushMatrix();
+				glTranslatef(	skeleton.joints[skeleton.jointlabels[righthand]].position.x,
+								skeleton.joints[skeleton.jointlabels[righthand]].position.y,
+								skeleton.joints[skeleton.jointlabels[righthand]].position.z);
+				glRotatef(-90,1,0,0);
+				glTranslatef(0,0,.05);
+				if(reloading<=0){
+					gunmodels[grenadebasemodel].draw();
+					if(grenphase==0)gunmodels[grenadepinmodel].draw();
+					glTranslatef(0,0,.005);
+					gunmodels[grenadespoonmodel].draw();
+				}
+			glPopMatrix();
+	}
+	
+	if(whichgun==grenade){
+		glPushMatrix();
+				glTranslatef(	skeleton.joints[skeleton.jointlabels[lefthand]].position.x,
+								skeleton.joints[skeleton.jointlabels[lefthand]].position.y,
+								skeleton.joints[skeleton.jointlabels[lefthand]].position.z);
+				glRotatef(-90,1,0,0);
+				glTranslatef(0,0,-.15);
+				if(reloading<=0){
+					if(grenphase==1)gunmodels[grenadepinmodel].draw();
+				}
+			glPopMatrix();
+	}
+	if(!litup){
+		glDisable(GL_LIGHT1);
+	}
+	if(litup){
+		GLfloat LightAmbient[]=	{ 0,0,0, 1.0f};
+		GLfloat LightDiffuse[]=	{ 1,1,1, 1.0f };
+		XYZ lightpoint;
+		lightpoint=skeleton.joints[skeleton.jointlabels[lefthand]].position;
+		GLfloat LightPosition[]=	{lightpoint.x,lightpoint.y,lightpoint.z,0};
+		glLightfv(GL_LIGHT1, GL_POSITION, LightPosition);
+		glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);		
+		glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);	
+		glEnable(GL_LIGHT1);
+		
+		litup=0;
+	}
+	
+	//Find forward vectors
+	if(who==0||skeleton.free!=0||skeleton.offset!=0||whichgun!=nogun||currentanimation==lyinganim||((currentanimation==getupfrontanim||currentanimation==getupbackanim)&&targetanimation==idleanim)){
+	if(!(skeleton.free==1&&longdead<=0)){
+	if(skeleton.offset&&skeleton.free<1){
+		XYZ normal;
+		skeleton.offset=0;
+		for(int i=0;i<skeleton.num_joints;i++){
+			skeleton.joints[i].oldposition=skeleton.joints[i].position;
+			skeleton.joints[i].position+=skeleton.joints[i].offset;
+			if(findLengthfast(skeleton.joints[i].offset)<multiplier*multiplier*25)skeleton.joints[i].offset=0;
+			else{
+				normal=skeleton.joints[i].offset;
+				Normalise(&normal);
+				skeleton.offset=1;
+				skeleton.joints[i].offset-=normal*multiplier*5;
+			}
+		}
+		skeleton.DoConstraints();
+	}
+	CrossProduct(skeleton.joints[skeleton.forwardjoints[1]].position-skeleton.joints[skeleton.forwardjoints[0]].position,skeleton.joints[skeleton.forwardjoints[2]].position-skeleton.joints[skeleton.forwardjoints[0]].position,&skeleton.forward);
+	Normalise(&skeleton.forward);
+	
+	CrossProduct(skeleton.joints[skeleton.lowforwardjoints[1]].position-skeleton.joints[skeleton.lowforwardjoints[0]].position,skeleton.joints[skeleton.lowforwardjoints[2]].position-skeleton.joints[skeleton.lowforwardjoints[0]].position,&skeleton.lowforward);
+	Normalise(&skeleton.lowforward);
+	
+	//Special forwards
+	skeleton.specialforward[0]=skeleton.forward;
+	
+	skeleton.specialforward[1]=skeleton.joints[skeleton.jointlabels[rightshoulder]].position+skeleton.joints[skeleton.jointlabels[rightwrist]].position;
+	skeleton.specialforward[1]=skeleton.joints[skeleton.jointlabels[rightelbow]].position-skeleton.specialforward[1]/2;
+	skeleton.specialforward[1]+=skeleton.forward*.2;
+	Normalise(&skeleton.specialforward[1]);
+	skeleton.specialforward[2]=skeleton.joints[skeleton.jointlabels[leftshoulder]].position+skeleton.joints[skeleton.jointlabels[leftwrist]].position;
+	skeleton.specialforward[2]=skeleton.joints[skeleton.jointlabels[leftelbow]].position-skeleton.specialforward[2]/2;
+	skeleton.specialforward[2]+=skeleton.forward*.2;
+	Normalise(&skeleton.specialforward[2]);
+
+	if(who==0&&aimamount>0&&health==100&&whichgun!=nogun){
+		//Facing
+		XYZ facing;
+		XYZ facingdown;
+		//Facing
+		facing=0;
+		facing.z=1;
+		
+		facing=DoRotation(facing,camera.rotation2,0,0);
+		facingdown=DoRotation(facing,90,0,0);
+		skeleton.specialforward[1]=skeleton.specialforward[1]*(1-aimamount)+facingdown*aimamount;
+		skeleton.specialforward[2]=skeleton.specialforward[2]*(1-aimamount)+facingdown*aimamount;
+	}
+	
+	skeleton.specialforward[3]=skeleton.joints[skeleton.jointlabels[righthip]].position+skeleton.joints[skeleton.jointlabels[rightankle]].position;
+	skeleton.specialforward[3]=skeleton.specialforward[3]/2-skeleton.joints[skeleton.jointlabels[rightknee]].position;
+	skeleton.specialforward[3]+=skeleton.lowforward*.2;
+	Normalise(&skeleton.specialforward[3]);
+	skeleton.specialforward[4]=skeleton.joints[skeleton.jointlabels[lefthip]].position+skeleton.joints[skeleton.jointlabels[leftankle]].position;
+	skeleton.specialforward[4]=skeleton.specialforward[4]/2-skeleton.joints[skeleton.jointlabels[leftknee]].position;
+	skeleton.specialforward[4]+=skeleton.lowforward*.2;
+	Normalise(&skeleton.specialforward[4]);
+
+	//Find joint rotations
+	for(int i=0;i<skeleton.num_joints;i++){
+		if(skeleton.joints[i].hasparent&&skeleton.joints[i].visible)
+		{
+			skeleton.FindRotationJoint(i);
+		}
+	}
+	for(int i=0;i<skeleton.num_muscles;i++){
+		if(skeleton.muscles[i].visible)
+		{
+			skeleton.FindRotationMuscle(i);
+		}
+	}}}
+	for(int i=0;i<skeleton.num_joints;i++){
+		if(skeleton.joints[i].hasparent&&skeleton.joints[i].visible)
+		{
+			glPushMatrix();
+				glTranslatef(	(skeleton.joints[i].position.x+skeleton.joints[i].parent->position.x)/2,
+								(skeleton.joints[i].position.y+skeleton.joints[i].parent->position.y)/2,
+								(skeleton.joints[i].position.z+skeleton.joints[i].parent->position.z)/2);
+				glRotatef(-skeleton.joints[i].rotate1+90,0,1,0);
+				glRotatef(-skeleton.joints[i].rotate2+90,0,0,1);
+				glRotatef(-skeleton.joints[i].rotate3,0,1,0);
+				if(skeleton.joints[i].modelnum==0&&(who!=0||thirdperson))skeletonmodels[skeleton.joints[i].modelnum].draw(costume[whichcostume].headcolor[0],costume[whichcostume].headcolor[1],costume[whichcostume].headcolor[2]);
+				if(skeleton.joints[i].modelnum==0&&(who==0&&thirdperson))skeletonmodels[9].draw();
+				if(skeleton.joints[i].modelnum==1&&(who!=0||thirdperson))skeletonmodels[skeleton.joints[i].modelnum].draw(costume[whichcostume].chestcolor[0],costume[whichcostume].chestcolor[1],costume[whichcostume].chestcolor[2]);
+				if(skeleton.joints[i].modelnum==2)skeletonmodels[skeleton.joints[i].modelnum].draw(costume[whichcostume].abdomencolor[0],costume[whichcostume].abdomencolor[1],costume[whichcostume].abdomencolor[2]);
+				if(skeleton.joints[i].modelnum==3)skeletonmodels[skeleton.joints[i].modelnum].draw(costume[whichcostume].upperarmcolor[0],costume[whichcostume].upperarmcolor[1],costume[whichcostume].upperarmcolor[2]);
+				if(skeleton.joints[i].modelnum==4)skeletonmodels[skeleton.joints[i].modelnum].draw(costume[whichcostume].lowerarmcolor[0],costume[whichcostume].lowerarmcolor[1],costume[whichcostume].lowerarmcolor[2]);
+				if(skeleton.joints[i].modelnum==5)skeletonmodels[skeleton.joints[i].modelnum].draw(costume[whichcostume].handcolor[0],costume[whichcostume].handcolor[1],costume[whichcostume].handcolor[2]);
+				if(skeleton.joints[i].modelnum==6)skeletonmodels[skeleton.joints[i].modelnum].draw(costume[whichcostume].upperlegcolor[0],costume[whichcostume].upperlegcolor[1],costume[whichcostume].upperlegcolor[2]);
+				if(skeleton.joints[i].modelnum==7)skeletonmodels[skeleton.joints[i].modelnum].draw(costume[whichcostume].lowerlegcolor[0],costume[whichcostume].lowerlegcolor[1],costume[whichcostume].lowerlegcolor[2]);
+				if(skeleton.joints[i].modelnum==8)skeletonmodels[skeleton.joints[i].modelnum].draw(costume[whichcostume].footcolor[0],costume[whichcostume].footcolor[1],costume[whichcostume].footcolor[2]);
+			glPopMatrix();
+		}
+	}
+	
+	for(int i=0;i<skeleton.num_muscles;i++){
+		if(skeleton.muscles[i].visible)
+		{
+			glPushMatrix();
+				glTranslatef(	(skeleton.muscles[i].parent1->position.x+skeleton.muscles[i].parent2->position.x)/2,
+								(skeleton.muscles[i].parent1->position.y+skeleton.muscles[i].parent2->position.y)/2,
+								(skeleton.muscles[i].parent1->position.z+skeleton.muscles[i].parent2->position.z)/2);
+				glRotatef(-skeleton.muscles[i].rotate1+90,0,1,0);
+				glRotatef(-skeleton.muscles[i].rotate2+90,0,0,1);
+				glRotatef(-skeleton.muscles[i].rotate3,0,1,0);
+				if(skeleton.muscles[i].parent1->modelnum==0&&(who!=0||thirdperson))skeletonmodels[skeleton.muscles[i].parent1->modelnum].draw(costume[whichcostume].headcolor[0],costume[whichcostume].headcolor[1],costume[whichcostume].headcolor[2]);
+				if(skeleton.muscles[i].parent1->modelnum==0&&(who==0&&thirdperson))skeletonmodels[9].draw();
+				if(skeleton.muscles[i].parent1->modelnum==1&&(who!=0||thirdperson))skeletonmodels[skeleton.muscles[i].parent1->modelnum].draw(costume[whichcostume].chestcolor[0],costume[whichcostume].chestcolor[1],costume[whichcostume].chestcolor[2]);
+				if(skeleton.muscles[i].parent1->modelnum==2)skeletonmodels[skeleton.muscles[i].parent1->modelnum].draw(costume[whichcostume].abdomencolor[0],costume[whichcostume].abdomencolor[1],costume[whichcostume].abdomencolor[2]);
+				if(skeleton.muscles[i].parent1->modelnum==3)skeletonmodels[skeleton.muscles[i].parent1->modelnum].draw(costume[whichcostume].upperarmcolor[0],costume[whichcostume].upperarmcolor[1],costume[whichcostume].upperarmcolor[2]);
+				if(skeleton.muscles[i].parent1->modelnum==4)skeletonmodels[skeleton.muscles[i].parent1->modelnum].draw(costume[whichcostume].lowerarmcolor[0],costume[whichcostume].lowerarmcolor[1],costume[whichcostume].lowerarmcolor[2]);
+				if(skeleton.muscles[i].parent1->modelnum==5)skeletonmodels[skeleton.muscles[i].parent1->modelnum].draw(costume[whichcostume].handcolor[0],costume[whichcostume].handcolor[1],costume[whichcostume].handcolor[2]);
+				if(skeleton.muscles[i].parent1->modelnum==6)skeletonmodels[skeleton.muscles[i].parent1->modelnum].draw(costume[whichcostume].upperlegcolor[0],costume[whichcostume].upperlegcolor[1],costume[whichcostume].upperlegcolor[2]);
+				if(skeleton.muscles[i].parent1->modelnum==7)skeletonmodels[skeleton.muscles[i].parent1->modelnum].draw(costume[whichcostume].lowerlegcolor[0],costume[whichcostume].lowerlegcolor[1],costume[whichcostume].lowerlegcolor[2]);
+				if(skeleton.muscles[i].parent1->modelnum==8)skeletonmodels[skeleton.muscles[i].parent1->modelnum].draw(costume[whichcostume].footcolor[0],costume[whichcostume].footcolor[1],costume[whichcostume].footcolor[2]);
+				
+		glPopMatrix();
+		}
+	}
+	if(whichgun==knife){
+		glPushMatrix();
+				glTranslatef(	skeleton.joints[skeleton.jointlabels[righthand]].position.x,
+								skeleton.joints[skeleton.jointlabels[righthand]].position.y,
+								skeleton.joints[skeleton.jointlabels[righthand]].position.z);
+				glRotatef(-skeleton.joints[skeleton.jointlabels[righthand]].rotate1+90-1.5,0,1,0);
+				glRotatef(-skeleton.joints[skeleton.jointlabels[righthand]].rotate2+90,0,0,1);
+				glRotatef(-skeleton.joints[skeleton.jointlabels[righthand]].rotate3,0,1,0);
+				glTranslatef(0,-.2,0);
+				gunmodels[knifemodel].draw();
+			glPopMatrix();
+	}
+	if(skeleton.offset&&skeleton.free<1){
+		for(int i=0;i<skeleton.num_joints;i++){
+			skeleton.joints[i].position=skeleton.joints[i].oldposition;
+		}
+	}
+	
+	glDisable(GL_LIGHT1);
+	
+	return 0;
+}
+
diff --git a/src/Person.h b/src/Person.h
new file mode 100644
index 0000000..e7542b0
--- /dev/null
+++ b/src/Person.h
@@ -0,0 +1,157 @@
+#ifndef _PERSON_H_
+#define _PERSON_H_
+
+/**> HEADER FILES <**/
+#include <cmath>
+#ifdef OS9 
+#include <gl.h>
+#else
+#include <GL/gl.h>
+#endif
+#ifdef OS9 
+#include "alut.h"
+#else
+#include <AL/al.h>
+#include <AL/alut.h>
+#endif
+#include "Quaternions.h"
+#include "Constants.h"
+#include "Skeleton.h"
+#include "Models.h"
+#include "Camera.h"
+#include "Sprites.h"
+
+#define playertype 0
+#define civiliantype 1
+#define eviltype 2
+#define viptype 3
+#define evilsnipertype 4
+#define evilassaultrifletype 5
+#define zombietype 6
+
+class HitStruct
+{
+	public:
+		Joint *joint1;
+		Joint *joint2;
+		XYZ hitlocation;
+		bool collision;
+};
+
+class Person
+{
+	public:
+		int eaten;
+		int currentframe;
+		int targetframe;
+		int currentanimation;
+		int targetanimation;
+		float target;
+		float playerhealth;
+		int modelnum;
+		XYZ oldplayercoords;
+		XYZ playercoords;
+		XYZ playervelocity;
+		float playerrotation;
+		float playerrotation2;
+		float playerlowrotation;
+		float pathcheckdelay;
+		bool onground;
+		bool backwardsanim;
+		XYZ facing;
+		XYZ velocity;
+		float shotdelay;
+		bool litup;
+		
+		bool existing;
+		
+		int type;
+		
+		int whichcostume;
+		
+		Skeleton skeleton;
+		Animation tempanimation;
+		
+		bool freshshootkey;
+		bool freshkickkey;
+		int bufferattack;
+		int jump_key;
+		int left_key;
+		int right_key;
+		int duck_key;
+		int shoot_key;
+		int kick_key;
+		int block_key;
+		
+		float speed;
+		bool aiming;
+		int grenphase;
+		float grenamount;
+		float aimamount;
+		float speedmult;
+		float pathsize;
+		
+		int pathnum;
+		int oldpathnum;
+		int oldoldpathnum;
+		int oldoldoldpathnum;
+		XYZ pathtarget;
+		int whichblockx;
+		int whichblocky;
+		
+		bool dead;
+		
+		XYZ averageloc;
+		XYZ oldaverageloc;
+		
+		float lastdistancevictim;
+		
+		bool firstlongdead;
+		float longdead;
+		
+		Joint *bjoint1,*bjoint2;
+		float bleeding;
+		float bleeddelay;
+		
+		float attacktarget;
+		int attackframe;
+		int killtarget;
+		bool killtargetvisible;
+		
+		float gunrotate1, gunrotate2, gunrotate3;
+		float recoil;
+		int whichgun;
+		float oldhealth;
+		float health;
+		float maxhealth;
+		float reloading;
+		int ammo;
+		int reloads[10];
+		bool running;
+		bool onpath;
+		
+		void FindRotationGun(XYZ start, XYZ target);
+		
+		int DrawSkeleton(int who);
+		void DoStuff(int who);
+		void DoAnimations(int who);	
+		void DoAnimationslite(int who);	
+		HitStruct BulletCollideWithPlayer(int who, XYZ start, XYZ end);		
+};
+
+class Costume
+{
+	public:
+		float headcolor[3];
+		float handcolor[3];
+		float footcolor[3];
+		float upperarmcolor[3];
+		float lowerarmcolor[3];
+		float upperlegcolor[3];
+		float lowerlegcolor[3];
+		float abdomencolor[3];
+		float chestcolor[3];
+};
+
+
+#endif
diff --git a/src/PhysicsMath.h b/src/PhysicsMath.h
new file mode 100644
index 0000000..c975941
--- /dev/null
+++ b/src/PhysicsMath.h
@@ -0,0 +1,1432 @@
+#ifndef _PHYSICSMATH_H_
+
+#define _PHYSICSMATH_H_
+
+
+
+#include <cmath>
+
+#include "Quaternions.h"
+
+
+
+//------------------------------------------------------------------------//
+
+// Misc. Constants
+
+//------------------------------------------------------------------------//
+
+
+
+float	const	pi	= 3.14159265f;
+
+float	const	g	= -32.174f;		// acceleration due to gravity, ft/s^2
+
+float	const	rho = 0.0023769f;	// desity of air at sea level, slugs/ft^3
+
+float	const	tol = 0.0000000001f;		// float type tolerance 
+
+
+
+
+
+//------------------------------------------------------------------------//
+
+// Misc. Functions
+
+//------------------------------------------------------------------------//
+
+inline	float	DegreesToRadians(float deg);
+
+inline	float	RadiansToDegrees(float rad);
+
+
+
+inline	float	DegreesToRadians(float deg)
+
+{
+
+	return deg * pi / 180.0f;
+
+}
+
+
+
+inline	float	RadiansToDegrees(float rad)
+
+{	
+
+	return rad * 180.0f / pi;
+
+}
+
+
+
+//------------------------------------------------------------------------//
+
+// Vector Class and vector functions
+
+//------------------------------------------------------------------------//
+
+class Vector {
+
+public:
+
+	float x;
+
+	float y;
+
+	float z;
+
+
+
+	Vector(void);
+
+	Vector(float xi, float yi, float zi);
+
+
+
+	float Magnitude(void);
+
+	void  Normalize(void);
+
+	void  Reverse(void);
+
+
+
+	Vector& operator+=(Vector u);	// vector addition
+
+	Vector& operator-=(Vector u);	// vector subtraction
+
+	Vector& operator*=(float s);	// scalar multiply
+
+	Vector& operator/=(float s);	// scalar divide
+
+
+
+	Vector operator-(void);
+
+
+
+};
+
+
+
+inline	Vector operator+(Vector u, Vector v);
+
+inline	Vector operator-(Vector u, Vector v);
+
+inline	Vector operator^(Vector u, Vector v);
+
+inline	float operator*(Vector u, Vector v);
+
+inline	Vector operator*(float s, Vector u);
+
+inline	Vector operator*(Vector u, float s);
+
+inline	Vector operator/(Vector u, float s);
+
+inline	float TripleScalarProduct(Vector u, Vector v, Vector w);
+
+
+
+inline Vector::Vector(void)
+
+{
+
+	x = 0;
+
+	y = 0;
+
+	z = 0;
+
+}
+
+
+
+inline Vector::Vector(float xi, float yi, float zi)
+
+{
+
+	x = xi;
+
+	y = yi;
+
+	z = zi;
+
+}
+
+
+
+inline	float Vector::Magnitude(void)
+
+{
+
+	return (float) fast_sqrt(x*x + y*y + z*z);
+
+}
+
+
+
+inline	void  Vector::Normalize(void)
+
+{
+
+	float m = (float) fast_sqrt(x*x + y*y + z*z);
+
+	if(m <= tol) m = 1;
+
+	x /= m;
+
+	y /= m;
+
+	z /= m;	
+
+
+
+	if (fabs(x) < tol) x = 0.0f;
+
+	if (fabs(y) < tol) y = 0.0f;
+
+	if (fabs(z) < tol) z = 0.0f;
+
+}
+
+
+
+inline	void  Vector::Reverse(void)
+
+{
+
+	x = -x;
+
+	y = -y;
+
+	z = -z;
+
+}
+
+
+
+inline Vector& Vector::operator+=(Vector u)
+
+{
+
+	x += u.x;
+
+	y += u.y;
+
+	z += u.z;
+
+	return *this;
+
+}
+
+
+
+inline	Vector& Vector::operator-=(Vector u)
+
+{
+
+	x -= u.x;
+
+	y -= u.y;
+
+	z -= u.z;
+
+	return *this;
+
+}
+
+
+
+inline	Vector& Vector::operator*=(float s)
+
+{
+
+	x *= s;
+
+	y *= s;
+
+	z *= s;
+
+	return *this;
+
+}
+
+
+
+inline	Vector& Vector::operator/=(float s)
+
+{
+
+	x /= s;
+
+	y /= s;
+
+	z /= s;
+
+	return *this;
+
+}
+
+
+
+inline	Vector Vector::operator-(void)
+
+{
+
+	return Vector(-x, -y, -z);
+
+}
+
+
+
+
+
+inline	Vector operator+(Vector u, Vector v)
+
+{
+
+	return Vector(u.x + v.x, u.y + v.y, u.z + v.z);
+
+}
+
+
+
+inline	Vector operator-(Vector u, Vector v)
+
+{
+
+	return Vector(u.x - v.x, u.y - v.y, u.z - v.z);
+
+}
+
+
+
+// Vector cross product (u cross v)
+
+inline	Vector operator^(Vector u, Vector v)
+
+{
+
+	return Vector(	u.y*v.z - u.z*v.y,
+
+					-u.x*v.z + u.z*v.x,
+
+					u.x*v.y - u.y*v.x );
+
+}
+
+
+
+// Vector dot product
+
+inline	float operator*(Vector u, Vector v)
+
+{
+
+	return (u.x*v.x + u.y*v.y + u.z*v.z);
+
+}
+
+
+
+inline	Vector operator*(float s, Vector u)
+
+{
+
+	return Vector(u.x*s, u.y*s, u.z*s);
+
+}
+
+
+
+inline	Vector operator*(Vector u, float s)
+
+{
+
+	return Vector(u.x*s, u.y*s, u.z*s);
+
+}
+
+
+
+inline	Vector operator/(Vector u, float s)
+
+{
+
+	return Vector(u.x/s, u.y/s, u.z/s);
+
+}
+
+
+
+// triple scalar product (u dot (v cross w))
+
+inline	float TripleScalarProduct(Vector u, Vector v, Vector w)
+
+{
+
+	return float(	(u.x * (v.y*w.z - v.z*w.y)) +
+
+					(u.y * (-v.x*w.z + v.z*w.x)) +
+
+					(u.z * (v.x*w.y - v.y*w.x)) );
+
+	//return u*(v^w);
+
+
+
+}
+
+
+
+
+
+
+
+//------------------------------------------------------------------------//
+
+// Matrix Class and matrix functions
+
+//------------------------------------------------------------------------//
+
+
+
+class Matrix3x3 {
+
+public:
+
+	// elements eij: i -> row, j -> column
+
+	float	e11, e12, e13, e21, e22, e23, e31, e32, e33;	
+
+
+
+	Matrix3x3(void);
+
+	Matrix3x3(	float r1c1, float r1c2, float r1c3, 
+
+				float r2c1, float r2c2, float r2c3, 
+
+				float r3c1, float r3c2, float r3c3 );
+
+
+
+	float	det(void);
+
+	Matrix3x3	Transpose(void);
+
+	Matrix3x3	Inverse(void);
+
+
+
+	Matrix3x3& operator+=(Matrix3x3 m);
+
+	Matrix3x3& operator-=(Matrix3x3 m);
+
+	Matrix3x3& operator*=(float s);
+
+	Matrix3x3& operator/=(float s);
+
+};
+
+
+
+inline	Matrix3x3 operator+(Matrix3x3 m1, Matrix3x3 m2);
+
+inline	Matrix3x3 operator-(Matrix3x3 m1, Matrix3x3 m2);
+
+inline	Matrix3x3 operator/(Matrix3x3 m, float s);
+
+inline	Matrix3x3 operator*(Matrix3x3 m1, Matrix3x3 m2);
+
+inline	Matrix3x3 operator*(Matrix3x3 m, float s);
+
+inline	Matrix3x3 operator*(float s, Matrix3x3 m);
+
+inline	Vector operator*(Matrix3x3 m, Vector u);
+
+inline	Vector operator*(Vector u, Matrix3x3 m);
+
+
+
+
+
+
+
+
+
+
+
+inline	Matrix3x3::Matrix3x3(void)
+
+{
+
+	e11 = 0;
+
+	e12 = 0;
+
+	e13 = 0;
+
+	e21 = 0;
+
+	e22 = 0;
+
+	e23 = 0;
+
+	e31 = 0;
+
+	e32 = 0;
+
+	e33 = 0;
+
+}
+
+
+
+inline	Matrix3x3::Matrix3x3(	float r1c1, float r1c2, float r1c3, 
+
+								float r2c1, float r2c2, float r2c3, 
+
+								float r3c1, float r3c2, float r3c3 )
+
+{
+
+	e11 = r1c1;
+
+	e12 = r1c2;
+
+	e13 = r1c3;
+
+	e21 = r2c1;
+
+	e22 = r2c2;
+
+	e23 = r2c3;
+
+	e31 = r3c1;
+
+	e32 = r3c2;
+
+	e33 = r3c3;
+
+}
+
+
+
+inline	float	Matrix3x3::det(void)
+
+{
+
+	return	e11*e22*e33 - 
+
+			e11*e32*e23 + 
+
+			e21*e32*e13 - 
+
+			e21*e12*e33 + 
+
+			e31*e12*e23 - 
+
+			e31*e22*e13;	
+
+}
+
+
+
+inline	Matrix3x3	Matrix3x3::Transpose(void)
+
+{
+
+	return Matrix3x3(e11,e21,e31,e12,e22,e32,e13,e23,e33);
+
+}
+
+
+
+inline	Matrix3x3	Matrix3x3::Inverse(void)
+
+{
+
+	float	d = e11*e22*e33 - 
+
+				e11*e32*e23 + 
+
+				e21*e32*e13 - 
+
+				e21*e12*e33 + 
+
+				e31*e12*e23 - 
+
+				e31*e22*e13;
+
+
+
+	if (d == 0) d = 1;
+
+
+
+	return	Matrix3x3(	(e22*e33-e23*e32)/d,
+
+						-(e12*e33-e13*e32)/d,
+
+						(e12*e23-e13*e22)/d,
+
+						-(e21*e33-e23*e31)/d,
+
+						(e11*e33-e13*e31)/d,
+
+						-(e11*e23-e13*e21)/d,
+
+						(e21*e32-e22*e31)/d,
+
+						-(e11*e32-e12*e31)/d,
+
+						(e11*e22-e12*e21)/d );	
+
+}
+
+
+
+inline	Matrix3x3& Matrix3x3::operator+=(Matrix3x3 m)
+
+{
+
+	e11 += m.e11;
+
+	e12 += m.e12;
+
+	e13 += m.e13;
+
+	e21 += m.e21;
+
+	e22 += m.e22;
+
+	e23 += m.e23;
+
+	e31 += m.e31;
+
+	e32 += m.e32;
+
+	e33 += m.e33;
+
+	return *this;
+
+}
+
+
+
+inline	Matrix3x3& Matrix3x3::operator-=(Matrix3x3 m)
+
+{
+
+	e11 -= m.e11;
+
+	e12 -= m.e12;
+
+	e13 -= m.e13;
+
+	e21 -= m.e21;
+
+	e22 -= m.e22;
+
+	e23 -= m.e23;
+
+	e31 -= m.e31;
+
+	e32 -= m.e32;
+
+	e33 -= m.e33;
+
+	return *this;
+
+}
+
+
+
+inline	Matrix3x3& Matrix3x3::operator*=(float s)
+
+{
+
+	e11 *= s;
+
+	e12 *= s;
+
+	e13 *= s;
+
+	e21 *= s;
+
+	e22 *= s;
+
+	e23 *= s;
+
+	e31 *= s;
+
+	e32 *= s;
+
+	e33 *= s;
+
+	return *this;
+
+}
+
+
+
+inline	Matrix3x3& Matrix3x3::operator/=(float s)
+
+{
+
+	e11 /= s;
+
+	e12 /= s;
+
+	e13 /= s;
+
+	e21 /= s;
+
+	e22 /= s;
+
+	e23 /= s;
+
+	e31 /= s;
+
+	e32 /= s;
+
+	e33 /= s;
+
+	return *this;
+
+}
+
+
+
+inline	Matrix3x3 operator+(Matrix3x3 m1, Matrix3x3 m2)
+
+{
+
+	return	Matrix3x3(	m1.e11+m2.e11,
+
+						m1.e12+m2.e12,
+
+						m1.e13+m2.e13,
+
+						m1.e21+m2.e21,
+
+						m1.e22+m2.e22,
+
+						m1.e23+m2.e23,
+
+						m1.e31+m2.e31,
+
+						m1.e32+m2.e32,
+
+						m1.e33+m2.e33);
+
+}
+
+
+
+inline	Matrix3x3 operator-(Matrix3x3 m1, Matrix3x3 m2)
+
+{
+
+	return	Matrix3x3(	m1.e11-m2.e11,
+
+						m1.e12-m2.e12,
+
+						m1.e13-m2.e13,
+
+						m1.e21-m2.e21,
+
+						m1.e22-m2.e22,
+
+						m1.e23-m2.e23,
+
+						m1.e31-m2.e31,
+
+						m1.e32-m2.e32,
+
+						m1.e33-m2.e33);
+
+}
+
+
+
+inline	Matrix3x3 operator/(Matrix3x3 m, float s)
+
+{	
+
+	return	Matrix3x3(	m.e11/s,
+
+						m.e12/s,
+
+						m.e13/s,
+
+						m.e21/s,
+
+						m.e22/s,
+
+						m.e23/s,
+
+						m.e31/s,
+
+						m.e32/s,
+
+						m.e33/s);
+
+}
+
+
+
+inline	Matrix3x3 operator*(Matrix3x3 m1, Matrix3x3 m2)
+
+{
+
+	return Matrix3x3(	m1.e11*m2.e11 + m1.e12*m2.e21 + m1.e13*m2.e31,
+
+						m1.e11*m2.e12 + m1.e12*m2.e22 + m1.e13*m2.e32,
+
+						m1.e11*m2.e13 + m1.e12*m2.e23 + m1.e13*m2.e33,
+
+						m1.e21*m2.e11 + m1.e22*m2.e21 + m1.e23*m2.e31,
+
+						m1.e21*m2.e12 + m1.e22*m2.e22 + m1.e23*m2.e32,
+
+						m1.e21*m2.e13 + m1.e22*m2.e23 + m1.e23*m2.e33,
+
+						m1.e31*m2.e11 + m1.e32*m2.e21 + m1.e33*m2.e31,
+
+						m1.e31*m2.e12 + m1.e32*m2.e22 + m1.e33*m2.e32,
+
+						m1.e31*m2.e13 + m1.e32*m2.e23 + m1.e33*m2.e33 );
+
+}
+
+
+
+inline	Matrix3x3 operator*(Matrix3x3 m, float s)
+
+{
+
+	return	Matrix3x3(	m.e11*s,
+
+						m.e12*s,
+
+						m.e13*s,
+
+						m.e21*s,
+
+						m.e22*s,
+
+						m.e23*s,
+
+						m.e31*s,
+
+						m.e32*s,
+
+						m.e33*s);
+
+}
+
+
+
+inline	Matrix3x3 operator*(float s, Matrix3x3 m)
+
+{
+
+	return	Matrix3x3(	m.e11*s,
+
+						m.e12*s,
+
+						m.e13*s,
+
+						m.e21*s,
+
+						m.e22*s,
+
+						m.e23*s,
+
+						m.e31*s,
+
+						m.e32*s,
+
+						m.e33*s);
+
+}
+
+
+
+inline	Vector operator*(Matrix3x3 m, Vector u)
+
+{
+
+	return Vector(	m.e11*u.x + m.e12*u.y + m.e13*u.z,
+
+					m.e21*u.x + m.e22*u.y + m.e23*u.z,
+
+					m.e31*u.x + m.e32*u.y + m.e33*u.z);					
+
+}
+
+
+
+inline	Vector operator*(Vector u, Matrix3x3 m)
+
+{
+
+	return Vector(	u.x*m.e11 + u.y*m.e21 + u.z*m.e31,
+
+					u.x*m.e12 + u.y*m.e22 + u.z*m.e32,
+
+					u.x*m.e13 + u.y*m.e23 + u.z*m.e33);
+
+}
+
+
+
+//------------------------------------------------------------------------//
+
+// Quaternion Class and Quaternion functions
+
+//------------------------------------------------------------------------//
+
+
+
+class Quaternion {
+
+public:
+
+	float	n;	// number (scalar) part
+
+	Vector	v;	// vector part: v.x, v.y, v.z
+
+
+
+	Quaternion(void);
+
+	Quaternion(float e0, float e1, float e2, float e3);
+
+
+
+	float	Magnitude(void);
+
+	Vector	GetVector(void);
+
+	float	GetScalar(void);
+
+	Quaternion	operator+=(Quaternion q);
+
+	Quaternion	operator-=(Quaternion q);
+
+	Quaternion operator*=(float s);
+
+	Quaternion operator/=(float s);
+
+	Quaternion	operator~(void) const { return Quaternion(n, -v.x, -v.y, -v.z);}
+
+};
+
+
+
+inline	Quaternion operator+(Quaternion q1, Quaternion q2);
+
+inline	Quaternion operator-(Quaternion q1, Quaternion q2);
+
+inline	Quaternion operator*(Quaternion q1, Quaternion q2);
+
+inline	Quaternion operator*(Quaternion q, float s);
+
+inline	Quaternion operator*(float s, Quaternion q);
+
+inline	Quaternion operator*(Quaternion q, Vector v);
+
+inline	Quaternion operator*(Vector v, Quaternion q);
+
+inline	Quaternion operator/(Quaternion q, float s);
+
+inline	float QGetAngle(Quaternion q);
+
+inline	Vector QGetAxis(Quaternion q);
+
+inline	Quaternion QRotate(Quaternion q1, Quaternion q2);
+
+inline	Vector	QVRotate(Quaternion q, Vector v);
+
+inline	Quaternion	MakeQFromEulerAngles(float x, float y, float z);
+
+inline	Vector	MakeEulerAnglesFromQ(Quaternion q);
+
+
+
+
+
+inline	Quaternion::Quaternion(void)
+
+{
+
+	n = 0;
+
+	v.x = 0;
+
+	v.y =  0;
+
+	v.z = 0;
+
+}
+
+
+
+inline	Quaternion::Quaternion(float e0, float e1, float e2, float e3)
+
+{
+
+	n = e0;
+
+	v.x = e1;
+
+	v.y = e2;
+
+	v.z = e3;
+
+}
+
+
+
+inline	float	Quaternion::Magnitude(void)
+
+{
+
+	return (float) fast_sqrt(n*n + v.x*v.x + v.y*v.y + v.z*v.z);
+
+}
+
+
+
+inline	Vector	Quaternion::GetVector(void)
+
+{
+
+	return Vector(v.x, v.y, v.z);
+
+}
+
+
+
+inline	float	Quaternion::GetScalar(void)
+
+{
+
+	return n;
+
+}
+
+
+
+inline	Quaternion	Quaternion::operator+=(Quaternion q)
+
+{
+
+	n += q.n;
+
+	v.x += q.v.x;
+
+	v.y += q.v.y;
+
+	v.z += q.v.z;
+
+	return *this;
+
+}
+
+
+
+inline	Quaternion	Quaternion::operator-=(Quaternion q)
+
+{
+
+	n -= q.n;
+
+	v.x -= q.v.x;
+
+	v.y -= q.v.y;
+
+	v.z -= q.v.z;
+
+	return *this;
+
+}
+
+
+
+inline	Quaternion Quaternion::operator*=(float s)
+
+{
+
+	n *= s;
+
+	v.x *= s;
+
+	v.y *= s;
+
+	v.z *= s;
+
+	return *this;
+
+}
+
+
+
+inline	Quaternion Quaternion::operator/=(float s)
+
+{
+
+	n /= s;
+
+	v.x /= s;
+
+	v.y /= s;
+
+	v.z /= s;
+
+	return *this;
+
+}
+
+
+
+/*inline	Quaternion	Quaternion::operator~()
+
+{
+
+	return Quaternion(n, -v.x, -v.y, -v.z);
+
+}*/
+
+
+
+inline	Quaternion operator+(Quaternion q1, Quaternion q2)
+
+{
+
+	return	Quaternion(	q1.n + q2.n,
+
+							q1.v.x + q2.v.x,
+
+							q1.v.y + q2.v.y,
+
+							q1.v.z + q2.v.z);
+
+}
+
+
+
+inline	Quaternion operator-(Quaternion q1, Quaternion q2)
+
+{
+
+	return	Quaternion(	q1.n - q2.n,
+
+							q1.v.x - q2.v.x,
+
+							q1.v.y - q2.v.y,
+
+							q1.v.z - q2.v.z);
+
+}
+
+
+
+inline	Quaternion operator*(Quaternion q1, Quaternion q2)
+
+{
+
+	return	Quaternion(	q1.n*q2.n - q1.v.x*q2.v.x - q1.v.y*q2.v.y - q1.v.z*q2.v.z,
+
+							q1.n*q2.v.x + q1.v.x*q2.n + q1.v.y*q2.v.z - q1.v.z*q2.v.y,
+
+							q1.n*q2.v.y + q1.v.y*q2.n + q1.v.z*q2.v.x - q1.v.x*q2.v.z,
+
+							q1.n*q2.v.z + q1.v.z*q2.n + q1.v.x*q2.v.y - q1.v.y*q2.v.x);							
+
+}
+
+
+
+inline	Quaternion operator*(Quaternion q, float s)
+
+{
+
+	return	Quaternion(q.n*s, q.v.x*s, q.v.y*s, q.v.z*s);
+
+}
+
+
+
+inline	Quaternion operator*(float s, Quaternion q)
+
+{
+
+	return	Quaternion(q.n*s, q.v.x*s, q.v.y*s, q.v.z*s);
+
+}
+
+
+
+inline	Quaternion operator*(Quaternion q, Vector v)
+
+{
+
+	return	Quaternion(	-(q.v.x*v.x + q.v.y*v.y + q.v.z*v.z),
+
+							q.n*v.x + q.v.y*v.z - q.v.z*v.y,
+
+							q.n*v.y + q.v.z*v.x - q.v.x*v.z,
+
+							q.n*v.z + q.v.x*v.y - q.v.y*v.x);
+
+}
+
+
+
+inline	Quaternion operator*(Vector v, Quaternion q)
+
+{
+
+	return	Quaternion(	-(q.v.x*v.x + q.v.y*v.y + q.v.z*v.z),
+
+							q.n*v.x + q.v.z*v.y - q.v.y*v.z,
+
+							q.n*v.y + q.v.x*v.z - q.v.z*v.x,
+
+							q.n*v.z + q.v.y*v.x - q.v.x*v.y);
+
+}
+
+
+
+inline	Quaternion operator/(Quaternion q, float s)
+
+{
+
+	return	Quaternion(q.n/s, q.v.x/s, q.v.y/s, q.v.z/s);
+
+}
+
+
+
+inline	float QGetAngle(Quaternion q)
+
+{
+
+	return	(float) (2*acos(q.n));
+
+}
+
+
+
+inline	Vector QGetAxis(Quaternion q)
+
+{
+
+	Vector v;
+
+	float m;
+
+
+
+	v = q.GetVector();
+
+	m = v.Magnitude();
+
+	
+
+	if (m <= tol)
+
+		return Vector();
+
+	else
+
+		return v/m;	
+
+}
+
+
+
+inline	Quaternion QRotate(Quaternion q1, Quaternion q2)
+
+{
+
+	return	q1*q2*(~q1);
+
+}
+
+
+
+inline	Vector	QVRotate(Quaternion q, Vector v)
+
+{
+
+	Quaternion t;
+
+
+
+
+
+	t = q*v*(~q);
+
+
+
+	return	t.GetVector();
+
+}
+
+
+
+inline	Quaternion	MakeQFromEulerAngles(float x, float y, float z)
+
+{
+
+	Quaternion	q;
+
+	double	roll = DegreesToRadians(x);
+
+	double	pitch = DegreesToRadians(y);
+
+	double	yaw = DegreesToRadians(z);
+
+	
+
+	double	cyaw, cpitch, croll, syaw, spitch, sroll;
+
+	double	cyawcpitch, syawspitch, cyawspitch, syawcpitch;
+
+
+
+	cyaw = cos(0.5f * yaw);
+
+	cpitch = cos(0.5f * pitch);
+
+	croll = cos(0.5f * roll);
+
+	syaw = sin(0.5f * yaw);
+
+	spitch = sin(0.5f * pitch);
+
+	sroll = sin(0.5f * roll);
+
+
+
+	cyawcpitch = cyaw*cpitch;
+
+	syawspitch = syaw*spitch;
+
+	cyawspitch = cyaw*spitch;
+
+	syawcpitch = syaw*cpitch;
+
+
+
+	q.n = (float) (cyawcpitch * croll + syawspitch * sroll);
+
+	q.v.x = (float) (cyawcpitch * sroll - syawspitch * croll); 
+
+	q.v.y = (float) (cyawspitch * croll + syawcpitch * sroll);
+
+	q.v.z = (float) (syawcpitch * croll - cyawspitch * sroll);
+
+
+
+	return q;
+
+}
+
+
+
+inline	Vector	MakeEulerAnglesFromQ(Quaternion q)
+
+{
+
+	double	r11, r21, r31, r32, r33, r12, r13;
+
+	double	q00, q11, q22, q33;
+
+	double	tmp;
+
+	Vector	u;
+
+
+
+	q00 = q.n * q.n;
+
+	q11 = q.v.x * q.v.x;
+
+	q22 = q.v.y * q.v.y;
+
+	q33 = q.v.z * q.v.z;
+
+
+
+	r11 = q00 + q11 - q22 - q33;
+
+	r21 = 2 * (q.v.x*q.v.y + q.n*q.v.z);
+
+	r31 = 2 * (q.v.x*q.v.z - q.n*q.v.y);
+
+	r32 = 2 * (q.v.y*q.v.z + q.n*q.v.x);
+
+	r33 = q00 - q11 - q22 + q33;
+
+
+
+	tmp = fabs(r31);
+
+	if(tmp > 0.999999)
+
+	{
+
+		r12 = 2 * (q.v.x*q.v.y - q.n*q.v.z);
+
+		r13 = 2 * (q.v.x*q.v.z + q.n*q.v.y);
+
+
+
+		u.x = RadiansToDegrees(0.0f); //roll
+
+		u.y = RadiansToDegrees((float) (-(pi/2) * r31/tmp)); // pitch
+
+		u.z = RadiansToDegrees((float) atan2(-r12, -r31*r13)); // yaw
+
+		return u;
+
+	}
+
+
+
+	u.x = RadiansToDegrees((float) atan2(r32, r33)); // roll
+
+	u.y = RadiansToDegrees((float) asin(-r31));		 // pitch
+
+	u.z = RadiansToDegrees((float) atan2(r21, r11)); // yaw
+
+	return u;
+
+	
+
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+#endif
+
diff --git a/src/Quaternions.cpp b/src/Quaternions.cpp
new file mode 100644
index 0000000..464c0f2
--- /dev/null
+++ b/src/Quaternions.cpp
@@ -0,0 +1,747 @@
+#include "Quaternions.h"
+
+// Functions
+quaternion Quat_Mult(quaternion q1, quaternion q2)
+{
+        quaternion QResult;
+        float a, b, c, d, e, f, g, h;
+        a = (q1.w + q1.x) * (q2.w + q2.x);
+        b = (q1.z - q1.y) * (q2.y - q2.z);
+        c = (q1.w - q1.x) * (q2.y + q2.z);
+        d = (q1.y + q1.z) * (q2.w - q2.x);
+        e = (q1.x + q1.z) * (q2.x + q2.y);
+        f = (q1.x - q1.z) * (q2.x - q2.y);
+        g = (q1.w + q1.y) * (q2.w - q2.z);
+        h = (q1.w - q1.y) * (q2.w + q2.z);
+        QResult.w = b + (-e - f + g + h) / 2;
+        QResult.x = a - (e + f + g + h) / 2;
+        QResult.y = c + (e - f + g - h) / 2;
+        QResult.z = d + (e - f - g + h) / 2;
+        return QResult;
+}
+
+XYZ XYZ::operator+(XYZ add){
+	XYZ ne;
+	ne=add;
+	ne.x+=x;
+	ne.y+=y;
+	ne.z+=z;
+	return ne;
+}
+
+XYZ XYZ::operator-(XYZ add){
+	XYZ ne;
+	ne=add;
+	ne.x=x-ne.x;
+	ne.y=y-ne.y;
+	ne.z=z-ne.z;
+	return ne;
+}
+
+XYZ XYZ::operator*(float add){
+	XYZ ne;
+	ne.x=x*add;
+	ne.y=y*add;
+	ne.z=z*add;
+	return ne;
+}
+
+XYZ XYZ::operator*(XYZ add){
+	XYZ ne;
+	ne.x=x*add.x;
+	ne.y=y*add.y;
+	ne.z=z*add.z;
+	return ne;
+}
+
+XYZ XYZ::operator/(float add){
+	XYZ ne;
+	ne.x=x/add;
+	ne.y=y/add;
+	ne.z=z/add;
+	return ne;
+}
+
+void XYZ::operator+=(XYZ add){
+	x+=add.x;
+	y+=add.y;
+	z+=add.z;
+}
+
+void XYZ::operator-=(XYZ add){
+	x=x-add.x;
+	y=y-add.y;
+	z=z-add.z;
+}
+
+void XYZ::operator*=(float add){
+	x=x*add;
+	y=y*add;
+	z=z*add;
+}
+
+void XYZ::operator*=(XYZ add){
+	x=x*add.x;
+	y=y*add.y;
+	z=z*add.z;
+}
+
+void XYZ::operator/=(float add){
+	x=x/add;
+	y=y/add;
+	z=z/add;
+}
+
+void XYZ::operator=(float add){
+	x=add;
+	y=add;
+	z=add;
+}
+
+void XYZ::vec(Vector add){
+	x=add.x;
+	y=add.y;
+	z=add.z;
+}
+
+bool XYZ::operator==(XYZ add){
+	if(x==add.x&&y==add.y&&z==add.z)return 1;
+	return 0;
+}
+
+quaternion To_Quat(Matrix_t m)
+{
+        // From Jason Shankel, (C) 2000.
+        quaternion Quat;
+        
+        double Tr = m[0][0] + m[1][1] + m[2][2] + 1.0, fourD;
+        double q[4];
+        
+        int i,j,k;
+        if (Tr >= 1.0)
+        {
+                fourD = 2.0*fast_sqrt(Tr);
+                q[3] = fourD/4.0;
+                q[0] = (m[2][1] - m[1][2]) / fourD;
+                q[1] = (m[0][2] - m[2][0]) / fourD;
+                q[2] = (m[1][0] - m[0][1]) / fourD;
+        }
+        else
+        {
+                if (m[0][0] > m[1][1])
+                {
+                        i = 0;
+                }
+                else
+                {
+                        i = 1;
+                }
+                if (m[2][2] > m[i][i])
+                {
+                        i = 2;
+                }
+                j = (i+1)%3;
+                k = (j+1)%3;
+                fourD = 2.0*fast_sqrt(m[i][i] - m[j][j] - m[k][k] + 1.0);
+                q[i] = fourD / 4.0;
+                q[j] = (m[j][i] + m[i][j]) / fourD;
+                q[k] = (m[k][i] + m[i][k]) / fourD;
+                q[3] = (m[j][k] - m[k][j]) / fourD;
+        }
+        
+        Quat.x = q[0];
+        Quat.y = q[1];
+        Quat.z = q[2];
+        Quat.w = q[3];
+        return Quat;
+}
+void Quat_2_Matrix(quaternion Quat, Matrix_t m)
+{
+        // From the GLVelocity site (http://glvelocity.gamedev.net)
+        float fW = Quat.w;
+        float fX = Quat.x;
+        float fY = Quat.y;
+        float fZ = Quat.z;
+        float fXX = fX * fX;
+        float fYY = fY * fY;
+        float fZZ = fZ * fZ;
+        m[0][0] = 1.0f - 2.0f * (fYY + fZZ);
+        m[1][0] = 2.0f * (fX * fY + fW * fZ);
+        m[2][0] = 2.0f * (fX * fZ - fW * fY);
+        m[3][0] = 0.0f;
+        m[0][1] = 2.0f * (fX * fY - fW * fZ);
+        m[1][1] = 1.0f - 2.0f * (fXX + fZZ);
+        m[2][1] = 2.0f * (fY * fZ + fW * fX);
+        m[3][1] = 0.0f;
+        m[0][2] = 2.0f * (fX * fZ + fW * fY);
+        m[1][2] = 2.0f * (fX * fZ - fW * fX);
+        m[2][2] = 1.0f - 2.0f * (fXX + fYY);
+        m[3][2] = 0.0f;
+        m[0][3] = 0.0f;
+        m[1][3] = 0.0f;
+        m[2][3] = 0.0f;
+        m[3][3] = 1.0f;
+}
+quaternion To_Quat(angle_axis Ang_Ax)
+{
+        // From the Quaternion Powers article on gamedev.net
+        quaternion Quat;
+        
+        Quat.x = Ang_Ax.x * sin(Ang_Ax.angle / 2);
+        Quat.y = Ang_Ax.y * sin(Ang_Ax.angle / 2);
+        Quat.z = Ang_Ax.z * sin(Ang_Ax.angle / 2);
+        Quat.w = cos(Ang_Ax.angle / 2);
+        return Quat;
+}
+angle_axis Quat_2_AA(quaternion Quat)
+{
+        angle_axis Ang_Ax;
+        float scale, tw;
+        tw = (float)acos(Quat.w) * 2;
+        scale = (float)sin(tw / 2.0);
+        Ang_Ax.x = Quat.x / scale;
+        Ang_Ax.y = Quat.y / scale;
+        Ang_Ax.z = Quat.z / scale;
+        
+        Ang_Ax.angle = 2.0 * acos(Quat.w)/(float)PI*180;
+        return Ang_Ax;
+}
+
+quaternion To_Quat(int In_Degrees, euler Euler)
+{
+        // From the gamasutra quaternion article
+        quaternion Quat;
+        float cr, cp, cy, sr, sp, sy, cpcy, spsy;
+        //If we are in Degree mode, convert to Radians
+        if (In_Degrees) {
+                Euler.x = Euler.x * (float)PI / 180;
+                Euler.y = Euler.y * (float)PI / 180;
+                Euler.z = Euler.z * (float)PI / 180;
+        }
+        //Calculate trig identities
+        //Formerly roll, pitch, yaw
+        cr = float(cos(Euler.x/2));
+        cp = float(cos(Euler.y/2));
+        cy = float(cos(Euler.z/2));
+        sr = float(sin(Euler.x/2));
+        sp = float(sin(Euler.y/2));
+        sy = float(sin(Euler.z/2));
+        
+        cpcy = cp * cy;
+        spsy = sp * sy;
+        Quat.w = cr * cpcy + sr * spsy;
+        Quat.x = sr * cpcy - cr * spsy;
+        Quat.y = cr * sp * cy + sr * cp * sy;
+        Quat.z = cr * cp * sy - sr * sp * cy;
+        
+        return Quat;
+}
+        
+quaternion QNormalize(quaternion Quat)
+{
+        float norm;
+        norm =  Quat.x * Quat.x + 
+                Quat.y * Quat.y + 
+                Quat.z * Quat.z + 
+                Quat.w * Quat.w;
+        Quat.x = float(Quat.x / norm);
+        Quat.y = float(Quat.y / norm);
+        Quat.z = float(Quat.z / norm);
+        Quat.w = float(Quat.w / norm);
+        return Quat;
+}
+
+XYZ Quat2Vector(quaternion Quat)
+{
+	QNormalize(Quat);
+
+	float fW = Quat.w;
+	float fX = Quat.x;
+	float fY = Quat.y;
+	float fZ = Quat.z;
+	
+	XYZ tempvec;
+
+	tempvec.x = 2.0f*(fX*fZ-fW*fY);
+	tempvec.y = 2.0f*(fY*fZ+fW*fX);
+	tempvec.z = 1.0f-2.0f*(fX*fX+fY*fY);
+	
+	return tempvec;
+}
+
+void CrossProduct(XYZ P, XYZ Q, XYZ *V){
+	V->x = P.y * Q.z - P.z * Q.y;
+	V->y = P.z * Q.x - P.x * Q.z;
+	V->z = P.x * Q.y - P.y * Q.x;
+}
+
+void Normalise(XYZ *vectory) {
+	float d = fast_sqrt(vectory->x*vectory->x+vectory->y*vectory->y+vectory->z*vectory->z);
+	if(d==0){return;}
+	vectory->x /= d;
+	vectory->y /= d;
+	vectory->z /= d;
+}
+
+float fast_sqrt (register float arg)
+{	
+#ifdef OS9 
+	// Can replace with slower return std::sqrt(arg);
+	register float result;
+
+	if (arg == 0.0) return 0.0;
+	
+	asm {
+		frsqrte		result,arg			// Calculate Square root
+	}	
+	
+	// Newton Rhapson iterations.
+	result = result + 0.5 * result * (1.0 - arg * result * result);
+	result = result + 0.5 * result * (1.0 - arg * result * result);
+	
+	return result * arg;
+#else
+	return sqrt(arg);
+#endif
+}
+
+float normaldotproduct(XYZ point1, XYZ point2){
+	GLfloat returnvalue;
+	Normalise(&point1);
+	Normalise(&point2);
+	returnvalue=(point1.x*point2.x+point1.y*point2.y+point1.z*point2.z);
+	return returnvalue;
+}
+
+extern float u0, u1, u2;
+extern float v0, v1, v2;
+extern float a, b;
+extern int i, j;
+extern bool bInter;
+extern float pointv[3];
+extern float p1v[3];
+extern float p2v[3];
+extern float p3v[3];
+extern float normalv[3];
+
+bool PointInTriangle(Vector *p, Vector normal, float p11, float p12, float p13, float p21, float p22, float p23, float p31, float p32, float p33)
+{
+	bInter=0;
+	
+	pointv[0]=p->x;
+	pointv[1]=p->y;
+	pointv[2]=p->z;
+	
+	
+	p1v[0]=p11;
+	p1v[1]=p12;
+	p1v[2]=p13;
+	
+	p2v[0]=p21;
+	p2v[1]=p22;
+	p2v[2]=p23;
+	
+	p3v[0]=p31;
+	p3v[1]=p32;
+	p3v[2]=p33;
+	
+	normalv[0]=normal.x;
+	normalv[1]=normal.y;
+	normalv[2]=normal.z;
+	
+#define ABS(X) (((X)<0.f)?-(X):(X) )
+#define MAX(A, B) (((A)<(B))?(B):(A))	
+	float max = MAX(MAX(ABS(normalv[0]), ABS(normalv[1])), ABS(normalv[2]));
+#undef MAX
+	if (max == ABS(normalv[0])) {i = 1; j = 2;} // y, z
+	if (max == ABS(normalv[1])) {i = 0; j = 2;} // x, z
+	if (max == ABS(normalv[2])) {i = 0; j = 1;} // x, y
+#undef ABS
+	
+	u0 = pointv[i] - p1v[i];
+	v0 = pointv[j] - p1v[j];
+	u1 = p2v[i] - p1v[i];
+	v1 = p2v[j] - p1v[j];
+	u2 = p3v[i] - p1v[i];
+	v2 = p3v[j] - p1v[j];
+
+	if (u1 > -1.0e-05f && u1 < 1.0e-05f)// == 0.0f)
+	{
+		b = u0 / u2;
+		if (0.0f <= b && b <= 1.0f)
+		{
+			a = (v0 - b * v2) / v1;
+			if ((a >= 0.0f) && (( a + b ) <= 1.0f))
+				bInter = 1;
+		}
+	}
+	else
+	{
+		b = (v0 * u1 - u0 * v1) / (v2 * u1 - u2 * v1);
+		if (0.0f <= b && b <= 1.0f)
+		{
+			a = (u0 - b * u2) / u1;
+			if ((a >= 0.0f) && (( a + b ) <= 1.0f ))
+				bInter = 1;
+		}
+	}
+
+	return bInter;
+}
+
+bool LineFacet(Vector p1,Vector p2,Vector pa,Vector pb,Vector pc,Vector *p)
+{
+   float d;
+   float a1,a2,a3;
+   float total,denom,mu;
+   Vector n,pa1,pa2,pa3;
+
+   //Calculate the parameters for the plane 
+   n.x = (pb.y - pa.y)*(pc.z - pa.z) - (pb.z - pa.z)*(pc.y - pa.y);
+   n.y = (pb.z - pa.z)*(pc.x - pa.x) - (pb.x - pa.x)*(pc.z - pa.z);
+   n.z = (pb.x - pa.x)*(pc.y - pa.y) - (pb.y - pa.y)*(pc.x - pa.x);
+   n.Normalize();
+   d = - n.x * pa.x - n.y * pa.y - n.z * pa.z;
+
+   //Calculate the position on the line that intersects the plane 
+   denom = n.x * (p2.x - p1.x) + n.y * (p2.y - p1.y) + n.z * (p2.z - p1.z);
+   if (abs(denom) < 0.0000001)        // Line and plane don't intersect 
+      return 0;
+   mu = - (d + n.x * p1.x + n.y * p1.y + n.z * p1.z) / denom;
+   p->x = p1.x + mu * (p2.x - p1.x);
+   p->y = p1.y + mu * (p2.y - p1.y);
+   p->z = p1.z + mu * (p2.z - p1.z);
+   if (mu < 0 || mu > 1)   // Intersection not along line segment 
+      return 0;
+    
+   if(!PointInTriangle( p, n, pa.x, pa.y, pa.z, pb.x, pb.y, pb.z, pc.x, pc.y, pc.z)){return 0;}
+   
+   return 1;
+}
+
+bool PointInTriangle(XYZ *p, XYZ normal, XYZ *p1, XYZ *p2, XYZ *p3)
+{
+	bInter=0;
+		
+	pointv[0]=p->x;
+	pointv[1]=p->y;
+	pointv[2]=p->z;
+	
+	
+	p1v[0]=p1->x;
+	p1v[1]=p1->y;
+	p1v[2]=p1->z;
+	
+	p2v[0]=p2->x;
+	p2v[1]=p2->y;
+	p2v[2]=p2->z;
+	
+	p3v[0]=p3->x;
+	p3v[1]=p3->y;
+	p3v[2]=p3->z;
+	
+	normalv[0]=normal.x;
+	normalv[1]=normal.y;
+	normalv[2]=normal.z;
+	
+#define ABS(X) (((X)<0.f)?-(X):(X) )
+#define MAX(A, B) (((A)<(B))?(B):(A))	
+	float max = MAX(MAX(ABS(normalv[0]), ABS(normalv[1])), ABS(normalv[2]));
+#undef MAX
+	if (max == ABS(normalv[0])) {i = 1; j = 2;} // y, z
+	if (max == ABS(normalv[1])) {i = 0; j = 2;} // x, z
+	if (max == ABS(normalv[2])) {i = 0; j = 1;} // x, y
+#undef ABS
+	
+	u0 = pointv[i] - p1v[i];
+	v0 = pointv[j] - p1v[j];
+	u1 = p2v[i] - p1v[i];
+	v1 = p2v[j] - p1v[j];
+	u2 = p3v[i] - p1v[i];
+	v2 = p3v[j] - p1v[j];
+
+	if (u1 > -1.0e-05f && u1 < 1.0e-05f)// == 0.0f)
+	{
+		b = u0 / u2;
+		if (0.0f <= b && b <= 1.0f)
+		{
+			a = (v0 - b * v2) / v1;
+			if ((a >= 0.0f) && (( a + b ) <= 1.0f))
+				bInter = 1;
+		}
+	}
+	else
+	{
+		b = (v0 * u1 - u0 * v1) / (v2 * u1 - u2 * v1);
+		if (0.0f <= b && b <= 1.0f)
+		{
+			a = (u0 - b * u2) / u1;
+			if ((a >= 0.0f) && (( a + b ) <= 1.0f ))
+				bInter = 1;
+		}
+	}
+
+	return bInter;
+}
+
+bool LineFacet(XYZ p1,XYZ p2,XYZ pa,XYZ pb,XYZ pc,XYZ *p)
+{
+   float d;
+   float a1,a2,a3;
+   float total,denom,mu;
+   XYZ n,pa1,pa2,pa3;
+
+   //Calculate the parameters for the plane 
+   n.x = (pb.y - pa.y)*(pc.z - pa.z) - (pb.z - pa.z)*(pc.y - pa.y);
+   n.y = (pb.z - pa.z)*(pc.x - pa.x) - (pb.x - pa.x)*(pc.z - pa.z);
+   n.z = (pb.x - pa.x)*(pc.y - pa.y) - (pb.y - pa.y)*(pc.x - pa.x);
+   Normalise(&n);
+   d = - n.x * pa.x - n.y * pa.y - n.z * pa.z;
+
+   //Calculate the position on the line that intersects the plane 
+   denom = n.x * (p2.x - p1.x) + n.y * (p2.y - p1.y) + n.z * (p2.z - p1.z);
+   if (abs(denom) < 0.0000001)        // Line and plane don't intersect 
+      return 0;
+   mu = - (d + n.x * p1.x + n.y * p1.y + n.z * p1.z) / denom;
+   p->x = p1.x + mu * (p2.x - p1.x);
+   p->y = p1.y + mu * (p2.y - p1.y);
+   p->z = p1.z + mu * (p2.z - p1.z);
+   if (mu < 0 || mu > 1)   // Intersection not along line segment 
+      return 0;
+    
+   if(!PointInTriangle( p, n, &pa, &pb, &pc)){return 0;}
+   
+   return 1;
+}
+
+extern float d;
+extern float a1,a2,a3;
+extern float total,denom,mu;
+extern XYZ pa1,pa2,pa3,n;
+
+float LineFacetd(XYZ p1,XYZ p2,XYZ pa,XYZ pb,XYZ pc,XYZ *p)
+{
+
+   //Calculate the parameters for the plane 
+   n.x = (pb.y - pa.y)*(pc.z - pa.z) - (pb.z - pa.z)*(pc.y - pa.y);
+   n.y = (pb.z - pa.z)*(pc.x - pa.x) - (pb.x - pa.x)*(pc.z - pa.z);
+   n.z = (pb.x - pa.x)*(pc.y - pa.y) - (pb.y - pa.y)*(pc.x - pa.x);
+   Normalise(&n);
+   d = - n.x * pa.x - n.y * pa.y - n.z * pa.z;
+
+   //Calculate the position on the line that intersects the plane 
+   denom = n.x * (p2.x - p1.x) + n.y * (p2.y - p1.y) + n.z * (p2.z - p1.z);
+   if (abs(denom) < 0.0000001)        // Line and plane don't intersect 
+      return 0;
+   mu = - (d + n.x * p1.x + n.y * p1.y + n.z * p1.z) / denom;
+   p->x = p1.x + mu * (p2.x - p1.x);
+   p->y = p1.y + mu * (p2.y - p1.y);
+   p->z = p1.z + mu * (p2.z - p1.z);
+   if (mu < 0 || mu > 1)   // Intersection not along line segment 
+      return 0;
+    
+   if(!PointInTriangle( p, n, &pa, &pb, &pc)){return 0;}
+   
+   return 1;
+}
+
+float LineFacetd(XYZ p1,XYZ p2,XYZ pa,XYZ pb,XYZ pc, XYZ n, XYZ *p)
+{
+
+   //Calculate the parameters for the plane 
+   d = - n.x * pa.x - n.y * pa.y - n.z * pa.z;
+
+   //Calculate the position on the line that intersects the plane 
+   denom = n.x * (p2.x - p1.x) + n.y * (p2.y - p1.y) + n.z * (p2.z - p1.z);
+   if (abs(denom) < 0.0000001)        // Line and plane don't intersect 
+      return 0;
+   mu = - (d + n.x * p1.x + n.y * p1.y + n.z * p1.z) / denom;
+   p->x = p1.x + mu * (p2.x - p1.x);
+   p->y = p1.y + mu * (p2.y - p1.y);
+   p->z = p1.z + mu * (p2.z - p1.z);
+   if (mu < 0 || mu > 1)   // Intersection not along line segment 
+      return 0;
+    
+   if(!PointInTriangle( p, n, &pa, &pb, &pc)){return 0;}
+   return 1;
+}
+
+float LineFacetd(XYZ *p1,XYZ *p2,XYZ *pa,XYZ *pb,XYZ *pc, XYZ *n, XYZ *p)
+{
+
+   //Calculate the parameters for the plane 
+   d = - n->x * pa->x - n->y * pa->y - n->z * pa->z;
+
+   //Calculate the position on the line that intersects the plane 
+   denom = n->x * (p2->x - p1->x) + n->y * (p2->y - p1->y) + n->z * (p2->z - p1->z);
+   if (abs(denom) < 0.0000001)        // Line and plane don't intersect 
+      return 0;
+   mu = - (d + n->x * p1->x + n->y * p1->y + n->z * p1->z) / denom;
+   p->x = p1->x + mu * (p2->x - p1->x);
+   p->y = p1->y + mu * (p2->y - p1->y);
+   p->z = p1->z + mu * (p2->z - p1->z);
+   if (mu < 0 || mu > 1)   // Intersection not along line segment 
+      return 0;
+    
+   if(!PointInTriangle( p, *n, pa, pb, pc)){return 0;}
+   return 1;
+}
+
+void ReflectVector(XYZ *vel, XYZ *n)
+{
+   XYZ vn;
+   XYZ vt;
+   float dotprod;
+   
+   dotprod=dotproduct(*n,*vel);
+   vn.x=n->x*dotprod;
+   vn.y=n->y*dotprod;
+   vn.z=n->z*dotprod;
+
+   vt.x=vel->x-vn.x;
+   vt.y=vel->y-vn.y;
+   vt.z=vel->z-vn.z;
+	
+   vel->x = vt.x - vn.x;
+   vel->y = vt.y - vn.y;
+   vel->z = vt.z - vn.z;
+}
+
+float dotproduct(XYZ point1, XYZ point2){
+	GLfloat returnvalue;
+	returnvalue=(point1.x*point2.x+point1.y*point2.y+point1.z*point2.z);
+	return returnvalue;
+}
+
+float findDistance(XYZ point1, XYZ point2){
+	return(fast_sqrt((point1.x-point2.x)*(point1.x-point2.x)+(point1.y-point2.y)*(point1.y-point2.y)+(point1.z-point2.z)*(point1.z-point2.z)));
+}
+
+float findLength(XYZ point1){
+	return(fast_sqrt((point1.x)*(point1.x)+(point1.y)*(point1.y)+(point1.z)*(point1.z)));
+}
+
+
+float findLengthfast(XYZ point1){
+	return((point1.x)*(point1.x)+(point1.y)*(point1.y)+(point1.z)*(point1.z));
+}
+
+float findDistancefast(XYZ point1, XYZ point2){
+	return((point1.x-point2.x)*(point1.x-point2.x)+(point1.y-point2.y)*(point1.y-point2.y)+(point1.z-point2.z)*(point1.z-point2.z));
+}
+
+XYZ DoRotation(XYZ thePoint, float xang, float yang, float zang){
+	XYZ newpoint;
+	if(xang){
+		xang*=6.283185;
+		xang/=360;
+	}
+	if(yang){
+		yang*=6.283185;
+		yang/=360;
+	}
+	if(zang){
+		zang*=6.283185;
+		zang/=360;
+	}
+	
+	
+	if(yang){
+	newpoint.z=thePoint.z*cos(yang)-thePoint.x*sin(yang);
+	newpoint.x=thePoint.z*sin(yang)+thePoint.x*cos(yang);
+	thePoint.z=newpoint.z;
+	thePoint.x=newpoint.x;
+	}
+	
+	if(zang){
+	newpoint.x=thePoint.x*cos(zang)-thePoint.y*sin(zang);
+	newpoint.y=thePoint.y*cos(zang)+thePoint.x*sin(zang);
+	thePoint.x=newpoint.x;
+	thePoint.y=newpoint.y;
+	}
+	
+	if(xang){
+	newpoint.y=thePoint.y*cos(xang)-thePoint.z*sin(xang);
+	newpoint.z=thePoint.y*sin(xang)+thePoint.z*cos(xang);
+	thePoint.z=newpoint.z;
+	thePoint.y=newpoint.y;	
+	}
+	
+	return thePoint;
+}
+
+float square( float f ) { return (f*f) ;}
+
+bool sphere_line_intersection (
+    float x1, float y1 , float z1,
+    float x2, float y2 , float z2,
+    float x3, float y3 , float z3, float r )
+{
+
+	 // x1,y1,z1  P1 coordinates (point of line)
+	 // x2,y2,z2  P2 coordinates (point of line)
+	 // x3,y3,z3, r  P3 coordinates and radius (sphere)
+	 // x,y,z   intersection coordinates
+	 //
+	 // This function returns a pointer array which first index indicates
+	 // the number of intersection point, followed by coordinate pairs.
+
+	 float x , y , z;
+	 float a, b, c, mu, i ;
+	
+	if(x1>x3+r&&x2>x3+r)return(0);
+	if(x1<x3-r&&x2<x3-r)return(0);
+	if(y1>y3+r&&y2>y3+r)return(0);
+	if(y1<y3-r&&y2<y3-r)return(0);
+	if(z1>z3+r&&z2>z3+r)return(0);
+	if(z1<z3-r&&z2<z3-r)return(0);
+	 a =  square(x2 - x1) + square(y2 - y1) + square(z2 - z1);
+	 b =  2* ( (x2 - x1)*(x1 - x3)
+	      + (y2 - y1)*(y1 - y3)
+	      + (z2 - z1)*(z1 - z3) ) ;
+	 c =  square(x3) + square(y3) +
+	      square(z3) + square(x1) +
+	      square(y1) + square(z1) -
+	      2* ( x3*x1 + y3*y1 + z3*z1 ) - square(r) ;
+	 i =   b * b - 4 * a * c ;
+
+	 if ( i < 0.0 )
+	 {
+	  // no intersection
+	  return(0);
+	 }
+
+	return(1);
+}
+
+XYZ DoRotationRadian(XYZ thePoint, float xang, float yang, float zang){
+	XYZ newpoint;
+	XYZ oldpoint;
+	
+	oldpoint=thePoint;
+	
+	if(yang!=0){
+	newpoint.z=oldpoint.z*cos(yang)-oldpoint.x*sin(yang);
+	newpoint.x=oldpoint.z*sin(yang)+oldpoint.x*cos(yang);
+	oldpoint.z=newpoint.z;
+	oldpoint.x=newpoint.x;
+	}
+	
+	if(zang!=0){
+	newpoint.x=oldpoint.x*cos(zang)-oldpoint.y*sin(zang);
+	newpoint.y=oldpoint.y*cos(zang)+oldpoint.x*sin(zang);
+	oldpoint.x=newpoint.x;
+	oldpoint.y=newpoint.y;
+	}
+	
+	if(xang!=0){
+	newpoint.y=oldpoint.y*cos(xang)-oldpoint.z*sin(xang);
+	newpoint.z=oldpoint.y*sin(xang)+oldpoint.z*cos(xang);
+	oldpoint.z=newpoint.z;
+	oldpoint.y=newpoint.y;	
+	}
+	
+	return oldpoint;
+	
+}
+
diff --git a/src/Quaternions.h b/src/Quaternions.h
new file mode 100644
index 0000000..0a0ca4f
--- /dev/null
+++ b/src/Quaternions.h
@@ -0,0 +1,94 @@
+
+#ifndef _QUATERNIONS_H_
+#define _QUATERNIONS_H_
+
+#ifdef OS9 
+#pragma mark -
+#endif
+
+#include "Maths.h"
+#ifdef OS9 
+#include <gl.h>
+#else
+#include <GL/gl.h>
+#endif
+#include "PhysicsMath.h"
+
+/**> Quaternion Structures <**/
+#define PI      3.14159265355555897932384626
+#define RADIANS 0
+#define DEGREES 1
+#define deg2rad .0174532925
+
+using namespace std;
+typedef float Matrix_t [4][4];
+struct euler
+{
+        float x, y, z;
+};
+struct angle_axis
+{
+        float x, y, z, angle;
+};
+struct quaternion
+{
+        float x, y, z, w;
+};
+
+class XYZ{
+	public:
+		float x;
+		float y;
+		float z;
+		XYZ operator+(XYZ add);
+		XYZ operator-(XYZ add);
+		XYZ operator*(float add);
+		XYZ operator*(XYZ add);
+		XYZ operator/(float add);
+		void operator+=(XYZ add);
+		void operator-=(XYZ add);
+		void operator*=(float add);
+		void operator*=(XYZ add);
+		void operator/=(float add);
+		void operator=(float add);
+		void vec(Vector add);
+		bool operator==(XYZ add);
+};
+
+/*********************> Quaternion Function definition <********/
+quaternion To_Quat(int Degree_Flag, euler Euler);
+quaternion To_Quat(angle_axis Ang_Ax);
+quaternion To_Quat(Matrix_t m);
+angle_axis Quat_2_AA(quaternion Quat);
+void Quat_2_Matrix(quaternion Quat, Matrix_t m);
+quaternion Normalize(quaternion Quat);
+quaternion Quat_Mult(quaternion q1, quaternion q2);
+quaternion QNormalize(quaternion Quat);
+XYZ Quat2Vector(quaternion Quat);
+
+void CrossProduct(XYZ P, XYZ Q, XYZ *V);
+void Normalise(XYZ *vectory);
+float normaldotproduct(XYZ point1, XYZ point2);
+float fast_sqrt (register float arg);
+bool PointInTriangle(XYZ *p, XYZ normal, XYZ *p1, XYZ *p2, XYZ *p3);
+bool LineFacet(XYZ p1,XYZ p2,XYZ pa,XYZ pb,XYZ pc,XYZ *p);
+float LineFacetd(XYZ p1,XYZ p2,XYZ pa,XYZ pb,XYZ pc,XYZ *p);
+float LineFacetd(XYZ p1,XYZ p2,XYZ pa,XYZ pb,XYZ pc,XYZ n, XYZ *p);
+float LineFacetd(XYZ *p1,XYZ *p2,XYZ *pa,XYZ *pb,XYZ *pc,XYZ *n, XYZ *p);
+bool PointInTriangle(Vector *p, Vector normal, float p11, float p12, float p13, float p21, float p22, float p23, float p31, float p32, float p33);
+bool LineFacet(Vector p1,Vector p2,Vector pa,Vector pb,Vector pc,Vector *p);
+void ReflectVector(XYZ *vel, XYZ *n);
+XYZ DoRotation(XYZ thePoint, float xang, float yang, float zang);
+XYZ DoRotationRadian(XYZ thePoint, float xang, float yang, float zang);
+float findDistance(XYZ point1, XYZ point2);
+float findLength(XYZ point1);
+float findLengthfast(XYZ point1);
+float findDistancefast(XYZ point1, XYZ point2);
+float dotproduct(XYZ point1, XYZ point2);
+bool sphere_line_intersection (
+    float x1, float y1 , float z1,
+    float x2, float y2 , float z2,
+    float x3, float y3 , float z3, float r );
+
+#endif
+
diff --git a/src/SConstruct b/src/SConstruct
new file mode 100644
index 0000000..70fa779
--- /dev/null
+++ b/src/SConstruct
@@ -0,0 +1,10 @@
+Program(
+	'blackshades',
+	Split('Camera.cpp Decals.cpp Fog.cpp Frustum.cpp  GameDraw.cpp GameInitDispose.cpp GameLoop.cpp GameTick.cpp ' + 
+	'Globals.cpp MacInput.cpp Main.cpp Maths.cpp Models.cpp Person.cpp Quaternions.cpp Serialize.cpp Skeleton.cpp ' +
+	'Sprites.cpp Support.cpp Text.cpp Timer.cpp Textures.cpp'),
+	CPPDEFS=['GNUSOURCE=1'],
+	CPPPATH=['.'],
+	CPPFLAGS=['-O2', '-Wall' ,'-g'],
+	LIBS=['GL', 'GLU', 'openal', 'alut', 'SDL', 'SDL_image', 'vorbisfile', 'vorbis']
+)
diff --git a/src/Serialize.cpp b/src/Serialize.cpp
new file mode 100644
index 0000000..589dcb9
--- /dev/null
+++ b/src/Serialize.cpp
@@ -0,0 +1,107 @@
+#include <unistd.h>
+
+#include "Models.h"
+#include "Quaternions.h"
+#include "Serialize.h"
+
+/* these all read big-endian data */
+
+int ReadBool(int fd, int count, bool *b)
+{
+	while (count--) {
+		unsigned char buf[1];
+		
+		if (read(fd, buf, 1) != 1) {
+			STUB_FUNCTION;
+		}
+		
+		*b = (buf[0] != 0) ? true : false;
+		
+		b++;
+	}
+	
+	return 1;
+}
+
+int ReadShort(int fd, int count, short *s)
+{
+	while (count--) {
+		unsigned char buf[2];
+		
+		if (read(fd, buf, 2) != 2) {
+			STUB_FUNCTION;
+		}
+		
+		*s = (short)((buf[0] << 8) | buf[1]);
+		
+		s++;
+	}
+	
+	return 1;
+}
+
+int ReadInt(int fd, int count, int *s)
+{
+	while (count--) {
+		unsigned char buf[4];
+		
+		if (read(fd, buf, 4) != 4) {
+			STUB_FUNCTION;
+		}
+		
+		*s = (int)((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]);
+		
+		s++;
+	}
+	
+	return 1;
+}
+
+union intfloat {
+	int i;
+	float f;
+} intfloat;
+
+int ReadFloat(int fd, int count, float *f)
+{
+	union intfloat infl;
+	
+	while (count--) {
+		ReadInt(fd, 1, &(infl.i));
+		
+		*f = infl.f;
+		
+		f++;
+	}
+	
+	return 1;
+}
+
+int ReadXYZ(int fd, int count, XYZ *xyz)
+{
+	while (count--) {
+		ReadFloat(fd, 1, &(xyz->x));
+		ReadFloat(fd, 1, &(xyz->y));
+		ReadFloat(fd, 1, &(xyz->z));
+		
+		xyz++;
+	}
+	
+	return 1;
+}
+
+int ReadTexturedTriangle(int fd, int count, TexturedTriangle *tt)
+{
+	while (count--) {
+		short pad;
+		ReadShort(fd, 3, tt->vertex);
+		ReadShort(fd, 1, &pad); /* crud */
+		ReadFloat(fd, 1, &(tt->r));
+		ReadFloat(fd, 1, &(tt->g));
+		ReadFloat(fd, 1, &(tt->b));
+		
+		tt++;
+	}
+	
+	return count;
+}
diff --git a/src/Serialize.h b/src/Serialize.h
new file mode 100644
index 0000000..4ecb46d
--- /dev/null
+++ b/src/Serialize.h
@@ -0,0 +1,13 @@
+#ifndef SERIALIZE_H
+#define SERIALIZE_H
+
+/* these all read big-endian data */
+
+int ReadBool(int fd, int count, bool *b);
+int ReadShort(int fd, int count, short *s);
+int ReadInt(int fd, int count, int *s);
+int ReadFloat(int fd, int count, float *f);
+int ReadXYZ(int fd, int count, XYZ *xyz);
+int ReadTexturedTriangle(int fd, int count, TexturedTriangle *tt);
+
+#endif
diff --git a/src/Skeleton.cpp b/src/Skeleton.cpp
new file mode 100644
index 0000000..5f1880f
--- /dev/null
+++ b/src/Skeleton.cpp
@@ -0,0 +1,817 @@
+/**> HEADER FILES <**/
+#include "Skeleton.h"
+
+#include "Serialize.h"
+
+extern double multiplier;
+extern unsigned int gSourceID[100];
+extern unsigned int gSampleSet[100];
+extern int visions;
+extern float rad2deg;
+extern Camera camera;
+extern float soundscalefactor;
+
+extern XYZ vel;
+extern XYZ midp;
+extern XYZ newpoint1,newpoint2;
+
+extern float oldlength;
+extern float relaxlength;
+
+extern float friction;
+extern int numrepeats;
+extern float groundlevel;
+extern float offset;
+extern XYZ impact;
+extern XYZ overpoint;
+extern XYZ underpoint;
+extern int whichtri;
+extern XYZ normalrotated;
+extern bool groundish;
+
+
+void Joint::DoConstraint()
+{
+	
+	if(hasparent){
+		//Find midpoint
+		midp=(position+parent->position)/2;
+		//Find vector from midpoint to second vector
+		vel=parent->position-midp;
+		//Change to unit vector
+		Normalise(&vel);
+		//Apply velocity change
+		velocity+=((midp-vel*length/2)-position);
+		parent->velocity+=((midp+vel*length/2)-parent->position);
+		//Move child point to within certain distance of parent point
+		if(!locked)position=midp-vel*length/2;
+		if(!parent->locked)parent->position=midp+vel*length/2;
+	}
+}
+
+void Muscle::DoConstraint(int broken)
+{
+	oldlength=length;
+	relaxlength=findDistance(parent1->position,parent2->position);
+	
+	if(type==boneconnect)strength=1;
+	if(type==constraint)strength=0;
+	
+	if(strength<0)strength=0;
+	if(strength>1)strength=1;
+	
+	length-=(length-relaxlength)*(1-strength)*multiplier*multiplier*10000;
+	length-=(length-targetlength)*(strength)*multiplier*multiplier*10000;
+	if(strength==0)length=relaxlength;
+	
+	if((relaxlength-length>0&&relaxlength-oldlength<0)||(relaxlength-length<0&&relaxlength-oldlength>0))length=relaxlength;
+	
+	if(length<minlength)length=minlength;
+	if(length>maxlength&&!broken)length=maxlength;
+	
+	//Find midpoint
+	midp=(parent1->position+parent2->position)/2;
+	//Find vector from midpoint to second vector
+	vel=parent2->position-midp;
+	//Change to unit vector
+	Normalise(&vel);
+	//Apply velocity change
+	newpoint1=midp-vel*length/2;
+	newpoint2=midp+vel*length/2;
+	parent1->velocity+=(newpoint1-parent1->position);
+	parent2->velocity+=(newpoint2-parent2->position);
+	//Move child point to within certain distance of parent point
+	if(!parent1->locked)parent1->position=newpoint1;
+	if(!parent2->locked)parent2->position=newpoint2;
+}
+
+void Skeleton::DoConstraints()
+{
+	numrepeats=3;
+	
+	for(int j=0; j<numrepeats; j++){
+		for(int i=0; i<num_joints; i++){
+			joints[i].DoConstraint();
+		}
+	}
+}
+
+void Skeleton::DoConstraints(Model *collide, XYZ *move, float rotation)
+{
+	friction=20;
+	numrepeats=2;
+	groundlevel=0;
+	
+	move->y+=.35;
+	
+	for(int j=0; j<numrepeats; j++){
+		for(int i=0; i<num_joints; i++){
+			if(joints[i].existing||i==jointlabels[lefthand]||i==jointlabels[righthand]){
+			//Length constraints
+			joints[i].DoConstraint();
+			//Ground constraint
+			offset=0;
+			overpoint=joints[i].position;
+			overpoint.y+=10;
+			underpoint=joints[i].position;
+			underpoint.y-=offset;
+			whichtri=collide->LineCheck2(overpoint,underpoint,&impact,*move,rotation);
+			if(collide->normals[whichtri].y<=.8)whichtri=collide->LineCheck2(joints[i].realoldposition,joints[i].position,&impact,*move,rotation);
+			if(joints[i].position.y<=groundlevel+offset||whichtri!=-1){
+				if(whichtri==-1||(whichtri!=-1&&collide->normals[whichtri].y>.8)){
+					if(whichtri==-1)joints[i].position.y=groundlevel+offset;
+					if(whichtri!=-1){
+						joints[i].position=impact;
+						joints[i].position.y+=offset;
+					}
+					joints[i].velocity.y*=-.3;
+					joints[i].velocity.x*=.3;
+					joints[i].velocity.z*=.3;
+				}
+				offset=.2;
+				if(whichtri!=-1&&collide->normals[whichtri].y<=.8){
+					normalrotated=DoRotation(collide->normals[whichtri],0,rotation,0);
+					joints[i].position=impact+normalrotated*offset;
+					ReflectVector(&joints[i].velocity,&normalrotated);
+					joints[i].velocity*=.3;
+				}
+				if(broken<=1){
+				XYZ avgvelocity;
+				avgvelocity=0;
+				float gLoc[3];
+				ALint tempint;
+				for(int k=0; k<num_joints; k++){
+					avgvelocity+=joints[k].velocity;
+				}
+				avgvelocity/=num_joints;
+				if(joints[i].label==head&&(findLengthfast(joints[i].velocity)>2||findLengthfast(avgvelocity)>2)){
+					avgvelocity+=joints[i].velocity;
+					gLoc[0]=joints[i].position.x/soundscalefactor;
+					gLoc[1]=joints[i].position.y/soundscalefactor;
+					gLoc[2]=joints[i].position.z/soundscalefactor;
+#ifdef DEBIAN_NEEDS_TO_UPDATE_THEIR_OPENAL					
+					alGetSourceiv(gSourceID[headlandsound], AL_SOURCE_STATE, &tempint);
+#else
+					alGetSourcei(gSourceID[headlandsound], AL_SOURCE_STATE, &tempint);
+#endif
+					if (tempint != AL_PLAYING){
+						alSourcef(gSourceID[headlandsound], AL_MIN_GAIN, ALfloat(findLengthfast(avgvelocity)*2/findDistancefast(joints[i].position,camera.position)*soundscalefactor*2));
+						alSourcef(gSourceID[headlandsound], AL_MAX_GAIN, ALfloat(findLengthfast(avgvelocity)*2/findDistancefast(joints[i].position,camera.position)*soundscalefactor*2));
+						alSourcefv(gSourceID[headlandsound], AL_POSITION, gLoc);
+						alSourcePlay(gSourceID[headlandsound]);}
+				}
+				avgvelocity=0;
+				for(int k=0; k<num_joints; k++){
+					avgvelocity+=joints[k].velocity;
+				}
+				avgvelocity/=num_joints;
+				if((joints[i].label==abdomen)&&(findLengthfast(joints[i].velocity)>2||findLengthfast(avgvelocity)>2)){
+					avgvelocity+=joints[i].velocity;
+					gLoc[0]=joints[i].position.x/soundscalefactor;
+					gLoc[1]=joints[i].position.y/soundscalefactor;
+					gLoc[2]=joints[i].position.z/soundscalefactor;
+#ifdef DEBIAN_NEEDS_TO_UPDATE_THEIR_OPENAL
+					alGetSourceiv(gSourceID[bodylandsound], AL_SOURCE_STATE, &tempint);
+#else
+					alGetSourcei(gSourceID[bodylandsound], AL_SOURCE_STATE, &tempint);
+#endif					
+					if (tempint != AL_PLAYING){
+						alSourcef(gSourceID[bodylandsound], AL_MIN_GAIN, ALfloat(findLengthfast(joints[i].velocity)*1/findDistancefast(joints[i].position,camera.position)*soundscalefactor*2));
+						alSourcef(gSourceID[bodylandsound], AL_MAX_GAIN, ALfloat(findLengthfast(joints[i].velocity)*1/findDistancefast(joints[i].position,camera.position)*soundscalefactor*2));
+						alSourcefv(gSourceID[bodylandsound], AL_POSITION, gLoc);
+						alSourcePlay(gSourceID[bodylandsound]);}
+				}
+				}
+			}}
+		}
+		if(num_muscles)
+		for(int i=0; i<num_muscles; i++){
+			//Length constraints
+			muscles[i].DoConstraint(broken);
+		}
+	}
+	
+	for(int i=0; i<num_joints; i++){
+		joints[i].realoldposition=joints[i].position;
+	}
+	
+	//Add velocity
+	for(int i=0; i<num_joints; i++){
+		if(joints[i].existing||i==jointlabels[lefthand]||i==jointlabels[righthand])joints[i].position=joints[i].position+joints[i].velocity*multiplier;
+	}
+}
+
+void Skeleton::DoGravity()
+{
+	for(int i=0; i<num_joints; i++){
+		joints[i].velocity.y+=gravity*multiplier;
+	}
+}
+
+void Skeleton::Draw(int  muscleview)
+{
+	float jointcolor[4];
+
+	if(muscleview!=2){
+		jointcolor[0]=0;
+		jointcolor[1]=0;
+		jointcolor[2]=.5;
+		jointcolor[3]=1;
+	}
+	
+	if(muscleview==2){
+		jointcolor[0]=0;
+		jointcolor[1]=0;
+		jointcolor[2]=0;
+		jointcolor[3]=.5;
+	}
+	//Calc motionblur-ness
+	for(int i=0; i<num_joints; i++){
+		joints[i].oldposition=joints[i].position;
+		joints[i].blurred=findDistance(joints[i].position,joints[i].oldposition)*100;
+		if(joints[i].blurred<1)joints[i].blurred=1;
+	}
+
+	//Do Motionblur
+	glDepthMask(0);
+	glEnable(GL_BLEND);
+	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+	glBegin(GL_QUADS);
+		for(int i=0; i<num_joints; i++){
+			if(joints[i].hasparent){
+				glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/joints[i].blurred);
+				glVertex3f(joints[i].position.x,joints[i].position.y,joints[i].position.z);
+				glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/joints[i].parent->blurred);
+				glVertex3f(joints[i].parent->position.x,joints[i].parent->position.y,joints[i].parent->position.z);
+				glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/joints[i].parent->blurred);
+				glVertex3f(joints[i].parent->oldposition.x,joints[i].parent->oldposition.y,joints[i].parent->oldposition.z);
+				glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/joints[i].blurred);
+				glVertex3f(joints[i].oldposition.x,joints[i].oldposition.y,joints[i].oldposition.z);
+			}
+		}
+		for(int i=0; i<num_muscles; i++){
+			if(muscles[i].type==boneconnect){
+				glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/muscles[i].parent2->blurred);
+				glVertex3f(muscles[i].parent1->position.x,muscles[i].parent1->position.y,muscles[i].parent1->position.z);
+				glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/muscles[i].parent2->blurred);
+				glVertex3f(muscles[i].parent2->position.x,muscles[i].parent2->position.y,muscles[i].parent2->position.z);
+				glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/muscles[i].parent2->blurred);
+				glVertex3f(muscles[i].parent2->oldposition.x,muscles[i].parent2->oldposition.y,muscles[i].parent2->oldposition.z);
+				glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/muscles[i].parent1->blurred);
+				glVertex3f(muscles[i].parent1->oldposition.x,muscles[i].parent1->oldposition.y,muscles[i].parent1->oldposition.z);
+			}
+		}
+	glEnd();
+
+	glBegin(GL_LINES);
+		for(int i=0; i<num_joints; i++){
+			if(joints[i].hasparent){
+				glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/joints[i].blurred);
+				glVertex3f(joints[i].position.x,joints[i].position.y,joints[i].position.z);
+				glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/joints[i].parent->blurred);
+				glVertex3f(joints[i].parent->position.x,joints[i].parent->position.y,joints[i].parent->position.z);
+			}
+		}
+		for(int i=0; i<num_muscles; i++){
+			if(muscles[i].type==boneconnect){
+				glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/muscles[i].parent1->blurred);
+				glVertex3f(muscles[i].parent1->position.x,muscles[i].parent1->position.y,muscles[i].parent1->position.z);
+				glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/muscles[i].parent2->blurred);
+				glVertex3f(muscles[i].parent2->position.x,muscles[i].parent2->position.y,muscles[i].parent2->position.z);
+			}
+		}
+		glColor3f(.6,.6,0);
+		if(muscleview==1)
+		for(int i=0; i<num_muscles; i++){
+			if(muscles[i].type!=boneconnect){
+				glVertex3f(muscles[i].parent1->position.x,muscles[i].parent1->position.y,muscles[i].parent1->position.z);
+				glVertex3f(muscles[i].parent2->position.x,muscles[i].parent2->position.y,muscles[i].parent2->position.z);
+			}
+		}	
+	glEnd();
+	
+	if(muscleview!=2){
+		glPointSize(3);
+		glBegin(GL_POINTS);
+			for(int i=0; i<num_joints; i++){
+				if(i!=selected)glColor4f(0,0,.5,1);
+				if(i==selected)glColor4f(1,1,0,1);
+				if(joints[i].locked&&i!=selected)glColor4f(1,0,0,1);
+				glVertex3f(joints[i].position.x,joints[i].position.y,joints[i].position.z);
+			}
+		glEnd();
+	}
+		
+	//Set old position to current position
+	if(muscleview==2)
+	for(int i=0; i<num_joints; i++){
+		joints[i].oldposition=joints[i].position;
+	}
+	glDepthMask(1);
+}
+
+void Skeleton::AddJoint(float x, float y, float z, int which)
+{
+	if(num_joints<max_joints-1){
+		joints[num_joints].velocity=0;
+		joints[num_joints].position.x=x;
+		joints[num_joints].position.y=y;
+		joints[num_joints].position.z=z;
+		joints[num_joints].locked=0;
+		
+		if(which>=num_joints||which<0)joints[num_joints].hasparent=0;
+		if(which<num_joints&&which>=0){
+			joints[num_joints].parent=&joints[which];
+			joints[num_joints].hasparent=1;
+			joints[num_joints].length=findDistance(joints[num_joints].position,joints[num_joints].parent->position);
+		}	
+		num_joints++;
+	}
+}
+
+void Skeleton::DeleteJoint(int whichjoint)
+{
+	if(whichjoint<num_joints&&whichjoint>=0){
+		for(int i=0;i<num_muscles;i++){
+			while(muscles[i].parent1==&joints[whichjoint]&&i<num_muscles)DeleteMuscle(i);
+			while(muscles[i].parent2==&joints[whichjoint]&&i<num_muscles)DeleteMuscle(i);
+		}
+		for(int i=0;i<num_joints;i++){
+			if(joints[i].parent==&joints[whichjoint])joints[i].hasparent=0;
+		}
+		joints[whichjoint].hasparent=0;
+	}
+}
+
+void Skeleton::DeleteMuscle(int whichmuscle)
+{
+	if(whichmuscle<num_muscles){
+		muscles[whichmuscle].minlength=muscles[num_muscles-1].minlength;
+		muscles[whichmuscle].maxlength=muscles[num_muscles-1].maxlength;
+		muscles[whichmuscle].strength=muscles[num_muscles-1].strength;
+		muscles[whichmuscle].parent1=muscles[num_muscles-1].parent1;
+		muscles[whichmuscle].parent2=muscles[num_muscles-1].parent2;
+		muscles[whichmuscle].length=muscles[num_muscles-1].length;
+		muscles[whichmuscle].visible=muscles[num_muscles-1].visible;
+		muscles[whichmuscle].type=muscles[num_muscles-1].type;
+		muscles[whichmuscle].targetlength=muscles[num_muscles-1].targetlength;
+		
+		num_muscles--;
+	}
+}
+
+void Skeleton::SetJoint(float x, float y, float z, int which, int whichjoint)
+{
+	if(whichjoint<num_joints){
+		joints[whichjoint].velocity=0;
+		joints[whichjoint].position.x=x;
+		joints[whichjoint].position.y=y;
+		joints[whichjoint].position.z=z;
+		
+		if(which>=num_joints||which<0)joints[whichjoint].hasparent=0;
+		if(which<num_joints&&which>=0){
+			joints[whichjoint].parent=&joints[which];
+			joints[whichjoint].hasparent=1;
+			joints[whichjoint].length=findDistance(joints[whichjoint].position,joints[whichjoint].parent->position);
+		}	
+	}
+}
+
+void Skeleton::AddMuscle(int attach1,int attach2,float minlength,float maxlength,int type)
+{
+	if(num_muscles<max_muscles-1&&attach1<num_joints&&attach1>=0&attach2<num_joints&&attach2>=0&&attach1!=attach2){
+		muscles[num_muscles].parent1=&joints[attach1];
+		muscles[num_muscles].parent2=&joints[attach2];
+		muscles[num_muscles].length=findDistance(muscles[num_muscles].parent1->position,muscles[num_muscles].parent2->position);
+		muscles[num_muscles].targetlength=findDistance(muscles[num_muscles].parent1->position,muscles[num_muscles].parent2->position);
+		muscles[num_muscles].strength=.7;
+		muscles[num_muscles].type=type;
+		muscles[num_muscles].minlength=minlength;
+		muscles[num_muscles].maxlength=maxlength;
+		
+		num_muscles++;
+	}
+}
+
+void Skeleton::MusclesSet()
+{
+	for(int i=0;i<num_muscles;i++){
+		muscles[i].length=findDistance(muscles[i].parent1->position,muscles[i].parent2->position);
+	}
+}
+
+void Skeleton::FindRotationJoint(int which)
+{
+	XYZ temppoint1,temppoint2,tempforward;
+	float distance;
+	
+	temppoint1=joints[which].position;
+	temppoint2=joints[which].parent->position;
+	distance=findDistance(temppoint1,temppoint2);
+	joints[which].rotate2=asin((temppoint1.y-temppoint2.y)/distance)*rad2deg;
+	temppoint1.y=0;
+	temppoint2.y=0;
+	joints[which].rotate1=acos((temppoint1.z-temppoint2.z)/findDistance(temppoint1,temppoint2))*rad2deg;
+	if(temppoint1.x>temppoint2.x)joints[which].rotate1=360-joints[which].rotate1;
+	if(joints[which].label==head)tempforward=specialforward[0];
+	else if(joints[which].label==rightshoulder||joints[which].label==rightelbow||joints[which].label==rightwrist||joints[which].label==righthand)tempforward=specialforward[1];
+	else if(joints[which].label==leftshoulder||joints[which].label==leftelbow||joints[which].label==leftwrist||joints[which].label==lefthand)tempforward=specialforward[2];
+	else if(joints[which].label==righthip||joints[which].label==rightknee||joints[which].label==rightankle)tempforward=specialforward[3];
+	else if(joints[which].label==lefthip||joints[which].label==leftknee||joints[which].label==leftankle)tempforward=specialforward[4];
+	else if(!joints[which].lower)tempforward=forward;
+	else if(joints[which].lower)tempforward=lowforward;
+	tempforward=DoRotation(tempforward,0,joints[which].rotate1-90,0);
+	tempforward=DoRotation(tempforward,0,0,joints[which].rotate2-90);
+	tempforward.y=0;
+	Normalise(&tempforward);
+	joints[which].rotate3=acos(0-tempforward.z)*rad2deg;
+	if(0>tempforward.x)joints[which].rotate3=360-joints[which].rotate3;
+}
+
+void Skeleton::FindRotationMuscle(int which)
+{
+	XYZ temppoint1,temppoint2,tempforward;
+	float distance;
+	
+	temppoint1=muscles[which].parent1->position;
+	temppoint2=muscles[which].parent2->position;
+	distance=findDistance(temppoint1,temppoint2);
+	muscles[which].rotate2=asin((temppoint1.y-temppoint2.y)/distance)*rad2deg;
+	temppoint1.y=0;
+	temppoint2.y=0;
+	muscles[which].rotate1=acos((temppoint1.z-temppoint2.z)/findDistance(temppoint1,temppoint2));
+	muscles[which].rotate1*=360/6.28;
+	if(temppoint1.x>temppoint2.x)muscles[which].rotate1=360-muscles[which].rotate1;
+	if(muscles[which].parent1->label==head)tempforward=specialforward[0];
+	else if(muscles[which].parent1->label==rightshoulder||muscles[which].parent1->label==rightelbow||muscles[which].parent1->label==rightwrist)tempforward=specialforward[1];
+	else if(muscles[which].parent1->label==leftshoulder||muscles[which].parent1->label==leftelbow||muscles[which].parent1->label==leftwrist)tempforward=specialforward[2];
+	else if(muscles[which].parent1->label==righthip||muscles[which].parent1->label==rightknee||muscles[which].parent1->label==rightankle)tempforward=specialforward[3];
+	else if(muscles[which].parent1->label==lefthip||muscles[which].parent1->label==leftknee||muscles[which].parent1->label==leftankle)tempforward=specialforward[4];
+	else if(!muscles[which].parent1->lower)tempforward=forward;
+	else if(muscles[which].parent1->lower)tempforward=lowforward;
+	tempforward=DoRotation(tempforward,0,muscles[which].rotate1-90,0);
+	tempforward=DoRotation(tempforward,0,0,muscles[which].rotate2-90);
+	tempforward.y=0;
+	Normalise(&tempforward);
+	muscles[which].rotate3=acos(0-tempforward.z)*rad2deg;
+	for(int i=0;i<num_joints;i++){
+		if(&joints[i]==muscles[which].parent1){
+			joints[i].rotate1=muscles[which].rotate1;
+			joints[i].rotate2=muscles[which].rotate2;
+			joints[i].rotate3=muscles[which].rotate3;
+		}
+	}
+	if(0>tempforward.x)muscles[which].rotate3=360-muscles[which].rotate3;
+}
+
+extern Skeleton testskeleton;
+
+void Animation::Load(char *fileName)
+{
+	float placeholder[3];
+	files.OpenFile((unsigned char*)fileName);
+	if(files.sFile){
+		ReadInt(files.sFile, 1, &numframes);
+		for(int i=0;i<numframes;i++){
+			for(int j=0;j<max_joints;j++){
+				ReadXYZ(files.sFile, 1, &position[j][i]);
+			}
+			for(int j=0;j<max_joints;j++){
+				ReadFloat(files.sFile, 1, &twist[j][i]);
+			}
+			for(int j=0;j<max_joints;j++){
+				ReadBool(files.sFile, 1, &onground[j][i]);
+			}
+			ReadFloat(files.sFile, 1, &speed[i]);
+			ReadFloat(files.sFile, 1, &gunrotation[i]);
+		}
+		for(int i=0;i<numframes;i++){
+			for(int j=0;j<max_joints;j++){
+				ReadFloat(files.sFile, 1, &twist2[j][i]);
+			}
+		}
+	}
+	
+	files.EndLoad();
+	
+	for(int j=0;j<numframes;j++){
+		for(int i=0;i<testskeleton.num_joints;i++){
+			testskeleton.joints[i].position=position[i][j];	
+		}
+		//Find forward vectors
+		CrossProduct(testskeleton.joints[testskeleton.forwardjoints[1]].position-testskeleton.joints[testskeleton.forwardjoints[0]].position,testskeleton.joints[testskeleton.forwardjoints[2]].position-testskeleton.joints[testskeleton.forwardjoints[0]].position,&testskeleton.forward);
+		Normalise(&testskeleton.forward);
+		
+		CrossProduct(testskeleton.joints[testskeleton.lowforwardjoints[1]].position-testskeleton.joints[testskeleton.lowforwardjoints[0]].position,testskeleton.joints[testskeleton.lowforwardjoints[2]].position-testskeleton.joints[testskeleton.lowforwardjoints[0]].position,&testskeleton.lowforward);
+		Normalise(&testskeleton.lowforward);
+		
+		//Special forwards
+		testskeleton.specialforward[0]=testskeleton.forward;
+		
+		testskeleton.specialforward[1]=testskeleton.joints[testskeleton.jointlabels[rightshoulder]].position+testskeleton.joints[testskeleton.jointlabels[rightwrist]].position;
+		testskeleton.specialforward[1]=testskeleton.joints[testskeleton.jointlabels[rightelbow]].position-testskeleton.specialforward[1]/2;
+		testskeleton.specialforward[1]+=testskeleton.forward*.2;
+		Normalise(&testskeleton.specialforward[1]);
+		testskeleton.specialforward[2]=testskeleton.joints[testskeleton.jointlabels[leftshoulder]].position+testskeleton.joints[testskeleton.jointlabels[leftwrist]].position;
+		testskeleton.specialforward[2]=testskeleton.joints[testskeleton.jointlabels[leftelbow]].position-testskeleton.specialforward[2]/2;
+		testskeleton.specialforward[2]+=testskeleton.forward*.2;
+		Normalise(&testskeleton.specialforward[2]);
+		
+		testskeleton.specialforward[3]=testskeleton.joints[testskeleton.jointlabels[righthip]].position+testskeleton.joints[testskeleton.jointlabels[rightankle]].position;
+		testskeleton.specialforward[3]=testskeleton.specialforward[3]/2-testskeleton.joints[testskeleton.jointlabels[rightknee]].position;
+		testskeleton.specialforward[3]+=testskeleton.lowforward*.2;
+		Normalise(&testskeleton.specialforward[3]);
+		testskeleton.specialforward[4]=testskeleton.joints[testskeleton.jointlabels[lefthip]].position+testskeleton.joints[testskeleton.jointlabels[leftankle]].position;
+		testskeleton.specialforward[4]=testskeleton.specialforward[4]/2-testskeleton.joints[testskeleton.jointlabels[leftknee]].position;
+		testskeleton.specialforward[4]+=testskeleton.lowforward*.2;
+		Normalise(&testskeleton.specialforward[4]);
+
+		//Find joint rotations
+		for(int i=0;i<testskeleton.num_joints;i++){
+			if(testskeleton.joints[i].hasparent&&testskeleton.joints[i].visible)
+			{
+				testskeleton.FindRotationJoint(i);
+			}
+		}
+		for(int i=0;i<testskeleton.num_muscles;i++){
+			if(testskeleton.muscles[i].visible)
+			{
+				testskeleton.FindRotationMuscle(i);
+			}
+		}
+		for(int i=0;i<testskeleton.num_muscles;i++){
+			if(testskeleton.muscles[i].visible)
+			{
+				mrotate1[i][j]=testskeleton.muscles[i].rotate1;
+				mrotate2[i][j]=testskeleton.muscles[i].rotate2;
+				mrotate3[i][j]=testskeleton.muscles[i].rotate3;
+				if(j!=0&&mrotate3[i][j]>mrotate3[i][j-1]+180)mrotate3[i][j]-=360;
+				if(j!=0&&mrotate3[i][j]<mrotate3[i][j-1]-180)mrotate3[i][j]+=360;
+				if(j!=0&&mrotate2[i][j]>mrotate2[i][j-1]+180)mrotate2[i][j]-=360;
+				if(j!=0&&mrotate2[i][j]<mrotate2[i][j-1]-180)mrotate2[i][j]+=360;
+				if(j!=0&&mrotate1[i][j]>mrotate1[i][j-1]+180)mrotate1[i][j]-=360;
+				if(j!=0&&mrotate1[i][j]<mrotate1[i][j-1]-180)mrotate1[i][j]+=360;
+			}
+		}
+		for(int i=0;i<testskeleton.num_joints;i++){
+			if(testskeleton.joints[i].hasparent&&testskeleton.joints[i].visible)
+			{
+				rotate1[i][j]=testskeleton.joints[i].rotate1;
+				rotate2[i][j]=testskeleton.joints[i].rotate2;
+				rotate3[i][j]=testskeleton.joints[i].rotate3;
+				if(j!=0&&rotate3[i][j]>rotate3[i][j-1]+180)rotate3[i][j]-=360;
+				if(j!=0&&rotate3[i][j]<rotate3[i][j-1]-180)rotate3[i][j]+=360;
+				if(j!=0&&rotate2[i][j]>rotate2[i][j-1]+180)rotate2[i][j]-=360;
+				if(j!=0&&rotate2[i][j]<rotate2[i][j-1]-180)rotate2[i][j]+=360;
+				if(j!=0&&rotate1[i][j]>rotate1[i][j-1]+180)rotate1[i][j]-=360;
+				if(j!=0&&rotate1[i][j]<rotate1[i][j-1]-180)rotate1[i][j]+=360;
+			}
+		}
+	}
+	
+	for(int k=0;k<2;k++)
+	for(int j=0;j<numframes;j++){
+		for(int i=0;i<testskeleton.num_muscles;i++){
+			if(testskeleton.muscles[i].visible)
+			{
+				if(j!=0&&mrotate3[i][j]>mrotate3[i][j-1]+180)mrotate3[i][j]-=360;
+				if(j!=0&&mrotate3[i][j]<mrotate3[i][j-1]-180)mrotate3[i][j]+=360;
+				if(j!=0&&mrotate2[i][j]>mrotate2[i][j-1]+180)mrotate2[i][j]-=360;
+				if(j!=0&&mrotate2[i][j]<mrotate2[i][j-1]-180)mrotate2[i][j]+=360;
+				if(j!=0&&mrotate1[i][j]>mrotate1[i][j-1]+180)mrotate1[i][j]-=360;
+				if(j!=0&&mrotate1[i][j]<mrotate1[i][j-1]-180)mrotate1[i][j]+=360;
+				
+				if(j==0&&mrotate3[i][j]>mrotate3[i][numframes-1]+180)mrotate3[i][j]-=360;
+				if(j==0&&mrotate3[i][j]<mrotate3[i][numframes-1]-180)mrotate3[i][j]+=360;
+				if(j==0&&mrotate2[i][j]>mrotate2[i][numframes-1]+180)mrotate2[i][j]-=360;
+				if(j==0&&mrotate2[i][j]<mrotate2[i][numframes-1]-180)mrotate2[i][j]+=360;
+				if(j==0&&mrotate1[i][j]>mrotate1[i][numframes-1]+180)mrotate1[i][j]-=360;
+				if(j==0&&mrotate1[i][j]<mrotate1[i][numframes-1]-180)mrotate1[i][j]+=360;
+			}
+		}
+		for(int i=0;i<testskeleton.num_joints;i++){
+			if(testskeleton.joints[i].hasparent&&testskeleton.joints[i].visible)
+			{
+				if(j!=0&&rotate3[i][j]>rotate3[i][j-1]+180)rotate3[i][j]-=360;
+				if(j!=0&&rotate3[i][j]<rotate3[i][j-1]-180)rotate3[i][j]+=360;
+				if(j!=0&&rotate2[i][j]>rotate2[i][j-1]+180)rotate2[i][j]-=360;
+				if(j!=0&&rotate2[i][j]<rotate2[i][j-1]-180)rotate2[i][j]+=360;
+				if(j!=0&&rotate1[i][j]>rotate1[i][j-1]+180)rotate1[i][j]-=360;
+				if(j!=0&&rotate1[i][j]<rotate1[i][j-1]-180)rotate1[i][j]+=360;
+				
+				if(j==0&&rotate3[i][j]>rotate3[i][numframes-1]+180)rotate3[i][j]-=360;
+				if(j==0&&rotate3[i][j]<rotate3[i][numframes-1]-180)rotate3[i][j]+=360;
+				if(j==0&&rotate2[i][j]>rotate2[i][numframes-1]+180)rotate2[i][j]-=360;
+				if(j==0&&rotate2[i][j]<rotate2[i][numframes-1]-180)rotate2[i][j]+=360;
+				if(j==0&&rotate1[i][j]>rotate1[i][numframes-1]+180)rotate1[i][j]-=360;
+				if(j==0&&rotate1[i][j]<rotate1[i][numframes-1]-180)rotate1[i][j]+=360;
+			}
+		}
+	}
+}
+
+void Animation::Load(char *fileName, float rotate)
+{
+	float placeholder[3];
+	files.OpenFile((unsigned char*)fileName);
+	if(files.sFile){
+		ReadInt(files.sFile, 1, &numframes);
+		for(int i=0;i<numframes;i++){
+			for(int j=0;j<max_joints;j++){
+				ReadXYZ(files.sFile, 1, &position[j][i]);
+				position[j][i]=DoRotation(position[j][i],0,rotate,0);
+			}
+			for(int j=0;j<max_joints;j++){
+				ReadFloat(files.sFile, 1, &twist[j][i]);
+			}
+			for(int j=0;j<max_joints;j++){
+				ReadBool(files.sFile, 1, &onground[j][i]);
+			}
+			ReadFloat(files.sFile, 1, &speed[i]);
+			ReadFloat(files.sFile, 1, &gunrotation[i]);
+		}
+		for(int i=0;i<numframes;i++){
+			for(int j=0;j<max_joints;j++){
+				ReadFloat(files.sFile, 1, &twist2[j][i]);
+			}
+		}
+	}
+	files.EndLoad();
+	
+	for(int j=0;j<numframes;j++){
+		for(int i=0;i<testskeleton.num_joints;i++){
+			testskeleton.joints[i].position=position[i][j];	
+		}
+		//Find forward vectors
+		CrossProduct(testskeleton.joints[testskeleton.forwardjoints[1]].position-testskeleton.joints[testskeleton.forwardjoints[0]].position,testskeleton.joints[testskeleton.forwardjoints[2]].position-testskeleton.joints[testskeleton.forwardjoints[0]].position,&testskeleton.forward);
+		Normalise(&testskeleton.forward);
+		
+		CrossProduct(testskeleton.joints[testskeleton.lowforwardjoints[1]].position-testskeleton.joints[testskeleton.lowforwardjoints[0]].position,testskeleton.joints[testskeleton.lowforwardjoints[2]].position-testskeleton.joints[testskeleton.lowforwardjoints[0]].position,&testskeleton.lowforward);
+		Normalise(&testskeleton.lowforward);
+		
+		//Special forwards
+		testskeleton.specialforward[0]=testskeleton.forward;
+		
+		testskeleton.specialforward[1]=testskeleton.joints[testskeleton.jointlabels[rightshoulder]].position+testskeleton.joints[testskeleton.jointlabels[rightwrist]].position;
+		testskeleton.specialforward[1]=testskeleton.joints[testskeleton.jointlabels[rightelbow]].position-testskeleton.specialforward[1]/2;
+		testskeleton.specialforward[1]+=testskeleton.forward*.2;
+		Normalise(&testskeleton.specialforward[1]);
+		testskeleton.specialforward[2]=testskeleton.joints[testskeleton.jointlabels[leftshoulder]].position+testskeleton.joints[testskeleton.jointlabels[leftwrist]].position;
+		testskeleton.specialforward[2]=testskeleton.joints[testskeleton.jointlabels[leftelbow]].position-testskeleton.specialforward[2]/2;
+		testskeleton.specialforward[2]+=testskeleton.forward*.2;
+		Normalise(&testskeleton.specialforward[2]);
+		
+		testskeleton.specialforward[3]=testskeleton.joints[testskeleton.jointlabels[righthip]].position+testskeleton.joints[testskeleton.jointlabels[rightankle]].position;
+		testskeleton.specialforward[3]=testskeleton.specialforward[3]/2-testskeleton.joints[testskeleton.jointlabels[rightknee]].position;
+		testskeleton.specialforward[3]+=testskeleton.lowforward*.2;
+		Normalise(&testskeleton.specialforward[3]);
+		testskeleton.specialforward[4]=testskeleton.joints[testskeleton.jointlabels[lefthip]].position+testskeleton.joints[testskeleton.jointlabels[leftankle]].position;
+		testskeleton.specialforward[4]=testskeleton.specialforward[4]/2-testskeleton.joints[testskeleton.jointlabels[leftknee]].position;
+		testskeleton.specialforward[4]+=testskeleton.lowforward*.2;
+		Normalise(&testskeleton.specialforward[4]);
+
+		//Find joint rotations
+		for(int i=0;i<testskeleton.num_joints;i++){
+			if(testskeleton.joints[i].hasparent&&testskeleton.joints[i].visible)
+			{
+				testskeleton.FindRotationJoint(i);
+			}
+		}
+		for(int i=0;i<testskeleton.num_muscles;i++){
+			if(testskeleton.muscles[i].visible)
+			{
+				testskeleton.FindRotationMuscle(i);
+			}
+		}
+		for(int i=0;i<testskeleton.num_muscles;i++){
+			if(testskeleton.muscles[i].visible)
+			{
+				mrotate1[i][j]=testskeleton.muscles[i].rotate1;
+				mrotate2[i][j]=testskeleton.muscles[i].rotate2;
+				mrotate3[i][j]=testskeleton.muscles[i].rotate3;
+				if(j!=0&&mrotate3[i][j]>mrotate3[i][j-1]+180)mrotate3[i][j]-=360;
+				if(j!=0&&mrotate3[i][j]<mrotate3[i][j-1]-180)mrotate3[i][j]+=360;
+				if(j!=0&&mrotate2[i][j]>mrotate2[i][j-1]+180)mrotate2[i][j]-=360;
+				if(j!=0&&mrotate2[i][j]<mrotate2[i][j-1]-180)mrotate2[i][j]+=360;
+				if(j!=0&&mrotate1[i][j]>mrotate1[i][j-1]+180)mrotate1[i][j]-=360;
+				if(j!=0&&mrotate1[i][j]<mrotate1[i][j-1]-180)mrotate1[i][j]+=360;
+			}
+		}
+		for(int i=0;i<testskeleton.num_joints;i++){
+			if(testskeleton.joints[i].hasparent&&testskeleton.joints[i].visible)
+			{
+				rotate1[i][j]=testskeleton.joints[i].rotate1;
+				rotate2[i][j]=testskeleton.joints[i].rotate2;
+				rotate3[i][j]=testskeleton.joints[i].rotate3;
+				if(j!=0&&rotate3[i][j]>rotate3[i][j-1]+180)rotate3[i][j]-=360;
+				if(j!=0&&rotate3[i][j]<rotate3[i][j-1]-180)rotate3[i][j]+=360;
+				if(j!=0&&rotate2[i][j]>rotate2[i][j-1]+180)rotate2[i][j]-=360;
+				if(j!=0&&rotate2[i][j]<rotate2[i][j-1]-180)rotate2[i][j]+=360;
+				if(j!=0&&rotate1[i][j]>rotate1[i][j-1]+180)rotate1[i][j]-=360;
+				if(j!=0&&rotate1[i][j]<rotate1[i][j-1]-180)rotate1[i][j]+=360;
+			}
+		}
+	}
+	
+	for(int k=0;k<2;k++)
+	for(int j=0;j<numframes;j++){
+		for(int i=0;i<testskeleton.num_muscles;i++){
+			if(testskeleton.muscles[i].visible)
+			{
+				if(j!=0&&mrotate3[i][j]>mrotate3[i][j-1]+180)mrotate3[i][j]-=360;
+				if(j!=0&&mrotate3[i][j]<mrotate3[i][j-1]-180)mrotate3[i][j]+=360;
+				if(j!=0&&mrotate2[i][j]>mrotate2[i][j-1]+180)mrotate2[i][j]-=360;
+				if(j!=0&&mrotate2[i][j]<mrotate2[i][j-1]-180)mrotate2[i][j]+=360;
+				if(j!=0&&mrotate1[i][j]>mrotate1[i][j-1]+180)mrotate1[i][j]-=360;
+				if(j!=0&&mrotate1[i][j]<mrotate1[i][j-1]-180)mrotate1[i][j]+=360;
+				
+				if(j==0&&mrotate3[i][j]>mrotate3[i][numframes-1]+180)mrotate3[i][j]-=360;
+				if(j==0&&mrotate3[i][j]<mrotate3[i][numframes-1]-180)mrotate3[i][j]+=360;
+				if(j==0&&mrotate2[i][j]>mrotate2[i][numframes-1]+180)mrotate2[i][j]-=360;
+				if(j==0&&mrotate2[i][j]<mrotate2[i][numframes-1]-180)mrotate2[i][j]+=360;
+				if(j==0&&mrotate1[i][j]>mrotate1[i][numframes-1]+180)mrotate1[i][j]-=360;
+				if(j==0&&mrotate1[i][j]<mrotate1[i][numframes-1]-180)mrotate1[i][j]+=360;
+			}
+		}
+		for(int i=0;i<testskeleton.num_joints;i++){
+			if(testskeleton.joints[i].hasparent&&testskeleton.joints[i].visible)
+			{
+				if(j!=0&&rotate3[i][j]>rotate3[i][j-1]+180)rotate3[i][j]-=360;
+				if(j!=0&&rotate3[i][j]<rotate3[i][j-1]-180)rotate3[i][j]+=360;
+				if(j!=0&&rotate2[i][j]>rotate2[i][j-1]+180)rotate2[i][j]-=360;
+				if(j!=0&&rotate2[i][j]<rotate2[i][j-1]-180)rotate2[i][j]+=360;
+				if(j!=0&&rotate1[i][j]>rotate1[i][j-1]+180)rotate1[i][j]-=360;
+				if(j!=0&&rotate1[i][j]<rotate1[i][j-1]-180)rotate1[i][j]+=360;
+				
+				if(j==0&&rotate3[i][j]>rotate3[i][numframes-1]+180)rotate3[i][j]-=360;
+				if(j==0&&rotate3[i][j]<rotate3[i][numframes-1]-180)rotate3[i][j]+=360;
+				if(j==0&&rotate2[i][j]>rotate2[i][numframes-1]+180)rotate2[i][j]-=360;
+				if(j==0&&rotate2[i][j]<rotate2[i][numframes-1]-180)rotate2[i][j]+=360;
+				if(j==0&&rotate1[i][j]>rotate1[i][numframes-1]+180)rotate1[i][j]-=360;
+				if(j==0&&rotate1[i][j]<rotate1[i][numframes-1]-180)rotate1[i][j]+=360;
+			}
+		}
+	}
+}
+
+void Skeleton::Load(char *fileName)
+{
+	int parentID;
+	bool what;
+	bool lock;
+	float placeholder[3];
+	files.OpenFile((unsigned char*)fileName);
+	if(files.sFile){
+		ReadInt(files.sFile, 1, &num_joints);
+		for(int i=0;i<num_joints;i++){
+			ReadXYZ(files.sFile, 1, &joints[i].position);
+			ReadFloat(files.sFile, 1, &joints[i].length);
+			ReadFloat(files.sFile, 1, &joints[i].mass);
+			ReadBool(files.sFile, 1, &joints[i].hasparent);
+			ReadBool(files.sFile, 1, &joints[i].locked);
+			ReadInt(files.sFile, 1, &joints[i].modelnum);
+			ReadBool(files.sFile, 1, &joints[i].visible);
+			ReadBool(files.sFile, 1, &what);
+			ReadInt(files.sFile, 1, &joints[i].label);
+			ReadInt(files.sFile, 1, &joints[i].hasgun);
+			ReadBool(files.sFile, 1, &joints[i].lower);
+			ReadInt(files.sFile, 1, &parentID);
+			if(joints[i].hasparent)joints[i].parent=&joints[parentID];
+			joints[i].velocity=0;
+			joints[i].oldposition=joints[i].position;
+			joints[i].existing=1;
+		}
+
+		ReadInt(files.sFile, 1, &num_muscles);
+		for(int i=0;i<num_muscles;i++){
+			ReadFloat(files.sFile, 1, &muscles[i].length);
+			ReadFloat(files.sFile, 1, &muscles[i].targetlength);
+			ReadFloat(files.sFile, 1, &muscles[i].minlength);
+			ReadFloat(files.sFile, 1, &muscles[i].maxlength);
+			ReadFloat(files.sFile, 1, &muscles[i].strength);
+			ReadInt(files.sFile, 1, &muscles[i].type);
+			ReadBool(files.sFile, 1, &muscles[i].visible);
+			ReadInt(files.sFile, 1, &parentID);
+			muscles[i].parent1=&joints[parentID];
+			ReadInt(files.sFile, 1, &parentID);
+			muscles[i].parent2=&joints[parentID];
+		}
+
+		for(int j=0;j<3;j++){
+			ReadInt(files.sFile, 1, &forwardjoints[j]);
+		}
+		for(int j=0;j<3;j++){
+			ReadInt(files.sFile, 1, &lowforwardjoints[j]);
+		}
+	}
+	files.EndLoad();
+	
+	for(int i=0;i<num_joints;i++){
+		for(int j=0;j<num_joints;j++){
+			if(joints[i].label==j)jointlabels[j]=i;
+		}
+	}
+	
+	broken=0;	
+}
+
diff --git a/src/Skeleton.h b/src/Skeleton.h
new file mode 100644
index 0000000..9730665
--- /dev/null
+++ b/src/Skeleton.h
@@ -0,0 +1,156 @@
+#ifndef _SKELETON_H_
+#define _SKELETON_H_
+
+/**> HEADER FILES <**/
+#ifdef OS9 
+#include <gl.h>
+#include "alut.h"
+#else
+#include <GL/gl.h>
+#include <AL/al.h>
+#include <AL/alut.h>
+#endif
+#include "Quaternions.h"
+#include "Constants.h"
+#include "Files.h"
+#include "Models.h"
+#include "Camera.h"
+
+#define boneconnect 0
+#define constraint 1
+#define muscle 2
+
+//head, neck, left shoulder, left elbow, left wrist, left hand
+		//right shoulder, right elbow, right wrist, right hand,
+		//middle, left hip, right hip,groin
+		//left knee,left ankle, left foot, right knee, right ankle, right foort
+		
+#define head 1
+#define neck 2
+#define leftshoulder 3
+#define leftelbow 4
+#define leftwrist 5
+#define lefthand 6
+#define rightshoulder 7
+#define rightelbow 8
+#define rightwrist 9
+#define righthand 10
+#define abdomen 11
+#define lefthip 12
+#define righthip 13
+#define groin 14
+#define leftknee 15
+#define leftankle 16
+#define leftfoot 17
+#define rightknee 18
+#define rightankle 19
+#define rightfoot 20
+
+class Joint
+{
+	public:
+		XYZ position;
+		XYZ oldposition;
+		XYZ realoldposition;
+		XYZ velocity;
+		XYZ offset;
+		float blurred;
+		float length;
+		float mass;
+		bool lower;
+		bool hasparent;
+		bool locked;
+		int modelnum;
+		bool visible;
+		bool existing;
+		Joint* parent;
+		int label;
+		int hasgun;
+		float rotate1,rotate2,rotate3;
+		
+		void DoConstraint();
+};
+
+class Muscle
+{
+	public:
+		float length;
+		float targetlength;
+		Joint* parent1;
+		Joint* parent2;
+		float maxlength;
+		float minlength;
+		int type;
+		bool visible;
+		void DoConstraint(int broken);
+		float rotate1,rotate2,rotate3;
+		
+		float strength;
+};
+
+class Animation
+{
+	public:
+		Files files;
+		int numframes;
+		bool canbeoverridden;
+		bool ismodified[max_joints][max_frames];
+		XYZ  position[max_joints][max_frames];
+		float twist[max_joints][max_frames];
+		float twist2[max_joints][max_frames];
+		float speed[max_frames];
+		float gunrotation[max_frames];
+		bool onground[max_joints][max_frames];
+		XYZ forward[max_frames];
+		float rotate1[max_joints][max_frames],rotate2[max_joints][max_frames],rotate3[max_joints][max_frames];
+		float mrotate1[max_joints][max_frames],mrotate2[max_joints][max_frames],mrotate3[max_joints][max_frames];
+		void Load(char *fileName);
+		void Load(char *fileName,float rotate);
+};
+
+
+class Skeleton
+{
+	public:
+		int num_joints;
+		Joint joints[max_joints];
+		int jointlabels[max_joints];
+		
+		int num_muscles;
+		Muscle muscles[max_muscles];
+	
+		int selected;
+	
+		int forwardjoints[3];
+		XYZ forward;
+	
+		int lowforwardjoints[3];
+		XYZ lowforward;
+		
+		int broken;
+		bool offset;
+		
+		XYZ specialforward[5];
+		
+		bool free;
+		
+		Files files;
+	
+		void DoConstraints();
+		void DoConstraints(Model *collide, XYZ *move, float rotation);
+		void DoGravity();
+		void DoBalance();
+		void MusclesSet();
+		void Draw(int muscleview);
+		void AddJoint(float x, float y, float z, int which);
+		void SetJoint(float x, float y, float z, int which, int whichjoint);
+		void DeleteJoint(int whichjoint);
+		void AddMuscle(int attach1,int attach2,float maxlength,float minlength,int type);
+		void DeleteMuscle(int whichmuscle);
+		void FindRotationJoint(int which);
+		void FindRotationMuscle(int which);
+		void Load(char *fileName);
+};
+
+#endif
+
diff --git a/src/Sprites.cpp b/src/Sprites.cpp
new file mode 100644
index 0000000..f800282
--- /dev/null
+++ b/src/Sprites.cpp
@@ -0,0 +1,331 @@
+#include "Sprites.h"
+#include "Textures.h"
+
+extern double multiplier;
+extern bool slomo;
+extern Fog fog;
+extern bool blood;
+extern float fogcolorr;
+extern float fogcolorg;
+extern float fogcolorb;
+//Functions
+extern float sinefluct;
+extern int environment;
+extern Model gunmodels[10];
+extern Camera camera;
+extern float precipitationhorz;
+extern float precipitationvert;
+extern float precipitationdensity;
+extern float snowdelay;
+
+int Sprites::MakeSprite(int atype, float abrightness, float acolor1, float acolor2, float acolor3, XYZ alocation, XYZ avelocity, float asize){
+	type[howmanysprites]=atype;
+	rotation[howmanysprites]=Random()%360;
+	brightness[howmanysprites]=abrightness;
+	color1[howmanysprites]=acolor1;
+	color2[howmanysprites]=acolor2;
+	color3[howmanysprites]=acolor3;
+	location[howmanysprites]=alocation;
+	oldlocation[howmanysprites]=alocation;
+	velocity[howmanysprites]=avelocity;
+	size[howmanysprites]=asize;
+	initialsize[howmanysprites]=asize;
+	initialbrightness[howmanysprites]=abrightness;
+	initialvelocity[howmanysprites]=avelocity;
+	alivetime[howmanysprites]=0;
+	owner[howmanysprites]=0;
+	if(howmanysprites<maxsprites){howmanysprites++;}
+	
+	return 0;
+}
+
+int Sprites::MakeSprite(int atype, float abrightness, float acolor1, float acolor2, float acolor3, XYZ alocation, XYZ avelocity, float asize, int aowner){
+	type[howmanysprites]=atype;
+	rotation[howmanysprites]=Random()%360;
+	brightness[howmanysprites]=abrightness;
+	color1[howmanysprites]=acolor1;
+	color2[howmanysprites]=acolor2;
+	color3[howmanysprites]=acolor3;
+	location[howmanysprites]=alocation;
+	oldlocation[howmanysprites]=alocation;
+	velocity[howmanysprites]=avelocity;
+	size[howmanysprites]=asize;
+	initialsize[howmanysprites]=asize;
+	initialbrightness[howmanysprites]=abrightness;
+	initialvelocity[howmanysprites]=avelocity;
+	alivetime[howmanysprites]=0;
+	owner[howmanysprites]=aowner;
+	if(howmanysprites<maxsprites){howmanysprites++;}
+	
+	return 0;
+}
+
+int Sprites::DeleteSprite(int which){
+	if(which>=0){
+		location[which]=location[howmanysprites-1];
+		oldlocation[which]=oldlocation[howmanysprites-1];
+		velocity[which]=velocity[howmanysprites-1];
+		initialsize[which]=initialsize[howmanysprites-1];
+		size[which]=size[howmanysprites-1];
+		brightness[which]=brightness[howmanysprites-1];
+		initialbrightness[which]=initialbrightness[howmanysprites-1];
+		color1[which]=color1[howmanysprites-1];
+		color2[which]=color2[howmanysprites-1];
+		color3[which]=color3[howmanysprites-1];
+		alivetime[which]=alivetime[howmanysprites-1];
+		rotation[which]=rotation[howmanysprites-1];
+		type[which]=type[howmanysprites-1];
+		type[howmanysprites-1]=0;
+		
+		if(howmanysprites>0){howmanysprites--;}
+	}
+	
+	return 0;
+}
+
+void Sprites::LoadFlareTexture(char *fileName)
+{
+	flaretextureptr = loadTexture(fileName);
+}
+
+void Sprites::LoadMuzzleFlareTexture(char *fileName)
+{
+	muzzleflaretextureptr = loadTexture(fileName);
+}
+
+void Sprites::LoadSmokeTexture(char *fileName)
+{
+	smoketextureptr = loadTexture(fileName);
+}
+
+void Sprites::LoadBloodTexture(char *fileName)
+{
+	bloodtextureptr = loadTexture(fileName);
+}
+
+void Sprites::LoadRainTexture(char *fileName)
+{
+	raintextureptr = loadTexture(fileName);
+}
+
+void Sprites::LoadSnowTexture(char *fileName)
+{
+	snowtextureptr = loadTexture(fileName);
+}
+
+void Sprites::LoadBulletTexture(char *fileName)
+{
+	bullettextureptr = loadTexture(fileName);
+}
+
+
+void Sprites::DoStuff()
+{
+	for(int i=0;i<howmanysprites;i++){
+		if(type[i]!=bullet&&type[i]!=bulletinstant&&type[i]!=grenadesprite&&type[i]!=pinsprite&&type[i]!=grenadesprite)oldlocation[i]=location[i];
+		if(type[i]==muzzleflashsprite)brightness[i]-=multiplier*10;
+		if(type[i]==flashsprite)brightness[i]-=multiplier*10;
+		if(type[i]==smokesprite||type[i]==smokespritenoup||type[i]==bloodspritedown||type[i]==particlesspritedown)brightness[i]-=multiplier*.5;
+		if(type[i]==bloodspritenoup)brightness[i]-=multiplier*.9;
+		if(type[i]==smokesprite)size[i]=initialsize[i]*abs(fast_sqrt(fast_sqrt((float)abs(initialbrightness[i]-brightness[i]))));//velocity[i].y+=multiplier*20;
+		if(type[i]==bloodspritenoup||type[i]==particlesspritedown)size[i]=initialsize[i]*(initialbrightness[i]-brightness[i]+.4)*(initialbrightness[i]-brightness[i]+.4);//velocity[i].y+=multiplier*20;
+		if(type[i]==bloodspritenoup||type[i]==particlesspritedown)velocity[i]=initialvelocity[i]*brightness[i];//velocity[i].y+=multiplier*20;
+		if(type[i]==bullet)brightness[i]-=multiplier;
+		if(type[i]==snowsprite)rotation[i]+=multiplier*50;
+		if(type[i]==smokesprite)rotation[i]+=multiplier*30;
+		if(type[i]==smokespritenoup)rotation[i]+=multiplier*30;
+		if(type[i]==bulletinstant){
+			brightness[i]=0;
+		}
+		if(type[i]==grenadesprite||type[i]==spoonsprite||type[i]==pinsprite){
+			if(findLengthfast(velocity[i])>0){
+				velocity[i].y+=gravity*multiplier;
+				rotation[i]+=multiplier*2;
+			}
+		}
+		if(type[i]==bloodspritedown||type[i]==particlesspritedown){
+			velocity[i].y+=gravity*multiplier;
+		}
+		
+		if(type[i]!=bulletinstant&&type[i]!=bullet)location[i]=location[i]+velocity[i]*multiplier;
+		
+		alivetime[i]+=multiplier;
+		if(brightness[i]<=0)DeleteSprite(i);
+		if(type[i]==snowsprite&&(location[i].y<-.1||environment!=snowy_environment))DeleteSprite(i);
+		if(type[i]==rainsprite&&(location[i].y<-.1||environment!=rainy_environment))DeleteSprite(i);
+		
+		if(type[i]==snowsprite){
+			if(location[i].x<camera.position.x-precipitationhorz){location[i].x+=precipitationhorz*2;}
+			if(location[i].z<camera.position.z-precipitationhorz){location[i].z+=precipitationhorz*2;}
+			if(location[i].y<camera.position.y-precipitationvert){location[i].y+=precipitationvert*2;snowdelay+=1/precipitationdensity*2;}
+			if(location[i].x>camera.position.x+precipitationhorz){location[i].x-=precipitationhorz*2;}
+			if(location[i].z>camera.position.z+precipitationhorz){location[i].z-=precipitationhorz*2;}
+			if(location[i].y>camera.position.y+precipitationvert){location[i].y-=precipitationvert*2;}
+		}
+		if(type[i]==rainsprite){
+			if(location[i].x<camera.position.x-precipitationhorz*.5){location[i].x+=precipitationhorz;}
+			if(location[i].z<camera.position.z-precipitationhorz*.5){location[i].z+=precipitationhorz;}
+			if(location[i].y<camera.position.y-precipitationvert){location[i].y+=precipitationvert*2;snowdelay+=1/precipitationdensity/4;}
+			if(location[i].x>camera.position.x+precipitationhorz*.5){location[i].x-=precipitationhorz;}
+			if(location[i].z>camera.position.z+precipitationhorz*.5){location[i].z-=precipitationhorz;}
+			if(location[i].y>camera.position.y+precipitationvert){location[i].y-=precipitationvert*2;}
+		}
+	}
+}
+
+void Sprites::draw()
+{
+	float M[16];
+	XYZ begProj,endProj,avgProj,persp;
+	XYZ between;
+	float oolen,dx,dy;
+	float bulletsize;
+	XYZ point;
+	glAlphaFunc(GL_GREATER, 0.01);
+	
+	//glEnable(GL_POLYGON_OFFSET_FILL);
+	
+	glEnable(GL_BLEND);
+	glDisable(GL_CULL_FACE);
+	glEnable(GL_TEXTURE_2D);
+	glDisable(GL_LIGHTING);
+	glDepthMask(0);
+	glAlphaFunc(GL_GREATER, 0.01);
+	for(int i=0;i<howmanysprites;i++){
+		if(type[i]==muzzleflashsprite){fog.TempFog(0,0,0); glBindTexture(GL_TEXTURE_2D, muzzleflaretextureptr);glBlendFunc(GL_SRC_ALPHA,GL_ONE);}
+		if(type[i]==flashsprite){fog.TempFog(0,0,0); glBindTexture(GL_TEXTURE_2D, flaretextureptr);glBlendFunc(GL_SRC_ALPHA,GL_ONE);}
+		if(type[i]==smokesprite||type[i]==smokespritenoup){fog.ResetFog(); glBindTexture(GL_TEXTURE_2D,  smoketextureptr);glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);}
+		if(type[i]==bloodspritedown||type[i]==bloodspritenoup){fog.ResetFog(); glBindTexture(GL_TEXTURE_2D,  smoketextureptr);glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);}
+		if(type[i]==particlesspritedown){fog.ResetFog(); glBindTexture(GL_TEXTURE_2D,  bloodtextureptr);glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);}
+		if(type[i]==snowsprite){fog.ResetFog(); glBindTexture(GL_TEXTURE_2D,  snowtextureptr);glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);}
+		if(type[i]==rainsprite){fog.ResetFog(); glBindTexture(GL_TEXTURE_2D,  raintextureptr);glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);}
+		if(type[i]==bullet||type[i]==bulletinstant){fog.ResetFog(); glBindTexture(GL_TEXTURE_2D,  bullettextureptr);glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);}
+		
+		glPushMatrix();
+		if(type[i]==muzzleflashsprite||type[i]==flashsprite||type[i]==smokesprite||type[i]==smokespritenoup||type[i]==snowsprite||type[i]==particlesspritedown||((type[i]==bloodspritenoup||type[i]==bloodspritedown)&&blood)){
+			glColor4f(color1[i]*fogcolorr*1.6,color2[i]*fogcolorg*1.6,color3[i]*fogcolorb*1.6,brightness[i]);
+			glTranslatef(location[i].x,location[i].y,location[i].z);
+			if(type[i]==snowsprite){
+				glTranslatef(sinefluct*rotation[i]/400,0,sinefluct*rotation[i]/400);
+			}
+			glGetFloatv(GL_MODELVIEW_MATRIX,M);
+			point.x=M[12];
+			point.y=M[13];
+			point.z=M[14];
+			glLoadIdentity();
+			glTranslatef(point.x, point.y, point.z);
+			glRotatef(rotation[i],0,0,1);
+			
+			glBegin(GL_TRIANGLES);
+					glTexCoord2f(1.0f, 1.0f); glVertex3f( .3f*size[i], .3f*size[i], 0.0f);
+					glTexCoord2f(0.0f, 1.0f); glVertex3f(-.3f*size[i], .3f*size[i], 0.0f);
+					glTexCoord2f(1.0f, 0.0f); glVertex3f( .3f*size[i],-.3f*size[i], 0.0f);
+					glTexCoord2f(0.0f, 0.0f); glVertex3f(-.3f*size[i],-.3f*size[i], 0.0f);
+					glTexCoord2f(1.0f, 0.0f); glVertex3f( .3f*size[i], -.3f*size[i], 0.0f);
+					glTexCoord2f(0.0f, 1.0f); glVertex3f(-.3f*size[i], .3f*size[i], 0.0f);
+				glEnd();
+			
+		}
+		
+		if(type[i]==rainsprite){
+			glColor4f(color1[i]*fogcolorr*1.6,color2[i]*fogcolorg*1.6,color3[i]*fogcolorb*1.6,brightness[i]);
+			glTranslatef(location[i].x,location[i].y,location[i].z);
+			glGetFloatv(GL_MODELVIEW_MATRIX,M);
+			for( int k=0; k<3; k+=2 ) 
+				for( int j=0; j<3; j++ ) {
+					if ( k==j )
+						M[k*4+j] = 1.0;
+					else
+						M[k*4+j] = 0.0;
+				}
+			
+			
+			
+			glLoadMatrixf(M);
+			glScalef(.2,abs(velocity[i].y)*multiplier,.2);
+			glBegin(GL_TRIANGLES);
+				glTexCoord2f(1.0f, 1.0f); glVertex3f( .3f*size[i], .3f*size[i], 0.0f);
+				glTexCoord2f(0.0f, 1.0f); glVertex3f(-.3f*size[i], .3f*size[i], 0.0f);
+				glTexCoord2f(1.0f, 0.0f); glVertex3f( .3f*size[i],-.3f*size[i], 0.0f);
+				glTexCoord2f(0.0f, 0.0f); glVertex3f(-.3f*size[i],-.3f*size[i], 0.0f);
+				glTexCoord2f(1.0f, 0.0f); glVertex3f( .3f*size[i], -.3f*size[i], 0.0f);
+				glTexCoord2f(0.0f, 1.0f); glVertex3f(-.3f*size[i], .3f*size[i], 0.0f);
+			glEnd();
+		}
+		
+		if(type[i]==grenadesprite||type[i]==spoonsprite||type[i]==pinsprite){
+			glTranslatef(location[i].x,location[i].y+.2,location[i].z);
+			glDisable(GL_BLEND);
+			glEnable(GL_FOG);
+			glEnable(GL_CULL_FACE);
+			glDisable(GL_TEXTURE_2D);
+			glEnable(GL_LIGHTING);
+			glEnable(GL_COLOR_MATERIAL);
+			glDepthMask(1);
+			glRotatef(rotation[i],1,.6,.3);
+			
+			if(type[i]==grenadesprite)gunmodels[grenadebasemodel].draw();
+			if(type[i]==spoonsprite)gunmodels[grenadespoonmodel].draw();
+			if(type[i]==pinsprite)gunmodels[grenadepinmodel].draw();
+			
+			glEnable(GL_BLEND);
+			glDisable(GL_FOG);
+			glDisable(GL_CULL_FACE);
+			glEnable(GL_TEXTURE_2D);
+			glDisable(GL_LIGHTING);
+			glDisable(GL_COLOR_MATERIAL);
+			glDepthMask(0);
+		}
+		
+		if(type[i]==bullet||type[i]==bulletinstant){
+			bulletsize=size[i];
+			glPushMatrix();
+				begProj=location[i];
+				endProj=velocity[i];
+				glPushMatrix();
+					glTranslatef(begProj.x,begProj.y,begProj.z);
+					glGetFloatv(GL_MODELVIEW_MATRIX,M);
+					begProj.x=M[12];
+					begProj.y=M[13];
+					begProj.z=M[14];
+				glPopMatrix();
+				glPushMatrix();
+					glTranslatef(endProj.x,endProj.y,endProj.z);
+					glGetFloatv(GL_MODELVIEW_MATRIX,M);
+					endProj.x=M[12];
+					endProj.y=M[13];
+					endProj.z=M[14];
+				glPopMatrix();
+				avgProj=(endProj+begProj)/2;
+				
+				dx	= endProj.x - begProj.x;
+				dy	= endProj.y - begProj.y;
+				oolen= 1/fast_sqrt(dx*dx+dy*dy)*0.5;
+				persp=0;
+				persp.x=-dy*oolen; persp.y=dx*oolen;
+				
+				glColor4f(color1[i]*fogcolorr*1.6,color2[i]*fogcolorg*1.6,color3[i]*fogcolorb*1.6,brightness[i]);
+				
+				glPushMatrix();
+					glLoadIdentity();
+					glBegin(GL_TRIANGLES);
+						glTexCoord2f(0.0f, 1.0f); glVertex3f(endProj.x-persp.x*bulletsize/2, endProj.y-persp.y*bulletsize/2, endProj.z);
+						glTexCoord2f(1.0f, 0.0f); glVertex3f(begProj.x+persp.x*bulletsize/2, begProj.y+persp.y*bulletsize/2, begProj.z);
+						glTexCoord2f(0.0f, 0.0f); glVertex3f(begProj.x-persp.x*bulletsize/2, begProj.y-persp.y*bulletsize/2, begProj.z);
+						glTexCoord2f(1.0f, 0.0f); glVertex3f(begProj.x+persp.x*bulletsize/2, begProj.y+persp.y*bulletsize/2, begProj.z);
+						glTexCoord2f(0.0f, 1.0f); glVertex3f(endProj.x-persp.x*bulletsize/2, endProj.y-persp.y*bulletsize/2, endProj.z);
+						glTexCoord2f(1.0f, 1.0f); glVertex3f(endProj.x+persp.x*bulletsize/2, endProj.y+persp.y*bulletsize/2, endProj.z);
+					glEnd();
+				glPopMatrix();
+			glPopMatrix();	
+		}
+		glPopMatrix();
+	}
+	fog.ResetFog(); 
+	glDepthMask(1);
+	glDisable(GL_TEXTURE_2D);
+	glEnable(GL_CULL_FACE);
+	//glDisable(GL_POLYGON_OFFSET_FILL);
+	
+}
+
diff --git a/src/Sprites.h b/src/Sprites.h
new file mode 100644
index 0000000..b1f6b2e
--- /dev/null
+++ b/src/Sprites.h
@@ -0,0 +1,94 @@
+#ifndef _SPRITE_H_
+#define _SPRITE_H_
+
+#include "Quaternions.h"
+#ifdef OS9 
+#include <gl.h>
+#include <glu.h>
+#else
+#include <GL/gl.h>
+#include <GL/glu.h>
+#endif
+#include "Files.h"
+#include "Quaternions.h"
+#include "Camera.h"
+#include "Models.h"
+#include "Fog.h"
+//
+// Model Structures
+//
+
+#define maxsprites 2000
+
+#define muzzleflashsprite 1
+#define smokesprite 2
+#define smokespritenoup 3
+#define flashsprite 6
+#define grenadesprite 7
+#define pinsprite 8
+#define spoonsprite 9
+#define bloodspritedown 10
+#define bloodspritenoup 11
+#define particlesspritedown 12
+#define snowsprite 13
+#define rainsprite 14
+
+#define bullet 4
+#define bulletinstant 5
+
+class Sprites{
+	public:
+				GLuint 				flaretextureptr;
+				GLuint 				muzzleflaretextureptr;
+				GLuint 				smoketextureptr;
+				GLuint 				bullettextureptr;
+				GLuint 				bloodtextureptr;
+				GLuint 				raintextureptr;
+				GLuint 				snowtextureptr;
+				
+				int howmanysprites;
+				
+				XYZ location[maxsprites];
+				XYZ oldlocation[maxsprites];
+				XYZ velocity[maxsprites];
+				XYZ initialvelocity[maxsprites];
+				float size[maxsprites];
+				float initialsize[maxsprites];
+				float brightness[maxsprites];
+				float initialbrightness[maxsprites];
+				float color1[maxsprites];
+				float color2[maxsprites];
+				float color3[maxsprites];
+				float alivetime[maxsprites];
+				float rotation[maxsprites];
+				int type[maxsprites];
+				int owner[maxsprites];
+				
+				void draw();
+				
+				int DeleteSprite(int which);
+				int MakeSprite(int atype, float abrightness, float acolor1, float acolor2, float acolor3, XYZ alocation, XYZ avelocity, float asize);
+				int MakeSprite(int atype, float abrightness, float acolor1, float acolor2, float acolor3, XYZ alocation, XYZ avelocity, float asize, int aowner);
+				
+				void DoStuff();
+				void LoadMuzzleFlareTexture(char *fileName);
+				void LoadFlareTexture(char *fileName);
+				void LoadSmokeTexture(char *fileName);
+				void LoadBulletTexture(char *fileName);
+				void LoadBloodTexture(char *fileName);
+				void LoadSnowTexture(char *fileName);
+				void LoadRainTexture(char *fileName);
+				
+				~Sprites() {
+					glDeleteTextures( 1, (const GLuint *)muzzleflaretextureptr );
+					glDeleteTextures( 1, (const GLuint *)flaretextureptr );
+					glDeleteTextures( 1, (const GLuint *)bullettextureptr );
+					glDeleteTextures( 1, (const GLuint *)smoketextureptr );
+					glDeleteTextures( 1, (const GLuint *)bloodtextureptr );
+					glDeleteTextures( 1, (const GLuint *)raintextureptr );
+					glDeleteTextures( 1, (const GLuint *)snowtextureptr );
+				};
+};
+
+#endif
+
diff --git a/src/Support.cpp b/src/Support.cpp
new file mode 100644
index 0000000..7c77fc5
--- /dev/null
+++ b/src/Support.cpp
@@ -0,0 +1,386 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "SDL/SDL.h"
+
+#include "Support.h"
+#include "Files.h"
+
+int Random()
+{
+#if RAND_MAX >= 65535
+	return (rand() % 65535) - 32767;
+#else
+#error please fix this for your platform
+#endif
+}
+
+void Microseconds(UnsignedWide *microTickCount)
+{
+	/* NOTE: hi isn't used in BS, so it's not implemented here */
+	/* TODO: does game need microsecond precision? */
+	microTickCount->hi = 0;
+	microTickCount->lo = SDL_GetTicks() * 1000;
+}
+
+void GetMouse(Point *p)
+{
+	int x;
+	int y;
+	
+	SDL_GetMouseState(&x, &y);
+	
+	p->h = x;
+	p->v = y;
+}
+
+void GetMouseRel(Point *p)
+{
+	int x;
+	int y;
+	
+	SDL_GetRelativeMouseState(&x, &y);
+	
+	p->h = x;
+	p->v = y;
+}
+int Button(void)
+{
+	return (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(1));
+}
+
+void InitMouse()
+{
+// STUB_FUNCTION;
+}
+
+void MoveMouse(int xcoord, int ycoord, Point *mouseloc)
+{
+	/* TODO: mouse warp is annoying when we can just grab the mouse */
+#ifdef FULLSCREEN
+	SDL_WarpMouse(xcoord, ycoord);
+	SDL_PumpEvents();
+#endif
+	GetMouse(mouseloc);
+}
+
+void DisposeMouse()
+{
+// STUB_FUNCTION;
+}
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#ifndef MAX_PATH
+#define MAX_PATH 256
+#endif
+
+static int find_filename(char *filename)
+{
+	char *ptr;
+	char *cur;
+	char *next;
+	DIR *dir;
+	struct dirent *dirent;
+	
+	if (access(filename, R_OK) == 0) {
+		return 1;
+	}
+	
+	ptr = filename;
+	
+	while (*ptr) {
+		if (ptr == filename || *ptr == '/') {
+			if (*ptr == '/') {
+				cur = ptr+1;
+			} else {
+				cur = ptr;
+			}
+			
+			if (*cur == 0) {
+				/* hit the end */
+				break;
+			}
+			
+			next = strchr(cur, '/');
+			
+			if (ptr != filename) {
+				*ptr = 0;
+			}
+			
+			if (next) {
+				*next = 0;
+			}
+			
+			if (ptr == filename && *ptr == '/') {
+				dir = opendir("/");
+			} else {
+				dir = opendir(filename);
+			}
+			
+			if (dir == NULL) {
+				if (ptr != filename) {
+					*ptr = '/';
+				}
+				
+				if (next) {
+					*next = 0;
+				}
+				
+				return 0;
+			}
+			
+			while ((dirent = readdir(dir)) != NULL) {
+				if (strcasecmp(cur, dirent->d_name) == 0) {
+					strcpy(cur, dirent->d_name);
+					break;
+				}
+			}
+			
+			closedir(dir);
+			
+			if (ptr != filename) {
+				*ptr = '/';
+			}
+			
+			if (next) {
+				*next = '/';
+				ptr = next;
+			} else {
+				ptr++;
+			}
+		} else {
+			ptr++;
+		}
+	}
+	
+	if (access(filename, R_OK) == 0) {
+		return 1;
+	}
+	
+	return 0;
+}
+
+static void fix_filename(const char *original, char *fixed)
+{
+	const char *start;
+	int i;
+	int len;
+
+	start = original;
+	if (original[0] == ':') {
+		start = &original[1];
+	}
+
+	fixed[MAX_PATH-1] = 0;
+	
+	strncpy(fixed, start, MAX_PATH);
+	
+	/* check to see if strncpy overwrote the terminator */
+	if (fixed[MAX_PATH-1] != 0) {
+		fixed[MAX_PATH-1] = 0;
+	
+		fprintf(stderr, "ERROR: file truncation error: %s -> %s\n", 
+			original, fixed);
+	}
+	
+	len = strlen(fixed);
+	for (i = 0; i < len; i++) {
+		if (fixed[i] == ':') {
+			fixed[i] = '/';
+		}
+	}
+	
+	/* 
+	   here we would try to see if the file is available (game dir),
+	   else try another dir
+	   
+	   really, this function also needs a flag to indicate whether
+	   it should only go to local (write) or both (read)
+	 */
+
+	if (find_filename(fixed) == 0) {
+		fprintf(stderr, "find failed: %s\n", fixed);
+	}
+}
+
+/*
+Convenient Filename Hacks
+*/
+
+FILE *cfh_fopen(const char *filename, const char *mode)
+{
+	char filename1[MAX_PATH];
+	
+	fix_filename(filename, filename1);
+	
+	return fopen(filename1, mode);	
+}
+
+int Files::OpenFile(Str255 Name)
+{
+	char filename1[MAX_PATH];
+	
+	fix_filename((char *)Name, filename1);
+	
+	sFile = open(filename1, O_RDONLY | O_BINARY);
+	return sFile;
+}
+
+void Files::EndLoad()
+{
+	if (sFile != -1) {
+		FSClose( sFile );
+	}
+	
+	sFile = -1;
+}
+
+#ifdef NOOGG    
+/*
+  Our own special magic version that fixes the filename.
+ */
+void alutLoadWAVFile_CFH(char *filename, ALenum *format, void **wave,
+	unsigned int *size, ALsizei *freq)
+{
+	char filename1[MAX_PATH];
+	ALsizei format1, size1, bits1, freq1;
+	
+	fix_filename(filename, filename1);
+	
+	alutLoadWAV(filename1, wave, &format1, &size1, &bits1, &freq1);
+	
+	*format = format1;
+	*size = size1;
+	*freq = freq1;
+}
+
+void alutUnloadWAV_CFH(ALenum format, void *wave, unsigned int size,
+	ALsizei freq)
+{
+	free(wave);
+}
+#else
+#include <vorbis/vorbisfile.h>
+
+/*
+Read the requested OGG file into memory, and extract the information required
+by OpenAL
+*/
+void LoadOGG_CFH(char *filename, ALenum *format, void **wave,
+	unsigned int *size, ALsizei *freq)
+{
+	char filename1[MAX_PATH];
+	ALsizei format1, size1, freq1;
+	void *wave1;
+	OggVorbis_File vf;
+	vorbis_info *vi;
+	FILE *fp;
+	int current_section;
+	char *buf;
+	int asize;
+	int err;
+	int eof;
+
+#if BYTE_ORDER == BIG_ENDIAN
+	const int endian = 1;
+#else
+	const int endian = 0;
+#endif
+
+	/* try to find the real file (and place it in filename1) */
+	fix_filename(filename, filename1);
+
+	/* open it for reading */
+	fp = fopen(filename1, "rb");
+	if (fp == NULL) {
+		fprintf(stderr, "ERROR: unable to open %s\n", filename1);
+		exit(EXIT_FAILURE);
+	}
+	
+	/* open it up */
+	err = ov_open(fp, &vf, NULL, 0);	
+	if (err < 0) {
+		fprintf(stderr, "ERROR: vorbis error %d opening %s\n", -err, filename1);
+		exit(EXIT_FAILURE);
+	}
+
+	/* get the ogg information */
+	vi = ov_info(&vf, -1);
+	if (vi == NULL) {
+		fprintf(stderr, "ERROR: vorbis error opening %s (ov_info failed)\n", filename1);
+		exit(EXIT_FAILURE);
+	}
+	
+	/* calculate the byte size */
+	size1 = vi->channels * 2 * ov_pcm_total(&vf, -1);
+
+	/* hack around some possible ogg vorbis weirdness */
+	asize = ((size1 + 2047) / 2048 + 1) * 2048;
+	
+	/* allocate our buffer */	
+	wave1 = malloc(asize);
+	
+	if (wave1 == NULL) {
+		fprintf(stderr, "ERROR: could not allocate %d bytes while loading %s\n", size1, filename1);
+		exit(EXIT_FAILURE);
+	}
+
+	/* read it in */
+	eof = 0;
+	buf = (char *)wave1;
+	
+	while(!eof) {
+		long ret = ov_read(&vf, buf, 1024, endian, 2, 1, 
+			&current_section);
+		
+		if (ret == 0) {
+			/* end of file */
+			eof = 1;
+		} else if (ret < 0) {
+			/* some sort of error */
+			
+			/* TODO: is this ok to ignore? */
+		} else {
+			buf += ret;
+		}
+	}
+
+	/* get the rest of the information */
+	if (vi->channels == 1) {
+		format1 = AL_FORMAT_MONO16;
+	} else if (vi->channels == 2) {
+		format1 = AL_FORMAT_STEREO16;
+	} else {
+		fprintf(stderr, "ERROR: ogg %s has %d channels\n", filename1, vi->channels);
+		exit(EXIT_FAILURE);
+	}
+	
+	freq1 = vi->rate;
+
+	/* we are done with the ogg, so free it */
+	ov_clear(&vf);
+	
+	/* finall, give the values to the caller */	
+	*format = format1;
+	*size = size1;
+	*freq = freq1;
+	*wave = wave1;
+}
+
+/*
+Free the OGG buffer
+*/
+void FreeOGG(ALenum format, void *wave, unsigned int size,
+	ALsizei freq)
+{
+	free(wave);
+}
+#endif
diff --git a/src/Support.h b/src/Support.h
new file mode 100644
index 0000000..49b83fc
--- /dev/null
+++ b/src/Support.h
@@ -0,0 +1,60 @@
+#ifndef SUPPORT_H
+#define SUPPORT_H
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include <AL/al.h>
+#include <AL/alut.h>
+
+#define STUB_FUNCTION fprintf(stderr,"STUB: %s at " __FILE__ ", line %d, thread %d\n",__FUNCTION__,__LINE__,getpid())
+
+#define fsFromStart SEEK_SET
+
+typedef unsigned char * Str255;
+typedef int OSErr;
+typedef short int SInt16;
+
+typedef bool Boolean;
+#define TRUE true
+#define FALSE false
+
+typedef struct UnsignedWide
+{
+	unsigned int lo;
+	unsigned int hi;
+} UnsignedWide;
+
+typedef struct Point
+{
+	int h;
+	int v;
+} Point;
+
+#define SetFPos(fildes, whence, offset) lseek(fildes, offset, whence)
+#define FSClose(fildes) close(fildes)
+
+int Random();
+void Microseconds(UnsignedWide *microTickCount);
+void GetMouse(Point *p);
+void GetMouseRel(Point *p);
+void GetKeys(unsigned long *keys);
+int Button(void);
+#ifdef NOOGG
+void alutLoadWAVFile_CFH(char *filename, ALenum *format, void **wave, 
+	unsigned int *size, ALsizei *freq);
+void alutUnloadWAV_CFH(ALenum format, void *wave, unsigned int size, 
+	ALsizei freq);
+#define alutLoadWAVFile alutLoadWAVFile_CFH
+#define alutUnloadWAV alutUnloadWAV_CFH 
+#else
+void LoadOGG_CFH(char *filename, ALenum *format, void **wave, 
+	unsigned int *size, ALsizei *freq);
+void FreeOGG(ALenum format, void *wave, unsigned int size, 
+	ALsizei freq);
+#endif
+
+
+FILE *cfh_fopen(const char *filename, const char *mode);
+
+#endif
diff --git a/src/TGALoader.cpp b/src/TGALoader.cpp
new file mode 100644
index 0000000..3090764
--- /dev/null
+++ b/src/TGALoader.cpp
@@ -0,0 +1,83 @@
+/**> HEADER FILES <**/
+#include "TGALoader.h"
+
+
+/********************> LoadTGA() <*****/
+TGAImageRec*	LoadTGA( char *filename )
+{    
+	GLubyte			TGAheader[12]={0,0,2,0,0,0,0,0,0,0,0,0};	// Uncompressed TGA Header
+	GLubyte			TGAcompare[12];								// Used To Compare TGA Header
+	GLubyte			header[6];									// First 6 Useful Bytes From The Header
+	GLuint			bytesPerPixel;								// Holds Number Of Bytes Per Pixel Used In The TGA File
+	GLuint			imageSize;									// Used To Store The Image Size When Setting Aside Ram
+	GLuint			temp;										// Temporary Variable
+	GLuint			type = GL_RGBA;								// Set The Default GL Mode To RBGA (32 BPP)
+	TGAImageRec		*texture;
+	FILE			*file;
+	
+	// Open The TGA File
+	file = cfh_fopen( filename, "rb" );
+
+	if( ( file == NULL ) ||	// Does File Even Exist?
+		( fread( TGAcompare, 1, sizeof( TGAcompare ), file ) != sizeof( TGAcompare ) ) ||	// Are There 12 Bytes To Read?
+		( memcmp( TGAheader, TGAcompare, sizeof( TGAheader ) ) != 0 ) ||	// Does The Header Match What We Want?
+		( fread( header, 1, sizeof( header ), file ) != sizeof( header ) ) )// If So Read Next 6 Header Bytes
+	{
+		// If anything failed then close the file and return false
+		fclose( file );
+		return NULL;
+	}
+	
+	// Create a new RGBAImageRec
+	texture = ( TGAImageRec* )malloc( sizeof( TGAImageRec ) );
+	
+	// Determine the TGA width (highbyte*256+lowbyte) and height (highbyte*256+lowbyte)
+	texture->sizeX  = header[1] * 256 + header[0];
+	texture->sizeY = header[3] * 256 + header[2];
+    
+    // Make sure the height, width, and bit depth are valid
+ 	if(	( texture->sizeX <= 0 ) || ( texture->sizeY <= 0 ) || ( ( header[4] != 24 ) && ( header[4] != 32 ) ) )
+	{
+		// If anything failed then close the file, free up memory for the image, and return NULL
+		fclose( file );
+		free( texture );
+		return NULL;
+	}
+	
+	// Grab The TGA's Bits Per Pixel (24 or 32)
+	texture->bpp = header[4];							
+	bytesPerPixel = texture->bpp/8;	// Divide By 8 To Get The Bytes Per Pixel
+	
+	// Calculate The Memory Required For The TGA Data
+	imageSize = texture->sizeX * texture->sizeY * bytesPerPixel;
+	
+	// Reserve Memory To Hold The TGA Data
+	texture->data = ( GLubyte* )malloc( imageSize );		
+	
+	// Make sure the right amount of memory was allocated
+	if(	( texture->data == NULL ) || ( fread( texture->data, 1, imageSize, file ) != imageSize ) )
+	{
+		// Free up the image data if there was any
+		if( texture->data != NULL )
+			free( texture->data );
+
+		// If anything failed then close the file, free up memory for the image, and return NULL
+		fclose( file );
+		free( texture );
+		return NULL;
+	}
+	
+	// Loop Through The Image Data
+	for( GLuint i = 0; i < int( imageSize ); i += bytesPerPixel )
+	{
+		// Swaps The 1st And 3rd Bytes ('R'ed and 'B'lue)
+		temp = texture->data[i];					// Temporarily Store The Value At Image Data 'i'
+		texture->data[i] = texture->data[i + 2];	// Set The 1st Byte To The Value Of The 3rd Byte
+		texture->data[i + 2] = temp;				// Set The 3rd Byte To The Value In 'temp' (1st Byte Value)
+	}
+	
+	// Close The File
+	fclose( file );
+	
+	return texture;
+}
diff --git a/src/TGALoader.h b/src/TGALoader.h
new file mode 100644
index 0000000..83f4476
--- /dev/null
+++ b/src/TGALoader.h
@@ -0,0 +1,36 @@
+#ifdef OS9 
+#pragma once
+#endif
+
+#ifndef	_TGA_LOADER_H_
+#define	_TGA_LOADER_H_
+
+
+/**> HEADER FILES <**/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef OS9 
+#include "gl.h"
+#else
+#include <GL/gl.h>
+#endif
+
+#include "Support.h"
+
+/**> DATA STRUCTURES <**/
+typedef struct TGAImageRec
+{
+	GLubyte	*data;		// Image Data (Up To 32 Bits)
+	GLuint	bpp;		// Image Color Depth In Bits Per Pixel.
+	GLuint	sizeX;
+	GLuint	sizeY;
+}	TGAImageRec;
+
+
+
+/**> FUNCTION PROTOTYPES <**/
+TGAImageRec*	LoadTGA( char *filename );
+
+
+#endif
diff --git a/src/Text.cpp b/src/Text.cpp
new file mode 100644
index 0000000..2c2323a
--- /dev/null
+++ b/src/Text.cpp
@@ -0,0 +1,68 @@
+/**> HEADER FILES <**/
+#include "Text.h"
+#include "Textures.h"
+
+void Text::LoadFontTexture(char *fileName)
+{
+	FontTexture = loadTexture(fileName);
+}
+
+void Text::BuildFont()								// Build Our Font Display List
+{
+	float	cx;											// Holds Our X Character Coord
+	float	cy;											// Holds Our Y Character Coord
+	int loop;
+	
+	base=glGenLists(256);								// Creating 256 Display Lists
+	glBindTexture(GL_TEXTURE_2D, FontTexture);			// Select Our Font Texture
+	for (loop=0; loop<256; loop++)						// Loop Through All 256 Lists
+	{
+		cx=float(loop%16)/16.0f;						// X Position Of Current Character
+		cy=float(loop/16)/16.0f;						// Y Position Of Current Character
+
+		glNewList(base+loop,GL_COMPILE);				// Start Building A List
+			glBegin(GL_QUADS);							// Use A Quad For Each Character
+				glTexCoord2f(cx,1-cy-0.0625f+.001);			// Texture Coord (Bottom Left)
+				glVertex2i(0,0);						// Vertex Coord (Bottom Left)
+				glTexCoord2f(cx+0.0625f,1-cy-0.0625f+.001);	// Texture Coord (Bottom Right)
+				glVertex2i(16,0);						// Vertex Coord (Bottom Right)
+				glTexCoord2f(cx+0.0625f,1-cy-.001);			// Texture Coord (Top Right)
+				glVertex2i(16,16);						// Vertex Coord (Top Right)
+				glTexCoord2f(cx,1-cy-+.001);					// Texture Coord (Top Left)
+				glVertex2i(0,16);						// Vertex Coord (Top Left)
+			glEnd();									// Done Building Our Quad (Character)
+			glTranslated(10,0,0);						// Move To The Right Of The Character
+		glEndList();									// Done Building The Display List
+	}													// Loop Until All 256 Are Built
+}
+
+void Text::glPrint(GLint x, GLint y, char *string, int set, float size, float width, float height)	// Where The Printing Happens
+{
+	if (set>1)
+	{
+		set=1;
+	}
+	glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+	glBindTexture(GL_TEXTURE_2D, FontTexture);			// Select Our Font Texture
+	glDisable(GL_DEPTH_TEST);							// Disables Depth Testing
+	glDisable(GL_LIGHTING);
+	glEnable(GL_BLEND);
+	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+	glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
+	glPushMatrix();										// Store The Projection Matrix
+	glLoadIdentity();									// Reset The Projection Matrix
+	glOrtho(0,width,0,height,-100,100);						// Set Up An Ortho Screen
+	glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
+	glPushMatrix();										// Store The Modelview Matrix
+	glLoadIdentity();
+	glScalef(size,size,1);									// Reset The Modelview Matrix
+	glTranslated(x,y,0);								// Position The Text (0,0 - Bottom Left)
+	glListBase(base-32+(128*set));						// Choose The Font Set (0 or 1)
+	glCallLists(strlen(string),GL_BYTE,string);			// Write The Text To The Screen
+	glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
+	glPopMatrix();										// Restore The Old Projection Matrix
+	glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
+	glPopMatrix();										// Restore The Old Projection Matrix
+	glEnable(GL_DEPTH_TEST);							// Enables Depth Testing
+	glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+}
diff --git a/src/Text.h b/src/Text.h
new file mode 100644
index 0000000..99e8a6c
--- /dev/null
+++ b/src/Text.h
@@ -0,0 +1,32 @@
+#ifndef _TEXT_H_
+#define _TEXT_H_
+
+
+/**> HEADER FILES <**/
+#include "Quaternions.h"
+#ifdef OS9 
+#include <gl.h>
+#include <glu.h>
+#else
+#include <GL/gl.h>
+#include <GL/glu.h>
+#endif
+#include "Files.h"
+#include "Quaternions.h"
+
+class Text{
+	public:
+		GLuint FontTexture;
+		GLuint base;
+		
+		void LoadFontTexture(char *fileName);
+		void BuildFont();
+		void glPrint(GLint x, GLint y, char *string, int set, float size, float width, float height);
+		
+		~Text(){
+			glDeleteTextures( 1, (const GLuint *)FontTexture );
+		}
+};
+
+#endif
+
diff --git a/src/Textures.cpp b/src/Textures.cpp
new file mode 100644
index 0000000..0f829dc
--- /dev/null
+++ b/src/Textures.cpp
@@ -0,0 +1,73 @@
+/*
+(c) 2008 Victor "ErV" Eremin, Voronezh, Russia.
+mailto: ErV2005@rambler.ru, erv@box.vsi.ru
+for non-ncommercial use only
+*/
+#include "Textures.h"
+#include <GL/glu.h>
+#include <SDL/SDL_image.h>
+#include <stdio.h>
+
+GLuint loadTexture(const char* filename_, GLenum minFilter, GLenum magFilter, bool mipmaps){
+	char filename[1024];
+	strcpy(filename, filename_+1);
+	while(true){
+		char *c = strchr(filename, ':');
+		if (!c) break;
+		*c = '/';
+	}
+	GLuint tex = 0;
+	glGenTextures(1, &tex);
+	glBindTexture(GL_TEXTURE_2D, tex);
+	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
+
+	SDL_Surface *surface = IMG_Load(filename);
+	if (!surface){
+		fprintf(stderr, "couldn't load file %s!\n", filename);
+		return 0;
+	}
+
+	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+	GLenum format = GL_RGBA;
+	int numColors = surface->format->BytesPerPixel;
+	if (surface){
+		switch (numColors){
+			case (4):{
+				if (surface->format->Rmask == 0x000000ff)
+                        format = GL_RGBA;
+                else
+                        format = GL_BGRA;
+				break;
+			};
+			case (3):{
+				if (surface->format->Rmask == 0x000000ff)
+                        format = GL_RGB;
+                else
+                        format = GL_BGR;
+			};
+		};
+		
+		//well, our textures are upside down. Fixing it here.
+		Uint32 bytesPerRow = surface->format->BytesPerPixel*surface->w;
+		char * buf = new char[bytesPerRow];
+		char* p = (char*)surface->pixels;
+		for (Uint32 i = 0; i < surface->h/2; i++){
+			Uint32 offset1 = i*bytesPerRow;
+			Uint32 offset2 = (surface->h - i - 1)*bytesPerRow;
+			memcpy(buf, &p[offset1], bytesPerRow);
+			memcpy(&p[offset1], &p[offset2], bytesPerRow);
+			memcpy(&p[offset2], buf, bytesPerRow);
+		}
+		delete[] buf;
+		
+		glTexImage2D(GL_TEXTURE_2D, 0, numColors, surface->w, surface->h, 0, format, GL_UNSIGNED_BYTE, surface->pixels);
+		if (mipmaps)
+		    gluBuild2DMipmaps(GL_TEXTURE_2D, format,  surface->w, surface->h, format, GL_UNSIGNED_BYTE, surface->pixels);
+	}
+	
+	delete surface;
+	return tex;
+}
+
diff --git a/src/Textures.h b/src/Textures.h
new file mode 100644
index 0000000..6deeb1e
--- /dev/null
+++ b/src/Textures.h
@@ -0,0 +1,14 @@
+/*
+(c) 2008 Victor "ErV" Eremin (Voronezh, Russia)
+mailto:ErV2005@rambler.ru, erv@box.vsi.ru
+for non-commercial use only
+*/
+#ifndef TEXTURES_H
+#define TEXTURES_H
+
+#include <SDL/SDL.h>
+#include <GL/gl.h>
+
+GLuint loadTexture(const char* filename, GLenum minFilter = GL_LINEAR, GLenum magFilter = GL_LINEAR, bool mipmaps = true);
+
+#endif
diff --git a/src/Timer.cpp b/src/Timer.cpp
new file mode 100644
index 0000000..80cc5f9
--- /dev/null
+++ b/src/Timer.cpp
@@ -0,0 +1,28 @@
+/**> HEADER FILES <**/
+#include <string.h>
+#include "Timer.h"				
+#include "Support.h"
+
+
+/********************> Timer <*****/
+void TimerInit(timer* theTimer)
+{
+	UnsignedWide			ms;								
+
+	Microseconds(&ms);									
+	 
+	memset(theTimer, 0, sizeof(timer));						
+
+	theTimer->mm_timer_start	= ms.lo;						
+	theTimer->mm_timer_elapsed	= theTimer->mm_timer_start;			
+}
+
+float TimerGetTime(timer* theTimer)
+{
+	UnsignedWide			ms;
+	
+	Microseconds(&ms);
+	
+	
+	return( (float) (ms.lo - theTimer->mm_timer_start) * 1000.0f);
+}
diff --git a/src/Timer.h b/src/Timer.h
new file mode 100644
index 0000000..c0c99a1
--- /dev/null
+++ b/src/Timer.h
@@ -0,0 +1,18 @@
+#ifndef _TIMER_H_
+#define _TIMER_H_
+
+
+/**> HEADER FILES <**/
+class timer			 							
+{
+	public:
+  	unsigned long mm_timer_start;			
+  	unsigned long mm_timer_elapsed;					
+};
+
+
+void TimerInit(timer* theTimer);
+float TimerGetTime(timer* theTimer);
+
+#endif
+