Skip to content
Snippets Groups Projects
Commit 69c76743 authored by dg's avatar dg
Browse files

Fix for Frenzy

Beckon, Panic and Paranoia should be less annoying to deal with


git-svn-id: http://svn.net-core.org/repos/t-engine4@4867 51575b47-30f0-44d4-a5cc-537603b46e54
parent d40f89d9
No related branches found
No related tags found
No related merge requests found
...@@ -103,7 +103,7 @@ newTalent{ ...@@ -103,7 +103,7 @@ newTalent{
return math.min(20, math.floor(5 + self:getTalentLevel(t) * 2)) return math.min(20, math.floor(5 + self:getTalentLevel(t) * 2))
end, end,
getChance = function(self, t) getChance = function(self, t)
return math.min(75, math.floor(42 + (math.sqrt(self:getTalentLevel(t)) - 1) * 20)) return math.min(75, math.floor(25 + (math.sqrt(self:getTalentLevel(t)) - 1) * 20))
end, end,
getSpellpowerChange = function(self, t) getSpellpowerChange = function(self, t)
return -self:combatTalentStatDamage(t, "wil", 8, 33) return -self:combatTalentStatDamage(t, "wil", 8, 33)
...@@ -132,7 +132,7 @@ newTalent{ ...@@ -132,7 +132,7 @@ newTalent{
local chance = t.getChance(self, t) local chance = t.getChance(self, t)
local spellpowerChange = t.getSpellpowerChange(self, t) local spellpowerChange = t.getSpellpowerChange(self, t)
local mindpowerChange = t.getMindpowerChange(self, t) local mindpowerChange = t.getMindpowerChange(self, t)
return ([[The connection between predator and prey allows you to speak to the mind of your target and beckon them closer. For %d turns they will try to come to you, even pushing others aside to do so. There is a %d%% chance each turn that they will move towards you instead of acting. The chance is halved if the target saves versus Mindpower and the effect may be dispelled if the target takes significant damage. The effect makes concentration difficult for your target, reducing spellpower and mindpower by %d until they reach you. return ([[The connection between predator and prey allows you to speak to the mind of your target and beckon them closer. For %d turns they will try to come to you, even pushing others aside to do so. They will move towards you instead of acting %d%% of the time but can save verses Mindpower to slow the effect. If they take significant damage, the beckoning may be overcome altogether. The effect makes concentration difficult for your target, reducing spellpower and mindpower by %d until they reach you.
Spellpower and Mindpower reduction increases with the Willpower stat.]]):format(duration, chance, -spellpowerChange) Spellpower and Mindpower reduction increases with the Willpower stat.]]):format(duration, chance, -spellpowerChange)
end, end,
} }
......
...@@ -32,10 +32,10 @@ newTalent{ ...@@ -32,10 +32,10 @@ newTalent{
return 8 return 8
end, end,
getParanoidAttackChance = function(self, t) getParanoidAttackChance = function(self, t)
return math.min(50, self:combatTalentMindDamage(t, 25, 40)) return math.min(60, self:combatTalentMindDamage(t, 30, 50))
end, end,
getDespairResistAllChange = function(self, t) getDespairResistAllChange = function(self, t)
return -self:combatTalentMindDamage(t, 15, 35) return -self:combatTalentMindDamage(t, 15, 40)
end, end,
hasEffect = function(self, t, target) hasEffect = function(self, t, target)
if target:hasEffect(target.EFF_PARANOID) then return true end if target:hasEffect(target.EFF_PARANOID) then return true end
...@@ -95,6 +95,8 @@ newTalent{ ...@@ -95,6 +95,8 @@ newTalent{
for i = 1, duration do for i = 1, duration do
eff.counts[i] = math.floor(eff.count / duration) + ((eff.count % duration >= i) and 1 or 0) eff.counts[i] = math.floor(eff.count / duration) + ((eff.count % duration >= i) and 1 or 0)
end end
else
print("* fears: failed to get effect", effectId)
end end
target:setEffect(effectId, duration, eff) target:setEffect(effectId, duration, eff)
...@@ -221,7 +223,7 @@ newTalent{ ...@@ -221,7 +223,7 @@ newTalent{
return 3 + math.floor(math.pow(self:getTalentLevel(t), 0.5) * 2.2) return 3 + math.floor(math.pow(self:getTalentLevel(t), 0.5) * 2.2)
end, end,
getChance = function(self, t) getChance = function(self, t)
return math.floor(25 + (math.sqrt(self:getTalentLevel(t)) - 1) * 20) return math.min(60, math.floor(30 + (math.sqrt(self:getTalentLevel(t)) - 1) * 22))
end, end,
action = function(self, t) action = function(self, t)
local range = self:getTalentRange(t) local range = self:getTalentRange(t)
......
...@@ -104,6 +104,7 @@ newTalent{ ...@@ -104,6 +104,7 @@ newTalent{
local attackChange = t.getAttackChange(self, t) local attackChange = t.getAttackChange(self, t)
local effStalker = self:hasEffect(self.EFF_STALKER) local effStalker = self:hasEffect(self.EFF_STALKER)
if core.fov.distance(self.x, self.y, effStalker.target.x, effStalker.target.y) > 1 then effStalker = nil end
for i = 1, 4 do for i = 1, 4 do
local target local target
if effStalker and not effStalker.target.dead then if effStalker and not effStalker.target.dead then
......
...@@ -434,53 +434,68 @@ newEffect{ ...@@ -434,53 +434,68 @@ newEffect{
do_act = function(self, eff) do_act = function(self, eff)
if eff.source.dead then if eff.source.dead then
self:removeEffect(self.EFF_BECKONED) self:removeEffect(self.EFF_BECKONED)
return
end end
if not self:enoughEnergy() then return nil end if not self:enoughEnergy() then return nil end
local distance = core.fov.distance(self.x, self.y, eff.source.x, eff.source.y) -- apply periodic timer instead of random chance
if math.floor(distance) > 1 and distance <= eff.range then if not eff.timer then
-- in range but not adjacent eff.timer = rng.float(0, 100)
end
-- add debuffs if not self:checkHit(eff.source:combatMindpower(), self:combatMentalResist(), 0, 95, 5) then
if not eff.spellpowerChangeId then eff.spellpowerChangeId = self:addTemporaryValue("combat_spellpower", eff.spellpowerChange) end eff.timer = eff.timer + eff.chance * 0.5
if not eff.mindpowerChangeId then eff.mindpowerChangeId = self:addTemporaryValue("combat_mindpower", eff.mindpowerChange) end game.logSeen(self, "#F53CBE#%s struggles against the beckoning.", self.name:capitalize())
else
-- custom pull logic (adapted from move_dmap; forces movement, pushes others aside, custom particles) eff.timer = eff.timer + eff.chance
local chance = eff.chance end
if self:checkHit(eff.source:combatMindpower(), self:combatMentalResist(), 0, 95, 5) then chance = chance * 0.5 end
if not self:attr("never_move") and rng.percent(chance) then if eff.timer > 100 then
local source = eff.source eff.timer = eff.timer - 100
local moveX, moveY = source.x, source.y -- move in general direction by default
if not self:hasLOS(source.x, source.y) then local distance = core.fov.distance(self.x, self.y, eff.source.x, eff.source.y)
local a = Astar.new(game.level.map, self) if math.floor(distance) > 1 and distance <= eff.range then
local path = a:calc(self.x, self.y, source.x, source.y) -- in range but not adjacent
if path then
moveX, moveY = path[1].x, path[1].y -- add debuffs
if not eff.spellpowerChangeId then eff.spellpowerChangeId = self:addTemporaryValue("combat_spellpower", eff.spellpowerChange) end
if not eff.mindpowerChangeId then eff.mindpowerChangeId = self:addTemporaryValue("combat_mindpower", eff.mindpowerChange) end
-- custom pull logic (adapted from move_dmap; forces movement, pushes others aside, custom particles)
if not self:attr("never_move") then
local source = eff.source
local moveX, moveY = source.x, source.y -- move in general direction by default
if not self:hasLOS(source.x, source.y) then
local a = Astar.new(game.level.map, self)
local path = a:calc(self.x, self.y, source.x, source.y)
if path then
moveX, moveY = path[1].x, path[1].y
end
end end
end
if moveX and moveY then if moveX and moveY then
local old_move_others, old_x, old_y = self.move_others, self.x, self.y local old_move_others, old_x, old_y = self.move_others, self.x, self.y
self.move_others = true self.move_others = true
local old = rawget(self, "aiCanPass") local old = rawget(self, "aiCanPass")
self.aiCanPass = mod.class.NPC.aiCanPass self.aiCanPass = mod.class.NPC.aiCanPass
mod.class.NPC.moveDirection(self, moveX, moveY, false) mod.class.NPC.moveDirection(self, moveX, moveY, false)
self.aiCanPass = old self.aiCanPass = old
self.move_others = old_move_others self.move_others = old_move_others
if old_x ~= self.x or old_y ~= self.y then if old_x ~= self.x or old_y ~= self.y then
game.level.map:particleEmitter(self.x, self.y, 1, "beckoned_move", {power=power, dx=self.x - source.x, dy=self.y - source.y}) game.level.map:particleEmitter(self.x, self.y, 1, "beckoned_move", {power=power, dx=self.x - source.x, dy=self.y - source.y})
end
end end
end end
end else
else -- adjacent or out of range..remove debuffs
-- adjacent or out of range..remove debuffs if eff.spellpowerChangeId then
if eff.spellpowerChangeId then self:removeTemporaryValue("combat_spellpower", eff.spellpowerChangeId)
self:removeTemporaryValue("combat_spellpower", eff.spellpowerChangeId) eff.spellpowerChangeId = nil
eff.spellpowerChangeId = nil end
end if eff.mindpowerChangeId then
if eff.mindpowerChangeId then self:removeTemporaryValue("combat_mindpower", eff.mindpowerChangeId)
self:removeTemporaryValue("combat_mindpower", eff.mindpowerChangeId) eff.mindpowerChangeId = nil
eff.mindpowerChangeId = nil end
end end
end end
end, end,
...@@ -916,7 +931,19 @@ newEffect{ ...@@ -916,7 +931,19 @@ newEffect{
do_act = function(self, eff) do_act = function(self, eff)
if not self:enoughEnergy() then return nil end if not self:enoughEnergy() then return nil end
if rng.percent(eff.attackChance) then -- apply periodic timer instead of random chance
if not eff.timer then
eff.timer = rng.float(0, 100)
end
if not self:checkHit(eff.source:combatMindpower(), self:combatMentalResist(), 0, 95, 5) then
eff.timer = eff.timer + eff.attackChance * 0.5
game.logSeen(self, "#F53CBE#%s struggles against the paranoia.", self.name:capitalize())
else
eff.timer = eff.timer + eff.attackChance
end
if eff.timer > 100 then
eff.timer = eff.timer - 100
local start = rng.range(0, 8) local start = rng.range(0, 8)
for i = start, start + 8 do for i = start, start + 8 do
local x = self.x + (i % 3) - 1 local x = self.x + (i % 3) - 1
...@@ -924,8 +951,8 @@ newEffect{ ...@@ -924,8 +951,8 @@ newEffect{
if (self.x ~= x or self.y ~= y) then if (self.x ~= x or self.y ~= y) then
local target = game.level.map(x, y, Map.ACTOR) local target = game.level.map(x, y, Map.ACTOR)
if target then if target then
game.logSeen(self, "#F53CBE#%s attacks %s in a fit of paranoia.", self.name, target.name) game.logSeen(self, "#F53CBE#%s attacks %s in a fit of paranoia.", self.name:capitalize(), target.name)
if self:attackTarget(target, nil, 1, false) then if self:attackTarget(target, nil, 1, false) and target ~= eff.source then
if not target:canBe("fear") then if not target:canBe("fear") then
game.logSeen(target, "#F53CBE#%s ignores the fear!", target.name:capitalize()) game.logSeen(target, "#F53CBE#%s ignores the fear!", target.name:capitalize())
elseif not target:checkHit(eff.mindpower, target:combatMentalResist()) then elseif not target:checkHit(eff.mindpower, target:combatMentalResist()) then
...@@ -1143,38 +1170,52 @@ newEffect{ ...@@ -1143,38 +1170,52 @@ newEffect{
if not self:enoughEnergy() then return nil end if not self:enoughEnergy() then return nil end
if eff.source.dead then return true end if eff.source.dead then return true end
local distance = core.fov.distance(self.x, self.y, eff.source.x, eff.source.y) -- apply periodic timer instead of random chance
if distance <= eff.range then if not eff.timer then
-- in range eff.timer = rng.float(0, 100)
if not self:attr("never_move") and rng.percent(eff.chance) then end
local sourceX, sourceY = eff.source.x, eff.source.y if not self:checkHit(eff.source:combatMindpower(), self:combatMentalResist(), 0, 95, 5) then
eff.timer = eff.timer + eff.chance * 0.5
local bestX, bestY game.logSeen(self, "#F53CBE#%s struggles against the panic.", self.name:capitalize())
local bestDistance = 0 else
local start = rng.range(0, 8) eff.timer = eff.timer + eff.chance
for i = start, start + 8 do end
local x = self.x + (i % 3) - 1 if eff.timer > 100 then
local y = self.y + math.floor((i % 9) / 3) - 1 eff.timer = eff.timer - 100
if x ~= self.x or y ~= self.y then local distance = core.fov.distance(self.x, self.y, eff.source.x, eff.source.y)
local distance = core.fov.distance(x, y, sourceX, sourceY) if distance <= eff.range then
if distance > bestDistance -- in range
and game.level.map:isBound(x, y) if not self:attr("never_move") then
and not game.level.map:checkAllEntities(x, y, "block_move", self) local sourceX, sourceY = eff.source.x, eff.source.y
and not game.level.map(x, y, Map.ACTOR) then
bestDistance = distance local bestX, bestY
bestX = x local bestDistance = 0
bestY = y local start = rng.range(0, 8)
for i = start, start + 8 do
local x = self.x + (i % 3) - 1
local y = self.y + math.floor((i % 9) / 3) - 1
if x ~= self.x or y ~= self.y then
local distance = core.fov.distance(x, y, sourceX, sourceY)
if distance > bestDistance
and game.level.map:isBound(x, y)
and not game.level.map:checkAllEntities(x, y, "block_move", self)
and not game.level.map(x, y, Map.ACTOR) then
bestDistance = distance
bestX = x
bestY = y
end
end end
end end
end
if bestX then
if bestX then self:move(bestX, bestY, false)
self:move(bestX, bestY, false) game.logPlayer(self, "#F53CBE#You panic and flee from %s.", eff.source.name)
game.logPlayer(self, "#F53CBE#You panic and flee from %s.", eff.source.name) else
else game.logSeen(self, "#F53CBE#%s panics and tries to flee from %s.", self.name:capitalize(), eff.source.name)
game.logSeen(self, "#F53CBE#%s panics and tries to flee from %s.", self.name:capitalize(), eff.source.name) self:useEnergy(game.energy_to_act * self:combatMovementSpeed(bestX, bestY))
self:useEnergy(game.energy_to_act * self:combatMovementSpeed(bestX, bestY)) end
end end
end end
end end
...@@ -1863,7 +1904,7 @@ newEffect{ ...@@ -1863,7 +1904,7 @@ newEffect{
addEffect = function(self, eff) addEffect = function(self, eff)
if eff.physicalResistId then self:removeTemporaryValue("resists", eff.physicalResistId) end if eff.physicalResistId then self:removeTemporaryValue("resists", eff.physicalResistId) end
eff.physicalResistId = self:addTemporaryValue("resists", { [DamageType.PHYSICAL]=eff.physicalResistChange }) eff.physicalResistId = self:addTemporaryValue("resists", { [DamageType.PHYSICAL]=eff.physicalResistChange })
local maxId local maxId
local maxValue = 0 local maxValue = 0
for id, def in ipairs(self.stats_def) do for id, def in ipairs(self.stats_def) do
...@@ -1992,9 +2033,9 @@ newEffect{ ...@@ -1992,9 +2033,9 @@ newEffect{
if old_eff.incStatsId then self:removeTemporaryValue("inc_stats", old_eff.incStatsId) end if old_eff.incStatsId then self:removeTemporaryValue("inc_stats", old_eff.incStatsId) end
old_eff.incStats = nil old_eff.incStats = nil
old_eff.incStatsId = nil old_eff.incStatsId = nil
self.tempeffect_def[self.EFF_MIMIC].activate(self, new_eff) self.tempeffect_def[self.EFF_MIMIC].activate(self, new_eff)
return new_eff return new_eff
end end
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment