Rock5's QuestLog Class

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.
Message
Author
User avatar
rock5
Posts: 12173
Joined: Tue Jan 05, 2010 3:30 am
Location: Australia

Re: Rock5's QuestLog Class

#21 Post by rock5 » Wed Aug 29, 2012 7:56 am

I was thinking, if I added it, I would add it to the quest:isComplete function. Have it return the goalcount as an extra value. But I still don't like it.

I think I've thought of something I'm happy to do as it doesn't change the way the functions work at the moment. How about a small function that returns the killcount? So it would work something like

Code: Select all

quest = questlog:getQuest("quest name")
killcount = quest:getKillCount(1)
Then you could just check if it increments. The '1' is the first kill goal. Most quests will have only 1 kill goal so maybe I'll have it default to '1'.

How does that sound?
  • 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

dx876234
Posts: 188
Joined: Sat Jul 24, 2010 6:13 am

Re: Rock5's QuestLog Class

#22 Post by dx876234 » Wed Aug 29, 2012 9:22 am

That would be perfect, actually its how I made it in my waypoint atm :)

-dx

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

Re: Rock5's QuestLog Class

#23 Post by rock5 » Wed Aug 29, 2012 9:58 am

Above function has been added to version 0.03.
  • 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

dx876234
Posts: 188
Joined: Sat Jul 24, 2010 6:13 am

Re: Rock5's QuestLog Class

#24 Post by dx876234 » Wed Sep 05, 2012 10:17 am

New challenge:

The quest "Three Playful Brothers" have 3 itemgoals, one for each brother but as we find each brother no items come into backpack.

As each brother has three different locations it can be found I am in need of testing if the sub-goal has been reached to be able to skip searching the rest of the locations when found.

So, hot to test for an itemgoal is completed when no item has been dropped?

-dx

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

Re: Rock5's QuestLog Class

#25 Post by rock5 » Wed Sep 05, 2012 1:15 pm

I see no way to do this from memory. I guess I could add some sort of function that returns the goals using the ingame functions. I'm not sure how I'd work it. I'll have to think about it.

If you want to look at how to do it, in the mean time, have a look at "igf_questStatus" function in the ingamefunctions.lua file.
  • 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: Rock5's QuestLog Class

#26 Post by rock5 » Thu Sep 06, 2012 12:29 am

I was doing other stuff last night but I thought about this this morning before I got up.

There is currently a questlog:getKillCount(goal) function. I can add a questlog:getItemCount(goal). If the goal is an actual item then it can count it from the inventory. If it's a task based goal then it has to use the in game function to get the goal state. Unfortunately the in game function only returns if the goal is complete or not, not the count.

But I think I've realised something about the kill and item goal lists. I think the kill list is for goals that need a count to be kept, so kill quests and quests that need tasks to be done a number of times. The item goal list is for items, and goals that only need to be done once. So for task based item goals we can assume a count of 1.

I also had another idea of how to get them from memory. I'l try that now.
  • 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

BillDoorNZ
Posts: 446
Joined: Wed Aug 03, 2011 7:37 pm

Re: Rock5's QuestLog Class

#27 Post by BillDoorNZ » Fri Sep 07, 2012 6:04 am

nice work rock...I had all this stuff working with RoMScript calls...was SLLLOOOW... will look at converting what I have and see where the gaps are. I use it for decision making in waypoint:

if (goal XYZ complete) the move on to next part
else re run this section

you can probably get the quest Rewards from memory too (which is also available via an in-game function) and then can build choice strategies around that for auto completing quests...

hmm...must go dig up my questbook and quest classes now :)

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

Re: Rock5's QuestLog Class

#28 Post by rock5 » Fri Sep 07, 2012 7:32 am

BillDoorNZ wrote:nice work rock...I had all this stuff working with RoMScript calls...was SLLLOOOW...
Interest has been ok. I think someone even released a script that had this userfunction as a requirement. If interest keeps up, I probably will add it to the bot.
BillDoorNZ wrote:you can probably get the quest Rewards from memory too (which is also available via an in-game function) and then can build choice strategies around that for auto completing quests...
I don't see the point of getting rewards from memory. You could just get the rewards when talking to the npc and make your decision there. There is no hurry when talking to npcs. Normally you don't need reward info, maybe only if you want to make a choice based on class. I remember doing a script that went to get the free armor packages and decided which to get based on class. So it can already be done.

