From 2feb6b19b14a0d5a5f0b851667c96113c255875e Mon Sep 17 00:00:00 2001
From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54>
Date: Tue, 5 Jun 2012 22:52:39 +0000
Subject: [PATCH] Gnaw reworked to a special disease that can make a ghoul pop.
 Invoke Tentacle should work anywhere

git-svn-id: http://svn.net-core.org/repos/t-engine4@5200 51575b47-30f0-44d4-a5cc-537603b46e54
---
 game/modules/tome/class/Actor.lua             |  8 +++
 game/modules/tome/data/general/npcs/ghoul.lua |  2 +-
 .../tome/data/talents/corruptions/plague.lua  | 27 +++++---
 game/modules/tome/data/talents/misc/npcs.lua  |  4 +-
 .../tome/data/talents/undeads/ghoul.lua       | 61 ++++++++++++++++---
 .../tome/data/timed_effects/magical.lua       | 29 +++++++++
 6 files changed, 112 insertions(+), 19 deletions(-)

diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua
index 513ca0389a..35d1914bec 100644
--- a/game/modules/tome/class/Actor.lua
+++ b/game/modules/tome/class/Actor.lua
@@ -2015,6 +2015,14 @@ function _M:die(src, death_note)
 			end
 		end)
 	end
+	
+	if self:hasEffect(self.EFF_GHOUL_ROT) then
+		local p = self:hasEffect(self.EFF_GHOUL_ROT)
+		if p.make_ghoul > 0 then
+			local t = p.src:getTalentFromId(p.src.T_GNAW)
+			t.spawn_ghoul(p.src, self, t)
+		end
+	end		
 
 	-- Curse of Corpses: Corpselight
 	-- Curse of Corpses: Reprieve from Death
