diff --git a/src/action/action_attack.cpp b/src/action/action_attack.cpp
index a812eca12..89a2dd426 100644
--- a/src/action/action_attack.cpp
+++ b/src/action/action_attack.cpp
@@ -477,7 +477,7 @@ void COrder_Attack::AttackTarget(CUnit &unit)
 			return;
 		}
 		// Save current command to come back.
-		COrder *savedOrder = this->Clone();
+		COrder *savedOrder = COrder::NewActionAttack(unit, this->goalPos);
 
 		if (unit.StoreOrder(savedOrder) == false) {
 			delete savedOrder;
diff --git a/src/action/action_upgradeto.cpp b/src/action/action_upgradeto.cpp
index b089eda5c..cab047d4f 100644
--- a/src/action/action_upgradeto.cpp
+++ b/src/action/action_upgradeto.cpp
@@ -116,7 +116,7 @@ static int TransformUnitIntoType(CUnit &unit, const CUnitType &newtype)
 	for (int i = 0; i < MaxCosts; ++i) {
 		if (player.MaxResources[i] != -1) {
 			player.MaxResources[i] += newtype.Stats[player.Index].Storing[i] - oldtype.Stats[player.Index].Storing[i];
-			player.SetResource(i, player.StoredResources[i], true);
+			player.SetResource(i, player.StoredResources[i], STORE_BUILDING);
 		}
 	}
 
diff --git a/src/ai/ai_magic.cpp b/src/ai/ai_magic.cpp
index d3e40c3d4..4b906fcde 100644
--- a/src/ai/ai_magic.cpp
+++ b/src/ai/ai_magic.cpp
@@ -37,6 +37,7 @@
 #include "unittype.h"
 #include "unit.h"
 #include "spells.h"
+#include "actions.h"
 #include "ai_local.h"
 
 /*----------------------------------------------------------------------------
@@ -55,8 +56,8 @@ void AiCheckMagic()
 	for (int i = 0; i < n; ++i) {
 		CUnit &unit = player.GetUnit(i);
 
-		// Check only magic units
-		if (unit.Type->CanCastSpell) {
+		// Check only idle magic units
+		if (unit.Type->CanCastSpell && unit.CurrentAction() != UnitActionSpellCast) {
 			for (unsigned int j = 0; j < SpellTypeTable.size(); ++j) {
 				// Check if we can cast this spell. SpellIsAvailable checks for upgrades.
 				if (unit.Type->CanCastSpell[j] && SpellIsAvailable(player, j)
diff --git a/src/animation/animation.cpp b/src/animation/animation.cpp
index cad4a9242..7fb1f3ebe 100644
--- a/src/animation/animation.cpp
+++ b/src/animation/animation.cpp
@@ -39,6 +39,8 @@
 
 #include "stratagus.h"
 
+#include "action/action_spellcast.h"
+
 #include "animation.h"
 
 #include "animation/animation_attack.h"
@@ -66,6 +68,7 @@
 #include "iolib.h"
 #include "player.h"
 #include "script.h"
+#include "spells.h"
 #include "unit.h"
 #include "unittype.h"
 
@@ -178,6 +181,22 @@ int ParseAnimInt(const CUnit *unit, const char *parseint)
 			return goal->Variable[index].Value * 100 / goal->Variable[index].Max;
 		}
 		return 0;
+	} else if ((s[0] == 'b') && unit != NULL) { //unit bool flag detected
+		const int index = UnitTypeVar.BoolFlagNameLookup[cur];// User bool flags
+		if (index == -1) {
+			fprintf(stderr, "Bad bool-flag name '%s'\n", cur);
+			Exit(1);
+			return 0;
+		}
+		return goal->Type->BoolFlag[index].value;
+	} else if ((s[0] == 's') && unit != NULL) { //spell type detected
+		Assert(goal->CurrentAction() == UnitActionSpellCast);
+		const COrder_SpellCast &order = *static_cast<COrder_SpellCast *>(goal->CurrentOrder());
+		const SpellType &spell = order.GetSpell();
+		if (!strcmp(spell.Ident.c_str(), cur)) {
+			return 1;
+		}
+		return 0;
 	} else if (s[0] == 'p' && unit != NULL) { //player variable detected
 		char *next = strchr(cur, '.');
 		if (next == NULL) {
diff --git a/src/animation/animation_setplayervar.cpp b/src/animation/animation_setplayervar.cpp
index 013659236..dd665deb8 100644
--- a/src/animation/animation_setplayervar.cpp
+++ b/src/animation/animation_setplayervar.cpp
@@ -138,14 +138,14 @@ static void SetPlayerData(int player, const char *prop, const char *arg, int val
 			fprintf(stderr, "Invalid resource \"%s\"", arg);
 			Exit(1);
 		}
-		Players[player].SetResource(resId, value);
+		Players[player].SetResource(resId, value, STORE_BOTH);
 	} else if (!strcmp(prop, "StoredResources")) {
 		const int resId = GetResourceIdByName(arg);
 		if (resId == -1) {
 			fprintf(stderr, "Invalid resource \"%s\"", arg);
 			Exit(1);
 		}
-		Players[player].SetResource(resId, value, true);
+		Players[player].SetResource(resId, value, STORE_BUILDING);
 	} else if (!strcmp(prop, "UnitLimit")) {
 		Players[player].UnitLimit = value;
 	} else if (!strcmp(prop, "BuildingLimit")) {
diff --git a/src/include/missile.h b/src/include/missile.h
index 3a5df6216..edbede9de 100644
--- a/src/include/missile.h
+++ b/src/include/missile.h
@@ -360,6 +360,9 @@ public:
 	int DrawLevel;             /// Level to draw missile at
 	int SpriteFrames;          /// number of sprite frames in graphic
 	int NumDirections;         /// number of directions missile can face
+	int ChangeVariable;        /// variable to change
+	int ChangeAmount;          /// how many to change
+	bool ChangeMax;            /// modify the max, if value will exceed it
 
 	/// @todo FiredSound defined but not used!
 	SoundConfig FiredSound;    /// fired sound
diff --git a/src/include/player.h b/src/include/player.h
index a6eb25767..3159ff1ed 100644
--- a/src/include/player.h
+++ b/src/include/player.h
@@ -45,6 +45,14 @@
 #endif
 #include "vec2i.h"
 
+/*----------------------------------------------------------------------------
+--  Definitons
+----------------------------------------------------------------------------*/
+
+#define STORE_OVERALL 0
+#define STORE_BUILDING 1
+#define STORE_BOTH 2
+
 /*----------------------------------------------------------------------------
 --  Declarations
 ----------------------------------------------------------------------------*/
@@ -135,7 +143,7 @@ public:
 	/// Adds/subtracts some resources to/from the player store
 	void ChangeResource(int resource, int value, bool store = false);
 	/// Set a resource of the player
-	void SetResource(int resource, int value, bool store = false);
+	void SetResource(int resource, int value, int type = STORE_OVERALL);
 	/// Check, if there enough resources for action.
 	bool CheckResource(int resource, int value);
 
diff --git a/src/include/unit.h b/src/include/unit.h
index 3b574a4cb..48b4a8e52 100644
--- a/src/include/unit.h
+++ b/src/include/unit.h
@@ -339,6 +339,10 @@
 #include "player.h"
 #endif
 
+#ifndef __MISSILE_H__
+#include "missile.h"
+#endif
+
 #include "vec2i.h"
 
 /*----------------------------------------------------------------------------
@@ -676,6 +680,10 @@ unsigned    ByPlayer : PlayerMax;   /// Track unit seen by player
 		if (IsInvisibile(player)) {
 			return false;
 		}
+		// Don't attack revealers
+		if (this->Type->Revealer) {
+			return false;
+		}
 		if ((player.Type == PlayerComputer && !this->Type->PermanentCloak)
 			|| IsVisible(player) || IsVisibleOnRadar(player)) {
 			return IsAliveOnMap();
@@ -960,7 +968,7 @@ extern void DestroyAllInside(CUnit &source);
 /// Calculate some value to measure the unit's priority for AI
 extern int ThreatCalculate(const CUnit &unit, const CUnit &dest);
 /// Hit unit with damage, if destroyed give attacker the points
-extern void HitUnit(CUnit *attacker, CUnit &target, int damage);
+extern void HitUnit(CUnit *attacker, CUnit &target, int damage, const Missile *missile = NULL);
 
 /// Calculate the distance from current view point to coordinate
 extern int ViewPointDistance(const Vec2i &pos);
diff --git a/src/missile/missile.cpp b/src/missile/missile.cpp
index 63d2d1e26..945866224 100644
--- a/src/missile/missile.cpp
+++ b/src/missile/missile.cpp
@@ -682,7 +682,7 @@ static void MissileHitsGoal(const Missile &missile, CUnit &goal, int splash)
 		} else {
 			Assert(missile.SourceUnit != NULL);
 			HitUnit(missile.SourceUnit, goal,
-					CalculateDamage(*missile.SourceUnit, goal) / splash);
+					CalculateDamage(*missile.SourceUnit, goal) / splash, &missile);
 		}
 	}
 }
@@ -1091,8 +1091,8 @@ void InitMissileTypes()
 **  Constructor.
 */
 MissileType::MissileType(const std::string &ident) :
-	Ident(ident), Transparency(0),
-	DrawLevel(0), SpriteFrames(0), NumDirections(0),
+	Ident(ident), Transparency(0), DrawLevel(0), 
+	SpriteFrames(0), NumDirections(0), ChangeVariable(-1), ChangeAmount(0), ChangeMax(false),
 	CorrectSphashDamage(false), Flip(false), CanHitOwner(false), FriendlyFire(false),
 	AlwaysFire(false), Class(), NumBounces(0), StartDelay(0), Sleep(0), Speed(0),
 	Range(0), SplashFactor(0), ImpactParticle(NULL), G(NULL)
diff --git a/src/missile/script_missile.cpp b/src/missile/script_missile.cpp
index 7f7a7602a..fd0e5b55e 100644
--- a/src/missile/script_missile.cpp
+++ b/src/missile/script_missile.cpp
@@ -116,6 +116,18 @@ void MissileType::Load(lua_State *l)
 			this->FiredSound.Name = LuaToString(l, -1);
 		} else if (!strcmp(value, "ImpactSound")) {
 			this->ImpactSound.Name = LuaToString(l, -1);
+		} else if (!strcmp(value, "ChangeVariable")) {
+			const int index = UnitTypeVar.VariableNameLookup[LuaToString(l, -1)];// User variables
+			if (index == -1) {
+				fprintf(stderr, "Bad variable name '%s'\n", LuaToString(l, -1));
+				Exit(1);
+				return;
+			}
+			this->ChangeVariable = index;
+		} else if (!strcmp(value, "ChangeAmount")) {
+			this->ChangeAmount = LuaToNumber(l, -1);
+		} else if (!strcmp(value, "ChangeMax")) {
+			this->ChangeMax = LuaToBoolean(l, -1);
 		} else if (!strcmp(value, "Class")) {
 			const char *className = LuaToString(l, -1);
 			unsigned int i = 0;
diff --git a/src/stratagus/player.cpp b/src/stratagus/player.cpp
index 7523e6131..abf36e3d9 100644
--- a/src/stratagus/player.cpp
+++ b/src/stratagus/player.cpp
@@ -812,18 +812,18 @@ int CPlayer::GetUnitCount() const
 **  Gets the player resource.
 **
 **  @param resource  Resource to get.
-**  @param store     Resource type to get
+**  @param type      Storing type
 **
-**  @note Resource types: 0 - overall store, 1 - store buildings, 2 - both
+**  @note Storing types: 0 - overall store, 1 - store buildings, 2 - both
 */
 int CPlayer::GetResource(int resource, int type)
 {
 	switch (type) {
-		case 0:
+		case STORE_OVERALL:
 			return this->Resources[resource];
-		case 1:
+		case STORE_BUILDING:
 			return this->StoredResources[resource];
-		case 2:
+		case STORE_BOTH:
 			return this->Resources[resource] + this->StoredResources[resource];
 		default:
 			DebugPrint("Wrong resource type\n");
@@ -844,6 +844,9 @@ void CPlayer::ChangeResource(int resource, int value, bool store)
 		int fromStore = std::min(this->StoredResources[resource], abs(value));
 		this->StoredResources[resource] -= fromStore;
 		this->Resources[resource] -= abs(value) - fromStore;
+		if (this->Resources[resource] < 0) {
+			this->Resources[resource] = 0;
+		}
 	} else {
 		if (store && this->MaxResources[resource] != -1) {
 			this->StoredResources[resource] += std::min(value, this->MaxResources[resource] - this->StoredResources[resource]);
@@ -858,13 +861,21 @@ void CPlayer::ChangeResource(int resource, int value, bool store)
 **
 **  @param resource  Resource to change.
 **  @param value     How many of this resource.
-**  @param store     If true, sets the building store resources, else the overall resources.
+**  @param type      Resource types: 0 - overall store, 1 - store buildings, 2 - both
 */
-void CPlayer::SetResource(int resource, int value, bool store)
+void CPlayer::SetResource(int resource, int value, int type)
 {
-	if (store && this->MaxResources[resource] != -1) {
+	if (type == STORE_BOTH) {
+		if (this->MaxResources[resource] != -1) {
+			const int toStore = std::min(0, value - this->Resources[resource]);
+			this->StoredResources[resource] = std::min(toStore, this->MaxResources[resource]);
+			this->Resources[resource] = std::max(0, value - toStore);
+		} else {
+			this->Resources[resource] = value;
+		}
+	} else if (type == STORE_BUILDING && this->MaxResources[resource] != -1) {
 		this->StoredResources[resource] = std::min(value, this->MaxResources[resource]);
-	} else {
+	} else if (type == STORE_OVERALL) {
 		this->Resources[resource] = value;
 	}
 }
diff --git a/src/stratagus/script_player.cpp b/src/stratagus/script_player.cpp
index 2b8b89a71..839c1e4f2 100644
--- a/src/stratagus/script_player.cpp
+++ b/src/stratagus/script_player.cpp
@@ -840,7 +840,7 @@ static int CclSetPlayerData(lua_State *l)
 
 		const std::string res = LuaToString(l, 3);
 		const int resId = GetResourceIdByName(l, res.c_str());
-		p->SetResource(resId, LuaToNumber(l, 4), true);
+		p->SetResource(resId, LuaToNumber(l, 4), STORE_BUILDING);
 		// } else if (!strcmp(data, "UnitTypesCount")) {
 		// } else if (!strcmp(data, "AiEnabled")) {
 		// } else if (!strcmp(data, "TotalNumUnits")) {
diff --git a/src/unit/script_unittype.cpp b/src/unit/script_unittype.cpp
index c8eea988f..cb3099b62 100644
--- a/src/unit/script_unittype.cpp
+++ b/src/unit/script_unittype.cpp
@@ -1179,16 +1179,11 @@ static int CclDefineUnitType(lua_State *l)
 */
 static int CclDefineUnitStats(lua_State *l)
 {
-	const int args = lua_gettop(l);
-	int j = 0;
-
-	CUnitType *type = UnitTypeByIdent(LuaToString(l, j + 1));
+	CUnitType *type = UnitTypeByIdent(LuaToString(l, 1));
+	const int playerId = LuaToNumber(l, 2);
+	
 	Assert(type);
-	++j;
-
-	int playerId = LuaToNumber(l, j + 1);
 	Assert(playerId < PlayerMax);
-	++j;
 
 	CUnitStats *stats = &type->Stats[playerId];
 	if (!stats->Variables) {
@@ -1196,51 +1191,61 @@ static int CclDefineUnitStats(lua_State *l)
 	}
 
 	// Parse the list: (still everything could be changed!)
-	for (; j < args; ++j) {
-		const char *value = LuaToString(l, j + 1);
+	const int args = lua_rawlen(l, 3);
+	for (int j = 0; j < args; ++j) {
+		lua_rawgeti(l, 3, j + 1);
+		const char *value = LuaToString(l, -1);
+		lua_pop(l, 1);
 		++j;
 
 		if (!strcmp(value, "costs")) {
-			if (!lua_istable(l, j + 1)) {
+			lua_rawgeti(l, 3, j + 1);
+			if (!lua_istable(l, -1)) {
 				LuaError(l, "incorrect argument");
 			}
-			const int subargs = lua_rawlen(l, j + 1);
+			const int subargs = lua_rawlen(l, -1);
 
 			for (int k = 0; k < subargs; ++k) {
-				lua_rawgeti(l, j + 1, k + 1);
+				lua_rawgeti(l, 3, j + 1);
+				lua_rawgeti(l, -1, k + 1);
 				value = LuaToString(l, -1);
 				lua_pop(l, 1);
 				++k;
 				const int resId = GetResourceIdByName(l, value);
-				lua_rawgeti(l, j + 1, k + 1);
+				lua_rawgeti(l, -1, k + 1);
 				stats->Costs[resId] = LuaToNumber(l, -1);
 				lua_pop(l, 1);
+				lua_pop(l, 1);
 			}
 		} else if (!strcmp(value, "storing")) {
-			if (!lua_istable(l, j + 1)) {
+			lua_rawgeti(l, 3, j + 1);
+			if (!lua_istable(l, -1)) {
 				LuaError(l, "incorrect argument");
 			}
-			const int subargs = lua_rawlen(l, j + 1);
+			const int subargs = lua_rawlen(l, -1);
 
 			for (int k = 0; k < subargs; ++k) {
-				lua_rawgeti(l, j + 1, k + 1);
+				lua_rawgeti(l, 3, j + 1);
+				lua_rawgeti(l, -1, k + 1);
 				value = LuaToString(l, -1);
 				lua_pop(l, 1);
 				++k;
 				const int resId = GetResourceIdByName(l, value);
-				lua_rawgeti(l, j + 1, k + 1);
+				lua_rawgeti(l, -1, k + 1);
 				stats->Storing[resId] = LuaToNumber(l, -1);
 				lua_pop(l, 1);
+				lua_pop(l, 1);
 			}
 		} else {
 			int i = UnitTypeVar.VariableNameLookup[value];// User variables
 			if (i != -1) { // valid index
-				if (lua_istable(l, j + 1)) {
-					DefineVariableField(l, stats->Variables + i, j + 1);
+				lua_rawgeti(l, 3, j + 1);
+				if (lua_istable(l, -1)) {
+					DefineVariableField(l, stats->Variables + i, -1);
 				} else if (lua_isnumber(l, -1)) {
 					stats->Variables[i].Enable = 1;
-					stats->Variables[i].Value = LuaToNumber(l, j + 1);
-					stats->Variables[i].Max = LuaToNumber(l, j + 1);
+					stats->Variables[i].Value = LuaToNumber(l, -1);
+					stats->Variables[i].Max = LuaToNumber(l, -1);
 				} else { // Error
 					LuaError(l, "incorrect argument for the variable in unittype");
 				}
diff --git a/src/unit/unit.cpp b/src/unit/unit.cpp
index 02be6fb1e..c916e79cb 100644
--- a/src/unit/unit.cpp
+++ b/src/unit/unit.cpp
@@ -959,7 +959,7 @@ void UnitLost(CUnit &unit)
 				const int newMaxValue = player.MaxResources[i] - type.Stats[player.Index].Storing[i];
 
 				player.MaxResources[i] = std::max(0, newMaxValue);
-				player.SetResource(i, player.StoredResources[i], true);
+				player.SetResource(i, player.StoredResources[i], STORE_BUILDING);
 			}
 		}
 		//  Handle income improvements, look if a player loses a building
@@ -2695,8 +2695,9 @@ int ThreatCalculate(const CUnit &unit, const CUnit &dest)
 **  @param attacker    Unit that attacks.
 **  @param target      Unit that is hit.
 **  @param damage      How many damage to take.
+**  @param missile     Which missile took the damage.
 */
-void HitUnit(CUnit *attacker, CUnit &target, int damage)
+void HitUnit(CUnit *attacker, CUnit &target, int damage, const Missile *missile)
 {
 	// Can now happen by splash damage
 	// Multiple places send x/y as damage, which may be zero
@@ -2836,6 +2837,16 @@ void HitUnit(CUnit *attacker, CUnit &target, int damage)
 		type->OnHit->run();
 	}
 
+	// Increase variables
+	if (missile && missile->Type->ChangeVariable != -1) {
+		const int var = missile->Type->ChangeVariable;
+		target.Variable[var].Enable = 1;
+		target.Variable[var].Value += missile->Type->ChangeAmount;
+		if (target.Variable[var].Value > target.Variable[var].Max && missile->Type->ChangeMax) {
+			target.Variable[var].Max = target.Variable[var].Value;
+		}
+	}
+
 	// Show impact missiles
 	if (target.Variable[SHIELD_INDEX].Value > 0
 		&& !target.Type->Impact[ANIMATIONS_DEATHTYPES + 1].Name.empty()) { // shield impact
diff --git a/src/unit/unittype.cpp b/src/unit/unittype.cpp
index 652d1e8fa..0de9886cb 100644
--- a/src/unit/unittype.cpp
+++ b/src/unit/unittype.cpp
@@ -368,7 +368,7 @@ static bool SaveUnitStats(const CUnitStats &stats, const CUnitType &type, int pl
 	if (stats == type.DefaultStat) {
 		return false;
 	}
-	file.printf("DefineUnitStats(\"%s\", %d,\n  ", type.Ident.c_str(), plynr);
+	file.printf("DefineUnitStats(\"%s\", %d, {\n  ", type.Ident.c_str(), plynr);
 	for (unsigned int i = 0; i < UnitTypeVar.GetNumberVariable(); ++i) {
 		file.printf("\"%s\", {Value = %d, Max = %d, Increase = %d%s},\n  ",
 					UnitTypeVar.VariableNameLookup[i], stats.Variables[i].Value,
@@ -382,14 +382,14 @@ static bool SaveUnitStats(const CUnitStats &stats, const CUnitType &type, int pl
 		}
 		file.printf("\"%s\", %d,", DefaultResourceNames[i].c_str(), stats.Costs[i]);
 	}
-	file.printf("\"storing\", {");
+	file.printf("},\n\"storing\", {");
 	for (unsigned int i = 0; i < MaxCosts; ++i) {
 		if (i) {
 			file.printf(" ");
 		}
 		file.printf("\"%s\", %d,", DefaultResourceNames[i].c_str(), stats.Storing[i]);
 	}
-	file.printf("})\n");
+	file.printf("}})\n");
 	return true;
 }