For example here is my level 55 package code.

Code: Select all

		player:target_NPC("Kabo Kennedy");
		AcceptQuestByName("Rewards for Students") yrest(2000)

		local choice
		if armorMap[player.Class1] == "cloth" then
			choice = 4
		elseif armorMap[player.Class1] == "leather" then
			choice = 3
		elseif armorMap[player.Class1] == "chain" then
			choice = 2
		elseif armorMap[player.Class1] == "plate" then
			choice = 1
		end
		CompleteQuestByName("Rewards for Students",choice)
  • 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

BillDoorNZ
Posts: 446
Joined: Wed Aug 03, 2011 7:37 pm

Re: Rock5's QuestLog Class

#29 Post by BillDoorNZ » Sat Sep 08, 2012 2:46 am

ah...I was more referring to having strategies that users can specify in their profile.


something like:

for Armor: I want to take call Cloth loot, if there is no cloth, then take Plate (tends to be worth more)
or : I just want money

then the bot just picks the most appropriate one - as you said tho, can happen at end.

my quest book class and quest classes (the quest class has the code for selecting reward index):

Code: Select all

CQuest = class(
	function (self, qId, minLevel, level, starterid, enderid, gold, xp, tp, rewardcategory, rewardsubcategory)
		self.Id = qId;
		self.Name = GetIdName(qId);
		self.MinLevel = minlevel;
		self.Level = level;
		self.StarterId = starterid;
		self.StarterName = GetIdName(starterid);
		self.EnderId = enderid;
		self.EnderName = GetIdName(enderid);
		self.Gold = gold;
		self.XP = xp;
		self.TP = tp;
		self.RewardCategory = rewardcategory;
		self.RewardSubCategory = rewardsubcategory;
		self.Rewards = {count=0}; 
		self.Accepted=false;
		self.Completed=false;
		self.Goals = {count=0};
	end
)

SELECTION_TYPE_GOLD = "gold";
SELECTION_TYPE_TYPE = "type";

local function SplitString(str, delim, maxNb)
    -- Eliminate bad cases...
    if string.find(str, delim) == nil then
        return { str }
    end
    if maxNb == nil or maxNb < 1 then
        maxNb = 0    -- No limit
    end
    local result = {}
    local pat = "(.-)" .. delim .. "()"
    local nb = 0
    local lastPos
    for part, pos in string.gfind(str, pat) do
        nb = nb + 1
        result[nb] = part
        lastPos = pos
        if nb == maxNb then break end
    end
    -- Handle the last field
    if nb ~= maxNb then
        result[nb + 1] = string.sub(str, lastPos)
    end
    return result
end

function CQuest:toString()
		printf("  "..tostring(self.Id).."\n");
		printf("  "..tostring(self.Name).."\n");
		printf("  "..tostring(self.MinLevel).."\n");
		printf("  "..tostring(self.Level).."\n");
		printf("  "..tostring(self.StarterId).."\n");
		printf("  "..tostring(self.StarterName).."\n");
		printf("  "..tostring(self.EnderId).."\n");
		printf("  "..tostring(self.EnderName).."\n");
		printf("  "..tostring(self.Gold).."\n");
		printf("  "..tostring(self.XP).."\n");
		printf("  "..tostring(self.TP).."\n");
		printf("  "..tostring(self.RewardCategory).."\n");
		printf("  "..tostring(self.RewardSubCategory).."\n");
		printf("  "..tostring(self.Accepted).."\n");
		printf("  "..tostring(self.Completed).."\n");
end;

