diff --git a/game/engines/default/engine/Quadratic.lua b/game/engines/default/engine/Quadratic.lua
new file mode 100644
index 0000000000000000000000000000000000000000..21e2b79bb6b478e7aaa5e337bb5305c0961c1204
--- /dev/null
+++ b/game/engines/default/engine/Quadratic.lua
@@ -0,0 +1,44 @@
+-- TE4 - T-Engine 4
+-- Copyright (C) 2009, 2010, 2011 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"
+
+--- Handles a 3D "quadratic" object
+-- It's mostly undeed, it simply allows quadratic to be serialized
+module(..., package.seeall, class.make)
+
+--- Make a particle emitter
+function _M:init()
+	self:loaded()
+end
+
+--- Serialization
+function _M:save()
+	return class.save(self, {
+		q = true,
+	})
+end
+
+function _M:cloned()
+	self:loaded()
+end
+
+function _M:loaded()
+	self.q = core.display.newQuadratic()
+end
diff --git a/game/modules/tome/data/damage_types.lua b/game/modules/tome/data/damage_types.lua
index 27658af4bf0c67fad3f7a1d2c205645cdfe68af1..f7cf458980ed5f95db86dc355a7b2ac2b0ceb42b 100644
--- a/game/modules/tome/data/damage_types.lua
+++ b/game/modules/tome/data/damage_types.lua
@@ -1421,3 +1421,20 @@ newDamageType{
 		end
 	end,
 }
