From 2938db4676dfcc2b2ec9c2a558132d78e6ccaeae Mon Sep 17 00:00:00 2001
From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54>
Date: Sat, 31 Jul 2010 13:35:52 +0000
Subject: [PATCH] Stealth now works correctly for monsters

git-svn-id: http://svn.net-core.org/repos/t-engine4@963 51575b47-30f0-44d4-a5cc-537603b46e54
---
 game/engine/Entity.lua            |  1 +
 game/engine/Tooltip.lua           | 10 ++++-----
 game/engine/class.lua             |  2 ++
 game/modules/tome/class/Actor.lua | 37 +++++++++++++++++++++++++++++--
 game/modules/tome/class/NPC.lua   |  5 +++--
 src/map.c                         | 12 ++++++++++
 6 files changed, 58 insertions(+), 9 deletions(-)

diff --git a/game/engine/Entity.lua b/game/engine/Entity.lua
index 357103247f..6bfee61256 100644
--- a/game/engine/Entity.lua
+++ b/game/engine/Entity.lua
@@ -30,6 +30,7 @@ local entities_load_functions = {}
 
 _M.__mo_repo = {}
 _M.__mo_final_repo = {}
+_M._no_save_fields = {}
 
 -- Setup the uids & MO repository as a weak value table, when the entities are no more used anywhere else they disappear from there too
 setmetatable(__uids, {__mode="v"})
diff --git a/game/engine/Tooltip.lua b/game/engine/Tooltip.lua
index a8cb476691..d317d0f29e 100644
--- a/game/engine/Tooltip.lua
+++ b/game/engine/Tooltip.lua
@@ -114,11 +114,11 @@ function _M:displayAtMap(tmx, tmy, mx, my)
 		local tt = {}
 		local seen = game.level.map.seens(tmx, tmy)
 		local remember = game.level.map.remembers(tmx, tmy)