function CQuest:getRewardConfiguredItemIndex()
	printf("********getRewardConfiguredItemIndex**********\n");
	--figure out which reward item to take based on user preferences
	local selectionType = settings.profile.options.QUEST_REWARD_SELECTION_TYPE;
	if (selectionType == nil) then selectionType=SELECTION_TYPE_GOLD; end;
	selectionType = string.lower(selectionType);
	printf(" : selectionType = "..selectionType.."\n");

	local rewardTypeOrder;
	
	if (selectionType == SELECTION_TYPE_TYPE) then
		rewardTypeOrder = settings.profile.options["QUEST_REWARD_TYPE_ORDER_"..string.upper(tostring(self.RewardCategory)).."_"..string.upper(tostring(self.RewardSubCategory))];
		if (rewardTypeOrder == nil) then rewardTypeOrder = settings.profile.options["QUEST_REWARD_TYPE_ORDER_"..string.upper(tostring(self.RewardCategory))]; end;
		if (rewardTypeOrder == nil) then rewardTypeOrder = settings.profile.options.QUEST_REWARD_TYPE_ORDER; end;
		
		if (rewardTypeOrder == nil) then selectionType = SELECTION_TYPE_GOLD; end;
		printf(" : rewardTypeOrder = "..tostring(rewardTypeOrder).."\n");
	end;
	
	local rewardIndex = 0;
	if (selectionType == SELECTION_TYPE_TYPE) then
		printf(" : selecting on type, reward order = "..tostring(rewardTypeOrder).."\n");
		local res = SplitString(rewardTypeOrder, ',');
		for k,j in pairs(res) do
			printf("    : checking for type "..tostring(j).."\n");
			for i, v in pairs(self.Rewards) do
				if (i ~= "count") then 
					printf("       : checking against "..tostring(v.value).."\n");
					if (string.upper(j) == string.upper(v.type)) then
						rewardIndex = i;
						break;
					end;
				end;
			end;
			if (rewardIndex > 0) then break; end;
		end;
		printf(" : rewardindex = "..tostring(rewardIndex).."\n");
		
	end
	
	if (rewardIndex == 0) then --always default to selecting on valuye
		printf(" : basing choice off value\n");
		local rewardGold = 0;
		--iterate over rewards and select most valuable
		printf("reward count: "..tostring(self.Rewards.count).."\n");
		for i,v in pairs(self.Rewards) do
			printf("Checking reward: "..tostring(i).." - "..tostring(v).."\n");
			if (i ~= "count") then 
				for k,l in pairs(v) do
					printf("\t\ttbl: "..tostring(k).." - "..tostring(l).."\n");
				end;
				printf("\t\titem: "..tostring(v.itemName).." - "..tostring(v.itemValue).."\n");
				if (tonumber(v.itemValue) > rewardGold) then 
					rewardIndex = i;
					rewardGold=tonumber(v.itemValue);
				end;
			end;
		end;
	end;

	printf(" : rewardindex = "..tostring(rewardIndex).."\n");
	
	return rewardIndex;
end;

function CQuest:update()
	local questState = RoMScript("CheckQuest("..self.Id..")");
	printf("questState="..tostring(questState).."\n");
	if (questState==0) then 
		self.Accepted = false;
		self.Completed = false;
	elseif (questState == 2) then
		self.Accepted = true;
		self.Completed = true;
	else
		self.Accepted = true;
		self.Completed = false;
	end;
end;

Code: Select all

QB_GOAL_NOT_COMPLETE = 0;
QB_GOAL_COMPLETE = 1;


CQuestBook = class(
	function(self)
		self.Quests = {};
	end
);

quest_DEBUG=true;

local function PrintLine(s)
	if (quest_DEBUG == true) then printf(s.."\n"); end;
end;