diff --git a/game/modules/tome/data/general/npcs/ghoul.lua b/game/modules/tome/data/general/npcs/ghoul.lua
index a99f705470..d934bb00df 100644
--- a/game/modules/tome/data/general/npcs/ghoul.lua
+++ b/game/modules/tome/data/general/npcs/ghoul.lua
@@ -48,7 +48,7 @@ newEntity{
 }
 
 newEntity{ base = "BASE_NPC_GHOUL",
-	name = "ghoul", color=colors.TAN,
+	name = "ghoul", color=colors.TAN, define_as = "GHOUL",
 	desc = [[Flesh is falling off in chunks from this decaying abomination.]],
 	level_range = {7, nil}, exp_worth = 1,
 	rarity = 1,
diff --git a/game/modules/tome/data/talents/corruptions/plague.lua b/game/modules/tome/data/talents/corruptions/plague.lua
index 7e49d91ecf..e28471dbc0 100644
--- a/game/modules/tome/data/talents/corruptions/plague.lua
+++ b/game/modules/tome/data/talents/corruptions/plague.lua
@@ -155,10 +155,9 @@ newTalent{
 	type = {"corruption/plague", 3},
 	require = corrs_req3,
 	points = 5,
-	vim = 35,
+	vim = 20,
 	cooldown = 15,
 	range = 6,
-	radius = 2,
 	tactical = { DISABLE = function(self, t, target)
 		-- Make sure the target has a disease
 		for eff_id, p in pairs(target.tmp) do
@@ -170,16 +169,17 @@ newTalent{
 	end },
 	direct_hit = true,
 	requires_target = true,
+	getDamage = function(self, t) return (100 + self:combatTalentSpellDamage(t, 0, 50)) / 100 end,
+	getDuration = function(self, t) return math.floor(2 + self:getTalentLevel(t) / 2) end,
+	getRadius = function(self, t) return 2 + math.floor(self:getTalentLevel(t)/3) end,
 	target = function(self, t)
-		return {type="ball", range=self:getTalentRange(t), radius=self:getTalentRadius(t)}
+		return {type="ball", range=self:getTalentRange(t), radius=t.getRadius(self, t)}
 	end,
 	action = function(self, t)
 		local tg = self:getTalentTarget(t)
 		local x, y = self:getTarget(tg)
 		if not x or not y then return nil end
 
-		local dur = math.floor(2 + self:getTalentLevel(t) / 2)
-
 		local source = nil
 		self:project(tg, x, y, function(px, py)
 			local target = game.level.map(px, py, engine.Map.ACTOR)
@@ -196,11 +196,11 @@ newTalent{
 			-- Make them EXPLODE !!!
 			for i, d in ipairs(diseases) do
 				target:removeEffect(d.id)
-				DamageType:get(DamageType.BLIGHT).projector(self, px, py, DamageType.BLIGHT, self:spellCrit(d.params.dam * d.params.dur))
+				DamageType:get(DamageType.BLIGHT).projector(self, px, py, DamageType.BLIGHT, self:spellCrit(d.params.dam * d.params.dur * t.getDamage(self, t)))
 			end
 
 			if #diseases > 0 and target:canBe("stun") then
-				target:setEffect(target.EFF_STUNNED, dur, {apply_power=self:combatSpellpower()})
+				target:setEffect(target.EFF_STUNNED, t.getDuration(self, t), {apply_power=self:combatSpellpower()})
 			elseif #diseases > 0 then
 				game.logSeen(target, "%s resists the stun!", target.name:capitalize())
 			end
@@ -211,8 +211,11 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
-		return ([[All your foes within a radius 2 ball infected with a disease enter a catalepsy, stunning them for %d turns and dealing all remaining disease damage instantly.]]):
-		format(math.floor(2 + self:getTalentLevel(t) / 2))
+		local radius = t.getRadius(self, t)
+		local duration = t.getDuration(self, t)
+		local damage = t.getDamage(self, t)
+		return ([[All your foes within a radius %d ball infected with a disease enter a catalepsy, stunning them for %d turns and dealing %d%% of all remaining disease damage instantly.]]):
+		format(radius, duration, damage * 100)
 	end,
 }
 
@@ -245,8 +248,12 @@ newTalent{
 			local disease = rng.table(diseases)
 			local params = disease.params
 			params.src = self
+			local disease_spread = { 
+				src=self, dam=disease.params.dam, str=disease.params.str, dex=disease.params.dex, con=disease.params.con, apply_power=self:combatSpellpower(),
+				heal_factor=disease.params.heal_factor, burst=disease.params.burst, rot_timer=disease.params.rot_timer, resist=disease.params.resist, make_ghoul=disease.params.make_ghoul,
+			} 
 			if target:canBe("disease") then
-				target:setEffect(disease.id, 6, {src=self, dam=disease.params.dam, str=disease.params.str, dex=disease.params.dex, con=disease.params.con, heal_factor=disease.params.heal_factor, burst=disease.params.burst, rot_timer=disease.params.rot_timer, resist=disease.params.resist, apply_power=self:combatSpellpower()})
+				target:setEffect(disease.id, 6, disease_spread)
 			else
 				game.logSeen(target, "%s resists the disease!", target.name:capitalize())
 			end
diff --git a/game/modules/tome/data/talents/misc/npcs.lua b/game/modules/tome/data/talents/misc/npcs.lua
index 52fe778877..65e31e2217 100644
--- a/game/modules/tome/data/talents/misc/npcs.lua
+++ b/game/modules/tome/data/talents/misc/npcs.lua
@@ -1181,10 +1181,12 @@ newTalent{
 		end
 
 		-- Find an actor with that filter
-		local m = game.zone:makeEntityByName(game.level, "actor", "GRGGLCK_TENTACLE")
+		local list = mod.class.NPC:loadList("/data/general/npcs/horror.lua")
+		local m = list.GRGGLCK_TENTACLE:clone()
 		if m then
 			m.exp_worth = 0
 			m:resolve()
+			m:resolve(nil, true)
 
 			m.summoner = self
 			m.summon_time = 10
diff --git a/game/modules/tome/data/talents/undeads/ghoul.lua b/game/modules/tome/data/talents/undeads/ghoul.lua
index 84b2ee2217..bc7d8caff0 100644
--- a/game/modules/tome/data/talents/undeads/ghoul.lua
+++ b/game/modules/tome/data/talents/undeads/ghoul.lua
@@ -120,29 +120,76 @@ newTalent{
 	require = undeads_req4,
 	points = 5,
 	cooldown = 15,
-	tactical = { ATTACK = 0.5, DISABLE = { stun = 2 } },
+	tactical = { ATTACK = {BLIGHT = 2} },
 	range = 1,
 	requires_target = true,
+	getDamage = function(self, t) return 0.2 + self:getTalentLevel(t) / 12 end,
+	getDuration = function(self, t) return 3 + math.ceil(self:getTalentLevel(t)) end,
+	getDiseaseDamage = function(self, t) return self:combatTalentStatDamage(t, "con", 5, 50) end,
+	getStatDamage = function(self, t) return self:combatTalentStatDamage(t, "con", 5, 20) end,
+	spawn_ghoul = function (self, target, t)
+		local x, y = util.findFreeGrid(target.x, target.y, 10, true, {[Map.ACTOR]=true})
+		if not x then return nil end
+
+		local list = mod.class.NPC:loadList("/data/general/npcs/ghoul.lua")
+		local m = list.GHOUL
+		if not m then return nil end
+
+		m:resolve() m:resolve(nil, true)
+		m.ai = "summoned"
+		m.ai_real = "dumb_talented_simple"
+		m.faction = self.faction
+		m.summoner = self
+		m.summoner_gain_exp = true
+		m.summon_time = 20
+		m.exp_worth = 0
+		m.no_drops = true
+		
+		game.zone:addEntity(game.level, m, "actor", target.x, target.y)
+		game.level.map:particleEmitter(target.x, target.y, 1, "slime")
+		game:playSoundNear(target, "talents/slime")
+		game.logPlayer(game.player, "A #DARK_GREEN#ghoul#LAST# rises from the corpse of %s.", target.name)
+	end,
 	action = function(self, t)
 		local tg = {type="hit", range=self:getTalentRange(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, 0.2 + self:getTalentLevel(t) / 12, true)
+		local hitted = self:attackTarget(target, nil, t.getDamage(self, t), true)
 
+		-- Damage Stats?
+		local str_damage, con_damage, dex_damage = 0
+		if self:getTalentLevel(t) >=2 then str_damage = t.getStatDamage(self, t) end
+		if self:getTalentLevel(t) >=3 then dex_damage = t.getStatDamage(self, t) end
+		if self:getTalentLevel(t) >=4 then con_damage = t.getStatDamage(self, t) end
+		
+		-- Ghoulify??
+		local ghoulify = 0
+		if self:getTalentLevel(t) >=5 then ghoulify = 1 end
+		
 		if hitted then
-			if target:canBe("stun") then
-				target:setEffect(target.EFF_STUNNED, 3 + math.ceil(self:getTalentLevel(t)), {apply_power=self:combatAttack()})
+			if target:canBe("disease") then
+				if target.dead and ghoulify > 0 then
+					t.spawn_ghoul(self, target, t)
+				end
+				target:setEffect(target.EFF_GHOUL_ROT, 3 + math.ceil(self:getTalentLevel(t)), {src=self, apply_power=self:combatPhysicalpower(), dam=t.getDiseaseDamage(self, t), str=str_damage, con=con_damage, dex=dex_damage, make_ghoul=ghoulify})
 			else
-				game.logSeen(target, "%s resists the stun!", target.name:capitalize())
+				game.logSeen(target, "%s resists the disease!", target.name:capitalize())
 			end
 		end
 
 		return true
 	end,
 	info = function(self, t)
-		return ([[Gnaw your target doing %d%% damage, trying to stun it instead of damaging it. If your attack hits, the target is stunned for %d turns.]]):
-		format(100 * (0.2 + self:getTalentLevel(t) / 12), 3 + math.ceil(self:getTalentLevel(t)))
+		local damage = t.getDamage(self, t)
+		local duration = t.getDuration(self, t)
+		local disease_damage = t.getDiseaseDamage(self, t)
+		local stat_damage = t.getStatDamage(self, t)
+		return ([[Gnaw your target for %d%% damage.  If your attack hits, the target may be infected with ghoul rot for %d turns.
+		Each turn Ghoul Rot inflicts %0.2f blight damage.  At talent level two Ghoul Rot also reduces Strength by %d, at level three it reduces Dexterity by %d, and at level four it reduces Constitution by %d.
+		At talent level five targets suffering from Ghoul Rot rise as friendly ghouls when slain.
+		The blight damage and stat damage scales with your Constitution.]]):
+		format(100 * damage, duration, damDesc(self, DamageType.BLIGHT, disease_damage), stat_damage, stat_damage, stat_damage)
 	end,
 }
 
diff --git a/game/modules/tome/data/timed_effects/magical.lua b/game/modules/tome/data/timed_effects/magical.lua
index fdc4bbc036..787cc42cdb 100644
--- a/game/modules/tome/data/timed_effects/magical.lua
+++ b/game/modules/tome/data/timed_effects/magical.lua
@@ -1541,6 +1541,35 @@ newEffect{
 	end,
 }
 
+newEffect{
+	name = "GHOUL_ROT", image = "talents/gnaw.png",
+	desc = "Ghoul Rot",
+	long_desc = function(self, eff)
+		local ghoulify = ""
+		if eff.make_ghoul > 0 then ghoulify = "  If the target dies while ghoul rot is active it will rise as a ghoul." end
+		return ("The target is infected by a disease, reducing its strength by %d, dexterity by %d, constitution by %d, and doing %0.2f blight damage per turn.%s"):format(eff.str, eff.dex, eff.con, eff.dam, ghoulify)
+	end,
+	type = "magical",
+	subtype = {disease=true, blight=true},
+	status = "detrimental",
+	parameters = {},
+	on_gain = function(self, err) return "#Target# is afflicted by ghoul rot!" end,
+	on_lose = function(self, err) return "#Target# is free from the ghoul rot." end,
+	-- Damage each turn
+	on_timeout = function(self, eff)
+		if self:attr("purify_disease") then self:heal(eff.dam)
+		else DamageType:get(DamageType.BLIGHT).projector(eff.src, self.x, self.y, DamageType.BLIGHT, eff.dam, {from_disease=true})
+		end
+	end,
+	-- Lost of CON
+	activate = function(self, eff)
+		eff.tmpid = self:addTemporaryValue("inc_stats", {[Stats.STAT_STR] = -eff.str, [Stats.STAT_DEX] = -eff.dex, [Stats.STAT_CON] = -eff.con})
+	end,
+	deactivate = function(self, eff)
+		self:removeTemporaryValue("inc_stats", eff.tmpid)
+	end,
+}
+
 newEffect{
 	name = "BLOODCASTING", image = "talents/bloodcasting.png",
 	desc = "Bloodcasting",
-- 
GitLab