Page 1 of 2
QuestByName
Posted: Sat Feb 05, 2011 6:02 am
by JackBlonder
This userfunction is usefull to accept/complete quests by their quest name or parts of it.
To use it just copy "userfunction_QuestByName.lua" to your "/rom/userfunctions/" folder and use the following commands in your waypoint files:
AcceptQuestByName() or
AcceptAllQuests() --Accept all available quests
AcceptQuestByName("word") --Accept first quest in list with "word" in it's name
CompleteQuestByName() or
CompleteAllQuests() --Complete all available quests
CompleteQuestByName("word") --Complete first quest in list with "word" in it's name
CompleteQuestByName("word",1) --Complete first quest in list with "word" in it's name and select reward number 1
Note:
-You have to target the quest NPC before using any these functions
e.g.
Code: Select all
player:target_NPC("Vega");
CompleteQuestByName()
Changelog
Version 0.97
-Added check for target
-Added check for number of quests in questbook
Version 0.96
-Change in retargeting
Version 0.95
-Special character replacement changed
-Went back to RomScript for retargeting
Version 0.94
-Changed retargeting to
Code: Select all
player:target_NPC(player:getTarget())
-Simplyfied function to compare questnames
Version 0.93
-Added retargeting NPC to retrieve updated data
Version 0.92
-Bugfix
Version 0.91
-Added reward selection
-Changed loop to complete/accept at least one time
-Added two new commands
ToDo:
-Anything suggested
These functions are part of the bot now so there is no need to install these userfunctions.
Re: QuestByName
Posted: Sat Feb 05, 2011 7:55 am
by rock5
You can do rewards like this. Add a second arg to the complete quest function
Code: Select all
CompleteQuestByName(_name, _reward)
Then do this before completing the quest
Code: Select all
if reward then
sendMacro("SpeakFrame_ClickQuestReward(SpeakQuestReward1_Item".._reward..")")
end
You are missing something important, though.
What happens if you open an NPC dialog and it jumps straight to the quest, bypassing the quest list? Then your functions wont work. The struggle I had with that is why I never released my quest functions. The best solution I could manage was to do a "CompletQuest()" first before trying to search the quest list. But I was never 100 % happy with the results.
Also, the quest list gets updated when it shows a new quest list. So if you talk to an NPC and it doesn't show a list then when you use the commands to get the quest list data, you will get obsolete data from the previous NPC you spoke to.
Re: QuestByName
Posted: Sat Feb 05, 2011 8:15 am
by JackBlonder
What happens if you open an NPC dialog and it jumps straight to the quest, bypassing the quest list? Then your functions wont work. The struggle I had with that is why I never released my quest functions. The best solution I could manage was to do a "CompletQuest()" first before trying to search the quest list. But I was never 100 % happy with the results.
Never came accross this problem yet.
I'll try to find an NPC with this kind of quest and take a look at the problem you mentioned.
Re: QuestByName
Posted: Sat Feb 05, 2011 8:41 am
by lisa
Same, first one that came to mind was a daily in Savage Lands, I'm heading there now to test it. I think there might be a NPC/quest in logar like this though.
Tested and works. This is a daily in SL as soon as you click the NPC the accept quest pops up, you also hand quest in to same NPC.
I should note I only tested it with the accept all function as you can see from the WP code.
Code: Select all
<!-- # 1 --><waypoint x="4669" z="16933" y="87">
player:target_NPC("Banbi Dirson");
AcceptQuestByName()
yrest(1000)
CompleteQuestByName()
yrest(1000)
</waypoint>
Code: Select all
Moving to waypoint #1, (4669, 16933)
We try to find NPC Banbi Dirson:
We successfully target NPC Banbi Dirson and try to open the dialog window
Quest accepted: deer leg provisions
Clearing target.
Moving to waypoint #1, (4669, 16933)
We try to find NPC Banbi Dirson:
We successfully target NPC Banbi Dirson and try to open the dialog window
Quest completed: Deer Leg Provisions
Clearing target.
Moving to waypoint #1, (4669, 16933)
We try to find NPC Banbi Dirson:
We successfully target NPC Banbi Dirson and try to open the dialog window
Quest accepted: deer leg provisions
Clearing target.
Moving to waypoint #1, (4669, 16933)
We try to find NPC Banbi Dirson:
We successfully target NPC Banbi Dirson and try to open the dialog window
Quest completed: Deer Leg Provisions
Tested in Logar aswell using a partial name for quest.
Code: Select all
<!-- # 1 --><waypoint x="-635" z="-6008" y="26">
player:target_NPC("Dell");
AcceptQuestByName("strange")
yrest(5000)
</waypoint>
Code: Select all
Moving to waypoint #1, (-635, -6008)
We try to find NPC Dell:
We successfully target NPC Dell and try to open the dialog window.
Quest accepted: strange request
Re: QuestByName
Posted: Sat Feb 05, 2011 9:30 am
by JackBlonder
Tested and works
Did you use the current version?
Maybe it worked because of
Also, the quest list gets updated when it shows a new quest list. So if you talk to an NPC and it doesn't show a list then when you use the commands to get the quest list data, you will get obsolete data from the previous NPC you spoke to.
I'll do further testing now.
I want to know what happens at
if
Code: Select all
availableQuests = RoMScript("GetNumQuest(3)"
returned 0 sooner
Re: QuestByName
Posted: Sat Feb 05, 2011 9:52 am
by rock5
lisa wrote:Same, first one that came to mind was a daily in Savage Lands, I'm heading there now to test it. I think there might be a NPC/quest in logar like this though.
Tested and works. This is a daily in SL as soon as you click the NPC the accept quest pops up, you also hand quest in to same NPC.
You're right it does work. Maybe dailies are different.
The same is not true of normal quest. Any easy way to test it is by creating a new character and heading to Pioneers Village. When getting your free gear it should jump from the complete quest to the accept quest dialog. Then start the CommandLine.xml as your waypoint file and type
It wont work. Even using "all" wont work. In fact if you type
It will try to complete the previous quest again.
Re: QuestByName
Posted: Sat Feb 05, 2011 10:08 am
by JackBlonder
That's right. You have to target the NPC again to update data before using a new command.
[Edit]
I changed the loops to at least do "accept/complete"-loop before checking for availableQuests.
Using
Code: Select all
AcceptQuestByName()
CompletQuestByName()
in a row will not work though.
You have to use
Code: Select all
player:target_NPC("npcname")
AcceptQuestByName()
player:target_NPC("npcname")
CompletQuestByName()
Please check out versvion 0.91 and report any problem.
Re: QuestByName
Posted: Sat Feb 05, 2011 10:14 am
by lisa
The quest I tested in Logar wasn't a daily, it was just a normal quest and worked fine. I'm not sure if I have the latest version though. The last I downloaded was in the previous topic we were discussing it in.
I tested it on new human character with this.
Code: Select all
<!-- # 1 --><waypoint x="-4039" z="-8290">
player:target_NPC("Laif Cindai");
AcceptQuestByName()
</waypoint>
<!-- # 2 --><waypoint x="-3777" z="-8488"></waypoint>
<!-- # 3 --><waypoint x="-3699" z="-8674">
player:target_NPC("Leighton");
AcceptQuestByName()
player:target_NPC("Leighton");
CompleteQuestByName()
</waypoint>
and it worked fine
Tested with the version on first post of this topic and it still works fine.
Re: QuestByName
Posted: Sat Feb 05, 2011 11:02 am
by rock5
I think that possibly, yes, re-targeting the NPC will work, hopefully for all npcs.
If we have to make sure we re-target the npc before doing either of these quest functions maybe we should make it part of the function. ie. the first thing it does is re-target the current target then does it's thing. Then you would only need to target the npc once.
What do you think?
Re: QuestByName
Posted: Sat Feb 05, 2011 11:09 am
by lisa
would that work with bulletin boards, I know when I use createpath it comes up with <UNKNOWN> as the targets name.
Seems you only need to retarget when going from accepting to completing and vice versa.
Re: QuestByName
Posted: Sat Feb 05, 2011 11:20 am
by rock5
lisa wrote:would that work with bulletin boards, I know when I use createpath it comes up with <UNKNOWN> as the targets name.
That's because you can't select the bulletin board to correctly target it in createpath. There should be no issue with targeting the board or retargeting it.
lisa wrote:Seems you only need to retarget when going from accepting to completing and vice versa.
Possibly, but how would one function know that the other just ran? I don't see any harm in just retargeting before continuing with the function.
Re: QuestByName
Posted: Sat Feb 05, 2011 3:28 pm
by JackBlonder
If we have to make sure we re-target the npc before doing either of these quest functions maybe we should make it part of the function. ie. the first thing it does is re-target the current target then does it's thing. Then you would only need to target the npc once.
I added the retargeting now and did some testing.
Hopefully this will work for all NPCs.
Re: QuestByName
Posted: Sat Feb 05, 2011 8:36 pm
by rock5
You can retarget your current target by using
Code: Select all
player:target_NPC(player:getTarget())
No need for RoMScript commands.
I'd simplify comparequestnames to
Code: Select all
function compareQuestnames(_name, _string)
_name = normaliseString(_name)
--printf("_name: %s\n",_name)
_string = normaliseString(_string)
--printf("_string: %s\n",_string)
if string.find(_name,_string) then
--printf("rtn1: %d\t rtn2: %d\n",rtn1,rtn2)
return true
else
return false
end
end
It's looking really good now. Better than my functions because this successfully (hopefully) deals with the 'quest list' issue which mine didn't.
Re: QuestByName
Posted: Sun Feb 06, 2011 1:51 am
by JackBlonder
Thanks for this. I'll change it in the next version.
You can retarget your current target by using
Code:
player:target_NPC(player:getTarget())
No need for RoMScript commands.
You're right about the comparequestnames().
Don't know why I did it that complicated
[Edit]
Just tested rev.571 with version 0.94 of my script with
Code: Select all
player:target_NPC(player:getTarget())
added.
Tried to accept the first human quest with
Code: Select all
<!-- # 1 --><waypoint x="-4039" z="-8290">
player:target_NPC("Laif Cindai");
AcceptQuestByName()
I got the following error
Code: Select all
Wir versuchen den NPC Laif Cindai zu finden:
Der NPC 'Laif Cindai' wurde erfolgreich ausgewählt. Wir öffnen das Dialogfenster
.
Wir versuchen den NPC table: 026619D8 zu finden: .../Downloads/micromacro/script
s/rom/classes/player.lua:3110: bad argument #2 to 'find' (string expected, got b
oolean)
Bot targets NPC with
Then in
Code: Select all
player:target_NPC(player:getTarget())
is called and returns the error.
I think it because getTarget() returns a pointer and target_NPC expects a string.
We could do it by using
Code: Select all
player:target_NPC(CPawn(targetPtr).Name)
but I'm not sure if this faster than using Romscript. What do you think?
[Edit]
I did some more testing.
Code: Select all
player:target_NPC(CPawn(targetPtr).Name)
sometimes returned <UNKNOWN> so I went back to RomScript until there's a better idea.
Furthermore I found a quest that has "" in its name (called "Fungus"-Begleiter in german). This made the script get stuck at
so I decided to add another char replacement at the normaliseString() function.
A new version (0.95) is uploaded. Please reported any ideas/problems.
Re: QuestByName
Posted: Sun Feb 06, 2011 8:46 pm
by rock5
JackBlonder wrote:I think it because getTarget() returns a pointer and target_NPC expects a string.
We could do it by using
Code: Select all
player:target_NPC(CPawn(targetPtr).Name)
Sorry my bad. But I think you meant to try
Code: Select all
player:target_NPC(CPawn(player.targetPtr).Name)
JackBlonder wrote:but I'm not sure if this faster than using Romscript. What do you think?
One thing you need to know about RoMScript is it's
really slow, taking as much as 500ms to finish sometimes. Then again, target_NPC uses RoMScript to send "UseSkill (1,1)" commands. In the end the fastest way will be the one that uses the least number of RoMScripts.
Hmm... maybe we could just use RoMScript("UseSkill(1,1)")? If the npc is already targeted, that should bring up the dialog. That's only 1 RoMScript. The way you do it I think does 3.
Note: If you didn't know, if you add a post the thread becomes highlighted as being unread so I would read it. But if you edit your last post after I've already read it, it remains marked as read and I might never know you edited it.
So if it's been long enough, it's better to add a post than edit an old one.
Re: QuestByName
Posted: Mon Feb 07, 2011 2:25 am
by JackBlonder
Ok. Thanks for the info.
Good to know RomScript is taking so long.
I'll try out
this evening and do some testing.
Note: If you didn't know, if you add a post the thread becomes highlighted as being unread so I would read it. But if you edit your last post after I've already read it, it remains marked as read and I might never know you edited it.
So if it's been long enough, it's better to add a post than edit an old one.
I wasn't sure about this and didn't want to make a double post.
But your right. If it's long enough it should be ok.
Re: QuestByName
Posted: Mon Feb 07, 2011 2:30 pm
by JackBlonder
I changed the retargeting to
as you suggested and did some testing.
Should work ok.
Re: QuestByName
Posted: Mon Feb 07, 2011 7:04 pm
by rock5
Now it might be time to think about error checking.
For instance, at the start you can check to see if you have a target or not (in case the user forgot to target the npc first). If not, print a warning message and exit the function. For that you could probably just use the memory functions. Something like;
Code: Select all
if not player:haveTarget() then
print (error message)
return
end
I just tested the 'accepting all' and it got stuck because my quest book was full. So you could add a check to see if you have room to accept the quest.
Gives you the number of quests in your quest book.
That's all that comes to mind at the moment.
Also, don't forget, you don't need to do "repeat val = romscript(com) until val" anymore since I fixed romscript. That mean you can do something like this;
Code: Select all
if RoMScript("GetNumQuestBookButton_QuestBook()") < 30 then
accept the quest
See how I avoided the need to use a variable.
Re: QuestByName
Posted: Tue Feb 08, 2011 2:19 am
by JackBlonder
Good ideas.
I'll implement it when I'm at home.
Re: QuestByName
Posted: Tue Feb 08, 2011 11:35 am
by JackBlonder
I have a problem when using
to check if we have target.
When our target is a daily board haveTarget() returns nil.
[Edit]
Curious!
When I use
Code: Select all
if (not player:haveTarget()) then
print("No target! Target NPC before using CompleteQuestByName")
return
end
I always get the print although I have a target.
But when I use
Code: Select all
if (player.TargetPtr == 0 or player.TargetPtr == nil) then
print("No target! Target NPC before using CompleteQuestByName")
return
end
it works as it should.
[Edit 2]
I think i got it.
haveTarget() does not return true so the if-function is called everytime. (right?)