Index: scripts/buttons.lua
===================================================================
--- scripts/buttons.lua	(Revision 9610)
+++ scripts/buttons.lua	(Arbeitskopie)
@@ -222,3 +222,16 @@
 	Allowed = "check-true", Hint = "~!NUKE EM",
 	ForUnit = {"unit-msilo"}})
 
+-- antievil -------------------------------------------------------------------
+
+DefineEvilButton({
+	Pos = 1, Level = 0, Icon = "icon-attack",
+	Action = "nuke",
+	Allowed = "check-true", Hint = "~!NUKE EM",
+	ForUnit = {}})
+
+DefineEvilButton({
+	Pos = 2, Level = 0, Icon = "icon-attack",
+	Action = "attackme",
+	Allowed = "check-true", Hint = "~!ATTACK WITH UNITS IN RANGE",
+	ForUnit = {}})
Index: engine/unit/unit.cpp
===================================================================
--- engine/unit/unit.cpp	(Revision 9610)
+++ engine/unit/unit.cpp	(Arbeitskopie)
@@ -62,6 +62,7 @@
 #include "editor.h"
 #include "spells.h"
 #include "luacallback.h"
+#include "commands.h"
 
 /*----------------------------------------------------------------------------
 --  Variables
@@ -2591,6 +2592,35 @@
 
 
 /*----------------------------------------------------------------------------
+--  Functions for enemys units
+----------------------------------------------------------------------------*/
+
+/**
+**  Attack unit with all units of one player in range that can attack it
+*/
+void CUnit::AttackWithUnitsInRange(const CPlayer *player, int range) {
+	CUnit *table[UnitMax];
+	CUnit *attacker;
+	int n;
+	int i;
+	
+	n = UnitCache.Select(X - range, Y - range, X + range + Type->TileWidth,
+		Y + range + Type->TileHeight, table, UnitMax);
+	
+	for (i = 0; i < n; ++i) {
+		attacker = table[i];
+		if (player != attacker->Player) {// we can't command this unit
+			continue;
+		}
+		if (attacker->IsUnusable()) {
+			continue;
+		}
+		SendCommandAttack(attacker, X, Y, this, 0);
+	}
+}
+
+
+/*----------------------------------------------------------------------------
 --  Initialize/Cleanup
 ----------------------------------------------------------------------------*/
 
Index: engine/include/interface.h
===================================================================
--- engine/include/interface.h	(Revision 9610)
+++ engine/include/interface.h	(Arbeitskopie)
@@ -65,6 +65,9 @@
 	ButtonCancel,         /// cancel
 	ButtonCancelTrain,    /// cancel training
 	ButtonCancelBuild,    /// cancel building
+
+	ButtonNuke,           /// nuke by button :)
+	ButtonAttackMe,       /// big attack by button :)
 };
 
 class ButtonAction;
@@ -88,6 +91,7 @@
 	IconConfig  Icon;        /// icon to display
 	int Key;                 /// alternative on keyboard
 	std::string Hint;        /// tip text
+	bool ForOwnUnits;
 };
 
 	/// Button area under cursor
@@ -236,6 +240,9 @@
 extern int AddButton(int pos, int level, const std::string &IconIdent,
 	ButtonCmd action, const std::string &value, const ButtonCheckFunc func,
 	const std::string &arg, const std::string &hint, const std::string &umask);
+extern int AddButton(bool forOwnUnits, int pos, int level, const std::string &IconIdent,
+	ButtonCmd action, const std::string &value, const ButtonCheckFunc func,
+	const std::string &arg, const std::string &hint, const std::string &umask);
 
 //
 // in mouse.cpp
Index: engine/include/unit.h
===================================================================
--- engine/include/unit.h	(Revision 9610)
+++ engine/include/unit.h	(Arbeitskopie)
@@ -735,6 +735,8 @@
 	bool IsTeamed(const CUnit *x) const;
 
 	bool IsUnusable() const;
+
+	void AttackWithUnitsInRange(const CPlayer *player, int range);
 };
 
 #define NoUnitP (CUnit *)0        /// return value: for no unit found
