Download
(12 Kb)
Download
Updated: 10/29/21 07:43 AM
Pictures
File Info
Compatibility:
Waking Flame (7.1.5)
Updated:10/29/21 07:43 AM
Created:06/20/18 05:41 AM
Monthly downloads:1,640
Total downloads:263,484
Favorites:212
MD5:
Categories:Casting Bars, Cooldowns, Combat Mods
Light Attack Helper  Popular! (More than 5000 hits)
Version: 4.2
by: kafeijao [More]
Light Attack Helper is a tool that helps you track your light attacks, it does this by incrementing a counter each time you actually hit a light attack.

Changelog
Version 4.2
  • Fixed not working for nightblades on the german localization.
Version 4.1
  • Fixed for the german localization.
Version 4.0
  • Fixed the addon for the current patch (Sorry for the delay).
  • Added a debug mode, check bellow how to use if you are having issues.
Version 3.5 - IMPORTANT CHANGE
This addon depends on the following libraries:
When you start to do light attack weaving normally you either do it too fast or too slow, the ideal is doing as fast as possible but still having the light attacks to register, this is where this addon comes in handy, to help you finding the sweet spot.

Since these days the light attacks are the most damaging ability, one of the best ways to improve dps is actually to perform better your light attack weaving. Light attack weaving is always using a light attack in between your skill abilities, this paired with animation canceling of the light attacks makes your damage spike, you can check on youtube for videos about Elder Scrolls Online animation canceling for further information.

The la/s is the light attacks per second from a fight. So if you want to push yourself try to increase this number as much as possible in your fights. I am tracking the light attacking information from the server, so the times will be influenced by your latency(ping), and the latency(ping) is not very constant so you might find a bit of floating values.

You can use /laprintfull to see the statistics from the parse, for example the max and min values to see if your parse was falwless, for example if you get a minimum lower than 800ms probably it means that you did 2 light attacks without a skill in between, and if the maximum is higher than 1800 probably means that you used two skills without a light attack in between (This of course depends on the skills used, as channeled skills will have a much longer light attack time in between).

Commands:
  • /laprint - Prints the last combat's light attack / s ratio.
  • /laprintfull - Prints the last combat's full statisctics.
  • /lapost - Posts to the chat the last combat's light attack / s ratio (send to people).
  • /lapostfull - Posts to the chat the last combat's full statisctics (send to people)
  • /lareset - Resets the light attack counter to 0.


Notes:
  1. The counter for ranged attacks will increment as soon as you shoot the light attack (if it knows it will hit) instead of when it actually hits, if it was on actual hit it would count the light attack after you barswap (if you do bar swap animation cancel) which feels a bit weird if you have the option to reset on barswap.
  2. The addon will not detect medium attacks from lightning and restoration staves, even if you enable counting the Heavy Attacks in the settings.


