diff -Nru tremulous/src/game/g_cmds.c tremulous.temp/src/game/g_cmds.c
--- tremulous/src/game/g_cmds.c	2007-02-28 18:32:04.000000000 +0100
+++ tremulous.temp/src/game/g_cmds.c	2007-02-28 18:32:04.000000000 +0100
@@ -960,6 +960,17 @@
     }
   }
 
+  if( g_allowShare.integer )
+  {
+    args = G_SayConcatArgs(0);
+    if( !Q_stricmpn( args, "say /share", 10 ) ||
+      !Q_stricmpn( args, "say_team /share", 15 ) )
+    {
+      Cmd_Share_f( ent );
+      return;
+    }
+  }
+
   if( trap_Argc( ) < 2 && !arg0 )
     return;
 
@@ -2716,6 +2727,209 @@
   ent->client->lastPoisonClient = ent;*/
 }
 
+/*
+=================
+Cmd_Share_f
+=================
+*/
+void Cmd_Share_f( gentity_t *ent )
+{
+  int   i, clientNum = 0, creds = 0, skipargs = 0;
+  int   clientNums[ MAX_CLIENTS ] = { -1 };
+  char  cmd[ 12 ];
+  char  arg1[ MAX_STRING_TOKENS ];
+  char  arg2[ MAX_STRING_TOKENS ];
+  pTeam_t team;
+
+  if( !ent || !ent->client || ( ent->client->pers.teamSelection == PTE_NONE ) )
+  {
+    return;
+  }
+  
+  if( !g_allowShare.integer )
+  {
+    return;
+  }
+
+  team = ent->client->pers.teamSelection;
+
+  G_SayArgv( 0, cmd, sizeof( cmd ) );
+  if( !Q_stricmp( cmd, "say" ) || !Q_stricmp( cmd, "say_team" ) )
+  {
+    skipargs = 1;
+    G_SayArgv( 1, cmd, sizeof( cmd ) );
+  }
+
+  // target player name is in arg1
+  G_SayArgv( 1+skipargs, arg1, sizeof( arg1 ) );
+  // amount to be shared is in arg2
+  G_SayArgv( 2+skipargs, arg2, sizeof( arg2 ) );
+
+  if( arg1[0] && !strchr( arg1, ';' ) && Q_stricmp( arg1, "target_in_aim" ) )
+  {
+    //check arg1 is a number
+    for( i = 0; arg1[ i ]; i++ )
+    {
+      if( arg1[ i ] < '0' || arg1[ i ] > '9' )
+      {
+        clientNum = -1;
+        break;
+      }
+    }
+
+    if( clientNum >= 0 )
+    {
+      clientNum = atoi( arg1 );
+    }
+    else if( G_ClientNumbersFromString( arg1, clientNums ) == 1 )
+    {
+      // there was one partial name match
+      clientNum = clientNums[ 0 ]; 
+    }
+    else
+    {
+      // look for an exact name match before bailing out
+      clientNum = G_ClientNumberFromString( ent, arg1 );
+      if( clientNum == -1 )
+      {
+        trap_SendServerCommand( ent-g_entities,
+          "print \"share: invalid player name specified.\n\"" );
+        return;
+      }
+    }
+  }
+  else // arg1 not set
+  {
+    vec3_t      forward, end;
+    trace_t     tr;
+    gentity_t   *traceEnt;
+
+    
+    // trace a teammate
+    AngleVectors( ent->client->ps.viewangles, forward, NULL, NULL );
+    VectorMA( ent->client->ps.origin, 8192 * 16, forward, end );
+
+    trap_Trace( &tr, ent->client->ps.origin, NULL, NULL, end, ent->s.number, MASK_PLAYERSOLID );
+    traceEnt = &g_entities[ tr.entityNum ];
+
+    if( tr.fraction < 1.0f && traceEnt->client &&
+      ( traceEnt->client->pers.teamSelection == team ) )
+    {
+      clientNum = traceEnt - g_entities;
+    }
+    else
+    {
+      trap_SendServerCommand( ent-g_entities,
+        va( "print \"share: aim at a teammate to share %s.\n\"",
+        ( team == PTE_HUMANS ) ? "credits" : "evolvepoints" ) );
+      return;
+    }
+  }
+
+  // verify target player team
+  if( ( clientNum < 0 ) || ( clientNum >= level.maxclients ) ||
+      ( level.clients[ clientNum ].pers.teamSelection != team ) )
+  {
+    trap_SendServerCommand( ent-g_entities,
+      "print \"share: not a valid player of your team.\n\"" );
+    return;
+  }
+
+  if( !arg2[0] || strchr( arg2, ';' ) )
+  {
+    // default credit count
+    if( team == PTE_HUMANS )
+    {
+      creds = FREEKILL_HUMAN;
+    }
+    else if( team == PTE_ALIENS )
+    {
+      creds = FREEKILL_ALIEN;
+    }
+  }
+  else
+  {
+    //check arg2 is a number
+    for( i = 0; arg2[ i ]; i++ )
+    {
+      if( arg2[ i ] < '0' || arg2[ i ] > '9' )
+      {
+        trap_SendServerCommand( ent-g_entities,
+          "print \"usage: share [name|slot#] [amount]\n\"" );
+        break;
+      }
+    }
+
+    // credit count from parameter
+    creds = atoi( arg2 );
+  }
+
+  // player specified "0" to transfer
+  if( creds <= 0 )
+  {
+    trap_SendServerCommand( ent-g_entities,
+      "print \"Ooh, you are a generous one, indeed!\n\"" );
+    return;
+  }
+
+  // transfer only credits the player really has
+  if( creds > ent->client->ps.persistant[ PERS_CREDIT ] )
+  {
+    creds = ent->client->ps.persistant[ PERS_CREDIT ];
+  }
+
+  // player has no credits
+  if( creds <= 0 )
+  {
+    trap_SendServerCommand( ent-g_entities,
+      "print \"Earn some first, lazy gal!\n\"" );
+    return;
+  }
+
+  // allow transfers only up to the credit/evo limit
+  if( ( team == PTE_HUMANS ) && 
+      ( creds > HUMAN_MAX_CREDITS - level.clients[ clientNum ].ps.persistant[ PERS_CREDIT ] ) )
+  {
+    creds = HUMAN_MAX_CREDITS - level.clients[ clientNum ].ps.persistant[ PERS_CREDIT ];
+  }
+  else if( ( team == PTE_ALIENS ) && 
+      ( creds > ALIEN_MAX_KILLS - level.clients[ clientNum ].ps.persistant[ PERS_CREDIT ] ) )
+  {
+    creds = ALIEN_MAX_KILLS - level.clients[ clientNum ].ps.persistant[ PERS_CREDIT ];
+  }
+
+  // target cannot take any more credits
+  if( creds <= 0 )
+  {
+    trap_SendServerCommand( ent-g_entities,
+      va( "print \"share: player cannot receive any more %s.\n\"",
+        ( team == PTE_HUMANS ) ? "credits" : "evolvepoints" ) );
+    return;
+  }
+
+  // transfer credits
+  ent->client->ps.persistant[ PERS_CREDIT ] -= creds;
+  trap_SendServerCommand( ent-g_entities,
+    va( "print \"share: transferred %d %s to %s^7.\n\"", creds,
+      ( team == PTE_HUMANS ) ? "credits" : "evolvepoints",
+      level.clients[ clientNum ].pers.netname ) );
+  level.clients[ clientNum ].ps.persistant[ PERS_CREDIT ] += creds;
+  trap_SendServerCommand( clientNum,
+    va( "print \"You have received %d %s from %s^7.\n\"", creds,
+      ( team == PTE_HUMANS ) ? "credits" : "evolvepoints",
+      ent->client->pers.netname ) );
+
+  G_LogPrintf( "Share: %i %i %i %d: %s^7 transferred %d%s to %s^7\n",
+    ent->client->ps.clientNum,
+    clientNum,
+    team,
+    creds,
+    ent->client->pers.netname,
+    creds,
+    ( team == PTE_HUMANS ) ? "c" : "e",
+    level.clients[ clientNum ].pers.netname );
+}
+
 
 /*
 =================
@@ -2830,6 +3044,8 @@
     Cmd_PTRCRestore_f( ent );
   else if( Q_stricmp( cmd, "test" ) == 0 )
     Cmd_Test_f( ent );
+  else if( Q_stricmp( cmd, "share" ) == 0 )
+    Cmd_Share_f( ent );
   else
     trap_SendServerCommand( clientNum, va( "print \"unknown cmd %s\n\"", cmd ) );
 }
diff -Nru tremulous/src/game/g_local.h tremulous.temp/src/game/g_local.h
--- tremulous/src/game/g_local.h	2007-02-28 18:32:00.000000000 +0100
+++ tremulous.temp/src/game/g_local.h	2007-02-28 18:32:04.000000000 +0100
@@ -682,6 +682,8 @@
 void      G_ChangeTeam( gentity_t *ent, pTeam_t newTeam );
 void      G_SanitiseName( char *in, char *out );
 void      G_PrivateMessage( gentity_t *ent );
+void      Cmd_Share_f( gentity_t *ent );
+
 
 //
 // g_physics.c
@@ -1120,6 +1122,7 @@
 extern  vmCvar_t  pmove_fixed;
 extern  vmCvar_t  pmove_msec;
 extern  vmCvar_t  g_rankings;
+extern  vmCvar_t  g_allowShare;
 extern  vmCvar_t  g_enableDust;
 extern  vmCvar_t  g_enableBreath;
 extern  vmCvar_t  g_singlePlayer;
diff -Nru tremulous/src/game/g_main.c tremulous.temp/src/game/g_main.c
--- tremulous/src/game/g_main.c	2007-02-28 18:32:00.000000000 +0100
+++ tremulous.temp/src/game/g_main.c	2007-02-28 18:32:04.000000000 +0100
@@ -137,6 +137,8 @@
 
 vmCvar_t  g_dretchPunt;
 
+vmCvar_t  g_allowShare;
+
 static cvarTable_t   gameCvarTable[ ] =
 {
   // don't override the cheat state set by the system
@@ -258,7 +260,9 @@
   
   { &g_dretchPunt, "g_dretchPunt", "1", CVAR_ARCHIVE, 0, qfalse  },
   
-  { &g_rankings, "g_rankings", "0", 0, 0, qfalse}
+  { &g_rankings, "g_rankings", "0", 0, 0, qfalse},
+  
+  { &g_allowShare, "g_allowShare", "1", CVAR_ARCHIVE, 0, qfalse}
 };
 
 static int gameCvarTableSize = sizeof( gameCvarTable ) / sizeof( gameCvarTable[ 0 ] );
