diff --git a/.clang_complete b/.clang_complete
new file mode 100644
index 0000000..733c14f
--- /dev/null
+++ b/.clang_complete
@@ -0,0 +1,4 @@
+-I /usr/include/SDL/
+-I /usr/include/freetype2/
+-I lib/lua/
+
diff --git a/gfx/spfx/exps.png b/gfx/spfx/exps.png
new file mode 100644
index 0000000..e3dfbb8
Binary files /dev/null and b/gfx/spfx/exps.png differ
diff --git a/src/input.h b/src/input.h
index 02ba676..96ab2fa 100644
--- a/src/input.h
+++ b/src/input.h
@@ -1,5 +1,5 @@
 #pragma once
-#include "SDL.h"
+#include <SDL.h>
 
 // Input types.
 typedef enum { KEYBIND_NULL, KEYBIND_KEYBOARD, KEYBIND_JAXIS, KEYBIND_JBUTTON } KeybindType;
diff --git a/src/lephisto.c b/src/lephisto.c
index 4e98483..8493d32 100644
--- a/src/lephisto.c
+++ b/src/lephisto.c
@@ -24,6 +24,7 @@
 #include "toolkit.h"
 #include "pilot.h"
 #include "sound.h"
+#include "spfx.h"
 #include "music.h"
 
 #define XML_START_ID    "Start"
