diff --git a/game/engines/default/engine/utils.lua b/game/engines/default/engine/utils.lua
index 1d66fbfe635c4b65dd657889660ce48132ac109d..7fdf9db38687dba7cfb25b0943b1d29ad2bc4885 100644
--- a/game/engines/default/engine/utils.lua
+++ b/game/engines/default/engine/utils.lua
@@ -283,6 +283,16 @@ function table.orderedPairs(t)
 	return orderedNext, t, nil
 end
 
+--- Shuffles the content of a table (list)
+function table.shuffle(t)
+	local n = #t
+	for i = n, 2, -1 do
+		local j = rng.range(1, i)
+		t[i], t[j] = t[j], t[i]
+	end
+	return t
+end
+
 function string.ordinal(number)
 	local suffix = "th"
 	number = tonumber(number)
diff --git a/game/modules/tome/class/GameState.lua b/game/modules/tome/class/GameState.lua
index d91418415c660f8b5dac200c4465d386fee61b0e..3c418f3a057640035684a2f12085f487cb2c96f8 100644
--- a/game/modules/tome/class/GameState.lua
+++ b/game/modules/tome/class/GameState.lua
@@ -1757,13 +1757,29 @@ end
 function _M:startEvents()
 	if not game.zone.events then print("No zone events loaded") return end
 
-	local evts = game.zone.events
-
 	if not game.zone.assigned_events then
 		local levels = {}
 		for i = 1, game.zone.max_level do levels[i] = {} end
 
+		-- Generate the events list for this zone, eventually loading from group files
+		local evts = {}
+		for i, e in ipairs(game.zone.events) do
+			if e.name then evts[#evts+1] = e.name
+			elseif e.group then
+				local f = loadfile("/data/general/events/groups/"..e..".lua")
+				setfenv(f, setmetatable({level=game.level, zone=game.zone}, {__index=_G}))
+				local list = f()
+				for j, ee in ipairs(list) do
+					if e.percent_factor and ee.percent then ee.percent = math.floor(ee.percent * e.percent_factor) end
+					if ee.name then evts[#evts+1] = ee.name end
+				end
+			end
+		end
+
+		-- Randomize the order they are checked as
+		table.shuffle(evts)
 		for i, e in ipairs(evts) do
+			-- If we allow it, try to find a level to host it
 			if e.always or rng.percent(e.percent) then
 				local lev = nil
 				if e.one_per_level then
diff --git a/game/modules/tome/data/general/events/groups/fareast-generic.lua b/game/modules/tome/data/general/events/groups/fareast-generic.lua
new file mode 100644
index 0000000000000000000000000000000000000000..1beb21b624e9eeafb8565f9ef9793b168fc940fa
--- /dev/null
+++ b/game/modules/tome/data/general/events/groups/fareast-generic.lua
@@ -0,0 +1,23 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010, 2011, 2012 Nicolas Casalini
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
+--
+-- Nicolas Casalini "DarkGod"
+-- darkgod@te4.org
+
+return {
+	{name="naga-portal", percent=7},
+	{name="fearscape-portal", percent=7},
+}
diff --git a/game/modules/tome/data/general/events/groups/outdoor-majeyal-generic.lua b/game/modules/tome/data/general/events/groups/outdoor-majeyal-generic.lua
new file mode 100644
index 0000000000000000000000000000000000000000..943ddae05cf9fe5eaaa58e4e6e7185f01d4798ce
--- /dev/null
+++ b/game/modules/tome/data/general/events/groups/outdoor-majeyal-generic.lua
@@ -0,0 +1,22 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010, 2011, 2012 Nicolas Casalini
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
+--
+-- Nicolas Casalini "DarkGod"
+-- darkgod@te4.org
+
+return {
+	{name="damp-cave", percent=10},
+}
diff --git a/game/modules/tome/data/general/events/groups/outdoor-majeyal-gloomy.lua b/game/modules/tome/data/general/events/groups/outdoor-majeyal-gloomy.lua
new file mode 100644
index 0000000000000000000000000000000000000000..3dc8cd0efa53f732f1d85b79ab7587c6f05791db
--- /dev/null
+++ b/game/modules/tome/data/general/events/groups/outdoor-majeyal-gloomy.lua
@@ -0,0 +1,23 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010, 2011, 2012 Nicolas Casalini
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
+--
+-- Nicolas Casalini "DarkGod"
+-- darkgod@te4.org
+
+return {
+	{name="tombstones", percent=10},
+	{name="old-battle-field", percent=5},
+}
diff --git a/game/modules/tome/data/zones/gorbat-pride/events.lua b/game/modules/tome/data/zones/gorbat-pride/events.lua
index 81dce66abcee85e7f65c969a392aa386f3e8e756..4454fe11bf13bbad0dd058b33d1345a8a88b62f6 100644
--- a/game/modules/tome/data/zones/gorbat-pride/events.lua
+++ b/game/modules/tome/data/zones/gorbat-pride/events.lua
@@ -18,6 +18,5 @@
 -- darkgod@te4.org
 
 return { one_per_level=true,
-	{name="naga-portal", percent=10},
-	{name="fearscape-portal", percent=10},
-}
\ No newline at end of file
+	{group="fareast-generic", percent_factor=1.5},
+}
diff --git a/game/modules/tome/data/zones/old-forest/events.lua b/game/modules/tome/data/zones/old-forest/events.lua
index 1f8958ae4c7b546b0a954696d5aa66a21a822076..b1e6d1252f7e7b5ccd932ccef59bba3f5a00d87b 100644
--- a/game/modules/tome/data/zones/old-forest/events.lua
+++ b/game/modules/tome/data/zones/old-forest/events.lua
@@ -18,7 +18,8 @@
 -- darkgod@te4.org
 
 return { one_per_level=true,
-	{name="damp-cave", percent=10},
 	{name="tombstones", percent=10},
 	{name="old-battle-field", percent=5},
+	{group="outdoor-majeyal-gloomy"},
+	{group="outdoor-majeyal-generic"},
 }
\ No newline at end of file
diff --git a/ideas/events b/ideas/events
index 9516d00c1c88eb0ae3edee504d3e69b60b7873c0..fdd7d59e125507c76d0a06a044949e92b8b104f4 100644
--- a/ideas/events
+++ b/ideas/events
@@ -1,5 +1,5 @@
 * fearscape invasion portal: demons pouring out: enter the demon gate; end up in orbit on a fearscape bit of land floating in space and destroy the master demon there
-* naga invasion portal: nagas pouring out: enter the water portal; end up in a water cave (provide air bubbles) and defeat the naga leader
+++ naga invasion portal: nagas pouring out: enter the water portal; end up in a water cave (provide air bubbles) and defeat the naga leader
 * 3 pedesrals, stay on each for 3 turns; each time a rare pops; when all 3 dead a portal pops and a randboss pops from it
 * 7 neutral cultists are spread on the level with a back stone nearby; when one is killed a timer starts, if all killed before timer is out a stair to a secret cave is revealed with an artifact inside
 ++ a few tombstones that can be interraced with; if disturbed a random undead (rare or randboss) may pop