GetIdByName userfunction (GetQuest, Skill And Buff Id)

Additional botting resources. Addons may be either for the game itself or for the RoM bot.
Forum rules
Only post additional bot resources here. Please do not ask unrelated questions.
Post Reply
Message
Author
kenzu38
Posts: 279
Joined: Sun Dec 02, 2012 8:52 am

GetIdByName userfunction (GetQuest, Skill And Buff Id)

#1 Post by kenzu38 » Fri Oct 09, 2015 5:00 pm

So here's a userfunction I made. Only tested it for a bit so this is a beta release. It didn't crash client though and seems like the functions are doing what they're supposed to do.


EDIT: released v1.2 beta, it's now a lot faster than before because the search method has been changed.

Common in all functions:

- Search string is not case-sensitive.

- All functions print results as they are found in table format.

- All functions return values. If only a single match is found, it only returns the id (or system text if you're using GetSysText). If nothing is found, it returns false.

Syntax:

Limits are the Search Range limits

Exact Match can only be true or false, it defaults to true which means only exact matches will be processed, put false to process partial matches. Putting nothing or nil in the exact match argument will default to true.

GetIdByName(search string, exact match, first lower limit, first upper limit, second lower limit, second upper limit)

- By default, it has no range limits so it searches the whole range but it is limited to only process stuff that has Sys(digits)_name as their system text.

Examples:
GetIdByName("dragon") -- will not find any match, there's plenty of dragons in game but there's not one that has only the name dragon.
GetIdByName("dragon", false) -- finds 593 matches.
GetIdByName("dragon", false, 100000, 120000) -- matches found cut to 58 as the range has been cut down considerably.
GetIdByName("dragon", false, 100000, 120000, 230000, 300000) -- matches found back up to 121 with the added search range.


GetQuestId(search string, quest type filter, exact match, first lower limit, first upper limit, second lower limit, second upper limit)

- Quest type argument should be either "normal", "daily" or "public". Anything other than those will default to "all", in which case the bot will return every quest type.

- Prints matches in table format. The table includes the Level and the Type apart from the Name and Id.

- By default, it only processes ids between 420000 and 430000 coz that's where quests are, but you can override it anytime through the function's arguments. You can change the default values (420000 - 430000) permanently in the user options section of the file.


Examples:
GetQuestId("juice") -- will not find any match
GetQuestId("juice delivery") -- prints and returns the id 422917
GetQuestId("juice", nil, false) -- nil defaults to "all" and we only searched for partial match. Will return 5 matches displaying all quest types and all quests with juice in its name.
GetQuestId("juice", "daily", false) -- matches found cut to 1 as there is only 1 quest that has juice in its name and is a daily.


GetSkillId(search string, exact match, first lower limit, first upper limit, second lower limit, second upper limit)

- Prints matches in table format. The table includes the CastTime and the Range apart from the Name and Id.

- By default, it only processes ids between 490000 and 499999 coz (I think) that's where all the skills are, but you can override it anytime through the function's arguments. You can also change the default values (490000 - 499999) permanently in the user options section of the file.


For Examples, see GetIdByName, this function is exactly like GetIdByName except that it has a built-in range filter.

GetBuffId(search string, exact match, first lower limit, first upper limit, second lower limit, second upper limit)

- By default, it only processes ids in two ranges between 500000 and 500999 and 620000 and 630000 coz (I think) that's where all the buffs are, but you can override it anytime through the function's arguments. You can also change the default values permanently in the user options section of the file.

Same as GetSkillId. For Examples, see GetIdByName, this function is exactly like GetIdByName except that it has a built-in range filter.

GetSysText(search string, exact match)

- This is essentially the most powerful search, it has no limitations whatsoever so it processes every text it can read. This means you can also use GetSysText to search for skills, quests, buffs etc.

Examples:
GetSysText("regional event") -- will not find any match
GetSysText("regional event", false) -- finds 5 matches
GetSysText("regional event now restarting") -- no matches as it is missing a "!" to be exact
GetSysText("regional event now restarting", false) -- prints and returns SC_ZONE_PE_3TH_ST1START
GetSysText("regional event now restarting!") -- prints and returns SC_ZONE_PE_3TH_ST1START


userfunction_GetIdByName.lua
v1.2 beta

- faster searches thanks to rock5's code
- added functions GetSysText, GetSkillId and GetBuffId.
- can now search two different ranges at once.
(12.37 KiB) Downloaded 317 times
Last edited by kenzu38 on Thu Oct 22, 2015 4:20 pm, edited 3 times in total.

User avatar
lisa
Posts: 8332
Joined: Tue Nov 09, 2010 11:46 pm
Location: Australia

Re: GetIdByName and GetQuestId userfunction

#2 Post by lisa » Fri Oct 09, 2015 5:15 pm

Haven't tried it but I do have a question, why have a table returned if more than 1 result but a single string if only 1 result, I ask because of how people will use it.

example.

Code: Select all

local id = GetIdByName("chill",620000,621000,false) table.print(id)
If for some reason there is only 1 result the table.print won't work

Code: Select all

Command> local id = "sometest" table.print(id)
onLoad error: [string "local id = "sometest" table.print(id)"]:1: Argument 1 passed to table.print() must be a table.
on the other side of the coin if you assume it was a string and it was a table you get

Code: Select all

Command> local id = {"sometest","someothertest"} print(id)
table: 02520EC8
So in order to not get errors people would need to check what type id is before trying to use it.
Remember no matter you do in life to always have a little fun while you are at it ;)

