diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua
index b782a78e95f871a8200ff3fa7596f4c4a3f68a8a..80b1cfbf4a1123c4c6ae6bb073531f03aea55397 100644
--- a/game/modules/tome/class/Actor.lua
+++ b/game/modules/tome/class/Actor.lua
@@ -4716,6 +4716,7 @@ local sustainCallbackCheck = {
 	callbackOnTemporaryEffect = "talents_on_tmp",
 	callbackOnTalentDisturbed = "talents_on_talent_disturbed",
 	callbackOnBlock = "talents_on_block",
+	callbackOnChronoWeaponFoldingHit = "talents_on_chrono_weapon_folding_hit",
 }
 _M.sustainCallbackCheck = sustainCallbackCheck
 
diff --git a/game/modules/tome/class/interface/Archery.lua b/game/modules/tome/class/interface/Archery.lua
index 8cc6bd0cfb2be205035b870a53917acba93fe2e2..9851a5b4be52ac5ed6133f556d91b832f1a891db 100644
--- a/game/modules/tome/class/interface/Archery.lua
+++ b/game/modules/tome/class/interface/Archery.lua
@@ -426,31 +426,6 @@ local function archery_projectile(tx, ty, tg, self, tmp)
 		self.shattering_impact_last_turn = game.turn
 	end
 
-	-- Temporal cast
-	if hitted and self:knowTalent(self.T_WEAPON_FOLDING) and self:isTalentActive(self.T_WEAPON_FOLDING) then
-		local dam = self:callTalent(self.T_WEAPON_FOLDING, "getDamage")
-		if self:knowTalent(self.T_FRAYED_THREADS) then
-			local burst_damage = dam * self:callTalent(self.T_FRAYED_THREADS, "getPercent")
-			local burst_radius = self:callTalent(self.T_FRAYED_THREADS, "getRadius")
-			self:project({type="ball", radius=burst_radius, friendlyfire=false}, target.x, target.y, DamageType.TEMPORAL, burst_damage)
-		end
-		if dam > 0 and not target.dead then
-			DamageType:get(DamageType.TEMPORAL).projector(self, target.x, target.y, DamageType.TEMPORAL, dam, tmp)
-		end
-	end
-	if hitted and self:knowTalent(self.T_IMPACT) and self:isTalentActive(self.T_IMPACT) then
-		local dam = self:callTalent(self.T_IMPACT, "getDamage")
-		local power = self:callTalent(self.T_IMPACT, "getApplyPower")
-		if self:knowTalent(self.T_FRAYED_THREADS) then
-			local burst_damage = dam * self:callTalent(self.T_FRAYED_THREADS, "getPercent")
-			local burst_radius = self:callTalent(self.T_FRAYED_THREADS, "getRadius")
-			self:project({type="ball", radius=burst_radius, friendlyfire=false}, target.x, target.y, DamageType.IMPACT, {dam=burst_damage, daze=burst_damage/2, power_check=power})
-		end
-		if dam > 0 and not target.dead then
-			DamageType:get(DamageType.IMPACT).projector(self, target.x, target.y, DamageType.IMPACT, {dam=dam, daze=dam/2, power_check=power}, tmp)
-		end
-	end
-
 	if self ~= target then
 		-- Regen on being hit
 		if hitted and not target.dead and target:attr("stamina_regen_when_hit") then target:incStamina(target.stamina_regen_when_hit) end
diff --git a/game/modules/tome/class/interface/Combat.lua b/game/modules/tome/class/interface/Combat.lua
index 543fde35b911868ff540860e82eb16bf24abcb4d..00a3408de83b7039a7179e30c7a7b88d56086330 100644
--- a/game/modules/tome/class/interface/Combat.lua
+++ b/game/modules/tome/class/interface/Combat.lua
@@ -625,33 +625,6 @@ function _M:attackTargetWith(target, weapon, damtype, mult, force_dam)
 		end
 	end
 