Index: engine/ui/script_ui.cpp
===================================================================
--- engine/ui/script_ui.cpp	(Revision 9610)
+++ engine/ui/script_ui.cpp	(Arbeitskopie)
@@ -876,6 +876,130 @@
 }
 
 /**
+**  Define a button.
+**
+**  @param l  Lua state.
+*/
+static int CclDefineEvilButton(lua_State *l)
+{
+	char buf[64];
+	const char *value;
+	const char *s2;
+	ButtonAction ba;
+
+	LuaCheckArgs(l, 1);
+	if (!lua_istable(l, 1)) {
+		LuaError(l, "incorrect argument");
+	}
+
+	//
+	// Parse the arguments
+	//
+	lua_pushnil(l);
+	while (lua_next(l, 1)) {
+		value = LuaToString(l, -2);
+		if (!strcmp(value, "Pos")) {
+			ba.Pos = LuaToNumber(l, -1);
+		} else if (!strcmp(value, "Level")) {
+			ba.Level = LuaToNumber(l, -1);
+		} else if (!strcmp(value, "Icon")) {
+			ba.Icon.Name = LuaToString(l, -1);
+		} else if (!strcmp(value, "Action")) {
+			value = LuaToString(l, -1);
+			if (!strcmp(value, "nuke")) {
+				ba.Action = ButtonNuke;
+			} else if (!strcmp(value, "attackme")) {
+				ba.Action = ButtonAttackMe;
+			} else {
+				LuaError(l, "Unsupported button action: %s" _C_ value);
+			}
+		} else if (!strcmp(value, "Value")) {
+			if (!lua_isnumber(l, -1) && !lua_isstring(l, -1)) {
+				LuaError(l, "incorrect argument");
+			}
+			if (lua_isnumber(l, -1)) {
+				sprintf_s(buf, sizeof(buf), "%ld", (long int)lua_tonumber(l, -1));
+				s2 = buf;
+			} else {
+				s2 = lua_tostring(l, -1);
+			}
+			ba.ValueStr = s2;
+		} else if (!strcmp(value, "Allowed")) {
+			value = LuaToString(l, -1);
+			if (!strcmp(value, "check-true")) {
+				ba.Allowed = ButtonCheckTrue;
+			} else if (!strcmp(value, "check-false")) {
+				ba.Allowed = ButtonCheckFalse;
+			} else if (!strcmp(value, "check-units-or")) {
+				ba.Allowed = ButtonCheckUnitsOr;
+			} else if (!strcmp(value, "check-units-and")) {
+				ba.Allowed = ButtonCheckUnitsAnd;
+			} else if (!strcmp(value, "check-network")) {
+				ba.Allowed = ButtonCheckNetwork;
+			} else if (!strcmp(value, "check-no-network")) {
+				ba.Allowed = ButtonCheckNoNetwork;
+			} else if (!strcmp(value, "check-no-work")) {
+				ba.Allowed = ButtonCheckNoWork;
+			} else if (!strcmp(value, "check-attack")) {
+				ba.Allowed = ButtonCheckAttack;
+			} else {
+				LuaError(l, "Unsupported action: %s" _C_ value);
+			}
+		} else if (!strcmp(value, "AllowArg")) {
+			int subargs;
+			int k;
+			std::string allowstr;
+
+			if (!lua_istable(l, -1)) {
+				LuaError(l, "incorrect argument");
+			}
+			subargs = lua_objlen(l, -1);
+			for (k = 0; k < subargs; ++k) {
+				lua_rawgeti(l, -1, k + 1);
+				s2 = LuaToString(l, -1);
+				lua_pop(l, 1);
+				allowstr += s2;
+				if (k != subargs - 1) {
+					allowstr += ",";
+				}
+			}
+			ba.AllowStr = allowstr;
+		} else if (!strcmp(value, "Hint")) {
+			ba.Hint = LuaToString(l, -1);
+		} else if (!strcmp(value, "ForUnit")) {
+			int subargs;
+			int k;
+			std::string umask;
+
+			if (!lua_istable(l, -1)) {
+				LuaError(l, "incorrect argument");
+			}
+			// FIXME: ba.UnitMask shouldn't be a string
+			umask = ",";
+			subargs = lua_objlen(l, -1);
+			for (k = 0; k < subargs; ++k) {
+				lua_rawgeti(l, -1, k + 1);
+				s2 = LuaToString(l, -1);
+				lua_pop(l, 1);
+				umask += s2;
+				umask += ",";
+			}
+			ba.UnitMask = umask;
+			if (ba.UnitMask.compare(0, 3, ",*,") == 0) {
+				ba.UnitMask = "*";
+			}
+		} else {
+			LuaError(l, "Unsupported tag: %s" _C_ value);
+		}
+		lua_pop(l, 1);
+	}
+	AddButton(false, ba.Pos, ba.Level, ba.Icon.Name, ba.Action, ba.ValueStr,
+		ba.Allowed, ba.AllowStr, ba.Hint, ba.UnitMask);
+
+	return 0;
+}
+
+/**
 **  Run the set-selection-changed-hook.
 */
 void SelectionChanged(void)
