From 998a1bf68b53a73e25f5941708b27bd674b6fa8f Mon Sep 17 00:00:00 2001
From: Allanis <allanis@saracraft.net>
Date: Tue, 5 Feb 2013 16:50:56 +0000
Subject: [PATCH] [Add] Rudimentary shooting. This needs some work. [Add]
 Layers should be working properly.

---
 .gitignore     |   1 +
 bin/Makefile   |   2 +-
 dat/outfit.xml |   4 +-
 src/ai.c       |   3 +-
 src/main.c     |  70 +++++++++++++++-------
 src/outfit.c   |  40 +++++++++++--
 src/outfit.h   |  44 +++++++++++---
 src/physics.c  |   8 +--
 src/physics.h  |   6 +-
 src/pilot.c    | 125 +++++++++++++++++++++++++++++---------
 src/pilot.h    |  25 ++++++--
 src/player.c   |  21 ++++++-
 src/player.h   |   6 +-
 src/ship.c     |  55 +++++++++++------
 src/ship.h     |  20 ++++++-
 src/weapon.c   | 158 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/weapon.h   |  11 ++++
 17 files changed, 496 insertions(+), 103 deletions(-)
 create mode 100644 src/weapon.c
 create mode 100644 src/weapon.h

diff --git a/.gitignore b/.gitignore
index 37a7842..1efab61 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,5 +26,6 @@
 *bin/Lephisto
 *bin/data
 *pack
+*core
 
 
diff --git a/bin/Makefile b/bin/Makefile
index 5869fef..a22f0ac 100644
--- a/bin/Makefile
+++ b/bin/Makefile
@@ -48,5 +48,5 @@ data: pack $(DATAFILES) ../src/pack.c
 	
 clean:
 	@echo -e "\tRemoving data.."
-	rm -rf $(OBJS) $(APPNAME) $(DATA) pack
+	rm -rf $(OBJS) $(APPNAME) $(DATA) pack core
 
diff --git a/dat/outfit.xml b/dat/outfit.xml
index 76b3a2c..8604419 100644
--- a/dat/outfit.xml
+++ b/dat/outfit.xml
@@ -9,7 +9,9 @@
     <specific type = "1">
       <sound>laser.wav</sound>
       <gfx>lasergreen.png</gfx>
-      <speed>450</speed>
+      <delay>500</delay>
+      <speed>550</speed>
+      <range>300</range>
       <accuracy>30</accuracy>
       <damage>
         <armor>20</armor>
diff --git a/src/ai.c b/src/ai.c
index 935c3f4..075d98f 100644
--- a/src/ai.c
+++ b/src/ai.c
@@ -89,7 +89,8 @@ static double pilot_turn = 0.;
 
 // Destroy the AI part of the pilot.
 void ai_destroy(Pilot* p) {
-  ai_freetask(p->task);
+  if(p->task)
+    ai_freetask(p->task);
 }
 
 // Init the AI stuff. Which is basically Lua.
diff --git a/src/main.c b/src/main.c
index c8df506..27e304c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -18,9 +18,11 @@
 #include "rng.h"
 #include "ai.h"
 #include "outfit.h"
+#include "pack.h"
+#include "weapon.h"
 #include "pilot.h"
 
-#define WINDOW_CAPTION  "Lephisto"
+#define APPNAME         "Lephisto"
 #define CONF_FILE       "conf"
 #define MINIMUM_FPS     0.5
 
@@ -31,14 +33,13 @@ static unsigned int time = 0; // Calculate FPS and movement.
 
 #define DATA_DEF  "data"
 char* data = NULL;
-
 static int show_fps = 1; // Default - True.
+static int max_fps = 0;
 
 // Prototypes.
 
 static void print_usage(char** argv);
 static void display_fps(const double dt);
-
 // Update.
 static void update_all(void);
 
