diff --git a/mapchooser_extended/configs/mapchooser_extended.cfg b/mapchooser_extended/configs/mapchooser_extended.cfg
index 8c53f82e..b81cf029 100644
--- a/mapchooser_extended/configs/mapchooser_extended.cfg
+++ b/mapchooser_extended/configs/mapchooser_extended.cfg
@@ -2,7 +2,7 @@
 {
 	"_groups"
 	{
-		"final_fantasy"
+		"1" // final fantasy
 		{
 			"_max" "2"
 			"ze_ffvii_cosmo_canyon_v1beta1" {}
@@ -32,7 +32,7 @@
 			"ze_FFXIV_Wanderers_Palace_v5_2f" {}
 			"ze_FFVII_Temple_Ancient_v3_3" {}
 		}
-		"cosmo"
+		"2" // cosmo
 		{
 			"_max" "1"
 			"ze_ffvii_cosmo_canyon_v1beta1" {}
@@ -42,7 +42,7 @@
 			"ze_ffvii_cosmo_canyon_v5test2" {}
 			"ze_ffvii_cosmo_canyon_v5fix" {}
 		}
-		"wester"
+		"3" // wester
 		{
 			"_max" "1"
 			"ze_ffxii_westersand_v2_11a" {}
@@ -51,7 +51,7 @@
 			"ze_FFXII_Westersand_v7" {}
 			"ze_FFXII_Westersand_v7_2" {}
 		}
-		"mako"
+		"4" // mako
 		{
 			"_max" "1"
 			"ze_FFVII_Mako_Reactor_b2" {}
@@ -60,20 +60,20 @@
 			"ze_FFVII_Mako_Reactor_v5_3" {}
 			"ZE_FFVII_Mako_Reactor_V6_B08" {}
 		}
-		"wanderes"
+		"5" // wanderes
 		{
 			"_max" "1"
 			"ze_ffxiv_wanderers_palace_css" {}
 			"ze_ffxiv_wanderers_palace_v4_5s" {}
 			"ze_FFXIV_Wanderers_Palace_v5_2f" {}
 		}
-		"minas"
+		"6" // minas
 		{
 			"_max" "1"
 			"ze_lotr_minas_tirith_v2_2fix" {}
 			"ze_lotr_minas_tirith_v3_3" {}
 		}
-		"rooftop"
+		"7" // rooftop
 		{
 			"_max" "2"
 			"ze_gargantua_v2_0" {}
@@ -294,4 +294,4 @@
 	{
 		"MinPlayers"	"20"
 	}
-}
\ No newline at end of file
+}
diff --git a/mapchooser_extended/scripting/include/mapchooser_extended.inc b/mapchooser_extended/scripting/include/mapchooser_extended.inc
index 93ee089e..d1c3804e 100644
--- a/mapchooser_extended/scripting/include/mapchooser_extended.inc
+++ b/mapchooser_extended/scripting/include/mapchooser_extended.inc
@@ -122,9 +122,9 @@ native int GetMapTimeRestriction(const char[] map);
 // >0 = More than MaxPlayers
 native int GetMapPlayerRestriction(const char[] map);
 
-// <0 = No group
-// >=0 = Group _max
-native int GetMapGroup(const char[] map, char[] group, int size);
+// <=0 = No group
+// >0 = Groups found
+native int GetMapGroups(const char[] map, int[] groups, int size);
 
 // <0 = No restriction
 // >=0 = Group _max -> Group full
diff --git a/mapchooser_extended/scripting/mapchooser_extended.sp b/mapchooser_extended/scripting/mapchooser_extended.sp
index 430e6d8e..7d711f93 100644
--- a/mapchooser_extended/scripting/mapchooser_extended.sp
+++ b/mapchooser_extended/scripting/mapchooser_extended.sp
@@ -408,7 +408,7 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max
 	CreateNative("GetMapMaxPlayers", Native_GetMapMaxPlayers);
 	CreateNative("GetMapTimeRestriction", Native_GetMapTimeRestriction);
 	CreateNative("GetMapPlayerRestriction", Native_GetMapPlayerRestriction);
-	CreateNative("GetMapGroup", Native_GetMapGroup);
+	CreateNative("GetMapGroups", Native_GetMapGroups);
 	CreateNative("GetMapGroupRestriction", Native_GetMapGroupRestriction);
 
 	return APLRes_Success;
@@ -1659,9 +1659,28 @@ void CreateNextVote()
 	int voteSize = GetVoteSize(2);
 	int limit = (voteSize < GetArraySize(tempMaps) ? voteSize : GetArraySize(tempMaps));
 
-	StringMap groups = new StringMap();
-	char group[255];
+	// group -> number of maps nominated from group
+	StringMap groupmap = new StringMap();
+	char groupstr[8];
 
+	// populate groupmap with maps from nomination list
+	static char map_[PLATFORM_MAX_PATH];
+	int groups_[32];
+	for(int i = 0; i < GetArraySize(g_NominateList); i++)
+	{
+		GetArrayString(g_NominateList, i, map_, PLATFORM_MAX_PATH);
+		int groupsfound = InternalGetMapGroups(map_, groups_, sizeof(groups_));
+		for(int group = 0; group < groupsfound; group++)
+		{
+			IntToString(group, groupstr, sizeof(groupstr));
+			int groupcur = 0;
+			groupmap.GetValue(groupstr, groupcur);
+			groupcur++;
+			groupmap.SetValue(groupstr, groupcur, true);
+		}
+	}
+
+	// find random maps which honor all restrictions
 	for(int i = 0; i < limit; i++)
 	{
 		int b;
@@ -1673,23 +1692,39 @@ void CreateNextVote()
 			if(InternalGetMapPlayerRestriction(map) == 0)
 				break;
 
-			int groupmax = InternalGetMapGroup(map, group, sizeof(group));
-			if(groupmax >= 0)
-			{
-				int groupcur = 0;
-				groups.GetValue(group, groupcur);
+			bool okay = true;
 
-				if(groupcur >= groupmax)
-					break;
-				groupcur++;
-				groups.SetValue(group, groupcur, true);
+			int groups[32];
+			int groupsfound = InternalGetMapGroups(map, groups, sizeof(groups));
+			for(int group = 0; group < groupsfound; group++)
+			{
+				IntToString(group, groupstr, sizeof(groupstr));
+
+				int groupmax = InternalGetGroupMax(groups[group]);
+				if(groupmax >= 0)
+				{
+					int groupcur = 0;
+					groupmap.GetValue(groupstr, groupcur);
+
+					if(groupcur >= groupmax)
+					{
+						okay = false;
+						break;
+					}
+
+					groupcur++;
+					groupmap.SetValue(groupstr, groupcur, true);
+				}
 			}
+
+			if(okay)
+				break;
 		}
 		PushArrayString(g_NextMapList, map);
 		RemoveFromArray(tempMaps, b);
 	}
 
-	delete groups;
+	delete groupmap;
 	CloseHandle(tempMaps);
 }
 
@@ -2177,7 +2212,7 @@ public int Native_GetMapPlayerRestriction(Handle plugin, int numParams)
 	return InternalGetMapPlayerRestriction(map);
 }
 
-public int Native_GetMapGroup(Handle plugin, int numParams)
+public int Native_GetMapGroups(Handle plugin, int numParams)
 {
 	int len;
 	GetNativeStringLength(1, len);
@@ -2189,11 +2224,11 @@ public int Native_GetMapGroup(Handle plugin, int numParams)
 	char[] map = new char[len+1];
 	GetNativeString(1, map, len+1);
 
-	char[] group = new char[size];
-	int groupmax = InternalGetMapGroup(map, group, size);
-	if(groupmax >= 0)
-		SetNativeString(2, group, size);
-	return groupmax;
+	int[] groups = new int[size];
+	int found = InternalGetMapGroups(map, groups, size);
+	if(found >= 0)
+		SetNativeArray(2, groups, size);
+	return found;
 }
 
 public int Native_GetMapGroupRestriction(Handle plugin, int numParams)
@@ -2208,45 +2243,51 @@ public int Native_GetMapGroupRestriction(Handle plugin, int numParams)
 	char[] map = new char[len+1];
 	GetNativeString(1, map, len+1);
 
-	static char group[255];
-	int groupmax = InternalGetMapGroup(map, group, sizeof(group));
-	int groupcur = 0;
-	if(groupmax >= 0)
-	{
-		static char map_[PLATFORM_MAX_PATH];
-		static char group_[255];
-		for(int i = 0; i < GetArraySize(g_NominateList); i++)
-		{
-			GetArrayString(g_NominateList, i, map_, PLATFORM_MAX_PATH);
-			int tmp = InternalGetMapGroup(map_, group_, sizeof(group_));
-			if(tmp == groupmax && StrEqual(group, group_))
-				groupcur++;
-		}
+	int groups[32];
+	int groupsfound = InternalGetMapGroups(map, groups, sizeof(groups));
 
-		if(groupcur >= groupmax)
+	for(int group = 0; group < groupsfound; group ++)
+	{
+		int groupcur = 0;
+		int groupmax = InternalGetGroupMax(groups[group]);
+
+		if(groupmax >= 0)
 		{
-			// Check if client has nominated a map in the same group and can change their nomination
-			if(client > 0 && client < MaxClients)
+			static char map_[PLATFORM_MAX_PATH];
+			int groups_[32];
+			for(int i = 0; i < GetArraySize(g_NominateList); i++)
 			{
-				int index = FindValueInArray(g_NominateOwners, client);
-				if(index != -1)
-				{
-					static char oldmap[PLATFORM_MAX_PATH];
-					GetArrayString(g_NominateList, index, oldmap, PLATFORM_MAX_PATH);
-					char oldgroup[255];
-					int tmp = InternalGetMapGroup(oldmap, oldgroup, sizeof(oldgroup));
-					if(tmp == groupmax && StrEqual(group, group_))
-						return -321;
-				}
+				GetArrayString(g_NominateList, i, map_, PLATFORM_MAX_PATH);
+				int tmp = InternalGetMapGroups(map_, groups_, sizeof(groups_));
+				if(FindIntInArray(groups_, tmp, groups[group]) != -1)
+					groupcur++;
 			}
 
-			return groupmax;
-		}
+			if(groupcur >= groupmax)
+			{
+				// Check if client has nominated a map in the same group and can change their nomination
+				bool okay = false;
+				if(client > 0 && client < MaxClients)
+				{
+					int index = FindValueInArray(g_NominateOwners, client);
+					if(index != -1)
+					{
+						static char oldmap[PLATFORM_MAX_PATH];
+						GetArrayString(g_NominateList, index, oldmap, PLATFORM_MAX_PATH);
+						static int oldgroups[32];
+						int tmp = InternalGetMapGroups(oldmap, oldgroups, sizeof(oldgroups));
+						if(FindIntInArray(groups_, tmp, groups[group]) != -1)
+							okay = true;
+					}
+				}
 
-		return -123;
+				if(!okay)
+					return groupmax;
+			}
+		}
 	}
 
-	return groupmax;
+	return -1;
 }
 
 
@@ -2433,8 +2474,9 @@ stock int InternalGetMapMaxPlayers(const char[] map)
 	return MaxPlayers;
 }
 
-stock int InternalGetMapGroup(const char[] map, char[] group, int size)
+stock int InternalGetMapGroups(const char[] map, int[] groups, int size)
 {
+	int found = 0;
 	if(g_Config && g_Config.JumpToKey("_groups"))
 	{
 		if(!g_Config.GotoFirstSubKey(false))
@@ -2445,19 +2487,44 @@ stock int InternalGetMapGroup(const char[] map, char[] group, int size)
 
 		do
 		{
-			int ret = g_Config.GetNum("_max", 1);
-			g_Config.GetSectionName(group, size);
+			char groupstr[8];
+			g_Config.GetSectionName(groupstr, sizeof(groupstr));
+			int group = StringToInt(groupstr);
 			if(g_Config.JumpToKey(map, false))
 			{
-				g_Config.Rewind();
-				return ret;
+				groups[found++] = group;
+				if(found >= size)
+				{
+					g_Config.Rewind();
+					return found;
+				}
+				g_Config.GoBack();
 			}
 		} while(g_Config.GotoNextKey());
 
 		g_Config.Rewind();
 	}
 
-	return -999;
+	return found;
+}
+
+stock int InternalGetGroupMax(int group)
+{
+	char groupstr[8];
+	IntToString(group, groupstr, sizeof(groupstr));
+	if(g_Config && g_Config.JumpToKey("_groups"))
+	{
+		if(g_Config.JumpToKey(groupstr, false))
+		{
+			int max = g_Config.GetNum("_max", -1);
+			g_Config.Rewind();
+			return max;
+		}
+
+		g_Config.Rewind();
+	}
+
+	return -1;
 }
 
 // 0 = Okay
@@ -2509,3 +2576,14 @@ stock int InternalGetMapPlayerRestriction(const char[] map)
 
 	return 0;
 }
+
+stock int FindIntInArray(int[] array, int size, int value)
+{
+	for(int i = 0; i < size; i++)
+	{
+		if(array[i] == value)
+			return i;
+	}
+
+	return -1;
+}