@@ -150,6 +151,7 @@ int main(int argc, char** argv) {
 
   // Data loading.
   factions_load();
+	spfx_load();
   outfit_load();
   ships_load();
   fleet_load();
@@ -203,6 +205,7 @@ int main(int argc, char** argv) {
   fleet_free();
   ships_free();
   outfit_free();
+	spfx_free(); 		// Remove the special effects.
   factions_free();
   gl_freeFont(&gl_smallFont);
 
@@ -242,6 +245,7 @@ static void fps_control(void) {
 // Update the game.
 static void update_space(void) {
   weapons_update(dt);
+	spfx_update(dt);
   pilots_update(dt);
 }
 
@@ -254,8 +258,8 @@ static void update_space(void) {
 //        | Back layer weapons.
 //        X
 //    N   | NPC ships.
-//        | Normal layer particles (above ships).
 //        | Front layer weapons.
+//        | Normal layer particles (above ships).
 //        X
 //    FG  | Player.
 //        | Foreground particles.
@@ -270,8 +274,10 @@ static void render_space(void) {
   // N.
   pilots_render();
   weapons_render(WEAPON_LAYER_FG);
+	spfx_render(SPFX_LAYER_BACK);
   // FG.  
   player_render();
+	spfx_render(SPFX_LAYER_FRONT);
   display_fps(dt);
 }
 
diff --git a/src/menu.c b/src/menu.c
index ae6633b..6ad2da2 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -1,5 +1,5 @@
 #include <string.h>
-#include "SDL.h"
+#include <SDL.h>
 
 #include "toolkit.h"
 #include "log.h"
diff --git a/src/music.c b/src/music.c
index 897e9c6..da7dd9f 100644
--- a/src/music.c
+++ b/src/music.c
@@ -1,7 +1,7 @@
 #include <AL/al.h>
 #include <AL/alc.h>
 #include <vorbis/vorbisfile.h>
-#include "SDL.h"
+#include <SDL.h>
 
 #include "lephisto.h"
 #include "log.h"
diff --git a/src/pause.c b/src/pause.c
index 2ec87c8..221ddec 100644
--- a/src/pause.c
+++ b/src/pause.c
@@ -1,5 +1,6 @@
 #include "weapon.h"
 #include "pilot.h"
+#include "spfx.h"
 #include "pause.h"
 
 // Main thing with pausing is to allow things based on time to
@@ -22,6 +23,7 @@ void pause(void) {
 
   pilots_pause();
   weapons_pause();
+	spfx_pause();
 
   paused = 1; // We should unpause it.
 }
@@ -31,6 +33,7 @@ void unpause(void) {
 
   pilots_unpause();
   weapons_unpause();
+	spfx_unpause();
 
   paused = 0;
 }
diff --git a/src/sound.c b/src/sound.c
index 5ccbffb..8fa84a4 100644
--- a/src/sound.c
+++ b/src/sound.c
@@ -1,7 +1,7 @@
 #include <sys/stat.h>
 #include <AL/alc.h>
-#include "SDL.h"
-#include "SDL_thread.h"
+#include <SDL.h>
+#include <SDL_thread.h>
 
 #include "lephisto.h"
 #include "log.h"
diff --git a/src/spfx.c b/src/spfx.c
new file mode 100644
index 0000000..4478673
--- /dev/null
+++ b/src/spfx.c
@@ -0,0 +1,221 @@
+#include <SDL.h>
+
+#include "lephisto.h"
+#include "log.h"
+#include "pilot.h"
+#include "physics.h"
+#include "opengl.h"
+#include "pause.h"
+#include "spfx.h"
+
+#define SPFX_GFX	"../gfx/spfx/" // Graphics location.
+#define SPFX_CHUNK 10 // Chunk to allocate when needed.
+
+typedef struct SPFX_Base_ {
+	char* name;
+
+	int anim; // Total duration in ms.
+	glTexture* gfx; // Will use each sprite as a frame.
+} SPFX_Base;
+
+static SPFX_Base* spfx_effects = NULL;
+static int spfx_neffects = 0;
+
+typedef struct SPFX_ {
+	Vec2 pos, vel;		// They don't accelerate.
+
+	int lastframe; 	// Need when pausing.
+	int effect; 		// Actual effect.
+	unsigned int t; // Start.
+} SPFX;
+
+// Front stack is for effects on player.
+// Back is for everything else.
+static SPFX* 	spfx_stack_front 		= NULL;
+static int 		spfx_nstack_front 	= 0;
+static int 		spfx_mstack_front 	= 0;
+static SPFX*	spfx_stack_back			= NULL;
+static int 		spfx_nstack_back		= 0;
+static int 		spfx_mstack_back		= 0;
+
+static int spfx_base_load(char* name, int anim, char* gfx, int sx, int sy);
+static void spfx_base_free(SPFX_Base* effect);
+static void spfx_destroy(SPFX* layer, int* nlayer, int spfx);
+static void spfx_update_layer(SPFX* layer, int* nlayer, const double dt);
+static void spfx_pause_layer(SPFX* layer, int nlayer);
+static void spfx_unpause_layer(SPFX* layer, int nlayer);
+
+// Load the SPFX_Base.
+static int spfx_base_load(char* name, int anim, char* gfx, int sx, int sy) {
+	SPFX_Base* cur;
+	char buf[PATH_MAX];
+
+	spfx_effects = realloc(spfx_effects, ++spfx_neffects*sizeof(SPFX_Base));
+	cur = &spfx_effects[spfx_neffects-1];
+
+	cur->name = strdup(name);
+	cur->anim = anim;
+	sprintf(buf, SPFX_GFX"%s", gfx);
+	cur->gfx = gl_newSprite(buf, sx, sy);
+
+	return 0;
+}
+
+static void spfx_base_free(SPFX_Base* effect) {
+	if(effect->name) free(effect->name);
+	if(effect->gfx) gl_freeTexture(effect->gfx);
+}
+
+// Load/Unload.
+int spfx_load(void) {
+	spfx_base_load("ExpS", 600, "exps.png", 6, 5);
+	return 0;
+}
+
+void spfx_free(void) {
+	int i;
+
+	// Get rid of all the particles and free the stacks.
+	spfx_clear();
+	if(spfx_stack_front) free(spfx_stack_front);
+	spfx_stack_front = NULL;
+	spfx_mstack_front = 0;
+	if(spfx_stack_back) free(spfx_stack_back);
+	spfx_stack_back = NULL;
+	spfx_mstack_back = 0;
+
+	for(i = 0; i < spfx_neffects; i++)
+		spfx_base_free(&spfx_effects[i]);
+	free(spfx_effects);
+	spfx_effects = NULL;
+	spfx_neffects = 0;
+}
+
+void spfx_add(int effect, const Vec2* pos, const Vec2* vel, const int layer) {
+	SPFX* cur_spfx;
+
+	if(layer == SPFX_LAYER_FRONT) {
+		// Front layer.
+		if(spfx_mstack_front < spfx_nstack_front+1) {
+			// We need more memory.
+			spfx_mstack_front += SPFX_CHUNK;
+			spfx_stack_front = realloc(spfx_stack_front, spfx_mstack_front*sizeof(SPFX));
+		}
+		cur_spfx = &spfx_stack_front[spfx_nstack_front];
+		spfx_nstack_front++;
+	}
+	else if(layer == SPFX_LAYER_BACK) {
+		// Back layer.
+		if(spfx_mstack_back < spfx_nstack_back+1) {
+			// Need more memory.
+			spfx_mstack_back += SPFX_CHUNK;
+			spfx_stack_back = realloc(spfx_stack_back, spfx_mstack_back*sizeof(SPFX));
+		}
+		cur_spfx = &spfx_stack_back[spfx_nstack_back];
+		spfx_nstack_back++;
+	}
+
+	cur_spfx->effect = effect;
+	vectcpy(&cur_spfx->pos, pos);
+	vectcpy(&cur_spfx->vel, vel);
+	cur_spfx->t = SDL_GetTicks();
+}
+
+void spfx_clear(void) {
+	int i;
+	for(i = spfx_nstack_front-1; i >= 0; i--)
+		spfx_destroy(spfx_stack_front, &spfx_nstack_front, i);
+	
+	for(i = spfx_nstack_back-1; i >= 0; i--)
+		spfx_destroy(spfx_stack_back, &spfx_nstack_back, i);
+}
+
+static void spfx_destroy(SPFX* layer, int* nlayer, int spfx) {
+	int i;
+	(*nlayer)--;
+	for(i = spfx; i < *nlayer; i++)
+		memcpy(&layer[i], &layer[i+1], sizeof(SPFX));
+}
+
+void spfx_update(const double dt) {
+	spfx_update_layer(spfx_stack_front, &spfx_nstack_front, dt);
+	spfx_update_layer(spfx_stack_back,  &spfx_nstack_back, dt);
+}
+
+static void spfx_update_layer(SPFX* layer, int* nlayer, const double dt) {
+	int i;
+	unsigned int t = SDL_GetTicks();
+
+	for(i = 0; i < *nlayer; i++) {
+		// Time to die!!!
+		if(t > (layer[i].t + spfx_effects[layer[i].effect].anim)) {
+			spfx_destroy(layer, nlayer, i);
+			i--;
+			continue;
+		}
+		// Mkay. Update it now.
+		vect_cadd(&layer[i].pos, dt*VX(layer[i].vel), dt*VY(layer[i].vel));
+	}
+}
+
+void spfx_render(const int layer) {
+	SPFX* spfx_stack;
+	int i, spfx_nstack;
+	SPFX_Base* effect;
+	int sx, sy;
+	unsigned int t = SDL_GetTicks();
+
+	// Get the appropriate layer.
+	switch(layer) {
+		case SPFX_LAYER_FRONT:
+			spfx_stack = spfx_stack_front;
+			spfx_nstack = spfx_nstack_front;
+			break;
+		case SPFX_LAYER_BACK:
+			spfx_stack = spfx_stack_back;
+			spfx_nstack = spfx_nstack_back;
+			break;
+	}
+	for(i = 0; i < spfx_nstack; i++) {
+		effect = &spfx_effects[spfx_stack[i].effect];
+
+		sx = (int)effect->gfx->sx;
+		sy = (int)effect->gfx->sy;
+
+		if(!paused) // Don't calculate frame if paused.
+			spfx_stack[i].lastframe = sx * sy
+						* MIN(((double)(t - spfx_stack[i].t)/(double)effect->anim), 1.);
+		
+		gl_blitSprite(effect->gfx,
+					VX(spfx_stack[i].pos), VY(spfx_stack[i].pos),
+					spfx_stack[i].lastframe % sx,
+					spfx_stack[i].lastframe / sx,
+					NULL);
+	}
+}
+
+void spfx_pause(void) {
+	spfx_pause_layer(spfx_stack_front, spfx_nstack_front);
+	spfx_pause_layer(spfx_stack_back, spfx_nstack_back);
+
+}
+
+static void spfx_pause_layer(SPFX* layer, int nlayer) {
+	int i;
+	unsigned int t = SDL_GetTicks();
+	for(i = 0; i < nlayer; i++)
+		layer[i].t -= t;
+}
+
+void spfx_unpause(void) {
+	spfx_unpause_layer(spfx_stack_front, spfx_nstack_front);
+	spfx_unpause_layer(spfx_stack_back, spfx_nstack_back);
+}
+
+static void spfx_unpause_layer(SPFX* layer, int nlayer) {
+	int i;
+	unsigned int t = SDL_GetTicks();
+	for(i = 0; i < nlayer; i++)
+		layer[i].t +=  t;
+}
+
diff --git a/src/spfx.h b/src/spfx.h
new file mode 100644
index 0000000..c8fd61f
--- /dev/null
+++ b/src/spfx.h
@@ -0,0 +1,22 @@
+#pragma once
+#include "physics.h"
+
+#define SPFX_LAYER_FRONT 	0
+#define SPFX_LAYER_BACK 	1
+
+void spfx_add(const int effect,
+			const Vec2* pos, const Vec2* vel, const int layer);
+
+// Stack manipulation functions.
+void spfx_update(const double dt);
+void spfx_render(const int layer);
+void spfx_clear(void);
+
+// Load/free.
+int spfx_load(void);
+void spfx_free(void);
+
+// Pause/Unpause routines.
+void spfx_pause(void);
+void spfx_unpause(void);
+
diff --git a/src/toolkit.h b/src/toolkit.h
index 6cfb683..21b2007 100644
--- a/src/toolkit.h
+++ b/src/toolkit.h
@@ -1,5 +1,5 @@
 #pragma once
-#include "SDL.h"
+#include <SDL.h>
 #include "opengl.h"
 #include "font.h"
 
diff --git a/src/weapon.c b/src/weapon.c
index 4f5c116..7f7c568 100644
--- a/src/weapon.c
+++ b/src/weapon.c
@@ -10,6 +10,7 @@
 #include "pilot.h"
 #include "collision.h"
 #include "player.h"
+#include "spfx.h"
 #include "weapon.h"
 
 #define weapon_isSmart(w) (w->think)
@@ -236,8 +237,11 @@ static void weapon_update(Weapon* w, const double dt, WeaponLayer layer) {
 // Good shot.
 static void weapon_hit(Weapon* w, Pilot* p, WeaponLayer layer) {
   // Someone should let the ai know it's been attacked.
-  if(!pilot_isPlayer(p))
+  if(!pilot_isPlayer(p)) {
     ai_attacked(p, w->parent);
+		spfx_add(0, &w->solid->pos, &p->solid->vel, SPFX_LAYER_BACK);
+	} else
+		spfx_add(0, &w->solid->pos, &p->solid->vel, SPFX_LAYER_FRONT);
   if(w->parent == PLAYER_ID)
     // Make hostile to player.
     pilot_setFlag(p, PILOT_HOSTILE);