diff --git a/game/engine/Actor.lua b/game/engine/Actor.lua
index 812635a84bff6c4c7a6363399dab61c2efd933b1..3c5b499ace3eb34c397743c31c0ef50b7ee2caf0 100644
--- a/game/engine/Actor.lua
+++ b/game/engine/Actor.lua
@@ -270,6 +270,22 @@ function _M:canSee(actor, def, def_pct)
 	return true, 100
 end
 
+--- Does the actor have LOS to the target
+function _M:hasLOS(x, y)
+	local l = line.new(self.x, self.y, x, y)
+	local lx, ly = l()
+	while lx and ly do
+		if game.level.map:checkAllEntities(lx, ly, "block_sight") then break end
+
+		lx, ly = l()
+	end
+	-- Ok if we are at the end reset lx and ly for the next code
+	if not lx and not ly then lx, ly = x, y end
+
+	if lx == x and ly == y then return true, lx, ly end
+	return false, lx, ly
+end
+
 local function gettable(base, name)
 	for w in name:gmatch("[^.]+") do
 		base = base[w]
diff --git a/game/engine/ai/talented.lua b/game/engine/ai/talented.lua
index 91b6d855dc0cb2aa88747ba58c0c4c1bf1ae1161..246c41fe029109e697814a34934c9d3116696f99 100644
--- a/game/engine/ai/talented.lua
+++ b/game/engine/ai/talented.lua
@@ -27,7 +27,7 @@ newAI("dumb_talented", function(self)
 	for tid, _ in pairs(self.talents) do
 		local t = self:getTalentFromId(tid)
 --		print(self.name, self.uid, "dumb ai talents can try use", t.name, tid, "::", t.mode, not self:isTalentCoolingDown(t), target_dist <= self:getTalentRange(t), self:preUseTalent(t, true), self:canProject({type="bolt"}, self.ai_target.actor.x, self.ai_target.actor.y))
-		if t.mode == "activated" and not self:isTalentCoolingDown(t) and target_dist <= self:getTalentRange(t) and self:preUseTalent(t, true) and self:canProject({type="bolt"}, self.ai_target.actor.x, self.ai_target.actor.y) then
+		if t.mode == "activated" and not self:isTalentCoolingDown(t) and target_dist <= self:getTalentRange(t) and self:preUseTalent(t, true) and self:canProject({type="bolt"}, self.ai_target.actor.x, self.ai_target.actor.y) and self:hasLOS(self.ai_target.actor.x, self.ai_target.actor.y) then
 			avail[#avail+1] = tid
 			print(self.name, self.uid, "dumb ai talents can use", t.name, tid)
 		elseif t.mode == "sustained" and not self:isTalentCoolingDown(t) and not self:isTalentActive(t.id) and self:preUseTalent(t, true) then
diff --git a/game/modules/tome/data/birth/classes/mage.lua b/game/modules/tome/data/birth/classes/mage.lua
index db04d071b7c4643f926be86ed6cd6181d6d899fa..a7647fc5ed8906d9c00db82b5f9fbeb0c19a2ec1 100644
--- a/game/modules/tome/data/birth/classes/mage.lua
+++ b/game/modules/tome/data/birth/classes/mage.lua
@@ -104,12 +104,12 @@ newBirthDescriptor{
 	},
 	stats = { mag=5, dex=3, wil=1, },
 	talents_types = {
-		["spell/alchemy"]={true, 0.3},
+		["spell/explosives"]={true, 0.3},
 		["spell/infusion"]={true, 0.3},
 		["spell/golemancy"]={true, 0.3},
 		["spell/advanced-golemancy"]={false, 0.3},
-		["spell/gemology"]={true, 0.3},
-		["spell/herbalism"]={false, 0.3},
+		["spell/stone-alchemy"]={true, 0.3},
+		["spell/fire-alchemy"]={false, 0.3},
 		["spell/staff-combat"]={true, 0.3},
 		["cunning/survival"]={false, -0.1},
 		["technique/combat-training"]={false, 0},
diff --git a/game/modules/tome/data/damage_types.lua b/game/modules/tome/data/damage_types.lua
index 464ef448294bf4f48306ca2e9939e16a86024fb4..a796f4973e9317324118db9ef18cb312d787c318 100644
--- a/game/modules/tome/data/damage_types.lua
+++ b/game/modules/tome/data/damage_types.lua
@@ -42,7 +42,8 @@ setDefaultProjector(function(src, x, y, type, dam)
 
 		-- Reduce damage with resistance
 		if target.resists then
-			local pen = (src.resists_pen.all or 0) + (src.resists_pen[type] or 0)
+			local pen = 0
+			if src.resists_pen then pen = (src.resists_pen.all or 0) + (src.resists_pen[type] or 0) end
 			local res = (target.resists.all or 0) + (target.resists[type] or 0)
 			res = res * (100 - pen) / 100
 			print("[PROJECTOR] res", res, (100 - res) / 100, " on dam", dam)
diff --git a/game/modules/tome/data/general/npcs/snow-giant.lua b/game/modules/tome/data/general/npcs/snow-giant.lua
index ae046bd2b248127d5ffed24e6058368b8434b947..4ae538587eb17304503f14acb9eb1b542e34ceb4 100644
--- a/game/modules/tome/data/general/npcs/snow-giant.lua
+++ b/game/modules/tome/data/general/npcs/snow-giant.lua
@@ -40,7 +40,7 @@ newEntity{
 	energy = { mod=1 },
 	stats = { str=20, dex=8, mag=6, con=16 },
 
-	resists = { [DamageType.PHYSICAL] = 20, [DamageType.FIRE] = 50, },
+	resists = { [DamageType.PHYSICAL] = 20, [DamageType.COLD] = 50, },
 
 	no_breath = 1,
 	confusion_immune = 1,
diff --git a/game/modules/tome/data/talents/spells/advanced-golemancy.lua b/game/modules/tome/data/talents/spells/advanced-golemancy.lua
index 2d7ad2f196215f29a713e12d3722b16dd529f580..4a373eb269d88c3d20f1c99397eba86baf2d5170 100644
--- a/game/modules/tome/data/talents/spells/advanced-golemancy.lua
+++ b/game/modules/tome/data/talents/spells/advanced-golemancy.lua
@@ -28,16 +28,12 @@ newTalent{
 		self.alchemy_golem:learnTalent(self.T_SWORD_MASTERY, true)
 		self.alchemy_golem:learnTalent(self.T_MACE_MASTERY, true)
 		self.alchemy_golem:learnTalent(self.T_AXE_MASTERY, true)
-		self.alchemy_golem:learnTalent(self.T_HEAVY_ARMOUR_TRAINING, true)
-		self.alchemy_golem:learnTalent(self.T_MASSIVE_ARMOUR_TRAINING, true)
 	end,
 	on_unlearn = function(self, t)
 		self.alchemy_golem:unlearnTalent(self.T_WEAPON_COMBAT, true)
 		self.alchemy_golem:unlearnTalent(self.T_SWORD_MASTERY, true)
 		self.alchemy_golem:unlearnTalent(self.T_MACE_MASTERY, true)
 		self.alchemy_golem:unlearnTalent(self.T_AXE_MASTERY, true)
-		self.alchemy_golem:unlearnTalent(self.T_HEAVY_ARMOUR_TRAINING, true)
-		self.alchemy_golem:unlearnTalent(self.T_MASSIVE_ARMOUR_TRAINING, true)
 	end,
 	info = function(self, t)
 		return ([[Improves your golem proficiency with two handed weapons.]])
diff --git a/game/modules/tome/data/talents/spells/alchemy.lua b/game/modules/tome/data/talents/spells/explosives.lua
similarity index 68%
rename from game/modules/tome/data/talents/spells/alchemy.lua
rename to game/modules/tome/data/talents/spells/explosives.lua
index 6a905325dc39ec588e12db8a1d5f547fb14353cc..f195113427b6c5541afad71b69f076129ee74a05 100644
--- a/game/modules/tome/data/talents/spells/alchemy.lua
+++ b/game/modules/tome/data/talents/spells/explosives.lua
@@ -109,6 +109,7 @@ newTalent{
 		if ammo then dam, damtype = t.computeDamage(self, t, ammo) end
 		return ([[Imbue an alchemist gem with an explosive charge of mana and throw it.
 		The gem will explode for %0.2f %s damage.
+		Each kind of gem will also provide a specific effect.
 		The damage will improve with better gems and Magic stat and the range with your dexterity.]]):format(dam, DamageType:get(damtype).name)
 	end,
 }
@@ -149,38 +150,82 @@ newTalent{
 }
 
 newTalent{
-	name = "Stone Touch",
+	name = "Shockwave Bomb",
 	type = {"spell/explosives",4},
 	require = spells_req4,
 	points = 5,
-	mana = 80,
-	cooldown = 15,
+	mana = 40,
+	cooldown = 10,
 	range = function(self, t)
-		if self:getTalentLevel(t) < 3 then return 1
-		else return math.floor(self:getTalentLevel(t)) end
+		return math.ceil(5 + self:getDex(12))
+	end,
+	computeDamage = function(self, t, ammo)
+		local inc_dam = 0
+		local damtype = DamageType.SPELLKNOCKBACK
+		local particle = "ball_fire"
+		inc_dam = self:getTalentLevel(self.T_FIRE_INFUSION) * 0.05 + (ammo.alchemist_bomb.power or 0) / 100
+		local dam = self:combatTalentSpellDamage(t, 15, 120, (ammo.alchemist_power + self:combatSpellpower()) / 2)
+		dam = dam * (1 + inc_dam)
+		return dam, damtype, particle
 	end,
 	action = function(self, t)
-		local tg = {type="beam", range=self:getTalentRange(t), talent=t}
-		if self:getTalentLevel(t) >= 3 then tg.type = "beam" end
+		local ammo = self:hasAlchemistWeapon()
+		if not ammo or ammo:getNumber() < 2 then
+			game.logPlayer(self, "You need to ready at least two alchemist gems in your quiver.")
+			return
+		end
+
+		local tg = {type="ball", range=self:getTalentRange(t)+(ammo.alchemist_bomb.range or 0), radius=2, talent=t}
 		local x, y = self:getTarget(tg)
 		if not x or not y then return nil end
-		self:project(tg, x, y, function(tx, ty)
+
+		ammo = self:removeObject(self:getInven("QUIVER"), 1)
+		if not ammo then return end
+
+		local dam, damtype, particle = t.computeDamage(self, t, ammo)
+		local prot = self:getTalentLevelRaw(self.T_ALCHEMIST_PROTECTION) * 0.2
+		local golem = game.level:hasEntity(self.alchemy_golem) and self.alchemy_golem or nil
+		local dam_done = 0
+
+		local tmp = {}
+		local grids = self:project(tg, x, y, function(tx, ty)
+			local d = dam
+			-- Protect yourself
+			if tx == self.x and ty == self.y then d = dam * (1 - prot) end
+			-- Protect the golem
+			if golem and tx == golem.x and ty == golem.y then d = dam * (1 - prot) end
+
+			DamageType:get(damtype).projector(self, tx, ty, damtype, self:spellCrit(d), tmp)
 			local target = game.level.map(tx, ty, Map.ACTOR)
 			if not target then return end
-
-			if target:checkHit(self:combatSpellpower(), target:combatSpellResist(), 0, 95, 10) and target:canBe("stone") and target:canBe("instakill") then
-				target:setEffect(target.EFF_STONED, math.floor((3 + self:getTalentLevel(t)) / 1.5), {})
-				game.level.map:particleEmitter(tx, ty, 1, "archery")
+			if ammo.alchemist_bomb.splash then
+				DamageType:get(DamageType[ammo.alchemist_bomb.splash.type]).projector(self, tx, ty, DamageType[ammo.alchemist_bomb.splash.type], ammo.alchemist_bomb.splash.dam)
+			end
+			if ammo.alchemist_bomb.stun and rng.percent(ammo.alchemist_bomb.stun.chance) and target:checkHit(self:combatSpellpower(), target:combatPhysicalResist(), 0, 95, 5) and target:canBe("stun") then
+				target:setEffect(target.EFF_STUNNED, ammo.alchemist_bomb.stun.dur, {})
+			end
+			if ammo.alchemist_bomb.daze and rng.percent(ammo.alchemist_bomb.daze.chance) and target:checkHit(self:combatSpellpower(), target:combatPhysicalResist(), 0, 95, 5) and target:canBe("stun") then
+				target:setEffect(target.EFF_DAZED, ammo.alchemist_bomb.daze.dur, {})
 			end
 		end)
-		game:playSoundNear(self, "talents/earth")
+
+		if ammo.alchemist_bomb.leech then self:heal(math.min(self.max_life * ammo.alchemist_bomb.leech / 100, dam_done)) end
+
+		local _ _, x, y = self:canProject(tg, x, y)
+		game.level.map:particleEmitter(x, y, tg.radius, particle, {radius=tg.radius, grids=grids, tx=x, ty=y})
+
+		if ammo.alchemist_bomb.mana then self:incMana(ammo.alchemist_bomb.mana) end
+
+		game:playSoundNear(self, "talents/arcane")
 		return true
 	end,
 	info = function(self, t)
-		return ([[Touch your foe and turn it into stone for %d turns.
-		Stoned creatures are unable to act or regen life and are very brittle.
-		If a stoned creature if hit by an attack that deals more than 30%% of its life it will shatter and be destroyed.
-		Stoned creatures are highly resistant to fire and lightning and somewhat resistant to physical attacks.
-		At level 3 it will become a beam.]]):format(math.floor((3 + self:getTalentLevel(t)) / 1.5))
+		local ammo = self:hasAlchemistWeapon()
+		local dam, damtype = 1
+		if ammo then dam = t.computeDamage(self, t, ammo) end
+		return ([[Crush together two alchemmist gems, this makes them extremely unstable.
+		You then throw them to a target area, they explode on impact dealing %0.2f physical damage and knocking back any creatures in the blast radius.
+		Each kind of gem will also provide a specific effect.
+		The damage will improve with better gems and Magic stat and the range with your dexterity.]]):format(dam)
 	end,
 }
diff --git a/game/modules/tome/data/talents/spells/fire-alchemy.lua b/game/modules/tome/data/talents/spells/fire-alchemy.lua
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/game/modules/tome/data/talents/spells/gemology.lua b/game/modules/tome/data/talents/spells/stone-alchemy.lua
similarity index 76%
rename from game/modules/tome/data/talents/spells/gemology.lua
rename to game/modules/tome/data/talents/spells/stone-alchemy.lua
index 961dd285dc214f755d79a9ffbd8a0767fc3d037e..e06e4dc0ce3690b59f1233c277f23140f4f8d634 100644
--- a/game/modules/tome/data/talents/spells/gemology.lua
+++ b/game/modules/tome/data/talents/spells/stone-alchemy.lua
@@ -19,7 +19,7 @@
 
 newTalent{
 	name = "Create Alchemist Gems",
-	type = {"spell/gemology-base", 1},
+	type = {"spell/stone-alchemy-base", 1},
 	require = spells_req1,
 	points = 1,
 	range = function(self, t)
@@ -58,7 +58,7 @@ newTalent{
 
 newTalent{
 	name = "Extract Gems",
-	type = {"spell/gemology", 1},
+	type = {"spell/stone-alchemy", 1},
 	require = spells_req1,
 	points = 5,
 	mana = 5,
@@ -84,7 +84,7 @@ newTalent{
 
 newTalent{
 	name = "Imbue Item",
-	type = {"spell/gemology", 2},
+	type = {"spell/stone-alchemy", 2},
 	require = spells_req2,
 	points = 5,
 	mana = 80,
@@ -106,39 +106,10 @@ newTalent{
 		You can only imbue items once, and it is permanent.]])
 	end,
 }
-
-newTalent{
-	name = "Gem Vision",
-	type = {"spell/gemology", 3},
-	require = spells_req3,
-	cooldown = 10,
-	mana = 15,
-	points = 5,
-	action = function(self, t)
-		local ammo = self:hasAlchemistWeapon()
-		if not ammo or ammo:getNumber() < 2 then
-			game.logPlayer(self, "You need to ready 2 alchemist gems in your quiver.")
-			return
-		end
-
-		local x, y = self:getTarget{type="ball", nolock=true, no_restrict=true, range=100, radius=3 + self:getTalentLevel(t)}
-		if not x then return nil end
-
-		for i = 1, 2 do self:removeObject(self:getInven("QUIVER"), 1) end
-		self:magicMap(3 + self:getTalentLevel(t), x, y)
-		game:playSoundNear(self, "talents/spell_generic2")
-		return true
-	end,
-	info = function(self, t)
-		return ([[Consumes two alchemist gems to see remote areas in a radius of %d.]]):
-		format(3 + self:getTalentLevel(t))
-	end,
-}
-
 newTalent{
 	name = "Gem Portal",
-	type = {"spell/gemology",4},
-	require = spells_req4,
+	type = {"spell/stone-alchemy",3},
+	require = spells_req3,
 	cooldown = 20,
 	mana = 20,
 	points = 5,
@@ -167,3 +138,40 @@ newTalent{
 		format(math.floor(4 + self:combatSpellpower(0.06) * self:getTalentLevel(t)))
 	end,
 }
+
+newTalent{
+	name = "Stone Touch",
+	type = {"spell/stone-alchemy",4},
+	require = spells_req4,
+	points = 5,
+	mana = 80,
+	cooldown = 15,
+	range = function(self, t)
+		if self:getTalentLevel(t) < 3 then return 1
+		else return math.floor(self:getTalentLevel(t)) end
+	end,
+	action = function(self, t)
+		local tg = {type="beam", range=self:getTalentRange(t), talent=t}
+		if self:getTalentLevel(t) >= 3 then tg.type = "beam" end
+		local x, y = self:getTarget(tg)
+		if not x or not y then return nil end
+		self:project(tg, x, y, function(tx, ty)
+			local target = game.level.map(tx, ty, Map.ACTOR)
+			if not target then return end
+
+			if target:checkHit(self:combatSpellpower(), target:combatSpellResist(), 0, 95, 10) and target:canBe("stone") and target:canBe("instakill") then
+				target:setEffect(target.EFF_STONED, math.floor((3 + self:getTalentLevel(t)) / 1.5), {})
+				game.level.map:particleEmitter(tx, ty, 1, "archery")
+			end
+		end)
+		game:playSoundNear(self, "talents/earth")
+		return true
+	end,
+	info = function(self, t)
+		return ([[Touch your foe and turn it into stone for %d turns.
+		Stoned creatures are unable to act or regen life and are very brittle.
+		If a stoned creature is hit by an attack that deals more than 30%% of its life it will shatter and be destroyed.
+		Stoned creatures are highly resistant to fire and lightning and somewhat resistant to physical attacks.
+		At level 3 it will become a beam.]]):format(math.floor((3 + self:getTalentLevel(t)) / 1.5))
+	end,
+}
diff --git a/ideas/classes.ods b/ideas/classes.ods
index 904bd394f3d737e6f3a95cc012ccfa7a1d81ef33..1a8943c80a4bd32d39622ad07a5b0e70e020a294 100644
Binary files a/ideas/classes.ods and b/ideas/classes.ods differ
diff --git a/ideas/crafting.ods b/ideas/crafting.ods
index 18377387632cbb4fb1de8ad513e13fb0c4d2ed38..c8e23c871496918e33dbaefce3d6573b495de7d6 100644
Binary files a/ideas/crafting.ods and b/ideas/crafting.ods differ