@@ -47,7 +48,7 @@ static void print_usage(char** argv) {
   LOG("USAGE: %s [OPTION]", argv[0]);
   LOG("Options are:");
   LOG("\t-f,    --fullscreen  - Fullscreen");
-  LOG("\t-F,    --fps         - Toggle frames per second");
+  LOG("\t-F,    --fps         - Limit frames per second");
   LOG("\t-d s,  --data s      - Set the data file to be s");
   LOG("\t-j n,  --joystick n  - Use joystick (n)");
   LOG("\t-J s,  --joystick s  - Use joystick whose name contains (s)");
@@ -57,6 +58,10 @@ static void print_usage(char** argv) {
 
 int main(int argc, char** argv) {
   int i;
+
+  // Print the version.
+  LOG(""APPNAME" v%d.%d.%d", VMAJOR, VMINOR, VREV);
+
   // Initialize SDL for possible warnings.
   SDL_Init(0);
   // Default values..
@@ -71,9 +76,10 @@ int main(int argc, char** argv) {
 
   // input.
   input_init();
-  input_setKeybind("accel",  KEYBIND_KEYBOARD, SDLK_w,      0);
-  input_setKeybind("left",   KEYBIND_KEYBOARD, SDLK_a,      0);
-  input_setKeybind("right",  KEYBIND_KEYBOARD, SDLK_d,      0);
+  input_setKeybind("accel",   KEYBIND_KEYBOARD, SDLK_w,     0);
+  input_setKeybind("left",    KEYBIND_KEYBOARD, SDLK_a,     0);
+  input_setKeybind("right",   KEYBIND_KEYBOARD, SDLK_d,     0);
+  input_setKeybind("primary", KEYBIND_KEYBOARD, SDLK_SPACE, 0);
 
   // Use Lua to parse configuration file.
   lua_State* L = luaL_newstate();
@@ -96,7 +102,7 @@ int main(int argc, char** argv) {
 
     lua_getglobal(L, "fps");
     if(lua_isnumber(L, -1))
-      show_fps = (int)lua_tonumber(L, -1);
+      max_fps = (int)lua_tonumber(L, -1);
 
     // Joystick.
     lua_getglobal(L, "joystick");
@@ -153,7 +159,7 @@ int main(int argc, char** argv) {
   // Parse arguments.
   static struct option long_options[] = {
     { "fullscreen",   no_argument,        0, 'f' },
-    { "fps",          optional_argument,  0, 'F' },
+    { "fps",          required_argument, 0, 'F' },
     { "data",         required_argument,  0, 'd' },
     { "joystick",     required_argument,  0, 'j' },
     { "joystick",     required_argument,  0, 'J' },
@@ -163,14 +169,14 @@ int main(int argc, char** argv) {
   };
   int option_index = 0;
   int c = 0;
-  while((c = getopt_long(argc, argv, "fFd:J:j:hv", long_options, &option_index)) != -1) {
+  while((c = getopt_long(argc, argv, "fF:d:J:j:hv", long_options, &option_index)) != -1) {
     switch(c) {
       case 'f':
         gl_screen.fullscreen = 1;
         break;
       case 'F':
         if(optarg != NULL) show_fps = atoi(optarg);
-        else show_fps = !show_fps;
+        else max_fps = !show_fps;
         break;
       case 'd':
         data = strdup(optarg);
@@ -195,11 +201,21 @@ int main(int argc, char** argv) {
   if(gl_init()) {
     // Initializes video output.
     WARN("Error initializing video output, exiting...");
+    SDL_Quit();
+    exit(EXIT_FAILURE);
+  }
+
+  // See if the data file is valid.
+  if(pack_check(data)) {
+    ERR("Data file '%s' not found", data);
+    WARN("You can specify what data file you want to use with '-d'");
+    WARN("See -h or -- help for more infoamtion.");
+    SDL_Quit();
     exit(EXIT_FAILURE);
   }
 
   // Window.
-  SDL_WM_SetCaption(WINDOW_CAPTION, NULL);
+  SDL_WM_SetCaption(APPNAME, NULL);
 
   // Input.
   if(indjoystick >= 0 || namjoystick != NULL) {
@@ -225,11 +241,11 @@ int main(int argc, char** argv) {
   space_load();
 
   // Testing.
-  pilot_create(get_ship("Ship"), "Player", NULL, NULL, PILOT_PLAYER);
+  pilot_create(get_ship("Ship"), "Player", 0., NULL, NULL, PILOT_PLAYER);
   gl_bindCamera(&player->solid->pos);
   space_init("SaraSys");
 
-  pilot_create(get_ship("Test"), NULL, NULL, NULL, 0);
+  pilot_create(get_ship("Test"), NULL, 2., NULL, NULL, 0);
 
   time = SDL_GetTicks();
 
@@ -268,19 +284,23 @@ int main(int argc, char** argv) {
 //
 //    BG  | Stars and planets.
 //        | Background particles.
+//        | Back layer weapons.
 //  X
 //    N   | NPC ships.
 //        | Normal layer particles (above ships).
+//        | Front layer weapons.
 //  X
 //    FG  | Player.
 //        | Foreground particles.
 //        | Text and GUI.
 // ========================================================
+static double fps_dt = 1.;
 static void update_all(void) {
   // dt in us.
   double dt = (double)(SDL_GetTicks() - time) / 1000.;
   time = SDL_GetTicks();
   
+  // TODO: This could use some work.
   if(dt > MINIMUM_FPS) {
     Vec2 pos;
     vect_csetmin(&pos, 10., (double)(gl_screen.h-40));
@@ -288,20 +308,27 @@ static void update_all(void) {
     SDL_GL_SwapBuffers();
     return;
   }
+  // If FPS is limited.
+  else if(max_fps != 0 && dt < 1./max_fps) {
+    double delay = 1./max_fps - dt;
+    SDL_Delay(delay);
+    fps_dt += delay; // Make sure it displays the propper FPS.
+  }
 
   glClear(GL_COLOR_BUFFER_BIT);
-  
+
+// --  
   // BG.
   space_render(dt);
   planets_render();
-  
-  // N
+  weapons_update(dt, WEAPON_LAYER_BG);
+  // N.
   pilots_update(dt);
-  
-  // FG.
-  player_renderGUI();
-
+  weapons_update(dt, WEAPON_LAYER_FG);
+  // FG.  
+  player_render();
   display_fps(dt);
+// --
 
   SDL_GL_SwapBuffers();
 }
@@ -310,7 +337,6 @@ static void update_all(void) {
 // Spit this out on display.
 static double fps = 0.;
 static double fps_cur = 0.;
-static double fps_dt = 1.;
 static void display_fps(const double dt) {
   fps_dt += dt;
   fps_cur += 1.;
diff --git a/src/outfit.c b/src/outfit.c
index 5187d6d..a70d521 100644
--- a/src/outfit.c
+++ b/src/outfit.c
@@ -4,6 +4,7 @@
 
 #include "main.h"
 #include "log.h"
+#include "pack.h"
 #include "outfit.h"
 
 #define XML_NODE_START  1
@@ -31,8 +32,27 @@ Outfit* outfit_get(const char* name) {
 }
 
 // Return 1 if outfit is a weapon.
-int outfit_isweapon(const Outfit* o) {
-  return (o->type > OUTFIT_TYPE_NULL && o->type <= OUTFIT_TYPE_MISSILE_SWARM_SMART);
+int outfit_isWeapon(const Outfit* o) {
+  return ((o->type == OUTFIT_TYPE_BOLT) || (o->type == OUTFIT_TYPE_BEAM));
+}
+
+// Return 1 if outfit is a launcher.
+int outfit_isLauncher(const Outfit* o) {
+  return((o->type == OUTFIT_TYPE_MISSILE_DUMB) ||
+        (o->type == OUTFIT_TYPE_MISSILE_SEEK) ||
+        (o->type == OUTFIT_TYPE_MISSILE_SEEK_SMART) ||
+        (o->type == OUTFIT_TYPE_MISSILE_SWARM) ||
+        (o->type == OUTFIT_TYPE_MISSILE_SWARM_SMART));
+}
+
+// Return 1 if outfit is weapon ammunition.
+int outfit_isAmmo(const Outfit* o) {
+  return((o->type == OUTFIT_TYPE_MISSILE_DUMB_AMMO) ||
+        (o->type == OUTFIT_TYPE_MISSILE_SEEK_AMMO) ||
+        (o->type == OUTFIT_TYPE_MISSILE_SEEK_SMART_AMMO) ||
+        (o->type == OUTFIT_TYPE_MISSILE_SWARM_AMMO) ||
+        (o->type == OUTFIT_TYPE_MISSILE_SWARM_SMART_AMMO));
+
 }
 
 const char* outfit_typename[] = {
@@ -40,10 +60,15 @@ const char* outfit_typename[] = {
   "Bolt Cannon",
   "Beam Cannon",
   "Dumb Missile",
+  "Dumb Missile Ammunition",
   "Seeker Missile",
-  "Smart Missile",
+  "Seeker Missile Ammunition",
+  "Smart Seeker Missile",
+  "Smart Seeker Missile Ammunition",
   "Swam Missile",
-  "Smart Swarm Missile"
+  "Swarm Missile Ammunition Pack",
+  "Smart Swarm Missile",
+  "Smart Swarm Missile Ammunition Pack"
 };
 
 const char* outfit_getType(const Outfit* o) {
@@ -61,6 +86,8 @@ static void outfit_parseSWeapon(Outfit* tmp, const xmlNodePtr parent) {
     // Load all the things.
     if(strcmp((char*)node->name, "speed")==0)
       tmp->speed = (double)atoi((char*)node->children->content);
+    else if(strcmp((char*)node->name, "delay")==0)
+      tmp->delay = atoi((char*)node->children->content);
     else if(strcmp((char*)node->name, "accuracy")==0)
       tmp->accuracy = atof((char*)node->children->content)*M_PI/180.; // to rad.
     else if(strcmp((char*)node->name, "gfx")==0) {
@@ -80,7 +107,8 @@ static void outfit_parseSWeapon(Outfit* tmp, const xmlNodePtr parent) {
   }
 #define MELEMENT(o,s) if((o) == 0) WARN("Outfit '%s' missing '"s"' element", tmp->name)
   MELEMENT(tmp->speed,          "speed");
-  MELEMENT(tmp->accuracy,        "tech");
+  MELEMENT(tmp->accuracy,       "tech");
+  MELEMENT(tmp->delay,          "delay");
   MELEMENT(tmp->damage_armor,   "armor' from element 'damage");
   MELEMENT(tmp->damage_shield,  "shield' from element 'damage");
 #undef MELEMENT
@@ -181,7 +209,7 @@ int outfit_load(void) {
 void outfit_free(void) {
   int i;
   for(i = 0; i < outfits; i++) {
-    if(outfit_isweapon(&outfit_stack[i]) && outfit_stack[i].gfx_space)
+    if(outfit_isWeapon(&outfit_stack[i]) && outfit_stack[i].gfx_space)
       gl_freeTexture(outfit_stack[i].gfx_space);
     free(outfit_stack[i].name);
   }
diff --git a/src/outfit.h b/src/outfit.h
index 350d0cb..235f674 100644
--- a/src/outfit.h
+++ b/src/outfit.h
@@ -1,42 +1,70 @@
 #pragma once
 #include "opengl.h"
 
+#define OUTFIT_PROP_WEAP_PRIMARY    (1<<0)
+#define OUTFIT_PROP_WEAP_SECONDARY  (1<<1)
+
 // Outfit types.
 typedef enum {
-  OUTFIT_TYPE_NULL,
+  OUTFIT_TYPE_NULL = 0,
   OUTFIT_TYPE_BOLT,
   OUTFIT_TYPE_BEAM,
   OUTFIT_TYPE_MISSILE_DUMB,
+  OUTFIT_TYPE_MISSILE_DUMB_AMMO,
   OUTFIT_TYPE_MISSILE_SEEK,
+  OUTFIT_TYPE_MISSILE_SEEK_AMMO,
   OUTFIT_TYPE_MISSILE_SEEK_SMART,
+  OUTFIT_TYPE_MISSILE_SEEK_SMART_AMMO,
   OUTFIT_TYPE_MISSILE_SWARM,
-  OUTFIT_TYPE_MISSILE_SWARM_SMART
+  OUTFIT_TYPE_MISSILE_SWARM_AMMO,
+  OUTFIT_TYPE_MISSILE_SWARM_SMART,
+  OUTFIT_TYPE_MISSILE_SWARM_SMART_AMMO
 } OutfitType;
 
 // An outfit depends a lot on the type.
 typedef struct {
   char* name;
 
+  // General specs.
   int max;
   int tech;
   int mass;
 
-  gl_texture gfx_store;
+  gl_texture gfx_store; // Store graphic.
+
+  int properties; // Properties stored bitwise.
   
+  // Type dependant.
   OutfitType type;
   union {
-    struct {
-      double speed;
-      double accuracy;
-      double damage_armor, damage_shield;
+    struct { // Beam/Bolt.
+      unsigned int delay; // Delay between shots.
+      double speed; // Speed of shot. (not applicable to beam.
+      double range;
+      double accuracy; // Desviation accuracy.
+      double damage_armor, damage_shield; // Damage.
 
       gl_texture* gfx_space;
     };
+    struct { // Launcher.
+      //unsigned int delay; // Delay between shots.
+    };
+    struct { // Ammo.
+      //double speed; // Max speed.
+      //double turn; // Turn vel.
+      //double thrust; // Acceleration.
+      //double damage_armor, damage_shield;
+
+      //gl_texture* gfx_space;
+    };
   };
 } Outfit;
 
 Outfit* outfit_get(const char* name);
-int outfit_isweapon(const Outfit* o);
+// Outfit types.
+int outfit_isWeapon(const Outfit* o);
+int outfit_isLauncher(const Outfit* o);
+int outfit_isAmmo(const Outfit* o);
 const char* outfit_getType(const Outfit* o);
 
 // Load/free outfit stack.
diff --git a/src/physics.c b/src/physics.c
index 8e3c103..b112647 100644
--- a/src/physics.c
+++ b/src/physics.c
@@ -175,11 +175,11 @@ static void rk4_update(Solid* obj, const double dt) {
 }
 
 // Initialize a new solid.
-void solid_init(Solid* dest, const double mass, const Vec2* vel, const Vec2* pos) {
+void solid_init(Solid* dest, const double mass, const double dir, const Vec2* pos, const Vec2* vel) {
   dest->mass = mass;
 
   vect_cset(&dest->force, 0., 0.);
-  dest->dir = 0.;
+  dest->dir = dir;
 
   if(vel == NULL) vectnull(&dest->vel);
   else vectcpy(&dest->vel, vel);
@@ -191,10 +191,10 @@ void solid_init(Solid* dest, const double mass, const Vec2* vel, const Vec2* pos
 }
 
 // Create a new solid.
-Solid* solid_create(const double mass, const Vec2* vel, const Vec2* pos) {
+Solid* solid_create(const double mass, const double dir, const Vec2* pos, const Vec2* vel) {
   Solid* dyn = MALLOC_L(Solid);
   assert(dyn != NULL);
-  solid_init(dyn, mass, vel, pos);
+  solid_init(dyn, mass, dir, pos, vel);
   return dyn;
 }
 
diff --git a/src/physics.h b/src/physics.h
index 1940ecd..30b82fa 100644
--- a/src/physics.h
+++ b/src/physics.h
@@ -37,7 +37,9 @@ struct Solid {
 typedef struct Solid Solid;
 
 // Solid manipulation.
-void solid_init(Solid* dest, const double mass, const Vec2* vel, const Vec2* pos);
-Solid* solid_create(const double mass, const Vec2* vel, const Vec2* pos);
+void solid_init(Solid* dest, const double mass, const double dir, 
+      const Vec2* pos, const Vec2* vel);
+Solid* solid_create(const double mass, const double dir, 
+      const Vec2* pos, const Vec2* vel);
 void solid_free(Solid* src);
 
diff --git a/src/pilot.c b/src/pilot.c
index 9c2f110..7a9b057 100644
--- a/src/pilot.c
+++ b/src/pilot.c
@@ -5,6 +5,7 @@
 
 #include "main.h"
 #include "log.h"
+#include "weapon.h"
 #include "pilot.h"
 
 // Stack of pilot id's to assure uniqueness.
@@ -13,6 +14,7 @@ static unsigned int pilot_id = 0;
 // Stack of pilots - yes, they come in stacks now.
 static Pilot** pilot_stack;
 static int pilots = 0;
+extern Pilot* player;
 
 // External.
 extern void ai_destroy(Pilot* p); // Ai.
@@ -20,7 +22,8 @@ extern void player_think(Pilot* pilot); // Player.c
 extern void ai_think(Pilot* pilot); // Ai.c
 // Internal.
 static void pilot_update(Pilot* pilot, const double dt);
-static void pilot_render(Pilot* pilot);
+void pilot_render(Pilot* pilot);
+static void pilot_free(Pilot* p);
 
 // Pull a pilot out of the pilot_stack based on id.
 Pilot* get_pilot(unsigned int id) {
@@ -31,6 +34,7 @@ Pilot* get_pilot(unsigned int id) {
       return pilot_stack[i];
   return NULL;
 #endif
+  if(id == 0) return player;
   // Dichotomical search.
   int i, n;
   for(i = 0, n = pilots/2; n > 0; n /= 2)
@@ -38,15 +42,40 @@ Pilot* get_pilot(unsigned int id) {
   return (pilot_stack[i]->id == id) ? pilot_stack[i] : NULL;
 }
 
+// Mkay, this is how we shoot. Listen up.
+void pilot_shoot(Pilot* p, int secondary) {
+  int i;
+  if(!secondary) {
+    // Primary weapons.
+    if(!p->outfits) return; // No outfits.
+
+    for(i = 0; p->outfits[i].outfit; i++) // Cycle through outfits to find weapons.
+      if(outfit_isWeapon(p->outfits[i].outfit) || // Is a weapon or launch?
+            outfit_isLauncher(p->outfits[i].outfit))
+        // Ready to shoot again.
+        if((SDL_GetTicks()-p->outfits[i].timer) > p->outfits[i].outfit->delay)
+          // Different weapons have different behaviours.
+          switch(p->outfits[i].outfit->type) {
+            case OUTFIT_TYPE_BOLT:
+              weapon_add(p->outfits[i].outfit, p->solid->dir, &p->solid->pos,
+                    &p->solid->vel, (p==player) ? WEAPON_LAYER_FG : WEAPON_LAYER_BG);
+              p->outfits[i].timer = SDL_GetTicks();
+              break;
+            default:
+              break;
+          }
+  }
+}
+
 // Render the pilot.
-static void pilot_render(Pilot* pilot) {
+void pilot_render(Pilot* p) {
   int sprite;
-  gl_texture* texture = pilot->ship->gfx_ship;
+  gl_texture* t = p->ship->gfx_ship;
 
   // Get the sprite corresponding to the direction facing.
-  sprite = (int)(pilot->solid->dir / (2.0*M_PI / (texture->sy * texture->sx)));
+  sprite = (int)(p->solid->dir / (2.0*M_PI / (t->sy * t->sx)));
 
-  gl_blitSprite(texture, &pilot->solid->pos, sprite % (int)texture->sx, sprite / (int)texture->sy);
+  gl_blitSprite(t, &p->solid->pos, sprite % (int)t->sx, sprite / (int)t->sy);
 }
 
 // Update the pilot.
@@ -68,17 +97,23 @@ static void pilot_update(Pilot* pilot, const double dt) {
 // ==Init pilot.===========================================
 // ship  : Ship pilot is flying.
 // name  : Pilot's name, if NULL, ships name will be used.
+// dir   : Initial facing direction. (radians)
 // vel   : Initial velocity.
 // pos   : Initial position.
 // flags : Tweaking the pilot.
 // ========================================================
-void pilot_init(Pilot* pilot, Ship* ship, char* name, const Vec2* vel, const Vec2* pos, const int flags) {
-  pilot->id = ++pilot_id; // New unique pilot id based on pilot_id, Can't be 0.
+void pilot_init(Pilot* pilot, Ship* ship, char* name, const double dir, const Vec2* pos, 
+      const Vec2* vel, const int flags) {
+
+  if(flags & PILOT_PLAYER) // Player is ID 0
+    pilot->id = 0;
+  else
+    pilot->id = ++pilot_id; // New unique pilot id based on pilot_id, Can't be 0.
   
   pilot->ship = ship;  
   pilot->name = strdup((name == NULL) ? ship->name : name);
 
-  pilot->solid = solid_create(ship->mass, vel, pos);
+  pilot->solid = solid_create(ship->mass, dir, pos, vel);
 
   // Max shields armor.
   pilot->armor = ship->armor;
@@ -88,39 +123,73 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, const Vec2* vel, const Vec
   // Initially idle.
   pilot->task = NULL;
 
+  // Outfits.
+  pilot->outfits = NULL;
+  ShipOutfit* so;
+  if(ship->outfit) {
+    int noutfits = 0;
+    for(so = ship->outfit; so; so = so->next) {
+      pilot->outfits = realloc(pilot->outfits, (noutfits+1)*sizeof(PilotOutfit));
+      pilot->outfits[noutfits].outfit = so->data;
+      pilot->outfits[noutfits].quantity = so->quantity;
+      pilot->outfits[noutfits].timer = 0;
+      noutfits++;
+    }
+    // Sentinal.
+    pilot->outfits = realloc(pilot->outfits, (noutfits+1)*sizeof(PilotOutfit));
+    pilot->outfits[noutfits].outfit = NULL;
+    pilot->outfits[noutfits].quantity = 0;
+    pilot->outfits[noutfits].timer = 0;
+  }
+
   if(flags & PILOT_PLAYER) {
     pilot->think = player_think; // Players don't need to thing! :P
+    pilot->render = NULL;
     pilot->properties |= PILOT_PLAYER;
     player = pilot;
-  } else
+  } else {
     pilot->think = ai_think;
-
-  pilot->update = pilot_update;
+    pilot->update = pilot_update;
+  }
 }
 
 // Create a new pilot - Params are same as pilot_init. Return pilot's id.
-unsigned int pilot_create(Ship* ship, char* name, const Vec2* vel, const Vec2* pos, const int flags) {
+unsigned int pilot_create(Ship* ship, char* name, const double dir,
+      const Vec2* pos, const Vec2* vel, const int flags) {
   Pilot* dyn = MALLOC_L(Pilot);
   if(dyn == NULL) {
     WARN("Unable to allocate memory.");
     return 0;
   }
-  pilot_init(dyn, ship, name, vel, pos, flags);
+  pilot_init(dyn, ship, name, dir, pos, vel, flags);
 
-  // Add to the stack.
-  pilot_stack = realloc(pilot_stack, ++pilots*sizeof(Pilot*));
-  pilot_stack[pilots-1] = dyn;
+  if(flags & PILOT_PLAYER) {
+    // Player.
+    if(!pilot_stack) {
+      pilot_stack = MALLOC_L(Pilot*);
+      pilots = 1;
+    }
+    pilot_stack[0] = dyn;
+  } else {
+    // Add to the stack.
+    pilot_stack = realloc(pilot_stack, ++pilots*sizeof(Pilot*));
+    pilot_stack[pilots-1] = dyn;
+  }
   return dyn->id;
 }
 
 // Frees and cleans up a pilot.
-void pilot_destroy(Pilot* p) {
-  int i;
-
+static void pilot_free(Pilot* p) {
   solid_free(p->solid);
+  free(p->outfits);
   free(p->name);
   ai_destroy(p);
+  free(p);
+}
 
+// Destroy pilot from stack.
+void pilot_destroy(Pilot* p) {
+  int i;
   for(i = 0; i < pilots; i++)
     if(pilot_stack[i] == p)
       break;
@@ -128,27 +197,27 @@ void pilot_destroy(Pilot* p) {
     pilot_stack[i] = pilot_stack[i+1];
     i++;
   }
-  free(p);
+  pilot_free(p);
 }
 
 // Free the prisoned pilot!
 void pilots_free(void) {
   int i;
-  for(i = 0; i < pilots; i++) {
-    solid_free(pilot_stack[i]->solid);
-    free(pilot_stack[i]->name);
-    free(pilot_stack[i]);
-  }
+  for(i = 0; i < pilots; i++)
+    pilot_free(pilot_stack[i]);
   free(pilot_stack);
 }
 
 // Update all pilots.
 void pilots_update(double dt) {
   int i;
-  for(i = pilots-1; i >= 0; i--) {
-    if(pilot_stack[i]->think != NULL)
+  for(i = 0; i < pilots; i++) {
+    if(pilot_stack[i]->think)
       pilot_stack[i]->think(pilot_stack[i]);
-    pilot_stack[i]->update(pilot_stack[i], dt);
+    if(pilot_stack[i]->update)
+      pilot_stack[i]->update(pilot_stack[i], dt);
+    if(pilot_stack[i]->render)
+      pilot_stack[i]->render(pilot_stack[i]);
   }
 }
 
diff --git a/src/pilot.h b/src/pilot.h
index cc89013..e8b0efb 100644
--- a/src/pilot.h
+++ b/src/pilot.h
@@ -2,10 +2,17 @@
 #include "main.h"
 #include "physics.h"
 #include "ai.h"
+#include "outfit.h"
 #include "ship.h"
 
 #define PILOT_PLAYER    1 // Pilot is a player.
 
+typedef struct {
+  Outfit* outfit; // Associated outfit.
+  unsigned int quantity; // Number of outfits of this type that the pilot has.
+  unsigned int timer; // Used to store last used weapon time.
+} PilotOutfit;
+
 // Primary pilot structure.
 typedef struct Pilot {
   unsigned int id; // Pilots id.
@@ -18,24 +25,30 @@ typedef struct Pilot {
   // Current health.
   double armor, shield, energy;
 
+  void (*think)(struct Pilot*); // AI thinking for the pilot.
   void (*update)(struct Pilot*, const double); // Update the pilot.
+  void (*render)(struct Pilot*); // Rendering the pilot.
+
+  // Outfit management.
+  PilotOutfit* outfits;
 
   unsigned int properties; // Used for AI etc.
 
   // AI.
-  void (*think)(struct Pilot*); // Ai thinking for the pilot.
   Task* task; // Current action.
 } Pilot;
 
 extern Pilot* player; // The player.
 Pilot* get_pilot(unsigned int id);
 
-// Creation.
-void pilot_init(Pilot* dest, Ship* ship, char* name,
-      const Vec2* vel, const Vec2* pos, const int flags);
+void pilot_shoot(Pilot* p, int secondary);
 
-unsigned int pilot_create(Ship* ship, char* name, const Vec2* vel,
-      const Vec2* pos, const int flags);
+// Creation.
+void pilot_init(Pilot* dest, Ship* ship, char* name, const double dir,
+      const Vec2* pos, const Vec2* vel, const int flags);
+
+unsigned int pilot_create(Ship* ship, char* name, const double dir,
+      const Vec2* pos, const Vec2* vel, const int flags);
 
 // Cleanup.
 void pilot_destroy(Pilot* p);
diff --git a/src/player.c b/src/player.c
index 5f797d7..9c86f28 100644
--- a/src/player.c
+++ b/src/player.c
@@ -16,11 +16,21 @@ typedef struct {
 } Keybind;
 static Keybind** player_input; // Contains the players keybindings.
 // Name of each keybinding.
-const char* keybindNames[] = { "accel", "left", "right" };
+const char* keybindNames[] = { "accel", "left", "right", "primary" };
 
 Pilot* player = NULL; // extern in pilot.h
 static double player_turn = 0.; // Turn velocity from input.
 static double player_acc  = 0.; // Accel velocity from input.
+static int player_primary = 0; // Player is shooting primary weapon.
+
+extern void pilot_render(Pilot* pilot); // Extern is in Pilot.*
+static void player_renderGUI(void);
+
+// Render the player.
+void player_render(void) {
+  pilot_render(player);
+  player_renderGUI();
+}
 
 // Used in pilot.c
 // Basically uses keyboard input instead of AI input.
@@ -29,13 +39,15 @@ void player_think(Pilot* player) {
   if(player_turn)
     player->solid->dir_vel -= player->ship->turn * player_turn;
 
+  //if(player_primary) pilot_shoot(player, 0);
+
   vect_pset(&player->solid->force, player->ship->thrust * player_acc, player->solid->dir);
 }
 
 // ================
 // GUI!
 // ================
-void player_renderGUI(void) {
+static void player_renderGUI(void) {
 
 }
 
@@ -99,6 +111,11 @@ static void input_key(int keynum, double value, int abs) {
     if(abs) player_turn = value;
     else player_turn += value;
   }
+  // Shoot primary weapon. BOOM BOOM.
+  else if(strcmp(player_input[keynum]->name, "primary")==0) {
+    if(value==KEY_PRESS) player_primary = 1;
+    else if(value == KEY_RELEASE) player_primary = 0;
+  }
 
   //Make sure values are sane.
   player_acc = ABS(player_acc);
diff --git a/src/player.h b/src/player.h
index dc248d5..9f23ed9 100644
--- a/src/player.h
+++ b/src/player.h
@@ -1,10 +1,12 @@
 #pragma once
 #include <SDL.h>
+#include "pilot.h"
+
+extern Pilot* pilot;
 
 typedef enum { KEYBIND_NULL, KEYBIND_KEYBOARD, KEYBIND_JAXIS, KEYBIND_JBUTTON } KeybindType;
 
-// GUI.
-void player_renderGUI(void);
+void player_render(void);
 
 int player_isFlag(unsigned int flag);
 void player_setFlag(unsigned int flag);
diff --git a/src/ship.c b/src/ship.c
index af8be5f..5afec1e 100644
--- a/src/ship.c
+++ b/src/ship.c
@@ -6,8 +6,6 @@
 #include "pack.h"
 #include "ship.h"
 
-#define MAX_PATH_NAME 30 // Maximum size of the path.
-
 #define XML_NODE_START  1
 #define XML_NODE_TEXT   3
 
@@ -20,6 +18,8 @@
 static Ship* ship_stack = NULL;
 static int ships = 0;
 
+static Ship* ship_parse(xmlNodePtr parent);
+
 // Get a ship based on it's name.
 Ship* get_ship(const char* name) {
   Ship* tmp = ship_stack;
@@ -33,11 +33,13 @@ Ship* get_ship(const char* name) {
   return tmp+i;
 }
 
-Ship* ship_parse(xmlNodePtr parent) {
+static Ship* ship_parse(xmlNodePtr parent) {
   xmlNodePtr cur, node;
   Ship* tmp = CALLOC_L(Ship);
+  ShipOutfit* otmp, *ocur;
 
-  char str[MAX_PATH_NAME] = "\0";
+  char str[PATH_MAX] = "\0";
+  xmlChar* xstr;
 
   tmp->name = (char*)xmlGetProp(parent, (xmlChar*)"name");
 
@@ -45,18 +47,12 @@ Ship* ship_parse(xmlNodePtr parent) {
 
   while((node = node->next)) { // Load all the data.
     if(strcmp((char*)node->name, "GFX")==0) {
-      cur = node->children;
-      if(strcmp((char*)cur->name, "text")==0) {
-        snprintf(str, strlen((char*)cur->content)+sizeof(SHIP_GFX),
-              SHIP_GFX"%s", (char*)cur->content);
-        tmp->gfx_ship = gl_newSprite(str, 6, 6);
-      }
-    }
-    else if(strcmp((char*)node->name, "class")==0) {
-      cur = node->children;
-      if(strcmp((char*)cur->name, "text")==0)
-        tmp->class = atoi((char*)cur->content);
+      snprintf(str, strlen((char*)node->children->content)+sizeof(SHIP_GFX),
+            SHIP_GFX"%s", (char*)node->children->content);
+      tmp->gfx_ship = gl_newSprite(str, 6, 6);
     }
+    else if(strcmp((char*)node->name, "class")==0)
+      tmp->class = atoi((char*)node->children->content);
     else if(strcmp((char*)node->name, "movement")==0) {
       cur = node->children;
       while((cur = cur->next)) {
@@ -66,10 +62,10 @@ Ship* ship_parse(xmlNodePtr parent) {
           tmp->turn = atoi((char*)cur->children->content);
         else if(strcmp((char*)cur->name, "speed")==0)
           tmp->speed = atoi((char*)cur->children->content);
+        }
       }
-    }
-    else if(strcmp((char*)node->name, "health")==0) {
-      cur = node->children;
+      else if(strcmp((char*)node->name, "health")==0) {
+        cur = node->children;
       while((cur = cur->next)) {
         if(strcmp((char*)cur->name, "armor")==0)
           tmp->armor = (double)atoi((char*)cur->children->content);
@@ -98,7 +94,28 @@ Ship* ship_parse(xmlNodePtr parent) {
           tmp->cap_cargo = atoi((char*)cur->children->content);
       }
     }
-  }
+    else if(strcmp((char*)node->name, "outfits")==0) {
+      cur = node->children;
+      while((cur = cur->next)) {
+        if(strcmp((char*)cur->name, "outfit")==0)
+          otmp = MALLOC_L(ShipOutfit);
+          otmp->data = outfit_get((char*)cur->children->content);
+          xstr = xmlGetProp(cur, (xmlChar*)"qunatity");
+          if(!xstr)
+            WARN("Ship '%s' is missing tag 'quantity for outfit '%s'",  tmp->name, otmp->data->name);
+          otmp->quantity = atoi((char*)xstr);
+          free(xstr);
+          otmp->next = NULL;
+
+          if((ocur = tmp->outfit) == NULL) tmp->outfit = otmp;
+          else {
+            while(ocur->next);
+            ocur->next = otmp;
+          }
+        }
+      }
+    }
+  
   tmp->thrust *= tmp->mass; // Helps keep number sane.
 
 #define MELEMENT(o,s) if(o == 0) WARN("Ship '%s' missing '"s"' element", tmp->name)
diff --git a/src/ship.h b/src/ship.h
index e998a45..ec4b355 100644
--- a/src/ship.h
+++ b/src/ship.h
@@ -1,10 +1,25 @@
 #pragma once
 #include "main.h"
+#include "outfit.h"
 #include "opengl.h"
 
-enum ship_class { SHIP_CLASS_NULL, SHIP_CLASS_CIVILIAN };
+enum ship_class { 
+  SHIP_CLASS_NULL,
+  SHIP_CLASS_CIV_LIGHT,
+  SHIP_CLASS_CIV_MEDIUM,
+  SHIP_CLASS_CIV_HEAVY
+};
 typedef enum ship_class ship_class;
 
+// Small wrapper for the outfits.
+typedef struct ShipOutfit {
+  struct ShipOutfit* next; // Linked list.
+  Outfit* data; // Data itself.
+  int quantity;
+} ShipOutfit;
+
+
+// Ship structure.
 typedef struct {
   char* name; // Ship name.
   ship_class class; // Ship class.
@@ -26,6 +41,9 @@ typedef struct {
 
   // Capacity.
   int cap_cargo, cap_weapon;
+  
+  // Outfits
+  ShipOutfit* outfit;
 } Ship;
 
 int ships_load(void);
diff --git a/src/weapon.c b/src/weapon.c
new file mode 100644
index 0000000..6e2bb2b
--- /dev/null
+++ b/src/weapon.c
@@ -0,0 +1,158 @@
+#include <math.h>
+#include <malloc.h>
+#include <string.h>
+
+#include "outfit.h"
+#include "physics.h"
+#include "main.h"
+#include "log.h"
+#include "weapon.h"
+
+typedef struct Weapon {
+  Solid* solid; // Actually has its own solid. :D
+
+  const Outfit* outfit; // Related outfit that fired.
+  unsigned int timer; // Mainly used to see when the weapon was fired.
+
+  void(*update)(struct Weapon*, const double); // Position update and render.
+  void(*think)(struct Weapon*); // Some missiles need to be inteligent.
+} Weapon;
+
+// Behind Pilot layer.
+static Weapon** backLayer = NULL; // Behind pilots.
+static int nbackLayer     = 0;    // Number of elements.
+static int mbackLayer     = 0;    // Allocated memory size.
+// Behind player layer.
+static Weapon** frontLayer = NULL;  // Behind pilots.
+static int nfrontLayer    = 0;    // Number of elements.
+static int mfrontLayer    = 0;    // Allocated memory size.
+
+
+static Weapon* weapon_create(const Outfit* outfit, const double dir,
+      const Vec2* pos, const Vec2* vel);
+
+static void weapon_render(const Weapon* w);
+static void weapon_update(Weapon* w, const double dt);
+static void weapon_free(Weapon* w);
+
+// Update all weapons in the layer.
+void weapons_update(const double dt, WeaponLayer layer) {
+  Weapon** wlayer;
+  int nlayer;
+
+  switch(layer) {
+    case WEAPON_LAYER_BG:
+      wlayer = backLayer;
+      nlayer = nbackLayer;
+      break;
+    case WEAPON_LAYER_FG:
+      wlayer = frontLayer;
+      nlayer = nfrontLayer;
+      break;
+  }
+  int i;
+  for(i = 0; i < nlayer; i++)
+    weapon_update(wlayer[i], dt);
+}
+
+// Render the weapons.
+static void weapon_render(const Weapon* w) {
+  int sprite;
+  gl_texture* t = w->outfit->gfx_space;
+
+  // Get the sprite corresponding to the direction facing.
+  sprite = (int)(w->solid->dir / (2.0*M_PI / (t->sy*t->sx)));
+
+  gl_blitSprite(t, &w->solid->pos, sprite % (int)t->sx, sprite / (int)t->sy);
+}
+
+// Update the weapon.
+static void weapon_update(Weapon* w, const double dt) {
+  if(w->think)
+    (*w->think)(w);
+  (*w->solid->update)(w->solid, dt);
+
+  weapon_render(w);
+}
+
+static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2* pos, const Vec2* vel) {
+  Vec2 v;
+  double mass = 1; // Presumer lasers have a mass of 1.
+  Weapon* w = MALLOC_L(Weapon);
+  w->outfit = outfit; // Non-Changeable.
+  w->update = weapon_update;
+  w->think = NULL;
+
+  switch(outfit->type) {
+    case OUTFIT_TYPE_BOLT:
+      vect_cset(&v, VY(*vel)+outfit->speed*cos(dir), VANGLE(*vel)+outfit->speed*sin(dir));
+      w->solid = solid_create(mass, dir, pos, &v);
+      break;
+    default:
+      break;
+  }
+  return w;
+}
+
+// Add a new weapon.
+void weapon_add(const Outfit* outfit, const double dir, const Vec2* pos, const Vec2* vel, WeaponLayer layer) {
+  if(!outfit_isWeapon(outfit)) {
+    ERR("Trying to create a weapon from a non-Weapon type Outfit");
+    return;
+  }
+
+  Weapon* w = weapon_create(outfit, dir, pos, vel);
+
+  // Set the propper layer.
+  Weapon** curLayer = NULL;
+  int* mLayer = NULL;
+  int* nLayer = NULL;
+  switch(layer) {
+    case WEAPON_LAYER_BG:
+      curLayer = backLayer;
+      nLayer = &nbackLayer;
+      mLayer = &mbackLayer;
+      break;
+    case WEAPON_LAYER_FG:
+      curLayer = frontLayer;
+      nLayer = &nfrontLayer;
+      mLayer = &mfrontLayer;
+      break;
+    default:
+      ERR("Invalid WEAPON_LAYER specified.");
+      return;
+  }
+  if(*mLayer > *nLayer) // More memory allocated than what we need.
+    curLayer[(*nLayer)++] = w;
+  else { // Need to allocate more memory.
+    switch(layer) {
+      case WEAPON_LAYER_BG:
+        curLayer = backLayer = realloc(curLayer, (++(*mLayer))*sizeof(Weapon));
+        break;
+      case WEAPON_LAYER_FG:
+        curLayer = frontLayer = realloc(curLayer, (++(*mLayer))*sizeof(Weapon*));
+        break;
+    }
+    curLayer[(*nLayer)++] = w;
+  }
+}
+
+// Clear the weapon.
+static void weapon_free(Weapon* w) {
+  solid_free(w->solid);
+  free(w);
+}
+
+// Clear all the weapons, do not free the layers.
+void weapon_clear(void) {
+  int i;
+  for(i = 0; i < nbackLayer; i++)
+    weapon_free(backLayer[i]);
+  nbackLayer = 0;
+  backLayer = NULL;
+  for(i = 0; i < nfrontLayer; i++)
+    weapon_free(frontLayer[i]);
+  nfrontLayer = 0;
+  frontLayer = NULL;
+}
+
diff --git a/src/weapon.h b/src/weapon.h
new file mode 100644
index 0000000..6d6df73
--- /dev/null
+++ b/src/weapon.h
@@ -0,0 +1,11 @@
+#pragma once
+#include "outfit.h"
+#include "physics.h"
+
+typedef enum { WEAPON_LAYER_BG, WEAPON_LAYER_FG } WeaponLayer;
+
+void weapon_add(const Outfit* outfit, const double dir,
+      const Vec2* pos, const Vec2* vel, WeaponLayer layer);
+
+void weapons_update(const double dt, WeaponLayer layer);
+