diff --git a/game/data/gfx/tactical_enemy.png b/game/data/gfx/tactical_enemy.png
new file mode 100644
index 0000000000000000000000000000000000000000..6a89b8e720e6358785254a67217be21faf9b844b
Binary files /dev/null and b/game/data/gfx/tactical_enemy.png differ
diff --git a/game/data/gfx/tactical_friend.png b/game/data/gfx/tactical_friend.png
new file mode 100644
index 0000000000000000000000000000000000000000..cb823e23b85bc9f92941279f3502a725385ab4aa
Binary files /dev/null and b/game/data/gfx/tactical_friend.png differ
diff --git a/game/data/gfx/tactical_neutral.png b/game/data/gfx/tactical_neutral.png
new file mode 100644
index 0000000000000000000000000000000000000000..72f99400ace9541b1dd3edb7a37fd5b829df8686
Binary files /dev/null and b/game/data/gfx/tactical_neutral.png differ
diff --git a/game/engine/Actor.lua b/game/engine/Actor.lua
index 37d2c82c8a0497dc9a65b5883f2eca98ecbd285e..980bd7324c18571fd5c2da8b2b315f4f1624ba6b 100644
--- a/game/engine/Actor.lua
+++ b/game/engine/Actor.lua
@@ -1,6 +1,7 @@
 require "engine.class"
 local Entity = require "engine.Entity"
 local Map = require "engine.Map"
+local Faction = require "engine.Faction"
 
 module(..., package.seeall, class.inherit(Entity))
 
@@ -8,9 +9,11 @@ function _M:init(t)
 	t = t or {}
 	self.name = t.name or "unknown npc"
 	self.level = t.level or 1
+	self.sight = t.sight or 20
 	self.energy = t.energy or { value=0, mod=1 }
 	self.energy.value = self.energy.value or 0
 	self.energy.mod = self.energy.mod or 0
+	self.faction = t.faction or "enemies"
 	Entity.init(self, t)
 end
 
@@ -45,3 +48,9 @@ function _M:useEnergy(val)
 	val = val or game.energy_to_act
 	self.energy.value = self.energy.value - val
 end
+
+--- What is our reaction toward the target
+-- See Faction:factionReaction()
+function _M:reactionToward(target)
+	return Faction:factionReaction(self.faction, target.faction)
+end
diff --git a/game/engine/Faction.lua b/game/engine/Faction.lua
new file mode 100644
index 0000000000000000000000000000000000000000..11ef3f51b52d37d6425fda522a4038204202f791
--- /dev/null
+++ b/game/engine/Faction.lua
@@ -0,0 +1,32 @@
+require "engine.class"
+
+--- Defines factions
+module(..., package.seeall, class.make)
+
+_M.factions = {}
+
+--- Adds a new faction
+-- Static method
+function _M:add(t)
+	assert(t.name, "no faction name")
+	assert(t.short_name, "no faction short_name")
+	t.reaction = t.reaction or {}
+	self.factions[t.short_name] = t
+end
+
+
+--- Returns the status of faction f1 toward f2
+-- @param f1 the source faction
+-- @param f2 the target faction
+-- @return a numerical value representing the reaction, 0 is neutral, <0 is aggressive, >0 is friendly
+function _M:factionReaction(f1, f2)
+	-- Faction always like itself
+	if f1 == f2 then return 100 end
+	if not self.factions[f1] then return 0 end
+	return self.factions[f1].reaction[f2] or 0
+end
+
+-- Add a few default factions
+_M:add{ short_name="players", name="Players", reaction={enemies=-100} }
+_M:add{ short_name="enemies", name="Enemies", reaction={player=-100,poorsods=-100} }
+_M:add{ short_name="poorsods", name="Poor Sods", reaction={} }
diff --git a/game/engine/Map.lua b/game/engine/Map.lua
index 5da2febce9a01932e755a310454eccd2d2593b1e..285943137a4da68ab2df57acf946289ec5db85a8 100644
--- a/game/engine/Map.lua
+++ b/game/engine/Map.lua
@@ -1,6 +1,7 @@
 require "engine.class"
 local Entity = require "engine.Entity"
 local Tiles = require "engine.Tiles"
+local Faction = require "engine.Faction"
 
 --- Represents a level map, handles display and various low level map work
 module(..., package.seeall, class.make)
@@ -29,6 +30,15 @@ function _M:setViewPort(w, h, tile_w, tile_h)
 	self.tile_w, self.tile_h = tile_w, tile_h
 end
 
+--- Defines the faction of the person seeing the map
+-- Usualy this will be the player's faction. If you do not want to use tactical display, dont use it
+function _M:setViewerFaction(faction, friend, neutral, enemy)
+	self.view_faction = faction
+	self.faction_friend = "tactical_friend.png"
+	self.faction_neutral = "tactical_neutral.png"
+	self.faction_enemy = "tactical_enemy.png"
+end
+
 --- Creates a map
 -- @param w width (in grids)
 -- @param h height (in grids)
@@ -77,11 +87,6 @@ function _M:fov(x, y, d)
 		for i = 0, self.w * self.h - 1 do self.seens[i] = nil end
 	end
 	self._fov(x, y, d)
-
-	-- Also seen the source itself
-	self.seens(x, y, true)
-	self.lites(x, y, true)
-	self.remembers(x, y, true)
 end
 
 --- Runs the FOV algorithm on the map, ligthing grids to allow rememberance
@@ -95,11 +100,6 @@ function _M:fovLite(x, y, d)
 		for i = 0, self.w * self.h - 1 do self.seens[i] = nil end
 		self._fov_lite(x, y, d)
 	end
-
-	-- Also seen the source itself
-	self.seens(x, y, true)
-	self.lites(x, y, true)
-	self.remembers(x, y, true)
 end
 
 --- Sets/gets a value from the map
@@ -150,6 +150,7 @@ function _M:display()
 		local e, si
 		local z
 		local order
+		local friend
 		for i = 0, self.w - 1 do for j = 0, self.h - 1 do
 			e, si = nil, 1
 			z = i + j * self.w
@@ -163,6 +164,17 @@ function _M:display()
 					elseif self.remembers[z] then
 						self.surface:merge(self.tiles:get(e.display, e.color_r/3, e.color_g/3, e.color_b/3, e.color_br/3, e.color_bg/3, e.color_bb/3, e.image), i * self.tile_w, j * self.tile_h)
 					end
+					-- Tactical overlay ?
+					if self.view_faction and e.faction then
+						friend = Faction:factionReaction(self.view_faction, e.faction)
+						if friend > 0 then
+							self.surface:merge(self.tiles:get(nil, 0,0,0, 0,0,0, self.faction_friend), i * self.tile_w, j * self.tile_h)
+						elseif friend < 0 then
+							self.surface:merge(self.tiles:get(nil, 0,0,0, 0,0,0, self.faction_enemy), i * self.tile_w, j * self.tile_h)
+						else
+							self.surface:merge(self.tiles:get(nil, 0,0,0, 0,0,0, self.faction_neutral), i * self.tile_w, j * self.tile_h)
+						end
+					end
 				end
 			end
 		end end
diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua
index 352acacfd5faec57eda67494a186d32d14a87277..b42b0f37b5bda5369bcb43417b89d9631671bae5 100644
--- a/game/modules/tome/class/Game.lua
+++ b/game/modules/tome/class/Game.lua
@@ -22,6 +22,7 @@ function _M:run()
 
 	Zone:setup{npc_class="mod.class.NPC", grid_class="mod.class.Grid", object_class="engine.Entity"}
 	Map:setViewPort(self.w, math.floor(self.h * 0.80), 16, 16)
+	Map:setViewerFaction("players")
 
 	self.zone = Zone.new("ancient_ruins")
 
diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua
index 96187d5245368fe1116108cf7484843322855aad..fd6f353415d6ade79d0064d0b3d01b34f878a0d8 100644
--- a/game/modules/tome/class/Player.lua
+++ b/game/modules/tome/class/Player.lua
@@ -5,7 +5,7 @@ module(..., package.seeall, class.inherit(mod.class.Actor))
 
 function _M:init(t)
 	mod.class.Actor.init(self, t)
-
+	self.faction = "players"
 	self.combat = { dam=10, atk=4, apr=2, def=6, armor=4 }
 end
 
diff --git a/game/modules/tome/class/interface/Combat.lua b/game/modules/tome/class/interface/Combat.lua
index 77c09ca209a6b1621db2ebc9bc09dc80d726d632..d331987361adead959668fba7d0cc41edb8b3409 100644
--- a/game/modules/tome/class/interface/Combat.lua
+++ b/game/modules/tome/class/interface/Combat.lua
@@ -24,6 +24,7 @@ function _M:attackTarget(target)
 	-- If hit is over 0 it connects, if it is 0 we still have 50% chance
 	if hit > 0 or (hit == 0 and rng.percent(50)) then
 		local dam = rng.avg(sc.dam * 2 / 3, sc.dam) - math.max(0, tc.armor - sc.apr)
+		if dam < 0 then dam = 0 end
 		game.logSeen(target, "%s hits %s for #aaaaaa#%0.2f physical damage#ffffff#.", self.name:capitalize(), target.name, dam)
 		target:takeHit(dam, self)
 	else