-		tt[#tt+1] = seen and game.level.map:checkEntity(tmx, tmy, Map.PROJECTILE, "tooltip")
-		tt[#tt+1] = seen and game.level.map:checkEntity(tmx, tmy, Map.ACTOR, "tooltip")
-		tt[#tt+1] = seen and game.level.map:checkEntity(tmx, tmy, Map.OBJECT, "tooltip")
-		tt[#tt+1] = seen and game.level.map:checkEntity(tmx, tmy, Map.TRAP, "tooltip")
-		tt[#tt+1] = remember and game.level.map:checkEntity(tmx, tmy, Map.TERRAIN, "tooltip")
+		tt[#tt+1] = seen and game.level.map:checkEntity(tmx, tmy, Map.PROJECTILE, "tooltip", game.level.map.actor_player)
+		tt[#tt+1] = seen and game.level.map:checkEntity(tmx, tmy, Map.ACTOR, "tooltip", game.level.map.actor_player)
+		tt[#tt+1] = seen and game.level.map:checkEntity(tmx, tmy, Map.OBJECT, "tooltip", game.level.map.actor_player)
+		tt[#tt+1] = seen and game.level.map:checkEntity(tmx, tmy, Map.TRAP, "tooltip", game.level.map.actor_player)
+		tt[#tt+1] = remember and game.level.map:checkEntity(tmx, tmy, Map.TERRAIN, "tooltip", game.level.map.actor_player)
 		if #tt > 0 then
 			self:set("%s", table.concat(tt, "\n---\n"))
 			self:display()
diff --git a/game/engine/class.lua b/game/engine/class.lua
index 7220f6a313..ecd0023394 100644
--- a/game/engine/class.lua
+++ b/game/engine/class.lua
@@ -185,8 +185,10 @@ end
 
 function _M:save(filter, allow, savefile)
 	filter = filter or {}
+	if self._no_save_fields then table.merge(filter, self._no_save_fields) end
 	if not allow then
 		filter.new = true
+		filter._no_save_fields = true
 		filter._mo = true
 		filter._mo_final = true
 	else
diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua
index 40580aaa31..40daac61af 100644
--- a/game/modules/tome/class/Actor.lua
+++ b/game/modules/tome/class/Actor.lua
@@ -53,6 +53,9 @@ module(..., package.seeall, class.inherit(
 	mod.class.interface.Combat
 ))
 
+-- Dont save the can_see_cache
+_M._no_save_fields.can_see_cache = true
+
 function _M:init(t, no_default)
 	-- Define some basic combat stats
 	self.combat_def = 0
@@ -140,6 +143,8 @@ function _M:init(t, no_default)
 	engine.interface.ActorStats.init(self, t)
 	engine.interface.ActorLevel.init(self, t)
 	engine.interface.ActorFOV.init(self, t)
+
+	self:resetCanSeeCache()
 end
 
 function _M:act()
@@ -202,6 +207,9 @@ function _M:act()
 	-- Still not dead ?
 	if self.dead then return false end
 
+	-- Ok reset the seen cache
+	self:resetCanSeeCache()
+
 	return true
 end
 
@@ -376,7 +384,8 @@ function _M:TextSizeCategory()
 	return sizecat
 end
 
-function _M:tooltip()
+function _M:tooltip(x, y, seen_by)
+	if seen_by and not seen_by:canSee(self) then return end
 	local factcolor, factstate = "#ANTIQUE_WHITE#", "neutral"
 	if self:reactionToward(game.player) < 0 then factcolor, factstate = "#LIGHT_RED#", "hostile"
 	elseif self:reactionToward(game.player) > 0 then factcolor, factstate = "#LIGHT_GREEN#", "friendly"
@@ -1055,7 +1064,7 @@ end
 --- Can the actor see the target actor
 -- This does not check LOS or such, only the actual ability to see it.<br/>
 -- Check for telepathy, invisibility, stealth, ...
-function _M:canSee(actor, def, def_pct)
+function _M:canSeeNoCache(actor, def, def_pct)
 	if not actor then return false, 0 end
 
 	-- ESP, see all, or only types/subtypes
@@ -1108,6 +1117,30 @@ function _M:canSee(actor, def, def_pct)
 	end
 end
 
+function _M:canSee(actor, def, def_pct)
+	if not actor then return false, 0 end
+
+	self.can_see_cache = self.can_see_cache or {}
+	local s = tostring(def).."/"..tostring(def_pct)
+
+	if self.can_see_cache[actor] and self.can_see_cache[actor][s] then return self.can_see_cache[actor][s][1], self.can_see_cache[actor][s][2] end
+	self.can_see_cache[actor] = self.can_see_cache[actor] or {}
+	self.can_see_cache[actor][s] = self.can_see_cache[actor][s] or {}
+
+	local res, chance = self:canSeeNoCache(actor, def, def_pct)
+	self.can_see_cache[actor][s] = {res,chance}
+
+	-- Make sure the display updates
+	if self.player and type(def) == "nil" and actor._mo then actor._mo:onSeen(res) end
+
+	return res, chance
+end
+
+function _M:resetCanSeeCache()
+	self.can_see_cache = {}
+	setmetatable(self.can_see_cache, {__mode="k"})
+end
+
 --- Can the target be applied some effects
 -- @param what a string describing what is being tried
 function _M:canBe(what)
diff --git a/game/modules/tome/class/NPC.lua b/game/modules/tome/class/NPC.lua
index c1a38c2e8c..dde58a4eb4 100644
--- a/game/modules/tome/class/NPC.lua
+++ b/game/modules/tome/class/NPC.lua
@@ -117,8 +117,9 @@ function _M:die(src)
 	return mod.class.Actor.die(self, src)
 end
 
-function _M:tooltip()
-	local str = mod.class.Actor.tooltip(self)
+function _M:tooltip(x, y, seen_by)
+	local str = mod.class.Actor.tooltip(self, x, y, seen_by)
+	if not str then return end
 	return str..([[
 
 Target: %s
diff --git a/src/map.c b/src/map.c
index 5865dfbf23..9762ba5b52 100644
--- a/src/map.c
+++ b/src/map.c
@@ -80,6 +80,17 @@ static int map_object_free(lua_State *L)
 	return 1;
 }
 
+static int map_object_on_seen(lua_State *L)
+{
+	map_object *obj = (map_object*)auxiliar_checkclass(L, "core{mapobj}", 1);
+	if (lua_isboolean(L, 2))
+	{
+		obj->on_seen = lua_toboolean(L, 2);
+	}
+	lua_pushboolean(L, obj->on_seen);
+	return 1;
+}
+
 static int map_object_texture(lua_State *L)
 {
 	map_object *obj = (map_object*)auxiliar_checkclass(L, "core{mapobj}", 1);
@@ -792,6 +803,7 @@ static const struct luaL_reg map_object_reg[] =
 	{"shader", map_object_shader},
 	{"invalidate", map_object_invalid},
 	{"isValid", map_object_is_valid},
+	{"onSeen", map_object_on_seen},
 	{NULL, NULL},
 };
 
-- 
GitLab