ToME: the Tales of Maj'Eyal

Everything about ToME
It is currently Sat Oct 21, 2017 1:51 pm

All times are UTC




Post new topic Reply to topic  [ 10 posts ] 
Author Message
PostPosted: Sun Jun 18, 2017 9:22 am 
Offline
Sher'Tul Godslayer

Joined: Mon Feb 14, 2011 11:16 pm
Posts: 2257
I'm trying to modify _M:onTakeHit in Actor.lua, by superloading a new version of the function.

I'm not sure how to set the return value and reference the local onTakeHit

here is what I have:

Code:
local _M = loadPrevious(...)
require "engine.class"
require "engine.Actor"
require "engine.Autolevel"
require "engine.interface.ActorInventory"
require "engine.interface.ActorTemporaryEffects"
require "mod.class.interface.ActorLife"
require "engine.interface.ActorProject"
require "engine.interface.ActorLevel"
require "engine.interface.ActorStats"
require "engine.interface.ActorTalents"
require "engine.interface.ActorResource"
require "engine.interface.BloodyDeath"
require "engine.interface.ActorFOV"
require "mod.class.interface.ActorPartyQuest"
require "mod.class.interface.Combat"
require "mod.class.interface.Archery"
require "mod.class.interface.ActorInscriptions"
local Faction = require "engine.Faction"
local Dialog = require "engine.ui.Dialog"
local Map = require "engine.Map"
local DamageType = require "engine.DamageType"

local onTakeHit = _M.onTakeHit
function _M:onTakeHit(value, src, death_note)
   src = src or {}
   if value <=0 then return 0 end
...

return value


With what do I replace "return 0" in the code? Is it "return onTakeHit(self, 0)"

and same for "return value"? Is it "return onTakeHit(self, value, src, death_note)" ?

thanks for your assistance!!

_________________
MADNESS rocks


Top
 Profile  
 
PostPosted: Sun Jun 18, 2017 1:45 pm 
Offline
Spiderkin

Joined: Mon Sep 21, 2015 8:45 pm
Posts: 504
Location: Middle of Nowhere
How you want to set up your new onTakeHit will kind of depend on what you want it do differently from the original. Basically, you will want to run the values through the original onTakeHit, making changes either before or after doing so (or both before and after, in some cases), and then return your new result.

Here are a couple examples from HousePet's Midnight and Verdant addons, respectively:
Code:
local basetakeHit = _M.takeHit
function _M:takeHit(value, src, death_note)
    -- Do stuff "before" loading the original file
    local dead, val = basetakeHit(self, value, src, death_note)  -- Loads the original file
    -- Do stuff "after" loading the original file
   if val and self:isTalentActive(self.T_HP_BLOOD_OF_THE_HEAVENS) then
      self:incNegative(math.floor(val/10))
   end
   
   if dead and src then
      if src:getEntityKind() == "actor" then
         if src:knowTalent(src.T_HP_DISCIPLE_OF_DUSK) and src:isTalentActive(src.T_HP_DISCIPLE_OF_DUSK) then
            local t = src:getTalentFromId(src.T_HP_DISCIPLE_OF_DUSK)
            src:incNegative(t.getNegativeRegen(self, t))
         end
      end
   end
   
    return dead, val
end


and

Code:
local basetakeHit = _M.takeHit
function _M:takeHit(value, src, death_note)
    -- Do stuff "before" loading the original file
    local dead, val = basetakeHit(self, value, src, death_note)  -- Loads the original file
    -- Do stuff "after" loading the original file
   if dead and src then
      if src:getEntityKind() == "actor" then
         local summoner = src.summoner
         if src:knowTalent(src.T_HP_FERTILIZE) then
            local t = src:getTalentFromId(src.T_HP_FERTILIZE)
            t.doFertilize(src, t, self)
         elseif summoner then
            if summoner:knowTalent(summoner.T_HP_FERTILIZE) then
               local t = summoner:getTalentFromId(summoner.T_HP_FERTILIZE)
               t.doFertilize(summoner, t, self)   
            end
         end
      end
   end
    return dead, val