function CQuestBook:update()
	self.Quests = {};
	local qCount = RoMScript("GetNumQuestBookButton_QuestBook()");
	PrintLine("Found "..tostring(qCount).." quests in quest book\n");
	
	for i=1,qCount,1 do
		coroutine.yield();
		RoMScript("ViewQuest_QuestBook("..tostring(i)..");");
		
		local qi = {};
		qi.id = RoMScript("GetQuestId("..tostring(i)..")"); 
		qi.level = RoMScript("GetQuestRequest("..tostring(i)..",-3)"); 
		qi.name = RoMScript("GetQuestRequest("..tostring(i)..",-2)");
		qi.starterId = RoMScript("QuestDetail_GetQuestNPC()");
		qi.enderId = RoMScript("QuestDetail_GetRequestQuestNPC()");
		qi.gold = RoMScript("GetQuestMoney_QuestDetail()");
		qi.xp = RoMScript("GetQuestExp_QuestDetail()");
		qi.tp = RoMScript("GetQuestTP_QuestDetail()");
		
		PrintLine(tostring(i)..": "..tostring(qi.id).." - "..tostring(qi.name).."\n");
		PrintLine("\tlevel: "..tostring(qi.level).." starterid: "..tostring(qi.starterId).." enderid: "..tostring(qi.enderId).."\n");
		PrintLine("\tgold: "..tostring(qi.gold).." xp: "..tostring(qi.xp).." tp: "..tostring(qi.tp).."\n");

		local quest = CQuest(qi.id, qi.level-3, qi.level, qi.starterId, qi.enderId, qi.gold, qi.xp, qi.tp, "", "");
		
		quest.Goals.count= RoMScript("GetQuestRequest("..tostring(i)..",-1)");
		for j = 1, quest.Goals.count do -- For each goal get name and status
			coroutine.yield();
			quest.Goals[j] = {};
			quest.Goals[j].Name, quest.Goals[j].Status = RoMScript("GetQuestRequest("..tostring(i)..","..tostring(j)..")");
		end
		
		--qi.rewards = {}
		
		self.Quests[i] = quest;
	end;
end

function CQuestBook:updateQuest(questId)
	PrintLine("updateQuest goals for quest: "..tostring(questId));
	local idx = self:getQuestIndex(questId);
	
	if (idx < 0) then 
		PrintLine("Could not find index for quest!!!");
		return; 
	end;
	
	local quest = self.Quests[idx];
	RoMScript("ViewQuest_QuestBook("..tostring(idx)..");");
	quest.Goals.count = RoMScript("GetQuestRequest("..tostring(idx)..",-1)");
	for j = 1, quest.Goals.count do -- For each goal get name and status
		quest.Goals[j] = {};
		quest.Goals[j].Name, quest.Goals[j].Status = RoMScript("GetQuestRequest("..tostring(idx)..","..tostring(j)..")");
		PrintLine("Added goal '"..quest.Goals[j].Name.."' at status '"..tostring(quest.Goals[j].Status));
	end
end;


