diff --git a/Source/Builtins.h b/Source/Builtins.h
old mode 100644
new mode 100755
index 7830a2fe..8c48eff4
--- a/Source/Builtins.h
+++ b/Source/Builtins.h
@@ -184,6 +184,7 @@ Available options:
 #define FTE_GFX_REMAPSHADER /* With the raw power of stuffcmds, the r_remapshader console command is exposed! This mystical command can be used to remap any shader to another. Remapped shaders that specify $diffuse etc in some form will inherit the textures implied by the surface. */
 #define FTE_ISBACKBUFFERED /* Allows you to check if a client has too many reliable messages pending. */
 #define FTE_MEMALLOC /* Allows dynamically allocating memory. Use pointers to access this memory. Memory will not be saved into saved games. */
+#define FTE_MEDIA_AVI /* playfilm command supports avi files. */
 #define FTE_MEDIA_CIN /* playfilm command supports q2 cin files. */
 #define FTE_MEDIA_ROQ /* playfilm command supports q3 roq files. */
 #define FTE_MULTIPROGS /* Multiple progs.dat files can be loaded inside the same qcvm. Insert new ones with addprogs inside the 'init' function, and use externvalue+externset to rewrite globals (and hook functions) to link them together. Note that the result is generally not very clean unless you carefully design for it beforehand. */
@@ -657,6 +658,7 @@ void() initents;	/* Part of FTE_MULTIPROGS. Called after fields have been finali
 void() m_init;
 void() m_shutdown;
 void(vector screensize) m_draw;	/* Provides the menuqc with a chance to draw. Will be called even if the menu does not have focus, so be sure to avoid that. COMPAT: screensize is not provided in DP. */
+void(vector screensize) m_drawloading;	/* Additional drawing function to draw loading screen overlays. */
 void(float scan, float chr) m_keydown;
 void(float scan, float chr) m_keyup;
 void(float wantmode) m_toggle;
@@ -1143,8 +1145,6 @@ const float RF_EXTERNALMODEL = 2;	/* Specifies that this entity should be displa
 #if defined(CSQC) || defined(MENU)
 const float RF_DEPTHHACK = 4;	/* Hacks the depth values such that the entity uses depth values as if it were closer to the screen. This is useful when combined with viewmodels to avoid weapons poking in to walls. */
 const float RF_ADDITIVE = 8;	/* Shaders from this entity will temporarily be hacked to use an additive blend mode instead of their normal blend mode. */
-#endif
-#ifdef CSQC
 const float RF_USEAXIS = 16;	/* The entity will be oriented according to the current v_forward+v_right+v_up vector values instead of the entity's .angles field. */
 const float RF_NOSHADOW = 32;	/* This entity will not cast shadows. Often useful on view models. */
 const float RF_FRAMETIMESARESTARTTIMES = 64;	/* Specifies that the frame1time, frame2time field are timestamps (denoting the start of the animation) rather than time into the animation. */
@@ -1621,6 +1621,16 @@ float(string) stof = #81; /* Part of FRIK_FILE, FTE_STRINGS, QW_ENGINE, ZQ_QC_ST
 void(vector where, float set) multicast = #82; /*
 		Once the MSG_MULTICAST network message buffer has been filled with data, this builtin is used to dispatch it to the given target, filtering by pvs for reduced network bandwidth. */
 
+#endif
+#if defined(CSQC) || defined(SSQC)
+string(float style, optional vector rgb) getlightstyle = #0:getlightstyle; /*
+		Obtains the light style string for the given style. */
+
+vector(float style) getlightstylergb = #0:getlightstylergb; /*
+		Obtains the current rgb value of the specified light style. In csqc, this is correct with regard to the current frame, while ssqc gives no guarentees about time and ignores client cvars. Note: use getlight if you want the actual light value at a point. */
+
+#endif
+#ifdef SSQC
 void(float style, float val, optional vector rgb) lightstylestatic = #5; /*
 		Sets the lightstyle to an explicit numerical level. From Hexen2. */
 