-	-- Temporal cast
-	if hitted and self:knowTalent(self.T_WEAPON_FOLDING) and self:isTalentActive(self.T_WEAPON_FOLDING) then
-		local dam = self:callTalent(self.T_WEAPON_FOLDING, "getDamage")
-		local burst_damage = 0
-		local burst_radius = 0
-		if self:knowTalent(self.T_FRAYED_THREADS) then
-			local burst_damage = dam * self:callTalent(self.T_FRAYED_THREADS, "getPercent")
-			local burst_radius = self:callTalent(self.T_FRAYED_THREADS, "getRadius")
-			self:project({type="ball", radius=burst_radius, friendlyfire=false}, target.x, target.y, DamageType.TEMPORAL, burst_damage)
-		end
-		if dam > 0 and not target.dead then
-			DamageType:get(DamageType.TEMPORAL).projector(self, target.x, target.y, DamageType.TEMPORAL, dam, tmp)
-		end
-	end
-	if hitted and self:knowTalent(self.T_IMPACT) and self:isTalentActive(self.T_IMPACT) then
-		local dam = self:callTalent(self.T_IMPACT, "getDamage")
-		local power = self:callTalent(self.T_IMPACT, "getApplyPower")
-		if self:knowTalent(self.T_FRAYED_THREADS) then
-			local burst_damage = dam * self:callTalent(self.T_FRAYED_THREADS, "getPercent")
-			local burst_radius = self:callTalent(self.T_FRAYED_THREADS, "getRadius")
-			self:project({type="ball", radius=burst_radius, friendlyfire=false}, target.x, target.y, DamageType.IMPACT, {dam=burst_damage, daze=burst_damage/2, power_check=power})
-		end
-		if dam > 0 and not target.dead then
-			DamageType:get(DamageType.IMPACT).projector(self, target.x, target.y, DamageType.IMPACT, {dam=dam, daze=dam/2, power_check=power}, tmp)
-		end
-	end
-
 	-- Ruin
 	if hitted and not target.dead and self:knowTalent(self.T_RUIN) and self:isTalentActive(self.T_RUIN) then
 		local t = self:getTalentFromId(self.T_RUIN)
