diff --git a/game/engine/Actor.lua b/game/engine/Actor.lua
index f929906f1319c94d1e81638aff0b5451715da103..722248b006033bc14dec659eb9c965bc7a5aab7b 100644
--- a/game/engine/Actor.lua
+++ b/game/engine/Actor.lua
@@ -160,3 +160,24 @@ function _M:removeTemporaryValue(prop, id, noupdate)
 		end
 	end
 end
+
+--- Increases/decreases an attribute
+-- The attributes are just actor properties, but this ensures they are numbers and not booleans
+-- thus making them compatible with temporary values system
+-- @param prop the property to use
+-- @param v the value to add, if nil this the function return
+-- @param fix forces the value to v, do not add
+-- @return nil if v was specified. If not then it returns the current value if it exists and is not 0 otherwise returns nil
+function _M:attr(prop, v, fix)
+	if v then
+		if fix then self.prop = v
+		else self.prop = (self.prop or 0) + v
+		end
+	else
+		if self.prop and self.prop ~= 0 then
+			return self.prop
+		else
+			return nil
+		end
+	end
+end
diff --git a/game/engine/interface/ActorTalents.lua b/game/engine/interface/ActorTalents.lua
index 97a8b3750e4bad2e790fdfad44dac288e2732e18..dd4b6c5042fd7de265ed09e1975565a0aed14da9 100644
--- a/game/engine/interface/ActorTalents.lua
+++ b/game/engine/interface/ActorTalents.lua
@@ -14,6 +14,7 @@ function _M:loadDefinition(file)
 	setfenv(f, setmetatable({
 		DamageType = require("engine.DamageType"),
 		Talents = self,
+		Map = require("engine.Map"),
 		newTalent = function(t) self:newTalent(t) end,
 		newTalentType = function(t) self:newTalentType(t) end,
 		load = function(f) self:loadDefinition(f) end
diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua
index f47ee59f9723e9541f2e8afce9df1e177d406988..389188e70325ffeb7209dac5f9eb6d6163869c98 100644
--- a/game/modules/tome/class/Actor.lua
+++ b/game/modules/tome/class/Actor.lua
@@ -73,13 +73,31 @@ end
 function _M:move(x, y, force)
 	local moved = false
 	if force or self:enoughEnergy() then
-		moved = engine.Actor.move(self, game.level.map, x, y, force)
+		-- Should we prob travel through walls ?
+		if not force and self:attr("prob_travel") and game.level.map:checkEntity(x, y, Map.TERRAIN, "block_move", self) then
+			moved = self:probabilityTravel(x, y)
+		else
+			moved = engine.Actor.move(self, game.level.map, x, y, force)
+		end
 		if not force and moved and not self.did_energy then self:useEnergy() end
 	end
 	self.did_energy = nil
 	return moved
 end
 
+function _M:probabilityTravel(x, y)
+	local dirx, diry = x - self.x, y - self.y
+	local tx, ty = x, y
+	while game.level.map:checkEntity(x, y, Map.TERRAIN, "block_move", self) do
+		tx = tx + dirx
+		ty = ty + diry
+	end
+	if game.level.map:isBound(x, y) then
+		return engine.Actor.move(self, game.level.map, tx, ty, false)
+	end
+	return true
+end
+
 function _M:tooltip()
 	return ("%s\n#00ffff#Level: %d\nExp: %d/%d\n#ff0000#HP: %d"):format(self.name, self.level, self.exp, self:getExpChart(self.level+1) or "---", self.life)
 end
diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua
index 49d917776a488c46b07a5ec14c3297a15b67f939..72cd7bdfc6c4b4461fbd22af63b8a52039728776 100644
--- a/game/modules/tome/class/Player.lua
+++ b/game/modules/tome/class/Player.lua
@@ -89,7 +89,10 @@ function _M:getTarget(typ)
 	if coroutine.running() then
 		local msg
 		if type(typ) == "string" then msg, typ = typ, nil
-		elseif type(typ) == "table" then msg = typ.msg end
+		elseif type(typ) == "table" then
+			if typ.default_target then self.target.target.entity = typ.default_target end
+			msg = typ.msg
+		end
 		game:targetMode("exclusive", msg, coroutine.running(), typ)
 		return coroutine.yield()
 	end
diff --git a/game/modules/tome/data/talents/spells/arcane.lua b/game/modules/tome/data/talents/spells/arcane.lua
index 6488b3ac8d9e710e02c3359df390962f8c18ffb4..f03b6cde583833fe027a36862fe2737c2d677fb6 100644
--- a/game/modules/tome/data/talents/spells/arcane.lua
+++ b/game/modules/tome/data/talents/spells/arcane.lua
@@ -75,7 +75,8 @@ newTalent{
 	tactical = {
 		DEFEND = 10,
 	},
-	action = function(self)
+	activate = function(self)
+		game.log("IMPLEMENT ME!")
 		return true
 	end,
 	require = { stat = { mag=60 }, level=40 },
diff --git a/game/modules/tome/data/talents/spells/conveyance.lua b/game/modules/tome/data/talents/spells/conveyance.lua
index 67bf132628bcfebeb1294271fb3167f5789b6d35..0521bf433ef6259e0b996efc5a0fa4e7d04c6b4f 100644
--- a/game/modules/tome/data/talents/spells/conveyance.lua
+++ b/game/modules/tome/data/talents/spells/conveyance.lua
@@ -2,26 +2,35 @@ newTalent{
 	name = "Phase Door",
 	type = {"spell/conveyance",1},
 	message = "@Source@ blinks.",
-	mana = 15,
-	cooldown = 9,
+	mana = 10,
+	cooldown = 8,
 	tactical = {
 		ESCAPE = 4,
 	},
 	action = function(self)
+		local target = self
+
+		if self:knowTalent(Talents.T_TARGETED_TELEPORT) then
+			local tx, ty = self:getTarget{default_target=self, type="hit", range=10}
+			if tx and ty then
+				target = game.level.map(tx, ty, Map.ACTOR) or self
+			end
+		end
+
 		local x, y = self.x, self.y
-		if self:knowTalent(self.T_TELEPORT_CONTROL) then
-			x, y = self:getTarget{type="ball", range=10 + self:combatSpellpower(0.1), radius=5 - self:combatSpellpower(0.04)}
+		if self:knowTalent(Talents.T_CONTROLLED_TELEPORT) then
+			x, y = self:getTarget{type="ball", range=10 + self:combatSpellpower(0.1), radius=5 - self:combatSpellpower(0.03)}
 			if not x then return nil end
 			-- Target code doesnot restrict the target coordinates to the range, it lets the poject function do it
 			-- but we cant ...
 			x, y = game.target:pointAtRange(self.x, self.y, x, y, 10 + self:combatSpellpower(0.1))
-			self:teleportRandom(x, y, 5 - self:combatSpellpower(0.4))
+			target:teleportRandom(x, y, 5 - self:combatSpellpower(0.03))
 		else
-			self:teleportRandom(x, y, 10 + self:combatSpellpower(0.1))
+			target:teleportRandom(x, y, 10 + self:combatSpellpower(0.1))
 		end
 		return true
 	end,
-	require = { stat = { mag=12 }, },
+	require = { stat = { mag=15 }, },
 	info = function(self)
 		return ([[Teleports you randomly on a small scale range (%d)
 		The range will increase with the Magic stat]]):format(10 + self:combatSpellpower(0.1))
@@ -29,12 +38,133 @@ newTalent{
 }
 
 newTalent{
-	name = "Teleport Control",
+	name = "Teleport",
 	type = {"spell/conveyance",2},
+	message = "@Source@ teleports away.",
+	mana = 20,
+	cooldown = 30,
+	tactical = {
+		ESCAPE = 8,
+	},
+	action = function(self)
+		local target = self
+
+		if self:knowTalent(Talents.T_TARGETED_TELEPORT) then
+			local tx, ty = self:getTarget{default_target=self, type="hit", range=10}
+			if tx and ty then
+				target = game.level.map(tx, ty, Map.ACTOR) or self
+			end
+		end
+
+		local x, y = self.x, self.y
+		if self:knowTalent(Talents.T_CONTROLLED_TELEPORT) then
+			x, y = self:getTarget{type="ball", range=100 + self:combatSpellpower(1), radius=5 - self:combatSpellpower(0.03)}
+			if not x then return nil end
+			-- Target code doesnot restrict the target coordinates to the range, it lets the poject function do it
+			-- but we cant ...
+			x, y = game.target:pointAtRange(self.x, self.y, x, y, 10 + self:combatSpellpower(0.1))
+			target:teleportRandom(x, y, 5 - self:combatSpellpower(0.03))
+		else
+			target:teleportRandom(x, y, 100 + self:combatSpellpower(1))
+		end
+		return true
+	end,
+	require = { stat = { mag=24 }, },
+	info = function(self)
+		return ([[Teleports you randomly on a small scale range (%d)
+		The range will increase with the Magic stat]]):format(10 + self:combatSpellpower(0.1))
+	end,
+}
+
+newTalent{
+	name = "Controlled Teleport",
+	type = {"spell/conveyance",4},
 	mode = "passive",
-	require = { stat = { mag=38 }, },
+	points = 2,
+	require = { stat = { mag=50 }, talent = {Talents.T_TELEPORT}, },
 	info = function(self)
 		return ([[Allows teleport spells to specify a target area. You will blink in this radius randomly.
-		The radius (%d) of the target area decreases with Magic stat]]):format(5 - self:combatSpellpower(0.04))
+		The radius (%d) of the target area decreases with Magic stat]]):format(5 - self:combatSpellpower(0.03))
+	end,
+}
+
+newTalent{
+	name = "Targeted Teleport",
+	type = {"spell/conveyance",4},
+	mode = "passive",
+	require = { stat = { mag=50 }, talent = {Talents.T_TELEPORT}, },
+	info = function(self)
+		return ([[Allows teleport spells to specify the affected target, either you, allies or foes.]])
+	end,
+}
+
+newTalent{
+	name = "Probability Travel",
+	type = {"spell/conveyance",4},
+	mode = "sustained",
+	points = 2,
+	cooldown = 40,
+	sustain_mana = 100,
+	tactical = {
+		MOVEMENT = 20,
+	},
+	activate = function(self)
+		self:attr("prob_travel", 1)
+		return true
+	end,
+	deactivate = function(self)
+		self:attr("prob_travel", -1)
+		return true
+	end,
+	require = { stat = { mag=34 }, level=25 },
+	info = function(self)
+		return ([[When you hit a solid surface this spell tears down the laws of probability to make you instantly appear on the other side.]])
+	end,
+}
+
+newTalent{
+	name = "Recall",
+	type = {"spell/conveyance",3},
+	mana = 30,
+	cooldown = 10,
+	action = function(self)
+--[[
+		local target = self
+		local tx, ty = self.x, self.y
+		if self:knowTalent(Talents.T_TELEKINESIS) or self:knowTalent(Talents.T_IMPERIOUS_SUMMON) then
+			local tx, ty = self:getTarget{default_target=self, type="hit", range=20}
+			if tx and ty then
+				target = game.level.map(tx, ty, Map.ACTOR) or self
+			end
+		end
+
+		if
+]]
+		game.log("IMPLEMENT ME!")
+		return true
+	end,
+	require = { stat = { mag=34 }, },
+	info = function(self)
+		return ([[Recalls you to your home town after a few turns.]])
+	end,
+}
+
+newTalent{
+	name = "Telekinesis",
+	type = {"spell/conveyance",4},
+	mode = "passive",
+	require = { stat = { mag=50 }, },
+	info = function(self)
+		return ([[Recall can now target an object on the floor to teleport it to your inventory.]])
+	end,
+}
+
+newTalent{
+	name = "Imperious Summon",
+	type = {"spell/conveyance",4},
+	mode = "passive",
+	require = { stat = { mag=50 }, },
+	info = function(self)
+		return ([[Recall can now target your foes to teleport one to you.]])
 	end,
 }
diff --git a/game/modules/tome/dialogs/LevelupTalentsDialog.lua b/game/modules/tome/dialogs/LevelupTalentsDialog.lua
index 1b9e4365eed52cde4096a751fcb30a703e52ae45..703c84a81abb2061d2860fd1f3738de92ff28942 100644
--- a/game/modules/tome/dialogs/LevelupTalentsDialog.lua
+++ b/game/modules/tome/dialogs/LevelupTalentsDialog.lua
@@ -72,33 +72,34 @@ function _M:learn(v)
 	end
 end
 
-function _M:learnTalent(t, v)
+function _M:learnTalent(t_id, v)
+	local t = self.actor:getTalentFromId(t_id)
 	if v then
-		if self.actor.unused_talents == 0 then
+		if self.actor.unused_talents < t.points then
 			self:simplePopup("Not enough talent points", "You have no talent points left!")
 			return
 		end
-		if not self.actor:canLearnTalent(self.actor:getTalentFromId(t)) then
+		if not self.actor:canLearnTalent(t_id) then
 			self:simplePopup("Cannot learn talent", "Prerequisites not met!")
 			return
 		end
-		if self.actor:knowTalent(t) then
+		if self.actor:knowTalent(t_id) then
 			self:simplePopup("Already known", "You already know this talent!")
 			return
 		end
-		self.actor:learnTalent(t)
-		self.actor.unused_talents = self.actor.unused_talents - 1
+		self.actor:learnTalent(t_id)
+		self.actor.unused_talents = self.actor.unused_talents - t.points
 	else
-		if not self.actor:knowTalent(t) then
+		if not self.actor:knowTalent(t_id) then
 			self:simplePopup("Impossible", "You do not know this talent!")
 			return
 		end
-		if self.actor_dup:knowTalent(t) == true and self.actor:knowTalent(t) == true then
+		if self.actor_dup:knowTalent(t_id) == true and self.actor:knowTalent(t_id) == true then
 			self:simplePopup("Impossible", "You cannot unlearn talents!")
 			return
 		end
-		self.actor:unlearnTalent(t)
-		self.actor.unused_talents = self.actor.unused_talents + 1
+		self.actor:unlearnTalent(t_id)
+		self.actor.unused_talents = self.actor.unused_talents + t.points
 	end
 	self:generateList()
 end
diff --git a/ideas/spells.ods b/ideas/spells.ods
index a22b916ca97ee085129ef648f50cc729f1b905ec..50cbe18f0563d209e2a0278ea440b3985bc8152e 100644
Binary files a/ideas/spells.ods and b/ideas/spells.ods differ
diff --git a/ideas/technics.ods b/ideas/technics.ods
index d6fa0c2aef929095e960d39c6d46ca464242e0dc..f3a7128754c0681497303e156ad55b5ed837fff5 100644
Binary files a/ideas/technics.ods and b/ideas/technics.ods differ