Thread Tools Display Modes
10/14/23, 02:29 PM   #1
sinnereso
AddOn Author - Click to view addons
Join Date: Oct 2022
Posts: 245
Question 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*"))

Last edited by sinnereso : 10/14/23 at 02:46 PM.
  Reply With Quote
10/14/23, 03:33 PM   #2
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 1,578
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.

Last edited by sirinsidiator : 10/14/23 at 03:36 PM.
  Reply With Quote
10/14/23, 03:47 PM   #3
sinnereso
AddOn Author - Click to view addons
Join Date: Oct 2022
Posts: 245
Originally Posted by sirinsidiator View Post
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.
  Reply With Quote
10/14/23, 04:20 PM   #4
sinnereso
AddOn Author - Click to view addons
Join Date: Oct 2022
Posts: 245
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.

Last edited by sinnereso : 10/14/23 at 05:00 PM.
  Reply With Quote
10/15/23, 03:59 AM   #5
FlatBadger
 
FlatBadger's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2021
Posts: 17
Originally Posted by sinnereso View Post
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
  Reply With Quote
10/15/23, 08:10 AM   #6
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 1,578
Originally Posted by sinnereso View Post
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.
  Reply With Quote
10/15/23, 08:53 AM   #7
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,989
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
  Reply With Quote
10/15/23, 08:57 AM   #8
sinnereso
AddOn Author - Click to view addons
Join Date: Oct 2022
Posts: 245
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".
  Reply With Quote
10/15/23, 09:26 AM   #9
sinnereso
AddOn Author - Click to view addons
Join Date: Oct 2022
Posts: 245
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.
  Reply With Quote

ESOUI » Developer Discussions » General Authoring Discussion » string.find or string.sub question


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off