function CQuestBook:getQuestIndex(questId)
	local i = 1;
	local idx = -1;

	while ((idx == -1) and (i <= #self.Quests)) do
		if (tonumber(self.Quests[i].Id) == tonumber(questId)) then
			idx = i;
		end;
		i = i + 1;
	end;
	
	return idx;
end;

function CQuestBook:getQuestById(questId)
	local idx = self:getQuestIndex(questId);
	if (idx > -1) then
		return self.Quests[idx];
	else
		return nil;
	end;
end;

function CQuestBook:updateRewardItems()
	local qCount = #self.Quests;
	for index=1,qCount,1 do
		coroutine.yield();
		self:fetchRewardItems(index)
	end
end;

function CQuestBook:fetchRewardItems(index)
	PrintLine("Fetching rewards for quest index: "..tostring(index));
	RoMScript("ViewQuest_QuestBook("..tostring(index)..");");

	--local _name = RoMScript("GetQuestName_QuestDetail()");
	PrintLine("Checking quest: "..self.Quests[index].Name);
	--printf("Checking quest: ".._name.."\n");
	
---***********************Quest data***********************
	local numItem 	= {};
	local rewardItems = RoMScript("GetQuestItemNumByType_QuestDetail( 3 )");  --number of reward items
	local choiceItems = RoMScript("GetQuestItemNumByType_QuestDetail( 2 )");  --Choice reward count
	if (self.Quests[index].Rewards == nil) then self.Quests[index].Rewards = {} end;
	self.Quests[index].Rewards.count = choiceItems;
	if( choiceItems ~= 0 ) then
		PrintLine("  - "..tostring(choiceItems).." rewards found:");
		for i = 1, choiceItems, 1 do
			local itemsName, itemsIconPath, itemiItemVal = RoMScript("GetQuestItemInfo_QuestDetail( 2, "..tostring(i).." )");		
			local reward = {};
			
			reward.itemName=itemsName;
			reward.itemCount=itemiItemVal;
			PrintLine("     : "..tostring(i)..". "..itemsName.."("..tostring(itemiItemVal)..")");
			
			self.Quests[index].Rewards[i]=reward;
		end
	end
end;

local FMT_QB_UPDATE = "QUEST\1BOOKUPDATE\1%s\1%s\0";
local FMT_QB_QUEST = "%d\2%s\2%d\2%d\2%d\2%d\2%d\2%d";

local FMT_QB_REWARD = "%d\3%s\3%d\2";

function CQuestBook:syncWithServer()
--send a message like: QUESTBOOK|UPDATE|Quest,rewards...
	local link = CServerLink("127.0.0.1", 31001, 5);
	
	local qCount = #self.Quests;
	for index=1,qCount,1 do
		self:syncQuestWithServer(index, link);
	end
	link:close();
end;

function CQuestBook:syncQuestWithServer(index, link)
--send a message like: QUESTBOOK|UPDATE|Quest,rewards...
	local linkDefined = (link ~= nil);
	if (not linkDefined) then
		link = CServerLink("127.0.0.1", 31001, 5);
	end;
	
	local quest = self.Quests[index];
	PrintLine("Sending quest: "..quest.Name..": reward count "..tostring(quest.Rewards.count));
	
	local rewardsText = "";
	for i=1,quest.Rewards.count,1 do
		local reward = quest.Rewards[i];
		if (reward) then
			local rewardFmt = sprintf(FMT_QB_REWARD, i, reward.itemName, reward.itemCount);
			rewardsText=rewardsText..rewardFmt;
		end;
	end;
	
	PrintLine("Level: "..tostring(quest.Level));
	PrintLine("StarterId: "..tostring(quest.StarterId));
	PrintLine("EnderId: "..tostring(quest.EnderId));
	local questDetail = sprintf(FMT_QB_QUEST, tonumber(quest.Id), tostring(quest.Name), tonumber(quest.Level), tonumber(quest.StarterId or 0), tonumber(quest.EnderId or quest.StarterId or 0), tonumber(quest.Gold), tonumber(quest.XP), tonumber(quest.TP));
	
	local questFmt = sprintf(FMT_QB_UPDATE, questDetail, rewardsText);
	link:send(questFmt, false);
	
	if (not linkDefined) then
		link:close();
	end;
end;

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

Re: Rock5's QuestLog Class

#30 Post by rock5 » Sat Sep 08, 2012 3:36 am

Firstly, your CQuest class is going to interfere with mine. You'll have to rename one. (CQuestBook, why didn't I think of that. Sounds much better that CQuestLog. :) )

Secondly, I'm not sure what you are trying to achieve. You said that you want to select cloth if it exists or select plate. So when creating the waypoint file you walk upto the npc, target it, press <Numpad5>, check the quest with the npc, if there is a cloth item (lets say it's option 1) you add the command "CompleteByName("questname",1)", if there isn't a cloth item then see which is the most expensive (lets say it's option 4) and add the command "CompleteByName("questname",4)". None of this requires anything extra.

Or are you saying you want to use a single command on all quests to automatically select the reward? Let me see your code... Do you want to be able to do something like

Code: Select all

player:target_NPC("npcname")
quest = questbook:getQuestById(questid)
CompleteQuestByName("questname", quest:getRewardConfiguredItemIndex())
  • 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

BillDoorNZ
Posts: 446
Joined: Wed Aug 03, 2011 7:37 pm

Re: Rock5's QuestLog Class

#31 Post by BillDoorNZ » Sat Sep 08, 2012 4:17 am

yep...auto selection by the bot - that way the waypoint file is more generic and not always taking what I program it to take :)

typical...making me rename my classes :) might start prefixing my classes from now on :)

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

Re: Rock5's QuestLog Class

