From 286206acc2b04ae2aab4856b54ad0bacecdaa987 Mon Sep 17 00:00:00 2001
From: DarkGod <darkgod@net-core.org>
Date: Fri, 4 Oct 2019 15:15:52 +0200
Subject: [PATCH] Greatly simplified Creeping Darkness code, it now simply
 blocks sight for all unless they have Dark Vision

---
 game/modules/tome/class/Actor.lua             | 47 ++++---------------
 game/modules/tome/class/NPC.lua               | 47 +------------------
 game/modules/tome/class/Player.lua            | 29 ------------
 .../tome/data/talents/cursed/darkness.lua     | 10 +++-
 4 files changed, 19 insertions(+), 114 deletions(-)

diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua
index bbce488522..a12e124637 100644
--- a/game/modules/tome/class/Actor.lua
+++ b/game/modules/tome/class/Actor.lua
@@ -7061,48 +7061,17 @@ function _M:hasLOS(x, y, what, range, source_x, source_y)
 	if range and core.fov.distance(source_x, source_y, x, y) <= range then range = nil end
 	local lx, ly, is_corner_blocked
 	local last_x, last_y = source_x, source_y
-	if what == "block_sight" then
-		local darkVisionRange
-		if self:knowTalent(self.T_DARK_VISION) then
-			local t = self:getTalentFromId(self.T_DARK_VISION)
-			darkVisionRange = self:getTalentRange(t)
+	local l = core.fov.line(source_x, source_y, x, y, what)
+	lx, ly, is_corner_blocked = l:step()
+	while lx and ly and not is_corner_blocked do
+		-- Check for the range
+		if range and core.fov.distance(source_x, source_y, lx, ly) > range then
+			break
 		end
+		last_x, last_y = lx, ly
+		if game.level.map:checkAllEntities(lx, ly, what) then break end
 
-		local l = core.fov.line(source_x, source_y, x, y, "block_sight")
-		local inCreepingDark = false
 		lx, ly, is_corner_blocked = l:step()
-		while lx and ly and not is_corner_blocked do
-			-- Check for the range
-			if range and core.fov.distance(source_x, source_y, lx, ly) > range then
-				break
-			end
-			last_x, last_y = lx, ly
-			if game.level.map:checkAllEntities(lx, ly, "block_sight") then
-				if darkVisionRange and game.level.map:checkAllEntities(lx, ly, "creepingDark") then
-					inCreepingDark = true
-				else
-					break
-				end
-			end
-			if inCreepingDark and darkVisionRange and core.fov.distance(source_x, source_y, lx, ly) > darkVisionRange then
-				break
-			end
-
-			lx, ly, is_corner_blocked = l:step()
-		end
-	else
-		local l = core.fov.line(source_x, source_y, x, y, what)
-		lx, ly, is_corner_blocked = l:step()
-		while lx and ly and not is_corner_blocked do
-			-- Check for the range
-			if range and core.fov.distance(source_x, source_y, lx, ly) > range then
-				break
-			end
-			last_x, last_y = lx, ly
-			if game.level.map:checkAllEntities(lx, ly, what) then break end
-
-			lx, ly, is_corner_blocked = l:step()
-		end
 	end
 
 	if last_x == x and last_y == y then return true, last_x, last_y end
diff --git a/game/modules/tome/class/NPC.lua b/game/modules/tome/class/NPC.lua
index 067dae2895..28f70f0701 100644
--- a/game/modules/tome/class/NPC.lua
+++ b/game/modules/tome/class/NPC.lua
@@ -168,55 +168,12 @@ function _M:lineFOV(tx, ty, extra_block, block, sx, sy)
 	local sees_target = core.fov.distance(sx, sy, tx, ty) <= self.sight and game.level.map.lites(tx, ty) or
 		act and self:canSee(act) and core.fov.distance(sx, sy, tx, ty) <= math.min(self.sight, math.max(self.heightened_senses or 0, self.infravision or 0))
 
-	local darkVisionRange
-	if self:knowTalent(self.T_DARK_VISION) then
-		local t = self:getTalentFromId(self.T_DARK_VISION)
-		darkVisionRange = self:getTalentRange(t)
-	end
-	local inCreepingDark = false
-
 	extra_block = type(extra_block) == "function" and extra_block
 		or type(extra_block) == "string" and function(_, x, y) return game.level.map:checkAllEntities(x, y, extra_block) end
 
 	-- This block function can be called *a lot*, so every conditional statement we move outside the function helps
-	block = block or sees_target and (darkVisionRange and
-			-- target is seen and source actor has dark vision
-			function(_, x, y)
-				if game.level.map:checkAllEntities(x, y, "creepingDark") then
-					inCreepingDark = true
-				end
-				if inCreepingDark and core.fov.distance(sx, sy, x, y) > darkVisionRange then
-					return true
-				end
-				return game.level.map:checkAllEntities(x, y, "block_sight") or
-					game.level.map:checkEntity(x, y, engine.Map.TERRAIN, "block_move") and not game.level.map:checkEntity(x, y, engine.Map.TERRAIN, "pass_projectile") or
-					extra_block and extra_block(self, x, y)
-			end
-			-- target is seen and source actor does NOT have dark vision
-			or function(_, x, y)
-				return game.level.map:checkAllEntities(x, y, "block_sight") or
-					game.level.map:checkEntity(x, y, engine.Map.TERRAIN, "block_move") and not game.level.map:checkEntity(x, y, engine.Map.TERRAIN, "pass_projectile") or
-					extra_block and extra_block(self, x, y)
-			end)
-		or darkVisionRange and
-			-- target is NOT seen and source actor has dark vision (do we even need to check for creepingDark in this case?)
-			function(_, x, y)
-				if game.level.map:checkAllEntities(x, y, "creepingDark") then
-					inCreepingDark = true
-				end
-				if inCreepingDark and core.fov.distance(sx, sy, x, y) > darkVisionRange then
-					return true
-				end
-				if core.fov.distance(sx, sy, x, y) <= self.sight and game.level.map.lites(x, y) then
-					return game.level.map:checkEntity(x, y, engine.Map.TERRAIN, "block_sight") or
-						game.level.map:checkEntity(x, y, engine.Map.TERRAIN, "block_move") and not game.level.map:checkEntity(x, y, engine.Map.TERRAIN, "pass_projectile") or
-						extra_block and extra_block(self, x, y)
-				else
-					return true
-				end
-			end
-		or
-			-- target is NOT seen and the source actor does NOT have dark vision
+	block = block or sees_target and 
+			-- target is NOT seen
 			function(_, x, y)
 				if core.fov.distance(sx, sy, x, y) <= self.sight and game.level.map.lites(x, y) then
 					return game.level.map:checkEntity(x, y, engine.Map.TERRAIN, "block_sight") or
diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua
index 88c70200e3..dafaddf663 100644
--- a/game/modules/tome/class/Player.lua
+++ b/game/modules/tome/class/Player.lua
@@ -634,19 +634,6 @@ function _M:playerFOV()
 	end
 
 	if not self:attr("blind") then
-		-- Handle dark vision; same as infravision, but also sees past creeping dark
-		-- this is treated as a sense, but is filtered by custom LOS code
-		if self:knowTalent(self.T_DARK_VISION) then
-			local t = self:getTalentFromId(self.T_DARK_VISION)
-			local range = self:getTalentRange(t)
-			self:computeFOV(range, "block_sense", function(x, y)
-				local actor = game.level.map(x, y, game.level.map.ACTOR)
-				if actor and self:hasLOS(x, y) then
-					game.level.map.seens(x, y, 0.6)
-				end
-			end, true, true, true)
-		end
-
 		-- Handle infravision/heightened_senses which allow to see outside of lite radius but with LOS
 		-- Note: Overseer of Nations bonus already factored into attributes
 		if self:attr("infravision") or self:attr("heightened_senses") then
@@ -701,26 +688,10 @@ function _M:lineFOV(tx, ty, extra_block, block, sx, sy)
 	local act = game.level.map(x, y, Map.ACTOR)
 	local sees_target = game.level.map.seens(tx, ty)
 
-	local darkVisionRange
-	if self:knowTalent(self.T_DARK_VISION) then
-		local t = self:getTalentFromId(self.T_DARK_VISION)
-		darkVisionRange = self:getTalentRange(t)
-	end
-	local inCreepingDark = false
-
 	extra_block = type(extra_block) == "function" and extra_block
 		or type(extra_block) == "string" and function(_, x, y) return game.level.map:checkAllEntities(x, y, extra_block) end
 
 	block = block or function(_, x, y)
-		if darkVisionRange then
-			if game.level.map:checkAllEntities(x, y, "creepingDark") then
-				inCreepingDark = true
-			end
-			if inCreepingDark and core.fov.distance(sx, sy, x, y) > darkVisionRange then
-				return true
-			end
-		end
-
 		if sees_target then
 			return game.level.map:checkAllEntities(x, y, "block_sight") or
 				game.level.map:checkEntity(x, y, engine.Map.TERRAIN, "block_move") and not game.level.map:checkEntity(x, y, engine.Map.TERRAIN, "pass_projectile") or
diff --git a/game/modules/tome/data/talents/cursed/darkness.lua b/game/modules/tome/data/talents/cursed/darkness.lua
index 09cc7c4600..8868607bf6 100644
--- a/game/modules/tome/data/talents/cursed/darkness.lua
+++ b/game/modules/tome/data/talents/cursed/darkness.lua
@@ -202,7 +202,12 @@ newTalent{
 	createDark = function(summoner, x, y, damage, duration, creep, creepChance, initialCreep)
 		local e = Object.new{
 			name = summoner.name:capitalize() .. "'s creeping dark",
-			block_sight=true,
+			block_sight=function(self, x, y, who)
+				if who and who.attr and who:attr("pierce_creeping_darkness") and x and who.x and core.fov.distance(x, y, who.x, who.y) <= who:attr("pierce_creeping_darkness") then
+					return false
+				end
+				return true
+			end,
 			canAct = false,
 			canCreep = true,
 			x = x, y = y,
@@ -355,6 +360,9 @@ newTalent{
 	getMovementSpeedChange = function(self, t)
 		return self:combatTalentScale(t, 0.75, 2.5, 0.75)
 	end,
+	passives = function(self, t, p)
+		self:talentTemporaryValue(p, "pierce_creeping_darkness", self:getTalentRange(t))
+	end,
 	info = function(self, t)
 		local range = self:getTalentRange(t)
 		local movementSpeedChange = t.getMovementSpeedChange(self, t)
-- 
GitLab