diff --git a/scripts/ai/test.lua b/scripts/ai/test.lua
index 0f0acf1..de5a7eb 100644
--- a/scripts/ai/test.lua
+++ b/scripts/ai/test.lua
@@ -3,10 +3,11 @@ control_rate = 2
 
 -- Required "control" function.
 function control()
-  pushtask(0, "follow");
+  say("IMA KILL YOU!!");
+  pushtask(0, "attack");
 end
 
-function follow()
+function attack()
   target = 0
   dir = face(target)
   dist = getdist(getpos(target))
diff --git a/src/ai.c b/src/ai.c
index 0f9e67d..d424085 100644
--- a/src/ai.c
+++ b/src/ai.c
@@ -8,6 +8,7 @@
 #include "main.h"
 #include "log.h"
 #include "pilot.h"
+#include "player.h"
 #include "physics.h"
 #include "pack.h"
 #include "ai.h"
@@ -78,6 +79,7 @@ static int ai_face(lua_State* L);         // face(number/pointer)
 static int ai_brake(lua_State* L);        // Brake()
 // Misc.
 static int ai_createvect(lua_State* L);   // createvect(number, number)
+static int ai_say(lua_State* L);          // say(string)
 // Combat.
 static int ai_shoot(lua_State* L);        // shoot(number) number = 1,2,3.
 