end


Looks like you would want to use "local dead, val = onTakeHit(self, value, src, death_note)" to get your original return value (or, in this case, values, as it looks like it returns two). So, in your case:
Code:
local onTakeHit = _M.onTakeHit
function _M:onTakeHit(value, src, death_note)
   local dead, val = onTakeHit(self, value, src, death_note)
   ...

   return dead, val

The "src = src or {}" and "if value <=0 then return 0 end" are in the original onTakeHit, so you don't really need to have this in your new onTakeHit, unless you want to change how that part of the function works. If you do want to change that, you should drop that above HP's note of "do stuff 'before' loading the original file" (neither of these examples actually makes changes before loading the original, only after).

Whenever I get into this stuff, I basically rip open other mods until I find one that does something similar to what I'm trying to do, copy and change it, then proceed with trial and error until I get it to do what I want it to.

And when that fails, turn to #tome on rizon IRC. Put your question out there and idle, odds are someone will be able to help you out.

Hopefully that was more helpful than confusing :wink:


Top
 Profile  
 
PostPosted: Sun Jun 18, 2017 9:21 pm 
Offline
Spiderkin

Joined: Mon Sep 21, 2015 8:45 pm
Posts: 504
Location: Middle of Nowhere
I saw your post in the ideas forum regarding Bone Shield... is that why you were looking to modify onTakeHit? If that's the case, you would pretty much have to just copy the entirety of the original function and make the changes you want within the portion that checks for Bone Shield. Which is not a good idea from a comparability perspective, not to mention you would have to update it every time ToME was updated with a change to onTakeHit. Basically, if you want to add new stuff into onTakeHit, it's not too bad, but if you want to modify stuff that's already in there, it's too messy.

Based on my knowledge and ability, at least.


Top
 Profile  
 
PostPosted: Sun Jun 18, 2017 9:23 pm 
Offline
Sher'Tul Godslayer

Joined: Mon Feb 14, 2011 11:16 pm
Posts: 2257
Thanks. That was helpful.

I want to change code inside the original function however so I think I have to superload a new version of the function.

I took your advice still and found something like what I need and it seems to be working.

_________________
MADNESS rocks


Top
 Profile  
 
PostPosted: Sun Jun 18, 2017 9:27 pm 
Offline
Sher'Tul Godslayer

Joined: Mon Feb 14, 2011 11:16 pm
Posts: 2257
nsrr wrote:
I saw your post in the ideas forum regarding Bone Shield... is that why you were looking to modify onTakeHit? If that's the case, you would pretty much have to just copy the entirety of the original function and make the changes you want within the portion that checks for Bone Shield. Which is not a good idea from a comparability perspective, not to mention you would have to update it every time ToME was updated with a change to onTakeHit. Basically, if you want to add new stuff into onTakeHit, it's not too bad, but if you want to modify stuff that's already in there, it's too messy.

Based on my knowledge and ability, at least.


Yes and no. Because of my testing so far I've noticed bone shields is triggered on average by 0.5-1.5 damage! Hence my other post. But I'm not sure if that could be done in the talent? Otherwise, yes it would require also modifying onhit.

_________________
MADNESS rocks


Top
 Profile  
 
PostPosted: Sun Jun 18, 2017 9:49 pm 
Offline
Spiderkin

Joined: Mon Sep 21, 2015 8:45 pm
Posts: 504
Location: Middle of Nowhere
jenx wrote:
nsrr wrote:
I saw your post in the ideas forum regarding Bone Shield... is that why you were looking to modify onTakeHit? If that's the case, you would pretty much have to just copy the entirety of the original function and make the changes you want within the portion that checks for Bone Shield. Which is not a good idea from a comparability perspective, not to mention you would have to update it every time ToME was updated with a change to onTakeHit. Basically, if you want to add new stuff into onTakeHit, it's not too bad, but if you want to modify stuff that's already in there, it's too messy.