diff --git a/game/modules/tome/data/zones/ancient_ruins/npcs.lua b/game/modules/tome/data/zones/ancient_ruins/npcs.lua
index 7065f30bbc1db1aec97829781158c42ca8ec779d..3044269494f490c6fe06f1d8854cb6c89939f01a 100644
--- a/game/modules/tome/data/zones/ancient_ruins/npcs.lua
+++ b/game/modules/tome/data/zones/ancient_ruins/npcs.lua
@@ -14,6 +14,7 @@ return {
 {
 	name = "baby dragon",
 	display = "d", color_r=128,
+	faction = "poorsods",
 	level = 1, exp_worth = 1,
 	life = 30,
 	mana = 1000,
diff --git a/src/core_lua.c b/src/core_lua.c
index 7ae5fbbe68b0e390a18a31052f89d260cb3f2d0f..df52d60252013a9adea128e96b9c96844b960a78 100644
--- a/src/core_lua.c
+++ b/src/core_lua.c
@@ -64,7 +64,6 @@ static int lua_new_fov(lua_State *L)
 	fov->opaque_ref = opaque_ref;
 	fov->map_ref = map_ref;
 	fov_settings_init(&(fov->fov_settings));
-	fov_settings_set_shape(&(fov->fov_settings), FOV_SHAPE_CIRCLE);
 	fov_settings_set_opacity_test_function(&(fov->fov_settings), map_opaque);
 	fov_settings_set_apply_lighting_function(&(fov->fov_settings), map_seen);
 
@@ -90,6 +89,7 @@ static int lua_fov(lua_State *L)
 	int radius = luaL_checknumber(L, 4);
 
 	fov_circle(&(fov->fov_settings), fov, NULL, x, y, radius+1);
+	map_seen(fov, x, y, 0, 0, radius, NULL);
 	return 0;
 }
 
@@ -98,14 +98,16 @@ static int lua_fov_calc_circle(lua_State *L)
 	int x = luaL_checknumber(L, 1);
 	int y = luaL_checknumber(L, 2);
 	int radius = luaL_checknumber(L, 3);
-	int map_ref = luaL_ref(L, LUA_REGISTRYINDEX);
-	int apply_ref = luaL_ref(L, LUA_REGISTRYINDEX);
-	int opaque_ref = luaL_ref(L, LUA_REGISTRYINDEX);
-
 	struct lua_fov fov;
+	fov.map_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+	fov.apply_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+	fov.opaque_ref = luaL_ref(L, LUA_REGISTRYINDEX);
 
 	fov_settings_init(&(fov.fov_settings));
+	fov_settings_set_opacity_test_function(&(fov.fov_settings), map_opaque);
+	fov_settings_set_apply_lighting_function(&(fov.fov_settings), map_seen);
 	fov_circle(&(fov.fov_settings), &fov, NULL, x, y, radius+1);
+	map_seen(&fov, x, y, 0, 0, radius, NULL);
 	fov_settings_free(&(fov.fov_settings));
 
 	luaL_unref(L, LUA_REGISTRYINDEX, fov.apply_ref);
@@ -122,9 +124,10 @@ static int lua_fov_calc_beam(lua_State *L)
 	int radius = luaL_checknumber(L, 3);
 	int direction = luaL_checknumber(L, 4);
 	float angle = luaL_checknumber(L, 5);
-	int map_ref = luaL_ref(L, LUA_REGISTRYINDEX);
-	int apply_ref = luaL_ref(L, LUA_REGISTRYINDEX);
-	int opaque_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+	struct lua_fov fov;
+	fov.map_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+	fov.apply_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+	fov.opaque_ref = luaL_ref(L, LUA_REGISTRYINDEX);
 	int dir = 0;
 
 	switch (direction)
@@ -139,10 +142,11 @@ static int lua_fov_calc_beam(lua_State *L)
 	case 9: dir = FOV_NORTHEAST; break;
 	}
 
-	struct lua_fov fov;
-
 	fov_settings_init(&(fov.fov_settings));
+	fov_settings_set_opacity_test_function(&(fov.fov_settings), map_opaque);
+	fov_settings_set_apply_lighting_function(&(fov.fov_settings), map_seen);
 	fov_beam(&(fov.fov_settings), &fov, NULL, x, y, radius+1, dir, angle);
+	map_seen(&fov, x, y, 0, 0, radius, NULL);
 	fov_settings_free(&(fov.fov_settings));
 
 	luaL_unref(L, LUA_REGISTRYINDEX, fov.apply_ref);