diff -ru tremulous-aw-901/src/game/bg_public.h tremulous-aw-901_warmup/src/game/bg_public.h
--- tremulous-aw-901/src/game/bg_public.h	2007-03-19 17:26:45.000000000 +0100
+++ tremulous-aw-901_warmup/src/game/bg_public.h	2007-03-22 15:27:39.000000000 +0100
@@ -34,6 +34,8 @@
 
 #define VOTE_TIME               30000 // 30 seconds before vote times out
 
+#define WARMUPMESSAGE_TIME      1000 // 1 second between two warmup messages
+
 #define MINS_Z                  -24
 #define DEFAULT_VIEWHEIGHT      26
 #define CROUCH_VIEWHEIGHT       12
diff -ru tremulous-aw-901/src/game/g_cmds.c tremulous-aw-901_warmup/src/game/g_cmds.c
--- tremulous-aw-901/src/game/g_cmds.c	2007-03-19 17:26:45.000000000 +0100
+++ tremulous-aw-901_warmup/src/game/g_cmds.c	2007-03-22 15:39:03.000000000 +0100
@@ -660,9 +660,11 @@
   if( g_doWarmup.integer &&
       level.time - level.startTime < g_warmup.integer * 1000 )
   {
+    /*
     trap_SendServerCommand( ent - g_entities, va( "print \"team: you can't join"
       " a team during warm up (%d seconds remaining)\n\"",
       g_warmup.integer - ( level.time - level.startTime ) / 1000 ) );
+    */
     return;
   }
 
diff -ru tremulous-aw-901/src/game/g_local.h tremulous-aw-901_warmup/src/game/g_local.h
--- tremulous-aw-901/src/game/g_local.h	2007-03-19 17:26:45.000000000 +0100
+++ tremulous-aw-901_warmup/src/game/g_local.h	2007-03-22 15:39:15.000000000 +0100
@@ -655,6 +655,8 @@
   int unlaggedTimes[ MAX_UNLAGGED_MARKERS ];
 
   char              layout[ MAX_QPATH ];
+  
+  int               warmupMessageTime;            // last warmup message level.time
 } level_locals_t;
 
 //
@@ -1113,6 +1115,7 @@
 extern  vmCvar_t  g_motd;
 extern  vmCvar_t  g_warmup;
 extern  vmCvar_t  g_doWarmup;
+extern  vmCvar_t  g_warmupMessage;
 extern  vmCvar_t  g_blood;
 extern  vmCvar_t  g_allowVote;
 extern  vmCvar_t  g_allowSpecVoting;
diff -ru tremulous-aw-901/src/game/g_main.c tremulous-aw-901_warmup/src/game/g_main.c
--- tremulous-aw-901/src/game/g_main.c	2007-03-19 17:26:45.000000000 +0100
+++ tremulous-aw-901_warmup/src/game/g_main.c	2007-03-22 15:47:14.000000000 +0100
@@ -69,6 +69,7 @@
 vmCvar_t  g_synchronousClients;
 vmCvar_t  g_warmup;
 vmCvar_t  g_doWarmup;
+vmCvar_t  g_warmupMessage;
 vmCvar_t  g_restarted;
 vmCvar_t  g_logFile;
 vmCvar_t  g_logFileSync;
@@ -177,6 +178,7 @@
 
   { &g_warmup, "g_warmup", "20", CVAR_ARCHIVE, 0, qtrue  },
   { &g_doWarmup, "g_doWarmup", "1", CVAR_ARCHIVE, 0, qtrue  },
+  { &g_warmupMessage, "g_warmupMessage", "", CVAR_ARCHIVE, 0, qtrue  },
   { &g_logFile, "g_logFile", "games.log", CVAR_ARCHIVE, 0, qfalse  },
   { &g_logFileSync, "g_logFileSync", "0", CVAR_ARCHIVE, 0, qfalse  },
 
@@ -1511,6 +1513,9 @@
   trap_SetConfigstring( CS_TEAMVOTE_TIME, "" );
   level.teamVoteTime[ 1 ] = 0;
   trap_SetConfigstring( CS_TEAMVOTE_TIME + 1, "" );
+  
+  // reset warmup messages
+  level.warmupMessageTime = 0;
 
   FindIntermissionPoint( );
 
@@ -2012,6 +2017,41 @@
 
 /*
 ==================
+CheckWarmup
+==================
+*/
+void CheckWarmup( void )
+{
+  if( g_doWarmup.integer &&
+      level.time - level.startTime < g_warmup.integer * 1000 &&
+      level.time - level.warmupMessageTime >= WARMUPMESSAGE_TIME )
+  {
+    int secs;
+    
+    level.warmupMessageTime = level.time;
+    secs = g_warmup.integer - ((level.time - level.startTime) / 1000) - 1;
+    
+    if( secs > 0 ) {
+      char *color = "";
+      
+      if( secs > 9 )
+        color = "^2";
+      else if( secs > 3 )
+        color = "^3";
+      else if( secs > 0 )
+        color = "^1";
+
+      trap_SendConsoleCommand( EXEC_APPEND, va( "cp ^7%s%s%d\n", g_warmupMessage.string, color, secs ) );
+    } else if( ! secs ) {
+      trap_SendConsoleCommand( EXEC_APPEND, va( "cp ^2Fight!\n" ) );
+    }
+    
+  }
+}
+
+
+/*
+==================
 CheckTeamVote
 ==================
 */
@@ -2295,6 +2335,9 @@
   // cancel vote if timed out
   CheckVote( );
 
+  // cancel if there's a warmup message to print
+  CheckWarmup( );
+
   // check team votes
   CheckTeamVote( PTE_HUMANS );
   CheckTeamVote( PTE_ALIENS );