@@ -1974,11 +1984,11 @@ float(float modidx, float framenum) frameduration = #277; /* Part of FTE_CSQC_SK
 void(float modidx, float framenum, __inout float basetime, float targettime, void(float timestamp, int code, string data) callback) processmodelevents = #0:processmodelevents; /*
 		Calls a callback for each event that has been reached. Basetime is set to targettime. */
 
-float(float modidx, float framenum, __inout float basetime, float targettime, __inout int code, __inout string data) getnextmodelevent = #0:getnextmodelevent; /*
+float(float modidx, float framenum, __inout float basetime, float targettime, __out int code, __out string data) getnextmodelevent = #0:getnextmodelevent; /*
 		Reports the next event within a model's animation. Returns a boolean if an event was found between basetime and targettime. Writes to basetime,code,data arguments (if an event was found, basetime is set to the event's time, otherwise to targettime).
 		WARNING: this builtin cannot deal with multiple events with the same timestamp (only the first will be reported). */
 
-float(float modidx, float framenum, int eventidx, __inout float timestamp, __inout int code, __inout string data) getmodeleventidx = #0:getmodeleventidx; /*
+float(float modidx, float framenum, int eventidx, __out float timestamp, __out int code, __out string data) getmodeleventidx = #0:getmodeleventidx; /*
 		Reports an indexed event within a model's animation. Writes to timestamp,code,data arguments on success. Returns false if the animation/event/model was out of range/invalid. Does not consider looping animations (retry from index 0 if it fails and you know that its a looping animation). This builtin is more annoying to use than getnextmodelevent, but can be made to deal with multiple events with the exact same timestamp. */
 
 #endif
diff --git a/Source/Client/Entities.c b/Source/Client/Entities.c
index 83f2c898..2cdcd2c1 100755
--- a/Source/Client/Entities.c
+++ b/Source/Client/Entities.c
@@ -57,14 +57,6 @@ void CSQC_Ent_Update( float flIsNew ) {
 		}
 		
 		setorigin( self, self.origin );
-	} else if ( fEntType == ENT_AMBIENTSOUND ) {
-		self.origin_x = readcoord();
-		self.origin_y = readcoord();
-		self.origin_z = readcoord();
-		
-		setorigin( self, self.origin );
-		
-		CSQC_ambient_generic( readstring(), readfloat(), readbyte() );
 	} else if ( fEntType == ENT_SPRITE ) {
 		self.origin_x = readcoord();
 		self.origin_y = readcoord();
diff --git a/Source/Client/HUD.c b/Source/Client/HUD.c
old mode 100644
new mode 100755
index 6e3c572d..aa4f71c2
--- a/Source/Client/HUD.c
+++ b/Source/Client/HUD.c
@@ -406,11 +406,6 @@ void HUD_Draw( void ) {
 	vHUDColor = autocvar_con_color * ( 1 / 255 );
 	
 	HUD_DrawTimer();
-	
-	if( getplayerkeyvalue( player_localnum, "*spectator" ) == "1" ) {
-		return;
-	}
-	
 	HUD_DrawRadar();
 	HUD_DrawHealth();
 	HUD_DrawArmor();
diff --git a/Source/Client/progs.src b/Source/Client/progs.src
index b97cc18c..fff42162 100755
--- a/Source/Client/progs.src
+++ b/Source/Client/progs.src
@@ -44,7 +44,6 @@ Defs.h
 ../Shared/Radio.c
 ../Shared/Equipment.c
 ../Shared/Animations.c
-../Server/AmbientSound.c
 
 Player.c
 View.c
diff --git a/Source/Menu/Defs.h b/Source/Menu/Defs.h
new file mode 100755
index 00000000..b0b8918a
--- /dev/null
+++ b/Source/Menu/Defs.h
@@ -0,0 +1,97 @@
+/*
+OpenCS Project
+Copyright (C) 2016, 2017 Marco "eukara" Hladik
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+#define KEY_UNKNOWN 		-1
+#define KEY_GAME 			0
+#define KEY_MENU 			2
+#define KEY_MENU_GRABBED 	3
+
+#define TARGET_MENU 	1
+#define TARGET_CLIENT 	2
+
+var vector vVideoAspect;
+var vector vVideoSize;
+var vector vMenuSize;
+var int iMenuPadding;
+
+var vector vMousePos;
+var float fInputKeyCode;
+var float fInputKeyASCII;
+var float fInputKeyDown;
+var float fMouseClick;
+
+var int iMenuActive;
+
+var float fMenuScale;
+
+float frametime;
+float fLastTime;
+
+/*
+=================
+gcd_r
+
+Returns the greatest common denominator
+=================
+*/
+int gcd_r( float a, float b ) {
+  if ( a == 0 ) { 
+	  return b;
+  }
+  
+  return gcd_r( floor( b%a ), a );
+}
+
+/*
+=================
+Menu_Util_GetAspect
+
+Returns the aspect ratio for the current mode.
+=================
+*/
+vector Menu_Util_GetAspect( vector vResolution ) {
+	int r = gcd_r( vResolution_x, vResolution_y );
+	return [ vResolution_x/r, vResolution_y/r ];
+}
+
+/*
+=================
+Menu_Util_GetAspectSize
+
+Returns the menu size for the given ratio.
+=================
+*/
+vector Menu_Util_GetMenuSize( vector vAspect ) {
+	float fScale = ( vAspect_x / vAspect_y );
+	
+		return [ rint( 480 * fScale ), 480 ];
+	
+}
+
+/*
+=================
+Menu_Util_GetMenuPadding
+
+Returns the padding size for the current ratio.
+=================
+*/
+int Menu_Util_GetMenuPadding( void ) {
+	return ( vMenuSize_x - 640 ) / 2;
+}
diff --git a/Source/Menu/Draw.c b/Source/Menu/Draw.c
new file mode 100755
index 00000000..65b494fa
--- /dev/null
+++ b/Source/Menu/Draw.c
@@ -0,0 +1,175 @@
+/*
+OpenCS Project
+Copyright (C) 2016, 2017 Marco "eukara" Hladik
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+int iMenuStage;
+float fFadeAlpha;
+int iButtonSelected;
+
+void drawmenupic( vector vPosition, string sPic, vector vSize, vector vRGB, float fAlpha, float fDrawflag ) {
+	vSize = vSize * fMenuScale;
+	vPosition = vPosition * fMenuScale;
+	drawpic( vPosition + [ iMenuPadding, 0, 0 ], sPic, vSize, vRGB, fAlpha, fDrawflag );
+}
+
+void drawmenustring( vector vPosition, string sText, vector vSize, vector vRGB, float fAlpha, float fDrawflag ) {
+	vSize = vSize * fMenuScale;
+	vPosition = vPosition * fMenuScale;
+	drawstring( vPosition + [ iMenuPadding, 0, 0 ], sText, vSize, vRGB, fAlpha, fDrawflag );
+}
+
+void m_mainbutton( vector vPos, string sText, int iItem, void() vFunc) {
+	static float fSelectionAlpha;
+	
+	if ( Menu_InputCheckMouse( vPos, '182 14' ) == TRUE ) {
+		if ( iButtonSelected != iItem ) {
+			iButtonSelected = iItem;
+			fSelectionAlpha = 0.0f;
+		}
+	}
+
+	if ( iButtonSelected == iItem ) {
+		if ( fMouseClick == TRUE ) {
+			drawmenustring( vPos, sText, '14 14', '1 0.5 0', fSelectionAlpha, 0 );
+			vFunc();
+			fMouseClick = FALSE;
+		} else {
+			drawmenustring( vPos, sText, '14 14', '1 1 1', 1 - fSelectionAlpha, 0 );
+			drawmenustring( vPos, sText, '14 14', '0.3 0.3 1', fSelectionAlpha, 0 );
+		}
+	} else {
+		drawmenustring( vPos, sText, '14 14', '1 1 1', fFadeAlpha, 0 );
+	}
+	
+	if ( fSelectionAlpha < 1.0f ) {
+		fSelectionAlpha += frametime;
+		if ( fSelectionAlpha > 1.0f ) {
+			fSelectionAlpha = 1.0f;
+		}
+	}
+}
+
+void m_button_findserver( void ) {
+	
+};
+
+void m_button_createserver( void ) {
+	localcmd( "map cs_office\n" );
+};
+
+void m_button_options( void ) {
+	
+};
+
+void m_button_replays( void ) {
+	
+};
+
+void m_button_quit( void ) {
+	localcmd( "quit\n" );
+};
+
+void m_drawback( void ) {
+	if ( clientstate() == 2 ) {
+		drawfill( '0 0', vVideoSize, '0 0 0', 0.75f );
+	} else {
+		drawmenupic( '0 0 0', "gfx/menu/back1", '720 480', '1 1 1', 1.0f, 0 );
+		drawpic( '0 0 0', "menu_static", vVideoSize, '1 1 1', 1.0f, 0 );
+		drawmenupic( '0 0 0', "gfx/menu/back2", '720 480', '1 1 1', 1.0f, 0 );
+	}
+}
+
+void m_draw( vector vScreenSize ) {
+	if ( iMenuActive == FALSE ) {
+		return;
+	}
+	
+	// we have to create frametime ourselves because menuqc is primitive
+	frametime = ( time - fLastTime );
+	fLastTime = time;
+	
+	// only update the videostuff if it's actually worth it
+	if ( vVideoSize != vScreenSize ) {
+		fFadeAlpha = 0.0f;
+		vVideoSize = vScreenSize;
+		vVideoAspect = Menu_Util_GetAspect( vVideoSize );
+		vMenuSize = Menu_Util_GetMenuSize( vVideoAspect );
+		iMenuPadding = Menu_Util_GetMenuPadding();
+		fMenuScale = vVideoSize_y / vMenuSize_y;
+	}
+	
+	if ( clientstate() != 2 ) {
+		drawfill( '0 0', vVideoSize, '0 0 0', 1.0f );
+	}
+	
+	// for weird Android peeps
+	if ( vVideoSize_x < vVideoSize_y ) {
+		drawstring( '45 105', "FreeCS is designed for", '16 16', '1 1 1', 1.0f, 0 );
+		drawstring( '45 125', "landscape mode. Please", '16 16', '1 1 1', 1.0f, 0 ); 
+		drawstring( '45 145', "Switch the orientation.", '16 16', '1 1 1', 1.0f, 0 );
+		return;
+	}
+	
+	if ( time < 5 ) {
+		iMenuStage = 0;
+		drawmenustring( '45 45', "FreeCS (c) 2016, 2017", '16 16', '1 1 1', fFadeAlpha, 0 );
+		drawmenustring( '45 85', "Note that FreeCS is not affiliated", '16 16', '1 1 1', fFadeAlpha, 0 ); 
+		drawmenustring( '45 105', "with Steam or Valve.", '16 16', '1 1 1', fFadeAlpha, 0 );
+		drawmenustring( '45 125', "The source code for this is released", '16 16', '1 1 1', fFadeAlpha, 0 ); 
+		drawmenustring( '45 145', "under the GPL v2.", '16 16', '1 1 1', fFadeAlpha, 0 );
+		drawmenustring( '45 185', "FreeCS requires the content from:", '16 16', '1 1 1', fFadeAlpha, 0 );
+		drawmenustring( '45 205', "Counter-Strike 1.5", '16 16', '1 1 1', fFadeAlpha, 0 );
+		drawmenustring( '45 225', "Half-Life", '16 16', '1 1 1', fFadeAlpha, 0 );
+		drawmenustring( '45 265', "Please see visit:", '16 16', '1 1 1', fFadeAlpha, 0 );
+		drawmenustring( '45 285', "eukara.github.io/FreeCS", '16 16', '1 1 1', fFadeAlpha, 0 );
+		drawmenustring( '45 325', "Developed by Marco Hladik", '16 16', '1 1 1', fFadeAlpha, 0 );
+	} else if ( time < 8 ) {
+		if ( iMenuStage == 0 ) {
+			fFadeAlpha = 0.0f;
+			iMenuStage = 1;
+		}
+		
+		m_drawback();
+		
+		if ( fFadeAlpha < 1.0f ) {
+			drawfill( '0 0', vScreenSize, '0 0 0', 1 - fFadeAlpha );
+		}
+	} else {
+		if ( iMenuStage == 1 ) {
+			fFadeAlpha = 0.0f;
+			iMenuStage = 2;
+		}
+		
+		m_drawback();
+		drawmenupic( '25 145 0', "gfx/menu/freecs", '236 43', '1 1 1', fFadeAlpha, 0 );
+		
+		m_mainbutton( '430 300', "  FIND SERVER", 1, m_button_findserver );
+		m_mainbutton( '430 324', "CREATE SERVER", 2, m_button_createserver );
+		m_mainbutton( '430 348', "      OPTIONS", 3, m_button_options);
+		m_mainbutton( '430 372', "      REPLAYS", 4, m_button_replays );
+		m_mainbutton( '430 396', "         QUIT", 5, m_button_quit );
+	}
+	
+	if ( fFadeAlpha < 1.0f ) {
+		fFadeAlpha += frametime * 0.5;
+		if ( fFadeAlpha > 1.0f ) {
+			fFadeAlpha = 1.0f;
+		}
+	}
+}
diff --git a/Source/Menu/Init.c b/Source/Menu/Init.c
new file mode 100755
index 00000000..e9350117
--- /dev/null
+++ b/Source/Menu/Init.c
@@ -0,0 +1,30 @@
+/*
+OpenCS Project
+Copyright (C) 2016, 2017 Marco "eukara" Hladik
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+void m_init( void ) {
+	precache_pic( "gfx/menu/back1" );
+	precache_pic( "gfx/menu/back2" );
+	precache_pic( "menu_static" );
+	precache_pic( "gfx/menu/freecs" );
+}
+
+void m_shutdown( void ) {
+	
+}
diff --git a/Source/Menu/Input.c b/Source/Menu/Input.c
new file mode 100755
index 00000000..66c5b136
--- /dev/null
+++ b/Source/Menu/Input.c
@@ -0,0 +1,107 @@
+/*
+OpenCS Project
+Copyright (C) 2016, 2017 Marco "eukara" Hladik
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+int Menu_InputCheckMouse( vector vPos, vector vReg ) {
+	vector vSMins, vSMaxs;
+	
+	vReg = vReg * fMenuScale;
+	vPos = vPos * fMenuScale + [ iMenuPadding, 0, 0 ];
+		
+	vSMins = vPos;
+	vSMaxs = vPos;
+	vSMins_x = vPos_x;
+	vSMaxs_y = vPos_y - 1;
+
+	vSMaxs_x = vPos_x + vReg_x;
+	vSMaxs_y = vPos_y + vReg_y;
+
+	if ( vMousePos_x >= vSMins_x && vMousePos_x <= vSMaxs_x ) {
+		if ( vMousePos_y >= vSMins_y && vMousePos_y <= vSMaxs_y ) {
+			return TRUE;
+		}
+	}
+	
+	return FALSE;
+}
+
+float Menu_InputEvent( float fEventType, float fKey, float fCharacter, float fDeviceID ) {
+	if ( fEventType == IE_KEYDOWN ) {
+		if ( fKey == K_MOUSE1 ) {
+			fMouseClick = 1;
+		} else {
+			if ( fKey == K_ESCAPE ) {
+				m_toggle( 0 );
+			}
+		
+			fInputKeyDown = 1;
+		}
+		
+		fInputKeyCode = fKey;
+		fInputKeyASCII = fCharacter;
+	} else if ( fEventType == IE_KEYUP ) {
+		if ( fKey == K_MOUSE1 ) {
+			fMouseClick = 0;
+		} else {
+			fInputKeyDown = 0;
+		}
+		
+		fInputKeyCode = 0;
+		fInputKeyASCII = 0;
+	} else if ( fEventType == IE_MOUSEABS ) {
+		vMousePos_x = fKey;
+		vMousePos_y = fCharacter;
+	} 
+	
+	return TRUE;
+}
+
+void m_display( void ) {
+	iMenuActive = TRUE;
+	setkeydest( KEY_MENU );
+	setmousetarget( TARGET_MENU );
+	setcursormode( TRUE, "gfx/cursor" );
+}
+
+void m_hide( void ) {
+	iMenuActive = FALSE;
+	setkeydest( KEY_GAME );
+	setmousetarget( TARGET_CLIENT );
+	setcursormode( FALSE );
+}
+
+void m_toggle( float fMode ) {
+	if ( fMode == FALSE ) {
+		m_hide();
+	} else {
+		m_display();
+	}
+}
+
+float m_consolecommand( string sCMD ) {
+	tokenize( sCMD );
+	switch ( argv( 0 ) ) {
+		case "togglemenu":
+		m_display( );
+		return TRUE;
+		break;
+		
+	}
+	return FALSE;
+}
diff --git a/Source/Menu/progs.src b/Source/Menu/progs.src
old mode 100644
new mode 100755
index 09afed6a..ec7fde49
--- a/Source/Menu/progs.src
+++ b/Source/Menu/progs.src
@@ -1,9 +1,14 @@
 #pragma target fte
 
-#pragma progs_dat  "../../opencs/menu.dat"
+#pragma progs_dat  "../../freecs/menu.dat"
+
+#define MENU
 
 #includelist
 ../Builtins.h
-../Globals.h
 ../Math.h
+Defs.h
+Init.c
+Input.c
+Draw.c
 #endlist
diff --git a/Source/Server/AmbientSound.c b/Source/Server/AmbientSound.c
old mode 100644
new mode 100755
index aaf36841..20f5e742
--- a/Source/Server/AmbientSound.c
+++ b/Source/Server/AmbientSound.c
@@ -40,18 +40,12 @@ Not Toggled (32) - 	Older FGDs show this as Not Looped.
       				Must be left unchecked for looping sound files. 
       				Note that actual looping depends purely on cue points defined in the .wav file (see notes).
 */
-#ifdef SSQC
+
 .float pitch;
 void ambient_generic( void ) {
 	static float ambient_generic_send( entity ePEnt, float fChanged ) {
-		WriteByte( MSG_ENTITY, ENT_AMBIENTSOUND ); // Identifier
-		WriteCoord( MSG_ENTITY, self.origin_x );
-		WriteCoord( MSG_ENTITY, self.origin_y );
-		WriteCoord( MSG_ENTITY, self.origin_z );
-		WriteString( MSG_ENTITY, self.message );
-		WriteFloat( MSG_ENTITY, self.health );
-		WriteByte( MSG_ENTITY, self.style );
-		return TRUE;
+		sound( self, CHAN_VOICE, self.message, self.health, self.style, self.pitch, 0, SOUNDFLAG_FORCELOOP );
+		return FALSE;
 	}
 	static void ambient_generic_use( void ) {
 		sound( self, CHAN_VOICE, self.message, self.health, self.style, self.pitch );
@@ -94,7 +88,7 @@ void ambient_generic( void ) {
 		self.vUse = ambient_generic_use;
 	} else {
 		self.noise = self.message; // Needed later for resuming
-		self.pvsflags = PVSF_NOREMOVE | PVSF_IGNOREPVS;
+		self.pvsflags = PVSF_USEPHS;
 		self.vUse = ambient_generic_useloop;
 		self.SendEntity = ambient_generic_send;
 		self.state = TRUE;
@@ -102,8 +96,3 @@ void ambient_generic( void ) {
 	
 	Entities_InitRespawnable( ambient_generic_respawn );
 }
-#else 
-void CSQC_ambient_generic( string sSample, float fVolume, float fAttenuation ) {
-	sound( self, CHAN_VOICE, sSample, fVolume, fAttenuation );
-}
-#endif
diff --git a/Source/Server/EntHostage.c b/Source/Server/EntHostage.c
index 7bdd2d1c..cfb2dbaa 100755
--- a/Source/Server/EntHostage.c
+++ b/Source/Server/EntHostage.c
@@ -41,7 +41,7 @@ entity hostage_waypoint( void ) {
 	setsize( ePoint, self.mins, self.maxs );
 	ePoint.classname = "remove_me";
 	ePoint.movetype = MOVETYPE_TOSS;
-//	setmodel( ePoint, "models/chick.mdl" ); // Visual feedback...
+	setmodel( ePoint, "models/chick.mdl" ); // Visual feedback...
 	return ePoint;
 }
 
@@ -133,7 +133,7 @@ void hostage_physics( void ) {
 		vector vEndAngle = vectoangles( self.eTargetPoint.origin - self.origin );
 		
 		// Slowly turn towards target
-		float fTurn = Math_LerpAngle( self.angles_y, vEndAngle_y, frametime );
+		float fTurn = Math_LerpAngle( self.angles_y, vEndAngle_y, frametime * 4 );
 		self.angles_y += fTurn;
 		
 		// Is the waypoint close? if so, remove and go set the next one!
@@ -153,7 +153,6 @@ void hostage_physics( void ) {
 		
 		// Don't switch states so often
 		if( self.fAttackFinished < time ) {
-			
 			// Here we check the distance of us and the player, then choosing if we should walk/run etc.
 			float fDist = vlen( self.eUser.origin - self.origin );
 			
@@ -183,17 +182,6 @@ void hostage_physics( void ) {
 			}
 		}
 		
-		// Decide speed and stuff
-		if ( self.style == HOSTAGE_WALK ) {
-			self.frame = 0;
-			input_movevalues = '110 0 0';
-		} else if ( self.style == HOSTAGE_RUN ) {
-			input_movevalues = '220 0 0';
-			self.frame = 2;
-		} else {
-			input_movevalues = '0 0 0';
-		}
-		
 		if ( fTurn > 0.01 ) {
 			self.frame = 5;
 		} else if ( fTurn < -0.01 ){
@@ -201,9 +189,23 @@ void hostage_physics( void ) {
 		} else {
 			self.frame = 13;
 		}
+		
+		// Decide speed and stuff
+		if ( self.style == HOSTAGE_WALK ) {
+			self.frame = 0;
+			input_movevalues_x = 110;
+		} else if ( self.style == HOSTAGE_RUN ) {
+			input_movevalues_x = 220;
+			self.frame = 2;
+		} else {
+			input_movevalues_x = 0;
+		}
 	}
-
+	
+	input_timelength = frametime;
+	self.movetype = MOVETYPE_WALK;
 	runstandardplayerphysics( self );
+	self.movetype = MOVETYPE_NONE;
 }
 
 /*
@@ -218,7 +220,7 @@ void hostage_entity( void ) {
 	static void hostage_entity_respawn( void ) {
 		setorigin( self, self.origin );
 		self.solid = SOLID_SLIDEBOX;
-		self.movetype = MOVETYPE_WALK;
+		self.movetype = MOVETYPE_NONE;
 		setmodel( self, self.model );
 		setsize( self, VEC_HULL_MIN + '0 0 36', VEC_HULL_MAX + '0 0 36' );
 		self.customphysics = hostage_physics;
diff --git a/Source/Server/EnvObjects.c b/Source/Server/EnvObjects.c
old mode 100644
new mode 100755
index 97c779b4..3a7e6204
--- a/Source/Server/EnvObjects.c
+++ b/Source/Server/EnvObjects.c
@@ -139,3 +139,55 @@ void env_render( void ) {
 	Entities_RenderSetup();
 	self.vUse = env_render_use;
 }
+
+/*
+=================
+env_explosion
+
+This entity creates any combination of fireball, 
+smoke, sparks, decals and sound, also known as an explosion.
+
+Attributes:
+Name (targetname) - Property used to identify entities.
+Magnitude (iMagnitude) - The size of the explosion. 100 is average.
+
+Flags:
+No Damage (1) - Explosion won't cause any damage.
+Repeatable (2) - Entity can be triggered more than once.
+No Fireball (4) - There is no orange fireball. It won't look much like an explosion...
+No Smoke (8) - Creates a pollution-free explosion.
+No Decals (16) - No scorch marks are left behind.
+No Sparks (32) - No sparks fly out.
+
+Notes:
+It's possible to create a similar effect with a combination of other entities, 
+but it wouldn't be much fun, so this quick and easy one is here instead!
+=================
+*/
+.int iMagnitude;
+
+enumflags {
+	ENVEXPLO_NODAMAGE,
+	ENVEXPLO_REPEATABLE,
+	ENVEXPLO_NOBALL,
+	ENVEXPLO_NOSMOKE,
+	ENVEXPLO_NODECAL,
+	ENVEXPLO_NOSPARKS
+};
+
+// TODO: Finish cosmetic effects
+void env_explosion( void ) {
+	static void env_explosion_use( void ) {
+		te_explosion( self.origin );
+		
+		if ( !( self.spawnflags & ENVEXPLO_NODAMAGE ) ) {
+			Damage_Radius( self.origin, self, 500, self.iMagnitude );
+		}
+		if ( !( self.spawnflags & ENVEXPLO_REPEATABLE ) ) {
+			self.vUse = __NULL__;
+			remove( self );
+		}
+	}
+	
+	self.vUse = env_explosion_use;
+}
diff --git a/freecs/csprogs.dat b/freecs/csprogs.dat
index e596c5ea..ec1dc3d5 100644
Binary files a/freecs/csprogs.dat and b/freecs/csprogs.dat differ
diff --git a/freecs/gfx/menu/back1.tga b/freecs/gfx/menu/back1.tga
new file mode 100755
index 00000000..80c96822
Binary files /dev/null and b/freecs/gfx/menu/back1.tga differ
diff --git a/freecs/gfx/menu/back2.tga b/freecs/gfx/menu/back2.tga
new file mode 100755
index 00000000..9408315c
Binary files /dev/null and b/freecs/gfx/menu/back2.tga differ
diff --git a/freecs/gfx/menu/freecs.tga b/freecs/gfx/menu/freecs.tga
new file mode 100755
index 00000000..b86ee629
Binary files /dev/null and b/freecs/gfx/menu/freecs.tga differ
diff --git a/freecs/gfx/menu/static.tga b/freecs/gfx/menu/static.tga
new file mode 100755
index 00000000..60b8748c
Binary files /dev/null and b/freecs/gfx/menu/static.tga differ
diff --git a/freecs/menu.dat b/freecs/menu.dat
new file mode 100755
index 00000000..424cefa4
Binary files /dev/null and b/freecs/menu.dat differ
diff --git a/freecs/particles/default.cfg b/freecs/particles/default.cfg
old mode 100644
new mode 100755
index 56f742f4..1c169d4c
--- a/freecs/particles/default.cfg
+++ b/freecs/particles/default.cfg
@@ -125,3 +125,62 @@ r_part decal_glass
 	randomvel 0 0 0
 	rotationstart -180 180
 }
+
+/////////////////////////////////////////////////
+//rocket explosions
+r_part ember
+{
+	count 1
+	texture "particles/fteparticlefont.tga"
+	tcoords 97 97 191 191 256
+	rgb 255 128 76
+	alpha 0
+	scale 15
+	scalefactor 1
+	friction 8
+	gravity 50
+	die 1
+	blend add
+	randomvel 5
+	veladd 1
+	rampmode delta
+	ramp 0	0	0	-0.5	0
+	ramp 0	0	0	0.1	0
+	ramp 0	0	0	0.1	0
+	ramp 0	0	0	0.1	0
+	ramp 0	0	0	0.1	0
+	ramp 0	0	0	0.1	0
+}
+
+//the bits that fly off
+r_part expgib
+{
+	cliptype expgib
+	texture "particles/fteparticlefont.tga"
+	tcoords 97 97 191 191 256
+	alpha 0
+	count	16
+	die 1
+	randomvel 128
+	gravity 50
+	friction 2
+	emit ember
+	emitinterval 0.01
+	spawnmode circle
+}
+
+//the heart of the explosion
+r_part te_explosion
+{
+	texture "particles/fteparticlefont.tga"
+	tcoords 97 97 191 191 256
+	count	1
+	scale 200
+	scalefactor 1
+	die 1
+	rgb 255 128 76
+	rgbdelta 0 -32 -32
+	friction 1
+	blend add
+	assoc expgib
+}
diff --git a/freecs/progs.dat b/freecs/progs.dat
index b2f45c57..ac359100 100644
Binary files a/freecs/progs.dat and b/freecs/progs.dat differ
diff --git a/freecs/scripts/fcs_menu.shader b/freecs/scripts/fcs_menu.shader
new file mode 100755
index 00000000..efbb74a3
--- /dev/null
+++ b/freecs/scripts/fcs_menu.shader
@@ -0,0 +1,9 @@
+menu_static
+{
+	{
+		map gfx/menu/static.tga
+		blendfunc add
+		tcMod scroll 0.025 0.025
+		tcMod scale 3 3
+	}
+}