diff --git a/game/modules/tome/data/birth/classes/chronomancer.lua b/game/modules/tome/data/birth/classes/chronomancer.lua
index aace9cbf5d144c102aa8d533dcdbfe623f970518..2c4c00feed65c5de3eb0e115e05a22c0133854f5 100644
--- a/game/modules/tome/data/birth/classes/chronomancer.lua
+++ b/game/modules/tome/data/birth/classes/chronomancer.lua
@@ -70,14 +70,15 @@ newBirthDescriptor{
 	stats = { mag=5, wil=2, con=2, },
 	talents_types = {
 		-- class
-		["chronomancy/fate-threading"]={true, 0.3},
 		["chronomancy/gravity"]={true, 0.3},
+		["chronomancy/matter"]={true, 0.3},
 		["chronomancy/spacetime-folding"]={true, 0.3},
 		["chronomancy/speed-control"]={true, 0.3},
-		["chronomancy/timeline-threading"]={true, 0.3},
 		["chronomancy/timetravel"]={true, 0.3},
 		
 		-- locked class
+		["chronomancy/fate-threading"]={false, 0.3},
+		["chronomancy/timeline-threading"]={false, 0.3},
 		["chronomancy/spellbinding"]={false, 0.3},
 		["chronomancy/spatial-tears"]={false, 0.3},
 
@@ -126,12 +127,13 @@ newBirthDescriptor{
 		-- class
 		["chronomancy/blade-threading"]={true, 0.3},
 		["chronomancy/bow-threading"]={true, 0.3},
-		["chronomancy/fate-threading"]={true, 0.1},
 		["chronomancy/spacetime-folding"]={true, 0.3},
 		["chronomancy/speed-control"]={true, 0.3},
 		["chronomancy/guardian"]={true, 0.3},
+		["chronomancy/temporal-combat"]={true, 0.3},
 		
 		-- class locked
+		["chronomancy/fate-threading"]={false, 0.1},
 		["chronomancy/threaded-combat"]={false, 0.3},
 		["chronomancy/temporal-hounds"]={false, 0.3},
 		["chronomancy/timetravel"]={false, 0.1},
diff --git a/game/modules/tome/data/talents/chronomancy/blade-threading.lua b/game/modules/tome/data/talents/chronomancy/blade-threading.lua
index d1cb1904c9c345711abdc4c1b17197bb6ddba80b..97aa827e18cb1152689eb45b3c96eb8826800886 100644
--- a/game/modules/tome/data/talents/chronomancy/blade-threading.lua
+++ b/game/modules/tome/data/talents/chronomancy/blade-threading.lua
@@ -69,7 +69,7 @@ newTalent{
 }
 
 newTalent{
-	name = "Weapon Folding",
+	name = "Weapon Folding", short_name = "WEAPON_FOLDING_BAD",
 	type = {"chronomancy/blade-threading", 2},
 	mode = "sustained",
 	require = chrono_req2,
diff --git a/game/modules/tome/data/talents/chronomancy/guardian.lua b/game/modules/tome/data/talents/chronomancy/guardian.lua
index 432ccb254a1caf4dee5e9db0725990c0ef0a7c22..4c74905e2154ce95a676dabf81444825cb47ba32 100644
--- a/game/modules/tome/data/talents/chronomancy/guardian.lua
+++ b/game/modules/tome/data/talents/chronomancy/guardian.lua
@@ -37,28 +37,6 @@ newTalent{
 	end,
 }
 
-newTalent{
-	name = "Invigorate",
-	type = {"chronomancy/guardian", 2},
-	require = chrono_req2,
-	points = 5,
-	paradox = function (self, t) return getParadoxCost(self, t, 20) end,
-	cooldown = 24,
-	fixed_cooldown = true,
-	tactical = { HEAL = 1 },
-	getDuration = function(self, t) return getExtensionModifier(self, t, math.floor(self:combatTalentLimit(self:getTalentLevel(t), 14, 4, 8))) end, -- Limit < 14
-	getPower = function(self, t) return self:combatTalentSpellDamage(t, 10, 50, getParadoxSpellpower(self, t)) end,
-	action = function(self, t)
-		self:setEffect(self.EFF_INVIGORATE, t.getDuration(self,t), {power=t.getPower(self, t)})
-		return true
-	end,
-	info = function(self, t)
-		local power = t.getPower(self, t)
-		local duration = t.getDuration(self, t)
-		return ([[For the next %d turns, you recover %0.1f life per turn and most other talents on cooldown will refresh twice as fast as usual.
-		The amount healed will increase with your Spellpower.]]):format(duration, power)
-	end,
-}
 
 newTalent{
 	name = "Guardian Unity",
@@ -133,58 +111,11 @@ newTalent{
 	end,
 }
 
-newTalent{
-	name = "Breach",
-	type = {"chronomancy/guardian", 4},
-	require = chrono_req4,
-	points = 5,
-	cooldown = 8,
-	paradox = function (self, t) return getParadoxCost(self, t, 15) end,
-	tactical = { ATTACK = {weapon = 2}, DISABLE = 3 },
-	requires_target = true,
+
 	range = function(self, t)
 		if self:hasArcheryWeapon("bow") then return util.getval(archery_range, self, t) end
 		return 1
 	end,
 	is_melee = function(self, t) return not self:hasArcheryWeapon("bow") end,
-	speed = function(self, t) return self:hasArcheryWeapon("bow") and "archery" or "weapon" end,
-	getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 1, 1.5) end,
-	getDuration = function(self, t) return getExtensionModifier(self, t, math.floor(self:combatTalentScale(t, 3, 7))) end,
-	on_pre_use = function(self, t, silent) if self:attr("disarmed") then if not silent then game.logPlayer(self, "You require a weapon to use this talent.") end return false end return true end,
-	archery_onhit = function(self, t, target, x, y)
-		target:setEffect(target.EFF_BREACH, t.getDuration(self, t), {})
-	end,
-	action = function(self, t)
-		local mainhand, offhand = self:hasDualWeapon()
 
-		if self:hasArcheryWeapon("bow") then
-			-- Ranged attack
-			local targets = self:archeryAcquireTargets({type="bolt"}, {one_shot=true, no_energy = true})
-			if not targets then return end
-			self:archeryShoot(targets, t, {type="bolt"}, {mult=t.getDamage(self, t)})
-		elseif mainhand then
-			-- Melee attack
-			local tg = {type="hit", range=self:getTalentRange(t), talent=t}
-			local x, y, target = self:getTarget(tg)
 			if not target or not self:canProject(tg, x, y) then return nil end
-			local hitted = self:attackTarget(target, nil, t.getDamage(self, t), true)
-
-			if hitted then
-				target:setEffect(target.EFF_BREACH, t.getDuration(self, t), {apply_power=getParadoxSpellpower(self, t)})
-			end
-		else
-			game.logPlayer(self, "You cannot use Breach without an appropriate weapon!")
-			return nil
-		end
-
-		return true
-	end,
-	info = function(self, t)
-		local duration = t.getDuration(self, t)
-		local damage = t.getDamage(self, t) * 100
-		return ([[Attack the target with either your bow or melee weapons for %d%% damage.
-		If the attack hits you'll breach the target's immunities, reducing armor hardiness, stun, pin, blindness, and confusion immunity by 50%% for %d turns.
-		Breach chance scales with your Spellpower.]])
-		:format(damage, duration)
-	end
-}
diff --git a/game/modules/tome/data/talents/chronomancy/temporal-combat.lua b/game/modules/tome/data/talents/chronomancy/temporal-combat.lua
index 720fe1b36809f9296b62d484e931475586b9fb35..de2c7d0854e5b44f7e9abd12251a1f5e40749e6d 100644
--- a/game/modules/tome/data/talents/chronomancy/temporal-combat.lua
+++ b/game/modules/tome/data/talents/chronomancy/temporal-combat.lua
@@ -16,3 +16,290 @@
 --
 -- Nicolas Casalini "DarkGod"
 -- darkgod@te4.org
+
+-- some helpers
+
+newTalent{
+	name = "Fold Fate",
+	type = {"chronomancy/other", 1},
+	paradox = function (self, t) return getParadoxCost(self, t, 10) end,
+	cooldown = 30,
+	tactical = { BUFF = 2, DEBUFF = 2 },
+	points = 5,
+	no_energy = true,
+	on_pre_use = function(self, t, silent)
+		for eff_id, p in pairs(self.tmp) do
+			local e = self.tempeffect_def[eff_id]
+			if true == e.subtype.weapon_manifold then
+				if not silent then
+					game.logPlayer(self, "You may only have one Weapon Manifold active at a time.")
+				end
+				return false
+			end
+		end
+		return true
+	end,
+	getChance = function(self, t) return 50	end,
+	action = function(self, t)
+		local duration = self:callTalent(self.T_WEAPON_MANIFOLD, "getDuration")
+		local dam = t.getChance(self, t)
+		local dox = self:callTalent(self.T_WEAPON_MANIFOLD, "getParadoxRegen")
+
+		self:setEffect(self.EFF_FOLD_FATE, duration, {dam = dam, src = self, paradox = dox})
+
+		return true
+	end,
+	info = function(self, t)
+		local duration = self:callTalent(self.T_WEAPON_MANIFOLD, "getDuration")
+		local dam = t.getChance(self, t)
+		local dox = self:callTalent(self.T_WEAPON_MANIFOLD, "getParadoxRegen")
+		return (
+		[[Fold a thread of fate into your weapons for %d turns, causing confusing dissonance when it strikes your targets as you damage their fates to repair the timeline.
+		Your melee and archery attacks have a %d%% chance to confuse any target you strike, and each hit brings your Paradox up to %0.1f closer to your chosen baseline.
+		The damage and Paradox regeneration will improve with your Paradox.]]
+		):format( duration, dam, dox )
+	end,
+}
+
+newTalent{
+	name = "Fold Gravity",
+	type = {"chronomancy/other", 1},
+	paradox = function (self, t) return getParadoxCost(self, t, 30) end,
+	cooldown = 30,
+	tactical = { BUFF = 2, DEBUFF = 2 },
+	points = 1,
+	no_energy = true,
+	on_pre_use = function(self, t, silent)
+		for eff_id, p in pairs(self.tmp) do
+			local e = self.tempeffect_def[eff_id]
+			if true == e.subtype.weapon_manifold then
+				if not silent then
+					game.logPlayer(self, "You may only have one Weapon Manifold active at a time.")
+				end
+				return false
+			end
+		end
+		return true
+	end,
+	getChance = function(self, t) return 25	end,
+	getEffDur = function(self, t) return 4 end,
+	action = function(self, t)
+		local duration = self:callTalent(self.T_WEAPON_MANIFOLD, "getDuration")
+		local damage = self:callTalent(self.T_WEAPON_FOLDING, "getDamage")
+		local chance = t.getChance(self, t)
+		local eff_dur = t.getEffDur(self, t)
+
+		self:setEffect(self.EFF_FOLD_GRAVITY, duration, {dam = damage, src = self, chance = chance})
+
+		return true
+	end,
+	info = function(self, t)
+		local duration = self:callTalent(self.T_WEAPON_MANIFOLD, "getDuration")
+		local damage = self:callTalent(self.T_WEAPON_FOLDING, "getDamage")
+		local chance = t.getChance(self, t)
+		local eff_dur = t.getEffDur(self, t)
+		return (
+		[[Fold a thread of gravity into your weapons for %d turns.
+		Your melee and archery attacks deal +%0.1f Physical damage, and each attack has a %d%% chance to Pin your target for %d turns.
+		The damage will improve with your Paradox, and the Pin will be applied with your Spellpower.]]
+		):format( duration, damDesc(self, DamageType.PHYSICAL, damage), chance, eff_dur )
+	end,
+}
+
+newTalent{
+	name = "Fold Void",
+	type = {"chronomancy/other", 1},
+	paradox = function (self, t) return getParadoxCost(self, t, 30) end,
+	cooldown = 30,
+	tactical = { BUFF = 2, DEBUFF = 2 },
+	points = 1,
+	no_energy = true,
+	on_pre_use = function(self, t, silent)
+		for eff_id, p in pairs(self.tmp) do
+		local e = self.tempeffect_def[eff_id]
+			if true == e.subtype.weapon_manifold then
+				if not silent then
+					game.logPlayer(self, "You may only have one Weapon Manifold active at a time.")
+				end
+				return false
+			end
+		end
+		return true
+	end,
+	getChance = function(self, t) return 25	end,
+	getEffDur = function(self, t) return 4 end,
+	action = function(self, t)
+		local duration = self:callTalent(self.T_WEAPON_MANIFOLD, "getDuration")
+		local damage = self:callTalent(self.T_WEAPON_FOLDING, "getDamage")
+		local chance = t.getChance(self, t)
+		local eff_dur = t.getEffDur(self, t)
+
+		self:setEffect(self.EFF_FOLD_VOID, duration, {dam = damage, src = self, chance = chance})
+
+		return true
+	end,
+	info = function(self, t)
+		local duration = self:callTalent(self.T_WEAPON_MANIFOLD, "getDuration")
+		local damage = self:callTalent(self.T_WEAPON_FOLDING, "getDamage")
+		local chance = t.getChance(self, t)
+		local eff_dur = t.getEffDur(self, t)
+		return (
+		[[Fold a thread of the void into your weapons for %d turns.
+		Your melee and archery attacks deal +%0.1f Darkness damage, and each attack has a %d%% chance to Blind your target for %d turns.
+		The damage will improve with your Paradox, and the Blindness will be applied with your Spellpower.]]
+		):format( duration, damDesc(self, DamageType.DARKNESS, damage), chance, eff_dur )
+	end,
+}
+
+-- Temporal Combat proper
+newTalent{
+	name = "Weapon Folding",
+	type = {"chronomancy/temporal-combat", 1},
+	mode = "sustained",
+	require = chrono_req1,
+	sustain_paradox = 12,
+	cooldown = 10,
+	tactical = { BUFF = 2 },
+	points = 5,
+	activate = function(self, t)
+		return {}
+	end,
+	deactivate = function(self, t, p)
+		return true
+	end,
+	getDamage = function(self, t) return 7 + self:combatSpellpower(0.092) * self:combatTalentScale(t, 1, 7) end,
+	callbackOnArcheryAttack = function(self, t, target, hitted, crit, weapon, ammo, damtype, mult, dam)
+		if not hitted then return end
+		if not target then return end
+		t.doWeaponFolding(self, t, target)
+	end,
+	callbackOnMeleeAttack = function(self, t, target, hitted, crit, weapon, damtype, mult, dam)
+		if not hitted then return end
+		if not target then return end
+		t.doWeaponFolding(self, t, target)
+	end,
+	doWeaponFolding = function(self, t, target)
+		local dam = t.getDamage(self,t)
+		if self:knowTalent(self.T_FRAYED_THREADS) then
+			self:callTalent(self.T_FRAYED_THREADS, "doExplosion", target, DamageType.TEMPORAL, dam)
+		end
+		if not target.dead then
+			DamageType:get(DamageType.TEMPORAL).projector(self, target.x, target.y, DamageType.TEMPORAL, dam)
+		end
+		
+		self:fireTalentCheck("callbackOnChronoWeaponFoldingHit", target, dam)
+	end,
+	info = function(self, t)
+		local damage = t.getDamage(self, t)
+		return ([[Folds a single dimension of your weapons (or ammo) upon itself, adding %0.2f temporal damage to your strikes and increasing your armor penetration by %d.
+		The armor penetration and damage will increase with your Spellpower.]]):format(damDesc(self, DamageType.TEMPORAL, damage), damage/2)
+	end,
+}
+
+
+newTalent{
+	name = "Weapon Manifold",
+	type = {"chronomancy/temporal-combat", 2},
+	require = chrono_req2,
+	mode = "passive",
+	points = 5,
+	on_learn = function(self, t)
+		self:learnTalent(Talents.T_FOLD_FATE, true)
+		self:learnTalent(Talents.T_FOLD_GRAVITY, true)
+		self:learnTalent(Talents.T_FOLD_VOID, true)
+	end,
+	on_unlearn = function(self, t)
+		self:unlearnTalent(Talents.T_FOLD_FATE)
+		self:unlearnTalent(Talents.T_FOLD_GRAVITY)
+		self:unlearnTalent(Talents.T_FOLD_VOID)
+	end,
+	getDuration = function(self, t) return 5 + paradoxTalentScale(self, t, 5, 15, 25) end,
+	getParadoxRegen = function(self, t) return 5 + paradoxTalentScale(self, t, 4, 25, 45) end,
+	info = function(self, t)
+		local damage = self:callTalent(self.T_WEAPON_FOLDING, "getDamage")
+		local dur    = t.getDuration(self, t)
+		local dox    = t.getParadoxRegen(self, t)
+		return ([[Advanced weapon folding. For %d turns, enhance your melee and archery attacks with the power of fate, gravity or the void.
+		Fold Fate: 50%% chance to Confuse your target for 4 turns, and you regain %0.1f Paradox.
+		Fold Gravity: %0.1f Physical damage, and you have a 25%% chance to Pin your target for 4 turns.
+		Fold Void: %0.1f Darkness damage, and you have a 25%% chance to Blind your target for 4 turns.
+		The Physical and Temporal damage and duration will increase with your Paradox and with investment in Weapon Folding. The Paradox recovery will increase with your Paradox. The status effects will become harder to resist as you gain Spellpower.]]
+		):format( dur, dox, damDesc(self, DamageType.PHYSICAL, damage), damDesc(self, DamageType.DARKNESS, damage) )
+	end,
+}
+
+newTalent{
+	name = "Invigorate",
+	type = {"chronomancy/temporal-combat", 3},
+	require = chrono_req3,
+	points = 5,
+	paradox = function (self, t) return getParadoxCost(self, t, 20) end,
+	cooldown = 24,
+	fixed_cooldown = true,
+	tactical = { HEAL = 1 },
+	getDuration = function(self, t) return getExtensionModifier(self, t, math.floor(self:combatTalentLimit(self:getTalentLevel(t), 14, 4, 8))) end, -- Limit < 14
+	getPower = function(self, t) return self:combatTalentSpellDamage(t, 10, 50, getParadoxSpellpower(self, t)) end,
+	action = function(self, t)
+		self:setEffect(self.EFF_INVIGORATE, t.getDuration(self,t), {power=t.getPower(self, t)})
+		return true
+	end,
+	info = function(self, t)
+		local power = t.getPower(self, t)
+		local duration = t.getDuration(self, t)
+		return ([[For the next %d turns, you recover %0.1f life and %0.1f stamina per turn, and most other talents on cooldown will refresh twice as fast as usual.
+		The life and stamina regeneration will increase with your Spellpower.]]):format(duration, power, power/2)
+	end,
+}
+
+newTalent{
+	name = "Breach",
+	type = {"chronomancy/temporal-combat", 4},
+	require = chrono_req4,
+	points = 5,
+	cooldown = 8,
+	paradox = function (self, t) return getParadoxCost(self, t, 15) end,
+	tactical = { ATTACK = {weapon = 2}, DISABLE = 3 },
+	requires_target = true,
+	range = archery_range,
+	speed = function(self, t) return self:hasArcheryWeapon("bow") and "archery" or "weapon" end,
+	getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 1, 1.5) end,
+	getDuration = function(self, t) return getExtensionModifier(self, t, math.floor(self:combatTalentScale(t, 3, 7))) end,
+	on_pre_use = function(self, t, silent) if self:attr("disarmed") then if not silent then game.logPlayer(self, "You require a weapon to use this talent.") end return false end return true end,
+	archery_onhit = function(self, t, target, x, y)
+		target:setEffect(target.EFF_BREACH, t.getDuration(self, t), {})
+	end,
+	action = function(self, t)
+		local mainhand, offhand = self:hasDualWeapon()
+
+		if self:hasArcheryWeapon("bow") then
+			-- Ranged attack
+			local targets = self:archeryAcquireTargets({type="bolt"}, {one_shot=true, no_energy = true})
+			if not targets then return end
+			self:archeryShoot(targets, t, {type="bolt"}, {mult=t.getDamage(self, t)})
+		elseif mainhand then
+			-- Melee attack
+			local tg = {type="hit", range=self:getTalentRange(t), talent=t}
+			local x, y, target = self:getTarget(tg)
+			if not x or not y or not target then return nil end
+			if core.fov.distance(self.x, self.y, x, y) > 1 then return nil end
+			local hitted = self:attackTarget(target, nil, t.getDamage(self, t), true)
+
+			if hitted then
+			target:setEffect(target.EFF_BREACH, t.getDuration(self, t), {apply_power=getParadoxSpellpower(self, t)})
+			end
+		else
+			game.logPlayer(self, "You cannot use Breach without an appropriate weapon!")
+			return nil
+		end
+
+		return true
+	end,
+	info = function(self, t)
+		local duration = t.getDuration(self, t)
+		local damage = t.getDamage(self, t) * 100
+		return ([[Attack the target with either your bow or melee weapons for %d%% damage.
+		If the attack hits you'll breach the target's immunities, reducing armor hardiness, stun, pin, blindness, and confusion immunity by 50%% for %d turns.
+		Breach chance scales with your Spellpower.]])
+		:format(damage, duration)
+	end
+}
diff --git a/game/modules/tome/data/talents/chronomancy/threaded-combat.lua b/game/modules/tome/data/talents/chronomancy/threaded-combat.lua
index 50559a98430379a7ca881c5085a0c89dfec00dc1..391ce984b1e2dd0f9eaaa49f75e566f5b424f8a9 100644
--- a/game/modules/tome/data/talents/chronomancy/threaded-combat.lua
+++ b/game/modules/tome/data/talents/chronomancy/threaded-combat.lua
@@ -27,6 +27,12 @@ newTalent{
 	points = 5,
 	getPercent = function(self, t) return paradoxTalentScale(self, t, 40, 80, 100)/100 end,
 	getRadius = function(self, t) return self:getTalentLevel(t) > 4 and 2 or 1 end,
+	doExplosion = function(self, t, target, damtype, base_dam)
+		local burst_damage = base_dam * t.getPercent(self, t)
+		local burst_radius = t.getRadius(self, t)
+		self:project({type="ball", radius=burst_radius, friendlyfire=false}, target.x, target.y, damtype, burst_damage)
+		-- fixme: graphics by damage type?
+	end,
 	info = function(self, t)
 		local percent = t.getPercent(self, t) * 100
 		local radius = t.getRadius(self, t)
diff --git a/game/modules/tome/data/timed_effects/magical.lua b/game/modules/tome/data/timed_effects/magical.lua
index 21d0d315a74f20e6fbb9860247bdb991f734a4cf..f44c38c88ef5db561a56a32fe2d58915174f1f46 100644
--- a/game/modules/tome/data/timed_effects/magical.lua
+++ b/game/modules/tome/data/timed_effects/magical.lua
@@ -1320,7 +1320,7 @@ newEffect{
 newEffect{
 	name = "INVIGORATE", image = "talents/invigorate.png",
 	desc = "Invigorate",
-	long_desc = function(self, eff) return ("The target is regaining %d life per turn and refreshing chronomancy spells at twice the normal rate."):format(eff.power) end,
+	long_desc = function(self, eff) return ("The target is regaining %d life per turn, %d stamina per turn, and refreshing chronomancy spells at twice the normal rate."):format(eff.power, eff.power/2) end,
 	type = "magical",
 	subtype = { temporal=true },
 	status = "beneficial",
@@ -1338,7 +1338,8 @@ newEffect{
 		end
 	end,
 	activate = function(self, eff)
-		eff.tmpid = self:addTemporaryValue("life_regen", eff.power)
+		eff.regenid = self:addTemporaryValue("life_regen", eff.power)
+		eff.stamid = self:addTemporaryValue("stamina_regen", eff.power / 2)
 		if core.shader.active(4) then
 			eff.particle1 = self:addParticles(Particles.new("shader_shield", 1, {toback=true,  size_factor=1.5, y=-0.3, img="healcelestial"}, {type="healing", time_factor=4000, noup=2.0, beamColor1={0xd8/255, 0xff/255, 0x21/255, 1}, beamColor2={0xf7/255, 0xff/255, 0x9e/255, 1}, circleColor={0,0,0,0}, beamsCount=5}))
 			eff.particle2 = self:addParticles(Particles.new("shader_shield", 1, {toback=false, size_factor=1.5, y=-0.3, img="healcelestial"}, {type="healing", time_factor=4000, noup=1.0, beamColor1={0xd8/255, 0xff/255, 0x21/255, 1}, beamColor2={0xf7/255, 0xff/255, 0x9e/255, 1}, circleColor={0,0,0,0}, beamsCount=5}))
@@ -1347,7 +1348,8 @@ newEffect{
 	deactivate = function(self, eff)
 		self:removeParticles(eff.particle1)
 		self:removeParticles(eff.particle2)
-		self:removeTemporaryValue("life_regen", eff.tmpid)
+		self:removeTemporaryValue("life_regen", eff.regenid)
+		self:removeTemporaryValue("stamina_regen", eff.stamid)
 	end,
 }
 
@@ -3334,4 +3336,124 @@ newEffect{
 			end
 		end
 	end,
+}
+
+
+
+newEffect{
+	name = "FOLD_FATE", image = "talents/fold_fate.png",
+	desc = "Fold Fate",
+	long_desc = function(self, eff)	return ("A thread of fate is bound to the target's weapons: ranged and melee attacks have a %d%% to Confuse, and shifts Paradox towards the target's baseline."):format(eff.dam) end,
+	status = "beneficial",
+	type = "magical",
+	subtype = { weapon_manifold=true, fate=true, },
+	parameters = { dam = 50, paradox = 10 },
+	on_gain = function(self, err) return "#Target# threads fate into a weapon manifold!", "+Fold Fate" end,
+	on_lose = function(self, err) return "#Target#'s weapon manifold unravels.", "-Fold Fate" end,
+	handleEffect = function(self, eff, target)
+		if eff.src:knowTalent(self.T_FRAYED_THREADS) then
+			eff.src:callTalent(self.T_FRAYED_THREADS, "doExplosion", target, DamageType.RANDOM_CONFUSION, eff.dam)
+		end
+		if not self.dead then
+			local dox = self:getParadox() - self.preferred_paradox
+			local fix = math.min( math.abs(dox), eff.paradox )
+			if dox > 0 then
+				self:incParadox( -fix )
+			elseif dox < 0 then
+				self:incParadox( fix )
+			end
+		end      
+	end,
+	callbackOnArcheryAttack = function(self, eff, target, hitted, crit, weapon, ammo, damtype, mult, dam)
+		if not hitted then return end
+		if not target then return end
+		self.tempeffect_def[eff.effect_id].handleEffect(self, eff, target)
+	end,
+	callbackOnMeleeAttack = function(self, eff, target, hitted, crit, weapon, damtype, mult, dam)
+		if not hitted then return end
+		if not target then return end
+		self.tempeffect_def[eff.effect_id].handleEffect(self, eff, target)
+	end,
+	activate = function(self, eff)
+		self:effectTemporaryValue(eff, "melee_project",  {[DamageType.RANDOM_CONFUSION] = eff.dam})
+		self:effectTemporaryValue(eff, "ranged_project", {[DamageType.RANDOM_CONFUSION] = eff.dam})
+	end,
+	deactivate = function(self, eff)
+	end,
+}
+
+newEffect{
+	name = "FOLD_GRAVITY", image = "talents/fold_gravity.png",
+	desc = "Fold Gravity",
+	long_desc = function(self, eff) return ("A thread of gravity is bound to the target's weapons: ranged and melee attacks inflict +%0.1f Physical damage, and have a %d%% chance to pin."):format(eff.dam, eff.chance) end,
+	status = "beneficial",
+	type = "magical",
+	subtype = { weapon_manifold=true, gravity=true, physical=true },
+	parameters = { dam = 10, chance = 25 },
+	on_gain = function(self, err) return "#Target# threads gravity into a weapon manifold!", "+Fold Gravity" end,
+	on_lose = function(self, err) return "#Target#'s weapon manifold unravels.", "-Fold Gravity" end,
+	handleEffect = function(self, eff, target)
+		if self:knowTalent(self.T_FRAYED_THREADS) then
+			self:callTalent(self.T_FRAYED_THREADS, "doExplosion", target, DamageType.RANDOM_CONFUSION, eff.dam)
+		end
+		if not target.dead and rng.percent(eff.chance) then
+			if target:canBe("pin") then
+			target:setEffect(target.EFF_PINNED, eff.dur, {apply_power=self:combatSpellpower()})
+			end
+		end      
+	end,
+	callbackOnArcheryAttack = function(self, eff, target, hitted, crit, weapon, ammo, damtype, mult, dam)
+		if not hitted then return end
+		if not target then return end
+		self.tempeffect_def[eff.effect_id].handleEffect(self, eff, target)
+	end,
+	callbackOnMeleeAttack = function(self, eff, target, hitted, crit, weapon, damtype, mult, dam)
+		if not hitted then return end
+		if not target then return end
+		self.tempeffect_def[eff.effect_id].handleEffect(self, eff, target)
+	end,
+	activate = function(self, eff)
+		self:effectTemporaryValue(eff, "melee_project",  {[DamageType.PHYSICAL] = eff.dam})
+		self:effectTemporaryValue(eff, "ranged_project", {[DamageType.PHYSICAL] = eff.dam})
+	end,
+	deactivate = function(self, eff)
+	end,
+}
+
+newEffect{
+	name = "FOLD_VOID", image = "talents/fold_void.png",
+	desc = "Fold Void",
+	long_desc = function(self, eff) return ("A thread of the void is bound to the target's weapons: ranged and melee attacks deal +%0.1f Darkness damage, and have a %d%% chance to blind."):format(eff.dam, eff.chance) end,
+	status = "beneficial",
+	type = "magical",
+	subtype = { weapon_manifold=true, void=true, darkness=true },
+	parameters = { dam = 50, paradox = 10 },
+	on_gain = function(self, err) return "#Target# threads void into a weapon manifold!", "+Fold Void"	end,
+	on_lose = function(self, err) return "#Target#'s weapon manifold unravels.", "-Fold Void" end,
+	handleEffect = function(self, eff, target)
+		if eff.src:knowTalent(self.T_FRAYED_THREADS) then
+			eff.src:callTalent(self.T_FRAYED_THREADS, "doExplosion", target, DamageType.RANDOM_CONFUSION, eff.dam)
+		end
+		if not target.dead and rng.percent( eff.chance ) then
+			if target:canBe("blind") then
+				target:setEffect(target.EFF_BLINDED, 3, {src=self, apply_power=self:combatSpellpower()})
+			end
+		end
+	end,
+	callbackOnArcheryAttack = function(self, eff, target, hitted, crit, weapon, ammo, damtype, mult, dam)
+		if not hitted then return end
+		if not target then return end
+		self.tempeffect_def[eff.effect_id].handleEffect(self, eff, target)
+	end,
+	callbackOnMeleeAttack = function(self, eff, target, hitted, crit, weapon, damtype, mult, dam)
+		if not hitted then return end
+		if not target then return end
+		self.tempeffect_def[eff.effect_id].handleEffect(self, eff, target)
+	end,
+	activate = function(self, eff)
+		self:effectTemporaryValue(eff, "melee_project",  {[DamageType.DARKNESS] = eff.dam})
+		self:effectTemporaryValue(eff, "ranged_project", {[DamageType.DARKNESS] = eff.dam})
+	end,
+	deactivate = function(self, eff)
+	end,
 }
\ No newline at end of file