DEBUG
If the addon is not counting a Light or Heavy Attacks for a particular weapon, or at all (maybe because a different language) follow this instructions and post it in the comments.
  1. Enable Debug Mode in the addon settings (it's at the bottom of the settings).
  2. Type /reloadui in your chat to clear the chat.
  3. Using an attack dummy in a player house, perform a single Heavy or Light attack (the one that is not counting).
  4. You will see a bunch of information in the chat. Take a screenshot all the info (you might need several screenshots if it's a lot of info).
  5. Post the screenshot(s) in the comments section AND provide the information: Type of weapon (eg: Duel Wield), Game Language (eg: English), and a brief description of the problem.

Thanks
Thanks @wambo for implementing LibChatMessage and making the libraries external.
Thanks WalterMort, FAR747, Beltroniko, mjbc, and nogetrandom for helping in the comments in my absence.
Thanks Anubis for providing the fix for the german localization.
Thanks Saenic for providing the fix for nightblades to work on german localization.
Version 4.2
+ Fixed german localization on nightblades.

Version 4.1
+ Fixed the strings for the german language.

Version 4.0
+ Fixed the ability names checking for the new DLC.
+ Fixed the count on Heavy attacks to not proc a single time.
+ Added a debug mode to be able to get logs from the users in case of issues.
+ API Bump

Version 3.5
+ Removed included libraries, now you need to install LibAddonMenu-2.0 and LibChatMessage libraries.
+ Implemented LibChatMessage (by @wambo)
+ API Bump

Version 3.4
+ Code cleanup and api Bump (I think xd).

Version 3.3
+ Code cleanup and api Bump.

Version 3.3
+ Fixed one issue where light attacks were not being detected on ranged attacks.

Version 3.2
+ Fixed one issue that happened when grouped.


Version 3.1
  • Added the display light attacks per second.
  • Changed the settings menu for better hide/show components.
  • Added the command /laprint /laprintfull /lapost /lapostfull to display statistics from the last fight.
  • Added event filters to improve performance.

Version 3.0
  • Added the display of the milliseconds between each light attack.
  • Added the option to hide and set the size for the milliseconds part on the settings.
  • Added the command /laprint to display statistics from the last fight.

Version 2.2
  • Added support for German and French clients. Maybe Japanese aswell (needs testing)

Version 2.1
  • Added font options on settings (Font, size, border, and color).
Optional Files (1)
File Name
Version
Size
Author
Date
Type
3.6
10kB
07/17/21 03:05 AM
Patch


Archived Files (11)
File Name
Version
Size
Uploader
Date
4.1
12kB
kafeijao
10/10/21 11:49 AM
4.0
12kB
kafeijao
10/09/21 05:39 AM
3.5
11kB
kafeijao
05/22/20 02:29 PM
3.4
56kB
kafeijao
03/11/19 09:23 PM
3.3
56kB
kafeijao
10/10/18 05:02 PM
3.2
56kB
kafeijao
10/10/18 03:49 PM
3.1
56kB
kafeijao
10/10/18 09:20 AM
3.0
53kB
kafeijao
07/13/18 08:37 AM
2.2
51kB
kafeijao
07/05/18 07:33 PM
2.1
49kB
kafeijao
07/03/18 01:08 PM
2.0
49kB
kafeijao
06/20/18 05:41 AM


Post A Reply Comment Options
Unread 06/04/21, 06:16 AM  
python1980

Forum posts: 0
File comments: 9
Uploads: 0
Yeah you got it. It works very well, thank you a lot.




Originally Posted by Beltroniko
But which weapons you were using? Dual Wield? like dual daggers?

You could try this one instead of the one I posted:

Code:
if abilityActionSlotType == ACTION_SLOT_TYPE_LIGHT_ATTACK and LightAttackHelper.playerName == sourceName and string.find(tostring(abilityName),"leichter") and string.find(tostring(abilityName),"angriff") and LightAttackHelper.isTheActualAttackCast(hitValue) then
But I can't test it, so I'm not sure if it works, if it does it will only work for german and I'm not even sure if it would work for all weapon types or types different from the one you used

I hope someone can jump in and get a much better fix for the issue
Report comment to moderator  
Reply With Quote
Unread 06/04/21, 06:10 AM  
python1980

Forum posts: 0
File comments: 9
Uploads: 0
yes dual weapon



Originally Posted by Beltroniko
But which weapons you were using? Dual Wield? like dual daggers?

You could try this one instead of the one I posted:

Code:
if abilityActionSlotType == ACTION_SLOT_TYPE_LIGHT_ATTACK and LightAttackHelper.playerName == sourceName and string.find(tostring(abilityName),"leichter") and string.find(tostring(abilityName),"angriff") and LightAttackHelper.isTheActualAttackCast(hitValue) then
But I can't test it, so I'm not sure if it works, if it does it will only work for german and I'm not even sure if it would work for all weapon types or types different from the one you used

I hope someone can jump in and get a much better fix for the issue
Report comment to moderator  
Reply With Quote
Unread 06/04/21, 06:04 AM  
Beltroniko

Forum posts: 0
File comments: 5
Uploads: 0
But which weapons you were using? Dual Wield? like dual daggers?

You could try this one instead of the one I posted:

Code:
if abilityActionSlotType == ACTION_SLOT_TYPE_LIGHT_ATTACK and LightAttackHelper.playerName == sourceName and string.find(tostring(abilityName),"leichter") and string.find(tostring(abilityName),"angriff") and LightAttackHelper.isTheActualAttackCast(hitValue) then
But I can't test it, so I'm not sure if it works, if it does it will only work for german and I'm not even sure if it would work for all weapon types or types different from the one you used

I hope someone can jump in and get a much better fix for the issue
Report comment to moderator  
Reply With Quote
Unread 06/04/21, 05:59 AM  
python1980

Forum posts: 0
File comments: 9
Uploads: 0
Re: Re: Re: Re: Re: AddOn Fix

I used leichter Angriff / light attack and rapid strikes

here you can search in english an get the german word for the skills https://www.elderscrollsbote.de/skills/?n=flurry&l=-1&t%5B%5D=1&t%5B%5D=2&t%5B%5D=4




Originally Posted by Beltroniko
Originally Posted by python1980
you got a pn, thanks very much.
I saw your prints but it's harder to fix in german, we'd probably need someone more knowledgeable with LUA language to help.

What I see is that in your case, the game is comparing:
A - leichter Angriff -> (I suppose this is Light Attack?)
B - leichter Doppleangriff -> (I suppose this is a Dual wield light attack? is this what you were using?)

So when the game compares both, it fails, cause they are not the same, and using my method (that sees if string B starts with string A) or mjbc's method (that sees is string B contains string A) it will still fail, cause if you look at those same strings in english:

A - Light Attack
B - Light Attack (Dual Wield)

Both "StartsWith" and "Compare" methods will work.

I hope someone more knowledgeable in Addon coding can come here and help fixing it for german as well. In the mean-time if you could send all the "light attack type" names with every weapon in german I think it would help whoever is able to do it greatly.
If they all use the same pattern as leichter Doppleangriff I might actually be able to make a very ugly coded german-only temporary fix for it, but I'd need to see all "light attack types" in text first.
Last edited by python1980 : 06/04/21 at 06:09 AM.
Report comment to moderator  
Reply With Quote
Unread 06/04/21, 05:45 AM  
Beltroniko

Forum posts: 0
File comments: 5
Uploads: 0
Re: Re: Re: Re: AddOn Fix

Originally Posted by python1980
you got a pn, thanks very much.
I saw your prints but it's harder to fix in german, we'd probably need someone more knowledgeable with LUA language to help.

What I see is that in your case, the game is comparing:
A - leichter Angriff -> (I suppose this is Light Attack?)
B - leichter Doppleangriff -> (I suppose this is a Dual wield light attack? is this what you were using?)

So when the game compares both, it fails, cause they are not the same, and using my method (that sees if string B starts with string A) or mjbc's method (that sees is string B contains string A) it will still fail, cause if you look at those same strings in english:

A - Light Attack
B - Light Attack (Dual Wield)

Both "StartsWith" and "Compare" methods will work.

I hope someone more knowledgeable in Addon coding can come here and help fixing it for german as well. In the mean-time if you could send all the "light attack type" names with every weapon in german I think it would help whoever is able to do it greatly.
If they all use the same pattern as leichter Doppleangriff I might actually be able to make a very ugly coded german-only temporary fix for it, but I'd need to see all "light attack types" in text first.
Last edited by Beltroniko : 06/04/21 at 05:48 AM.
Report comment to moderator  
Reply With Quote
Unread 06/04/21, 05:32 AM  
python1980

Forum posts: 0
File comments: 9
Uploads: 0
Re: Re: AddOn Fix

Doesn´t work in german too. :-( there is still no count of light attacks





I solved it with

Code:
if abilityActionSlotType == ACTION_SLOT_TYPE_LIGHT_ATTACK and LightAttackHelper.playerName == sourceName and zo_plainstrfind(abilityName, GetString(LAH_LIGHT_ATTACK)) and LightAttackHelper.isTheActualAttackCast(hitValue) then
But I don't know which one is faster, didn't do any perf tests.[/quote]
Report comment to moderator  
Reply With Quote
Unread 06/04/21, 05:23 AM  
python1980

Forum posts: 0
File comments: 9
Uploads: 0
Re: Re: Re: AddOn Fix

you got a pn, thanks very much.




Hey python,

In able to be able to help, and make it work in German, I'd need you to do something first, so that I can see the values that are involved.

I'd need you to add this line before the "if" I mentioned in my main comment:

d("DEBUG - Ability Name - " .. tostring(abilityName) .. " - " .. tostring(GetString(LAH_LIGHT_ATTACK)) .. " Result: " .. tostring(abilityName == GetString(LAH_LIGHT_ATTACK)))

After you do it, reload UI and make a couple light attacks and skills in a target dummy, then send me the results you get in the chat window.

Don't forget to remove this line again (or add "--") before it and reload again so that you don't get that message everytime you do an action.[/quote]
Last edited by python1980 : 06/04/21 at 05:23 AM.
Report comment to moderator  
Reply With Quote
Unread 06/04/21, 05:22 AM  
Beltroniko

Forum posts: 0
File comments: 5
Uploads: 0
Oh nice, that should also fix it for other languages. I'm not knowledgeable of the ESO/Lua functions but I'd assume that zo_plainstrfind works like a "contains" in common languages? If so I'd say it's the best solution.

Performance wise I also have no idea how things affect the game but I'd risk saying both should be very lightweight operations and shouldn't affect anything, don't you think?
Report comment to moderator  
Reply With Quote
Unread 06/04/21, 05:04 AM  
mjbc

Forum posts: 0
File comments: 3
Uploads: 0
Re: AddOn Fix

Originally Posted by Beltroniko
Hey guys,

I had never seen LUA code, but I'm so dependent on this addon that I decided to give it a look and try to understand what was going on. My solution is not the most elegant one programming wise but it works and from my tests it doesn't break anything. I'm sure someone more experienced with LUA code and that understands how the game works better will come up with a more elegant one.

Basically the problem was this part of the if clause in the onCombatEvent handler:
abilityName == GetString(LAH_LIGHT_ATTACK)

Something must have changed in the game, that the first part returns "Light Attack (<weapon type>)" so for example it returns "Light Attack (Inferno)" while the second part just returns "Light Attack"... I guess this was changed in the game and before this patch it returned "Light Attack" without the weapon type.

So, the solution is to find this piece of code on line 674 (remove word wrap on notepad and use ctrl+g to find it):

Code:
if abilityActionSlotType == ACTION_SLOT_TYPE_LIGHT_ATTACK and LightAttackHelper.playerName == sourceName and abilityName == GetString(LAH_LIGHT_ATTACK) and LightAttackHelper.isTheActualAttackCast(hitValue) then
For:

Code:
if abilityActionSlotType == ACTION_SLOT_TYPE_LIGHT_ATTACK and LightAttackHelper.playerName == sourceName and string.sub(tostring(abilityName),1,string.len(tostring(GetString(LAH_LIGHT_ATTACK)))) == GetString(LAH_LIGHT_ATTACK) and LightAttackHelper.isTheActualAttackCast(hitValue) then
Basically what this does is checking if the first string starts with "Light Attack", ignoring the rest of it.

I'm not sure if this will fix it in languages other then english, it will depend if the "type" of the light attack comes after the "light attack" description or not, if this is the case and I have time I can try to help fixing it.

Hope this fixes it for you guys.
I solved it with

Code:
if abilityActionSlotType == ACTION_SLOT_TYPE_LIGHT_ATTACK and LightAttackHelper.playerName == sourceName and zo_plainstrfind(abilityName, GetString(LAH_LIGHT_ATTACK)) and LightAttackHelper.isTheActualAttackCast(hitValue) then
But I don't know which one is faster, didn't do any perf tests.
Report comment to moderator  
Reply With Quote
Unread 06/04/21, 04:56 AM  
Beltroniko

Forum posts: 0
File comments: 5
Uploads: 0
Re: Re: AddOn Fix

Originally Posted by python1980
Originally Posted by Beltroniko
Hey guys,

I had never seen LUA code, but I'm so dependent on this addon that I decided to give it a look and try to understand what was going on. My solution is not the most elegant one programming wise but it works and from my tests it doesn't break anything. I'm sure someone more experienced with LUA code and that understands how the game works better will come up with a more elegant one.

Basically the problem was this part of the if clause in the onCombatEvent handler:
abilityName == GetString(LAH_LIGHT_ATTACK)

Something must have changed in the game, that the first part returns "Light Attack (<weapon type>)" so for example it returns "Light Attack (Inferno)" while the second part just returns "Light Attack"... I guess this was changed in the game and before this patch it returned "Light Attack" without the weapon type.

So, the solution is to find this piece of code on line 674 (remove word wrap on notepad and use ctrl+g to find it):

Code:
if abilityActionSlotType == ACTION_SLOT_TYPE_LIGHT_ATTACK and LightAttackHelper.playerName == sourceName and abilityName == GetString(LAH_LIGHT_ATTACK) and LightAttackHelper.isTheActualAttackCast(hitValue) then
For:

Code:
if abilityActionSlotType == ACTION_SLOT_TYPE_LIGHT_ATTACK and LightAttackHelper.playerName == sourceName and string.sub(tostring(abilityName),1,string.len(tostring(GetString(LAH_LIGHT_ATTACK)))) == GetString(LAH_LIGHT_ATTACK) and LightAttackHelper.isTheActualAttackCast(hitValue) then
Basically what this does is checking if the first string starts with "Light Attack", ignoring the rest of it.

I'm not sure if this will fix it in languages other then english, it will depend if the "type" of the light attack comes after the "light attack" description or not, if this is the case and I have time I can try to help fixing it.

Hope this fixes it for you guys.
Doesn´t work in Germany. pls help
Hey python,

In able to be able to help, and make it work in German, I'd need you to do something first, so that I can see the values that are involved.

I'd need you to add this line before the "if" I mentioned in my main comment:

d("DEBUG - Ability Name - " .. tostring(abilityName) .. " - " .. tostring(GetString(LAH_LIGHT_ATTACK)) .. " Result: " .. tostring(abilityName == GetString(LAH_LIGHT_ATTACK)))

After you do it, reload UI and make a couple light attacks and skills in a target dummy, then send me the results you get in the chat window.

Don't forget to remove this line again (or add "--") before it and reload again so that you don't get that message everytime you do an action.
Report comment to moderator  
Reply With Quote
Unread 06/04/21, 02:04 AM  
python1980

Forum posts: 0
File comments: 9
Uploads: 0
Re: AddOn Fix

Originally Posted by Beltroniko
Hey guys,

I had never seen LUA code, but I'm so dependent on this addon that I decided to give it a look and try to understand what was going on. My solution is not the most elegant one programming wise but it works and from my tests it doesn't break anything. I'm sure someone more experienced with LUA code and that understands how the game works better will come up with a more elegant one.

Basically the problem was this part of the if clause in the onCombatEvent handler:
abilityName == GetString(LAH_LIGHT_ATTACK)

Something must have changed in the game, that the first part returns "Light Attack (<weapon type>)" so for example it returns "Light Attack (Inferno)" while the second part just returns "Light Attack"... I guess this was changed in the game and before this patch it returned "Light Attack" without the weapon type.

So, the solution is to find this piece of code on line 674 (remove word wrap on notepad and use ctrl+g to find it):

Code:
if abilityActionSlotType == ACTION_SLOT_TYPE_LIGHT_ATTACK and LightAttackHelper.playerName == sourceName and abilityName == GetString(LAH_LIGHT_ATTACK) and LightAttackHelper.isTheActualAttackCast(hitValue) then
For:

Code:
if abilityActionSlotType == ACTION_SLOT_TYPE_LIGHT_ATTACK and LightAttackHelper.playerName == sourceName and string.sub(tostring(abilityName),1,string.len(tostring(GetString(LAH_LIGHT_ATTACK)))) == GetString(LAH_LIGHT_ATTACK) and LightAttackHelper.isTheActualAttackCast(hitValue) then
Basically what this does is checking if the first string starts with "Light Attack", ignoring the rest of it.

I'm not sure if this will fix it in languages other then english, it will depend if the "type" of the light attack comes after the "light attack" description or not, if this is the case and I have time I can try to help fixing it.

Hope this fixes it for you guys.
Doesn´t work in Germany. pls help
Report comment to moderator  
Reply With Quote
Unread 06/03/21, 09:38 PM  
Beltroniko

Forum posts: 0
File comments: 5
Uploads: 0
AddOn Fix

Hey guys,

I had never seen LUA code, but I'm so dependent on this addon that I decided to give it a look and try to understand what was going on. My solution is not the most elegant one programming wise but it works and from my tests it doesn't break anything. I'm sure someone more experienced with LUA code and that understands how the game works better will come up with a more elegant one.

Basically the problem was this part of the if clause in the onCombatEvent handler:
abilityName == GetString(LAH_LIGHT_ATTACK)

Something must have changed in the game, that the first part returns "Light Attack (<weapon type>)" so for example it returns "Light Attack (Inferno)" while the second part just returns "Light Attack"... I guess this was changed in the game and before this patch it returned "Light Attack" without the weapon type.

So, the solution is to find this piece of code on line 674 (remove word wrap on notepad and use ctrl+g to find it):

Code:
if abilityActionSlotType == ACTION_SLOT_TYPE_LIGHT_ATTACK and LightAttackHelper.playerName == sourceName and abilityName == GetString(LAH_LIGHT_ATTACK) and LightAttackHelper.isTheActualAttackCast(hitValue) then
For:

Code:
if abilityActionSlotType == ACTION_SLOT_TYPE_LIGHT_ATTACK and LightAttackHelper.playerName == sourceName and string.sub(tostring(abilityName),1,string.len(tostring(GetString(LAH_LIGHT_ATTACK)))) == GetString(LAH_LIGHT_ATTACK) and LightAttackHelper.isTheActualAttackCast(hitValue) then
Basically what this does is checking if the first string starts with "Light Attack", ignoring the rest of it.

I'm not sure if this will fix it in languages other then english, it will depend if the "type" of the light attack comes after the "light attack" description or not, if this is the case and I have time I can try to help fixing it.

Hope this fixes it for you guys.
Last edited by Beltroniko : 06/03/21 at 09:47 PM.
Report comment to moderator  
Reply With Quote
Unread 06/03/21, 04:25 PM  
Shantoo

Forum posts: 0
File comments: 27
Uploads: 0
Originally Posted by Zand3rs
Has anyone figured out what the problem is yet?
I'm no LUA programmer but I think somewhere in this code is the issue:

****

local lastLA = GetGameTimeMilliseconds()
function LightAttackHelper.updateRatio(counts)

local wasFirstLA = false
local msValue

if counts then
if not LightAttackHelper.shotFirstLightAttack then
wasFirstLA = true
LightAttackHelper.shotFirstLightAttack = true
lastLA = GetGameTimeMilliseconds()
LightAttackHelper.msNumbers = {}

else
local thisLA = GetGameTimeMilliseconds()
msValue = thisLA - lastLA
table.insert(LightAttackHelper.msNumbers, msValue)
lastLA = thisLA
end
end

LightAttackHelperWindowInfo:SetText("")

if LightAttackHelper.savedVariables.displayedUnderTheCounter == "LA/Second" then

if LightAttackHelper.combatStartedTimeMs == nil then
LightAttackHelperWindowInfo:SetText("8 la/s")
else

local combatDuration = GetGameTimeMilliseconds() - LightAttackHelper.combatStartedTimeMs
local laRatio = string.format("%.2f", 1000 * (#LightAttackHelper.msNumbers + 1) / combatDuration) .. " la/s"
LightAttackHelperWindowInfo:SetText(laRatio)

end

*****

In this section of the code:

local laRatio = string.format("%.2f", 1000 * (#LightAttackHelper.msNumbers + 1) / combatDuration) .. " la/s"

LightAttackHelper.msNumbers is always returning a zero, so the ratio ends up being the result of dividing 1 by the combatDuration.

I also had to comment out the " if counts then" section to get that far. So it may be a few things. Hopefully someone smarter than me about this stuff can be more helpful. Really would like to get this to work.
Report comment to moderator  
Reply With Quote
Unread 06/03/21, 08:18 AM  
Zand3rs
AddOn Author - Click to view AddOns

Forum posts: 5
File comments: 16
Uploads: 2
Has anyone figured out what the problem is yet?
Report comment to moderator  
Reply With Quote
Unread 06/02/21, 04:58 PM  
nodmg

Forum posts: 0
File comments: 1
Uploads: 0
blackwood update ?

i allways used this addon cant even dps without lol pls update for blackwood
Report comment to moderator  
Reply With Quote
Post A Reply



Category Jump: