diff --git a/src/include/ui/contenttype.h b/src/include/ui/contenttype.h
index 1a59e9628..ff5b06ae0 100644
--- a/src/include/ui/contenttype.h
+++ b/src/include/ui/contenttype.h
@@ -149,9 +149,10 @@ private:
 class CContentTypeLifeBar : public CContentType
 {
 public:
-	CContentTypeLifeBar() : Index(-1), Width(0), Height(0), hasBorder(true), colors(NULL), values(NULL) {}
+	CContentTypeLifeBar() : Index(-1), ValueFunc(NULL), ValueMax(-1), Width(0), Height(0), hasBorder(true), colors(NULL), values(NULL) {}
 	virtual ~CContentTypeLifeBar()
 	{
+		FreeNumberDesc(ValueFunc);
 		delete[] colors;
 		delete[] values;
 	}
@@ -161,6 +162,8 @@ public:
 
 private:
 	int Index;            /// Index of the variable to show, -1 if not.
+	NumberDesc *ValueFunc;/// Handler of the value function
+	int ValueMax;         /// Max, when used with a value function
 	int Width;            /// Width of the bar.
 	int Height;           /// Height of the bar.
 	bool hasBorder;       /// True for additional border.
diff --git a/src/ui/contenttype.cpp b/src/ui/contenttype.cpp
index b289194fc..125418a77 100644
--- a/src/ui/contenttype.cpp
+++ b/src/ui/contenttype.cpp
@@ -273,13 +273,18 @@ static const CUnit *GetUnitRef(const CUnit &unit, EnumUnit e)
 */
 /* virtual */ void CContentTypeLifeBar::Draw(const CUnit &unit, CFont *) const
 {
-	Assert((unsigned int) this->Index < UnitTypeVar.GetNumberVariable());
-	if (!unit.Variable[this->Index].Max) {
-		return;
-	}
-
 	Uint32 color;
-	int f = (100 * unit.Variable[this->Index].Value) / unit.Variable[this->Index].Max;
+	int f;
+	if (this->Index != -1) {
+		Assert((unsigned int) this->Index < UnitTypeVar.GetNumberVariable());
+		if (!unit.Variable[this->Index].Max) {
+			return;
+		}
+		f = (100 * unit.Variable[this->Index].Value) / unit.Variable[this->Index].Max;
+	} else {
+		f = (100 * EvalNumber(this->ValueFunc)) / this->ValueMax;
+		f = f > 100 ? 100 : f;
+	}
 	int i = 0;
 
 	// get to right color
@@ -494,10 +499,34 @@ static EnumUnit Str2EnumUnit(lua_State *l, const char *s)
 	for (lua_pushnil(l); lua_next(l, -2); lua_pop(l, 1)) {
 		const char *key = LuaToString(l, -2);
 		if (!strcmp(key, "Variable")) {
-			const char *const name = LuaToString(l, -1);
-			this->Index = UnitTypeVar.VariableNameLookup[name];
-			if (this->Index == -1) {
-				LuaError(l, "unknown variable '%s'" _C_ name);
+			if (lua_isstring(l, -1)) {
+				const char *const name = LuaToString(l, -1);
+				this->Index = UnitTypeVar.VariableNameLookup[name];
+				if (this->Index == -1) {
+					LuaError(l, "unknown variable '%s'" _C_ name);
+				}
+			} else {
+				if (!lua_istable(l, -1)) {
+					LuaError(l, "incorrect argument, need list of size 2 with {function, max} or a string with the name of a unit variable");
+				}
+				for (lua_pushnil(l); lua_next(l, -2); lua_pop(l, 1)) {
+					const char *key = LuaToString(l, -2);
+					if (!strcmp(key, "Max")) {
+						this->ValueMax = LuaToNumber(l, -1);
+					} else if (!strcmp(key, "Value")) {
+						this->ValueFunc = CclParseNumberDesc(l);
+						lua_pushnil(l); // ParseStringDesc eat token
+					} else {
+						lua_pop(l, 1);
+						LuaError(l, "unknow value '%s'" _C_ key);
+					}
+				}
+				if (this->ValueMax == -1) {
+					this->ValueMax = 100;
+				}
+				if (this->ValueFunc == NULL) {
+					LuaError(l, "didn't set a value function");
+				}
 			}
 		} else if (!strcmp(key, "Height")) {
 			this->Height = LuaToNumber(l, -1);
@@ -542,7 +571,7 @@ static EnumUnit Str2EnumUnit(lua_State *l, const char *s)
 	if (this->Width <= 0) {
 		this->Width = 50; // Default value.
 	}
-	if (this->Index == -1) {
+	if (this->Index == -1 && this->ValueFunc == NULL) {
 		LuaError(l, "variable undefined for LifeBar");
 	}
 	if (this->colors == NULL || this->values == NULL) {