When something fires a projectile, it rolls your evasion chance. If it does, it picks a random value from -evasion_spread to +evasion_spread to add to the target x location, and another random value in the same range to add to the target y location.
I don't like this for a number of reasons. First, it only works on projectiles - not beam attacks or ranged weapon hits (like the projecting ego). Secondly, I don't like how it's split into two separate values. Also, the player can get around evasion by just targeting the square behind the enemy with evasion - it's only triggered when the enemy is in the square selected for the shot.
A nice misdirection mechanic that affected the player would probably actually show the enemy in a different location. That's pretty involved, though. I don't think there's any easy way to get a misdirection effect on the player that can't be easily circumvented.
Anyway, I'm suggesting two improvements.
First, I'd like the amount of misdirection to be multiplied by the distance between the two actors, and to have it applied to all actions equally. This would improve two circumstances. An enemy across the room will no longer ignore your misdirection because its a beam attack, and an adjacent enemy will no longer be fooled just because they're trying to hit you with a projectile.
The second is to change the misdirection attribute to be a misdirection area. So, roughly speaking, if you got +4 misdirection for a given attack, then the enemy should target one of 5 random squares, centered on the one you occupy. This'd let you get several misdirection items stack without making it too strong - it's basically a natural square root scaling, but expressed in actual physical terms.
So, the end result would be a misdirection attribute which is your effective misdirection area at range 10. Every tile closer reduces this by 1/9, until there's 0 effective misdirection for adjacent actors.
Proposed code:
Code: Select all
function(self, target)
if not target:attr 'misdirection' then return target.x, target.y end
local distance = core.fov.distance(self.x, self.y, target.x, target.y)
local area = 1 + target.misdirection * (distance - 1) / 9
local radius = math.sqrt(rng.float(0, area) / math.pi)
local angle = rng.float(0, math.pi * 2)
return math.floor(target.x + 0.5 + math.cos(angle) * radius), math.floor(target.y + 0.5 + math.sin(angle) * radius)
end