diff --git a/src/action/action_research.cpp b/src/action/action_research.cpp
index 6c664fe1d..9f68ac09b 100644
--- a/src/action/action_research.cpp
+++ b/src/action/action_research.cpp
@@ -100,6 +100,11 @@ void HandleActionResearch(CUnit *unit)
 
 		unit->Player->Notify(NotifyGreen, unit->X, unit->Y,
 			_("%s: complete"), unit->Type->Name.c_str());
+		if (unit->Player == ThisPlayer) {
+			if (GameSounds.ResearchComplete[unit->Player->Race].Sound) 
+				PlayGameSound(GameSounds.ResearchComplete[unit->Player->Race].Sound,
+							MaxSampleVolume);
+		}
 		if (unit->Player->AiEnabled) {
 			AiResearchComplete(unit, upgrade);
 		}
diff --git a/src/editor/editloop.cpp b/src/editor/editloop.cpp
index 59d54cff8..bae2fe5b1 100644
--- a/src/editor/editloop.cpp
+++ b/src/editor/editloop.cpp
@@ -1387,7 +1387,7 @@ static void EditorCallbackButtonDown(unsigned button)
 				if (!UnitPlacedThisPress && CursorBuilding) {
 					if (CanBuildUnitType(NULL, CursorBuilding,
 							tileX, tileY, 1)) {
-						PlayGameSound(GameSounds.PlacementSuccess.Sound,
+						PlayGameSound(GameSounds.PlacementSuccess[ThisPlayer->Race].Sound,
 							MaxSampleVolume);
 						EditorPlaceUnit(tileX, tileY,
 							CursorBuilding, Players + Editor.SelectedPlayer);
@@ -1395,7 +1395,7 @@ static void EditorCallbackButtonDown(unsigned button)
 						UI.StatusLine.Clear();
 					} else {
 						UI.StatusLine.Set(_("Unit can't be placed here."));
-						PlayGameSound(GameSounds.PlacementError.Sound,
+						PlayGameSound(GameSounds.PlacementError[ThisPlayer->Race].Sound,
 							MaxSampleVolume);
 					}
 				}
diff --git a/src/include/netconnect.h b/src/include/netconnect.h
index f6494958d..47f2e602e 100644
--- a/src/include/netconnect.h
+++ b/src/include/netconnect.h
@@ -92,7 +92,7 @@ class CServerSetup {
 public:
 	unsigned char *Serialize() const;
 	void Deserialize(const unsigned char *p);
-	static size_t Size() { return 1+1+1+1+1+1+1+1+ 1*PlayerMax + 1*PlayerMax + 1*PlayerMax + 4*PlayerMax; }
+	static size_t Size() { return 4+4+4+4+4+4+4+4+ 4*PlayerMax + 4*PlayerMax + 4*PlayerMax + 4*PlayerMax; }
 	void Clear() {
 		ResourcesOption = UnitsOption = FogOfWar = RevealMap =
 			GameTypeOption = Difficulty = MapRichness = 0;
@@ -101,18 +101,18 @@ public:
 		memset(LastFrame, 0, sizeof(LastFrame));
 	}
 
-	Uint8  ResourcesOption;       /// Resources option
-	Uint8  UnitsOption;           /// Unit # option
-	Uint8  FogOfWar;              /// Fog of war option
-	Uint8  RevealMap;             /// Reveal all the map
-	Uint8  TilesetSelection;      /// Tileset select option
-	Uint8  GameTypeOption;        /// Game type option
-	Uint8  Difficulty;            /// Difficulty option
-	Uint8  MapRichness;           /// Map richness option
-	Uint8  CompOpt[PlayerMax];    /// Free slot option selection  {"Available", "Computer", "Closed" }
-	Uint8  Ready[PlayerMax];      /// Client ready state
-	Uint8  Race[PlayerMax];       /// Client race selection
-	Uint32 LastFrame[PlayerMax];  /// Last message received
+	Uint32  ResourcesOption;       /// Resources option
+	Uint32  UnitsOption;           /// Unit # option
+	Uint32  FogOfWar;              /// Fog of war option
+	Uint32  RevealMap;             /// Reveal all the map
+	Uint32  TilesetSelection;      /// Tileset select option
+	Uint32  GameTypeOption;        /// Game type option
+	Uint32  Difficulty;            /// Difficulty option
+	Uint32  MapRichness;           /// Map richness option
+	Uint32  CompOpt[PlayerMax];    /// Free slot option selection  {"Available", "Computer", "Closed" }
+	Uint32  Ready[PlayerMax];      /// Client ready state
+	Uint32  Race[PlayerMax];       /// Client race selection
+	Uint32  LastFrame[PlayerMax];  /// Last message received
 	// Fill in here...
 };
 
diff --git a/src/include/sound.h b/src/include/sound.h
index 09a01c243..84141ac7d 100644
--- a/src/include/sound.h
+++ b/src/include/sound.h
@@ -65,14 +65,18 @@ class LuaActionListener;
 class GameSound
 {
 public:
-	SoundConfig PlacementError;    /// used by ui
-	SoundConfig PlacementSuccess;  /// used by ui
-	SoundConfig Click;             /// used by ui
-	SoundConfig Docking;               /// ship reaches coast
-	SoundConfig BuildingConstruction;  /// building under construction
-	SoundConfig WorkComplete[MAX_RACES];  /// building ready
-	SoundConfig Rescue[MAX_RACES];  /// rescue units
-	SoundConfig ChatMessage;           /// chat message
+	SoundConfig PlacementError[MAX_RACES];        /// used by ui
+	SoundConfig PlacementSuccess[MAX_RACES];      /// used by ui
+	SoundConfig Click;                            /// used by ui
+	SoundConfig Docking;                          /// ship reaches coast
+	SoundConfig BuildingConstruction[MAX_RACES];  /// building under construction
+	SoundConfig WorkComplete[MAX_RACES];          /// building ready
+	SoundConfig Rescue[MAX_RACES];                /// rescue units
+	SoundConfig ChatMessage;                      /// chat message
+	SoundConfig ResearchComplete[MAX_RACES];      /// research complete message
+	SoundConfig NotEnough1[MAX_RACES];            /// not enough minerals message
+	SoundConfig NotEnough2[MAX_RACES];            /// not enough ore message
+	SoundConfig NotEnoughFood[MAX_RACES];         /// not enough food message
 };
 
 /**
diff --git a/src/include/unit.h b/src/include/unit.h
index 1208bbdee..dd2e04ac5 100644
--- a/src/include/unit.h
+++ b/src/include/unit.h
@@ -471,7 +471,8 @@ enum UnitVoiceGroup {
 	VoiceBuilding,          /// only for building under construction
 	VoiceDocking,           /// only for transport reaching coast
 	VoiceRepairing,         /// repairing
-	VoiceHarvesting         /// harvesting
+	VoiceHarvesting,        /// harvesting
+	VoiceAttack             /// Attack command
 };
 
 /**
diff --git a/src/include/unitsound.h b/src/include/unitsound.h
index ea157ab53..ed756466e 100644
--- a/src/include/unitsound.h
+++ b/src/include/unitsound.h
@@ -70,6 +70,7 @@ class CUnitSound {
 public:
 	SoundConfig Selected;           /// selected by user
 	SoundConfig Acknowledgement;    /// acknowledge of use command
+	SoundConfig Attack;             /// attack confirm command
 	SoundConfig Ready;              /// unit training... ready
 	SoundConfig Repair;             /// unit repairing
 	SoundConfig Harvest[MaxCosts];  /// unit harvesting
diff --git a/src/include/util.h b/src/include/util.h
index 7b73592a7..3d7fb3340 100644
--- a/src/include/util.h
+++ b/src/include/util.h
@@ -39,6 +39,7 @@
 
 #ifndef __unix
 #undef NOUSER
+#define _WIN32_WINNT 0x0400
 #include <winsock2.h>
 #include <windows.h>
 #elif defined(__hpux)
diff --git a/src/pathfinder/pathfinder.cpp b/src/pathfinder/pathfinder.cpp
index 6ced07a98..147b0cd56 100644
--- a/src/pathfinder/pathfinder.cpp
+++ b/src/pathfinder/pathfinder.cpp
@@ -208,6 +208,8 @@ int UnitReachable(const CUnit *src, const CUnit *dst, int range)
 	//
 	//  Find a path to the goal.
 	//
+	if (src->Type->Building)
+		return 0;
 	depth = PlaceReachable(src, dst->X, dst->Y,
 	 dst->Type->TileWidth, dst->Type->TileHeight, 0, range);
 	if (depth <= 0) {
diff --git a/src/sound/script_sound.cpp b/src/sound/script_sound.cpp
index b675f1c57..21d80c820 100644
--- a/src/sound/script_sound.cpp
+++ b/src/sound/script_sound.cpp
@@ -252,17 +252,49 @@ static int CclDefineGameSounds(lua_State *l)
 			}
 			GameSounds.Click.Sound = (CSound *)data->Data;
 		} else if (!strcmp(value, "placement-error")) {
-			if (!lua_isuserdata(l, j + 1) ||
-					(data = (LuaUserData *)lua_touserdata(l, j + 1))->Type != LuaSoundType) {
+			if (!lua_istable(l, j + 1) || lua_objlen(l, j + 1) != 2) {
+				LuaError(l, "incorrect argument");
+			}
+			lua_rawgeti(l, j + 1, 1);
+			value = LuaToString(l, -1);
+			lua_pop(l, 1);
+			for (i = 0; i < PlayerRaces.Count; ++i) {
+				if (!strcmp(PlayerRaces.Name[i].c_str(), value)) {
+					break;
+				}
+			}
+			if (i == PlayerRaces.Count) {
+				LuaError(l, "Unknown race: %s" _C_ value);
+			}
+			lua_rawgeti(l, j + 1, 2);
+			if (!lua_isuserdata(l, -1) ||
+					(data = (LuaUserData *)lua_touserdata(l, -1))->Type != LuaSoundType) {
 				LuaError(l, "Sound id expected");
 			}
-			GameSounds.PlacementError.Sound = (CSound *)data->Data;
+			lua_pop(l, 1);
+			GameSounds.PlacementError[i].Sound = (CSound *)data->Data;
 		} else if (!strcmp(value, "placement-success")) {
-			if (!lua_isuserdata(l, j + 1) ||
-					(data = (LuaUserData *)lua_touserdata(l, j + 1))->Type != LuaSoundType) {
+			if (!lua_istable(l, j + 1) || lua_objlen(l, j + 1) != 2) {
+				LuaError(l, "incorrect argument");
+			}
+			lua_rawgeti(l, j + 1, 1);
+			value = LuaToString(l, -1);
+			lua_pop(l, 1);
+			for (i = 0; i < PlayerRaces.Count; ++i) {
+				if (!strcmp(PlayerRaces.Name[i].c_str(), value)) {
+					break;
+				}
+			}
+			if (i == PlayerRaces.Count) {
+				LuaError(l, "Unknown race: %s" _C_ value);
+			}
+			lua_rawgeti(l, j + 1, 2);
+			if (!lua_isuserdata(l, -1) ||
+					(data = (LuaUserData *)lua_touserdata(l, -1))->Type != LuaSoundType) {
 				LuaError(l, "Sound id expected");
 			}
-			GameSounds.PlacementSuccess.Sound = (CSound *)data->Data;
+			lua_pop(l, 1);
+			GameSounds.PlacementSuccess[i].Sound = (CSound *)data->Data;
 		} else if (!strcmp(value, "work-complete")) {
 			if (!lua_istable(l, j + 1) || lua_objlen(l, j + 1) != 2) {
 				LuaError(l, "incorrect argument");
@@ -285,6 +317,94 @@ static int CclDefineGameSounds(lua_State *l)
 			}
 			lua_pop(l, 1);
 			GameSounds.WorkComplete[i].Sound = (CSound *)data->Data;
+		} else if (!strcmp(value, "research-complete")) {
+			if (!lua_istable(l, j + 1) || lua_objlen(l, j + 1) != 2) {
+				LuaError(l, "incorrect argument");
+			}
+			lua_rawgeti(l, j + 1, 1);
+			value = LuaToString(l, -1);
+			lua_pop(l, 1);
+			for (i = 0; i < PlayerRaces.Count; ++i) {
+				if (!strcmp(PlayerRaces.Name[i].c_str(), value)) {
+					break;
+				}
+			}
+			if (i == PlayerRaces.Count) {
+				LuaError(l, "Unknown race: %s" _C_ value);
+			}
+			lua_rawgeti(l, j + 1, 2);
+			if (!lua_isuserdata(l, -1) ||
+					(data = (LuaUserData *)lua_touserdata(l, -1))->Type != LuaSoundType) {
+				LuaError(l, "Sound id expected");
+			}
+			lua_pop(l, 1);
+			GameSounds.ResearchComplete[i].Sound = (CSound *)data->Data;
+		} else if (!strcmp(value, "not-enough-min")) {
+			if (!lua_istable(l, j + 1) || lua_objlen(l, j + 1) != 2) {
+				LuaError(l, "incorrect argument");
+			}
+			lua_rawgeti(l, j + 1, 1);
+			value = LuaToString(l, -1);
+			lua_pop(l, 1);
+			for (i = 0; i < PlayerRaces.Count; ++i) {
+				if (!strcmp(PlayerRaces.Name[i].c_str(), value)) {
+					break;
+				}
+			}
+			if (i == PlayerRaces.Count) {
+				LuaError(l, "Unknown race: %s" _C_ value);
+			}
+			lua_rawgeti(l, j + 1, 2);
+			if (!lua_isuserdata(l, -1) ||
+					(data = (LuaUserData *)lua_touserdata(l, -1))->Type != LuaSoundType) {
+				LuaError(l, "Sound id expected");
+			}
+			lua_pop(l, 1);
+			GameSounds.NotEnough1[i].Sound = (CSound *)data->Data;
+		} else if (!strcmp(value, "not-enough-ore")) {
+			if (!lua_istable(l, j + 1) || lua_objlen(l, j + 1) != 2) {
+				LuaError(l, "incorrect argument");
+			}
+			lua_rawgeti(l, j + 1, 1);
+			value = LuaToString(l, -1);
+			lua_pop(l, 1);
+			for (i = 0; i < PlayerRaces.Count; ++i) {
+				if (!strcmp(PlayerRaces.Name[i].c_str(), value)) {
+					break;
+				}
+			}
+			if (i == PlayerRaces.Count) {
+				LuaError(l, "Unknown race: %s" _C_ value);
+			}
+			lua_rawgeti(l, j + 1, 2);
+			if (!lua_isuserdata(l, -1) ||
+					(data = (LuaUserData *)lua_touserdata(l, -1))->Type != LuaSoundType) {
+				LuaError(l, "Sound id expected");
+			}
+			lua_pop(l, 1);
+			GameSounds.NotEnough2[i].Sound = (CSound *)data->Data;
+		}else if (!strcmp(value, "not-enough-food")) {
+			if (!lua_istable(l, j + 1) || lua_objlen(l, j + 1) != 2) {
+				LuaError(l, "incorrect argument");
+			}
+			lua_rawgeti(l, j + 1, 1);
+			value = LuaToString(l, -1);
+			lua_pop(l, 1);
+			for (i = 0; i < PlayerRaces.Count; ++i) {
+				if (!strcmp(PlayerRaces.Name[i].c_str(), value)) {
+					break;
+				}
+			}
+			if (i == PlayerRaces.Count) {
+				LuaError(l, "Unknown race: %s" _C_ value);
+			}
+			lua_rawgeti(l, j + 1, 2);
+			if (!lua_isuserdata(l, -1) ||
+					(data = (LuaUserData *)lua_touserdata(l, -1))->Type != LuaSoundType) {
+				LuaError(l, "Sound id expected");
+			}
+			lua_pop(l, 1);
+			GameSounds.NotEnoughFood[i].Sound = (CSound *)data->Data;
 		} else if (!strcmp(value, "rescue")) {
 			if (!lua_istable(l, j + 1) || lua_objlen(l, j + 1) != 2) {
 				LuaError(l, "incorrect argument");
diff --git a/src/sound/sound.cpp b/src/sound/sound.cpp
index 980cb815c..3ea30900f 100644
--- a/src/sound/sound.cpp
+++ b/src/sound/sound.cpp
@@ -63,28 +63,8 @@
 
 /**
 **  Various sounds used in game.
-**
-**  FIXME: @todo support more races. Must remove static config.
 */
-GameSound GameSounds
-#ifndef laterUSE_CCL
-// FIXME: Removing this crashes?
-={
-	SoundConfig("placement error"),
-	SoundConfig("placement success"),
-	SoundConfig("click"),
-	SoundConfig("transport docking"),
-	SoundConfig("building construction"),
-	{ SoundConfig("basic human voices work complete"),
-		SoundConfig("basic orc voices work complete"),
-	},
-	{ SoundConfig("rescue (human) UNUSED"),
-		SoundConfig("rescue (orc) UNUSED"),
-	},
-	SoundConfig("click"),
-}
-#endif
-	;
+GameSound GameSounds;
 
 /**
 **  Selection handling
@@ -187,6 +167,8 @@ static CSound *ChooseUnitVoiceSound(const CUnit *unit, UnitVoiceGroup voice)
 	switch (voice) {
 		case VoiceAcknowledging:
 			return unit->Type->Sound.Acknowledgement.Sound;
+		case VoiceAttack:
+			return unit->Type->Sound.Attack.Sound;
 		case VoiceReady:
 			return unit->Type->Sound.Ready.Sound;
 		case VoiceSelected:
@@ -198,7 +180,7 @@ static CSound *ChooseUnitVoiceSound(const CUnit *unit, UnitVoiceGroup voice)
 		case VoiceWorkCompleted:
 			return GameSounds.WorkComplete[ThisPlayer->Race].Sound;
 		case VoiceBuilding:
-			return GameSounds.BuildingConstruction.Sound;
+			return GameSounds.BuildingConstruction[ThisPlayer->Race].Sound;
 		case VoiceDocking:
 			return GameSounds.Docking.Sound;
 		case VoiceRepairing:
@@ -503,14 +485,22 @@ void InitSoundClient(void)
 	}
 	// let's map game sounds, look if already setup in ccl.
 
-	if (!GameSounds.PlacementError.Sound) {
-		GameSounds.PlacementError.Sound =
-			SoundForName(GameSounds.PlacementError.Name);
+	for (unsigned int i = 0; i < PlayerRaces.Count; ++i) {
+		if (!GameSounds.PlacementError[i].Sound &&
+				!GameSounds.PlacementError[i].Name.empty()) {
+			GameSounds.PlacementError[i].Sound =
+				SoundForName(GameSounds.PlacementError[i].Name);
+		}
 	}
-	if (!GameSounds.PlacementSuccess.Sound) {
-		GameSounds.PlacementSuccess.Sound =
-			SoundForName(GameSounds.PlacementSuccess.Name);
+
+	for (unsigned int i = 0; i < PlayerRaces.Count; ++i) {
+		if (!GameSounds.PlacementSuccess[i].Sound &&
+				!GameSounds.PlacementSuccess[i].Name.empty()) {
+			GameSounds.PlacementSuccess[i].Sound =
+				SoundForName(GameSounds.PlacementSuccess[i].Name);
+		}
 	}
+
 	if (!GameSounds.Click.Sound) {
 		GameSounds.Click.Sound = SoundForName(GameSounds.Click.Name);
 	}
@@ -518,9 +508,13 @@ void InitSoundClient(void)
 		GameSounds.Docking.Sound =
 			SoundForName(GameSounds.Docking.Name);
 	}
-	if (!GameSounds.BuildingConstruction.Sound) {
-		GameSounds.BuildingConstruction.Sound =
-			SoundForName(GameSounds.BuildingConstruction.Name);
+
+	for (unsigned int i = 0; i < PlayerRaces.Count; ++i) {
+		if (!GameSounds.BuildingConstruction[i].Sound &&
+				!GameSounds.BuildingConstruction[i].Name.empty()) {
+			GameSounds.BuildingConstruction[i].Sound =
+				SoundForName(GameSounds.BuildingConstruction[i].Name);
+		}
 	}
 	for (unsigned int i = 0; i < PlayerRaces.Count; ++i) {
 		if (!GameSounds.WorkComplete[i].Sound &&
@@ -529,6 +523,34 @@ void InitSoundClient(void)
 				SoundForName(GameSounds.WorkComplete[i].Name);
 		}
 	}
+	for (unsigned int i = 0; i < PlayerRaces.Count; ++i) {
+		if (!GameSounds.ResearchComplete[i].Sound &&
+				!GameSounds.ResearchComplete[i].Name.empty()) {
+			GameSounds.ResearchComplete[i].Sound =
+				SoundForName(GameSounds.ResearchComplete[i].Name);
+		}
+	}
+	for (unsigned int i = 0; i < PlayerRaces.Count; ++i) {
+		if (!GameSounds.NotEnough1[i].Sound &&
+				!GameSounds.NotEnough1[i].Name.empty()) {
+			GameSounds.NotEnough1[i].Sound =
+				SoundForName(GameSounds.NotEnough1[i].Name);
+		}
+	}
+	for (unsigned int i = 0; i < PlayerRaces.Count; ++i) {
+		if (!GameSounds.NotEnough2[i].Sound &&
+				!GameSounds.NotEnough2[i].Name.empty()) {
+			GameSounds.NotEnough2[i].Sound =
+				SoundForName(GameSounds.NotEnough2[i].Name);
+		}
+	}
+	for (unsigned int i = 0; i < PlayerRaces.Count; ++i) {
+		if (!GameSounds.NotEnoughFood[i].Sound &&
+				!GameSounds.NotEnoughFood[i].Name.empty()) {
+			GameSounds.NotEnoughFood[i].Sound =
+				SoundForName(GameSounds.NotEnoughFood[i].Name);
+		}
+	}
 	for (unsigned int i = 0; i < PlayerRaces.Count; ++i) {
 		if (!GameSounds.Rescue[i].Sound && !GameSounds.Rescue[i].Name.empty()) {
 			GameSounds.Rescue[i].Sound =
diff --git a/src/sound/unitsound.cpp b/src/sound/unitsound.cpp
index c58bf0f41..7950131c1 100644
--- a/src/sound/unitsound.cpp
+++ b/src/sound/unitsound.cpp
@@ -145,6 +145,10 @@ void MapUnitSounds(void)
 					INFINITE_SOUND_RANGE);
 				*/
 			}
+			if (!type->Sound.Attack.Name.empty()) {
+				type->Sound.Attack.Sound =
+					SoundForName(type->Sound.Attack.Name);
+			}
 			if (!type->Sound.Ready.Name.empty()) {
 				type->Sound.Ready.Sound =
 					SoundForName(type->Sound.Ready.Name);
diff --git a/src/stratagus/player.cpp b/src/stratagus/player.cpp
index 3f6bcb8c9..2d270a8f4 100644
--- a/src/stratagus/player.cpp
+++ b/src/stratagus/player.cpp
@@ -636,6 +636,14 @@ int CPlayer::CheckCosts(const int *costs) const
 				DefaultResourceNames[i].c_str(), DefaultActions[i].c_str(), DefaultResourceNames[i].c_str());
 
 			err |= 1 << i;
+			if (i==1)
+				if (GameSounds.NotEnough1[this->Race].Sound) 
+					PlayGameSound(GameSounds.NotEnough1[this->Race].Sound,
+								MaxSampleVolume);
+			if (i==2)
+				if (GameSounds.NotEnough2[this->Race].Sound) 
+					PlayGameSound(GameSounds.NotEnough2[this->Race].Sound,
+								MaxSampleVolume);
 		}
 	}
 	return err;
diff --git a/src/tolua/network.pkg b/src/tolua/network.pkg
index 578defeac..041e81071 100644
--- a/src/tolua/network.pkg
+++ b/src/tolua/network.pkg
@@ -16,14 +16,14 @@ void NetworkServerResyncClients(void);
 void NetworkDetachFromServer(void);
 
 class CServerSetup {
-	unsigned char ResourcesOption;
-	unsigned char UnitsOption;
-	unsigned char FogOfWar;
-	unsigned char RevealMap;
-	unsigned char TilesetSelection;
-	unsigned char GameTypeOption;
-	unsigned char Difficulty;
-	unsigned char MapRichness;
+	unsigned int ResourcesOption;
+	unsigned int UnitsOption;
+	unsigned int FogOfWar;
+	unsigned int RevealMap;
+	unsigned int TilesetSelection;
+	unsigned int GameTypeOption;
+	unsigned int Difficulty;
+	unsigned int MapRichness;
 	unsigned CompOpt[PlayerMax];
 	unsigned Ready[PlayerMax];
 	unsigned Race[PlayerMax];
diff --git a/src/ui/botpanel.cpp b/src/ui/botpanel.cpp
index 79f5a5dfb..9a8fd8aca 100644
--- a/src/ui/botpanel.cpp
+++ b/src/ui/botpanel.cpp
@@ -1040,7 +1040,7 @@ void CButtonPanel::DoClicked(int button)
 				int autocast = 0;
 
 				if (!SpellTypeTable[spellId]->AutoCast) {
-					PlayGameSound(GameSounds.PlacementError.Sound,
+					PlayGameSound(GameSounds.PlacementError[ThisPlayer->Race].Sound,
 						MaxSampleVolume);
 					break;
 				}
@@ -1202,7 +1202,10 @@ void CButtonPanel::DoClicked(int button)
 					!(KeyModifiers & ModifierShift));
 				UI.StatusLine.Clear();
 				ClearCosts();
-			}
+			} else if (Selected[0]->Player->CheckLimits(type) == -3)
+				if (GameSounds.NotEnoughFood[Selected[0]->Player->Race].Sound) 
+					PlayGameSound(GameSounds.NotEnoughFood[Selected[0]->Player->Race].Sound,
+								MaxSampleVolume);
 			break;
 
 		case ButtonUpgradeTo:
diff --git a/src/ui/mouse.cpp b/src/ui/mouse.cpp
index aa1282c60..081f54c35 100644
--- a/src/ui/mouse.cpp
+++ b/src/ui/mouse.cpp
@@ -186,10 +186,6 @@ void DoRightButton(int sx, int sy)
 			continue;
 		}
 		Assert(unit);
-		if (!acknowledged) {
-			PlayUnitSound(unit, VoiceAcknowledging);
-			acknowledged = 1;
-		}
 		type = unit->Type;
 		action = type->MouseAction;
 
@@ -198,6 +194,10 @@ void DoRightButton(int sx, int sy)
 		//
 		if ((KeyModifiers & ModifierControl) && dest) {
 			dest->Blink = 4;
+			if (!acknowledged) {
+				PlayUnitSound(unit, VoiceAcknowledging);
+				acknowledged = 1;
+			}
 			SendCommandFollow(unit, dest, flush);
 			continue;
 		}
@@ -212,12 +212,20 @@ void DoRightButton(int sx, int sy)
 				if (dest->CanMove() && CanTransport(dest, unit)) {
 					DebugPrint("Send command follow\n");
 					// is flush value correct ?
+					if (!acknowledged) {
+						PlayUnitSound(unit, VoiceAcknowledging);
+						acknowledged = 1;
+					}
 					SendCommandFollow(dest, unit, 0);
 				}
 				// FIXME : manage correctly production units.
 				if (!unit->CanMove() || CanTransport(dest, unit)) {
 					dest->Blink = 4;
 					DebugPrint("Board transporter\n");
+					if (!acknowledged) {
+						PlayUnitSound(unit, VoiceAcknowledging);
+						acknowledged = 1;
+					}
 					SendCommandBoard(unit, -1, -1, dest, flush);
 					continue;
 				}
@@ -229,6 +237,10 @@ void DoRightButton(int sx, int sy)
 				if (unit->CanMove()) {
 					DebugPrint("Send command follow\n");
 					// is flush value correct ?
+					if (!acknowledged) {
+						PlayUnitSound(unit, VoiceAcknowledging);
+						acknowledged = 1;
+					}
 					SendCommandFollow(unit, dest, 0);
 				} else if (!dest->CanMove()) {
 					DebugPrint("Want to transport but no unit can move\n");
@@ -236,6 +248,10 @@ void DoRightButton(int sx, int sy)
 				}
 				dest->Blink = 4;
 				DebugPrint("Board transporter\n");
+				if (!acknowledged) {
+					PlayUnitSound(unit, VoiceAcknowledging);
+					acknowledged = 1;
+				}
 				SendCommandBoard(dest, -1, -1, unit, flush);
 				continue;
 			}
@@ -251,6 +267,10 @@ void DoRightButton(int sx, int sy)
 					dest->Variable[HP_INDEX].Value < dest->Variable[HP_INDEX].Max &&
 					(dest->Player == unit->Player || unit->IsAllied(dest))) {
 				dest->Blink = 4;
+				if (!acknowledged) {
+					PlayUnitSound(unit, VoiceAcknowledging);
+					acknowledged = 1;
+				}
 				SendCommandRepair(unit, x, y, dest, flush);
 				continue;
 			}
@@ -262,6 +282,10 @@ void DoRightButton(int sx, int sy)
 							dest->Type->CanStore[unit->CurrentResource] &&
 							dest->Player == unit->Player) {
 						dest->Blink = 4;
+						if (!acknowledged) {
+							PlayUnitSound(unit, VoiceAcknowledging);
+							acknowledged = 1;
+						}
 						SendCommandReturnGoods(unit, dest, flush);
 						continue;
 					}
@@ -273,6 +297,10 @@ void DoRightButton(int sx, int sy)
 							(dest->Player == unit->Player ||
 								(dest->Player->Index == PlayerNumNeutral))) {
 						dest->Blink = 4;
+						if (!acknowledged) {
+							PlayUnitSound(unit, VoiceAcknowledging);
+							acknowledged = 1;
+						}
 						SendCommandResource(unit, dest, flush);
 						continue;
 					}
@@ -285,6 +313,10 @@ void DoRightButton(int sx, int sy)
 								Map.ForestOnMap(x, y) &&
 								((unit->CurrentResource != res) ||
 									(unit->ResourcesHeld < type->ResInfo[res]->ResourceCapacity))) {
+							if (!acknowledged) {
+								PlayUnitSound(unit, VoiceAcknowledging);
+								acknowledged = 1;
+							}
 							SendCommandResourceLoc(unit, x, y, flush);
 							break;
 						}