#32 Post by rock5 » Sat Sep 08, 2012 5:30 am

The problem with that is there are too many variables. Do I choose by type? What if I'm already wearing something better? That means being able to rate items, both rewards items as well as worn items? What if other users don't like the way you rate them? What if the rewards are all the same item, such as rings, and I have to choose by item stats? What if the items don't fall into any of the categories I'm testing for, do I ust pick a default value or do I error? Do I just ignore all of the above and just select by price?

All of this is too much work. Just making the decission, is enough for a userfunction all to itself. And I'm pretty sure you can't even get all the info you need to make such decisions which is why I gave up on my similar project.

The one thing I would concider adding to my questlog class is maybe a "fetchRewardItems" function. That way you could concentrate on just making a function that rates the rewards and makes the selection and not have to worry about all the class stuff. How does that sound?
  • 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: Rock5's QuestLog Class

#33 Post by rock5 » Sat Sep 08, 2012 5:44 am

rock5 wrote:And I'm pretty sure you can't even get all the info you need to make such decisions which is why I gave up on my similar project.
I just realised something. I was never able to get all the information I wanted about rewards, when I was working on my "item rater" because I was trying to get as much info as possible from the npc dialog because I thought "you might not have the quest in your quest book so you have to get the info from the dialog.

But it just occured to me (I don't know why I never realised this before) to select a reward and complete the quest you have to have already accepted the quest. That means I should be able to get the rewards from the quest book and therefore probably from memory too. :D
  • 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

BillDoorNZ
Posts: 446
Joined: Wed Aug 03, 2011 7:37 pm

Re: Rock5's QuestLog Class

#34 Post by BillDoorNZ » Sat Sep 08, 2012 8:50 am

lol

hear what you are saying about complexity of reward item choosing. I only ever built that stuff for how I play the game, which is a helluva lot simpler than making it generic.

to make it generic, y'd have to allow a plugin style algorithm which would be beyond joe user anyway.

BillDoorNZ
Posts: 446
Joined: Wed Aug 03, 2011 7:37 pm

Re: Rock5's QuestLog Class

#35 Post by BillDoorNZ » Wed Sep 19, 2012 3:29 pm

Finally had some time to start fiddling with this. I'm adding the following method to the CQuest class (as I use something like it ALL the time).

It was a right pain to do this, as the 2 types of goals are held in separate tables. I might refactor a bit and amalgamate the two tables into 1 with a goal type property instead. That should make it easier to work with when you want to check ALL goals as well :)

NOTE: This is complete untested - haven't even tried to start the bot with this code in the userfunction yet :) Just posting here while I'm not playing :(

Code: Select all

	function CQuest:isGoalComplete(nameorid)
		--find the goal first!
		local goalObject = nil;
		local goalIndex = -1;
		local isKillGoal = false;
		
		for k,goal in pairs(self.KillGoals) do
			if type(nameorid) == "number" then
				matched = (goal.Id == nameorid)
			else
				if string.find(nameorid,".",1,true) then -- Use Pattern Search
					matched = string.find(string.lower(goal.Name), string.lower(nameorid))
				else -- Use plain search
					matched = string.find(string.lower(goal.Name), string.lower(nameorid), 1, true)
				end
			end

			if matched then
				goalIndex = k;
				goalObject = goal;
				isKillGoal = true;
				break;
			end
		end;
		
		if (~goalObject) then
			--is an item quest
			for k,goal in pairs(self.ItemGoals) do
				if type(nameorid) == "number" then
					matched = (goal.Id == nameorid)
				else
					if string.find(nameorid,".",1,true) then -- Use Pattern Search
						matched = string.find(string.lower(goal.Name), string.lower(nameorid))
					else -- Use plain search
						matched = string.find(string.lower(goal.Name), string.lower(nameorid), 1, true)
					end
				end

				if matched then
					goalIndex = k;
					goalObject = goal;
					break;
				end
			end;
		end;
		
		if (goal) then
			if (isKillGoal) then
				return (self:getKillCount(k) < goal.NumReq);
			else
				return (inventory:itemTotalCount(goal.Id) < goal.NumReq);
			end;
		end;
		return false;
	end;

BillDoorNZ
Posts: 446
Joined: Wed Aug 03, 2011 7:37 pm

Re: Rock5's QuestLog Class

#36 Post by BillDoorNZ » Wed Sep 19, 2012 3:48 pm

any chance you saw the address offsets for gold, xp and tp for the quest in there too Rock? :)

