diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua
index e05c241175ef50a84f9ae0a174893b7e20d52483..d618387a17ef3c4c45de7cc0ba967abb63284066 100644
--- a/game/modules/tome/class/Game.lua
+++ b/game/modules/tome/class/Game.lua
@@ -1121,6 +1121,7 @@ function _M:countBirthUnlocks()
 	local max = 0
 	local list = {
 		campaign_infinite_dungeon = true,
+		campaign_arena = true,
 
 		undead_ghoul = true,
 		undead_skeleton = true,
diff --git a/game/modules/tome/class/PlayerDisplay.lua b/game/modules/tome/class/PlayerDisplay.lua
index 48d4a05ecb5a6a9f9830b1296d794ee7372f8559..de163b38884224231f0fb46ffe4bd88f72c33e1b 100644
--- a/game/modules/tome/class/PlayerDisplay.lua
+++ b/game/modules/tome/class/PlayerDisplay.lua
@@ -265,6 +265,49 @@ function _M:display()
 		h = h + self.font_h
 	end
 
+	if game.level and game.level.arena then
+		h = h + self.font_h
+		local arena = game.level.arena
+		self:makeTexture(("-Arena mode-"), x, h, 255, 255, 255) h = h + self.font_h
+
+		if arena.score > world.arena.scores[1].score then
+			self:makeTexture(("Score(TOP): %d"):format(arena.score), x, h, 255, 255, 100) h = h + self.font_h
+		else
+			self:makeTexture(("Score: %d"):format(arena.score), x, h, 255, 255, 255) h = h + self.font_h
+		end
+		if arena.currentWave > world.arena.bestWave then
+			self:makeTexture(("Wave(TOP) %d"):format(arena.currentWave), x, h, 255, 255, 100)
+		elseif arena.currentWave > world.arena.lastScore.wave then
+			self:makeTexture(("Wave %d"):format(arena.currentWave), x, h, 100, 100, 255)
+		else
+			self:makeTexture(("Wave %d"):format(arena.currentWave), x, h, 255, 255, 255)
+		end
+		if arena.event > 0 then
+			if arena.event == 1 then
+				self:makeTexture((" [MiniBoss]"), x + (self.font_w * 13), h, 255, 255, 100)
+			elseif arena.event == 2 then
+				self:makeTexture((" [Boss]"), x + (self.font_w * 13), h, 255, 0, 255)
+			elseif arena.event == 3 then
+				self:makeTexture((" [Final]"), x + (self.font_w * 13), h, 255, 10, 15)
+			end
+		end
+		h = h + self.font_h
+		if arena.pinch == true then
+			self:makeTexture(("Bonus: %d (x%.1f)"):format(arena.bonus, arena.bonusMultiplier), x, h, 255, 50, 50) h = h + self.font_h
+		else
+			self:makeTexture(("Bonus: %d (x%.1f)"):format(arena.bonus, arena.bonusMultiplier), x, h, 255, 255, 255) h = h + self.font_h
+		end
+		if arena.display then
+			h = h + self.font_h
+			self:makeTexture(arena.display[1], x, h, 255, 0, 255) h = h + self.font_h
+			self:makeTexture(" VS", x, h, 255, 0, 255) h = h + self.font_h
+			self:makeTexture(arena.display[2], x, h, 255, 0, 255) h = h + self.font_h
+		else
+			self:makeTexture("Rank: "..arena.printRank(arena.rank, arena.ranks), x, h, 255, 255, 255) h = h + self.font_h
+		end
+		h = h + self.font_h
+	end
+
 	h = h + self.font_h
 	for tid, act in pairs(player.sustain_talents) do
 		if act then
@@ -285,6 +328,7 @@ function _M:display()
 			self:mouseTooltip(desc, self:makeTexture(("#LIGHT_GREEN#%s(%d)"):format(e.desc,dur), x, h, 255, 255, 255)) h = h + self.font_h
 		end
 	end
+
 end
 
 function _M:toScreen()
diff --git a/game/modules/tome/class/generator/actor/Arena.lua b/game/modules/tome/class/generator/actor/Arena.lua
new file mode 100644
index 0000000000000000000000000000000000000000..f54f5e977855bd34b39cf9a883febcc50cf1f47f
--- /dev/null
+++ b/game/modules/tome/class/generator/actor/Arena.lua
@@ -0,0 +1,484 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010 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
+
+require "engine.class"
+local Map = require "engine.Map"
+require "engine.Generator"
+
+module(..., package.seeall, class.inherit(engine.Generator))
+
+function _M:init(zone, map, level, spots)
+	engine.Generator.init(self, zone, map, level, spots)
+	self.data = level.data.generator.actor
+	self.level = level
+	self.rate = self.data.rate
+	self.max_rate = 5
+	self.turn_scale = game.energy_per_tick / game.energy_to_act
+end
+
+function _M:tick()
+	if game.level.arena.initEvent == true and game.level.arena.lockEvent == false then
+		game.level.arena.lockEvent = true
+		if game.level.arena.event == 1 then
+			local mboss = math.floor(game.level.arena.currentWave / game.level.arena.eventWave)
+			self:summonMiniboss(mboss)
+			return
+		elseif game.level.arena.event == 2 then
+			local boss = math.floor(game.level.arena.currentWave / (game.level.arena.eventWave * 3))
+			self:generateBoss(boss)
+			return
+		elseif game.level.arena.event == 3 then
+			self:generateMaster()
+		end
+	end
+
+	if game.level.arena.pinch == true or game.level.turn_counter or game.level.arena.delay > 0 then return
+	else --Get entity data.
+		local dangerMin = 1 + math.floor(game.level.arena.currentWave * 0.1)
+		local dangerMax = dangerMin + (game.level.arena.currentWave ^ game.level.arena.dangerMod)
+		local en = rng.range(dangerMin, dangerMax)
+		local t = self:calculateWave()
+		if t.special then t = t.special(t) end
+		for i = 1, t.wave do
+			self:generateOne(t)
+		end
+		if t.entitySub then t.entity = t.entitySub self:generateOne(t) end
+		game.level.arena.delay = self:mitigateDelay(t.delay, en)
+	end
+end
+
+function _M:mitigateDelay(val, l)
+	local wave = game.level.arena.currentWave
+	if wave > 10 and l + 1 < wave then
+		local reduction = math.floor(wave * 0.1)
+		if reduction > 3 then reduction = 3 end
+	end
+	return val
+end
+
+function _M:summonMiniboss(val)
+	local miniboss = {
+		{ name = "SKELERAT", wave = 4, entry = 2, display = "Skeletal rats", score = 100, power = 5 },
+		{ name = "GLADIATOR", wave = 2, entry = 1, display = "Gladiators", score = 150, power = 10 },
+		{ nil },
+		{ name = "GOLDCRYSTAL", wave = 4, entry = 3, display = "Golden crystals", score = 250, power = 15 },
+		{ name = "MASTERSLINGER", wave = 3, entry = 2, display = "Master slingers", score = 350, power = 20 },
+		{ nil },
+		{ name = "MASTERALCHEMIST", wave = 1, entry = 1, display = "Master Alchemist", score = 400, power = 25 },
+		{ name = "MULTIHUEWYRMIC", wave = 1, entry = 1, display = "Multi-hued Wyrmic", score = 400, power = 30 },
+		{ nil },
+		{ name = "REAVER", wave = 2, entry = 2, display = "Reaver", score = 800, power = 40 },
+		{ name = "HEADLESSHORROR", wave = 1, entry = 1, display = "Headless horror", score = 1000, power = 50 },
+	}
+	local e = miniboss[val] or miniboss[1]
+	for i = 1, e.wave do
+		self:generateMiniboss(e)
+	end
+	game.level.arena.display = {game.player.name.." the "..game.level.arena.printRank(game.level.arena.rank, game.level.arena.ranks), e.display}
+	local verb = ""
+	game:playSoundNear(game.player, "talents/teleport")
+	if e.wave > 1 then verb = " appear!!" else verb = " appears!!" end
+	game.log("#LIGHT_RED#"..e.display..verb)
+end
+
+function _M:getEntrance(val)
+	if val == 1 then return game.level.arena.entry.main
+		elseif val == 3 then return game.level.arena.entry.crystal
+		else return game.level.arena.entry.corner
+	end
+end
+
+function _M:generateMiniboss(e)
+	local m = self.zone:makeEntityByName(self.level, "actor", e.name)
+	if m then
+		local entry = self:getEntrance(e.entry)
+		m.arenaPower = e.power
+		m.arenaScore = e.score
+		if m.on_added then m.on_added_orig = m.on_added end
+		m.on_added = function (self)
+			if m.on_added_orig then m.on_added_orig(self) end
+			game.level.arena.danger = game.level.arena.danger + self.arenaPower
+			game.level.map:particleEmitter(self.x, self.y, 1, "teleport")
+			game.level.arena.pinchValue = game.level.arena.pinchValue + self.arenaPower
+		end
+		if m.on_die then m.on_die_orig = m.on_die end
+		m.on_die = function (self)
+			if m.on_die_orig then m.on_die_orig(self) end
+			game.level.arena.danger = game.level.arena.danger - self.arenaPower
+			game.level.arena.bonus = game.level.arena.bonus + self.arenaScore
+			game.level.map:particleEmitter(self.x, self.y, 1, "ball_fire", {radius = 1})
+		end
+		self:place(m, entry, true)
+	else print("[ARENA] Miniboss error ("..e.display..")")
+	end
+end
+
+function _M:place(m, entry, elite)
+	local place = rng.range(1, entry.max)
+	local x, y = entry[place]()
+	local tries = 0
+	while (not m:canMove(x, y)) and tries < entry.max + 2 do
+		x, y = entry[place]()
+		place = rng.range(1, entry.max)
+		tries = tries + 1
+	end
+	if elite == true then
+		self.zone:addEntity(self.level, m, "actor", x, y)
+	elseif tries < entry.max + 2 then
+		self.zone:addEntity(self.level, m, "actor", x, y)
+	end
+end
+
+
+function _M:generateBoss(val)
+	local bosses = {
+		{ name = "ARENA_BOSS_RYAL", display = "Ryal the Towering", chat = "arena_boss_ryal",
+		score = 1500, power = 35,
+		start = function ()
+			local Chat = require "engine.Chat"
+			local chat = Chat.new("arena", {name="Boss fight!"}, game.player)
+			chat:invoke("ryal-entry")
+		end,
+		finish = function ()
+			local Chat = require "engine.Chat"
+			local chat = Chat.new("arena", {name="Victory!!"}, game.player)
+			chat:invoke("ryal-defeat")
+		end
+		},
+		{ name = "ARENA_BOSS_FRYJIA", display = "Fryjia the Hailstorm", chat= "arena_boss_fryjia",
+		score = 2500, power = 55,
+		start = function ()
+			local Chat = require "engine.Chat"
+			local chat = Chat.new("arena", {name="Boss fight!"}, game.player)
+			chat:invoke("fryjia-entry")
+		end,
+		finish = function ()
+			local Chat = require "engine.Chat"
+			local chat = Chat.new("arena", {name="Victory!!"}, game.player)
+			chat:invoke("fryjia-defeat")
+		end
+		},
+		{ name = "ARENA_BOSS_RIALA", display = "Riala the Crimson", chat = "arena_boss_riala",
+		score = 3500, power = 85,
+		start = function ()
+			local Chat = require "engine.Chat"
+			local chat = Chat.new("arena", {name="Boss fight!"}, game.player)
+			chat:invoke("riala-entry")
+		end,
+		finish = function ()
+			local Chat = require "engine.Chat"
+			local chat = Chat.new("arena", {name="Victory!!"}, game.player)
+			chat:invoke("riala-defeat")
+		end
+		},
+		{ name = "ARENA_BOSS_VALFREN", display = "Valfren the Rampage", chat = "arena_boss_valfren",
+		score = 4500, power = 125,
+		start = function ()
+			game.level.map:setShown(0.3, 0.3, 0.3, 1)
+			game.level.map:setObscure(0.3*0.6, 0.3*0.6, 0.3*0.6, 1)
+			local Chat = require "engine.Chat"
+			local chat = Chat.new("arena", {name="Boss fight!"}, game.player)
+			chat:invoke("valfren-entry")
+		end,
+		finish = function ()
+			game.level.map:setShown(1, 1, 1, 1)
+			game.level.map:setObscure(1*0.6, 1*0.6, 1*0.6, 1)
+			local Chat = require "engine.Chat"
+			local chat = Chat.new("arena", {name="Victory!!"}, game.player)
+			chat:invoke("valfren-defeat")
+		end
+		},
+	}
+	local e = bosses[val] or bosses[1]
+	local m = self.zone:makeEntityByName(self.level, "actor", e.name)
+	if m then
+		m.arenaPower = e.power
+		m.arenaScore = e.score
+		m.on_added = function (self)
+			game.level.arena.danger = game.level.arena.danger + self.arenaPower
+			game.level.map:particleEmitter(self.x, self.y, 1, "teleport")
+			game:playSoundNear(game.player, "talents/teleport")
+			game.level.arena.pinchValue = game.level.arena.pinchValue + self.arenaPower
+		end
+		m.on_die = function (self)
+			game.level.arena.danger = game.level.arena.danger - self.arenaPower
+			game.level.arena.bonus = game.level.arena.bonus + self.arenaScore
+			game.level.map:particleEmitter(self.x, self.y, 1, "ball_fire", {radius = 2})
+			self.arenaDefeat()
+		end
+		e.start()
+		m.arenaDefeat = e.finish
+		self.zone:addEntity(self.level, m, "actor", 7, 1)
+		game.level.arena.display = {game.player.name.." the "..game.level.arena.printRank(game.level.arena.rank, game.level.arena.ranks), e.display}
+		game.log("#LIGHT_RED#WARNING! "..e.display.." appears!!!")
+		else print("[ARENA] - Boss error #1! ("..e.display..")")
+	end
+end
+
+function _M:generateMaster()
+	local defmaster = true
+	local master
+	if game.level.arena.finalWave < 60 then
+		master = world.arena.master30 or nil
+	else
+		master = world.arena.master60 or nil
+	end
+	if master then
+		if master.version[1] == game.__mod_info.version[1] and	master.version[2] == game.__mod_info.version[2] and master.version[3] == game.__mod_info.version[3] then
+			defmaster = false
+		else
+			defmaster = true
+		end
+	else defmaster = true
+	end
+
+	if defmaster == true then
+		local m = self.zone:makeEntityByName(self.level, "actor", "ARENA_BOSS_MASTER_DEFAULT")
+		if m then
+			m.on_added = function (self)
+				local Chat = require "engine.Chat"
+				local chat = Chat.new("arena", {name="The final fight!"}, game.player)
+				chat:invoke("master-entry")
+				game.level.arena.danger = game.level.arena.danger + 1000
+				game.level.map:particleEmitter(self.x, self.y, 3, "teleport")
+				game:playSoundNear(game.player, "talents/teleport")
+				game.level.arena.pinchValue = game.level.arena.pinchValue + 100
+			end
+			m.on_die = function (self)
+				game.level.arena.danger = 0
+				game.level.arena.bonus = 100
+				game.level.map:particleEmitter(self.x, self.y, 1, "ball_fire", {radius = 5})
+				game.level.arena.clear()
+				local Chat = require "engine.Chat"
+				local chat = Chat.new("arena", {name="Congratulations!"}, game.player)
+				chat:invoke("master-defeat")
+			end
+			self.zone:addEntity(self.level, m, "actor", 7, 1)
+			local rank = math.floor(game.level.arena.rank)
+			game.level.arena.display = {game.player.name.." the "..game.level.arena.printRank(game.level.arena.rank, game.level.arena.ranks), "Rej the Master of Arena"}
+			game.log("#LIGHT_RED#WARNING! Rej Arkatis, the master of the arena, appears!!!")
+			else print("[ARENA] - Finale error #1! (Default master error)")
+		end
+	else
+		local m = master
+		mod.class.NPC.castAs(m)
+		engine.interface.ActorAI.init(m, m)
+		m.on_added = function (self)
+			local Chat = require "engine.Chat"
+			local chat = Chat.new("arena", {name="The final fight!"}, game.player)
+			chat:invoke("master-entry")
+			game.level.arena.danger = game.level.arena.danger + 1000
+			game.level.map:particleEmitter(self.x, self.y, 3, "teleport")
+			game:playSoundNear(game.player, "talents/teleport")
+			game.level.arena.pinchValue = game.level.arena.pinchValue + 100
+		end
+		m.on_die = function (self)
+			game.level.arena.danger = 0
+			game.level.arena.bonus = 100
+			game.level.map:particleEmitter(self.x, self.y, 1, "ball_fire", {radius = 3})
+			game.level.arena.clear()
+			local Chat = require "engine.Chat"
+			local chat = Chat.new("arena", {name="Congratulations!"}, game.player)
+			chat:invoke("master-defeat")
+
+		end
+		self.zone:addEntity(self.level, m, "actor", 7, 1)
+		game.level.arena.display = {game.player.name.." the "..game.level.arena.printRank(game.level.arena.rank, game.level.arena.ranks), m.name.." the Master of Arena"}
+		game.log("#LIGHT_RED#WARNING! "..m.name..", the master of the arena, appears!!!")
+	end
+end
+
+function _M:calculateWave()
+--TODO:Apply some reduction in delay based on current wave.
+	local foe = {
+--Relative cannon fodder.
+		{ entity = { type = "vermin", subtype = "rodent" }, --Wave 1
+			wave = 4, power = 2, delay = 3, bonus = 0.1, score = 5, entry = 2 },
+		{ entity = { type = "insect", subtype = "ant" },
+			wave = 2, power = 2, delay = 2, bonus = 0.1, score = 15 , entry = 2 },
+		{ entity = { type = "animal", subtype = "canine" },
+			wave = 2, power = 3, delay = 3, bonus = 0.1 , score = 25, entry = 2 },
+		{ entity = { name = "white ooze" },
+			wave = 1, power = 3, delay = 3, bonus = 0.1, score = 15, entry = 2,
+			special = function (self) if game.level.arena.currentWave > 10 then self.wave = 2 end if game.level.arena.currentWave > 15 then self.entity = { name = "green ooze" } end return self end },
+		{ entity = { name = "cutpurse" }, --Wave ~5
+			wave = 1, power = 8, delay = 3, bonus = 0.1, score = 40, entry = 1 },
+		{ entity = { name = "white crystal" },
+			wave = 1, power = 5, delay = 4, bonus = 0.5 , score = 100, entry = 3},
+		{ entity = { name = "slinger" },
+			wave = 1, power = 7, delay = 4, bonus = 0.2, score = 100, entry = 1,
+			special = function (self) if game.level.arena.currentWave > 35 then self.entity = { name = "high slinger" } end return self end },
+		{ entity = { name = "brown bear" },
+			wave = 1, power = 4, delay = 3, bonus = 0.2, score = 100 , entry = 2},
+		{ entity = { type = "animal", subtype = "snake" },
+			wave = 2, power = 4, delay = 3, bonus = 0.1, score = 100 , entry = 2},
+		{ entity = { type = "humanoid", subtype = "human", name = "rogue" }, --Wave ~10
+			wave = 1, power = 6, delay = 3, bonus = 0.2, score = 100 , entry = 1,
+			special = function (self) if game.level.arena.currentWave > 30 then self.wave = 2 end return self end },
+		{ entity = { type = "animal", subtype = "bear" },
+			wave = 2, power = 4, delay = 5, bonus = 0.3, score = 80, entry = 2 },
+		{ entity = { type = "vermin", subtype = "ooze" },
+			wave = 4, power = 3, delay = 2, bonus = 0.1, score = 15, entry = 2 },
+		{ entity = { type = "undead", subtype = "skeleton" },
+			wave = 1, power = 8, delay = 4, bonus = 0.2, score = 120, entry = 2,
+			special = function (self) if game.level.arena.currentWave > 15 then self.wave = 2 end return self end },
+		{ entity = { name = "ghoul" },
+			wave = 1, power = 7, delay = 5, bonus = 0.2, score = 150, entry = 1,
+			special = function (self) if game.level.arena.currentWave > 20 then self.wave, self.entry = 2, 2 end return self end },
+		{ entity = { type = "humanoid", subtype = "human", name = "alchemist" },
+			wave = 1, power = 9, delay = 3, bonus = 0.2, score = 150, entry = 1,
+			special = function (self) if game.level.arena.currentWave > 25 then self.wave = 2 end return self end },
+		{ entity = { type = "immovable", subtype = "crystal" },
+			wave = 2, power = 5, delay = 3, bonus = 0.5 , score = 100, entry = 3,
+			special = function (self) if game.level.arena.currentWave > 20 then self.wave = 3 end if game.level.arena.currentWave > 45 then self.wave = 4 end return self end },
+		{ entity = { type = "giant", subtype = "troll" },
+			wave = 1, power = 4, delay = 2, bonus = 0.2 , score = 150, entry = 1 },
+		{ entity = { name = "blood mage" },
+			wave = 1, power = 10, delay = 2, bonus = 0.5 , score = 200, entry = 1 },
+		{ entity = { name = "honey tree" },
+			wave = 1, power = 4, delay = 3, bonus = 0.3 , score = 120, entry = 3,
+			special = function (self) if game.level.arena.currentWave > 35 then self.wave, self.score  = 2, 150 end return self end },
+		{ entity = { name = "skeleton mage" },
+			wave = 1, power = 10, delay = 4, bonus = 0.3, score = 150 , entry = 1,
+			special = function (self) if game.player.level > 10 then self.wave = 2 end return self end },
+		{ entity = { name = "high gladiator" },
+			wave = 1, power = 6, delay = 1, bonus = 0.3, score = 200, entry = 1,
+			special = function (self) if game.level.arena.currentWave > 30 then self.wave = 2 end return self end },
+		{ entity = { name = "wisp" },
+			wave = 4, power = 1, delay = 1, bonus = 0.3, score = 50 , entry = 3 },
+		{ entity = { name = "minotaur" },
+			wave = 1, power = 12, delay = 3, bonus = 0.3, score = 150 , entry = 2 },
+		{ entity = { name = "shadowblade" },
+			wave = 1, power = 13, delay = 1, bonus = 0.4, score = 200 , entry = 1 },
+		{ entity = { name = "orc soldier" },
+			wave = 1, power = 10, delay = 4, bonus = 0.3, score = 150 , entry = 1,
+			special = function (self) if game.level.arena.currentWave > 25 then self.entity = {type = "humanoid", subtype = "orc"} end return self end },
+		{ entity = { name = "bone giant" },
+			wave = 1, power = 11, delay = 3, bonus = 0.3, score = 150 , entry = 2,
+			special = function (self) if game.player.level > 30 then self.wave, self.power = 2, 8 end return self end },
+		{ entity = { name = "ziguranth warrior" },
+			wave = 2, power = 8, delay = 2, bonus = 0.3, score = 130 , entry = 1 },
+		{ entity = { name = "orc archer" },
+			wave = 2, power = 10, delay = 5, bonus = 0.2, score = 100, entry = 2,
+			special = function (self) if game.player.level > 25 then self.wave, self.score  = 3, 125 end if game.player.level > 35 then self.wave, self.score  = 4, 150 end return self end },
+		{ entity = { name = "hexer" },
+			wave = 1, power = 13, delay = 1, bonus = 0.5 , score = 250, entry = 1 },
+		{ entity = { name = "wisp" },
+			wave = 6, power = 1, delay = 1, bonus = 0.3, score = 50 , entry = 3 },
+		{ entity = { name = "orc assassin" },
+			wave = 2, power = 10, delay = 4, bonus = 0.2, score = 200, entry = 2 },
+		{ entity = { name = "fire wyrmic" }, entitySub = { name = "ice wyrmic"},
+			wave = 1, power = 11, delay = 3, bonus = 0.3, score = 250, entry = 1 },
+		{ entity = { name = "sand wyrmic" }, entitySub = { name = "storm wyrmic" },
+			wave = 1, power = 11, delay = 3, bonus = 0.3, score = 250, entry = 1 },
+		{ entity = { name = "martyr" },
+			wave = 1, power = 13, delay = 1, bonus = 0.5 , score = 250, entry = 1 },
+		{ entity = { type = "vermin", subtype = "sandworm" },
+			wave = 1, power = 10, delay = 3, bonus = 0.2, score = 200, entry = 2 },
+		{ entity = { name = "ritch larva" },
+			wave = 2, power = 4, delay = 3, bonus = 0.1, score = 150, entry = 2 },
+		{ entity = { type = "giant", subtype = "ice" },
+			wave = 1, power = 8, delay = 2, bonus = 0.5, score = 300, entry = 1 },
+		{ entity = { name = "naga myrmidon" },
+			wave = 1, power = 9, delay = 2, bonus = 0.3, score = 300, entry = 1,
+			special = function (self) if game.level.arena.currentWave > 40 then self.wave = 2 end return self end },
+		{ entity = { name = "quasit" },
+			wave = 1, power = 9, delay = 2, bonus = 0.2, score = 300, entry = 2 },
+		{ entity = { name = "wretchling" },
+			wave = 1, power = 10, delay = 3, bonus = 0.3, score = 250, entry = 2,
+			special = function (self) if game.player.level > 25 then self.wave = 3 end if game.player.level > 35 then self.wave = 4 end return self end },
+		{ entity = { name = "great gladiator" },
+			wave = 2, power = 9, delay = 3, bonus = 0.3, score = 300, entry = 1 },
+		{ entity = { name = "bloated horror" },
+			wave = 2, power = 11, delay = 2, bonus = 0.4, score = 300, entry = 3 },
+		{ entity = { name = "umber hulk" },
+			wave = 1, power = 10, delay = 3, bonus = 0.3, score = 350, entry = 1 },
+		{ entity = { name = "anorithil" },
+			wave = 1, power = 10, delay = 2, bonus = 0.5, score = 450, entry = 1 },
+		{ entity = { name = "naga tide huntress" },
+			wave = 1, power = 10, delay = 2, bonus = 0.3, score = 300, entry = 2 },
+		{ entity = { name = "ritch hunter" },
+			wave = 4, power = 6, delay = 5, bonus = 0.4, score = 250, entry = 2 },
+		{ entity = { type = "undead", subtype = "wight" },
+			wave = 1, power = 11, delay = 2, bonus = 0.5, score = 400, entry = 1 },
+		{ entity = { name = "sun paladin" },
+			wave = 1, power = 12, delay = 2, bonus = 1, score = 450, entry = 1 },
+		{ entity = { name = "dread" },
+			wave = 1, power = 13, delay = 2, bonus = 1, score = 450, entry = 2 },
+		{ entity = { name = "naga psyren" },
+			wave = 1, power = 10, delay = 2, bonus = 0.3, score = 400, entry = 2 },
+		{ entity = { name = "star crusader" },
+			wave = 1, power = 14, delay = 2, bonus = 1, score = 450, entry = 2 },
+
+	}
+	local dangerMin = 1 + math.floor(game.level.arena.currentWave * 0.1)
+	local dangerMax = dangerMin + (game.level.arena.currentWave ^ game.level.arena.dangerMod)
+	if dangerMax > #foe then dangerMax = #foe end
+	local val = rng.range(dangerMin, dangerMax)
+	return foe[val]
+end
+
+function _M:generateOne(e)
+	local m = self.zone:makeEntity(self.level, "actor", e.entity, nil, true)
+	if m then
+		local escort = m.make_escort
+		m.make_escort = nil
+		local entry = self:getEntrance(e.entry)
+		m.arenaPower = e.power * m.level
+		m.arenaBonusMult = e.bonus
+		m.arenaScore = e.score
+		if m.on_added then m.on_added_orig = m.on_added end
+		if e.entry == 3 then
+			m.on_added = function (self)
+				if self.on_added_orig then self.on_added_orig(self) end
+				game.level.arena.danger = game.level.arena.danger + self.arenaPower
+				game:playSoundNear(game.player, "talents/teleport")
+				game.level.map:particleEmitter(self.x, self.y, 0.5, "teleport")
+			end
+		else
+			m.on_added = function (self)
+				if m.on_added_orig then m.on_added_orig(self) end
+				game.level.arena.danger = game.level.arena.danger + self.arenaPower
+			end
+		end
+		if m.on_die then m.on_die_orig = m.on_die end
+		m.on_die = function (self)
+			if self.on_die_orig then self.on_die_orig(self) end
+			game.level.arena.danger = game.level.arena.danger - self.arenaPower
+			if game.level.arena.pinch == false then
+				game.log("#LIGHT_GREEN#Your score multiplier increases by #WHITE#"..self.arenaBonusMult.."#LIGHT_GREEN#!")
+				game.level.arena.bonusMultiplier = game.level.arena.bonusMultiplier + self.arenaBonusMult
+			else
+				game.level.arena.bonus = game.level.arena.bonus + self.arenaScore
+			end
+			game.level.arena.kills = game.level.arena.kills + 1
+			if game.level.arena.kills > 5 then
+				game.level.arena.bonusMultiplier = game.level.arena.bonusMultiplier + 0.1
+				game.log("#LIGHT_GREEN#Your score multiplier increases by #WHITE#0.1#LIGHT_GREEN#!")
+			end
+			if self.level > game.player.level + 3 then
+				game.log("#YELLOW#You defeat an experienced enemy!")
+				local raise = (self.level - game.player.level) + 0.03
+				if raise > 0.5 then raise = 0.5 end
+				game.level.arena.raiseRank(raise)
+			end
+		end
+		self:place(m, entry, false)
+	end
+end
diff --git a/game/modules/tome/data/achievements/arena.lua b/game/modules/tome/data/achievements/arena.lua
new file mode 100644
index 0000000000000000000000000000000000000000..19a7232c25db8e8ecd436a87c0ceeaa2c1ce98f1
--- /dev/null
+++ b/game/modules/tome/data/achievements/arena.lua
@@ -0,0 +1,58 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010 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
+
+newAchievement{
+	name = "The Arena",
+	desc = [[Unlocked Arena mode.]],
+}
+
+newAchievement{
+	name = "Arena Battler 20",
+	desc = [[Got to wave 20 in the arena.]],
+}
+
+newAchievement{
+	name = "Arena Battler 50",
+	desc = [[Got to wave 50 in the arena.]],
+}
+	
+newAchievement{
+	name = "Almost Master of Arena",
+	desc = [[Became the new master of the arena in 30-wave mode.]],
+}
+
+newAchievement{
+	name = "Master of Arena",
+	desc = [[Became the new master of the arena in 60-wave mode.]],
+}
+	
+newAchievement{
+	name = "XXX the Destroyer",
+	desc = [[Earned the rank of Destroyer in the arena.]],
+}
+	
+newAchievement{
+	name = "Grand Master",
+	desc = [[Earned the rank of Grand Master in the arena.]],
+}
+
+newAchievement{
+	name = "Ten at one blow",
+	desc = [[Killed ten enemies in a single turn, in the arena.]],
+}	
diff --git a/game/modules/tome/data/birth/descriptors.lua b/game/modules/tome/data/birth/descriptors.lua
index 0a0a5674cc47763b44bc5f8fa20c37cf44dfdae7..71422632420bd8c03721dd7e334e644add0942f4 100644
--- a/game/modules/tome/data/birth/descriptors.lua
+++ b/game/modules/tome/data/birth/descriptors.lua
@@ -40,6 +40,7 @@ newBirthDescriptor{
 			Tutorial = "disallow",
 			["Maj'Eyal"] = "allow",
 			Infinite = function() return profile.mod.allow_build.campaign_infinite_dungeon and "allow" or "disallow" end,
+			Arena = function() return profile.mod.allow_build.campaign_arena and "allow" or "disallow" end,
 			Ents = "disallow",
 			Spydre = "disallow",
 			Orcs = "disallow",
diff --git a/game/modules/tome/data/birth/worlds.lua b/game/modules/tome/data/birth/worlds.lua
index e6937caf44bff986b9345aeeb7685ca44654bb65..cb512cd2224e6e3d77c7366ecaef98651b3b5f31 100644
--- a/game/modules/tome/data/birth/worlds.lua
+++ b/game/modules/tome/data/birth/worlds.lua
@@ -53,6 +53,38 @@ newBirthDescriptor{
 	},
 }
 
+local default_eyal_descriptors = {
+	race =
+	{
+		__ALL__ = "disallow",
+		Human = "allow",
+		Elf = "allow",
+		Dwarf = "allow",
+		Halfling = "allow",
+		Undead = function() return profile.mod.allow_build.undead and "allow" or "disallow" end,
+	},
+
+	class =
+	{
+		__ALL__ = "disallow",
+		-- currently psionics consist only of mindslayers
+		Psionic = "allow",
+		Warrior = "allow",
+		Archer = "allow",
+		Rogue = "allow",
+		Mage = "allow",
+		Divine = function() return profile.mod.allow_build.divine and "allow" or "disallow" end,
+		Wilder = function() return (
+			profile.mod.allow_build.wilder_summoner or
+			profile.mod.allow_build.wilder_wyrmic
+			) and "allow" or "disallow"
+		end,
+		Corrupter = function() return profile.mod.allow_build.corrupter and "allow" or "disallow" end,
+		Afflicted = function() return profile.mod.allow_build.afflicted and "allow" or "disallow" end,
+		Chronomancer = function() return profile.mod.allow_build.chronomancer and "allow" or "disallow" end,
+		Psionic = function() return profile.mod.allow_build.psionic and "allow" or "disallow" end,
+	},
+}
 
 -- Player worlds/campaigns
 newBirthDescriptor{
@@ -66,39 +98,7 @@ newBirthDescriptor{
 		"You are an adventurer, setting out to find lost treasure and glory.",
 		"But what lurks in the shadows of the world?",
 	},
-	descriptor_choices =
-	{
-		race =
-		{
-			__ALL__ = "disallow",
-			Human = "allow",
-			Elf = "allow",
-			Dwarf = "allow",
-			Halfling = "allow",
-			Undead = function() return profile.mod.allow_build.undead and "allow" or "disallow" end,
-		},
-
-		class =
-		{
-			__ALL__ = "disallow",
-			-- currently psionics consist only of mindslayers
-			Psionic = "allow",
-			Warrior = "allow",
-			Archer = "allow",
-			Rogue = "allow",
-			Mage = "allow",
-			Divine = function() return profile.mod.allow_build.divine and "allow" or "disallow" end,
-			Wilder = function() return (
-				profile.mod.allow_build.wilder_summoner or
-				profile.mod.allow_build.wilder_wyrmic
-				) and "allow" or "disallow"
-			end,
-			Corrupter = function() return profile.mod.allow_build.corrupter and "allow" or "disallow" end,
-			Afflicted = function() return profile.mod.allow_build.afflicted and "allow" or "disallow" end,
-			Chronomancer = function() return profile.mod.allow_build.chronomancer and "allow" or "disallow" end,
-			Psionic = function() return profile.mod.allow_build.psionic and "allow" or "disallow" end,
-		},
-	},
+	descriptor_choices = default_eyal_descriptors,
 }
 
 newBirthDescriptor{
@@ -110,39 +110,7 @@ newBirthDescriptor{
 		"Play as your favorite race and class and venture into the infinite dungeon.",
 		"The only limit to how far you can go is your own skill!",
 	},
-	descriptor_choices =
-	{
-		race =
-		{
-			__ALL__ = "disallow",
-			Human = "allow",
-			Elf = "allow",
-			Dwarf = "allow",
-			Halfling = "allow",
-			Undead = function() return profile.mod.allow_build.undead and "allow" or "disallow" end,
-		},
-
-		class =
-		{
-			__ALL__ = "disallow",
-			-- currently psionics consist only of mindslayers
-			Psionic = "allow",
-			Warrior = "allow",
-			Archer = "allow",
-			Rogue = "allow",
-			Mage = "allow",
-			Divine = function() return profile.mod.allow_build.divine and "allow" or "disallow" end,
-			Wilder = function() return (
-				profile.mod.allow_build.wilder_summoner or
-				profile.mod.allow_build.wilder_wyrmic
-				) and "allow" or "disallow"
-			end,
-			Corrupter = function() return profile.mod.allow_build.corrupter and "allow" or "disallow" end,
-			Afflicted = function() return profile.mod.allow_build.afflicted and "allow" or "disallow" end,
-			Chronomancer = function() return profile.mod.allow_build.chronomancer and "allow" or "disallow" end,
-			Psionic = function() return profile.mod.allow_build.psionic and "allow" or "disallow" end,
-		},
-	},
+	descriptor_choices = default_eyal_descriptors,
 	copy = {
 		-- Give the orb of knowledge
 		resolvers.inventory{ id=true, {defined="ORB_KNOWLEDGE"}},
@@ -159,6 +127,36 @@ newBirthDescriptor{
 	},
 }
 
+newBirthDescriptor{
+	type = "world",
+	name = "Arena",
+	display_name = "The Arena: Challenge of the Master",
+	desc =
+	{
+		"Play as a lone warrior setting foot in the Arena's challenge!",
+		"You can use any class and race into it.",
+		"Check out how far you can go! Can you become the new Master of the Arena?",
+		"If so, you will battle your own champion next time!",
+	},
+	descriptor_choices = default_eyal_descriptors,
+	copy = {
+		death_dialog = "ArenaFinish",
+
+		-- Give the orb of knowledge
+		resolvers.inventory{ id=true, {defined="ORB_KNOWLEDGE"}},
+		resolvers.generic(function(e) e.hotkey[12] = {"inventory", "Orb of Knowledge"} end),
+
+		-- Override normal stuff
+		before_starting_zone = function(self)
+			self.starting_level = 1
+			self.starting_level_force_down = nil
+			self.starting_zone = "arena"
+			self.starting_quest = "arena"
+			self.starting_intro = "arena"
+		end,
+	},
+}
+
 newBirthDescriptor{
 	type = "world",
 	name = "Orcs",
diff --git a/game/modules/tome/data/chats/arena-start.lua b/game/modules/tome/data/chats/arena-start.lua
new file mode 100644
index 0000000000000000000000000000000000000000..412ef834977251294e3056c2fe5a95f7602773e7
--- /dev/null
+++ b/game/modules/tome/data/chats/arena-start.lua
@@ -0,0 +1,194 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010 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
+
+local give_boots_rush = function(self, player)
+	local o = game.zone:makeEntityByName(game.level, "object", "ARENA_BOOTS_RUSH")
+	if o then
+		o:identify(true)
+		player:addObject(player.INVEN_INVEN, o)
+		game.zone:addEntity(game.level, o, "object")
+		game.level.arena.perk = "Rush"..game.level.arena.modeString
+	end
+end
+
+local give_boots_phas = function(self, player)
+	local o = game.zone:makeEntityByName(game.level, "object", "ARENA_BOOTS_PHAS")
+	if o then
+		o:identify(true)
+		player:addObject(player.INVEN_INVEN, o)
+		game.zone:addEntity(game.level, o, "object")
+		game.level.arena.perk = "Phasing"..game.level.arena.modeString
+	end
+end
+
+local give_boots_dise = function(self, player)
+	local o = game.zone:makeEntityByName(game.level, "object", "ARENA_BOOTS_DISE")
+	if o then
+		o:identify(true)
+		player:addObject(player.INVEN_INVEN, o)
+		game.zone:addEntity(game.level, o, "object")
+		game.level.arena.perk = "Disengage"..game.level.arena.modeString
+	end
+end
+
+local give_boots_lspeed = function(self, player)
+	local o = game.zone:makeEntityByName(game.level, "object", "ARENA_BOOTS_LSPEED")
+	if o then
+		o:identify(true)
+		player:addObject(player.INVEN_INVEN, o)
+		game.zone:addEntity(game.level, o, "object")
+		game.level.arena.perk = "LSpeed"..game.level.arena.modeString
+	end
+end
+
+local give_bow = function(self, player)
+	local o = game.zone:makeEntityByName(game.level, "object", "ARENA_BOW")
+	if o then
+		o:identify(true)
+		player:addObject(player.INVEN_INVEN, o)
+		game.zone:addEntity(game.level, o, "object")
+		game.level.arena.perk = "Bow"..game.level.arena.modeString
+	end
+end
+
+local give_sling = function(self, player)
+	local o = game.zone:makeEntityByName(game.level, "object", "ARENA_SLING")
+	if o then
+		o:identify(true)
+		player:addObject(player.INVEN_INVEN, o)
+		game.zone:addEntity(game.level, o, "object")
+		game.level.arena.perk = "Sling"..game.level.arena.modeString
+	end
+end
+
+local give_healinfu = function(self, player)
+	local o = game.zone:makeEntity(game.level, "object", {name="healing infusion"}, 1, true)
+	if o then
+		o:identify(true)
+		o.inscription_data.heal = 350
+		o.inscription_data.cooldown = o.inscription_data.cooldown + 5
+		player:addObject(player.INVEN_INVEN, o)
+		game.zone:addEntity(game.level, o, "object")
+		game.level.arena.perk = "Heal"..game.level.arena.modeString
+	end
+end
+
+local give_imbue = function(self, player)
+	player:learnTalent(player.T_IMBUE_ITEM, true, 4)
+	player.changed = true
+	game.level.arena.perk = "Imbue"..game.level.arena.modeString
+end
+
+local give_debugarms = function(self, player)
+	local o = game.zone:makeEntityByName(game.level, "object", "ARENA_DEBUG_CANNON")
+	if o then
+		o:identify(true)
+		player:addObject(player.INVEN_INVEN, o)
+		game.zone:addEntity(game.level, o, "object")
+	end
+	o = nil
+	o = game.zone:makeEntityByName(game.level, "object", "ARENA_DEBUG_ARMOR")
+	if o then
+		o:identify(true)
+		player:addObject(player.INVEN_INVEN, o)
+		game.zone:addEntity(game.level, o, "object")
+	end
+	game.level.arena.perk = "Debug"..game.level.arena.modeString
+end
+
+local arena_3 = function(self, player)
+	game.level.arena.eventWave = 2
+	game.level.arena.finalWave = 3
+	game.level.arena.modeString = "3"
+end
+
+local arena_30 = function(self, player)
+	game.level.arena.eventWave = 5
+	game.level.arena.finalWave = 31
+	game.level.arena.modeString = "30"
+end
+
+local arena_60 = function(self, player)
+	game.level.arena.eventWave = 5
+	game.level.arena.finalWave = 61
+	game.level.arena.modeString = "60"
+end
+
+local give_bonus = function(self, player)
+	game.level.arena.bonusMin = 1.1
+	game.level.arena.bonusMultiplier = 1.1
+	game.level.arena.perk = "None"..game.level.arena.modeString
+end
+
+local save_clear = function(self, player)
+	world.arena = nil
+	if not world.arena then
+		local emptyScore = {name = nil, score = 0, perk = nil, wave = 1, sex = nil, race = nil, class = nil}
+		world.arena = {
+			master30 = nil,
+			master60 = nil,
+			lastScore = emptyScore,
+			bestWave = 1,
+			ver = 1
+		}
+		world.arena.scores = {[1] = emptyScore}
+	end
+	local o = game.zone:makeEntityByName(game.level, "object", "ARENA_SCORING")
+	if o then game.zone:addEntity(game.level, o, "object", 7, 3) end
+end
+
+
+newChat{ id="perks",
+	text = [[#LIGHT_GREEN#Preparing for the arena, you brought with you...]],
+	answers = {
+		{"A pair of boots of disengagement...", action=give_boots_dise},
+		{"A pair of boots of rushing...", action=give_boots_rush},
+		{"A pair of boots of phasing...", action=give_boots_phas},
+		--{"#DARK_BLUE#A pair of boots of lightning speed...", action=give_boots_lspeed},
+		{"A healing infusion...", action=give_healinfu},
+		{"A bow of steady shots...", action=give_bow},
+		{"A sling of flare...", action=give_sling},
+		{"The talent to imbue gems...", action=give_imbue},
+		--{"[DEBUG] Debug arms!", action=give_debugarms},
+		{"Nothing!", action=give_bonus},
+	}
+}
+
+newChat{ id="welcome",
+	text = "#LIGHT_GREEN#You take a look at the ranking boards before entering.\n"..text,
+	answers = {
+		--{"Enter the arena for 3 rounds[DEBUG]", action=arena_3, jump="perks"},
+		{"Enter the arena for 30 rounds", action=arena_30, jump="perks"},
+		{"Enter the arena for 60 rounds", action=arena_60, jump="perks"},
+		--{"Enter the arena for as much as you can last", action=arena_inf, jump="perks"},
+		{"#LIGHT_RED#[Reset all arena save data]", action=save_clear, jump="welcome2"},
+	}
+}
+
+newChat{ id="welcome2",
+	text = "What will you do now?",
+	answers = {
+		--{"Enter the arena for 3 rounds[DEBUG]", action=arena_3, jump="perks"},
+		{"Enter the arena for 30 rounds", action=arena_30, jump="perks"},
+		{"Enter the arena for 60 rounds", action=arena_60, jump="perks"},
+		--{"Enter the arena for as much as you can last", action=arena_inf, jump="perks"},
+	}
+}
+
+return "welcome"
diff --git a/game/modules/tome/data/chats/arena-unlock.lua b/game/modules/tome/data/chats/arena-unlock.lua
new file mode 100644
index 0000000000000000000000000000000000000000..9e5bb57f57f4f6326abc669d1a50dc9578d93bfd
--- /dev/null
+++ b/game/modules/tome/data/chats/arena-unlock.lua
@@ -0,0 +1,97 @@
+newChat{ id="welcome",
+	text = [[#LIGHT_GREEN#*A tall, hooded man stares at you*#WHITE#
+I am waiting for a great fighter. Go away.
+#LIGHT_GREEN#*The man ignores you for a few uncomfortable seconds, then asks:*#WHITE#
+What is it? Are you the fighter I am waiting for?
+]],
+	answers = {
+		{"No", jump="no"},
+		{"Yes", jump="yes"},
+	}
+}
+
+newChat{ id="no",
+	text = [[#LIGHT_GREEN#*The man stares back at you*#WHITE#
+That's unfortunate. You look like a fighter.
+#LIGHT_GREEN#*The hooded man draws a smile in his face. You can't tell if it's an arrogant
+#LIGHT_GREEN#smirk, or a sign of satisfaction. Concerned, you draw your hand closer to your
+#LIGHT_GREEN#weapon*#WHITE#
+Heheheh...Indeed, you are.
+I am looking for strong fighters for battling in the arena. A tiny entertainment for the
+masses...but also a good source of good gold, and battles.
+Listen, here is the deal. If you can prove your worth as fighter, I will give you
+an invitation to the arena.
+Fight three combatants, if you win, you get a pass. If you can survive, that is...
+]],
+	answers = {
+		{"Interesting, I am up to the challenge.", jump="yes"},
+		{"I am not interested.", jump="ok"},
+	}
+}
+
+newChat{ id="yes",
+	text = [[#LIGHT_GREEN#*The man shows a devious smile*#WHITE#
+Ah, excellent. A great fighter is always willing to head into battle.
+Heheh...very well then, follow me, @playerdescriptor.race@.
+#LIGHT_GREEN#*The man starts walking away, but suddenly turns to you*#WHITE#
+Just remember, you might lose your life if you are weak...
+But that is not the case, is it? Heheh...
+]],
+	answers = {
+		{"Let's go", jump="go"},
+		{"Wait, I am not ready yet.", jump="ok"},
+	}
+}
+
+newChat{ id="go",
+	text = "#LIGHT_GREEN#*The man quietly walks away, after making you a gesture to follow him*",
+	answers = {
+		{"#LIGHT_GREEN#*You follow the man*",
+		action = function (self, player)
+			self:die()
+			player:grantQuest("arena-unlock")
+			game:changeLevel(1, "arena-unlock")
+			require("engine.ui.Dialog"):simpleLongPopup("Get ready!", "Defeat all three enemies!", 400)
+		end
+		},
+	}
+}
+
+
+newChat{ id="win",
+	text = [[#LIGHT_GREEN#*The cornac rogue comes back from the shadows*#WHITE#
+Hehehe, well done, @playerdescriptor.race@! I knew you had potential.
+#LIGHT_GREEN#*The rogue takes out his hood, showing a fairly young, but unmistakingly
+#LIGHT_GREEN#battle-hardened man. He is smiling widely, but this time you can clearly
+#LIGHT_GREEN#recognize satisfaction in his smile.#WHITE#
+The name's Rej. I work for the arena to recruit great fighters who can give a good
+show...and not die in two blows.
+A promise is a promise. This envelope contains an invitation to the arena, and a map
+with its location.
+When you are done adventuring, I'll like to see you there.
+#LIGHT_GREEN#*As you travel back to Derth in company of the rogue, you both talk about past
+#LIGHT_GREEN#battles and techniques. His experience in combat inspires you greatly. (#WHITE#+2 generic talent points#LIGHT_GREEN#)
+#WHITE#Very well, @playername@. I must go now. I need to meet with some fighters at
+Zigur, not too far from here.
+Come to the arena when you are done with your adventures, will you?.
+]],
+	answers = {
+		{ "I will. Farewell for now.", action = function (self, player)
+			game:changeLevel(1, "town-derth")
+			player.unused_generics = player.unused_generics + 2
+			game:setAllowedBuild("campaign_arena", true)
+			game.player:setQuestStatus("arena-unlock", engine.Quest.COMPLETED)
+			world:gainAchievement("THE_ARENA", game.player)
+		end
+		},
+	}
+}
+
+newChat{ id="ok",
+	text = "#WHITE#I see... come back if you change your mind...",
+	answers = {
+		{ "See you."},
+	}
+}
+
+return "welcome"
diff --git a/game/modules/tome/data/chats/arena.lua b/game/modules/tome/data/chats/arena.lua
new file mode 100644
index 0000000000000000000000000000000000000000..8f46ce8a8b53b15d4a0650f3ccbab1595eaad126
--- /dev/null
+++ b/game/modules/tome/data/chats/arena.lua
@@ -0,0 +1,176 @@
+newChat{ id="ryal-entry",
+text = [[#LIGHT_GREEN#*A gigantic bone giant walks through the main gate.
+#LIGHT_GREEN#Its shape is intricate and sharp, resembling a drake, but with countless
+#LIGHT_GREEN#spikes instead of wings.
+#LIGHT_GREEN#The massive undead stares at you with unusual...intellect.
+#LIGHT_GREEN#You have heard of him. Ryal the Towering, your first obstacle!
+#LIGHT_GREEN#As an eerie blue glow fills where its eyes should be, the undead giant
+#LIGHT_GREEN#roars and multiple bones fly in your general direction!*
+]],
+	answers = {
+		{"Have at you!!"},
+	}
+}
+
+newChat{ id="ryal-defeat",
+text = [[#LIGHT_GREEN#*After taking several hits, the undead giant finally succumbs
+#LIGHT_GREEN#to your attacks*
+#LIGHT_GREEN#Suddenly, Ryal's body starts to regenerate!
+#LIGHT_GREEN#Standing tall again, you can almost feel its emotionless skull staring
+#LIGHT_GREEN#at you with...satisfaction.
+#WHITE#Hehehe...well done, @playerdescriptor.race@.
+#LIGHT_GREEN#*Ryal quietly turns towards the gate and leaves, seemingly unharmed*
+]],
+	answers = {
+		{"It was fun, bone giant!"},
+		{"...what? unharmed?"}
+	}
+}
+
+newChat{ id="fryjia-entry",
+text = [[#LIGHT_GREEN#*The wind chills as a young girl walks calmly through the gate.
+#LIGHT_GREEN#She looks surprisingly young, with extremely pale skin and contrasting
+#LIGHT_GREEN#long black hair. She examines you with eerie calmness*#WHITE#
+I am known as Fryjia the Hailstorm. That's all you need to know, @playerdescriptor.race@. Let us begin.
+#LIGHT_GREEN#*The whole arena starts to get colder as she speaks, and the audience
+#LIGHT_GREEN#starts wearing their finest cloaks*]],
+	answers = {
+		{"Bring it!"},
+	}
+}
+
+newChat{ id="fryjia-defeat",
+text = [[#LIGHT_GREEN#*With your final blow, Fryjia falls, unable to continue*
+#LIGHT_GREEN#*She awkwardly stands up, but doesn't seem critically injured*
+#WHITE# I...I admit defeat.
+#LIGHT_GREEN#*The audience "oooohs" in awe. Fryjia has turned her back to you*
+#WHITE# @playerdescriptor.race@. You are not the person I am looking for...
+#LIGHT_GREEN#*Leaving you wondering what she was talking about, the young girl walks
+#LIGHT_GREEN#towards the gate. As it closes, you realize her eyes are wet with tears.
+]],
+	answers = {
+		{"..."},
+		{"w...what was that about?"}
+	}
+}
+
+newChat{ id="riala-entry",
+text = [[#LIGHT_GREEN#*The gate opens, revealing a mature human woman in crimson robes.
+#LIGHT_GREEN#She looks at you with a wide smile*
+#WHITE# My, my, what a fine @playerdescriptor.race@ you are. What was your name again, @playername@? I am soo delighted to be your rival today.
+#LIGHT_GREEN#*She speaks quietly as if telling a secret* #WHITE#You know, so few get past the little one as of late, it's such a bore.#LIGHT_GREEN#*She giggles*#WHITE#
+So! I am Reala, the Crimson. I came directly from Angolwen. Despite, you know, the whole thing with the Spellblaze, people still enjoys a few magic tricks!
+#LIGHT_GREEN#*She snaps her fingers, and then flames start dancing around her!*#WHITE#
+Fryjia told me about you, the poor thing, so I will not underestimate such a promising aspirant #LIGHT_GREEN#*She smiles warmly* #WHITE#So, let's make haste my dear!
+There is a battle to fight here!]],
+	answers = {
+		{"Let's go!"},
+	}
+}
+
+newChat{ id="riala-defeat",
+text = [[#LIGHT_GREEN#*With the final blow, Reala falls...to suddenly burst in flames!!
+#LIGHT_GREEN#You stare at the blazing inferno with understandable confusion,
+#LIGHT_GREEN#until you hear her voice from behind*#WHITE#
+Oh, my dear! That was quite the fight wasn't it? I concede you the honor of victory.
+#LIGHT_GREEN#*She bows politely*
+Fryjia was right about you, you seem to be a champion on the works!
+Oh, and, please forgive her behavior. You will understand when you meet her father.
+And, if you keep fighting like this, it will be really soon.
+So, it's been my pleasure, @playername@. #LIGHT_GREEN#*She vanishes in a spiral of flame*]],
+	answers = {
+		{"I am pumped up! What's next?"},
+		{"Am I the only person with a name that can die here?"}
+	}
+}
+
+newChat{ id="valfren-entry",
+text = [[#LIGHT_GREEN#*You suddenly realize everything has turned dark.
+#LIGHT_GREEN#You look around searching for your rival. And then you notice it. Standing
+#LIGHT_GREEN#right before you, a massive battle armor with an equally massive battle axe.
+#LIGHT_GREEN#It wasn't there just a second ago. You step back and examine him better,
+#LIGHT_GREEN#realizing it's actually a human inside that hulking, worn armor. You can't see
+#LIGHT_GREEN#his eyes, but you know he's piercing your soul with his stare*
+f...t...ma....ll...
+#LIGHT_GREEN#*You hear a devilish voice, coming from everywhere at once!! But...you are
+#LIGHT_GREEN#unable to understand anything! It doesn't seem like any language used in
+#LIGHT_GREEN#Maj'Eyal!
+#LIGHT_GREEN#And then...a piercing, demonic roar...you are overwhelmed by extreme
+#LIGHT_GREEN#emotions invading your very soul!!*
+]],
+	answers = {
+		{"#LIGHT_GREEN#*You valiantly stand against the darkness*"},
+	}
+}
+
+newChat{ id="valfren-defeat",
+text = [[#LIGHT_GREEN#*You valiantly deliver the finishing blow!*
+#LIGHT_GREEN#*Valfren collapses as the light returns to this world.
+#LIGHT_GREEN#You close your eyes for a brief instant, Fryjia is there when you open them*
+Father... #LIGHT_GREEN#*She stands silent for a few seconds*#WHITE# You win, @playerdescriptor.race@.
+You have done well. Prepare for your final battle...if you win, we will be at your service.
+Good luck...
+#LIGHT_GREEN#*After a few uncomfortable seconds, Valfren starts to move again.
+#LIGHT_GREEN#He stands up and walks away with Fryjia. At the gates, Valfren turns his
+#LIGHT_GREEN#head in your direction. You look at him, and then, he looks above
+#LIGHT_GREEN#the arena's walls. You follow his guide...to meet the Master of the Arena*
+
+#LIGHT_GREEN#*There it is. Your goal. Your heart beats fast, as the time has come*
+#LIGHT_GREEN#*The Master of the Arena smiles proudly*
+#RED#The final battle begins when the gate closes, just this final time!!
+]],
+	answers = {
+		{"I will defeat you, Master of the Arena!!!"},
+		{"I will become Master of the Arena instead of the Master of the Arena!!"},
+		{"Wealth and glory! Wealth and glory!"},
+	}
+}
+
+newChat{ id="master-entry",
+text = [[#LIGHT_GREEN#*Finally, the master of the arena comes into the gates!
+#LIGHT_GREEN#The public roars with excitement as he faces you with confidence!*
+I applaud you, @playerdescriptor.race@! You have fought with might and courage!
+And now...the time for the final showdown!
+#LIGHT_GREEN#*The master assumes a fighting stance. The audience cheers!*
+Like you, I started from nowhere. I won't underestimate someone with such potential.
+#LIGHT_GREEN#*The master smirks, you assume your fighting stance as well, and the
+#LIGHT_GREEN#audience cheers you as well, making the excitement grow inside you*
+Can you hear it, the public cheering? That's what this is about.
+Pursue glory with all your might, @playerdescriptor.race@!!
+#LIGHT_GREEN#*The master steps forward into the sand*
+]],
+	answers = {
+		{"Wealth and glory!!!"},
+	}
+}
+
+newChat{ id="master-defeat",
+text = [[#LIGHT_GREEN#*After a glorious battle, the Master falls!*
+Hah...haha. You did it, @playerdescriptor.race@...
+#LIGHT_GREEN#*The master of the arena, defeated, stands up with a wide smile.
+#LIGHT_GREEN#Feeling the master's approval, you pick up its weapon, now lying
+#LIGHT_GREEN#in the blood-stained sand.*
+Everyone! We got a champion today!!
+#LIGHT_GREEN#*The audience rages and shouts your name repeatedly*
+Congratulations, @playerdescriptor.race@. You are the Master now.
+Now you shall take your rightful place as the champion.
+Just remember...like me, you shall fall one day...
+But meanwhile, this is your place! Welcome to paradise, @playerdescriptor.race@!
+#LIGHT_GREEN#*You see several sponsors and military recruiters approach the
+#LIGHT_GREEN#now defeated master, offering deals and good positions in the army.
+#LIGHT_GREEN#You smile, victorious, knowing your life will be glorious from now on.
+#LIGHT_GREEN#Because even if you are defeated in the future...
+#LIGHT_GREEN#You can always sell your image and live large.
+
+#YELLOW#CONGRATULATIONS!
+#YELLOW#You are the new master of the arena! You are great and epic!
+#YELLOW#You shall remain as the new master until someone challenges you!
+#YELLOW#Next time you play, you shall battle this new champion instead!
+]],
+	answers = {
+		{"WEALTH!! AND!! GLORYYYYY!!"},
+		{"I won't need to save chicks from cults anymore!", cond=function(npc, player) if player.female == true then return false else return true end end },
+		{"I hereby stand victorious, awaiting future challenges!"},
+		{"#LIGHT_GREEN#*dance*"},
+	}
+}
diff --git a/game/modules/tome/data/general/grids/basic.lua b/game/modules/tome/data/general/grids/basic.lua
index 88ea2b887c8f52d0170c654b2f52f46c809b477e..686d629ba081e093a6b7515720bf051798d60e26 100644
--- a/game/modules/tome/data/general/grids/basic.lua
+++ b/game/modules/tome/data/general/grids/basic.lua
@@ -153,17 +153,17 @@ newEntity{
 	dig = "FLOOR",
 }
 for i = 1, 5 do
-	newEntity{ base = "WALL", define_as = "WALL"..i, image = "terrain/granite_wall1_"..i..".png", nice_tiler = false}
-	newEntity{ base = "WALL", define_as = "WALL_NORTH"..i, image = "terrain/granite_wall1_"..i..".png", add_displays = {class.new{image="terrain/granite_wall3.png", z=18, display_y=-1}}, nice_tiler = false}
-	newEntity{ base = "WALL", define_as = "WALL_PILLAR_8"..i, image = "terrain/granite_wall1_"..i..".png", add_displays = {class.new{image="terrain/granite_wall_pillar_8.png", z=18, display_y=-1}}, nice_tiler = false}
+	newEntity{ base = "WALL", define_as = "WALL"..i, image = "terrain/granite_wall1_"..i..".png"}
+	newEntity{ base = "WALL", define_as = "WALL_NORTH"..i, image = "terrain/granite_wall1_"..i..".png", add_displays = {class.new{image="terrain/granite_wall3.png", z=18, display_y=-1}}}
+	newEntity{ base = "WALL", define_as = "WALL_PILLAR_8"..i, image = "terrain/granite_wall1_"..i..".png", add_displays = {class.new{image="terrain/granite_wall_pillar_8.png", z=18, display_y=-1}}}
 end
-newEntity{ base = "WALL", define_as = "WALL_NORTH_SOUTH", image = "terrain/granite_wall2.png", add_displays = {class.new{image="terrain/granite_wall3.png", z=18, display_y=-1}}, nice_tiler = false}
-newEntity{ base = "WALL", define_as = "WALL_SOUTH", image = "terrain/granite_wall2.png", nice_tiler = false}
-for i = 1, 17 do newEntity{ base = "WALL", define_as = "WALL_SOUTH"..i, image = "terrain/granite_wall2_"..i..".png", nice_tiler = false} end
-newEntity{ base = "WALL", define_as = "WALL_SMALL_PILLAR", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_small.png"}, class.new{image="terrain/granite_wall_pillar_small_top.png", z=18, display_y=-1}}, nice_tiler = false}
-newEntity{ base = "WALL", define_as = "WALL_PILLAR_6", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_3.png"}, class.new{image="terrain/granite_wall_pillar_9.png", z=18, display_y=-1}}, nice_tiler = false}
-newEntity{ base = "WALL", define_as = "WALL_PILLAR_4", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_1.png"}, class.new{image="terrain/granite_wall_pillar_7.png", z=18, display_y=-1}}, nice_tiler = false}
-newEntity{ base = "WALL", define_as = "WALL_PILLAR_2", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_2.png"}}, nice_tiler = false}
+newEntity{ base = "WALL", define_as = "WALL_NORTH_SOUTH", image = "terrain/granite_wall2.png", add_displays = {class.new{image="terrain/granite_wall3.png", z=18, display_y=-1}}}
+newEntity{ base = "WALL", define_as = "WALL_SOUTH", image = "terrain/granite_wall2.png"}
+for i = 1, 17 do newEntity{ base = "WALL", define_as = "WALL_SOUTH"..i, image = "terrain/granite_wall2_"..i..".png"} end
+newEntity{ base = "WALL", define_as = "WALL_SMALL_PILLAR", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_small.png"}, class.new{image="terrain/granite_wall_pillar_small_top.png", z=18, display_y=-1}}}
+newEntity{ base = "WALL", define_as = "WALL_PILLAR_6", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_3.png"}, class.new{image="terrain/granite_wall_pillar_9.png", z=18, display_y=-1}}}
+newEntity{ base = "WALL", define_as = "WALL_PILLAR_4", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_1.png"}, class.new{image="terrain/granite_wall_pillar_7.png", z=18, display_y=-1}}}
+newEntity{ base = "WALL", define_as = "WALL_PILLAR_2", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_2.png"}}}
 
 -----------------------------------------
 -- Big Walls
@@ -196,17 +196,17 @@ newEntity{
 	air_level = -20,
 }
 for i = 1, 5 do
-	newEntity{ base = "HARDWALL", define_as = "HARDWALL"..i, image = "terrain/granite_wall1_"..i..".png", nice_tiler = false}
-	newEntity{ base = "HARDWALL", define_as = "HARDWALL_NORTH"..i, image = "terrain/granite_wall1_"..i..".png", add_displays = {class.new{image="terrain/granite_wall3.png", z=18, display_y=-1}}, nice_tiler = false}
-	newEntity{ base = "HARDWALL", define_as = "HARDWALL_PILLAR_8"..i, image = "terrain/granite_wall1_"..i..".png", add_displays = {class.new{image="terrain/granite_wall_pillar_8.png", z=18, display_y=-1}}, nice_tiler = false}
+	newEntity{ base = "HARDWALL", define_as = "HARDWALL"..i, image = "terrain/granite_wall1_"..i..".png"}
+	newEntity{ base = "HARDWALL", define_as = "HARDWALL_NORTH"..i, image = "terrain/granite_wall1_"..i..".png", add_displays = {class.new{image="terrain/granite_wall3.png", z=18, display_y=-1}}}
+	newEntity{ base = "HARDWALL", define_as = "HARDWALL_PILLAR_8"..i, image = "terrain/granite_wall1_"..i..".png", add_displays = {class.new{image="terrain/granite_wall_pillar_8.png", z=18, display_y=-1}}}
 end
-newEntity{ base = "HARDWALL", define_as = "HARDWALL_NORTH_SOUTH", image = "terrain/granite_wall2.png", add_displays = {class.new{image="terrain/granite_wall3.png", z=18, display_y=-1}}, nice_tiler = false}
-newEntity{ base = "HARDWALL", define_as = "HARDWALL_SOUTH", image = "terrain/granite_wall2.png", nice_tiler = false}
-for i = 1, 17 do newEntity{ base = "HARDWALL", define_as = "HARDWALL_SOUTH"..i, image = "terrain/granite_wall2_"..i..".png", nice_tiler = false} end
-newEntity{ base = "HARDWALL", define_as = "HARDWALL_SMALL_PILLAR", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_small.png"}, class.new{image="terrain/granite_wall_pillar_small_top.png", z=18, display_y=-1}}, nice_tiler = false}
-newEntity{ base = "HARDWALL", define_as = "HARDWALL_PILLAR_6", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_3.png"}, class.new{image="terrain/granite_wall_pillar_9.png", z=18, display_y=-1}}, nice_tiler = false}
-newEntity{ base = "HARDWALL", define_as = "HARDWALL_PILLAR_4", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_1.png"}, class.new{image="terrain/granite_wall_pillar_7.png", z=18, display_y=-1}}, nice_tiler = false}
-newEntity{ base = "HARDWALL", define_as = "HARDWALL_PILLAR_2", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_2.png"}}, nice_tiler = false}
+newEntity{ base = "HARDWALL", define_as = "HARDWALL_NORTH_SOUTH", image = "terrain/granite_wall2.png", add_displays = {class.new{image="terrain/granite_wall3.png", z=18, display_y=-1}}}
+newEntity{ base = "HARDWALL", define_as = "HARDWALL_SOUTH", image = "terrain/granite_wall2.png"}
+for i = 1, 17 do newEntity{ base = "HARDWALL", define_as = "HARDWALL_SOUTH"..i, image = "terrain/granite_wall2_"..i..".png"} end
+newEntity{ base = "HARDWALL", define_as = "HARDWALL_SMALL_PILLAR", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_small.png"}, class.new{image="terrain/granite_wall_pillar_small_top.png", z=18, display_y=-1}}}
+newEntity{ base = "HARDWALL", define_as = "HARDWALL_PILLAR_6", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_3.png"}, class.new{image="terrain/granite_wall_pillar_9.png", z=18, display_y=-1}}}
+newEntity{ base = "HARDWALL", define_as = "HARDWALL_PILLAR_4", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_1.png"}, class.new{image="terrain/granite_wall_pillar_7.png", z=18, display_y=-1}}}
+newEntity{ base = "HARDWALL", define_as = "HARDWALL_PILLAR_2", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_2.png"}}}
 
 
 -----------------------------------------
@@ -230,10 +230,10 @@ newEntity{
 	always_remember = true,
 	door_closed = "DOOR",
 }
-newEntity{ base = "DOOR", define_as = "DOOR_HORIZ", image = "terrain/granite_door1.png", add_displays = {class.new{image="terrain/granite_wall3.png", z=18, display_y=-1}}, nice_tiler = false, door_opened = "DOOR_HORIZ_OPEN"}
-newEntity{ base = "DOOR_OPEN", define_as = "DOOR_HORIZ_OPEN", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_door1_open.png", z=17}, class.new{image="terrain/granite_wall3.png", z=18, display_y=-1}}, nice_tiler = false, door_closed = "DOOR_HORIZ"}
-newEntity{ base = "DOOR", define_as = "DOOR_VERT", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_door1_vert.png", z=17}, class.new{image="terrain/granite_door1_vert_north.png", z=18, display_y=-1}}, door_opened = "DOOR_OPEN_VERT", nice_tiler = false, dig = "DOOR_OPEN_VERT"}
-newEntity{ base = "DOOR_OPEN", define_as = "DOOR_OPEN_VERT", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_door1_open_vert.png", z=17}, class.new{image="terrain/granite_door1_open_vert_north.png", z=18, display_y=-1}}, nice_tiler = false, door_closed = "DOOR_VERT"}
+newEntity{ base = "DOOR", define_as = "DOOR_HORIZ", image = "terrain/granite_door1.png", add_displays = {class.new{image="terrain/granite_wall3.png", z=18, display_y=-1}}, door_opened = "DOOR_HORIZ_OPEN"}
+newEntity{ base = "DOOR_OPEN", define_as = "DOOR_HORIZ_OPEN", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_door1_open.png", z=17}, class.new{image="terrain/granite_wall3.png", z=18, display_y=-1}}, door_closed = "DOOR_HORIZ"}
+newEntity{ base = "DOOR", define_as = "DOOR_VERT", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_door1_vert.png", z=17}, class.new{image="terrain/granite_door1_vert_north.png", z=18, display_y=-1}}, door_opened = "DOOR_OPEN_VERT", dig = "DOOR_OPEN_VERT"}
+newEntity{ base = "DOOR_OPEN", define_as = "DOOR_OPEN_VERT", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_door1_open_vert.png", z=17}, class.new{image="terrain/granite_door1_open_vert_north.png", z=18, display_y=-1}}, door_closed = "DOOR_VERT"}
 
 newEntity{
 	define_as = "DOOR_VAULT",
@@ -248,8 +248,8 @@ newEntity{
 	door_player_check = "This door seems to have been sealed off, you think you can open it.",
 	door_opened = "DOOR_OPEN",
 }
-newEntity{ base = "DOOR_VAULT", define_as = "DOOR_VAULT_HORIZ", image = "terrain/granite_door1.png", add_displays = {class.new{image="terrain/granite_wall3.png", z=18, display_y=-1}}, nice_tiler = false, door_opened = "DOOR_HORIZ_OPEN"}
-newEntity{ base = "DOOR_VAULT", define_as = "DOOR_VAULT_VERT", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_door1_vert.png", z=17}, class.new{image="terrain/granite_door1_vert_north.png", z=18, display_y=-1}}, door_opened = "DOOR_OPEN_VERT", nice_tiler = false}
+newEntity{ base = "DOOR_VAULT", define_as = "DOOR_VAULT_HORIZ", image = "terrain/granite_door1.png", add_displays = {class.new{image="terrain/granite_wall3.png", z=18, display_y=-1}}, door_opened = "DOOR_HORIZ_OPEN"}
+newEntity{ base = "DOOR_VAULT", define_as = "DOOR_VAULT_VERT", image = "terrain/marble_floor.png", add_displays = {class.new{image="terrain/granite_door1_vert.png", z=17}, class.new{image="terrain/granite_door1_vert_north.png", z=18, display_y=-1}}, door_opened = "DOOR_OPEN_VERT"}
 
 -----------------------------------------
 -- Old walls
@@ -260,7 +260,7 @@ newEntity{
 	display = '.', color_r=255, color_g=255, color_b=255, back_color=colors.DARK_GREY,
 --	nice_tiler = { method="replace", base={"OLD_FLOOR", 100, 1, 4}},
 }
---for i = 1, 4 do newEntity{ base = "OLD_FLOOR", define_as = "OLD_FLOOR"..i, image = "terrain/oldstone_floor"..(i > 1 and "_"..i or "")..".png", nice_tiler = false} end
+--for i = 1, 4 do newEntity{ base = "OLD_FLOOR", define_as = "OLD_FLOOR"..i, image = "terrain/oldstone_floor"..(i > 1 and "_"..i or "")..".png"} end
 
 newEntity{
 	define_as = "OLD_WALL",
@@ -273,15 +273,15 @@ newEntity{
 	air_level = -20,
 }
 for i = 1, 5 do
-	newEntity{ base = "OLD_WALL", define_as = "OLD_WALL"..i, image = "terrain/granite_wall1_"..i..".png", nice_tiler = false}
-	newEntity{ base = "OLD_WALL", define_as = "OLD_WALL_NORTH"..i, image = "terrain/granite_wall1_"..i..".png", add_displays = {class.new{image="terrain/granite_wall3.png", z=18, display_y=-1}}, nice_tiler = false}
-	newEntity{ base = "OLD_WALL", define_as = "OLD_WALL_PILLAR_8"..i, image = "terrain/granite_wall1_"..i..".png", add_displays = {class.new{image="terrain/granite_wall_pillar_8.png", z=18, display_y=-1}}, nice_tiler = false}
+	newEntity{ base = "OLD_WALL", define_as = "OLD_WALL"..i, image = "terrain/granite_wall1_"..i..".png"}
+	newEntity{ base = "OLD_WALL", define_as = "OLD_WALL_NORTH"..i, image = "terrain/granite_wall1_"..i..".png", add_displays = {class.new{image="terrain/granite_wall3.png", z=18, display_y=-1}}}
+	newEntity{ base = "OLD_WALL", define_as = "OLD_WALL_PILLAR_8"..i, image = "terrain/granite_wall1_"..i..".png", add_displays = {class.new{image="terrain/granite_wall_pillar_8.png", z=18, display_y=-1}}}
 end
-newEntity{ base = "OLD_WALL", define_as = "OLD_WALL_NORTH_SOUTH", image = "terrain/granite_wall2.png", add_displays = {class.new{image="terrain/granite_wall3.png", z=18, display_y=-1}}, nice_tiler = false}
-for i = 1, 3 do newEntity{ base = "OLD_WALL", define_as = "OLD_WALL_NORTH_SOUTH"..i, image = "terrain/granite_wall_lichen_"..i..".png", add_displays = {class.new{image="terrain/granite_wall3.png", z=18, display_y=-1}}, nice_tiler = false} end
-newEntity{ base = "OLD_WALL", define_as = "OLD_WALL_SOUTH", image = "terrain/granite_wall2.png", nice_tiler = false}
-for i = 1, 3 do newEntity{ base = "OLD_WALL", define_as = "OLD_WALL_SOUTH"..i, image = "terrain/granite_wall_lichen_"..i..".png", nice_tiler = false} end
-newEntity{ base = "OLD_WALL", define_as = "OLD_WALL_SMALL_PILLAR", image = "terrain/oldstone_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_small.png"}, class.new{image="terrain/granite_wall_pillar_small_top.png", z=18, display_y=-1}}, nice_tiler = false}
-newEntity{ base = "OLD_WALL", define_as = "OLD_WALL_PILLAR_6", image = "terrain/oldstone_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_3.png"}, class.new{image="terrain/granite_wall_pillar_9.png", z=18, display_y=-1}}, nice_tiler = false}
-newEntity{ base = "OLD_WALL", define_as = "OLD_WALL_PILLAR_4", image = "terrain/oldstone_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_1.png"}, class.new{image="terrain/granite_wall_pillar_7.png", z=18, display_y=-1}}, nice_tiler = false}
-newEntity{ base = "OLD_WALL", define_as = "OLD_WALL_PILLAR_2", image = "terrain/oldstone_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_2.png"}}, nice_tiler = false}
+newEntity{ base = "OLD_WALL", define_as = "OLD_WALL_NORTH_SOUTH", image = "terrain/granite_wall2.png", add_displays = {class.new{image="terrain/granite_wall3.png", z=18, display_y=-1}}}
+for i = 1, 3 do newEntity{ base = "OLD_WALL", define_as = "OLD_WALL_NORTH_SOUTH"..i, image = "terrain/granite_wall_lichen_"..i..".png", add_displays = {class.new{image="terrain/granite_wall3.png", z=18, display_y=-1}}} end
+newEntity{ base = "OLD_WALL", define_as = "OLD_WALL_SOUTH", image = "terrain/granite_wall2.png"}
+for i = 1, 3 do newEntity{ base = "OLD_WALL", define_as = "OLD_WALL_SOUTH"..i, image = "terrain/granite_wall_lichen_"..i..".png"} end
+newEntity{ base = "OLD_WALL", define_as = "OLD_WALL_SMALL_PILLAR", image = "terrain/oldstone_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_small.png"}, class.new{image="terrain/granite_wall_pillar_small_top.png", z=18, display_y=-1}}}
+newEntity{ base = "OLD_WALL", define_as = "OLD_WALL_PILLAR_6", image = "terrain/oldstone_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_3.png"}, class.new{image="terrain/granite_wall_pillar_9.png", z=18, display_y=-1}}}
+newEntity{ base = "OLD_WALL", define_as = "OLD_WALL_PILLAR_4", image = "terrain/oldstone_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_1.png"}, class.new{image="terrain/granite_wall_pillar_7.png", z=18, display_y=-1}}}
+newEntity{ base = "OLD_WALL", define_as = "OLD_WALL_PILLAR_2", image = "terrain/oldstone_floor.png", add_displays = {class.new{image="terrain/granite_wall_pillar_2.png"}}}
diff --git a/game/modules/tome/data/general/npcs/crystal.lua b/game/modules/tome/data/general/npcs/crystal.lua
new file mode 100644
index 0000000000000000000000000000000000000000..513b4fe69b3017ae9ab8c860239e39ba82fc13f0
--- /dev/null
+++ b/game/modules/tome/data/general/npcs/crystal.lua
@@ -0,0 +1,116 @@
+local Talents = require("engine.interface.ActorTalents")
+
+newEntity{
+	define_as = "BASE_NPC_CRYSTAL",
+	type = "immovable", subtype = "crystal",
+	display = "%", color=colors.WHITE,
+	desc = "A shining crystal formation charged with magical energies.",
+	body = { INVEN = 10 },
+	autolevel = "caster",
+	ai = "dumb_talented_simple", ai_state = { talent_in=1, },
+	resolvers.drops{chance=25, nb=1, {type="jewelry", ego_chance = 100}},
+	max_life = resolvers.rngavg(12,34),
+	stats = { str=1, dex=5, mag=20, con=1 },
+	energy = { mod=0.5 },
+	infravision = 20,
+	combat_armor = 10, combat_def = 1,
+	never_move = 1,
+	blind_immune = 1,
+	fear_immune = 1,
+	rank = 2,
+	size_category = 2,
+	poison_immune = 1,
+	disease_immune = 1,
+	no_breath = 1,
+	confusion_immune = 1,
+	disease_immune = 1,
+	poison_immune = 1,
+	see_invisible = 25,
+	resolvers.talents{
+		[Talents.T_PHASE_DOOR]=1,
+	}
+}
+
+
+newEntity{ base = "BASE_NPC_CRYSTAL",
+	name = "red crystal", color=colors.RED,
+	desc = "A formation of red crystal. It emits bright red, scorching light.",
+	level_range = {1, nil}, exp_worth = 1,
+	rarity = 1,
+	resists = { [DamageType.FIRE] = 100, [DamageType.ICE] = -100 },
+	resolvers.talents{
+		[Talents.T_FLAME]=1,
+	}
+}
+
+newEntity{ base = "BASE_NPC_CRYSTAL",
+	name = "white crystal", color=colors.WHITE,
+	desc = "A formation of white crystal. It emits bright white, chilling light.",
+	level_range = {1, nil}, exp_worth = 1,
+	rarity = 1,
+	resists = { [DamageType.ICE] = 100, [DamageType.FIRE] = -100 },
+	resolvers.talents{
+		[Talents.T_ICE_SHARDS]=1,
+	}
+}
+
+newEntity{ base = "BASE_NPC_CRYSTAL",
+	name = "black crystal", color=colors.BLACK,
+	desc = "A formation of black crystal. It absorbs all light around it.",
+	level_range = {1, nil}, exp_worth = 1,
+	rarity = 2,
+	resists = { [DamageType.LIGHT] = 100 ,[DamageType.DARKNESS] = -100 },
+	resolvers.talents{
+		[Talents.T_SOUL_ROT]=1,
+	}
+}
+
+newEntity{ base = "BASE_NPC_CRYSTAL",
+	name = "crimson crystal", color=colors.DARK_RED,
+	desc = "A formation of crimson crystal. It emits a crimson light reminiscent of blood.",
+	level_range = {1, nil}, exp_worth = 1,
+	rarity = 3,
+	resists = { [DamageType.LIGHT] = -100 },
+	resolvers.talents{
+		[Talents.T_BLOOD_GRASP]=1,
+	}
+}
+
+newEntity{ base = "BASE_NPC_CRYSTAL",
+	name = "blue crystal", color=colors.BLUE,
+	desc = "A formation of blue crystal. Its light shines like the ocean's waves.",
+	level_range = {1, nil}, exp_worth = 1,
+	rarity = 4,
+	resists = { [DamageType.ICE] = -100 },
+	resolvers.talents{
+		[Talents.T_WATER_BOLT]=3,
+	}
+}
+
+newEntity{ base = "BASE_NPC_CRYSTAL",
+	name = "multi-hued crystal", color=colors.VIOLET,
+	shader = "quad_hue",
+	desc = "A formation of multi-hued crystal. It shines with all the colors of the rainbow.",
+	level_range = {1, nil}, exp_worth = 1,
+	rarity = 4,
+	resists = { [DamageType.LIGHT] = 100 },
+	resolvers.talents{
+		[Talents.T_ELEMENTAL_BOLT]=1,
+	},
+	talent_cd_reduction={
+		[Talents.T_ELEMENTAL_BOLT]=2,
+	}
+}
+
+newEntity{ base = "BASE_NPC_CRYSTAL",
+	name = "shimmering crystal", color=colors.GREEN,
+	shader = "quad_hue",
+	desc = "A formation of shimmering crystal. Orbs of light circle around it.",
+	level_range = {1, nil}, exp_worth = 1,
+	rarity = 5,
+	resists = { [DamageType.LIGHT] = 100 },
+	summon = {{name = "wisp", number=3, hasxp=false}},
+	resolvers.talents{
+		[Talents.T_SUMMON]=1,
+	}
+}
diff --git a/game/modules/tome/data/gfx/particles/arena_gate.lua b/game/modules/tome/data/gfx/particles/arena_gate.lua
new file mode 100644
index 0000000000000000000000000000000000000000..828bb0b6b0cbea6ed6b066b4d9a1671b854fb92c
--- /dev/null
+++ b/game/modules/tome/data/gfx/particles/arena_gate.lua
@@ -0,0 +1,21 @@
+base_size = 32
+
+return {
+	base = 2000,
+
+	angle = { 0, 360 }, anglev = { 4000, 5000 }, anglea = { 20, 60 },
+
+	life = { 20, 30 },
+	size = { 7, 8 }, sizev = {0, 0}, sizea = {0, 0},
+
+	r = {240, 255}, rv = {0, 10}, ra = {0, 0},
+	g = {200, 214}, gv = {0, 0}, ga = {0, 0},
+	b = {150, 163}, bv = {0, 10}, ba = {0, 0},
+	a = {25, 120}, av = {0, 0}, aa = {0, 0},
+
+}, function(self)
+	self.nb = (self.nb or 0) + 1
+	if self.nb < 3 then
+		self.ps:emit(20)
+	end
+end
\ No newline at end of file
diff --git a/game/modules/tome/data/lore/arena.lua b/game/modules/tome/data/lore/arena.lua
new file mode 100644
index 0000000000000000000000000000000000000000..1962aac0adb8a1f643d46ba9a1fdec00c2902e7d
--- /dev/null
+++ b/game/modules/tome/data/lore/arena.lua
@@ -0,0 +1,22 @@
+newLore{
+	id = "arena-scoring",
+	category = "arena",
+	name = "Arena for dummies",
+	lore = [[#{italic}#You find a note with some highlighted words...
+#{bold}#SCORING IN THE ARENA
+
+#{normal}#The rules of the arena are simple.
+Every wave, the gates will open, releasing enemies. When the gates close, you will be given a bonus score.
+The bonus will #YELLOW#decrease every turn #WHITE#, but #YELLOW#enemies you kill at this point#WHITE#, will
+raise your bonus. When you defeat all enemies, you will be granted your bonus score, multiplied by
+your bonus multiplier.
+
+Every few rounds, a miniboss round will come. After two miniboss rounds, one out of four bosses will appear.
+#YELLOW#Kill enemies before the gates close #WHITE#to raise your score multiplier!.
+#YELLOW#Kill several enemies at once or very strong enemies #WHITE#to please the audience and increase your rank!.
+#YELLOW#Collect gold #WHITE#to increase your score and resources at the end of each round.
+#YELLOW#Kill enemies fast to get better scores!
+#YELLOW#Take advantage of the trap at the center of the arena!
+Good luck!
+]],
+}
\ No newline at end of file
diff --git a/game/modules/tome/data/lore/lore.lua b/game/modules/tome/data/lore/lore.lua
index 926e5a5a1e200c6f9fafdd22159d71a1bfe75f36..fa65d7442799c530fc5c97da6a06c3b3dcbaabfd 100644
--- a/game/modules/tome/data/lore/lore.lua
+++ b/game/modules/tome/data/lore/lore.lua
@@ -33,3 +33,4 @@ load("/data/lore/spellblaze.lua")
 load("/data/lore/orc-prides.lua")
 load("/data/lore/age-allure.lua")
 load("/data/lore/misc.lua")
+load("/data/lore/arena.lua")
diff --git a/game/modules/tome/data/maps/towns/derth.lua b/game/modules/tome/data/maps/towns/derth.lua
index 23fc4a21f201ce35df69ed460aee1df976a4374a..bffabdcf1d7e419644c4b332445a6899d3316878 100644
--- a/game/modules/tome/data/maps/towns/derth.lua
+++ b/game/modules/tome/data/maps/towns/derth.lua
@@ -49,6 +49,21 @@ quickEntity('c', {show_tooltip=true, name="Closed store", display='*', color=col
 quickEntity('d', {show_tooltip=true, name="Closed store", display='*', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"})
 quickEntity('e', {show_tooltip=true, name="Closed store", display='*', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"})
 
+defineTile('r', "GRASS", nil, mod.class.NPC.new{
+	type = "humanoid", subtype = "human",
+	display = "p",
+	faction = "allied-kingdoms",
+	name = "Shady cornac man", color=colors.DARK_BLUE, unique = true,
+	instakill_immune = 1,
+	teleport_immune = 1,
+	move_others = true,
+	open_door = true,
+	size_category = 3, rank = 2,
+	ai = "simple",
+	can_talk = "arena-unlock",
+	can_quest = true,
+})
+
 startx = 76
 starty = 36
 
@@ -60,7 +75,7 @@ return {
 [[                   ,,----TTTTTT--------------TTTTTTTTTT-----,,,,,            ]],
 [[                 ,,---TTTT..................----------TTTTT------,,          ]],
 [[                ,---TTT....--ssssssss-..---..........-----TTTTTT---,,,       ]],
-[[               ,--TTT...-----SSSSSSSS--.----------,,.....------TTT----,,     ]],
+[[               ,--TTT...----rSSSSSSSS--.----------,,.....------TTT----,,     ]],
 [[             ,,--TT...-,,,,--ssssssss-..-sssssssssss,---......---TTTT--T,,   ]],
 [[           ,,---TT..-------,,##9#####-.--sssssssssss-,-------...----TT--TT,  ]],
 [[          ,---  T..--sssSsss,,,,------.--StSStSSSStS--,------.-....--TT--TT,^]],
diff --git a/game/modules/tome/data/maps/zones/arena-unlock.lua b/game/modules/tome/data/maps/zones/arena-unlock.lua
new file mode 100644
index 0000000000000000000000000000000000000000..9d7faa6676e2ac4a56cd939bb1c49b6ea21023b0
--- /dev/null
+++ b/game/modules/tome/data/maps/zones/arena-unlock.lua
@@ -0,0 +1,47 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010 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
+
+defineTile("#", "WALL")
+defineTile("+", "LOCK")
+quickEntity(':', {name='grass', display='.', color=colors.LIGHT_GREEN, image="terrain/grass.png"})
+defineTile(".", "SAND")
+defineTile("-", "FLOOR")
+quickEntity('T', {name='tree', display='#', color=colors.LIGHT_GREEN, block_move=true, block_sight=true, image="terrain/grass.png", add_displays = {mod.class.Grid.new{image="terrain/tree_alpha1.png"}}})
+
+startx = 8
+starty = 12
+
+-- ASCII map section
+return [[
+:.:::T:::.::::T:T
+:#######+#######:
+:#...#.....#...#:
+:#.............#.
+:#....#...#....#:
+.##...........##T
+:#.............#:
+T#...#.....#...#:
+.#.............#:
+:##...........##:
+:#....#...#....#:
+:#.............#.
+:#...#..:..#...#:
+:#######+#######:
+:::TT:T:::T:.::.:
+]]
diff --git a/game/modules/tome/data/maps/zones/arena.lua b/game/modules/tome/data/maps/zones/arena.lua
new file mode 100644
index 0000000000000000000000000000000000000000..ff2ac3c5dd9ec12ae25f4851b05c3e0a1ffea58e
--- /dev/null
+++ b/game/modules/tome/data/maps/zones/arena.lua
@@ -0,0 +1,45 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010 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
+
+defineTile("#", "WALL")
+defineTile("+", "LOCK")
+defineTile("1", "WALL_SEE")
+defineTile(".", "SAND")
+defineTile("-", "FLOOR")
+
+startx = 7
+starty = 1
+
+-- ASCII map section
+return [[
++######-######+
+#--.1.---.1.--#
+#-...........-#
+#....1...1....#
+#1...........1#
+#.............#
+#.............#
+#...1..-..1...#
+#.............#
+#.............#
+#1...........1#
+#....1...1....#
+#-...........-#
+#--.1.....1.--#
++#############+]]
diff --git a/game/modules/tome/data/quests/arena-unlock.lua b/game/modules/tome/data/quests/arena-unlock.lua
new file mode 100644
index 0000000000000000000000000000000000000000..d59e8ced0c71484b372312862c6f55d6c9f0a0d7
--- /dev/null
+++ b/game/modules/tome/data/quests/arena-unlock.lua
@@ -0,0 +1,9 @@
+name = "The agent of the arena"
+desc = function(self, who)
+	local desc = {}
+	desc[#desc+1] = "You were asked to prove your worth as a fighter by a rogue, in order to participate in the arena"
+	if self:isCompleted() then
+		desc[#desc+1] = "You succesfully defeated your adversaries and gained access to the arena!"
+	end
+	return table.concat(desc, "\n")
+end
diff --git a/game/modules/tome/data/quests/arena.lua b/game/modules/tome/data/quests/arena.lua
new file mode 100644
index 0000000000000000000000000000000000000000..c987f169aebf57e8f6e55a9f92cd786a42ef8358
--- /dev/null
+++ b/game/modules/tome/data/quests/arena.lua
@@ -0,0 +1,26 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010 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
+
+name = "The Arena"
+desc = function(self, who)
+	local desc = {}
+	desc[#desc+1] = "Seeking wealth, glory, and a great fight, you challenge the Arena!"
+	desc[#desc+1] = "Can you defeat your foes and become Master of Arena?"
+	return table.concat(desc, "\n")
+end
diff --git a/game/modules/tome/data/talents/misc/npcs.lua b/game/modules/tome/data/talents/misc/npcs.lua
index 66991b8fdf86578b8774351c653e960d1dc1e050..271b2872be334da6e64423f656f2d806388b75b5 100644
--- a/game/modules/tome/data/talents/misc/npcs.lua
+++ b/game/modules/tome/data/talents/misc/npcs.lua
@@ -968,3 +968,61 @@ newTalent{
 		return ([[Invoke your tentacles on your victim.]])
 	end,
 }
+
+newTalent{
+	short_name = "EXPLODE",
+	name = "Explode",
+	type = {"technique/other", 1},
+	points = 5,
+	message = "@Source@ explodes against @target@.",
+	cooldown = 1,
+	range = 1,
+	requires_target = true,
+	action = function(self, t)
+		local tg = {type="bolt", range=1}
+		local x, y, target = self:getTarget(tg)
+		if math.floor(core.fov.distance(self.x, self.y, x, y)) > 1 then return nil end
+		self:project(tg, x, y, DamageType.LIGHT, math.floor(self:combatSpellpower(0.25) * self:getTalentLevel(t)), {type="light"})
+		self:die(self)
+		game:playSoundNear(self, "talents/arcane")
+		return true
+	end,
+	info = function(self, t)
+		return ([[Explodes in a blinding light.]])
+	end,
+}
+
+newTalent{
+	short_name = "ELEMENTAL_BOLT",
+	name = "Elemental bolt",
+	type = {"spell/other", 1},
+	points = 5,
+	mana = 10,
+	message = "@Source@ casts Elemental Bolt!",
+	cooldown = 3,
+	range = 20,
+	proj_speed = 2,
+	requires_target = true,
+	action = function(self, t)
+		local tg = {type = "bolt", range = 20, talent = t}
+		local x, y = self:getTarget(tg)
+		if not x or not y then return nil end
+		local elem = rng.table{
+			{DamageType.FIRE, "flame", "bolt_fire"},
+			{DamageType.COLD, "freeze", "bolt_ice"},
+			{DamageType.LIGHTNING, "lightning_explosion", "bolt_lightning"},
+			{DamageType.ACID, "acid", "bolt_acid"},
+			{DamageType.NATURE, "slime", "bolt_slime"},
+			{DamageType.BLIGHT, "blood", "bolt_blood"},
+			{DamageType.LIGHT, "light", "bolt_light"},
+			{DamageType.ARCANE, "manathrust", "bolt_arcane"},
+		}
+		tg.display={particle=elem[3]}
+		self:projectile(tg, x, y, elem[1], math.floor(self:getMag(100) * self:getTalentLevel(t)), {type=elem[2]})
+		game:playSoundNear(self, "talents/arcane")
+		return true
+	end,
+	info = function(self, t)
+		return ([[Fire a slow bolt of a random element. Damage raises with magic stat.]])
+	end,
+}
diff --git a/game/modules/tome/data/texts/intro-arena.lua b/game/modules/tome/data/texts/intro-arena.lua
new file mode 100644
index 0000000000000000000000000000000000000000..fba18bb2188ca1ff889855104f2f9ab10607cc53
--- /dev/null
+++ b/game/modules/tome/data/texts/intro-arena.lua
@@ -0,0 +1,28 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010 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 [[Welcome #LIGHT_GREEN#@name@#WHITE#.
+As you walk forward, you hear the increasingly loud cheers coming from outside.
+As you step into the arena, the scorching sun blinds your eyes temporarily.
+You look up, and meet your target eye to eye. The Master of the Arena, carefully examining
+the newcomer. He smirks, and starts looking at the other fighters with interest.
+Whoever defeats the Master of Arena will achieve utmost glory. 
+Determined to win, you draw your weapons and advance defiantly. 
+The public roars in anticipation....
+]]
diff --git a/game/modules/tome/data/texts/unlock-campaign_arena.lua b/game/modules/tome/data/texts/unlock-campaign_arena.lua
new file mode 100644
index 0000000000000000000000000000000000000000..4e298587ab4ff170f4c309b6b88b1a597d02a29d
--- /dev/null
+++ b/game/modules/tome/data/texts/unlock-campaign_arena.lua
@@ -0,0 +1,34 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010 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 "New game campaign: #LIGHT_GREEN#The Arena: Challenge of the Master",
+[[
+The arena, a way of violent entertainment. 
+A delight for the audience, a source of wealth and glory. A place where aspiring fighters, former adventurers and those cursed to fight
+eternally gather to hack away at each other.
+
+You have unlocked the Arena and can now create new characters in a new campaign: #LIGHT_GREEN#The Arena#WHITE#.
+
+The arena pits you against multiple enemies in an open field, making your battle tactics important for survival.
+Campaign features:#YELLOW#
+- No quests, plots, friendly creatures or ways out: only you against all odds.
+- Exclusive scoring system where the faster you kill, the more you earn. Scores are kept for bragging rights!
+- Pure hack and slash MAYHEM!
+- Your champion becomes the new master of the arena, allowing you to challenge your own champions!
+]]
diff --git a/game/modules/tome/data/zones/arena-unlock/grids.lua b/game/modules/tome/data/zones/arena-unlock/grids.lua
new file mode 100644
index 0000000000000000000000000000000000000000..915aa9b4b1246f6b72c4d3e0d9735938d5a8b920
--- /dev/null
+++ b/game/modules/tome/data/zones/arena-unlock/grids.lua
@@ -0,0 +1,43 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010 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
+
+load("/data/general/grids/basic.lua")
+load("/data/general/grids/sand.lua")
+
+newEntity{
+	define_as = "WALL_SEE",
+	name = "wall", image = "terrain/granite_wall1.png",
+	display = '#', color_r=255, color_g=255, color_b=255, back_color=colors.GREY,
+	always_remember = true,
+	does_block_move = true,
+	can_pass = {pass_wall=1},
+	block_sight = false,
+	air_level = -20,
+	dig = "FLOOR",
+}
+
+newEntity{
+	define_as = "LOCK",
+	name = "closed gate", image = "terrain/sealed_door.png",
+	display = '+', color=colors.WHITE, back_color=colors.DARK_UMBER,
+	notice = true,
+	always_remember = true,
+	block_sight = true,
+	does_block_move = true,
+}
diff --git a/game/modules/tome/data/zones/arena-unlock/npcs.lua b/game/modules/tome/data/zones/arena-unlock/npcs.lua
new file mode 100644
index 0000000000000000000000000000000000000000..1491af412bc10cc35a4c6ddc784eae2b845243ae
--- /dev/null
+++ b/game/modules/tome/data/zones/arena-unlock/npcs.lua
@@ -0,0 +1,162 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010 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
+
+local Talents = require("engine.interface.ActorTalents")
+
+newEntity{ name = "gladiator",
+	define_as = "GLADIATOR",
+	type = "humanoid", subtype = "human",
+	color=colors.GOLD, display = "p",
+
+	combat = { dam=resolvers.rngavg(5,12), atk=2, apr=6, physspeed=2 },
+	body = { INVEN = 10, MAINHAND=1, OFFHAND=1, BODY=1, QUIVER=1 },
+	resolvers.drops{chance=25, nb=1, {} },
+	resolvers.drops{chance=100, nb=1, {type="money"} },
+
+	life_rating = 15,
+	rank = 3,
+	infravision = 10,
+	lite = 2,
+	open_door = true,
+	autolevel = "warrior",
+	ai = "dumb_talented_simple", ai_state = { ai_move = "move_dmap", talent_in = 1 },
+	energy = { mod = 1 },
+
+	stats = { str=15, dex=15, mag=1, con=15 },
+	desc = [[A menacing man in heavy armor, wielding a mace. He looks battle-hardened.]],
+	level_range = {5, 19}, exp_worth = 2,
+	rarity = false,
+	max_life = resolvers.rngavg(100,125),
+	resolvers.equip{
+		{type="weapon", subtype="mace", autoreq=true},
+		{type="armor", subtype="shield", autoreq=true},
+		{type="armor", subtype="heavy", autoreq=true},
+		{type="armor", subtype="feet", autoreq=true},
+	},
+	resolvers.talents{
+		[Talents.T_SHIELD_PUMMEL]=2,
+		[Talents.T_RUSH]=3,
+		[Talents.T_REPULSION]=2,
+		[Talents.T_HEAVY_ARMOUR_TRAINING] = 1,
+		[Talents.T_WEAPON_COMBAT] = 1,
+	},
+	on_die = function (self)
+		local m = game.zone:makeEntityByName(game.level, "actor", "SLINGER")
+		if m then
+			game.zone:addEntity(game.level, m, "actor", 8, 2)
+		end
+	end
+}
+
+newEntity{ name = "slinger",
+	define_as = "SLINGER",
+	type = "humanoid", subtype = "halfling",
+	color=colors.GOLD, display = "p",
+
+	combat = { dam=resolvers.rngavg(5,12), atk=2, apr=6, physspeed=2 },
+	body = { INVEN = 10, MAINHAND=1, OFFHAND=1, BODY=1, QUIVER=1 },
+	resolvers.drops{chance=25, nb=1, {} },
+	resolvers.drops{chance=100, nb=1, {type="money"} },
+
+	life_rating = 8,
+	rank = 3,
+	infravision = 10,
+	lite = 2,
+	open_door = true,
+	autolevel = "slinger",
+	ai = "dumb_talented_simple", ai_state = { ai_move = "move_dmap", talent_in = 1 },
+	energy = { mod = 1 },
+
+	stats = { str=10, dex=15, cun=15, con=8 },
+	desc = [[A halfling slinger. He seems adept at combat.]],
+	level_range = {6, 20}, exp_worth = 1,
+	rarity = false,
+	max_life = resolvers.rngavg(100,110),
+	resolvers.equip{
+		{type="weapon", subtype="sling", autoreq=true},
+		{type="ammo", subtype="shot", autoreq=true},
+		{type="ammo", subtype="shot"},
+		{type="armor", subtype="shield", autoreq=true},
+	},
+	resolvers.talents{
+		[Talents.T_SHOOT]=1,
+		[Talents.T_DISENGAGE]=2,
+		[Talents.T_RAPID_SHOT]=3,
+		[Talents.T_INERTIAL_SHOT]=2,
+		[Talents.T_HEAVE]=3,
+		[Talents.T_WEAPON_COMBAT] = 2,
+	},
+	on_added = function (self)
+		game.level.map:particleEmitter(self.x, self.y, 1, "teleport")
+		game:playSoundNear(game.player, "talents/teleport")
+	end,
+	on_die = function (self)
+		local m = game.zone:makeEntityByName(game.level, "actor", "ARCANEBLADE")
+		if m then
+			game.zone:addEntity(game.level, m, "actor", 8, 2)
+		end
+	end
+}
+
+newEntity{ name = "arcane blade",
+	define_as = "ARCANEBLADE",
+	type = "humanoid", subtype = "human",
+	color=colors.GOLD, display = "p",
+
+	combat = { dam=resolvers.rngavg(6,12), atk=3, apr=6, physspeed=2 },
+	body = { INVEN = 10, MAINHAND=1, OFFHAND=1, BODY=1, QUIVER=1 },
+	resolvers.drops{chance=100, nb=1, {type="weapon", ego_chance=100}},
+	resolvers.drops{chance=100, nb=2, {type="money"} },
+
+	life_rating = 15,
+	rank = 3,
+	infravision = 10,
+	lite = 2,
+	open_door = true,
+	autolevel = "warrior",
+	ai = "dumb_talented_simple", ai_state = { ai_move = "move_dmap", talent_in = 1 },
+	energy = { mod = 1 },
+
+	stats = { str=20, dex=20, mag=8, con=16 },
+	desc = [[A human Arcane Blade. His body shows multiple scars from battle.]],
+	level_range = {6, 21}, exp_worth = 2,
+	rarity = false,
+	max_life = resolvers.rngavg(100,130),
+	resolvers.equip{
+		{type="weapon", subtype="greatsword", autoreq=true},
+		{type="armor", subtype="heavy", autoreq=true},
+		{type="armor", subtype="feet", autoreq=true},
+	},
+	resolvers.talents{
+		[Talents.T_ARCANE_COMBAT]=2,
+		[Talents.T_ARCANE_FEED]=2,
+		[Talents.T_FLAME]=1,
+		[Talents.T_HEAVY_ARMOUR_TRAINING] = 2,
+		[Talents.T_WEAPON_COMBAT] = 2,
+	},
+	on_added = function (self)
+		game.level.map:particleEmitter(self.x, self.y, 1, "teleport")
+		game:playSoundNear(game.player, "talents/teleport")
+	end,
+	on_die = function (self)
+		local Chat = require "engine.Chat"
+		local chat = Chat.new("arena-unlock", {name="Cornac rogue"}, game.player)
+		chat:invoke("win")
+	end
+}
diff --git a/game/modules/tome/data/zones/arena-unlock/objects.lua b/game/modules/tome/data/zones/arena-unlock/objects.lua
new file mode 100644
index 0000000000000000000000000000000000000000..4e7b8c6c6405bb629806f2279b08ee9e45700cf7
--- /dev/null
+++ b/game/modules/tome/data/zones/arena-unlock/objects.lua
@@ -0,0 +1,20 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010 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
+
+load("/data/general/objects/objects.lua")
diff --git a/game/modules/tome/data/zones/arena-unlock/traps.lua b/game/modules/tome/data/zones/arena-unlock/traps.lua
new file mode 100644
index 0000000000000000000000000000000000000000..f8f844f583d30b1999a9bf7a520221cdebdfa557
--- /dev/null
+++ b/game/modules/tome/data/zones/arena-unlock/traps.lua
@@ -0,0 +1,20 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010 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
+
+load("/data/general/traps/elemental.lua")
diff --git a/game/modules/tome/data/zones/arena-unlock/zone.lua b/game/modules/tome/data/zones/arena-unlock/zone.lua
new file mode 100644
index 0000000000000000000000000000000000000000..c7c848351cf2541d111b96b979994c6901308e63
--- /dev/null
+++ b/game/modules/tome/data/zones/arena-unlock/zone.lua
@@ -0,0 +1,44 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010 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 = "Derth (Southeast)",
+	level_range = {5, 12},
+	level_scheme = "player",
+	max_level = 1,
+	actor_adjust_level = function(zone, level, e) return zone.base_level + e:getRankLevelAdjust() + level.level-1 + rng.range(-1,2) end,
+	width = 17, height = 16,
+	all_remembered = true,
+	all_lited = true,
+	persistant = "zone",
+	ambiant_music = "a_lomos_del_dragon_blanco.ogg",
+	no_level_connectivity = true,
+	generator =  {
+		map = {
+			class = "engine.generator.map.Static",
+			map = "zones/arena-unlock",
+		},
+	},
+	post_process = function(level)
+		local m = game.zone:makeEntityByName(game.level, "actor", "GLADIATOR")
+		if m then
+			game.zone:addEntity(game.level, m, "actor", 8, 2)
+		end
+	end
+}
diff --git a/game/modules/tome/data/zones/arena/grids.lua b/game/modules/tome/data/zones/arena/grids.lua
new file mode 100644
index 0000000000000000000000000000000000000000..915aa9b4b1246f6b72c4d3e0d9735938d5a8b920
--- /dev/null
+++ b/game/modules/tome/data/zones/arena/grids.lua
@@ -0,0 +1,43 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010 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
+
+load("/data/general/grids/basic.lua")
+load("/data/general/grids/sand.lua")
+
+newEntity{
+	define_as = "WALL_SEE",
+	name = "wall", image = "terrain/granite_wall1.png",
+	display = '#', color_r=255, color_g=255, color_b=255, back_color=colors.GREY,
+	always_remember = true,
+	does_block_move = true,
+	can_pass = {pass_wall=1},
+	block_sight = false,
+	air_level = -20,
+	dig = "FLOOR",
+}
+
+newEntity{
+	define_as = "LOCK",
+	name = "closed gate", image = "terrain/sealed_door.png",
+	display = '+', color=colors.WHITE, back_color=colors.DARK_UMBER,
+	notice = true,
+	always_remember = true,
+	block_sight = true,
+	does_block_move = true,
+}
diff --git a/game/modules/tome/data/zones/arena/npcs.lua b/game/modules/tome/data/zones/arena/npcs.lua
new file mode 100644
index 0000000000000000000000000000000000000000..4dcf86abda0ea64df62b5f0381b4181553fb9938
--- /dev/null
+++ b/game/modules/tome/data/zones/arena/npcs.lua
@@ -0,0 +1,1048 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010 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
+
+-- Load all others
+load("/data/general/npcs/all.lua")
+load("/data/general/npcs/crystal.lua")
+load("/data/general/npcs/bone-giant.lua")
+load("/data/general/npcs/ritch.lua")
+load("/data/general/npcs/ziguranth.lua")
+local Talents = require("engine.interface.ActorTalents")
+
+--Base arena human
+newEntity{ define_as = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	display = "@", color=colors.UMBER,
+
+	combat = { dam=resolvers.rngavg(5,12), atk=2, apr=6, physspeed=2 },
+
+	body = { INVEN = 10, MAINHAND=1, OFFHAND=1, BODY=1, QUIVER=1 },
+	resolvers.drops{chance=25, nb=1, {} },
+	resolvers.drops{chance=100, nb=1, {type="money"} },
+	infravision = 10,
+	lite = 2,
+	life_rating = 10, rank = 2, size_category = 3,
+	open_door = true,
+	autolevel = "warrior",
+	stun_immune = 0.2,
+	confusion_immune = 0.1,
+	fear_immune = 0.1,
+	ai = "dumb_talented_simple", ai_state = { ai_move = "move_dmap", talent_in = 1 },
+	energy = { mod = 1 },
+	stats = { str = 10, dex = 10, mag = 10, con = 10 },
+	resolvers.talents{ [Talents.T_HEAVY_ARMOUR_TRAINING] = 2, },
+	resolvers.equip{
+		{type="armor", subtype="feet", autoreq=true},
+	},
+}
+
+newEntity{ name = "wisp",
+	type = "elemental", subtype = "light",
+	display = "*", color=colors.YELLOW,
+	desc = [[A floating orb of magical energy. It shines with a radiant light. They explode Pupon contact.]],
+	combat = { dam=10, atk=5, apr=10, physspeed=1 },
+	level_range = {1, nil},
+	exp_worth = 1,
+	max_life = 10,
+	body = { INVEN = 10, MAINHAND=1, OFFHAND=1, BODY=1, QUIVER=1 },
+	no_drops = true, open_door = false,
+	infravision = 20,
+	rarity = 1,
+	lite = 4,
+	life_rating = 1, rank = 1, size_category = 1,
+	autolevel = "caster",
+	ai = "dumb_talented_simple", ai_state = { ai_move = "move_dmap", talent_in = 1 },
+	energy = { mod = 1 },
+	stats = { str = 9, dex = 20, mag = 20 },
+	resolvers.talents{
+		[Talents.T_EXPLODE] = 3,
+	},
+	no_breath = 1,
+	blind_immune = 1,
+	fear_immune = 1,
+	rank = 2,
+	size_category = 1,
+	poison_immune = 1,
+	disease_immune = 1,
+	poison_immune = 1,
+	stun_immune = 1,
+	resolvers.sustains_at_birth(),
+}
+
+--Minibosses
+
+newEntity{ 	name = "skeletal rat",
+	base = "BASE_NPC_RODENT",
+	define_as = "SKELERAT",
+	desc = [[The diminutive skeleton of a giant rat, charged with evil energies. Nobody understands the usefulness of undead rodents until several of them come after you]],
+	color = colors.GOLD,
+	level_range = {3, 4},
+	exp_worth = 2,
+	rank = 3,
+	max_life = resolvers.rngavg(30, 45),
+	combat = { dam = 7, atk = 15, apr = 10 },
+	stats = { str=8, dex=15, mag=1, con=5 },
+	combat_def = 2,
+	resolvers.talents{
+		[Talents.T_SOUL_ROT]=1,
+	},
+	resolvers.sustains_at_birth(),
+}
+
+newEntity{ name = "golden crystal",
+	base = "BASE_NPC_CRYSTAL",
+	define_as = "GOLDCRYSTAL",
+	color=colors.GOLD,
+	desc = "A formation of golden crystal. It emits a golden radiance equalling the sun itself.",
+	level_range = {1, 99},
+	exp_worth = 2,
+	rank = 3,
+	resolvers.drops{chance=100, nb=1, {type="jewelry", ego_chance=100}},
+	max_life = resolvers.rngavg(12,34),
+	resists = { [DamageType.LIGHT] = 100 },
+	resolvers.talents{
+		[Talents.T_SEARING_LIGHT]=1,
+	},
+	resolvers.sustains_at_birth(),
+}
+
+newEntity{ name = "master alchemist",
+	define_as = "MASTERALCHEMIST",
+	base = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	color=colors.ORANGE,
+
+	life_rating = 8,
+
+	stats = { str = 12, dex = 20, cun = 5, mag = 20, con = 10 },
+	desc = [[Deadly fighters using explosive gems to attack.]],
+	level_range = {15, nil}, exp_worth = 2,
+	rarity = 10,
+	rank = 3,
+	max_life = 120,
+	equipment = resolvers.equip{
+		{type="weapon", subtype="staff", ego_chance=100, autoreq=true},
+		{type="armor", subtype="cloth", ego_chance=100, autoreq=true},
+	},
+	resolvers.drops{chance=100, nb=1, {type="wand", ego_chance=100}},
+	autolevel = "dexmage",
+	combat_def = 3,
+	resolvers.talents{
+		[Talents.T_SHOCKWAVE_BOMB]=3,
+		[Talents.T_EXPLOSION_EXPERT]=3,
+		[Talents.T_ALCHEMIST_PROTECTION]=5,
+		[Talents.T_STAFF_MASTERY]=4,
+		[Talents.T_FIRE_INFUSION]=3,
+		[Talents.T_ACID_INFUSION]=3,
+		[Talents.T_GEM_PORTAL]=2,
+		[Talents.T_ELEMENTAL_BOLT]=2,
+	},
+	resolvers.generic(function(self)
+		local t = self:getTalentFromId(self.T_CREATE_ALCHEMIST_GEMS)
+		local gem = t.make_gem(self, t, "GEM_AGATE")
+		self:wearObject(gem, true, false)
+	end),
+}
+
+newEntity{ name = "multihued wyrmic",
+	define_as = "MULTIHUEWYRMIC",
+	base = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	color=colors.GOLD,
+	female = true,
+	shader = "quad_hue",
+	resolvers.drops{chance=100, nb=3, {type="scroll"} },
+	stats = { str = 20, dex = 20, mag = 20, con = 9, wil = 15 },
+	desc = [[A powerful wyrmic with mastery over several elements.]],
+	level_range = {20, nil}, exp_worth = 2,
+	rarity = 10,
+	rank = 3,
+	instakill_immune = 1,
+	stun_immune = 0.8,
+	confusion_immune = 0.7,
+	max_life = 180,
+	resolvers.equip{
+		{type="weapon", subtype="battleaxe", autoreq=true},
+		{type="armor", subtype="cloak", autoreq=true},
+	},
+	combat_armor = 0, combat_def = 6,
+	resolvers.talents{
+		[Talents.T_LIGHTNING_SPEED] = 5,
+		[Talents.T_ICE_CLAW] = 4,
+		[Talents.T_WING_BUFFET] = 3,
+		[Talents.T_ICY_SKIN] = 2,
+		[Talents.T_TORNADO] = 1,
+		[Talents.T_DEATH_DANCE] = 3,
+		[Talents.T_RUSH] = 3,
+		[Talents.T_WEAPON_COMBAT]=2,
+		[Talents.T_WEAPONS_MASTERY]=2,
+	},
+}
+
+newEntity{ name = "master slinger",
+	define_as = "MASTERSLINGER",
+	base = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	color=colors.GOLD,
+
+	life_rating = 11,
+	rank = 3,
+	autolevel = "slinger",
+	stats = { str=11, dex=15, cun = 15, mag=1, con=13 },
+	desc = [[Expert slingers on hire by the arena. They are great at their jobs.]],
+	level_range = {12, nil}, exp_worth = 2,
+	rarity = 10,
+	max_life = resolvers.rngavg(100,110),
+	resolvers.equip{
+		{type="weapon", subtype="sling", autoreq=true},
+		{type="ammo", subtype="shot", autoreq=true},
+		{type="armor", subtype="shield", autoreq=true},
+	},
+	combat_armor = 1, combat_def = 4,
+	resolvers.talents{
+		[Talents.T_SHOOT]=1,
+		[Talents.T_DISENGAGE]=2,
+		[Talents.T_RAPID_SHOT]=3,
+		[Talents.T_INERTIAL_SHOT]=3,
+		[Talents.T_HEAVE]=3,
+		[Talents.T_SHIELD_EXPERTISE]=1,
+		[Talents.T_SLING_MASTERY]=1,
+	},
+}
+
+newEntity{ name = "gladiator",
+	define_as = "GLADIATOR",
+	base = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	color=colors.GOLD,
+
+	life_rating = 15,
+	rank = 3,
+
+	stats = { str=20, dex=10, mag=1, con=16 },
+	desc = [[Mercenaries hired by the arena for the sole purpose of entertainment. They make a living beating people up.]],
+	level_range = {7, nil}, exp_worth = 2,
+	rarity = 10,
+	max_life = resolvers.rngavg(80,100),
+	resolvers.equip{
+		{type="weapon", subtype="mace", autoreq=true},
+		{type="armor", subtype="shield", autoreq=true},
+		{type="armor", subtype="heavy", autoreq=true},
+	},
+	resolvers.drops{chance=100, nb=1, {type="weapon", ego_chance=100}},
+	combat_def = 4,
+	resolvers.talents{
+		[Talents.T_SHIELD_PUMMEL]=2,
+		[Talents.T_RUSH]=1,
+		[Talents.T_REPULSION]=2,
+	},
+}
+
+newEntity{ name = "reaver",
+	define_as = "REAVER",
+	base = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	color=colors.GOLD,
+	stats = { str = 20, dex = 20, mag = 20, con = 9, wil = 15 },
+	desc = [[A warrior of death.]],
+	level_range = {25, nil}, exp_worth = 2,
+	rarity = 10,
+	rank = 3,
+	max_life = 150,
+	resolvers.equip{
+		{type="weapon", subtype="longsword", autoreq=true},
+		{type="weapon", subtype="longsword", autoreq=true},
+		{type="armor", subtype="heavy", autoreq=true},
+	},
+	autolevel = "warriormage",
+	combat_def = 4,
+	resolvers.talents{
+		[Talents.T_DRAIN] = 4,
+		[Talents.T_BONE_SPEAR] = 3,
+		[Talents.T_BONE_GRAB] = 2,
+		[Talents.T_BONE_SHIELD] = 2,
+		[Talents.T_VIRULENT_DISEASE] = 2,
+		[Talents.T_CORRUPTED_STRENGTH] = 2,
+		[Talents.T_REND] = 2,
+		[Talents.T_RUIN] = 2,
+		[Talents.T_ACID_BLOOD] = 2,
+		[Talents.T_WEAPON_COMBAT] = 2,
+
+	},
+}
+
+newEntity{ name = "headless horror",
+	base = "BASE_NPC_HORROR", define_as = "HEADLESSHORROR",
+	color=colors.GOLD,
+	desc ="A headless gangly humanoid with a large distended stomach. Was captured and tamed by the first master of the arena.",
+	level_range = {30, nil}, exp_worth = 1,
+	rarity = 3,
+	rank = 3,
+	autolevel = "warrior",
+	ai = "dumb_talented_simple", ai_state = { ai_move="move_dmap", talent_in=1, },
+	combat = { dam=18, atk=18, apr=10, dammod={str=1} },
+	combat = {damtype=DamageType.PHYSICAL},
+	no_auto_resists = true,
+
+	resolvers.talents{
+		[Talents.T_MANA_CLASH]=4,
+		[Talents.T_GRAB]=4,
+	},
+
+	on_added = function(self)
+		local eyes = {}
+		for i = 1, 3 do
+			local x, y = util.findFreeGrid(self.x, self.y, 15, true, {[engine.Map.ACTOR]=true})
+			if x and y then
+				local m = game.zone:makeEntity(game.level, "actor", {properties={"is_eldritch_eye"}, special_rarity="_eldritch_eye_rarity"}, nil, true)
+				if m then
+					m.summoner = self
+					game.zone:addEntity(game.level, m, "actor", x, y)
+					eyes[m] = true
+
+					local damtype = next(m.resists)
+					self.resists[damtype] = 100
+					self.resists.all = (self.resists.all or 0) + 30
+				end
+			end
+		end
+		self.eyes = eyes
+	end,
+	on_die = function(self, src)
+		local nb = 0
+		for eye, _ in pairs(self.eyes) do
+			if not eye.dead then eye:die(src) nb = nb + 1 end
+		end
+		if nb > 0 then
+			game.logSeen(self, "#AQUAMARINE#As %s falls all its eyes fall to the ground!", self.name)
+		end
+	end,
+}
+
+
+--Bosses
+
+newEntity{ name = "Ryal",
+	base = "BASE_NPC_BONE_GIANT",
+	color=colors.VIOLET,
+	define_as = "ARENA_BOSS_RYAL",
+	desc = "A gargantuan bone giant resembling a wingless wyrm. He is fully sentient and surprisingly fast.",
+	rank = 4, unique = true,
+	resolvers.equip{
+		{type="weapon", subtype="trident", autoreq=true, special_rarity="trident_rarity"},
+	},
+	instakill_immune = 1,
+	level_range = {9, nil}, exp_worth = 3,
+	max_life = resolvers.rngavg(120,150),
+	combat_armor = 0, combat_def = 10,
+	melee_project = {[DamageType.BLIGHT]=resolvers.mbonus(15, 1)},
+	autolevel = "warriormage",
+	talent_cd_reduction={
+		[Talents.T_KNOCKBACK] = 2,
+	},
+	resolvers.talents {
+		[Talents.T_EXOTIC_WEAPONS_MASTERY]=2,
+		[Talents.T_BONE_SHIELD]=2,
+		[Talents.T_THROW_BONES]=1,
+		[Talents.T_KNOCKBACK]=3,
+		[Talents.T_BLINDING_SPEED]=1,
+	},
+	resolvers.sustains_at_birth(),
+}
+
+newEntity{ name = "Fryjia Loren",
+	define_as = "ARENA_BOSS_FRYJIA",
+	type = "humanoid", subtype = "human",
+	display = "@",
+	color=colors.VIOLET,
+	desc = [[A young girl with skin pale as snow. She is small, but deadly in battle, unleashing a constant barrage of ice shards in battle.]],
+	level_range = {12, nil}, exp_worth = 3,
+	rank = 4,
+	size_category = 2,
+	female = true,
+	max_life = 75, life_rating = 11,
+	infravision = 20,
+	stats = { str=10, dex=20, cun=10, mag=15, con=10, wil = 15 },
+	resists={[DamageType.FIRE] = -100, [DamageType.ICE] = 60},
+
+	instakill_immune = 1,
+	stun_immune = 0.5,
+	fear_immune = 1,
+
+	open_door = true,
+
+	autolevel = "dexmage",
+	ai = "dumb_talented_simple", ai_state = { talent_in=1, ai_move="move_astar", },
+
+	body = { INVEN = 10, MAINHAND=1, OFFHAND=1, BODY=1, HEAD=1, FEET=1 },
+
+	resolvers.equip{
+		{type="weapon", subtype="dagger", autoreq=true},
+		{type="weapon", subtype="dagger", autoreq=true},
+		{type="armor", subtype="light", autoreq=true},
+		{type="armor", subtype="light", autoreq=true}
+	},
+	talent_cd_reduction={
+		[Talents.T_ICE_SHARDS] = 3,
+		[Talents.T_LIGHTNING_SPEED] = 4,
+		[Talents.T_DISENGAGE] = 5,
+		[Talents.T_RUSH] = 3,
+	},
+	resolvers.talents{
+		[Talents.T_DUAL_WEAPON_TRAINING] = 2,
+		[Talents.T_DUAL_WEAPON_DEFENSE] = 1,
+		[Talents.T_DUAL_STRIKE] = 1,
+		[Talents.T_RUSH] = 4,
+		[Talents.T_SUPPRESSION] = 3,
+		[Talents.T_PITY] = 1,
+		[Talents.T_MANAFLOW] = 3,
+		[Talents.T_QUICK_RECOVERY] = 5,
+		[Talents.T_DISENGAGE] = 5,
+		[Talents.T_ICE_CLAW] = 3,
+		[Talents.T_LIGHTNING_SPEED] = 2,
+		[Talents.T_UTTERCOLD]=2,
+		[Talents.T_TIDAL_WAVE]=2,
+		[Talents.T_ICE_SHARDS]=3,
+	},
+	resolvers.sustains_at_birth(),
+}
+
+newEntity{ name = "Riala Shalarak",
+	define_as = "ARENA_BOSS_RIALA",
+	type = "humanoid", subtype = "human",
+	display = "@",
+	color=colors.VIOLET,
+	desc = [[A strong female magician. Years of experience make her a dangerous combatant.]],
+	level_range = {25, nil}, exp_worth = 3,
+	rank = 4,
+	size_category = 3,
+	female = true,
+	max_life = 150, life_rating = 30,
+	infravision = 20,
+	stats = { str=15, dex=15, cun=20, mag=30, con=15, wil=15 },
+	resists={[DamageType.FIRE] = 100, [DamageType.ICE] = -20},
+
+	instakill_immune = 1,
+	stun_immune = 0.5,
+	fear_immune = 0.5,
+	open_door = true,
+
+	autolevel = "caster",
+	ai = "dumb_talented_simple", ai_state = { talent_in=1, ai_move="move_astar", },
+
+	body = { INVEN = 10, MAINHAND=1, OFFHAND=1, BODY=1, HEAD=1, FEET=1 },
+
+	summon = {{name = "wisp", number=3, hasxp=false}},
+
+	resolvers.equip{
+		{type="weapon", subtype="staff", autoreq=true},
+		{type="armor", subtype="cloth", autoreq=true}
+	},
+	resolvers.talents{
+		[Talents.T_FIREFLASH] = 2,
+		[Talents.T_ILLUMINATE] = 5,
+		[Talents.T_STRIKE] = 2,
+		[Talents.T_SUMMON] = 1,
+		[Talents.T_ELEMENTAL_BOLT] = 3,
+		[Talents.T_PHASE_DOOR] = 3,
+		[Talents.T_DISRUPTION_SHIELD] = 2,
+		[Talents.T_STAFF_MASTERY] = 2,
+		[Talents.T_DEFENSIVE_POSTURE] = 2,
+	},
+	resolvers.sustains_at_birth(),
+}
+
+newEntity{ name = "Valfren Loren",
+	define_as = "ARENA_BOSS_VALFREN",
+	type = "humanoid", subtype = "human",
+	display = "@",
+	color=colors.VIOLET,
+	desc = [[A massive armor with a massive axe containing a massively cursed person. He is cursed to fight eternally.]],
+	level_range = {16, nil}, exp_worth = 3,
+	rank = 4,
+	size_category = 4,
+	female = false,
+	max_life = 160, life_rating = 15,
+	infravision = 0,
+	stats = { str=25, dex=25, cun=5, mag=10, con=15, wil=35 },
+	resists={[DamageType.DARKNESS] = 100, [DamageType.LIGHT] = -70},
+
+	instakill_immune = 1,
+
+	open_door = true,
+
+	autolevel = "warrior",
+	ai = "dumb_talented_simple", ai_state = { talent_in=1, ai_move="move_astar", },
+
+	body = { INVEN = 10, MAINHAND=1, OFFHAND=1, BODY=1, HEAD=1, FEET=1 },
+
+	resolvers.equip{
+		{type="weapon", subtype="battleaxe", autoreq=true, ego_chance=100},
+		{type="armor", subtype="massive", autoreq=true, ego_chance=100}
+	},
+	resolvers.talents{
+		[Talents.T_GLOOM] = 5,
+		[Talents.T_BLINDSIDE] = 3,
+		[Talents.T_SLASH] = 4,
+		[Talents.T_SEETHE] = 5,
+		[Talents.T_RAMPAGE] = 8,
+		[Talents.T_BRUTALITY] = 3,
+		[Talents.T_INSTINCTS] = 3,
+		[Talents.T_RECKLESS_CHARGE] = 5,
+		[Talents.T_MASSIVE_ARMOUR_TRAINING] = 5,
+		[Talents.T_WEAPON_COMBAT] = 2,
+	},
+	resolvers.sustains_at_birth(),
+}
+
+newEntity{ name = "Rej Arkatis",
+	define_as = "ARENA_BOSS_MASTER_DEFAULT",
+	type = "humanoid", subtype = "human",
+	display = "@",
+	color=colors.VIOLET,
+	desc = [[A cornac fighter of respectable talent. He emerged from nowhere and became the true master of fighting.]],
+	level_range = {1, nil}, exp_worth = 3,
+	rank = 5,
+	size_category = 3,
+	female = false,
+	max_life = 180, life_rating = 20,
+	infravision = 20,
+	stats = { str=15, dex=20, cun=25, mag=20, con=15, wil=35 },
+	resists={[DamageType.DARKNESS] = -20},
+	no_drops = true,
+
+	instakill_immune = 1,
+	stun_immune = 0.7,
+	fear_immune = 0.6,
+	open_door = true,
+
+	ai = "dumb_talented_simple", ai_state = { talent_in=1, ai_move="move_astar", },
+
+	body = { INVEN = 10, MAINHAND=1, OFFHAND=1, BODY=1, HEAD=1, FEET=1 },
+
+	resolvers.equip{
+		{type="weapon", subtype="dagger", autoreq=true, ego_chance=100},
+		{type="weapon", subtype="dagger", autoreq=true, ego_chance=100},
+		{type="armor", subtype="cloak", autoreq=true, ego_chance=100},
+	},
+	autolevel = "rogue",
+	combat_def = 2,
+	resolvers.talents{
+		[Talents.T_STEALTH]=5,
+		[Talents.T_SHADOW_CUNNING]=4,
+		[Talents.T_SHADOWSTEP]=3,
+		[Talents.T_SHADOW_COMBAT]=3,
+		[Talents.T_SHADOW_FEED]=2,
+		[Talents.T_DEADLY_STRIKES]=2,
+		[Talents.T_ILLUMINATE]=4,
+		[Talents.T_PHASE_DOOR]=4,
+		[Talents.T_HIDE_IN_PLAIN_SIGHT]=5,
+		[Talents.T_STICKY_SMOKE]=3,
+		[Talents.T_DISENGAGE]=5,
+		[Talents.T_RUSH]=5,
+		[Talents.T_WILLFUL_COMBAT]=3,
+		[Talents.T_DUAL_WEAPON_TRAINING] = 5,
+	},
+	resolvers.sustains_at_birth(),
+}
+
+--Regular
+
+newEntity{ name = "slinger",
+	base = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	color=colors.UMBER,
+	life_rating = 8, stats = { str = 7, dex = 10, cun = 10, mag = 1, con = 7 },
+	desc = [[Ranged fighters coming to the arena looking for wealth and glory, just like you.]],
+	level_range = {4, nil}, exp_worth = 1,
+	rarity = 1,
+	max_life = resolvers.rngavg(80,95),
+	resolvers.equip{
+		{type="weapon", subtype="sling", autoreq=true},
+		{type="ammo", subtype="shot", autoreq=true},
+	},
+	autolevel = "slinger",
+	combat_def = 2,
+	resolvers.talents{
+		[Talents.T_SHOOT]=1,
+		[Talents.T_DISENGAGE]=2,
+		[Talents.T_RAPID_SHOT]=2
+	},
+}
+
+newEntity{ name = "high slinger",
+	base = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	color=colors.DARK_UMBER,
+	life_rating = 8, stats = { str = 7, dex = 10, cun = 10, mag = 1, con = 7 },
+	desc = [[Ranged fighters coming to the arena looking for wealth and glory, just like you.]],
+	level_range = {4, nil}, exp_worth = 1,
+	rarity = 1,
+	max_life = resolvers.rngavg(80,95),
+	resolvers.equip{
+		{type="weapon", subtype="sling", autoreq=true},
+		{type="ammo", subtype="shot", autoreq=true},
+	},
+	autolevel = "slinger",
+	combat_def = 2,
+	resolvers.talents{
+		[Talents.T_SHOOT]=1,
+		[Talents.T_DISENGAGE]=3,
+		[Talents.T_HEAVE]=1,
+		[Talents.T_RAPID_SHOT]=4,
+		[Talents.T_INERTIAL_SHOT]=2,
+	},
+}
+
+newEntity{ name = "alchemist",
+	base = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	color=colors.ORANGE,
+
+	life_rating = 8,
+
+	stats = { str = 7, dex = 11, cun = 1, mag = 11, con = 6 },
+	desc = [[Deadly fighters using explosive gems to attack.]],
+	level_range = {1, nil}, exp_worth = 1,
+	rarity = 1,
+	max_life = 60,
+	equipment = resolvers.equip{
+		{type="weapon", subtype="staff", autoreq=true},
+		{type="armor", subtype="cloth", autoreq=true},
+	},
+	resolvers.drops{chance=40, {type="wand", ego_chance=100}},
+	autolevel = "dexmage",
+	combat_def = 2,
+	resolvers.talents{
+		[Talents.T_THROW_BOMB]=2,
+		[Talents.T_ALCHEMIST_PROTECTION]=4,
+		[Talents.T_LIGHTNING_INFUSION]=2,
+		[Talents.T_ACID_INFUSION]=2,
+		[Talents.T_FIRE_INFUSION]=2,
+		[Talents.T_ELEMENTAL_BOLT]=1,
+	},
+	resolvers.generic(function(self)
+		local t = self:getTalentFromId(self.T_CREATE_ALCHEMIST_GEMS)
+		local gem = t.make_gem(self, t, "GEM_AGATE")
+		self:wearObject(gem, true, false)
+	end),
+}
+
+newEntity{ name = "blood mage",
+	base = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	color=colors.CRIMSON,
+
+	life_rating = 4,
+
+	stats = { str = 7, dex = 11, cun = 1, mag = 11, con = 6 },
+	desc = [[A man dressed in black robes. You feel weak as you hear their ominous chanting.]],
+	level_range = {1, nil}, exp_worth = 1,
+	rarity = 1,
+	max_life = 40,
+	equipment = resolvers.equip{
+		{type="weapon", subtype="staff", autoreq=true},
+		{type="armor", subtype="cloth", autoreq=true},
+	},
+	resolvers.drops{chance=40, {type="wand", ego_chance=100}},
+	autolevel = "caster",
+	resolvers.talents{
+		[Talents.T_BLOOD_GRASP] = 4,
+		[Talents.T_CURSE_OF_VULNERABILITY] = 2,
+		[Talents.T_PHASE_DOOR] = 1,
+	},
+}
+
+newEntity{ name = "hexer",
+	base = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	color=colors.DARK_GREY,
+
+	life_rating = 1,
+
+	stats = { str = 7, dex = 11, cun = 1, mag = 15, con = 6 },
+	desc = [[A man dressed in black robes. You feel a thousand curses being put on you.]],
+	level_range = {1, nil}, exp_worth = 1,
+	rarity = 1,
+	max_life = 10,
+	equipment = resolvers.equip{
+		{type="weapon", subtype="staff", autoreq=true},
+		{type="armor", subtype="cloth", autoreq=true},
+	},
+	resolvers.drops{chance=40, {type="wand", ego_chance=100}},
+	autolevel = "caster",
+	resolvers.talents{
+		[Talents.T_BURNING_HEX]=3,
+		[Talents.T_EMPATHIC_HEX]=1,
+		[Talents.T_HYMN_OF_SHADOWS]=3,
+		[Talents.T_SOUL_ROT]=3,
+	},
+}
+
+newEntity{ name = "rogue",
+	base = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	color=colors.DARK_BLUE,
+
+	life_rating = 8,
+
+	stats = { str = 7, dex = 10, cun = 28, mag = 1, con = 7 },
+	desc = [[Stealthy fighters trying to achieve victory with trickery. Be careful or they will steal your sight!]],
+	level_range = {1, nil}, exp_worth = 1,
+	rarity = 1,
+	max_life = 60,
+	resolvers.equip{
+		{type="weapon", subtype="dagger", autoreq=true},
+		{type="weapon", subtype="dagger", autoreq=true},
+		{type="armor", subtype="cloak", autoreq=true},
+		{name="rough leather gloves", autoreq=true},
+	},
+	autolevel = "rogue",
+	combat_def = 2,
+	resolvers.talents{
+		[Talents.T_STEALTH]=3,
+		[Talents.T_HIDE_IN_PLAIN_SIGHT]=5,
+		[Talents.T_STICKY_SMOKE]=2,
+		[Talents.T_DISENGAGE]=1,
+		[Talents.T_DUAL_WEAPON_TRAINING] = 1,
+	},
+}
+
+newEntity{ name = "shadowblade",
+	base = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	color=colors.BLACK,
+
+	life_rating = 10,
+
+	stats = { str = 7, dex = 10, cun = 28, mag = 1, con = 7 },
+	desc = [[Stealthy fighters trying to achieve victory with trickery. Be careful or they will steal your life!]],
+	level_range = {1, nil}, exp_worth = 1,
+	rarity = 1,
+	max_life = 100,
+	resolvers.equip{
+		{type="weapon", subtype="dagger", autoreq=true},
+		{type="weapon", subtype="dagger", autoreq=true},
+		{type="armor", subtype="cloak", autoreq=true},
+		{name="rough leather gloves", autoreq=true},
+	},
+	autolevel = "rogue",
+	combat_def = 2,
+	resolvers.talents{
+		[Talents.T_STEALTH]=4,
+		[Talents.T_SHADOW_CUNNING]=3,
+		[Talents.T_SHADOWSTEP]=1,
+		[Talents.T_SHADOW_COMBAT]=2,
+		[Talents.T_ILLUMINATE]=3,
+		[Talents.T_HIDE_IN_PLAIN_SIGHT]=5,
+		[Talents.T_DISENGAGE]=2,
+		[Talents.T_DUAL_WEAPON_TRAINING] = 3,
+	},
+}
+
+newEntity{ name = "fire wyrmic",
+	base = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	color=colors.RED,
+	resolvers.drops{chance=30, nb=1, {type="scroll"}},
+	stats = { str = 10, dex = 10, mag = 10, con = 9, wil = 15},
+	desc = [[A fire wyrmic aspiring to win the tournament. He comes paired with an ice wyrmic.]],
+	level_range = {1, nil}, exp_worth = 1, autolevel = "wyrmic",
+	rarity = 1,
+	max_life = resolvers.rngavg(90,105),
+	resolvers.equip{
+		{type="weapon", subtype="battleaxe", autoreq=true},
+		{type="armor", subtype="cloak", autoreq=true},
+	},
+	combat_armor = 1, combat_def = 4,
+	resolvers.talents{
+		[Talents.T_BELLOWING_ROAR] = 1,
+		[Talents.T_WING_BUFFET] = 2,
+		[Talents.T_DEVOURING_FLAME] = 1,
+		[Talents.T_DEATH_DANCE] = 2,
+		[Talents.T_WEAPONS_MASTERY]=2,
+	},
+}
+
+newEntity{ name = "ice wyrmic",
+	base = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	color=colors.BLUE,
+	resolvers.drops{chance=30, nb=1, {type="scroll"}},
+	stats = { str = 10, dex = 10, mag = 10, con = 9, wil = 15},
+	desc = [[An ice wyrmic aspiring to win the tournament. He comes paired with a fire wyrmic.]],
+	level_range = {1, nil}, exp_worth = 1, autolevel = "wyrmic",
+	rarity = 1,
+	female = true,
+	max_life = resolvers.rngavg(90,105),
+	resolvers.equip{
+		{type="weapon", subtype="battleaxe", autoreq=true},
+		{type="armor", subtype="cloak", autoreq=true},
+	},
+	combat_armor = 1, combat_def = 4,
+	resolvers.talents{
+		[Talents.T_ICE_CLAW] = 3,
+		[Talents.T_ICY_SKIN] = 3,
+		[Talents.T_ICE_WALL] = 2,
+		[Talents.T_RUSH] = 2,
+		[Talents.T_WEAPON_COMBAT]=2,
+	},
+}
+
+newEntity{ name = "sand wyrmic",
+	base = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	color = {r = 204, g = 255, b = 95},
+	resolvers.drops{chance=30, nb=1, {type="scroll"}},
+	stats = { str = 10, dex = 10, mag = 10, con = 9, wil = 15},
+	desc = [[A sand wyrmic aspiring to win the tournament. He comes paired with a storm wyrmic.]],
+	level_range = {1, nil}, exp_worth = 1, autolevel = "wyrmic",
+	rarity = 1,
+	max_life = resolvers.rngavg(90,105),
+
+	make_escort = {
+		{name="storm wyrmic", number=1},
+	},
+	resolvers.equip{
+		{type="weapon", subtype="battleaxe", autoreq=true},
+		{type="armor", subtype="cloak", autoreq=true},
+	},
+	combat_armor = 1, combat_def = 4,
+	resolvers.talents{
+		[Talents.T_EARTHEN_MISSILES] = 3,
+		[Talents.T_SAND_BREATH] = 2,
+		[Talents.T_NATURE_TOUCH] = 2,
+		[Talents.T_DEATH_DANCE] = 2,
+		[Talents.T_WEAPONS_MASTERY]=2,
+	},
+}
+
+newEntity{ name = "storm wyrmic",
+	base = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	color=colors.WHITE,
+	resolvers.drops{chance=30, nb=1, {type="scroll"}},
+	stats = { str = 10, dex = 10, mag = 10, con = 9, wil = 15},
+	desc = [[A storm wyrmic aspiring to win the tournament. He comes paired with a sand wyrmic.]],
+	level_range = {1, nil}, exp_worth = 1, autolevel = "wyrmic",
+	rarity = 1,
+	female = true,
+	max_life = resolvers.rngavg(90,105),
+
+	resolvers.equip{
+		{type="weapon", subtype="battleaxe", autoreq=true},
+		{type="armor", subtype="cloak", autoreq=true},
+	},
+	combat_armor = 1, combat_def = 4,
+	resolvers.talents{
+		[Talents.T_LIGHTNING_SPEED] = 4,
+		[Talents.T_STATIC_FIELD] = 2,
+		[Talents.T_TORNADO] = 1,
+		[Talents.T_DISENGAGE] = 3,
+		[Talents.T_WEAPON_COMBAT]=2,
+	},
+}
+
+newEntity{ name = "high gladiator",
+	base = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	color=colors.DARK_RED,
+
+	life_rating = 11,
+
+	stats = { str=15, dex=15, mag=1, con=15, wil=20 },
+	desc = [[Mercenaries hired by the arena for the sole purpose of entertainment. They make a living beating people up.]],
+	level_range = {14, nil}, exp_worth = 1,
+	rarity = 10,
+	max_life = 90,
+	resolvers.equip{
+		{type="weapon", subtype="mace", autoreq=true},
+		{type="armor", subtype="shield", autoreq=true},
+		{type="armor", subtype="heavy", autoreq=true},
+	},
+	autolevel = "warrior",
+	resolvers.drops{chance=50, nb=1, {type="weapon", ego_chance=20}},
+	combat_def = 3,
+	resolvers.talents{
+		[Talents.T_SHIELD_PUMMEL]=2,
+		[Talents.T_RUSH]=2,
+		[Talents.T_DISENGAGE]=2,
+		[Talents.T_REPULSION]=2,
+		[Talents.T_OVERPOWER]=2,
+		[Talents.T_WEAPONS_MASTERY]=1,
+	},
+}
+
+newEntity{ name = "great gladiator",
+	base = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	color=colors.VERY_DARK_RED,
+
+	life_rating = 12,
+
+	stats = { str=20, dex=20, mag=5, con=15, wil=25 },
+	desc = [[Mercenaries hired by the arena for the sole purpose of entertainment. They make a living beating people up.]],
+	level_range = {19, nil}, exp_worth = 2,
+	rarity = 10,
+	max_life = 120,
+	resolvers.equip{
+		{type="weapon", subtype="trident", autoreq=true, special_rarity="trident_rarity"},
+		{type="armor", subtype="heavy", autoreq=true},
+	},
+	autolevel = "warrior",
+	resolvers.drops{chance=75, nb=1, {type="weapon", ego_chance=40}},
+	combat_def = 4,
+	resolvers.talents{
+		[Talents.T_RUSH]=5,
+		[Talents.T_EXOTIC_WEAPONS_MASTERY]=2,
+		[Talents.T_JUGGERNAUT]=3,
+		[Talents.T_DEATH_DANCE]=3,
+		[Talents.T_BATTLE_CRY]=2,
+		[Talents.T_WEAPONS_MASTERY]=2,
+		[Talents.T_WEAPON_COMBAT]=2,
+	},
+}
+
+newEntity{ name = "martyr",
+	base = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	color=colors.SALMON,
+	life_rating = 12,
+
+	stats = { str=15, dex=15, mag=20, con=10, wil=15 },
+	desc = [[A devout soldier.]],
+	level_range = {15, nil}, exp_worth = 2,
+	rarity = 10,
+	max_life = 200,
+	resolvers.equip{
+		{type="weapon", subtype="longsword", ego_chance=10, autoreq=true},
+		{type="armor", subtype="shield", ego_chance=30, autoreq=true},
+	},
+	autolevel = "caster",
+	combat_def = 4,
+	resolvers.talents{
+		[Talents.T_MARTYRDOM]=2,
+		[Talents.T_RUSH]=2,
+		[Talents.T_CHANT_OF_FORTRESS]=3,
+		[Talents.T_RETRIBUTION]=1,
+		[Talents.T_WEAPONS_MASTERY]=2,
+		[Talents.T_SHIELD_EXPERTISE]=2,
+	},
+}
+
+newEntity{ name = "anorithil",
+	base = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	color=colors.GREY,
+	life_rating = 12,
+
+	stats = { str=10, dex=10, mag=15, con=10, wil=15 },
+	desc = [[Divine warriors from afar. They use the power of light and darkness against you!]],
+	level_range = {15, nil}, exp_worth = 2,
+	rarity = 10,
+	max_life = 120,
+	resolvers.equip{
+		{type="weapon", subtype="staff", ego_chance=30, autoreq=true},
+		{type="armor", subtype="cloth", ego_chance=30, autoreq=true},
+	},
+	autolevel = "caster",
+	resolvers.drops{chance=50, nb=1, {type="weapon", subtype="staff", ego_chance=100}},
+	combat_def = 4,
+	resolvers.talents{
+		[Talents.T_CIRCLE_OF_SHIFTING_SHADOWS]=2,
+		[Talents.T_CIRCLE_OF_BLAZING_LIGHT]=2,
+		[Talents.T_TWILIGHT]=2,
+		[Talents.T_SEARING_LIGHT]=2,
+		[Talents.T_MOONLIGHT_RAY]=1,
+		[Talents.T_HYMN_OF_SHADOWS]=2,
+		[Talents.T_CHANT_OF_FORTRESS]=2,
+	},
+}
+
+newEntity{ name = "sun paladin",
+	base = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	color=colors.LIGHT_UMBER,
+	life_rating = 12,
+
+	stats = { str=20, dex=20, mag=15, con=10, wil=15 },
+	desc = [[Divine warriors from afar. They wield the power of light, and a mean sword.]],
+	level_range = {15, nil}, exp_worth = 2,
+	rarity = 10,
+	max_life = 150,
+	resolvers.equip{
+		{type="weapon", subtype="longsword", ego_chance=30, autoreq=true},
+		{type="armor", subtype="massive", autoreq=true},
+		{type="armor", subtype="shield", ego_chance=30, autoreq=true},
+	},
+	resolvers.drops{chance=50, nb=1, {type="weapon", subtype="staff", ego_chance=100}},
+	combat_def = 4,
+	autolevel = "warriormage",
+	resolvers.talents{
+		[Talents.T_CHANT_OF_FORTITUDE]=3,
+		[Talents.T_WEAPON_OF_LIGHT]=2,
+		[Talents.T_WAVE_OF_POWER]=2,
+		[Talents.T_CRUSADE]=3,
+		[Talents.T_SHIELD_OF_LIGHT]=1,
+		[Talents.T_BRANDISH]=1,
+		[Talents.T_MASSIVE_ARMOUR_TRAINING]=2,
+		[Talents.T_WEAPON_COMBAT]=2,
+	},
+}
+
+newEntity{ name = "star crusader",
+	base = "BASE_NPC_ARENA1",
+	type = "humanoid", subtype = "human",
+	color=colors.GOLD,
+	life_rating = 10,
+
+	stats = { str=25, dex=25, mag=25, con=8, wil=25 },
+	desc = [[Divine warriors from afar. They wield the power of light, and a mean sword. Darkness too.]],
+	level_range = {20, nil}, exp_worth = 2,
+	rarity = 10,
+	max_life = 150,
+	stun_immune = 0.9,
+	fear_immune = 1,
+	stun_immune = 0.2,
+	confusion_immune = 0.4,
+	resolvers.equip{
+		{type="weapon", subtype="longsword", ego_chance=30, autoreq=true},
+		{type="armor", subtype="massive", autoreq=true},
+		{type="armor", subtype="shield", ego_chance=50, autoreq=true},
+	},
+	resolvers.drops{chance=50, nb=1, {type="weapon", subtype="staff", ego_chance=100}},
+	combat_def = 4,
+	autolevel = "warriormage",
+	resolvers.talents{
+		[Talents.T_CIRCLE_OF_SHIFTING_SHADOWS]=2,
+		[Talents.T_CIRCLE_OF_BLAZING_LIGHT]=2,
+		[Talents.T_TWILIGHT]=2,
+		[Talents.T_SEARING_LIGHT]=2,
+		[Talents.T_MOONLIGHT_RAY]=1,
+		[Talents.T_HYMN_OF_SHADOWS]=2,
+		[Talents.T_CHANT_OF_FORTRESS]=2,
+		[Talents.T_WEAPON_OF_LIGHT]=2,
+		[Talents.T_CRUSADE]=3,
+		[Talents.T_BRANDISH]=1,
+		[Talents.T_RETRIBUTION]=1,
+		[Talents.T_MASSIVE_ARMOUR_TRAINING]=1,
+		[Talents.T_WEAPON_COMBAT]=2,
+		[Talents.T_WEAPONS_MASTERY]=2,
+	},
+}
diff --git a/game/modules/tome/data/zones/arena/objects.lua b/game/modules/tome/data/zones/arena/objects.lua
new file mode 100644
index 0000000000000000000000000000000000000000..c6a394919724600f0b9e67f6f6ac17c2c8fdee69
--- /dev/null
+++ b/game/modules/tome/data/zones/arena/objects.lua
@@ -0,0 +1,301 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010 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
+
+load("/data/general/objects/objects.lua")
+local Talents = require "engine.interface.ActorTalents"
+
+newEntity{ base = "BASE_LORE",
+	define_as = "ARENA_SCORING",
+	name = "Arena for dummies", lore="arena-scoring",
+	desc = [[A note explaining the arena's scoring rules. Someone must have dropped it.]],
+	rarity = false,
+	is_magic_device = false,
+	encumberance = 0,
+}
+
+
+-- Id stuff
+newEntity{ define_as = "ORB_KNOWLEDGE",
+	unique = true, quest=true,
+	type = "jewelry", subtype="orb",
+	unided_name = "orb", no_unique_lore = true,
+	name = "Orb of Knowledge", identified = true,
+	display = "*", color=colors.VIOLET, image = "object/ruby.png",
+	encumber = 1,
+	desc = [[This orb was given to you by Elisa the halfling scryer, it will automatically identify normal and rare items for you and can be activated to identify all others.]],
+
+	on_drop = function(self, who)
+		if who == game.player then
+			game.logPlayer(who, "You cannot bring yourself to drop the %s", self:getName())
+			return true
+		end
+	end,
+
+	max_power = 1, power_regen = 1,
+	use_power = { name = "use the orb", power = 1,
+		use = function(self, who)
+			for inven_id, inven in pairs(who.inven) do
+				for item, o in ipairs(inven) do
+					if not o:isIdentified() then
+						o:identify(true)
+						game.logPlayer(who, "You have: %s", o:getName{do_colour=true})
+					end
+				end
+			end
+		end
+	},
+
+	carrier = {
+		auto_id_mundane = 1,
+	},
+}
+
+newEntity{
+	define_as = "ARENA_BOOTS_DISE",
+	slot = "FEET",
+	type = "armor", subtype="feet",
+	add_name = " (#ARMOR#)",
+	display = "]", color=colors.UMBER, image = resolvers.image_material("boots", "leather"),
+	encumber = 2,
+	desc = [[A pair of boots made of leather. They seem to be of exceptional quality.]],
+	name = "a pair of leather boots of disengagement", suffix=true, instant_resolve=true,
+	egoed = true,
+	greater_ego = true,
+	identified = true,
+	rarity = false,
+	cost = 0,
+	material_level = 1,
+	wielder = {
+		combat_armor = 2,
+		fatigue = 1,
+	},
+	max_power = 20, power_regen = 1,
+	use_talent = { id = Talents.T_DISENGAGE, level = 2, power = 10 },
+}
+
+newEntity{
+	define_as = "ARENA_BOOTS_PHAS",
+	slot = "FEET",
+	type = "armor", subtype="feet",
+	add_name = " (#ARMOR#)",
+	display = "]", color=colors.UMBER, image = resolvers.image_material("boots", "leather"),
+	encumber = 2,
+	desc = [[A pair of boots made of leather. They seem to be of exceptional quality.]],
+	name = "a pair of leather boots of phasing", suffix=true, instant_resolve=true,
+	egoed = true,
+	greater_ego = true,
+	identified = true,
+	cost = 0,
+	rarity = false,
+	material_level = 1,
+	wielder = {
+		combat_armor = 2,
+		fatigue = 1,
+	},
+	max_power = 25, power_regen = 1,
+	use_power = { name = "blink to a nearby random location", power = 15, use = function(self, who)
+		game.level.map:particleEmitter(who.x, who.y, 1, "teleport")
+		who:teleportRandom(who.x, who.y, 10 + who:getMag(5))
+		game.level.map:particleEmitter(who.x, who.y, 1, "teleport")
+		game:playSoundNear(who, "talents/teleport")
+		game.logSeen(who, "%s uses %s!", who.name:capitalize(), self:getName{no_count=true})
+		return nil, true
+	end}
+}
+
+newEntity{
+	define_as = "ARENA_BOOTS_RUSH",
+	slot = "FEET",
+	type = "armor", subtype="feet",
+	add_name = " (#ARMOR#)",
+	display = "]", color=colors.UMBER, image = resolvers.image_material("boots", "leather"),
+	encumber = 2,
+	desc = [[A pair of boots made of leather. They seem to be of exceptional quality.]],
+	name = "a pair of leather boots of rushing", suffix=true, instant_resolve=true,
+	egoed = true,
+	rarity = false,
+	greater_ego = true,
+	identified = true,
+	cost = 0,
+	material_level = 1,
+	wielder = {
+		combat_armor = 2,
+		fatigue = 1,
+	},
+	max_power = 20, power_regen = 1,
+	use_talent = { id = Talents.T_RUSH, level = 2, power = 10 },
+}
+
+newEntity{
+	define_as = "ARENA_DEBUG_CANNON",
+	slot = "MAINHAND",
+	slot_forbid = "OFFHAND",
+	type = "weapon", subtype="cannon",
+	name = "debug cannon",
+	display = "}", color=colors.BLUE,
+	encumber = 4,
+	egoed = true,
+	unique = true,
+	greater_ego = true,
+	identified = true,
+	max_power = 20, power_regen = 1,
+	cost = 0,
+	material_level = 1,
+	rarity = 9999999999999,
+	metallic = true,
+	twohanded = true,
+	combat = { talented = "bow", sound = "actions/arrow", sound_miss = "actions/arrow",},
+	archery = "bow",
+	combat = {
+		range = 16,
+		physspeed = 1,
+		talented = "mace",
+		dam = resolvers.rngavg(22,30),
+		apr = 2,
+		physcrit = 1,
+		dammod = {str=1.2},
+		damrange = 1.5,
+		sound = "actions/melee",
+		sound_miss = "actions/melee_miss",
+	},
+	basic_ammo = {
+		dam = 3000,
+		apr = 5000,
+		physcrit = 10,
+		dammod = {wil = 2},
+	},
+	wielder = {
+		ranged_project={
+			[DamageType.LIGHTNING] = 3000,
+			[DamageType.LIGHT] = 3000,
+		},
+		fatigue = 1,
+	},
+	desc = [[A powerful weapon from another world. It operates on a graviton engine.]],
+	use_talent = { id = Talents.T_GRAVITY_SPIKE, level = 6, power = 10 },
+}
+
+newEntity{
+	define_as = "ARENA_DEBUG_ARMOR",
+	slot = "BODY",
+	type = "armor", subtype="mechanic",
+	add_name = " (#ARMOR#)",
+	display = "[", color=colors.SLATE, image = resolvers.image_material("plate", "metal"),
+	unique = true,
+	name = "Full frame",
+	unided_name = "Strange armor",
+	desc = [[A powered armor from another world. Worn by fighters facing unstable dimensional fields.]],
+	color = colors.BLACK,
+	metallic = true,
+	rarity = 99999999999,
+	cost = 250,
+	material_level = 3,
+	max_power = 20, power_regen = 1,
+	wielder = {
+		combat_armor = 120,
+		combat_def = 120,
+		combat_def_ranged = 120,
+		max_encumber = 300,
+		life_regen = 1000,
+		stamina_regen = 20,
+		fatigue = 0,
+		max_stamina = 500,
+		max_life = 3000,
+		knockback_immune = 1,
+		stun_immune = 1,
+		size_category = 2,
+	},
+	use_talent = { id = Talents.T_TWILIGHT_SURGE, level = 99, power = 10 },
+}
+
+
+newEntity{
+	define_as = "ARENA_BOOTS_LSPEED",
+	slot = "FEET",
+	type = "armor", subtype="feet",
+	add_name = " (#ARMOR#)",
+	display = "]", color=colors.UMBER, image = resolvers.image_material("boots", "leather"),
+	encumber = 2,
+	desc = [[A pair of boots made of leather. They seem to be of exceptional quality.]],
+	name = "a pair of leather boots of lightning speed", suffix=true, instant_resolve=true,
+	egoed = true,
+	greater_ego = true,
+	identified = true,
+	rarity = false,
+	cost = 0,
+	material_level = 1,
+	wielder = {
+		combat_armor = 2,
+		fatigue = 1,
+	},
+	max_power = 20, power_regen = 1,
+	use_talent = { id = Talents.T_LIGHTNING_SPEED, level = 2, power = 10 },
+}
+
+newEntity{
+	define_as = "ARENA_BOW",
+	base = "BASE_LONGBOW",
+	name = "elm longbow of steady shot",
+	level_range = {1, 10},
+	require = { stat = { dex=11 }, },
+	rarity = false,
+	egoed = true,
+	greater_ego = true,
+	identified = true,
+	cost = 0,
+	material_level = 1,
+	use_talent = { id = Talents.T_STEADY_SHOT, level = 2, power = 10 },
+	max_power = 15, power_regen = 1,
+	combat = {
+		range = 8,
+		physspeed = 0.8,
+	},
+	basic_ammo = {
+		dam = 12,
+		apr = 5,
+		physcrit = 1,
+		dammod = {dex=0.7, str=0.5},
+	},
+}
+
+newEntity{
+	define_as = "ARENA_SLING",
+	base = "BASE_SLING",
+	name = "rough leather sling of flare",
+	level_range = {1, 10},
+	require = { stat = { dex=11 }, },
+	rarity = false,
+	egoed = true,
+	greater_ego = true,
+	identified = true,
+	cost = 0,
+	material_level = 1,
+	use_talent = { id = Talents.T_FLARE, level = 2, power = 15 },
+	max_power = 15, power_regen = 1,
+	combat = {
+		range = 8,
+		physspeed = 0.8,
+	},
+	basic_ammo = {
+		dam = 12,
+		apr = 1,
+		physcrit = 4,
+		dammod = {dex=0.7, cun=0.5},
+	},
+}
diff --git a/game/modules/tome/data/zones/arena/traps.lua b/game/modules/tome/data/zones/arena/traps.lua
new file mode 100644
index 0000000000000000000000000000000000000000..f8f844f583d30b1999a9bf7a520221cdebdfa557
--- /dev/null
+++ b/game/modules/tome/data/zones/arena/traps.lua
@@ -0,0 +1,20 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010 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
+
+load("/data/general/traps/elemental.lua")
diff --git a/game/modules/tome/data/zones/arena/zone.lua b/game/modules/tome/data/zones/arena/zone.lua
new file mode 100644
index 0000000000000000000000000000000000000000..0fc62a0fb9d8cf90b1c30b724dc871484212c32a
--- /dev/null
+++ b/game/modules/tome/data/zones/arena/zone.lua
@@ -0,0 +1,436 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010 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 = "The Arena",
+	level_range = {1, 50},
+	level_scheme = "player",
+	max_level = 1,
+	actor_adjust_level = function(zone, level, e) return game.player.level + rng.range(-2, 2) end,
+	width = 15, height = 15,
+	all_remembered = true,
+	all_lited = true,
+	no_worldport = true,
+	--ambiant_music = "a_lomos_del_dragon_blanco.ogg",
+
+	generator =  {
+		map = {
+			class = "engine.generator.map.Static",
+			map = "zones/arena",
+			zoom = 4,
+		},
+		actor = { },
+		object = { },
+		trap = { },
+
+	},
+
+
+	on_turn = function(self)
+		if game.turn % 10 ~= 0 or game.level.arena.event == 4 then return end
+		game.level.arena.checkPinch()
+		require("mod.class.generator.actor.Arena").new(self, game.level.map, game.level, {}):tick()
+		if game.level.turn_counter then
+			if game.level.turn_counter > 0 then game.level.turn_counter = game.level.turn_counter - 10
+			else
+				--Clear up items and do gold bonus if applicable.
+				--The wave starts at this point.
+				game.level.turn_counter = nil
+				if game.level.arena.event == 1 then game.log("#GOLD#Miniboss round starts!!")
+				elseif game.level.arena.event == 2 then game.log("#VIOLET#Boss round starts!!!")
+				elseif game.level.arena.event == 3 then game.log("#LIGHT_RED#Final round starts!!!!")
+				end
+				game.level.arena.removeStuff()
+				if game.player.money > 0 then
+					game.level.arena.goldToScore()
+				end
+				game.level.arena.openGates()
+			end
+		end
+		if game.level.arena.bonus > 0 then game.level.arena.bonus = game.level.arena.bonus - 10  end
+		if game.level.arena.delay > 0 then game.level.arena.delay = game.level.arena.delay - 1  end
+		--Only raise danger level while you can raise bonus multiplier.
+		if game.level.arena.dangerMod < 1.5 and game.level.arena.pinch == false
+		and game.level.arena.delay  <= 0 and not game.level.turn_counter then
+			game.level.arena.dangerMod = game.level.arena.dangerMod + 0.02
+		end
+		--Reset kill counter
+		if game.level.arena.kills > 0 then
+			game.level.arena.checkCombo(game.level.arena.kills)
+			game.level.arena.totalKills = game.level.arena.totalKills + game.level.arena.kills
+		 end
+		game.level.arena.kills = 0
+	end,
+
+
+	post_process = function(level)
+		game.player.money = 0
+		game.player.no_resurrect = true
+		game.player.on_die = function (self, src)
+			local rank = math.floor(game.level.arena.rank)
+			local drank
+			if rank < 0 then drank = "Master of Arena" else drank = game.level.arena.ranks[rank] or "nobody" end
+			local lastScore = {
+				name = game.player.name.." the "..drank,
+				score = game.level.arena.score,
+				perk = game.level.arena.perk,
+				wave = game.level.arena.currentWave,
+				sex = game.player.descriptor.sex,
+				race = game.player.descriptor.subrace,
+				class = game.player.descriptor.subclass,
+			}
+			game.level.arena.updateScores(lastScore)
+		end
+
+		--Allow players to shoot bows and stuff by default. Move it back to perks if too powerful.
+		game.player:learnTalent(game.player.T_SHOOT, true)
+		game.player.changed = true
+		level.turn_counter = 50 --5 turns before action starts.
+		--world.arena = nil
+		if not world.arena or not world.arena.ver then
+			local emptyScore = {name = nil, score = 0, perk = nil, wave = 1, sex = nil, race = nil, class = nil}
+			world.arena = {
+				master30 = nil,
+				master60 = nil,
+				lastScore = emptyScore,
+				bestWave = 1,
+				ver = 1
+			}
+			world.arena.scores = {[1] = emptyScore}
+			local o = game.zone:makeEntityByName(game.level, "object", "ARENA_SCORING")
+			if o then game.zone:addEntity(game.level, o, "object", 7, 3) end
+		end
+		level.arena = {
+			ranks = { "nobody", "rat stomper", "aspirant", "fighter", "brave", "powerful", "promise", "rising star", "destroyer", "obliterator", "annihilator", "grandious", "glorious", "victorious", "ultimate", "ultimate", "ultimate", "ultimate", "ultimate", "grand master" },
+			rank = 1,
+			perk = nil,
+			event = 0,
+			initEvent = false,
+			lockEvent = false,
+			display = nil,
+			kills = 0,
+			totalKills = 0,
+			currentWave = 1,
+			eventWave = 5,
+			finalWave = 61,
+			modeString = "60",
+			danger = 0,
+			dangerTop = 12,
+			dangerMod = 0,
+			score = 0,
+			delay = 0,
+			pinch = false,
+			pinchValue = 0,
+			bonus = 0,
+			clearItems = false,
+			bonusMultiplier = 1,
+			bonusMin = 1,
+			entry = {
+				--The physical doors
+				door = {
+					max = 5,
+					function () return 0, 0 end,
+					function () return 0, 14 end,
+					function () return 14, 0 end,
+					function () return 14, 14 end,
+					function () return 7, 0 end
+				},
+				--Main gate
+				main = {
+					max = 4,
+					function () return 7, 0 end,
+					function () return 7, 1 end,
+					function () return 8, 1 end,
+					function () return 6, 1 end
+				},
+				--Corner gates
+				corner = {
+					max = 12,
+					function () return 1, 1 end,
+					function () return 2, 1 end,
+					function () return 1, 2 end,
+
+					function () return 13, 13 end,
+					function () return 12, 13 end,
+					function () return 13, 12 end,
+
+					function () return 1, 13 end,
+					function () return 2, 13 end,
+					function () return 1, 12 end,
+
+					function () return 13, 1 end,
+					function () return 12, 1 end,
+					function () return 13, 2 end,
+				},
+				--Crystal gates
+				crystal = {
+					max = 8,
+					function () return 4, 2 end,
+					function () return 10, 2 end,
+					function () return 10, 12 end,
+					function () return 4, 12 end,
+
+					function () return 1, 4 end,
+					function () return 12, 4 end,
+					function () return 1, 10 end,
+					function () return 12, 10 end,
+				}
+			},
+			clear = function()
+				game.player:setQuestStatus("arena", engine.Quest.COMPLETED)
+				local master = game.player:cloneFull()
+				game.level.arena.rank = -1
+				game.player:die(game.player)
+				master.version = game.__mod_info.version
+				master.no_drops = true
+				master.energy.value = 0
+				master.player = nil
+				master.rank = 5
+				master.color_r = 255
+				master.color_g = 0
+				master.color_b = 255
+				master._mo:invalidate()
+				master.ai = "dumb_talented_simple"
+				master.ai_state = {talent_in=1}
+				master.faction="enemies"
+				master.life = master.max_life
+				-- Remove some talents
+				local tids = {}
+				for tid, _ in pairs(master.talents) do
+					local t = master:getTalentFromId(tid)
+					if t.no_npc_use then tids[#tids+1] = t end
+				end
+				game.level.arena.event = 4
+				if game.level.arena.finalWave > 60 then
+					world:gainAchievement("MASTER_OF_ARENA", game.player)
+					world.arena.master60 = master
+				else
+					world:gainAchievement("ALMOST_MASTER_OF_ARENA", game.player)
+					world.arena.master30 = master
+				end
+			end,
+			printRankings = function (val)
+				local scores = world.arena.scores
+				if not scores[1].name then return "#LIGHT_GREEN#...but it's been wiped out recently."
+				else
+					local text = ""
+					local tmp = ""
+					local line = function (txt, col) return " "..col..txt.."\n" end
+					local stri = "%s (%s %s %s)\n Score %d[%s]) - Wave: %d"
+					local i = 1
+					while(scores[i] and scores[i].name) do
+						p = scores[i]
+						tmp = stri:format(p.name:capitalize(), p.sex, p.race, p.class, p.score, p.perk, p.wave)
+						text = text..line(tmp, "#LIGHT_BLUE#")
+						i = i + 1
+					end
+					p = world.arena.lastScore
+					tmp = "\n#YELLOW#LAST:"..stri:format(p.name:capitalize(), p.sex, p.race, p.class, p.score, p.perk, p.wave)
+					return text..line(tmp, "#YELLOW#")
+				end
+			end,
+			printRank = function (r, ranks)
+				local rank = math.floor(r)
+				if rank > #ranks then rank = #ranks end
+				return ranks[rank]
+			end,
+			updateScores = function(l)
+				local scores = world.arena.scores
+				table.insert(scores, l)
+				table.sort(scores, function(a,b) return a.score > b.score end)
+				if #scores > 10 then table.remove(scores) end
+				world.arena.scores = scores
+				if l.wave > world.arena.bestWave then world.arena.bestWave = l.wave end
+				world.arena.lastScore = l
+			end,
+			openGates = function()
+				local gates = game.level.arena.entry.door
+				local g = game.zone:makeEntityByName(game.level, "terrain", "FLOOR")
+				local x, y = 0, 0
+				for i = 1, gates.max do
+					x, y = gates[i]()
+					game.zone:addEntity(game.level, g, "terrain", x, y)
+				end
+				game:playSoundNear(game.player, "talents/earth")
+				game.log("#LIGHT_GREEN#The gates open!")
+			end,
+			closeGates = function()
+				local gates = game.level.arena.entry.door
+				local g = game.zone:makeEntityByName(game.level, "terrain", "LOCK")
+				local x, y = 0, 0
+				for i = 1, gates.max do
+					x, y = gates[i]()
+					game.zone:addEntity(game.level, g, "terrain", x, y)
+					game.level.map:particleEmitter(x, y, 0.5, "arena_gate")
+				end
+				game:playSoundNear(game.player, "talents/earth")
+				game.log("#LIGHT_RED#The gates close!")
+			end,
+			raiseRank = function (val)
+				if game.level.arena.rank >= 20 then return end
+				local currentRank = math.floor(game.level.arena.rank)
+				game.level.arena.rank = game.level.arena.rank + val
+				local newRank = math.floor(game.level.arena.rank)
+				if currentRank < newRank then --Player's rank increases!
+					local x, y = game.level.map:getTileToScreen(game.player.x, game.player.y)
+					if rank == 9 then world:gainAchievement("XXX_THE_DESTROYER", game.player)
+					elseif rank == 20 then world:gainAchievement("GRAND_MASTER", game.player)
+					end
+					game.flyers:add(x, y, 90, 0, -0.5, "RANK UP!!", { 2, 57, 185 }, false)
+					game.log("#LIGHT_GREEN#The public is pleased by your performance! You now have the rank of #WHITE#"..game.level.arena.ranks[newRank].."!")
+				end
+			end,
+			checkCombo = function (k)
+				if k >= 10 then world:gainAchievement("TEN_AT_ONE_BLOW", game.player) end
+				if k > 2 then
+					local x, y = game.level.map:getTileToScreen(game.player.x, game.player.y)
+					local b = k * 0.035
+					game.level.arena.raiseRank(b)
+					game.flyers:add(x, y, 90, 0, -0.5, k.." kills!", { 2, 57, 185 }, false)
+					game.log("#YELLOW#You killed "..k.." enemies in a single turn! The public is excited!")
+				else return
+				end
+			end,
+			addTrap = function ()
+				local g = game.zone:makeEntity(game.level, "trap", nil, nil, true)
+				local d = game.level.arena.currentWave
+				g.dam = 5 + (d * 2) + rng.range(d, d * 1.5)
+				game.zone:addEntity(game.level, g, "trap", 7, 7)
+				g:setKnown(game.player, true)
+				game.level.map:updateMap(7, 7)
+				game.level.map:particleEmitter(7, 7, 0.3, "demon_teleport")
+				if d > 1 then game.log("#YELLOW#The trap changes...") end
+			end,
+			goldToScore = function ()
+				local x, y = game.level.map:getTileToScreen(game.player.x, game.player.y)
+				local goldAward = game.player.money * 100
+				local healthAward = game.player.money * 10
+				local regStamina = goldAward * 0.5
+				game.level.arena.score = game.level.arena.score + goldAward
+				game.flyers:add(x, y, 90, 0, -0.6, "GOLD BONUS! +"..goldAward.." SCORE!", { 2, 57, 185 }, false)
+				game.log("#ROYAL_BLUE#Gold bonus! Score increased by #WHITE#"..goldAward.."#ROYAL_BLUE#! #LIGHT_GREEN#You also recover some health(#WHITE#+"..healthAward.."#LIGHT_GREEN#!)#LAST#")
+				if game.player:knowTalent(game.player.T_STAMINA_POOL) then
+					game.player:incStamina(regStamina)
+					game.log("#LIGHT_GREEN#Stamina(#WHITE#+"..regStamina.."#LIGHT_GREEN#)")
+				end
+				game.player.money = 0
+				game.player:heal(healthAward)
+				game.player.changed = true
+			end,
+			initWave = function (val) --Clean up and start a new wave.
+				if val > 20 then --If the player has more than 20 turns of rest, clean up all items lying around.
+					game.level.arena.clearItems = true
+					game.log("#YELLOW#Items lying around will disappear in #WHITE#"..val.."#YELLOW# turns!#LAST#")
+				end
+				game.level.arena.dangerTop = game.level.arena.dangerTop + (2 + math.floor(game.level.arena.currentWave * 0.05))
+				game.level.arena.currentWave = game.level.arena.currentWave + 1
+				game.level.arena.dangerMod = 0.7 + (game.level.arena.currentWave * 0.005)
+				game.level.arena.bonus = 0
+				game.level.level = game.level.arena.currentWave
+				game.level.arena.bonusMultiplier = game.level.arena.bonusMin
+				game.level.arena.pinchValue = 0
+				game.level.arena.pinch = false
+				if game.level.arena.display then game.level.arena.display = nil end
+				if game.level.arena.currentWave % game.level.arena.eventWave == 0 then
+					if game.level.arena.currentWave % (game.level.arena.eventWave * 3) == 0 then --Boss round!
+						game.log("#VIOLET#Boss round!!!")
+						game.level.arena.event = 2
+					else --Miniboss round!
+						game.log("#GOLD#Miniboss round!")
+						game.level.arena.event = 1
+					end
+				elseif game.level.arena.currentWave == game.level.arena.finalWave then --Final round!
+					game.level.arena.event = 3
+					game.log("#LIGHT_RED#Final round!!!")
+				else --Regular stuff.
+					game.level.arena.event = 0
+				end
+				game.level.arena.initEvent = false
+				game.level.arena.lockEvent = false
+				game.level.arena.addTrap()
+				if game.level.arena.currentWave == 21 then world:gainAchievement("ARENA_BATTLER_20", game.player)
+				elseif game.level.arena.currentWave == 51 then world:gainAchievement("ARENA_BATTLER_50", game.player)
+				end
+			end,
+			removeStuff = function ()
+				for i = 0, game.level.map.w - 1 do
+					for j = 0, game.level.map.h - 1 do
+						local nb = game.level.map:getObjectTotal(i, j)
+						for z = nb, 1, -1 do game.level.map:removeObject(i, j, z) end
+					end
+				end
+			end,
+			doReward = function (val)
+				local col = "#ROYAL_BLUE#"
+				local hgh = "#WHITE#"
+				local dangerBonus = val * 0.5
+				local scoreBonus = game.level.arena.bonus * 0.2
+				local clearBonus = math.ceil(game.level.arena.currentWave ^ 1.85)
+				local rankBonus = math.floor(game.level.arena.rank) * 20
+				local expAward = (dangerBonus + scoreBonus + clearBonus + rankBonus) * game.level.arena.bonusMultiplier
+				local x, y = game.level.map:getTileToScreen(game.player.x, game.player.y)
+				game.player:gainExp(expAward)
+				game.level.arena.score = game.level.arena.score + game.level.arena.bonus
+				game.flyers:add(x, y, 90, 0, -1, "Round Clear! +"..expAward.." EXP!", { 2, 57, 185 }, true)
+				game.log(col.."Wave clear!")
+				game.log(col.."Clear bonus: "..hgh..clearBonus..col.."! Score bonus: "..hgh..scoreBonus..col.."! Danger bonus: "..hgh..dangerBonus..col.."! Rank bonus: "..hgh..rankBonus..col.."!")
+				game.log(col.."Your experience increases by"..hgh..expAward..col.."!")
+				game.player.changed = true
+			end,
+			clearRound = function () --Relax and give rewards.
+				--Do rewarding.
+				local val = game.level.arena.pinchValue
+				local plvl = game.player.level
+				game.level.arena.doReward(val)
+				--Set rest time.
+				local rest_time = val
+				if not plvl == game.player.level then --If bonuses made the player level up, give minimal time.
+					if rest_time > 30 then rest_time = 30 end
+				else
+					if rest_time < 10 then rest_time = 10
+					elseif rest_time > 80 then rest_time = 80
+					end
+				end
+				game.level.turn_counter = rest_time * 10
+				game.level.arena.initWave(val)
+			end,
+			checkPinch = function ()
+				if game.level.arena.danger > game.level.arena.dangerTop and game.level.arena.pinch == false then --The player is in a pinch!
+					if game.level.arena.danger - game.level.arena.dangerTop < 10 then return end --Ignore minimal excess of power.
+					game.level.arena.pinch = true
+					game.level.arena.pinchValue = game.level.arena.danger - game.level.arena.dangerTop
+					game.level.arena.bonus = (game.level.arena.pinchValue * 20) + 200
+					game.level.arena.closeGates()
+				elseif game.level.arena.danger <= 0 and game.level.arena.pinch == true then --The player cleared the round.
+					if game.level.arena.event == 0 then
+						game.level.arena.clearRound()
+					elseif game.level.arena.lockEvent == false then --Call minibosses or boss next turn.
+						game.level.arena.initEvent = true
+					else --Round is clear
+						game.level.arena.clearRound()
+					end
+				end
+			end,
+		}
+		local Chat = require "engine.Chat"
+		local chat = Chat.new("arena-start", {name="Arena mode"}, game.player, {text = level.arena.printRankings()})
+		chat:invoke()
+		game.level.arena.addTrap()
+	end
+}
diff --git a/game/modules/tome/data/zones/town-derth/grids.lua b/game/modules/tome/data/zones/town-derth/grids.lua
index 54f3736d46e0bba482e647af43c7aaa074715a66..20a179e9e456b10acbf6950202f771c7d599c075 100644
--- a/game/modules/tome/data/zones/town-derth/grids.lua
+++ b/game/modules/tome/data/zones/town-derth/grids.lua
@@ -17,3 +17,9 @@
 -- Nicolas Casalini "DarkGod"
 -- darkgod@te4.org
 
+newEntity{
+	define_as = "GRASS",
+	name = "grass", image = "terrain/grass.png",
+	display = '.', color=colors.LIGHT_GREEN, back_color={r=44,g=95,b=43},
+	grow = "TREE",
+}
\ No newline at end of file
diff --git a/game/modules/tome/dialogs/ArenaFinish.lua b/game/modules/tome/dialogs/ArenaFinish.lua
new file mode 100644
index 0000000000000000000000000000000000000000..8b9ff8d2ff0cc202adc685b413218d53316fda29
--- /dev/null
+++ b/game/modules/tome/dialogs/ArenaFinish.lua
@@ -0,0 +1,162 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010 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
+
+require "engine.class"
+local Dialog = require "engine.ui.Dialog"
+local Textzone = require "engine.ui.Textzone"
+local Separator = require "engine.ui.Separator"
+local List = require "engine.ui.List"
+local Savefile = require "engine.Savefile"
+local Map = require "engine.Map"
+
+module(..., package.seeall, class.inherit(Dialog))
+
+function _M:init(actor)
+	self.actor = actor
+	Dialog.init(self, "Arena mode", 500, 300)
+
+	actor:saveUUID()
+
+	self:generateList()
+
+	self.c_desc = Textzone.new{width=self.iw, auto_height=true, text=self:printRanking() }
+	self.c_list = List.new{width=self.iw, nb_items=#self.list, list=self.list, fct=function(item) self:use(item) end}
+
+	self:loadUI{
+		{left=0, top=0, ui=self.c_desc},
+		{left=5, top=self.c_desc.h, padding_h=10, ui=Separator.new{dir="vertical", size=self.iw - 10}},
+		{left=0, bottom=0, ui=self.c_list},
+	}
+	self:setFocus(self.c_list)
+	self:setupUI(false, true)
+end
+
+function _M:printRanking()
+	local scores = world.arena.scores
+	if not scores[1].name then return "#LIGHT_GREEN#No high scores. This should not happen."
+	else
+		local text = ""
+		local tmp = ""
+		local line = function (txt, col) return " "..col..txt.."\n" end
+		local stri = "%s (%s %s %s)\n Score %d[%s]) - Wave: %d"
+		local i = 1
+		while(scores[i] and scores[i].name) do
+			p = scores[i]
+			tmp = stri:format(p.name:capitalize(), p.sex, p.race, p.class, p.score, p.perk, p.wave)
+			if p.name == world.arena.lastScore.name and p.score == world.arena.lastScore.score and
+			p.wave == world.arena.lastScore.wave and p.perk == world.arena.lastScore.perk then
+				text = text..line(tmp, "#YELLOW#")
+			else
+				text = text..line(tmp, "#LIGHT_BLUE#")
+			end
+			i = i + 1
+		end
+	return text
+	end
+end
+
+--- Clean the actor from debuffs/buffs
+function _M:cleanActor(actor)
+	local effs = {}
+
+	-- Go through all spell effects
+	for eff_id, p in pairs(actor.tmp) do
+		local e = actor.tempeffect_def[eff_id]
+		effs[#effs+1] = {"effect", eff_id}
+	end
+
+	-- Go through all sustained spells
+	for tid, act in pairs(actor.sustain_talents) do
+		if act then
+			effs[#effs+1] = {"talent", tid}
+		end
+	end
+
+	while #effs > 0 do
+		local eff = rng.tableRemove(effs)
+
+		if eff[1] == "effect" then
+			actor:removeEffect(eff[2])
+		else
+			actor:forceUseTalent(eff[2], {ignore_energy=true})
+		end
+	end
+end
+
+--- Restore resources
+function _M:restoreResources(actor)
+	if actor.resetToFull then
+		actor:resetToFull()
+		actor.energy.value = game.energy_to_act
+	end
+end
+
+--- Basic resurrection
+function _M:resurrectBasic(actor)
+	actor.dead = false
+	actor.died = (actor.died or 0) + 1
+
+	local x, y = util.findFreeGrid(actor.x, actor.y, 20, true, {[Map.ACTOR]=true})
+	if not x then x, y = actor.x, actor.y end
+	actor.x, actor.y = nil, nil
+
+	actor:move(x, y, true)
+	game.level:addEntity(actor)
+	game:unregisterDialog(self)
+	game.level.map:redisplay()
+	actor.energy.value = game.energy_to_act
+	actor.changed = true
+	game.paused = true
+end
+
+function _M:use(item)
+	if not item then return end
+	local act = item.action
+
+	if act == "exit" then
+		local save = Savefile.new(game.save_name)
+		save:delete()
+		save:close()
+		world:saveWorld()
+		if item.subaction == "none" then
+			util.showMainMenu()
+		elseif item.subaction == "restart" then
+			util.showMainMenu(false, engine.version[4], engine.version[1].."."..engine.version[2].."."..engine.version[3], game.__mod_info.short_name, game.save_name, true, "auto_quickbirth=true")
+		end
+	elseif act == "cheat" then
+		game.logPlayer(self.actor, "#LIGHT_BLUE#You resurrect! CHEATER !")
+
+		self:cleanActor(self.actor)
+		self:restoreResources(self.actor)
+		self:resurrectBasic(self.actor)
+	elseif act == "dump" then
+		game:registerDialog(require("mod.dialogs.CharacterSheet").new(self.actor))
+	end
+end
+
+function _M:generateList()
+	local list = {}
+
+	if config.settings.cheat then list[#list+1] = {name="Resurrect by cheating", action="cheat"} end
+	list[#list+1] = {name="Character dump", action="dump"}
+	list[#list+1] = {name="Restart the same character", action="exit", subaction="restart"}
+	list[#list+1] = {name="Exit to main menu", action="exit", subaction="none"}
+
+	self.list = list
+end