@@ -298,10 +330,18 @@ void DoRightButton(int sx, int sy)
 			if (UnitUnderCursor != NULL && dest != NULL && dest != unit &&
 					(dest->Player == unit->Player || unit->IsAllied(dest))) {
 				dest->Blink = 4;
+				if (!acknowledged) {
+					PlayUnitSound(unit, VoiceAcknowledging);
+					acknowledged = 1;
+				}
 				SendCommandFollow(unit, dest, flush);
 				continue;
 			}
 			// Move
+			if (!acknowledged) {
+				PlayUnitSound(unit, VoiceAcknowledging);
+				acknowledged = 1;
+			}
 			SendCommandMove(unit, x, y, flush);
 			continue;
 		}
@@ -313,6 +353,10 @@ void DoRightButton(int sx, int sy)
 			if (dest != NULL && unit->CurrentAction() != UnitActionBuilt) {
 				if (unit->IsEnemy(dest)) {
 					dest->Blink = 4;
+					if (!acknowledged) {
+						PlayUnitSound(unit, VoiceAttack);
+						acknowledged = 1;
+					}
 					if (action == MouseActionSpellCast) {
 						// This is for demolition squads and such
 						Assert(unit->Type->CanCastSpell);
@@ -331,6 +375,10 @@ void DoRightButton(int sx, int sy)
 				if ((dest->Player == unit->Player || unit->IsAllied(dest)) &&
 						dest != unit) {
 					dest->Blink = 4;
+					if (!acknowledged) {
+						PlayUnitSound(unit, VoiceAcknowledging);
+						acknowledged = 1;
+					}
 					SendCommandFollow(unit, dest, flush);
 					continue;
 				}
@@ -351,14 +399,30 @@ void DoRightButton(int sx, int sy)
 			if ((KeyModifiers & ModifierControl)) {
 				if (RightButtonAttacks) {
 					SendCommandMove(unit, x, y, flush);
+					if (!acknowledged) {
+						PlayUnitSound(unit, VoiceAcknowledging);
+						acknowledged = 1;
+					}
 				} else {
+					if (!acknowledged) {
+						PlayUnitSound(unit, VoiceAttack);
+						acknowledged = 1;
+					}
 					SendCommandAttack(unit, x, y, NoUnitP, flush);
 				}
 			} else {
 				if (RightButtonAttacks) {
+					if (!acknowledged) {
+						PlayUnitSound(unit, VoiceAttack);
+						acknowledged = 1;
+					}
 					SendCommandAttack(unit, x, y, NoUnitP, flush);
 				} else {
 					// Note: move is correct here, right default is move
+					if (!acknowledged) {
+						PlayUnitSound(unit, VoiceAcknowledging);
+						acknowledged = 1;
+					}
 					SendCommandMove(unit, x, y, flush);
 				}
 			}
@@ -371,6 +435,10 @@ void DoRightButton(int sx, int sy)
 				(dest && dest != unit) &&
 				(dest->Player == unit->Player || unit->IsAllied(dest))) {
 			dest->Blink = 4;
+			if (!acknowledged) {
+				PlayUnitSound(unit, VoiceAcknowledging);
+				acknowledged = 1;
+			}
 			SendCommandFollow(unit, dest, flush);
 			continue;
 		}
@@ -383,6 +451,10 @@ void DoRightButton(int sx, int sy)
 					dest->Player == unit->Player) {
 				dest->Blink = 4;
 				SendCommandReturnGoods(dest, unit, flush);
+				if (!acknowledged) {
+					PlayUnitSound(unit, VoiceAcknowledging);
+					acknowledged = 1;
+				}
 				continue;
 			}
 			// tell to go and harvest from a building
@@ -403,15 +475,27 @@ void DoRightButton(int sx, int sy)
 			if (dest != NULL && dest->Type->GivesResource && dest->Type->CanHarvest &&
 					(dest->Player == unit->Player || dest->Player->Index == PlayerNumNeutral)) {
 				dest->Blink = 4;
+				if (!acknowledged) {
+					PlayUnitSound(unit, VoiceAcknowledging);
+					acknowledged = 1;
+				}
 				SendCommandResource(unit, dest, flush);
 				continue;
 			}
 			// FIXME: support harvesting more types of terrain.
 			if (Map.IsFieldExplored(unit->Player, x, y) && Map.ForestOnMap(x, y)) {
+				if (!acknowledged) {
+					PlayUnitSound(unit, VoiceAcknowledging);
+					acknowledged = 1;
+				}
 				SendCommandResourceLoc(unit, x, y, flush);
 				break;
 			}
 		}
+		if (!acknowledged) {
+			PlayUnitSound(unit, VoiceAcknowledging);
+			acknowledged = 1;
+		}
 
 		SendCommandMove(unit, x, y, flush);
 	}
@@ -1246,7 +1330,15 @@ static void SendCommand(int sx, int sy)
 	if (ret) {
 		// Acknowledge the command with first selected unit.
 		for (int i = 0; i < NumSelected; ++i) {
-			if (Selected[i]->Type->Sound.Acknowledgement.Sound) {
+			if (ret==ButtonAttack || ret==ButtonAttackGround || ret==ButtonSpellCast) {
+				if (Selected[i]->Type->Sound.Attack.Sound) {
+					PlayUnitSound(Selected[i], VoiceAttack);
+					break;
+				} else if (Selected[i]->Type->Sound.Acknowledgement.Sound) {
+					PlayUnitSound(Selected[i], VoiceAcknowledging);
+					break;
+				}
+			} else if (Selected[i]->Type->Sound.Acknowledgement.Sound) {
 				PlayUnitSound(Selected[i], VoiceAcknowledging);
 				break;
 			}
@@ -1502,7 +1594,7 @@ void UIHandleButtonDown(unsigned button)
 				// 0 Test build, don't really build
 				if (CanBuildUnitType(Selected[0], CursorBuilding, x, y, 0) &&
 						(explored || ReplayRevealMap)) {
-					PlayGameSound(GameSounds.PlacementSuccess.Sound,
+					PlayGameSound(GameSounds.PlacementSuccess[ThisPlayer->Race].Sound,
 						MaxSampleVolume);
 					for (int i = 0; i < NumSelected; ++i) {
 						SendCommandBuildBuilding(Selected[i], x, y, CursorBuilding,
@@ -1512,7 +1604,7 @@ void UIHandleButtonDown(unsigned button)
 						CancelBuildingMode();
 					}
 				} else {
-					PlayGameSound(GameSounds.PlacementError.Sound,
+					PlayGameSound(GameSounds.PlacementError[ThisPlayer->Race].Sound,
 						MaxSampleVolume);
 				}
 			} else {
diff --git a/src/unit/script_unittype.cpp b/src/unit/script_unittype.cpp
index 745c3203e..22d1707a9 100644
--- a/src/unit/script_unittype.cpp
+++ b/src/unit/script_unittype.cpp
@@ -954,6 +954,10 @@ static int CclDefineUnitType(lua_State *l)
 					lua_rawgeti(l, -1, k + 1);
 					type->Sound.Acknowledgement.Name = LuaToString(l, -1);
 					lua_pop(l, 1);
+				} else if (!strcmp(value, "attack")) {
+					lua_rawgeti(l, -1, k + 1);
+					type->Sound.Attack.Name = LuaToString(l, -1);
+					lua_pop(l, 1);
 				} else if (!strcmp(value, "ready")) {
 					lua_rawgeti(l, -1, k + 1);
 					type->Sound.Ready.Name = LuaToString(l, -1);
diff --git a/src/unit/unit.cpp b/src/unit/unit.cpp
index 501d3853f..6b6407ae0 100644
--- a/src/unit/unit.cpp
+++ b/src/unit/unit.cpp
@@ -3142,6 +3142,7 @@ void HitUnit(CUnit *attacker, CUnit *target, int damage)
 	}
 
 	/* Target Reaction on Hit */
+	if (target->Player->AiEnabled){
 	switch(target->CurrentAction()) {
 		case UnitActionTrain:
 		case UnitActionUpgradeTo:
@@ -3158,12 +3159,12 @@ void HitUnit(CUnit *attacker, CUnit *target, int damage)
 			//
 			return;
 		case UnitActionResource:
-			if (target->SubAction >= 65/* SUB_STOP_GATHERING */)
+			if (target->SubAction >= 65)
 			{
 				//Normal return to depot
 				return;
 			}
-			if (target->SubAction > 55 /* SUB_START_GATHERING */ &&
+			if (target->SubAction > 55  &&
 				target->ResourcesHeld > 0) {
 				//escape to Depot with this what you have;
 				target->Data.ResWorker.DoneHarvesting = 1;
@@ -3184,11 +3185,12 @@ void HitUnit(CUnit *attacker, CUnit *target, int damage)
 		default:
 		break;
 	}
+	}
 
 	//
 	// Attack units in range (which or the attacker?)
 	//
-	if (attacker && target->IsAgressive()) {
+	if (attacker && target->IsAgressive() && target->CanMove()) {
 			if (RevealAttacker && CanTarget(target->Type, attacker->Type)) {
 				// Reveal Unit that is attacking
 				goal = attacker;
@@ -3200,6 +3202,8 @@ void HitUnit(CUnit *attacker, CUnit *target, int damage)
 					goal = AttackUnitsInReactRange(target);
 				}
 			}
+			if (target->CurrentAction()!=UnitActionStill && !target->Player->AiEnabled)
+					return;
 			if (goal) {
 				if (target->SavedOrder.Action == UnitActionStill) {
 					// FIXME: should rewrite command handling
diff --git a/src/video/cursor.cpp b/src/video/cursor.cpp
index 3346fd05b..e2a74854c 100644
--- a/src/video/cursor.cpp
+++ b/src/video/cursor.cpp
@@ -232,6 +232,12 @@ static void DrawBuildingCursor(void)
 	DrawShadow(CursorBuilding, CursorBuilding->StillFrame, x, y);
 	DrawUnitType(CursorBuilding, CursorBuilding->Sprite, ThisPlayer->Index,
 		CursorBuilding->StillFrame, x, y);
+	if (CursorBuilding->CanAttack && CursorBuilding->Stats->Variables[ATTACKRANGE_INDEX].Value>0){
+		Video.DrawCircleClip(ColorRed,
+					x + CursorBuilding->TileWidth * TileSizeX / 2,
+					y + CursorBuilding->TileHeight * TileSizeY / 2,
+					(CursorBuilding->Stats->Variables[ATTACKRANGE_INDEX].Max + (CursorBuilding->TileWidth - 1)) * TileSizeX + 1);
+	}
 
 	//
 	//  Draw the allow overlay
diff --git a/src/video/sdl.cpp b/src/video/sdl.cpp
index 5e72c376e..4a80b1c0d 100644
--- a/src/video/sdl.cpp
+++ b/src/video/sdl.cpp
@@ -48,13 +48,16 @@
 #include <string.h>
 
 #include <limits.h>
+
 #ifndef _MSC_VER
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #endif
+
 #include "SDL.h"
+
 #ifdef USE_GLES
 #include "SDL_gles.h"
 #include "GLES/gl.h"
@@ -69,6 +72,7 @@
 #ifdef USE_WIN32
 #include "net_lowlevel.h"
 #include "SDL_syswm.h"
+#include <shellapi.h>
 #endif
 
 #ifdef USE_MAEMO