Once I have all that, then that pretty much replaces all the calls I make to Rom. Which will be fantastic! I tend to disable my Quest Book updating when I play as it takes it too long to get all the quest info. With your new stuff, I can see that I will be able to leave it all running as it will be blindingly fast in comparison.

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

Re: Rock5's QuestLog Class

#37 Post by rock5 » Thu Sep 20, 2012 1:05 am

BillDoorNZ wrote:It was a right pain to do this, as the 2 types of goals are held in separate tables. I might refactor a bit and amalgamate the two tables into 1 with a goal type property instead. That should make it easier to work with when you want to check ALL goals as well
Pretty much all the functions I've added so far benefit from them being separate tables because they need to be treated differently even though for this function it would have benefited them being in one.

Comments:
  • - The function is a good idea because then the user doesn't have to figure out which type goal is.
    - 'matched' needs to be localized.
    - "(~goalObject)" I think you meant "(not goalObject)"
    -

    Code: Select all

    return (inventory:itemTotalCount(goal.Id) < goal.NumReq);
    should be

    Code: Select all

    return (self:getItemCount(k) < goal.NumReq);
    Because not all item goals are items but tasks instead. So if it's not an item it gets the goal using a RoMScript. Wait, I haven't posted that function yet. Well, when I do, that's the function you should use.
    - Maybe 1 last comment. You save 3 variables to help you decide which one line command to use at the end. Maybe you could just do the command instead. So instead of

    Code: Select all

             if matched then
                goalIndex = k;
                goalObject = goal;
                isKillGoal = true;
                break;
             end
    you could do

    Code: Select all

             if matched then
                return (self:getKillCount(k) < goal.NumReq);
             end
    - Which makes me realize you forgot to use those 3 variables at the end there anyway.
Otherwise I'm happy 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

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

Re: Rock5's QuestLog Class

#38 Post by rock5 » Thu Sep 20, 2012 1:13 am

BillDoorNZ wrote:any chance you saw the address offsets for gold, xp and tp for the quest in there too Rock? :)

Once I have all that, then that pretty much replaces all the calls I make to Rom. Which will be fantastic! I tend to disable my Quest Book updating when I play as it takes it too long to get all the quest info. With your new stuff, I can see that I will be able to leave it all running as it will be blindingly fast in comparison.
Why do you need gold, xp and tp? The only reason I can think of is to make a decision. You most likely will make the decision at a location once. I'm of the philosophy that you shouldn't get stuff from memory unless it's necessary, for example when continuously checking the status of a quest while farming. For things you do only once or at safe locations such as at the npc, I'd just use RoMScript. Saves on maintenance later.
  • 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

Buster99
Posts: 69
Joined: Fri Nov 25, 2011 9:27 am

Re: Rock5's QuestLog Class

#39 Post by Buster99 » Mon Dec 31, 2012 5:15 pm

I am having all kinds of troubles using getQuestStatus in the Dwarf starting zone quests. I am using it the exact same way I do in other scripts in other zones, which continue to work flawlessly. I can not get it to return a "complete" so the script just continues to kill the quest mobs endlessly. I have tried by name and by using the ID's from runesdb.

Is there a problem with this because the zone quests are new and not discoverable by getQuestStatus?

Is there another way for me to script mob kills? Accepting and completing quests work fine but its these kill quests I cannot get to work.

Thanks for any help in advance.

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

Re: Rock5's QuestLog Class

#40 Post by rock5 » Mon Dec 31, 2012 10:28 pm

I've actually been looking at this recently. It seems an address, that the file uses, has changed. So it needs updating. I'll keep working on it and get a fix out.
  • 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

Post Reply

Who is online

Users browsing this forum: No registered users and 12 guests