Page 1 of 1

Problems with callbackOnTakeDamage

Posted: Wed Jan 31, 2018 8:42 pm
by ghostbuster
I try to make an addon with a talent that converts part of the damage *taken* to a specific type (mind) (for a psionic class that gets some benefits from taking mind damage).

I did not find anything similar in any vaniila or addon talent.
So here is what I tried in the talent code.
The idea is to have a callback in the default projector that reduces the original damage and projects the new converted mind damage on the grid.

Code: Select all

callbackOnTakeDamage = function(self, t, src, x, y, type, dam, tmp)
   local ff = self:isTalentActive(t.id)
   if not ff then return dam end
   if type == DamageType.MIND then	return dam end
   local mdam = dam * t.getMindConvert(self,t)
   DamageType:get(DamageType.MIND).projector(src, x, y, DamageType.MIND, mdam)
   game:delayedLogDamage(self, self, 0, "#YELLOW_GREEN##Target# displaced some damage to its mind!")
    dam = dam - mdam
   return {dam=dam}
end,


There are indeed two different problems:

1/ there is lua error with this code. The problem obviously comes from the call to a projector in the callback.

Code: Select all

Lua Error: /engine/interface/ActorTalents.lua:322: /engine/interface/ActorTalents.lua:295: /engine/interface/ActorTalents.lua:162: /data/damage_types.lu
a:477: attempt to index local 'ret' (a number value)
stack traceback:
        /data/damage_types.lua:477: in function 'projector'
        /data-mentalist/talents/psionic/mental-resilience.lua:59: in function 'callTalent'
        /mod/class/Actor.lua:5247: in function 'cb'
        /data/damage_types.lua:475: in function 'defaultProjector'
        /data/damage_types.lua:703: in function 'projector'
        /mod/class/interface/Combat.lua:600: in function 'attackTargetWith'
        /mod/class/interface/Combat.lua:225: in function 'attackTarget'
        /data/talents/misc/misc.lua:75: in function </data/talents/misc/misc.lua:54>
        [C]: in function 'xpcall'
        /engine/interface/ActorTalents.lua:160: in function </engine/interface/ActorTalents.lua:149>
        At [C]:-1 
        At [C]:-1 error
        At /engine/interface/ActorTalents.lua:322 useTalent
        At /mod/class/interface/Combat.lua:37 attack
   ...
I do not understand what I am doing wrong. Anybody has an idea?

2/ Actually, what I would like to use is callbackOnTakeDamageBeforeResists, instead of callbackOnTakeDamage in order to avoid the double resists application for the original damage and the converted mind damage. If I replace in the talent with callbackOnTakeDamageBeforeResists, absolutely nothing happens. The callback seems to be completely ignored.
I 'grep -r' in the source tree and the callback is only used in one place for an effect that I never noticed (chromatic resonance). Does anybody knows if there is problem with the callback or if I use it incorrectly?

Re: Problems with callbackOnTakeDamage

Posted: Thu Feb 01, 2018 1:29 am
by HousePet
Problem 1:
Remember that dam is sometimes a single value and sometimes a table. You don't seem to have checked for this.
Also, you appear to be taking a single value and then returning it as a value in a table.

Re: Problems with callbackOnTakeDamage

Posted: Thu Feb 01, 2018 7:47 am
by ghostbuster
I changed the code to take into account if dam is a table, but there is still the same error.

Code: Select all

callbackOnTakeDamage = function(self, t, src, x, y, dtype, dam, tmp)
   local ff = self:isTalentActive(t.id)
   if dtype == DamageType.MIND then   return dam end
   local mdam
   if not ff then return dam end
   if type(dam) == 'number' then
      mdam = dam * t.getMindConvert(self,t)
      dam = dam - mdam
   else
      mdam = dam.dam * t.getMindConvert(self,t)
      dam.dam = dam.dam - mdam
   end
   DamageType:get(DamageType.MIND).projector(src, x, y, DamageType.MIND, mdam)
   game:delayedLogDamage(self, self, 0, "#YELLOW_GREEN##Target# displaced some damage to its mind!")
   return dam
end,
Actually, I think the problem is really the call of a projector in the callback. If the line is commented out, there are no longer any error.
It is strange as the default projector in damage_types.lua calls many projectors for damage conversion of the damage dealt. I do not understand why it is not possible to do that in a callback for the damage taken.

Re: Problems with callbackOnTakeDamage

Posted: Thu Feb 01, 2018 5:23 pm
by ghostbuster
I tried in a hook and it worked solving all the problems.

But I was still worried not to understand why my code was incorrect.
I finally discovered that damage hooks always expect that the damage is returned in an array, even if it was initially a number.
So always returning an array fixed the problem.

Code: Select all

callbackOnTakeDamage = function(self, t, src, x, y, dtype, dam, tmp)
   local ff = self:isTalentActive(t.id)
   local ret
   if type(dam) == 'number' then
       ret={dam = dam}
   else
       ret = dam
   end
   if not ff then return ret end
   if dtype == DamageType.MIND then   return ret end
   local mdam = ret.dam * t.getMindConvert(self,t)
   ret.dam = ret.dam- mdam
   DamageType:get(DamageType.MIND).projector(src, x, y, DamageType.MIND, mdam)
   game:delayedLogDamage(self, self, 0, "#YELLOW_GREEN##Target# displaced some damage to its mind!")
   return ret
end,
Concerning problem #2 (using before resist hook), it was probably an interaction with my buggy code. It works well.