Based on my knowledge and ability, at least.


Yes and no. Because of my testing so far I've noticed bone shields is triggered on average by 0.5-1.5 damage! Hence my other post. But I'm not sure if that could be done in the talent? Otherwise, yes it would require also modifying onhit.


Hmm... well, technically onTakeHit checks if the damage is above 0 and if the talent is sustained and then calls the talents 'absorb' function. It might be possible to just change that function to implement a low-cap on the damage, but I'm not entirely sure. I would have to spend a little more time studying it.


Top
 Profile  
 
PostPosted: Mon Jun 19, 2017 4:59 am 
Offline
Spiderkin

Joined: Mon Sep 21, 2015 8:45 pm
Posts: 504
Location: Middle of Nowhere
Okay, so I managed to jerry-rig something by modifying onTakeHit and altering the absorb function inside of Bone Shield. Seems to work, at least when Bone Shield is your only damage mitigation, but it should also take into account all of the shields and such that might reduce damage before Bone Shield would normally trigger... I just don't have the time to test all of them.

If you want to be the guinea pig, the addon is attached. It's not uploaded, so it will invalidate your save if you use it, but I'm pretty sure you don't care about that.

If everything checks out, let me know and I will upload the addon.

One thing I did notice with my testing was that in some cases it seemed that only a certain number of bone shields would trigger in one turn, so it appeared that some damage was getting through even if it was above the threshold. Both times it was from Irresistible Sun, once from Aeryn in Orcs, and once from Alluin in AoA. I can't see any reason that the changes I made would cause this to happen, but /shrug. Maybe I can look into it a bit more on my next day off.


Attachments:
tome-boneshield_tweak.zip [6.04 KiB]
Downloaded 11 times
Top
 Profile  
 
PostPosted: Mon Jun 19, 2017 9:40 am 
Offline
Sher'Tul Godslayer

Joined: Mon Feb 14, 2011 11:16 pm
Posts: 2257
nsrr wrote:
Okay, so I managed to jerry-rig something by modifying onTakeHit and altering the absorb function inside of Bone Shield. Seems to work, at least when Bone Shield is your only damage mitigation, but it should also take into account all of the shields and such that might reduce damage before Bone Shield would normally trigger... I just don't have the time to test all of them.

If you want to be the guinea pig, the addon is attached. It's not uploaded, so it will invalidate your save if you use it, but I'm pretty sure you don't care about that.

If everything checks out, let me know and I will upload the addon.

One thing I did notice with my testing was that in some cases it seemed that only a certain number of bone shields would trigger in one turn, so it appeared that some damage was getting through even if it was above the threshold. Both times it was from Irresistible Sun, once from Aeryn in Orcs, and once from Alluin in AoA. I can't see any reason that the changes I made would cause this to happen, but /shrug. Maybe I can look into it a bit more on my next day off.


ok, i downloaded and checked your code.

I reckon there is a dead easy way to do this however, simply by changing if value > 0 to if value > min_dmg. let's say it's set to 25:

Code:
if value > 25 and self:isTalentActive(self.T_BONE_SHIELD) then
      local oldval = value
      local t = self:getTalentFromId(self.T_BONE_SHIELD)
      if t.absorb(self, t, self:isTalentActive(self.T_BONE_SHIELD)) then
            game:delayedLogDamage(src, self, 0, ("#SLATE#(%d to bones)#LAST#"):format(value), false)
            value = 0
      end
end

_________________
MADNESS rocks


Top
 Profile  
 
PostPosted: Mon Jun 19, 2017 5:10 pm 
Offline
Spiderkin

