ESOUI

ESOUI (https://www.esoui.com/forums/index.php)
-   General Authoring Discussion (https://www.esoui.com/forums/forumdisplay.php?f=174)
-   -   string.find or string.sub question (https://www.esoui.com/forums/showthread.php?t=10709)

sinnereso 10/14/23 02:29 PM

string.find or string.sub question
 
Ive been messing with thew new ingame pvp kill feed which i love but I wanted to refine ot to a mmore personal level to not spam out my chat So ive added it to my addon but have been having ocasional popup error which I haven't found the exact cause of.

The new EVENT_PVP_KILL_FEED_DEATH is perfect for my need but has some issues. it fires twice for every kill/death so ive had to make a switch to not display same data twice which was easy enough but now I have a rare popup error "expected integer, got nil" on this line:

Code:

victomCharacterName = victomCharacterName:sub(victomCharacterName:find("^%w+%s*"))
ive been trying different ways to basically strip off the ^M and ^F off the character names to display them in chat. ive tried:

Code:

"^%w+%s*"
"^%w+(%s%w+)"
"^%w+%s*%w*%s*%w*%s*%w*%s*%w*"

its random and works fine 99% of the time. I cant tell if its just too many events too fast issue or something in my code. any ideas?

error example:
Code:

bad argument #2 to 'string.sub' (integer expected, got nil)
stack traceback:
[C]: in function 'string.sub'
user:/AddOns/RidinDirty/RidinDirty.lua:1626: in function 'RidinDirty.KillFeedAudio'
|caaaaaa<Locals> eventCode = 131386, killLocation = "Chalman Keep", killerDisplayName = "@sinnereso", killerCharacterName = "Michael Cullen^Mx", killerAlliance = 2, killerRank = 50, victomDisplayName = "@Irishpierre", victomCharacterName = "Imize^Mx", victomAlliance = 1, victomRank = 16 </Locals>|r

line1626 is the 1st code example:
Code:

victomCharacterName = victomCharacterName:sub(victomCharacterName:find("^%w+%s*"))

sirinsidiator 10/14/23 03:33 PM

Your error happens because string.find can either return 2 numbers when a result is found, or nil otherwise.
As a result, in case the name string does not contain a localization tag like ^F your code will produce an error since string.sub expects two numbers as input.
One solution would be to store the start and end values into local variables and only call sub when start is not nil:
Lua Code:
  1. local startIndex, endIndex = victomCharacterName:find("^%w+%s*")
  2. if startIndex then
  3. victomCharacterName = victomCharacterName:sub(startIndex, endIndex)
  4. end
A (imho) more elegant way would be to let the localization system take care of it for you and simply pass the name through zo_strformat:
Lua Code:
  1. victomCharacterName = zo_strformat("<<1>>", victomCharacterName)

Regardless you should never directly pass return values from one function into another unless you own them, as it's a troublesome source of future errors in case either of them changes their signature and the number of returns or input arguments changes.
For example a while ago ZOS introduced a new argument "_aSuppressCallbackHandler_" to the SetText method of the editbox. In one of my addons I simply passed the return value of another function that returned the text and some extra values since the extras would just go into the void, right? Hope you can imagine how difficult it was to figure out why the code that worked perfectly fine for years suddenly stopped working. ;)

sinnereso 10/14/23 03:47 PM

Quote:

Originally Posted by sirinsidiator (Post 48604)
Your error happens because string.find can either return 2 numbers when a result is found, or nil otherwise.
As a result, in case the name string does not contain a localization tag like ^F your code will produce an error since string.sub expects two numbers as input.
One solution would be to store the start and end values into local variables and only call sub when start is not nil:
Lua Code:
  1. local startIndex, endIndex = victomCharacterName:find("^%w+%s*")
  2. if startIndex then
  3. victomCharacterName = victomCharacterName:sub(startIndex, endIndex)
  4. end
A (imho) more elegant way would be to let the localization system take care of it for you and simply pass the name through zo_strformat:
Lua Code:
  1. victomCharacterName = zo_strformat("<<1>>", victomCharacterName)

Regardless you should never directly pass return values from one function into another unless you own them, as it's a troublesome source of future errors in case either of them changes their signature and the number of returns or input arguments changes.
For example a while ago ZOS introduced a new argument "_aSuppressCallbackHandler_" to the SetText method of the editbox. In one of my addons I simply passed the return value of another function that returned the text and some extra values since the extras would just go into the void, right? Hope you can imagine how difficult it was to figure out why the code that worked perfectly fine for years suddenly stopped working. ;)

ya for sure.. its been tough to 100% fix. Ive been weak on these special characters anyway so I thought this would be good excercise. My issue is im not seeing anything unexpected in the error. As you can see victomCharacterName is a normal "Name^Mx" but still popped the error when 5 kills before that worked fine. I will mention There may be an issue with the new kill feed event double firing which may or may not be related. Ive had to crate a switch to not display the same even twice due to it.

sinnereso 10/14/23 04:20 PM

this seems to be working so far:

Code:

victomCharacterName = victomCharacterName:sub(victomCharacterName:find("^[%w ]+"))
im no expert on other languages but my goal is to keep only alphanumeric and spaces from left to right which will filter out the ^Mx etc. Giving this a whorl a bit here to see if I get the rare error.

EDIT: Still gettin the random error.. ill have to revert back to stock CHARACTER NAME^Mx chat output for now until I get get it sorted. I thought I was gonna be a simple fix.

FlatBadger 10/15/23 03:59 AM

Quote:

Originally Posted by sinnereso (Post 48606)
this seems to be working so far:

Code:

victomCharacterName = victomCharacterName:sub(victomCharacterName:find("^[%w ]+"))
im no expert on other languages but my goal is to keep only alphanumeric and spaces from left to right which will filter out the ^Mx etc. Giving this a whorl a bit here to see if I get the rare error.

EDIT: Still gettin the random error.. ill have to revert back to stock CHARACTER NAME^Mx chat output for now until I get get it sorted. I thought I was gonna be a simple fix.

Have you tried
Code:

victomCharacterName = zo_strformat("<<1>>", victomCharacterName)
as sirinsidiator suggested? That should do the trick for you. I use
Code:

<<C:1>>
to retain initial capitalisation. There's a nice reference here for all your options: https://wiki.esoui.com/How_to_format...h_zo_strformat

sirinsidiator 10/15/23 08:10 AM

Quote:

Originally Posted by sinnereso (Post 48606)
this seems to be working so far:

Code:

victomCharacterName = victomCharacterName:sub(victomCharacterName:find("^[%w ]+"))
im no expert on other languages but my goal is to keep only alphanumeric and spaces from left to right which will filter out the ^Mx etc. Giving this a whorl a bit here to see if I get the rare error.

EDIT: Still gettin the random error.. ill have to revert back to stock CHARACTER NAME^Mx chat output for now until I get get it sorted. I thought I was gonna be a simple fix.

The pattern you used is fine as long as the input string contains the character sequence in question. But as I said, as soon as it doesn't, you will receive an error. There is no other pattern you can use that will fix that. As I explained, you will need to properly handle the case where find does not return anything instead.

In other words, you are making assumptions about the input value that do not seem to hold true. EVENT_PVP_KILL_FEED_DEATH can and will return character names that do not include ^Mx or ^Fx at the end.

Baertram 10/15/23 08:53 AM

Quote:

I will mention There may be an issue with the new kill feed event double firing which may or may not be related. Ive had to crate a switch to not display the same even twice due to it.
https://www.esoui.com/forums/showpos...3&postcount=26

sinnereso 10/15/23 08:57 AM

Code:

victomCharacterName = zo_strformat("<<1>>", victomCharacterName)
works perfectly ty.. I've look at this before a few times but it didn't appear to me capable of removing the gender and I didnt realize they were seperate entities within the original "victomCharacterName".

sinnereso 10/15/23 09:26 AM

Quote:

Originally Posted by Baertram (Post 48611)

im using for the moment this setup:
Code:

function RidinDirty.KillFeedAudio(eventCode, killLocation, killerDisplayName, killerCharacterName, killerAlliance, killerRank, victomDisplayName, victomCharacterName, victomAlliance, victomRank)
        if GetUnitDisplayName('player') == killerDisplayName and RidinDirty.victomName ~= victomDisplayName then--GetUnitName("player")
                RidinDirty.savedVariables.pvpKills = (RidinDirty.savedVariables.pvpKills + 1)
                RidinDirty.victomName = victomDisplayName-- Duplicate entry filter
                PlaySound(RidinDirty.ultSnd)
                if RidinDirty.PvpKillFeedEnabled() then return end
                if not ZO_ShouldPreferUserId() then
                        victomCharacterName = zo_strformat("<<1>>", victomCharacterName)-- Strip gemders
                        df(RidinDirty.logo .. " |cCC6600You have killed " .. tostring(victomCharacterName) .. " [KB-" .. tostring(RidinDirty.savedVariables.pvpKills) .. " / D-" .. tostring(RidinDirty.savedVariables.pvpDeaths) .. "]|r")
                else
                        df(RidinDirty.logo .. " |cCC6600You have killed " .. tostring(victomDisplayName) .. " [KB-" .. tostring(RidinDirty.savedVariables.pvpKills) .. " / D-" .. tostring(RidinDirty.savedVariables.pvpDeaths) .. "]|r")
                end
        elseif GetUnitDisplayName('player') == victomDisplayName and RidinDirty.victomName ~= victomDisplayName then
                RidinDirty.savedVariables.pvpDeaths = (RidinDirty.savedVariables.pvpDeaths + 1)
                RidinDirty.victomName = victomDisplayName-- Duplicate entry filter
                zo_callLater(function() RidinDirty.victomName = "empty" end, 3000)
                if RidinDirty.PvpKillFeedEnabled() then return end
                if not ZO_ShouldPreferUserId() then
                        killerCharacterName = zo_strformat("<<1>>", killerCharacterName)-- Strip genders
                        df(RidinDirty.logo .. " |cCC6600You were killed by " .. tostring(killerCharacterName) .. " [KB-" .. tostring(RidinDirty.savedVariables.pvpKills) .. " / D-" .. tostring(RidinDirty.savedVariables.pvpDeaths) .. "]|r")
                else
                        df(RidinDirty.logo .. " |cCC6600You were killed by " .. tostring(killerDisplayName) .. " [KB-" .. tostring(RidinDirty.savedVariables.pvpKills) .. " / D-" .. tostring(RidinDirty.savedVariables.pvpDeaths) .. "]|r")
                end
        end
end

It does the job except if you kill the same person twice in a row it wont display, but I did work out a reset to allow being killed by same person twice. Ill look into working this fix in..

Also the EVENT_PVP_KILL_FEED_DEATH has the killer & victom charactername/displayname reversed from the event in the api notes.


All times are GMT -6. The time now is 11:24 PM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2014 - 2022 MMOUI