wiki here http://www.solarstrike.net/wiki/index.php?title=Manual

User avatar
rock5
Posts: 12173
Joined: Tue Jan 05, 2010 3:30 am
Location: Australia

Re: GetIdByName and GetQuestId userfunction

#3 Post by rock5 » Sat Oct 10, 2015 4:48 am

So if a user doesn't know what range to check and checks the whole range, how long does it take ion average to run?
  • Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
  • I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
  • How to: copy and paste in micromacro
    ________________________
    Quote:
    • “They say hard work never hurt anybody, but I figure, why take the chance.”
          • Ronald Reagan

kenzu38
Posts: 279
Joined: Sun Dec 02, 2012 8:52 am

Re: GetIdByName and GetQuestId userfunction

#4 Post by kenzu38 » Sun Oct 11, 2015 3:02 pm

lisa wrote:So in order to not get errors people would need to check what type id is before trying to use it.
Yes they'll just have to type in extra code if they're not sure how many results they will get.

I wanted to make things inline with the function name so I made it like that. You want to get an id, and id you will get (if there's only one result).

Anyway, I made it quickly so I never really had a lot of time to think things through. Now, though, I think people who will be using this will not put this in a WP most likely. And so the return values will probably never be used. But I still wanna make it return values so I will keep that functionality.

What I will add are prints as the function gets a match. It will print each result as they are found.

I also have some time right now to search for known ranges of buff ids and skill ids. I plan on adding GetSkillId and GetBuffId as well.

When I finish the new version, I will also explain more clearly a few things I might have missed.
rock5 wrote:So if a user doesn't know what range to check and checks the whole range, how long does it take ion average to run?
GetQuestId is fast, probably 3 seconds tops. But when I tried the 620000 - 630000 range for buffs, it was slow even if it's only 10k ids like GetQuestId. Didn't really time it but it's probably more than a minute. So, I really need to post some notice on the OP to explain this to potential users.

User avatar
rock5
Posts: 12173
Joined: Tue Jan 05, 2010 3:30 am
Location: Australia

Re: GetIdByName and GetQuestId userfunction

#5 Post by rock5 » Mon Oct 12, 2015 7:01 pm

kenzu38 wrote:Yes they'll just have to type in extra code if they're not sure how many results they will get.

I wanted to make things inline with the function name so I made it like that. You want to get an id, and id you will get (if there's only one result).
You could always do what we have done in the past and return an id as the first argument and a table for all matches in the second argument. Similar to player:findNearestNameOrId.
kenzu38 wrote:GetQuestId is fast, probably 3 seconds tops. But when I tried the 620000 - 630000 range for buffs, it was slow even if it's only 10k ids like GetQuestId. Didn't really time it but it's probably more than a minute. So, I really need to post some notice on the OP to explain this to potential users.
Hm... I wonder if it's possible to search in memory directly for the string and return the matching id. All you would have to do is search for the string in the text string range, find the matching the previous matching string which should be in the form of Sys123456_name, extract the id and return it. If that could work then it would be nearly as fast as GetIdName.

If it can be done like that why haven't I added it in the past you might ask. I think it's because there is no need in a botting script for a GetNameId function. You could for instance use the function with the commandline script to get an id but then you would use the id in your waypoint files, you wouldn't use the function itself. You can get thing ids other ways so there wasn't really a need for that function. For instance you can use my ToolipIds addon. You could use the fdb extractor and language viewer. You could search in memory using Cheat Engine. It doesn't hurt to have another way to get the id but if it's going to take so long then it's not really useful if there are other faster ways.
  • Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
  • I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
  • How to: copy and paste in micromacro
    ________________________
    Quote:
    • “They say hard work never hurt anybody, but I figure, why take the chance.”
          • Ronald Reagan

kenzu38
Posts: 279
Joined: Sun Dec 02, 2012 8:52 am

Re: GetIdByName and GetQuestId userfunction

#6 Post by kenzu38 » Tue Oct 13, 2015 6:44 pm

rock5 wrote:You could always do what we have done in the past and return an id as the first argument and a table for all matches in the second argument. Similar to player:findNearestNameOrId.
Yea, I suppose I could do this. But I don't see the point now that I have added prints every time it finds a match.
rock5 wrote:Hm... I wonder if it's possible to search in memory directly for the string and return the matching id. All you would have to do is search for the string in the text string range, find the matching the previous matching string which should be in the form of Sys123456_name, extract the id and return it. If that could work then it would be nearly as fast as GetIdName.
I don't fiddle with memory that much. Didn't even know there was a place in memory these strings are bundled together. I looked it up now with CE, and yea I suppose this will be quick if it somehow works. Problem I see in this though is if the clusters change addresses when there's a new patch. Then the function will need some maintenance work.
rock5 wrote:If it can be done like that why haven't I added it in the past you might ask. I think it's because there is no need in a botting script for a GetNameId function. You could for instance use the function with the commandline script to get an id but then you would use the id in your waypoint files, you wouldn't use the function itself.
Yea, I'm aware how people will be using the function. Like I said earlier:
Anyway, I made it quickly so I never really had a lot of time to think things through. Now, though, I think people who will be using this will not put this in a WP most likely.

rock5 wrote:You can get thing ids other ways so there wasn't really a need for that function. For instance you can use my ToolipIds addon. You could use the fdb extractor and language viewer. You could search in memory using Cheat Engine. It doesn't hurt to have another way to get the id but if it's going to take so long then it's not really useful if there are other faster ways.
GetIdByName is something I added after I completed GetQuestId and saw that it worked well. It was added just for its functionality and not for its efficiency. I myself just treat it as novelty. I wouldn't exclude it from the userfunction though since it's ready-made code and it's always good to have some ready-made codes however rarely you might need them.

And as for GetQuestId, I think it's useful in some cases, that's why I took the time to code it. You'll have to meet the condition that you know at least a substantial part of the name though.

I think the tooltips addon is the best choice but with the addon, I think you'll have to mouse over the quest, so it's either you have to have the quest in the questbook or be near the NPC who gives it. But it's not always the case, and I think that is when GetQuestId steps in as the best alternative out of the methods you mentioned.

With CE and Language viewer, you won't always know right away which is the exact quest you're looking for since plenty of quests have the same names. But with GetQuestId's filter, that's not the case.


Anyway, I said earlier that I was planning to add GetSkillId and GetBuffId. Well, I finished coding it but decided to exclude GetSkillId since it was really slow. GetBuffId though is tolerable with just over a minute of waiting before you get the Id. Not the most efficient really, but once everything is substantiated in memory, the succeeding searches get a lot faster. So I'll release it for now since it's already been done. But I might redo it soon when I find a faster way of searching.

User avatar
rock5
Posts: 12173
Joined: Tue Jan 05, 2010 3:30 am
Location: Australia

Re: GetIdByName and GetQuestId userfunction

#7 Post by rock5 » Wed Oct 14, 2015 5:01 am

kenzu38 wrote:I looked it up now with CE, and yea I suppose this will be quick if it somehow works. Problem I see in this though is if the clusters change addresses when there's a new patch. Then the function will need some maintenance work.
No, not really. It would use the same addresses that getTEXT function uses so the address will always be correct (unless that patch is so radical that it breaks update.lua).
kenzu38 wrote:I think the tooltips addon is the best choice but with the addon, I think you'll have to mouse over the quest, so it's either you have to have the quest in the questbook or be near the NPC who gives it. But it's not always the case, and I think that is when GetQuestId steps in as the best alternative out of the methods you mentioned.

With CE and Language viewer, you won't always know right away which is the exact quest you're looking for since plenty of quests have the same names. But with GetQuestId's filter, that's not the case.
My favourite method is using the language viewer because it's the quickest to start up. I rarely start up the game these days. But you are correct, you can't tell which quest with the same name is the public/daily/normal quest so yours could be useful in that case.
  • Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
  • I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
  • How to: copy and paste in micromacro
    ________________________
    Quote:
    • “They say hard work never hurt anybody, but I figure, why take the chance.”
          • Ronald Reagan

User avatar
rock5
Posts: 12173
Joined: Tue Jan 05, 2010 3:30 am
Location: Australia

Re: GetIdByName and GetQuestId userfunction

#8 Post by rock5 » Wed Oct 14, 2015 9:08 am

I got the urge to fiddle a bit so I copy and pasted some code, made a few modifications and came up with the following.

Code: Select all

local function collectKeys(text)
	-- local function to find start of string byt finding the null before the string
	local function findLastNull(address)
		while memoryReadByte(getProc(), address) ~= 0 do
			address = address - 1
		end
		return address
	end

	-- Start and end address of the text strings
	local addressPtrsBase = memoryReadInt(getProc(), addresses.getTEXT)
	local startloc = memoryReadInt(getProc(), addressPtrsBase + 0x268)
	local endloc = memoryReadInt(getProc(), addressPtrsBase + 0x26C)
	local searchlen = endloc - startloc

	-- The pattern and mask. ? wild cards are supported.
	local pattern = text
	local mask = text:gsub("[^?]","x")

	-- Search for all matches
	local results={}
	local searchloc = startloc
	while searchloc < endloc do
		local found = findPatternInProcess(getProc(), pattern, mask, searchloc, searchlen);
		if found == 0 then
			break
		end

		-- Search back for start of string
		local textStartAddress = findLastNull(found)
		if textStartAddress == nil then -- not found
			break
		end

		-- Read full string
		local tmpText = memoryReadString(getProc(), textStartAddress+1)

		-- Search back for matching key string
		local keyStartAddress = findLastNull(textStartAddress-1)

		if keyStartAddress < startloc then -- The very first key isn't preceded by a null
			keyStartAddress = startloc-1
		end

		-- Read key string
		local tmpKey = memoryReadString(getProc(), keyStartAddress+1)

		-- Print and add to results
		table.insert(results,{Key=tmpKey, Name=tmpText})

		-- Continue searching for more results
		searchloc = textStartAddress+ #tmpText + 2
		searchlen = endloc - searchloc
	end

	return results
end

function printTEXTKeys(text)
	local results = collectKeys(text)
	for i,v in pairs(results) do
		print(v.Key, v.Name)
	end
end

function printNameIds(text, startId, endId)
	local results = collectKeys(text)
	for i,v in pairs(results) do
		local id = v.Key:match("^Sys(%d%d%d%d%d%d)_name$")
		if id then id=tonumber(id) end
		if id and (startId == nil or id >= startId) and (endId == nil or id <= endId) then
			print(id,v.Name)
		end
	end
end
As I was coding it I realized that the function can be used to find any key string, not just ids. So I made 2 functions. startId and endId are optional if you want to specify a range.

printTEXTKeys(text) prints the key strings for any text and

printNameIds(text, startId, endId) prints the ids that match the text.

The limitations of these functions is that they are case sensitive although I've included the ability to use ? as a wildcard.

Example usage:

Code: Select all

Command> printTEXTKeys("Regional event has ended")
SC_ZONE_PE_3TH_FAIL     Regional event has ended.
SC_ZONE_PE_3TH_ST1OVER  Regional event has ended successfully!
Command> printNameIds("wrapped Belt")
221544  Gold-wrapped Belt
I'm not sure what you would want to do with it.
  • Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
  • I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
  • How to: copy and paste in micromacro
    ________________________
    Quote:
    • “They say hard work never hurt anybody, but I figure, why take the chance.”
          • Ronald Reagan

kenzu38
Posts: 279
Joined: Sun Dec 02, 2012 8:52 am

Re: GetIdByName and GetQuestId userfunction

#9 Post by kenzu38 » Wed Oct 14, 2015 5:11 pm

Very nice. So, do you plan to release or integrate that to the bot?

Anyway, I think I'm gonna mess around with that local function, that's just what I needed for the GetSkillId I was planning to make.

Oh and btw, speaking of skills, I was looking at addresses.lua and I saw something that could be useful for my function but I haven't seen it get used anywhere else so I have no idea how to use it.

It's the SkillClass offset. First of all, is it the class that can use the said skill? If so, what's the data type you're looking for in memory and what are the expected values and the meaning of those values?

User avatar
rock5
Posts: 12173
Joined: Tue Jan 05, 2010 3:30 am
Location: Australia

Re: GetIdByName and GetQuestId userfunction

#10 Post by rock5 » Fri Oct 16, 2015 2:06 am

kenzu38 wrote:Very nice. So, do you plan to release or integrate that to the bot?
Because it's not used while botting I think I wont add it to the bot. Feel free to integrate it into your userfunction.
kenzu38 wrote:Oh and btw, speaking of skills, I was looking at addresses.lua and I saw something that could be useful for my function but I haven't seen it get used anywhere else so I have no idea how to use it.

It's the SkillClass offset. First of all, is it the class that can use the said skill? If so, what's the data type you're looking for in memory and what are the expected values and the meaning of those values?
Seeing as it's not used by the bot it's probably just some old obsolete value. I couldn't hazard a guess how it was used if at all. I tried looking in the repository log for any mention of it but couldn't find it.
  • Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
  • I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
  • How to: copy and paste in micromacro
    ________________________
    Quote:
    • “They say hard work never hurt anybody, but I figure, why take the chance.”
          • Ronald Reagan

kenzu38
Posts: 279
Joined: Sun Dec 02, 2012 8:52 am

Re: GetIdByName and GetQuestId userfunction

#11 Post by kenzu38 » Sat Oct 17, 2015 7:46 am

Alright, thanks for the codes then. I'll help myself to them. I have an idea how to improve them a bit. That'll have to wait though, I'm busy right now with polishing some scripts I intend to release later.

kenzu38
Posts: 279
Joined: Sun Dec 02, 2012 8:52 am

Re: GetIdByName and GetQuestId userfunction

#12 Post by kenzu38 » Thu Oct 22, 2015 1:40 pm

Alright, finally got some free time today so I had the time to work on this. It's now a lot faster thanks to rock's code. I made it case-insensitive by automatically subbing the first letters to ?. Not sure it will work on 100% of the text but I think it will probably work 99% of the time.

Post Reply

Who is online

Users browsing this forum: No registered users and 5 guests