Joined: Mon Sep 21, 2015 8:45 pm
Posts: 504
Location: Middle of Nowhere
I mean, if you want to just edit your own Actor file and change the value on the Bone Shield check to something higher than zero, sure, that would do it.

I was looking at this from an addon perspective, and in order to make a change like that would require basically overwriting the entire onTakeHit function. That's the worst way to do it, from a compatibility stand point.

My method does re-use a portion of the onTakeHit code, but only for the sake of calculating what the damage value would be at the point where it would normally be passed to Bone Shield. If the manner or order of those sources of damage mitigation were to change, it could mess with my code, but the only other way to do it, that I could see, would be to have it based on the original, un-mitigated damage. As I understood it, the reason that Bone Shields are often wasted on insignificant damage is because it has already been mitigated by other talents by the time it gets to the Bone Shield check, so we want our new check to take those sources of damage reduction into account.

In order to make sure all of the other stuff that occurs in onTakeHit will still happen, we need to pass the value back to the original function and let it run through... which means it will get passed back to the original Bone Shield check and trigger Bone Shield's 'absorb' function, which does not take the value of the damage as a parameter. See, my method modifies the 'absorb' function to give it a couple of extra, optional parameters. When my modified onTakeHit is run, the very first thing it will do is see if Bone Shield is active. If it is, we call Bone Shield's 'absorb' function, passing it everything 'absorb' normally expects, plus two new parameters. One is a simple boolean, to trigger the damage check, and the other is the damage value, which we run through dummy versions of all of the damage mitigation that normally occurs before Bone Shield, to ensure we are checking the fully mitigated value. (I refer to these as dummy versions because they don't trigger any of the stuff that would happen when these other mechanics are actually called, such as reducing the remaining value of a damage shield, for instance. We are only interested in how these would affect the value, which is why we store the original 'value' as a separate variable and then set 'value' back to that original number at the end, after we do our check, so that onTakeHit will still be working with the proper number when all of these mechanics are actually called.)

So, we pass the boolean, to trigger the check, and the mitigated value. The modified 'absorb' function will now see that boolean is true and check the value we pass it against the threshold we added to Bone Shield. If the value is below the threshold, we pass a 'true' back to onTakeHit, and from there it will set a temporary value for the actor. Then, when the original onTakeHit is run, it will do the original Bone Shield check for any value greater than zero, and call the 'absorb' function. Our modified 'absorb' function now has a check for that temporary value, and if it is set (meaning the damage was below the threshold) then it will abort the function, just as it would if your bone shield was out of charges. In this way we can essentially check the damage value without having to change the original 'absorb' call, which does not pass on the damage value.

I understand that is probably confusing and hard to follow, but that's about the best I can explain it.

I actually had to keep referencing back to my addon to get all of that straight. In doing so, I think I realized what was causing the shield to fail to trigger sometimes. I forgot to clear the temporary value before each check against the threshold, so once it was set it would stay set until the end of the turn, when all such temp values are automatically cleared. Meaning that any damage above the threshold would get through if occurred during the same turn but after a value that was below the threshold. That should be fixed now, but I still need to check it. I also still need to check if the interaction with all of those other sources of mitigation is working. Might take a while for me to test it all, but if you want to try out this updated version, it's attached.


Attachments:
tome-boneshield_tweak.zip [6.06 KiB]
Downloaded 8 times
Top
 Profile  
 
PostPosted: Mon Jun 19, 2017 6:06 pm 
Offline
Spiderkin

Joined: Mon Sep 21, 2015 8:45 pm
Posts: 504
Location: Middle of Nowhere
Meh, I verified that I fixed the issue it had before and I gave it cursory check to make sure most of common forms of mitigation (such as damage shields) are being properly accounted for, so I uploaded it. Could be a bug in there somewhere, at least as far as the mitigation calculation that comes before the check is concerned, but a lot of those are things that someone with Bone Shield is unlikely to have, anyway, such as Mitosis.

I'll have a thread for it up in a minute.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 10 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group