+
+newDamageType{
+	name = "manaworm", type = "MANAWORM",
+	projector = function(src, x, y, type, dam)
+		local realdam = DamageType:get(DamageType.ARCANE).projector(src, x, y, DamageType.ARCANE, dam)
+		local target = game.level.map(x, y, Map.ACTOR)
+		if target then
+			if target:knowTalent(target.T_MANA_POOL) then
+				target:setEffect(target.EFF_MANAWORM, 5, {power=dam * 5, src=src})
+				src:disappear(src)
+			else
+				game.logSeen(target, "%s is unaffected.", target.name:capitalize())
+			end
+		end
+		return realdam
+	end,
+}
diff --git a/game/modules/tome/data/general/grids/void.lua b/game/modules/tome/data/general/grids/void.lua
index 2a139ea61b3a7141b393002a1df279d005a54168..0faf977a0dc1899a24d491372c502ee556036b0a 100644
--- a/game/modules/tome/data/general/grids/void.lua
+++ b/game/modules/tome/data/general/grids/void.lua
@@ -39,6 +39,7 @@ newEntity{
 	pass_projectile = true,
 	air_level = -40,
 	is_void = true,
+	can_pass = {pass_void=1},
 }
 
 newEntity{
diff --git a/game/modules/tome/data/general/npcs/losgoroth.lua b/game/modules/tome/data/general/npcs/losgoroth.lua
new file mode 100644
index 0000000000000000000000000000000000000000..8034614202b4d5a3f01611a215667338d7c964bb
--- /dev/null
+++ b/game/modules/tome/data/general/npcs/losgoroth.lua
@@ -0,0 +1,75 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010, 2011 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{
+	define_as = "BASE_NPC_LOSGOROTH", -- lost goroth = void terror
+	type = "elemental", subtype = "void",
+	blood_color = colors.DARK_GREY,
+	display = "E", color=colors.DARK_GREY,
+	desc = [[Losgoroth are mighty void elementals, native to the void between the stars, they are rarely seen on the planet's surface.]],
+
+	combat = { dam=resolvers.levelup(resolvers.mbonus(40, 15), 1, 1.2), atk=15, apr=15, dammod={mag=0.8}, damtype=DamageType.ARCANE },
+
+	body = { INVEN = 10, MAINHAND=1, OFFHAND=1, BODY=1 },
+
+	infravision = 10,
+	life_rating = 8,
+	rank = 2,
+	size_category = 3,
+	levitation = 1,
+
+	autolevel = "dexmage",
+	ai = "dumb_talented_simple", ai_state = { ai_move="move_dmap", talent_in=2, },
+	stats = { str=10, dex=8, mag=6, con=16 },
+
+	resists = { [DamageType.PHYSICAL] = -30, [DamageType.ARCANE] = 100 },
+
+	no_breath = 1,
+	poison_immune = 1,
+	disease_immune = 1,
+}
+
+newEntity{ base = "BASE_NPC_LOSGOROTH",
+	name = "losgoroth", color=colors.GREY,
+	level_range = {1, nil}, exp_worth = 1,
+	rarity = 1,
+	max_life = resolvers.rngavg(70,80),
+	combat_armor = 0, combat_def = 20,
+	on_melee_hit = { [DamageType.ARCANE] = resolvers.mbonus(20, 10), },
+
+	resolvers.talents{
+		[Talents.T_VOID_BLAST]={base=1, every=7, max=7},
+		[Talents.T_PHASE_DOOR]=2,
+	},
+}
+
+newEntity{ base = "BASE_NPC_LOSGOROTH",
+	name = "manaworm", color=colors.BLUE,
+	level_range = {2, nil}, exp_worth = 1,
+	desc = [[Manaworms are losgoroth which feed of the mana of arcane users. If they ever come in melee contact with a spellcaster they latch onto him and start draining their mana away.]],
+	rarity = 3,
+	max_life = resolvers.rngavg(40,60),
+	movement_speed = 0.7,
+	combat_armor = 0, combat_def = 20,
+	on_melee_hit = { [DamageType.ARCANE] = resolvers.mbonus(20, 10), },
+	can_pass = {pass_void=70},
+	combat = { atk=10000, apr=10000, damtype=DamageType.MANAWORM }, -- They can not miss
+}
diff --git a/game/modules/tome/data/gfx/particles/bolt_void.lua b/game/modules/tome/data/gfx/particles/bolt_void.lua
new file mode 100644
index 0000000000000000000000000000000000000000..1954e2e433b4446ca4829c15252fa321a2c15087
--- /dev/null
+++ b/game/modules/tome/data/gfx/particles/bolt_void.lua
@@ -0,0 +1,52 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010, 2011 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 { generator = function()
+	local radius = 0
+	local sradius = (radius + 0.5) * (engine.Map.tile_w + engine.Map.tile_h) / 2
+	local ad = rng.float(0, 360)
+	local a = math.rad(ad)
+	local r = rng.float(0, sradius / 4)
+	local x = r * math.cos(a)
+	local y = r * math.sin(a)
+	local bx = math.floor(x / engine.Map.tile_w)
+	local by = math.floor(y / engine.Map.tile_h)
+	local static = rng.percent(40)
+	local c = rng.range(40, 100)/255
+
+	return {
+		trail = 1,
+		life = 6,
+		size = 3, sizev = 0, sizea = 0,
+
+		x = x, xv = 0, xa = 0,
+		y = y, yv = 0, ya = 0,
+		dir = a, dirv = 0, dira = 0,
+		vel = sradius / 2 / 6, velv = 0, vela = 0,
+
+		r = c,   rv = 0, ra = 0,
+		g = c,   gv = 0.005, ga = 0.0005,
+		b = c,      bv = 0, ba = 0,
+		a = rng.range(140, 255)/255,    av = static and -0.034 or 0, aa = 0.005,
+	}
+end, },
+function(self)
+	self.ps:emit(30)
+end,
+30*6
diff --git a/game/modules/tome/data/gfx/particles/image.lua b/game/modules/tome/data/gfx/particles/image.lua
index 50cc75d15050056287536afca1461f8dedd62fbb..b1005d7632285b03246454135024944da6656ed9 100644
--- a/game/modules/tome/data/gfx/particles/image.lua
+++ b/game/modules/tome/data/gfx/particles/image.lua
@@ -26,7 +26,7 @@ local a = 1
 
 return { generator = function()
 	return {
-		life = 10,
+		life = 1,
 		size = size, sizev = 0, sizea = 0,
 
 		x = x, xv = 0, xa = 0,
diff --git a/game/modules/tome/data/gfx/particles/voidblast.lua b/game/modules/tome/data/gfx/particles/voidblast.lua
new file mode 100644
index 0000000000000000000000000000000000000000..cfb9808b08d98233d078d82275c4ad7e4f97fb84
--- /dev/null
+++ b/game/modules/tome/data/gfx/particles/voidblast.lua
@@ -0,0 +1,42 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010, 2011 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
+
+base_size = 32
+
+return {
+	base = 1000,
+
+	angle = { 0, 360 }, anglev = { 2000, 4000 }, anglea = { 20, 60 },
+
+	life = { 5, 10 },
+	size = { 4, 6 }, sizev = {0, 0}, sizea = {0, 0},
+
+	r = {80, 140}, rv = {0, 10}, ra = {0, 0},
+	g = {80, 140}, gv = {0, 0}, ga = {0, 0},
+	b = {80, 140}, bv = {0, 10}, ba = {0, 0},
+	a = {180, 255}, av = {0, 0}, aa = {0, 0},
+
+}, function(self)
+	self.nb = (self.nb or 0) + 1
+	if self.nb < 6 then
+		self.ps:emit(20)
+	end
+end,
+600,
+"particle_torus"
diff --git a/game/modules/tome/data/gfx/particles/voidtrail.lua b/game/modules/tome/data/gfx/particles/voidtrail.lua
new file mode 100644
index 0000000000000000000000000000000000000000..ce2059fa474031de848922abdf7a12e7e117b231
--- /dev/null
+++ b/game/modules/tome/data/gfx/particles/voidtrail.lua
@@ -0,0 +1,56 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010, 2011 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 nb = 0
+
+return { generator = function()
+	local radius = 0
+	local sradius = (radius + 0.5) * (engine.Map.tile_w + engine.Map.tile_h) / 2
+	local ad = rng.float(0, 360)
+	local a = math.rad(ad)
+	local r = rng.float(0.1, sradius / 2)
+	local x = r * math.cos(a)
+	local y = r * math.sin(a)
+	local bx = math.floor(x / engine.Map.tile_w)
+	local by = math.floor(y / engine.Map.tile_h)
+	local static = rng.percent(40)
+
+	return {
+		trail = 1,
+		life = 3 + 9 * (sradius - r) / sradius,
+		size = 3, sizev = 0, sizea = 0,
+
+		x = x, xv = 0, xa = 0,
+		y = y, yv = 0, ya = 0,
+		dir = 0, dirv = 0, dira = 0,
+		vel = 0, velv = 0, vela = 0,
+
+		r = rng.range(80, 140)/255,   rv = 0, ra = 0,
+		g = rng.range(80, 140)/255,   gv = 0.005, ga = 0.0005,
+		b = rng.range(80, 140)/255,      bv = 0, ba = 0,
+		a = rng.range(140, 255)/255,    av = static and -0.034 or 0, aa = 0.005,
+	}
+end, },
+function(self)
+	if nb < 1 then
+		self.ps:emit(40)
+	end
+	nb = nb + 1
+end,
+40
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/eyal-world.png b/game/modules/tome/data/gfx/shockbolt/terrain/eyal-world.png
new file mode 100644
index 0000000000000000000000000000000000000000..5d855b7892abc958bdfca270fbe43fcdda573834
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/eyal-world.png differ
diff --git a/game/modules/tome/data/talents/misc/npcs.lua b/game/modules/tome/data/talents/misc/npcs.lua
index 57613993fb3e43bd76e121cc25451481e667bad1..89e36613308bc12026b46cc2835c3bde98566efc 100644
--- a/game/modules/tome/data/talents/misc/npcs.lua
+++ b/game/modules/tome/data/talents/misc/npcs.lua
@@ -540,6 +540,32 @@ newTalent{
 	end,
 }
 
+newTalent{
+	name = "Void Blast",
+	type = {"spell/other", },
+	points = 5,
+	mana = 3,
+	cooldown = 2,
+	tactical = { ATTACK = 7 },
+	range = 10,
+	reflectable = true,
+	requires_target = true,
+	proj_speed = 2,
+	target = function(self, t) return {type="bolt", range=self:getTalentRange(t), talent=t, display={particle="bolt_void", trail="voidtrail"}} end,
+	action = function(self, t)
+		local tg = self:getTalentTarget(t)
+		local x, y = self:getTarget(tg)
+		if not x or not y then return nil end
+		self:projectile(tg, x, y, DamageType.ARCANE, self:spellCrit(self:combatTalentSpellDamage(t, 15, 240)), {type="voidblast"})
+		game:playSoundNear(self, "talents/arcane")
+		return true
+	end,
+	info = function(self, t)
+		return ([[Fires a blast of void energies that slowly travel to their target, dealing %0.2f% arcane damage on impact.
+		The damage will increase with the Magic stat]]):format(damDesc(self, DamageType.ARCANE, self:combatTalentSpellDamage(t, 15, 240)))
+	end,
+}
+
 newTalent{
 	name = "Restoration",
 	type = {"spell/other", 1},
diff --git a/game/modules/tome/data/talents/spells/aegis.lua b/game/modules/tome/data/talents/spells/aegis.lua
index ea63e18d515187cbb66a2aecece5770a096b4d3d..b799be8c96f1fbaf1a4021a6b0b7930f01c13a66 100644
--- a/game/modules/tome/data/talents/spells/aegis.lua
+++ b/game/modules/tome/data/talents/spells/aegis.lua
@@ -26,7 +26,7 @@ newTalent{
 	mana = 25,
 	cooldown = 16,
 	tactical = { HEAL = 2 },
-	getHeal = function(self, t) return 40 + self:combatTalentSpellDamage(t, 140, 520) end,
+	getHeal = function(self, t) return 40 + self:combatTalentSpellDamage(t, 10, 520) end,
 	action = function(self, t)
 		self:heal(self:spellCrit(t.getHeal(self, t)), self)
 		game:playSoundNear(self, "talents/heal")
diff --git a/game/modules/tome/data/timed_effects.lua b/game/modules/tome/data/timed_effects.lua
index 45e7dd38b6ed5011fd7e7edb3d3573e7b8a9b851..cded0c8c2dbb47796bbb51d993a37130b0098623 100644
--- a/game/modules/tome/data/timed_effects.lua
+++ b/game/modules/tome/data/timed_effects.lua
@@ -4092,3 +4092,21 @@ newEffect{
 	deactivate = function(self, eff)
 	end,
 }
+
+newEffect{
+	name = "MANAWORM",
+	desc = "Manaworm",
+	long_desc = function(self, eff) return ("The target is infected by a manaworm, draining %0.2f mana per turns and releasing it as arcane damage to the target."):format(eff.power) end,
+	type = "magical",
+	status = "detrimental",
+	parameters = {power=10},
+	on_gain = function(self, err) return "#Target# is infected by a manaworm!", "+Manaworm" end,
+	on_lose = function(self, err) return "#Target# is no longer infected.", "-Manaworm" end,
+	on_timeout = function(self, eff)
+		local dam = eff.power
+		if dam > self:getMana() then dam = self:getMana() end
+		self:incMana(-dam)
+		DamageType:get(DamageType.ARCANE).projector(eff.src, self.x, self.y, DamageType.ARCANE, dam)
+	end,
+}
+
diff --git a/game/modules/tome/data/zones/abashed-expanse/npcs.lua b/game/modules/tome/data/zones/abashed-expanse/npcs.lua
index 5efb16ed70d88ecc3f7111daf99ccac47593f85d..f4abf83ce9e2af55add3023d85075ddfae6da635 100644
--- a/game/modules/tome/data/zones/abashed-expanse/npcs.lua
+++ b/game/modules/tome/data/zones/abashed-expanse/npcs.lua
@@ -21,18 +21,18 @@
 --load("/data/general/npcs/vermin.lua", rarity(2))
 --load("/data/general/npcs/snake.lua", rarity(3))
 --load("/data/general/npcs/bear.lua", rarity(2))
-load("/data/general/npcs/crystal.lua", rarity(1))
+--load("/data/general/npcs/crystal.lua", rarity(10))
+load("/data/general/npcs/losgoroth.lua", rarity(1))
 
 --load("/data/general/npcs/all.lua", rarity(4, 35))
 
 local Talents = require("engine.interface.ActorTalents")
 
-newEntity{ base="BASE_NPC_CRYSTAL", define_as = "SPELLBLAZE_CRYSTAL",
-	allow_infinite_dungeon = true,
+newEntity{ base="BASE_NPC_LOSGOROTH", define_as = "SPACIAL_DISTURBANCE",
 	unique = true,
-	name = "Spellblaze Crystal", tint=colors.PURPLE, image = "npc/spellblaze_crystal.png",
+	name = "Spacial Disturbance",
 	color=colors.VIOLET,
-	desc = [[A formation of purple crystal. It seems strangely aware.]],
+	desc = [[A hole in the fabric of space, it seems to be the source of hte expanse unstability.]],
 	level_range = {7, nil}, exp_worth = 2,
 	max_life = 150, life_rating = 12, fixed_rating = true,
 	mana_regen = 3,
diff --git a/game/modules/tome/data/zones/abashed-expanse/zone.lua b/game/modules/tome/data/zones/abashed-expanse/zone.lua
index d3d39fc487750db48e06802609a3ea49dface714..9caa5dd12cbe5e7e60daae0d79849f6213051258 100644
--- a/game/modules/tome/data/zones/abashed-expanse/zone.lua
+++ b/game/modules/tome/data/zones/abashed-expanse/zone.lua
@@ -41,28 +41,24 @@ return {
 			no_tunnels = true,
 			rooms = {"space_tree_pod"},
 			['.'] = "FLOATING_ROCKS",
---			['T'] = {"TREE","TREE2","TREE3","TREE4","TREE5","TREE6","TREE7","TREE8","TREE9","TREE10","TREE11","TREE12","TREE13","TREE14","TREE15","TREE16","TREE17","TREE18","TREE19","TREE20",},
---			['.'] = {"BURNT_GROUND1","BURNT_GROUND2","BURNT_GROUND3","BURNT_GROUND4",},
 			['T'] = {"BURNT_TREE1","BURNT_TREE2","BURNT_TREE3","BURNT_TREE4","BURNT_TREE5","BURNT_TREE6","BURNT_TREE7","BURNT_TREE8","BURNT_TREE9","BURNT_TREE10","BURNT_TREE11","BURNT_TREE12","BURNT_TREE13","BURNT_TREE14","BURNT_TREE15","BURNT_TREE16","BURNT_TREE17","BURNT_TREE18","BURNT_TREE19","BURNT_TREE20",},
 			['#'] = "OUTERSPACE",
---			up = "GRASS",
---			down = "GRASS",
 			wormhole = "WORMHOLE",
 			door = "GRASS",
 		},
 		actor = {
 			class = "engine.generator.actor.Random",
-			nb_npc = {10, 15},
+			nb_npc = {20, 30},
 			filters = { {max_ood=2}, },
 			guardian = "SPACIAL_DISTURBANCE",
 		},
 		object = {
 			class = "engine.generator.object.Random",
-			nb_object = {6, 9},
+			nb_object = {0, 0},
 		},
 		trap = {
 			class = "engine.generator.trap.Random",
-			nb_trap = {6, 9},
+			nb_trap = {0, 0},
 		},
 	},
 
@@ -73,13 +69,13 @@ return {
 		if game.turn % 10 ~= 0 or not game.level.data.teleport_zones then return end
 		game.level.data.next_move = game.level.data.next_move - 1
 		if game.level.data.next_move <= 0 then
-			game.level.data.next_move = rng.range(3, 7)
+			game.level.data.next_move = 1
 
 			local void = game.zone.grid_list.OUTERSPACE
 			local map = game.level.map
 			local pods = table.clone(game.level.pods)
 
-			for __ = 1, 10 do
+			for __ = 1, 1 do
 			local pod = rng.tableRemove(pods)
 --			print("====== MOVING POD", table.serialize(pod,nil,true))
 			local x, y = pod.x1, pod.y1
@@ -218,9 +214,12 @@ return {
 
 	post_process = function(level)
 		local Map = require "engine.Map"
+		local Quadratic = require "engine.Quadratic"
 		level.background_particle1 = require("engine.Particles").new("starfield_static", 1, {width=Map.viewport.width, height=Map.viewport.height, nb=300, a_min=0.5, a_max = 0.8, size_min = 1, size_max = 3})
 		level.background_particle2 = require("engine.Particles").new("starfield_static", 1, {width=Map.viewport.width, height=Map.viewport.height, nb=300, a_min=0.5, a_max = 0.9, size_min = 4, size_max = 8})
-		level.world_particle = require("engine.Particles").new("image", 1, {size=512, image="shockbolt/terrain/eyal-world", x=400, y=400})
+		level.world_particle = require("engine.Particles").new("image", 1, {size=1, image="shockbolt/terrain/eyal-world", x=400, y=400})
+		level.world_sphere = Quadratic.new()
+		game.zone.world_sphere_rot = (game.zone.world_sphere_rot or 0)
 	end,
 
 	background = function(level, x, y, nb_keyframes)
@@ -229,5 +228,14 @@ return {
 		local parx, pary = level.map.mx / (level.map.w - Map.viewport.mwidth), level.map.my / (level.map.h - Map.viewport.mheight)
 		level.background_particle2.ps:toScreen(x - parx * 40, y - pary * 40, true, 1)
 		level.world_particle.ps:toScreen(x - parx * 60, y - pary * 60, true, 1)
+
+		core.display.glMatrix(true)
+		core.display.glTranslate(x + 350 - parx * 60, y + 350 - pary * 60, 0)
+		core.display.glRotate(120, 0, 1, 0)
+		core.display.glRotate(300, 1, 0, 0)
+		level.world_sphere.q:sphere(0, 0, 300, game.zone.world_sphere_rot, 0, 0, 1)
+		game.zone.world_sphere_rot = game.zone.world_sphere_rot + 0.01
+
+		core.display.glMatrix(false)
 	end,
 }
diff --git a/game/modules/tome/data/zones/maze/npcs.lua b/game/modules/tome/data/zones/maze/npcs.lua
index 6301fcadc96bb6214b405f532e8b8feecd47ed3d..596166a8b55e9ca896bcd65779e44b46b9eb2c30 100644
--- a/game/modules/tome/data/zones/maze/npcs.lua
+++ b/game/modules/tome/data/zones/maze/npcs.lua
@@ -95,7 +95,7 @@ newEntity{ base = "BASE_NPC_SPIDER", define_as = "NIMISIL",
 
 	combat_armor = 25, combat_def = 33,
 
-	combat = {dam=80, atk=30, apr=15, dammod={mag=1.1}, damtype="ARCANE"},
+	combat = {dam=80, atk=30, apr=15, dammod={mag=1.1}, damtype=DamageType.ARCANE},
 
 	autolevel = "caster",
 	ai = "tactical", ai_state = { talent_in=1, ai_move="move_astar", },
diff --git a/game/modules/tome/data/zones/temporal-rift/npcs.lua b/game/modules/tome/data/zones/temporal-rift/npcs.lua
index 1f87ecebbd325f224ea50183e8afda0b027ddbd6..b4375b8832d3a32d7c26c41f156f8f41e4994cc0 100644
--- a/game/modules/tome/data/zones/temporal-rift/npcs.lua
+++ b/game/modules/tome/data/zones/temporal-rift/npcs.lua
@@ -32,7 +32,7 @@ newEntity{ define_as = "BEN_CRUTHDAR_ABOMINATION",
 	max_stamina = 85,
 	stats = { str=20, dex=15, wil=18, con=20 },
 	rank = 3.5,
-	size_category = 2,
+	size_category = 3,
 	infravision = 10,
 	instakill_immune = 1,
 	move_others=true,
diff --git a/game/modules/tome/data/zones/town-lumberjack-village/npcs.lua b/game/modules/tome/data/zones/town-lumberjack-village/npcs.lua
index e27d8c1a1eccd3ec6b4b2339035b25b7ff728ba8..266f7868d6fc77451408e3b4bca4dfe72c4ed196 100644
--- a/game/modules/tome/data/zones/town-lumberjack-village/npcs.lua
+++ b/game/modules/tome/data/zones/town-lumberjack-village/npcs.lua
@@ -31,7 +31,7 @@ A gloomy aura emanates from him.]],
 	max_stamina = 85,
 	stats = { str=20, dex=15, wil=18, con=20 },
 	rank = 4,
-	size_category = 2,
+	size_category = 3,
 	infravision = 10,
 	instakill_immune = 1,
 	move_others=true,
diff --git a/src/core_lua.c b/src/core_lua.c
index 6515a50cb8ec631b251b6dcecae1d12f3d77759f..a18d68a86d5591e487cd049a3984570c5f5b7d6d 100644
--- a/src/core_lua.c
+++ b/src/core_lua.c
@@ -1295,6 +1295,19 @@ static int gl_translate(lua_State *L)
 	return 0;
 }
 
+static int gl_rotate(lua_State *L)
+{
+	glRotatef(lua_tonumber(L, 1), lua_tonumber(L, 2), lua_tonumber(L, 3), lua_tonumber(L, 4));
+	return 0;
+}
+
+static int gl_matrix(lua_State *L)
+{
+	if (lua_toboolean(L, 1)) glPushMatrix();
+	else glPopMatrix();
+	return 0;
+}
+
 static int sdl_texture_bind(lua_State *L)
 {
 	GLuint *t = (GLuint*)auxiliar_checkclass(L, "gl{texture}", 1);
@@ -1522,6 +1535,55 @@ static int sdl_set_mouse_cursor(lua_State *L)
 	return 0;
 }
 
+/**************************************************************
+ * Quadratic Objects
+ **************************************************************/
+static int gl_new_quadratic(lua_State *L)
+{
+	GLUquadricObj **quadratic = (GLUquadricObj**)lua_newuserdata(L, sizeof(GLUquadricObj*));
+	auxiliar_setclass(L, "gl{quadratic}", -1);
+
+	*quadratic = gluNewQuadric( );
+	gluQuadricNormals(*quadratic, GLU_SMOOTH);
+	gluQuadricTexture(*quadratic, GL_TRUE);
+
+	return 1;
+}
+
+static int gl_free_quadratic(lua_State *L)
+{
+	GLUquadricObj **quadratic = (GLUquadricObj**)auxiliar_checkclass(L, "gl{quadratic}", 1);
+
+	gluDeleteQuadric(*quadratic);
+
+	lua_pushnumber(L, 1);
+	return 1;
+}
+
+static int gl_quadratic_sphere(lua_State *L)
+{
+	GLUquadricObj **quadratic = (GLUquadricObj**)auxiliar_checkclass(L, "gl{quadratic}", 1);
+	float x = luaL_checknumber(L, 2);
+	float y = luaL_checknumber(L, 3);
+	float rad = luaL_checknumber(L, 4);
+	float rot = luaL_checknumber(L, 5);
+	float rot_x = luaL_checknumber(L, 6);
+	float rot_y = luaL_checknumber(L, 7);
+	float rot_z = luaL_checknumber(L, 8);
+
+	glPushMatrix();
+	glTranslatef(x, y, 0);
+	glRotatef(rot, rot_x, rot_y, rot_z);
+
+	glEnable(GL_DEPTH_TEST);
+	gluSphere(*quadratic, rad, 64, 64);
+	glDisable(GL_DEPTH_TEST);
+
+	glPopMatrix();
+
+	return 0;
+}
+
 /**************************************************************
  * Framebuffer Objects
  **************************************************************/
@@ -1596,7 +1658,7 @@ static int gl_fbo_use(lua_State *L)
 		glMatrixMode(GL_PROJECTION);
 		glPushMatrix();
 		glLoadIdentity();
-		glOrtho(0, fbo->w, fbo->h, 0, -101, 101);
+		glOrtho(0, fbo->w, fbo->h, 0, -1001, 1001);
 		glMatrixMode(GL_MODELVIEW);
 
 		// Reset The View
@@ -1786,6 +1848,7 @@ static const struct luaL_reg displaylib[] =
 	{"newSurface", sdl_new_surface},
 	{"newTile", sdl_new_tile},
 	{"newFBO", gl_new_fbo},
+	{"newQuadratic", gl_new_quadratic},
 	{"drawQuad", gl_draw_quad},
 	{"FBOActive", gl_fbo_is_active},
 	{"disableFBO", gl_fbo_disable},
@@ -1799,6 +1862,8 @@ static const struct luaL_reg displaylib[] =
 	{"setGamma", sdl_set_gamma},
 	{"glTranslate", gl_translate},
 	{"glScale", gl_scale},
+	{"glRotate", gl_rotate},
+	{"glMatrix", gl_matrix},
 	{NULL, NULL},
 };
 
@@ -1853,6 +1918,13 @@ static const struct luaL_reg gl_fbo_reg[] =
 	{NULL, NULL},
 };
 
+static const struct luaL_reg gl_quadratic_reg[] =
+{
+	{"__gc", gl_free_quadratic},
+	{"sphere", gl_quadratic_sphere},
+	{NULL, NULL},
+};
+
 /******************************************************************
  ******************************************************************
  *                              RNG                               *
@@ -2310,6 +2382,7 @@ int luaopen_core(lua_State *L)
 	auxiliar_newclass(L, "line{core}", line_reg);
 	auxiliar_newclass(L, "gl{texture}", sdl_texture_reg);
 	auxiliar_newclass(L, "gl{fbo}", gl_fbo_reg);
+	auxiliar_newclass(L, "gl{quadratic}", gl_quadratic_reg);
 	auxiliar_newclass(L, "sdl{surface}", sdl_surface_reg);
 	auxiliar_newclass(L, "sdl{font}", sdl_font_reg);
 	luaL_openlib(L, "core.display", displaylib, 0);
diff --git a/src/main.c b/src/main.c
index 1be80c14f35d10191708fa0a1b46daa4da6cc3d7..ce19df14dfa199bd78b7ea6eb08933a10cc68c82 100644
--- a/src/main.c
+++ b/src/main.c
@@ -637,7 +637,7 @@ int resizeWindow(int width, int height)
 
 	/* Set our perspective */
 	//gluPerspective( 45.0f, ratio, 0.1f, 100.0f );
-	glOrtho(0, width, height, 0, -101, 101);
+	glOrtho(0, width, height, 0, -1001, 1001);
 
 	/* Make sure we're chaning the model view and not the projection */
 	glMatrixMode( GL_MODELVIEW );