diff --git a/game/engines/default/engine/Actor.lua b/game/engines/default/engine/Actor.lua
index 08085e66d8a0a380244c2e1688795ff06d4ee235..5eb4ff4385e3369c68627a8b3809396c8c10a20f 100644
--- a/game/engines/default/engine/Actor.lua
+++ b/game/engines/default/engine/Actor.lua
@@ -95,6 +95,12 @@ function _M:defineDisplayCallback()
 		ps[#ps+1] = e
 	end
 
+	local f_self = nil
+	local f_danger = nil
+	local f_friend = nil
+	local f_enemy = nil
+	local f_neutral = nil
+
 	self._mo:displayCallback(function(x, y, w, h)
 		local e
 		for i = 1, #ps do
@@ -103,6 +109,37 @@ function _M:defineDisplayCallback()
 			else self:removeParticles(e)
 			end
 		end
+
+		-- Tactical info
+		if game.level and game.level.map.view_faction then
+			local map = game.level.map
+
+			if not f_self then
+				f_self = game.level.map.tilesTactic:get(nil, 0,0,0, 0,0,0, map.faction_self)
+				f_danger = game.level.map.tilesTactic:get(nil, 0,0,0, 0,0,0, map.faction_danger)
+				f_friend = game.level.map.tilesTactic:get(nil, 0,0,0, 0,0,0, map.faction_friend)
+				f_enemy = game.level.map.tilesTactic:get(nil, 0,0,0, 0,0,0, map.faction_enemy)
+				f_neutral = game.level.map.tilesTactic:get(nil, 0,0,0, 0,0,0, map.faction_neutral)
+			end
+
+			if self.faction then
+				local friend
+				if not map.actor_player then friend = Faction:factionReaction(map.view_faction, self.faction)
+				else friend = map.actor_player:reactionToward(self) end
+
+				if self == map.actor_player then
+					f_self:toScreen(x, y, w, h)
+				elseif map:faction_danger_check(self) then
+					f_danger:toScreen(x, y, w, h)
+				elseif friend > 0 then
+					f_friend:toScreen(x, y, w, h)
+				elseif friend < 0 then
+					f_enemy:toScreen(x, y, w, h)
+				else
+					f_neutral:toScreen(x, y, w, h)
+				end
+			end
+		end
 		return true
 	end)
 end
diff --git a/game/engines/default/engine/Map.lua b/game/engines/default/engine/Map.lua
index f05c103abbc7d5faf46de620a197c3810fc78a70..360fdeee5fae9ffa6bfa694dbfb263c3ddd7010b 100644
--- a/game/engines/default/engine/Map.lua
+++ b/game/engines/default/engine/Map.lua
@@ -459,42 +459,6 @@ function _M:display(x, y, nb_keyframe, always_show)
 	self.display_x, self.display_y = x or self.display_x, y or self.display_y
 
 	self._map:toScreen(self.display_x, self.display_y, nb_keyframe, always_show)
-
-	-- Tactical display
-	if self.view_faction then
-		local e
-		local z
-		local adx, ady
-		local friend
-		for i = self.mx, self.mx + self.viewport.mwidth do
-		for j = self.my, self.my + self.viewport.mheight do
-			local z = i + j * self.w
-
-			if self.seens[z] then
-				e = self(i, j, ACTOR)
-				if e and (not self.actor_player or self.actor_player:canSee(e)) then
-					-- Tactical overlay ?
-					if e.faction then
-						if not self.actor_player then friend = Faction:factionReaction(self.view_faction, e.faction)
-						else friend = self.actor_player:reactionToward(e) end
-						if e._mo then adx, ady = e._mo:getMoveAnim(self._map, i, j) else adx, ady = 0, 0 end -- Make sure we display on the real screen coords: handle current move anim position
-						if e == self.actor_player then
-							self.tilesTactic:get(nil, 0,0,0, 0,0,0, self.faction_self):toScreen(self.display_x + (adx + i - self.mx) * self.tile_w * self.zoom, self.display_y + (ady + j - self.my) * self.tile_h * self.zoom, self.tile_w * self.zoom, self.tile_h * self.zoom)
-						elseif self:faction_danger_check(e) then
-							self.tilesTactic:get(nil, 0,0,0, 0,0,0, self.faction_danger):toScreen(self.display_x + (adx + i - self.mx) * self.tile_w * self.zoom, self.display_y + (ady + j - self.my) * self.tile_h * self.zoom, self.tile_w * self.zoom, self.tile_h * self.zoom)
-						elseif friend > 0 then
-							self.tilesTactic:get(nil, 0,0,0, 0,0,0, self.faction_friend):toScreen(self.display_x + (adx + i - self.mx) * self.tile_w * self.zoom, self.display_y + (ady + j - self.my) * self.tile_h * self.zoom, self.tile_w * self.zoom, self.tile_h * self.zoom)
-						elseif friend < 0 then
-							self.tilesTactic:get(nil, 0,0,0, 0,0,0, self.faction_enemy):toScreen(self.display_x + (adx + i - self.mx) * self.tile_w * self.zoom, self.display_y + (ady + j - self.my) * self.tile_h * self.zoom, self.tile_w * self.zoom, self.tile_h * self.zoom)
-						else
-							self.tilesTactic:get(nil, 0,0,0, 0,0,0, self.faction_neutral):toScreen(self.display_x + (adx + i - self.mx) * self.tile_w * self.zoom, self.display_y + (ady + j - self.my) * self.tile_h * self.zoom, self.tile_w * self.zoom, self.tile_h * self.zoom)
-						end
-					end
-				end
-			end
-		end end
-	end
-
 	self:displayParticles(nb_keyframe)
 	self:displayEffects()
 	self:displayEmotes(nb_keyframe)
diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua
index fbabbcae2f9187d80bb4b095f59c9766159764bc..82b15723bdd7c89a95e54ef27fffea0215e8e8c4 100644
--- a/game/modules/tome/class/Actor.lua
+++ b/game/modules/tome/class/Actor.lua
@@ -392,6 +392,71 @@ function _M:act()
 	return true
 end
 
+--- Attach or remove a display callback
+-- Defines particles to display
+function _M:defineDisplayCallback()
+	if not self._mo then return end
+
+	local ps = {}
+	for e, _ in pairs(self.__particles) do
+		ps[#ps+1] = e
+	end
+
+	local f_self = nil
+	local f_danger = nil
+	local f_friend = nil
+	local f_enemy = nil
+	local f_neutral = nil
+
+	self._mo:displayCallback(function(x, y, w, h)
+		local e
+		for i = 1, #ps do
+			e = ps[i]
+			if e.ps:isAlive() then e.ps:toScreen(x + w / 2, y + h / 2, true)
+			else self:removeParticles(e)
+			end
+		end
+
+		-- Tactical info
+		if game.level and game.level.map.view_faction then
+			local map = game.level.map
+
+			-- Tactical life info
+			local dh = h * 0.1
+			core.display.drawQuad(x, y + h - dh, w, dh, 139, 210, 77, 128)
+			core.display.drawQuad(x, y + h - dh, w * self.life / self.max_life, dh, 50, 220, 77, 255)
+
+			if not f_self then
+				f_self = game.level.map.tilesTactic:get(nil, 0,0,0, 0,0,0, map.faction_self)
+				f_danger = game.level.map.tilesTactic:get(nil, 0,0,0, 0,0,0, map.faction_danger)
+				f_friend = game.level.map.tilesTactic:get(nil, 0,0,0, 0,0,0, map.faction_friend)
+				f_enemy = game.level.map.tilesTactic:get(nil, 0,0,0, 0,0,0, map.faction_enemy)
+				f_neutral = game.level.map.tilesTactic:get(nil, 0,0,0, 0,0,0, map.faction_neutral)
+			end
+
+			if self.faction then
+				local friend
+				if not map.actor_player then friend = Faction:factionReaction(map.view_faction, self.faction)
+				else friend = map.actor_player:reactionToward(self) end
+
+				if self == map.actor_player then
+					f_self:toScreen(x, y, w, h)
+				elseif map:faction_danger_check(self) then
+					f_danger:toScreen(x, y, w, h)
+				elseif friend > 0 then
+					f_friend:toScreen(x, y, w, h)
+				elseif friend < 0 then
+					f_enemy:toScreen(x, y, w, h)
+				else
+					f_neutral:toScreen(x, y, w, h)
+				end
+			end
+		end
+
+		return true
+	end)
+end
+
 function _M:move(x, y, force)
 	local moved = false
 	local ox, oy = self.x, self.y