Rethinking Ovale's way of calculating spell info.
ShmooDude opened this issue ยท 1 comments
Right now, Ovale is doing a lot of calculations multiple times when it really needs to only be done a handful. I'm mostly speaking of the power module but there might be other places it's relevant.
Right now, especially with regards to SpellRequire (generally auras increasing/decreasing spell costs) it's doing a lot of calculations everytime PowerCost is called. Using my feral script, that happens something like 1000 times a second. It's the 4th most time consuming function under the profiling (the other big non-BestAction one being OvaleSpellBook_state_IsUsableSpell).
What I'm thinking is this: instead of running all those calculations every time, we precalculate them and only update when necessary. Ovale already does this to some extent in Compile. Most things under SpellInfo are pretty much already done this way (talents, specs, if_spell, etc.). The big thing is for this to happen when it's an aura.
I believe that we can change the logic from checking all the auras every time you want to determine the power cost, to having the auras apply and remove their effects when they are gained/lost. To make the necessary (baseline) calculations, we only need 3 numbers. The cost, the multiplier, and refund. From there, we get to the aura logic. Instead of doing SpellRequire, we will make a new SpellEffect looking like:
SpellEffect(<auraId> <add?><powerType><_percent?> <value>=<spellId>,<spellId>,<spellId>, ...)
What this will do, is upon gaining that aura, the aura module will save and to a table. Something like: si.spellEffect[<spellId>] = { auraId = <auraId>, <add?><powerType><_percent?>=<value>
The power module will then loop through this table (in case there are multiple auras affecting it). This way, we are only checking for the aura if we already know it is (or was) there. It also has the side effect of greatly reducing the number of lines required in the spells file and more resembles how these effects are done in wow's data files.
What I'd like to do from there (which may or may not be viable as I might be bypassing too many necessary checks) is to create essentially a timeline of power costs. So for example Swipe which has 2 auras potentially affecting it:
[baseline] = { cost, multiplier, refund }
40, 1, 0
[aura.gained] = { cost, multiplier, refund }
40, 0.5, 0 (berserk/incarn)
[aura.gained] = { cost, multiplier, refund }
30, 0.5, 0 (scent of blood @ -10)
[aura.ending] = { cost, multiplier, refund }
30, 1, 0 (berserk/incarn)
[aura.ending] = { cost, multiplier, refund }
40, 1, 0 (scent of blood @ -10)
This is updated every time the any of the aura's serial advances. Then all PowerCost has to do is check where within the timeline it falls based on the time it's sent. I might need to include something extra for consuming an aura, not sure.
Are there any obvious flaws in my logic in terms of this being doable? If there are I would think it might have to do with the resetting of the states?
EDIT: I should note that its the 4th highest when soloing on a target dummy. Auras become much more CPU intensive in raids.