@@ -130,6 +132,7 @@ int ai_init(void) {
   lua_register(L, "shoot",        ai_shoot);
   // Misc.
   lua_register(L, "createvect",   ai_createvect);
+  lua_register(L, "say",          ai_say);
 
   char* buf = pack_readfile(DATA, "../scripts/ai/test.lua", NULL);
 
@@ -363,6 +366,15 @@ static int ai_createvect(lua_State* L) {
   return 1;
 }
 
+static int ai_say(lua_State* L) {
+  MIN_ARGS(1);
+
+  if(lua_isstring(L, 1))
+    player_message("Comm %s> \"%s\"", cur_pilot->name, lua_tostring(L, 1));
+
+  return 0;
+}
+
 // Pew pew.. Says the pilot.
 static int ai_shoot(lua_State* L) {
   int n = 1;
diff --git a/src/main.c b/src/main.c
index 410666f..985c8df 100644
--- a/src/main.c
+++ b/src/main.c
@@ -26,13 +26,14 @@
 #define CONF_FILE       "conf"
 #define MINIMUM_FPS     0.5
 
-#define FONT_SIZE       10
+#define FONT_SIZE       12
 
 extern const char* keybindNames[]; // Keybindings.
 
 static int quit = 0; // Primary loop.
 static unsigned int time = 0; // Calculate FPS and movement.
 
+// Just some default crap.
 #define DATA_DEF  "data"
 char* data = NULL;
 static int show_fps = 1; // Default - True.
@@ -255,6 +256,9 @@ int main(int argc, char** argv) {
 
   pilot_create(get_ship("Test"), NULL, 2., NULL, NULL, 0);
 
+  player_message("Welcome to "APPNAME"!");
+  player_message(" v%d.%d.%d", VMAJOR, VMINOR, VREV);
+
   time = SDL_GetTicks();
 
   // Main looops.
diff --git a/src/opengl.h b/src/opengl.h
index fb0866f..da45e6e 100644
--- a/src/opengl.h
+++ b/src/opengl.h
@@ -43,6 +43,7 @@ typedef struct {
   GLuint* textures;
   GLuint list_base;
 } gl_font;
+extern gl_font gl_defFont; // Default font.
 
 // gl_font loading/freeing.
 // If font is NULL it uses the internal default font, same with gl_print
diff --git a/src/physics.c b/src/physics.c
index 557fcc6..e53ce8d 100644
--- a/src/physics.c
+++ b/src/physics.c
@@ -178,6 +178,8 @@ static void rk4_update(Solid* obj, const double dt) {
 void solid_init(Solid* dest, const double mass, const double dir, const Vec2* pos, const Vec2* vel) {
   dest->mass = mass;
 
+  dest->dir_vel = 0.;
+
   vect_cset(&dest->force, 0., 0.);
   dest->dir = dir;
   if((dest->dir > 2.*M_PI) || (dest->dir < 0.))
diff --git a/src/player.c b/src/player.c
index 9f44437..4b94991 100644
--- a/src/player.c
+++ b/src/player.c
@@ -89,6 +89,7 @@ typedef struct {
   Vec2 pos_radar;
   Vec2 pos_shield, pos_armor, pos_energy;
   Vec2 pos_target, pos_target_health;
+  Vec2 pos_msg;
 } GUI;
 
 GUI gui; // Le Gui!
@@ -96,8 +97,36 @@ GUI gui; // Le Gui!
 double gui_xoff = 0.;
 double gui_yoff = 0.;
 
+// Messages.
+#define MSG_SIZE_MAX 80
+int msg_timeout = 20000;
+int msg_max = 5; // Max messages on screen.
+typedef struct {
+  char str[MSG_SIZE_MAX];
+  unsigned int t;
+} Msg;
+static Msg* msg_stack;
+
 extern void pilot_render(Pilot* pilot); // Extern is in Pilot.*
 
+void player_message(const char* fmt, ...) {
+  va_list ap;
+  int i;
+
+  if(fmt == NULL) return; // Message not valid.
+
+  for(i = 1; i < msg_max; i++)
+    if(msg_stack[msg_max-i-1].str[0] != '\0') {
+      strcpy(msg_stack[msg_max-i].str, msg_stack[msg_max-i-1].str);
+      msg_stack[msg_max-i].t = msg_stack[msg_max-i-1].t;
+    }
+    va_start(ap, fmt);
+    vsprintf(msg_stack[0].str, fmt, ap);
+    va_end(ap);
+
+    msg_stack[0].t = SDL_GetTicks() + msg_timeout;
+}
+
 // Render the player.
 void player_render(void) {
   int i;
@@ -105,18 +134,19 @@ void player_render(void) {
   Pilot* p;
   Vec2 v;
 
+  // Render the player target graphics.
   if(player_target) {
     p = get_pilot(player_target);
 
     vect_csetmin(&v, VX(p->solid->pos) - p->ship->gfx_space->sw * PILOT_SIZE_APROX/2.,
           VY(p->solid->pos) + p->ship->gfx_space->sh * PILOT_SIZE_APROX/2.);
-    gl_blitSprite(gui.gfx_targetPilot, &v, 0, 0);
+    gl_blitSprite(gui.gfx_targetPilot, &v, 0, 0); // Top left.
     VX(v) += p->ship->gfx_space->sw * PILOT_SIZE_APROX;
-    gl_blitSprite(gui.gfx_targetPilot, &v, 1, 0);
+    gl_blitSprite(gui.gfx_targetPilot, &v, 1, 0); // Top right.
     VY(v) -= p->ship->gfx_space->sh * PILOT_SIZE_APROX;
-    gl_blitSprite(gui.gfx_targetPilot, &v, 1, 1);
+    gl_blitSprite(gui.gfx_targetPilot, &v, 1, 1); // Bottom right.
     VX(v) -= p->ship->gfx_space->sw * PILOT_SIZE_APROX;
-    gl_blitSprite(gui.gfx_targetPilot, &v, 0, 1);
+    gl_blitSprite(gui.gfx_targetPilot, &v, 0, 1); // Bottom left.
   }
 
   // Render the player.
@@ -165,6 +195,8 @@ void player_render(void) {
           glVertex2d(MAX(x-sx, -gui.radar.w/2.), MAX(y-sy, -gui.radar.h/2.)); // Bottom left.
         glEnd(); // The Quads.
       }
+      glBegin(GL_POINTS); // For ze player.
+      break;
     case RADAR_CIRCLE:
       glBegin(GL_POINTS);
       for(i = 1; i < pilots; i++) {
@@ -241,6 +273,17 @@ void player_render(void) {
       // On armor.
       gl_print(NULL, &gui.pos_target_health, "%s: %.0f%%", "Armor", p->armor/p->armor_max*100.);
   }
+  // Messages.
+  VX(v) = VX(gui.pos_msg);
+  VY(v) = VY(gui.pos_msg) + (double)(gl_defFont.h*msg_max)*1.2;
+  for(i = 0; i < msg_max; i++) {
+    VY(v) -= (double)gl_defFont.h*1.2;
+    if(msg_stack[msg_max-i-1].str[0] != '\0') {
+      if(msg_stack[msg_max-i-1].t < SDL_GetTicks())
+        msg_stack[msg_max-i-1].str[0] = '\0';
+      else gl_print(NULL, &v, "%s", msg_stack[msg_max-i-1].str);
+    }
+  }
 }
 
 // Init GUI.
@@ -288,6 +331,9 @@ int gui_init(void) {
         VX(gui.pos_frame) + 10 + 10,
         VY(gui.pos_frame) + gui.gfx_frame->h - 256 - SHIP_TARGET_H + 10);
 
+  // Message system.
+  vect_csetmin(&gui.pos_msg, 20, 30);
+  msg_stack = calloc(msg_max, sizeof(Msg));
 
   return 0;
 
@@ -296,6 +342,10 @@ int gui_init(void) {
 // Free the GUI.
 void gui_free(void) {
   gl_freeTexture(gui.gfx_frame);
+  gl_freeTexture(gui.gfx_targetPilot);
+  gl_freeTexture(gui.gfx_targetPlanet);
+
+  free(msg_stack);
 }
 
 // Used in pilot.c
diff --git a/src/player.h b/src/player.h
index c98e3a1..46a517f 100644
--- a/src/player.h
+++ b/src/player.h
@@ -21,3 +21,6 @@ void input_exit(void);
 void input_setKeybind(char* keybind, KeybindType type, int key, int reverse);
 void input_handle(SDL_Event* event);
 
+// Misc.
+void player_message(const char* fmt, ...);
+