diff -uNr teeworlds-0.5.1-old/src/game/server/entities/character.cpp teeworlds-0.5.1-flagball/src/game/server/entities/character.cpp
--- teeworlds-0.5.1-old/src/game/server/entities/character.cpp	2009-10-04 18:36:26.335735745 +0400
+++ teeworlds-0.5.1-flagball/src/game/server/entities/character.cpp	2009-10-04 18:36:25.299977855 +0400
@@ -208,9 +208,9 @@
 	//	drop ball
 	game.create_sound_global (SOUND_CTF_DROP);
 	ball->drop_tick = server_tick ();
-	ball->last_carrying_player = player;
-	ball->last_carrying_player_team = team;
-	ball->carrying_character = 0;
+	ball->last_carrier = player;
+	ball->last_carrier_team = team;
+	ball->carrier = 0;
 	ball->vel = direction;
         ball = NULL;
 
@@ -225,8 +225,8 @@
 void CHARACTER::capture_ball(BALL* b) 
 {
 	ball = b;
-	b->carrying_character = this;
-	b->last_carrying_player = 0;
+	b->carrier = this;
+	b->last_carrier_team = team;
 	b->pos = core.pos;
 	b->at_stand = 0;
 
@@ -632,7 +632,7 @@
 		for (int i = 0; i < FB_MAX_BALLS; ++i)
 		{
 			BALL* b = static_cast<GAMECONTROLLER_FB *>(game.controller)->balls[i];
-			if (b && !b->carrying_character)
+			if (b && !b->carrier)
 			{
 				// It may be not a good idea to pass this to
 				// config, but we need some easy way to test
diff -uNr teeworlds-0.5.1-old/src/game/server/entities/laser.cpp teeworlds-0.5.1-flagball/src/game/server/entities/laser.cpp
--- teeworlds-0.5.1-old/src/game/server/entities/laser.cpp	2009-10-04 18:36:26.300727098 +0400
+++ teeworlds-0.5.1-flagball/src/game/server/entities/laser.cpp	2009-10-04 18:36:25.298976832 +0400
@@ -3,6 +3,8 @@
 #include <game/generated/g_protocol.hpp>
 #include <game/server/gamecontext.hpp>
 #include "laser.hpp"
+#include <game/server/gamemodes/fb.hpp>
+#include <engine/e_config.h>
 
 //////////////////////////////////////////////////
 // laser
@@ -31,11 +33,29 @@
 
 	this->from = from;
 	pos = at;
+	hit_ball(from, pos);
 	energy = -1;		
 	hit->take_damage(vec2(0,0), tuning.laser_damage, owner, WEAPON_RIFLE);
 	return true;
 }
 
+void LASER::hit_ball(vec2 from, vec2 to) {
+	if (config.sv_fb_laser_momentum == 0) return;
+	for (int i = 0; i < FB_MAX_BALLS; ++i)
+	{
+		BALL* ball = static_cast<GAMECONTROLLER_FB *>(game.controller)->balls[i];
+		if (!ball || ball->carrier) continue;
+		vec2 ball_pos = ball->pos + vec2(config.sv_fb_ball_offset_x, -config.sv_fb_ball_offset_y);
+		if (distance(ball_pos, closest_point_on_line(from, to, ball_pos)) < config.sv_fb_ball_radius)
+		{
+			ball->vel += normalize(to - from) * config.sv_fb_laser_momentum * 0.1f;
+			ball->drop_tick = server_tick();
+			ball->last_carrier = game.players[owner];
+			ball->last_carrier_team = game.players[owner]->team;
+		}
+	};
+};
+
 void LASER::do_bounce()
 {
 	eval_tick = server_tick();
@@ -54,6 +74,7 @@
 	{
 		if(!hit_character(pos, to))
 		{
+			hit_ball(pos, to);
 			// intersected
 			from = pos;
 			pos = to;
@@ -78,6 +99,7 @@
 	{
 		if(!hit_character(pos, to))
 		{
+			hit_ball(pos, to);
 			from = pos;
 			pos = to;
 			energy = -1;
diff -uNr teeworlds-0.5.1-old/src/game/server/entities/laser.hpp teeworlds-0.5.1-flagball/src/game/server/entities/laser.hpp
--- teeworlds-0.5.1-old/src/game/server/entities/laser.hpp	2009-10-04 18:36:26.300727098 +0400
+++ teeworlds-0.5.1-flagball/src/game/server/entities/laser.hpp	2009-10-04 18:36:25.296977203 +0400
@@ -17,6 +17,7 @@
 	int owner;
 	
 	bool hit_character(vec2 from, vec2 to);
+	void hit_ball(vec2 from, vec2 to);
 	void do_bounce();
 	
 public:
diff -uNr teeworlds-0.5.1-old/src/game/server/gamemodes/fb.cpp teeworlds-0.5.1-flagball/src/game/server/gamemodes/fb.cpp
--- teeworlds-0.5.1-old/src/game/server/gamemodes/fb.cpp	2009-10-04 18:36:26.345726700 +0400
+++ teeworlds-0.5.1-flagball/src/game/server/gamemodes/fb.cpp	2009-10-04 18:36:26.298735787 +0400
@@ -58,19 +58,19 @@
 	for (int i = 0; i < FB_MAX_BALLS; i++)
 	{
 		BALL *b = balls[i];
-		if (!b || !b->carrying_character)
+		if (!b || !b->carrier)
 			continue;
 
-		if (killer && b->carrying_character == killer->get_character())
+		if (killer && b->carrier == killer->get_character())
 			had_flag |= 2;
-		if (b->carrying_character == victim)
+		if (b->carrier == victim)
 		{
 			//	drop ball
 			game.create_sound_global (SOUND_CTF_DROP);
 			b->drop_tick = server_tick ();
-			b->last_carrying_player = victim->player;
-			b->last_carrying_player_team = victim->team;
-			b->carrying_character = 0;
+			b->last_carrier = victim->player;
+			b->last_carrier_team = victim->team;
+			b->carrier = 0;
 			victim->ball = NULL;
 			b->vel = vec2 (0, 0);
 
@@ -109,10 +109,10 @@
 
 bool GAMECONTROLLER_FB::handle_goal (BALL *b, int goal)
 {
-	PLAYER *const p = b->carrying_character ? b->carrying_character->player : b->last_carrying_player;
-	const int team = b->carrying_character ? p->team : b->last_carrying_player_team;
+	PLAYER *const p = b->carrier ? b->carrier->player : b->last_carrier;
+	const int team = b->last_carrier_team;
 	const bool own_goal = team == goal;
-	const bool tee_goal = b->carrying_character ? true : false;
+	const bool tee_goal = b->carrier ? true : false;
 	
 	//	update scores
 	if (own_goal)
@@ -182,7 +182,7 @@
 	game.send_broadcast(bc_msg, -1);
 
 	// kick unteachable player from server
-	if (config.sv_fb_owngoal_kick && p->num_owngoals >= config.sv_fb_owngoal_kick)
+	if (config.sv_fb_owngoal_kick && p && p->num_owngoals >= config.sv_fb_owngoal_kick)
 	{
 		char chat_msg[256];
 		str_format (chat_msg, sizeof (chat_msg), "%s was automatically kicked. Cause: Scored too many own-goals (%d).",
@@ -202,8 +202,13 @@
 {
 	for (int i = 0; i < FB_MAX_BALLS; ++i)
 	{
-		if (balls[i] && !balls[i]->at_stand && p == balls[i]->last_carrying_player)
-			balls[i]->last_carrying_player = 0;
+		if (balls[i] && !balls[i]->at_stand)
+		{
+			if (balls[i]->carrier && p == balls[i]->carrier->player)
+				balls[i]->carrier = NULL;
+			if (p == balls[i]->last_carrier)
+				balls[i]->last_carrier = NULL;
+		}
 	}
 }
 
@@ -218,10 +223,24 @@
 		
 		for (int i = 0; i < MAX_CLIENTS; ++i)
 		{
-			if (!game.players[i] || game.players[i]->team == -1)
-				continue;
+			if (!game.players[i]) continue;
 
 			//	auto-kick if idle
+                        if (game.players[i]->team == -1)
+                        {
+                                 if (config.sv_fb_spectator_idle_time 
+                                         && game.players[i]->last_mousemove_tick + config.sv_fb_spectator_idle_time * server_tickspeed () <= server_tick ())
+                                 {
+                                                 char chat_msg[256];
+                                                 str_format (chat_msg, sizeof (chat_msg), "%s was automatically kicked. Cause: Has been idling too long (%d).",
+                                                         server_clientname (game.players[i]->client_id), config.sv_fb_idle_time);
+
+                                                 server_kick (game.players[i]->client_id,
+                                                         "You have been idling too long!");
+                                 };
+                                 continue;
+                        };
+
 			if (config.sv_fb_idle_time &&
 				game.players[i]->last_mousemove_tick + config.sv_fb_idle_time * server_tickspeed () <= server_tick ())
 			{	
@@ -327,8 +346,8 @@
 				continue;
 
 			//	update ball position
-			if (b->carrying_character)
-				b->pos = b->carrying_character->pos;
+			if (b->carrier)
+				b->pos = b->carrier->pos;
 			else if (!b->at_stand)
 				{	
 					//	ball hits death tile
@@ -378,23 +397,23 @@
 			if (is_goal)
 				continue;
 
-			if (b->carrying_character)
+			if (b->carrier)
 			{	//	ball is carried by player
 
 				//	warn ball-carrying player once when he is near his own goal
-				if (config.sv_fb_owngoal_warn && !b->carrying_character->player->owngoal_warned && b->carrying_character->team < num_goals &&
-					(distance(b->carrying_character->pos, goal_pos[b->carrying_character->team]) < config.sv_fb_goalsize * 5))
+				if (config.sv_fb_owngoal_warn && !b->carrier->player->owngoal_warned && b->carrier->team < num_goals &&
+					(distance(b->carrier->pos, goal_pos[b->carrier->team]) < config.sv_fb_goalsize * 5))
 				{
 					game.send_broadcast(
 						"Attention! This is your team's goal\n"
 						"you are approaching. You probably\n"
 						"want to go to the other side!",
-						b->carrying_character->player->client_id);
+						b->carrier->player->client_id);
 
 					// play the server-chat sound
-					game.create_sound(b->carrying_character->pos, SOUND_CHAT_SERVER, cmask_one(b->carrying_character->player->client_id));
+					game.create_sound(b->carrier->pos, SOUND_CHAT_SERVER, cmask_one(b->carrier->player->client_id));
 
-					b->carrying_character->player->owngoal_warned = true;
+					b->carrier->player->owngoal_warned = true;
 				}
 			}
 			else
@@ -410,7 +429,7 @@
 					for (int i = 0; i < max_num; ++i)
 					{
 						if (!close_characters[i]->alive || close_characters[i]->team == -1 || col_intersect_line (b->pos, close_characters[i]->pos, NULL, NULL) ||
-							balls[bi ^ 1]->carrying_character == close_characters[i]) // don't take flag if already have one (might be useful with two flags)
+							balls[bi ^ 1]->carrier == close_characters[i]) // don't take flag if already have one (might be useful with two flags)
 							continue;
 						close_characters[curr_num++] = close_characters[i];
 					}
@@ -426,16 +445,8 @@
 						ch->player->score += config.sv_fb_score_player_stand;
 						b->at_stand = 0;
 					}				
-					b->carrying_character = ch;
-					b->last_carrying_player = 0;
-					ch->ball = b;
-
-					// switch to ninja-ball-mode
-					ch->ninja.activationtick = server_tick();
-					ch->weapons[WEAPON_NINJA].got = true;
-					ch->weapons[WEAPON_NINJA].ammo = -1;
-					ch->last_weapon = ch->active_weapon;
-					ch->active_weapon = WEAPON_NINJA;
+
+					ch->capture_ball(b);
 
 					for (int c = 0; c < MAX_CLIENTS; c++)
 					{
@@ -466,9 +477,9 @@
 
 void BALL::reset ()
 {
-	carrying_character = 0;
-	last_carrying_player = 0;
-	last_carrying_player_team = team;
+	carrier = 0;
+	last_carrier = 0;
+	last_carrier_team = team;
 	at_stand = 1;
 	pos = stand_pos;
 	vel = vec2 (0, 0);
@@ -485,11 +496,12 @@
 	NETOBJ_FLAG *ball = static_cast<NETOBJ_FLAG *> (snap_new_item (NETOBJTYPE_FLAG, team, sizeof (NETOBJ_FLAG)));
 	ball->x = static_cast<int> (pos.x);
 	ball->y = static_cast<int> (pos.y);
-	ball->team = team;
+	if (config.sv_fb_laser_momentum) ball->team = last_carrier_team;
+	else ball->team = team;
 	ball->carried_by = -1;
 	
 	if (at_stand)
 		ball->carried_by = -2;
-	else if (carrying_character && carrying_character->player)
-		ball->carried_by = carrying_character->player->client_id;
+	else if (carrier && carrier->player)
+		ball->carried_by = carrier->player->client_id;
 }
diff -uNr teeworlds-0.5.1-old/src/game/server/gamemodes/fb.hpp teeworlds-0.5.1-flagball/src/game/server/gamemodes/fb.hpp
--- teeworlds-0.5.1-old/src/game/server/gamemodes/fb.hpp	2009-10-04 18:36:26.345726700 +0400
+++ teeworlds-0.5.1-flagball/src/game/server/gamemodes/fb.hpp	2009-10-04 18:36:26.298735787 +0400
@@ -27,9 +27,9 @@
 {
 public:
 	static const int phys_size = 14;
-	CHARACTER *carrying_character;
-	PLAYER *last_carrying_player;
-	int last_carrying_player_team;
+	CHARACTER *carrier;
+	PLAYER *last_carrier;
+	int last_carrier_team;
 	vec2 vel;
 	vec2 stand_pos;
 	
diff -uNr teeworlds-0.5.1-old/src/game/variables.hpp teeworlds-0.5.1-flagball/src/game/variables.hpp
--- teeworlds-0.5.1-old/src/game/variables.hpp	2009-10-04 18:36:26.345726700 +0400
+++ teeworlds-0.5.1-flagball/src/game/variables.hpp	2009-10-04 18:36:25.312976763 +0400
@@ -76,13 +76,15 @@
 MACRO_CONFIG_INT(sv_fb_ball_offset_x, 0, 0, 1000, CFGFLAG_SERVER, "X offset of the hookable center of the ball with respect to the lower left corner of the image (default=0)")
 MACRO_CONFIG_INT(sv_fb_ball_offset_y, 38, 0, 1000, CFGFLAG_SERVER, "Y offset of the hookable center of the ball with respect to the lower left corner of the image (default=0)")
 MACRO_CONFIG_INT(sv_fb_ball_radius, 40, 0, 1000, CFGFLAG_SERVER, "Flag hookable radius")
+MACRO_CONFIG_INT(sv_fb_laser_momentum, 207, -3000, 3000, CFGFLAG_SERVER, "Momentum passed to a flag when it is hit by laser (default=207)")
 MACRO_CONFIG_INT(sv_fb_goalsize, 64, 32, 500, CFGFLAG_SERVER, "Radius defining goal (default=64).")
 MACRO_CONFIG_INT(sv_fb_goalcamp, 1, 0, 1, CFGFLAG_SERVER, "Turns on/off goal camp protection (0=off, 1=on (default=1)).")
 MACRO_CONFIG_INT(sv_fb_goalcamp_time, 3, 1, 600, CFGFLAG_SERVER, "Number of seconds allowed lingering near a goal (default=3).")
 MACRO_CONFIG_INT(sv_fb_goalcamp_factor, 40, 10, 100, CFGFLAG_SERVER, "Goal camp protection radius (value/10.0*sv_fb_goalsize (default=40)).")
 MACRO_CONFIG_INT(sv_fb_hook_ball, 1, 0, 1, CFGFLAG_SERVER, "Turns on/off the possibily to capture the ball by hook (0=off, 1=on (default=1))")
-MACRO_CONFIG_STR(sv_fb_on_idle, 10, "spectate", CFGFLAG_SERVER, "What to do when player idling too long. Possible values: spectate, kick. Default is nothing")
-MACRO_CONFIG_INT(sv_fb_idle_time, 90, 0, 600, CFGFLAG_SERVER, "Number of seconds after an idling player gets kicked or being forced to join to spectators (0=off (default=90)).")
+MACRO_CONFIG_STR(sv_fb_on_idle, 10, ".", CFGFLAG_SERVER, "What to do when player idling too long. Possible values: spectate, kick. Default is nothing")
+MACRO_CONFIG_INT(sv_fb_idle_time, 0, 0, 600, CFGFLAG_SERVER, "Number of seconds after an idling player gets kicked or being forced to join to spectators (0=off (default=90)).")
+MACRO_CONFIG_INT(sv_fb_spectator_idle_time, 0, 0, 10000, CFGFLAG_SERVER, "Number of seconds after an idling spectator gets kicked");
 MACRO_CONFIG_INT(sv_fb_instagib, 0, 0, 1, CFGFLAG_SERVER, "Turns on/off instagib modification (0=off, 1=on (default=0)).")
 MACRO_CONFIG_INT(sv_fb_owngoal, 1, 0, 1, CFGFLAG_SERVER, "Turns on/off own goals (0=off, 1=on (default=1)).")
 MACRO_CONFIG_INT(sv_fb_owngoal_kick, 2, 0, 20, CFGFLAG_SERVER, "Number of own goals allowed before kicking the player (0=infinite (default=2)).")
diff -uNr teeworlds-0.5.1-old/src/game/version.hpp teeworlds-0.5.1-flagball/src/game/version.hpp
--- teeworlds-0.5.1-old/src/game/version.hpp	2009-10-04 18:36:26.345726700 +0400
+++ teeworlds-0.5.1-flagball/src/game/version.hpp	2009-10-04 18:36:25.234986115 +0400
@@ -4,4 +4,4 @@
 #define GAME_NETVERSION "0.5 " GAME_NETVERSION_HASH
 
 /*	FlagBall-MOD version	*/
-#define MOD_VERSION "0.1.16"
+#define MOD_VERSION "1.17"
