If you are adjacent to the said wall, the freeze may hit youself instead.
This bug had been here since 1.2 or some time like that, and the cause of this bug may be more confusing that it seemed.
In code data/talents/spells/ice.lua:42
Code: Select all
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 _ _, _, _, x, y = self:canProject(tg, x, y)
local target = game.level.map(x, y, Map.ACTOR)
if not x or not y then return nil end
Code: Select all
local _ _, _, _, x, y = self:canProject(tg, x, y)
The function defination of canProject have five return values
can_project, stop_x, stop_y, radius_x, radius_y
(stop_x, stop_y) is for where the projection stops.
That is, if you throw a bolt or beam to a wall, the projectile will hit into the wall, for exact one tile.
(radius_x, radius_y) is for where radius effect should start from.
That is, if you throw a fireball, the ball should stay out of the wall.
Or, the AoE damage can cross a 1-width wall and hit foes at the other side of the wall.
In this case, Freeze use the latter returned pair, which means it can't hit enemy in wall, and may hit its user instead.
And because Freeze use "hit" and is not considered as a projectile, it will really do damage to you.
Simply changing it to
Code: Select all
local _ _, x, y = self:canProject
That is because Freeze will become a ball with Essence of the Dead, so it should check this to choose the correct return value.
However, the wrong code will still act normally here. Because even it gives a wrong coordinate, another function project for really apply the damage will still avoid hitting into the wall, upon knowing it's a ball. That is what in case with Warp Mine.
After searching canProject in the source code, I found it have widespread usage in talent code and many other codes, in fact, 342 occurances. Its usage is mostly correct, but maybe with a few exceptions, like the Freeze that we have discovered in this post. The real damage is mostly done by a function project, which will do the check that canProject have already done. So, most of the usage of this function is purely graphical, like, to show the graphical effect of talents. So, it would only cause a graphical bug at most.
However, some of them will be used to determine the target, and a few of them may mistakely use a wrong return value. Mostly this misuse will not cause any bug because of additional sanity check, or project correcting fix the bug of ball like targets using (stop_x, stop_y). Currently, Freeze is the only violator that may cause real problem I have seen after investigate some usages, but somebody may discover something else. (Anomaly Displacement Shield is one, but you can't cast it manually most of the time, and you won't want to cast it on enemy in wall even if you can do so, so it is okay) Also, I am not sure about its usage among addon creators, but a few of them may use a wrong function call like Freeze.
While the whole targeting code in talent seemed a bit inconsistent among all the talents, it would take really much more work to reconstruct, so it would be better to leave them intact. just give some more indicative alias for the two type of function calls may be helpful for addon developer, however.
Also, the two function have some redundant code, and even some difference if you compare them. They also share some redundant code with engine/Target.lua. I myself can't explain all of those differences, but at least the following line seem to be a bug.
In engine/interface/ActorProject.lua:56
Code: Select all
typ.start_y = typ.start_y or typ.y or typ.source_actor and typ.source_actor.y or self.x