@@ -982,6 +1106,7 @@
 	lua_register(Lua, "RightButtonMoves", CclRightButtonMoves);
 
 	lua_register(Lua, "DefineButton", CclDefineButton);
+	lua_register(Lua, "DefineEvilButton", CclDefineEvilButton);
 
 	lua_register(Lua, "DefineButtonStyle", CclDefineButtonStyle);
 
Index: engine/ui/botpanel.cpp
===================================================================
--- engine/ui/botpanel.cpp	(Revision 9610)
+++ engine/ui/botpanel.cpp	(Arbeitskopie)
@@ -96,7 +96,7 @@
 /**
 **  Add a button
 */
-int AddButton(int pos, int level, const std::string &icon_ident,
+int AddButton(bool forOwnUnits, int pos, int level, const std::string &icon_ident,
 	ButtonCmd action, const std::string &value, const ButtonCheckFunc func,
 	const std::string &allow, const std::string &hint, const std::string &umask)
 {
@@ -106,6 +106,7 @@
 	ba = new ButtonAction;
 	Assert(ba);
 
+	ba->ForOwnUnits = forOwnUnits;
 	ba->Pos = pos;
 	ba->Level = level;
 	ba->Icon.Name = icon_ident;
@@ -156,7 +157,17 @@
 	return 1;
 }
 
+/**
+**  Add a button
+*/
+int AddButton(int pos, int level, const std::string &icon_ident,
+	ButtonCmd action, const std::string &value, const ButtonCheckFunc func,
+	const std::string &allow, const std::string &hint, const std::string &umask)
+{
+	return AddButton(true, pos, level, icon_ident, action, value, func, allow, hint, umask);
+}
 
+
 /**
 **  Cleanup buttons.
 */
@@ -563,6 +574,13 @@
 		case ButtonCancelBuild:
 			res = unit->Orders[0]->Action == UnitActionBuilt;
 			break;
+
+		case ButtonNuke:
+			res = true;
+			break;
+		case ButtonAttackMe:
+			res = true;
+			break;
 	}
 #if 0
 	// there is a additional check function -- call it
@@ -597,6 +615,10 @@
 	unit_ident = ",elites-group,";
 
 	for (z = 0; z < (int)UnitButtonTable.size(); ++z) {
+		if (!UnitButtonTable[z]->ForOwnUnits) {
+			continue;
+		}
+
 		if (UnitButtonTable[z]->Level != CurrentButtonLevel) {
 			continue;
 		}
@@ -666,6 +688,10 @@
 		buttonaction = UnitButtonTable[z];
 		Assert(0 < buttonaction->Pos && buttonaction->Pos <= (int)UI.ButtonPanel.Buttons.size());
 
+		if (!buttonaction->ForOwnUnits) {
+			continue;
+		}
+
 		// Same level
 		if (buttonaction->Level != CurrentButtonLevel) {
 			continue;
@@ -689,6 +715,56 @@
 	return res;
 }
 
+static ButtonAction *UpdateButtonPanelForEnemy(const CUnit *unit)
+{
+	//deactivated int allow;
+	std::string unit_ident;
+	ButtonAction *buttonaction;
+	ButtonAction *res;
+	int z;
+
+	Assert(unit);
+
+	res = new ButtonAction[UI.ButtonPanel.Buttons.size()];
+	for (z = 0; z < (int)UI.ButtonPanel.Buttons.size(); ++z) {
+		res[z].Pos = -1;
+	}
+
+	unit_ident = "," + unit->Type->Ident + ",";
+
+	for (z = 0; z < (int)UnitButtonTable.size(); ++z) {
+		int pos; // keep position, modified if alt-buttons required
+
+		buttonaction = UnitButtonTable[z];
+		Assert(0 < buttonaction->Pos && buttonaction->Pos <= (int)UI.ButtonPanel.Buttons.size());
+
+		if (buttonaction->ForOwnUnits) {
+			continue;
+		}
+
+		// Same level
+		if (buttonaction->Level != CurrentButtonLevel) {
+			continue;
+		}
+
+		// any unit or unit in list - no, we want them for all units
+		//if (buttonaction->UnitMask[0] != '*' &&
+		//		buttonaction->UnitMask.find(unit_ident) == std::string::npos) {
+		//	continue;
+		//}
+		// deactivated allow = IsButtonAllowed(unit, buttonaction);
+
+		pos = buttonaction->Pos;
+
+		// is button allowed after all?
+		// deactivated if (allow) {
+		// OverWrite, So take last valid button.
+		res[pos - 1] = *buttonaction;
+		//deactivated }
+	}
+	return res;
+}
+
 /**
 **  Update button panel.
 **
@@ -710,6 +786,7 @@
 	unit = Selected[0];
 	// foreign unit
 	if (unit->Player != ThisPlayer && !ThisPlayer->IsTeamed(unit)) {
+		CurrentButtons = UpdateButtonPanelForEnemy(unit);
 		return;
 	}
 
@@ -751,8 +829,7 @@
 	//  Button not available.
 	//  or Not Teamed
 	//
-	if (CurrentButtons[button].Pos == -1 ||
-			!ThisPlayer->IsTeamed(Selected[0])) {
+	if (CurrentButtons[button].Pos == -1) {
 		return;
 	}
 
@@ -914,6 +991,29 @@
 				ClearCosts();
 			}
 			break;
+
+		case ButtonAttackMe:
+			Selected[0]->AttackWithUnitsInRange(ThisPlayer, 50);
+			break;
+
+
+		case ButtonNuke:
+			int i;
+	
+			CUnit *array[MAX_UNIT_SLOTS];
+
+			int unitcount = FindUnitsByType(UnitTypeByIdent("unit-msilo"), array, MAX_UNIT_SLOTS);
+			SpellType *spelltype = SpellTypeByIdent("spell-nuke");
+	
+			for (i=0; i<unitcount; i++) {
+				if (array[i]->Player == ThisPlayer) {
+					if (array[i]->Variable[MANA_INDEX].Value >= spelltype->ManaCost) {
+						SendCommandSpellCast(array[i], 0, 0, Selected[0], spelltype->Slot, 1);
+						break;
+					}
+				}
+			}
+			break;
 	}
 }
 
Index: engine/ui/mouse.cpp
===================================================================
--- engine/ui/mouse.cpp	(Revision 9610)
+++ engine/ui/mouse.cpp	(Arbeitskopie)
@@ -1555,8 +1555,7 @@
 					}
 				}
 			} else if (ButtonAreaUnderCursor == ButtonAreaButton) {
-				if (!GameObserve && !GamePaused &&
-						ThisPlayer->IsTeamed(Selected[0])) {
+				if (!GameObserve && !GamePaused) {
 					UI.ButtonPanel.DoClicked(ButtonUnderCursor);
 				}
 			}
