Page 1 of 1

Modified openGiftbags1To10() function

Posted: Thu Aug 15, 2013 1:43 pm
by Bill D Cat
I took some time this morning to rewrite the code for the openGiftbags1to10() function. I play mostly on the Nexon private server and so had issues with the first quest I turned in taking me to level 3. This modified function will open all available bags when the bot levels from 1 to 10. After level 10 it just issues a "return" call and skips the function completely.

Code: Select all

-- open gift bag (at the moment level 1-10)
-- Updated by Bill D Cat on Aug 15, 2013
-- Loop to allow all bags up to current level to be opened. Useful if XP orb used and more than one level gained, or if playing on Nexon private server.
-- Only use Fruit of Extra Experience at level 9, otherwise the second one is wasted at level 10 if the 1hr buff hasn't expired.
function openGiftbags1To10(_player_level)
	player:updateMounted()
	local wasMounted = player.Mounted
	if( not _player_level) then _player_level = player.Level; end
	if _player_level > 10 then return; end											-- Don't waste time checking for bags beyond level 10.
	for kk = 1, 10 do																-- Find first available bag. Reduce item not found messages.
		for i,v in pairs(database.giftbags)  do
			if( v.level == kk) then
			local gb_item = inventory:findItem( v.itemid, "bags" );				-- Find item in backpack
				if ( gb_item and v.type == "bag" ) then
					ll = kk
				end
			end
		end
	end
	for jj = ll, _player_level do
		for i,v in pairs(database.giftbags)  do
			if( v.level == jj) then
				local gb_item = inventory:findItem( v.itemid, "bags" );				-- Find item in backpack
				if ( not gb_item ) then
					cprintf(cli.yellow, language[174], GetIdName(v.itemid) );		-- item not found
				elseif (v.type == "bag") then 
					cprintf(cli.lightblue, language[170], jj );						-- Open and equip gift bag for level
					gb_item:use()
					yrest(6000);													-- wait for using that item
					inventory:update();												-- update slots
				elseif (v.type == "is") then
					cprintf(cli.lightblue, language[159], gb_item.Name );			-- Moving to Item Shop bag:
					gb_item:moveTo("itemshop")
				elseif (v.armor == armorMap[player.Class1] or v.type == "" ) then 	-- Only equip items that meet class requirements.
					cprintf(cli.lightblue, language[171], gb_item.Name );			-- Open/equip item:
					gb_item:use()
				elseif (v.type == "xp" and jj == _player_level) then				-- Only use Fruit of Extra Experience at level 9
					cprintf(cli.lightblue, language[171], gb_item.Name );			-- Open/equip item:
					gb_item:use()
					yrest(3000);													-- wait for using that item
				end
			end
		end
	end
	player:updateMounted()
	if wasMounted and not player.Mounted then
		player:mount()
	end
end
The other change needed for this to work properly is to set the type of the Fruit of Extra Experience to "xp" in the database/giftbags.xml file.

Code: Select all

	<giftbag itemid="202152" type="xp"	armor=""        level="9" name="Frucht der zus\132tzlichen Erfahrung" />

Re: Modified openGiftbags1To10() function

Posted: Thu Aug 15, 2013 9:49 pm
by Bill D Cat
I noticed another issue with the current giftbags.xml file. Because the Elf bags are listed at the end and do not include the Item Shop items they contain, the function will never move them into the Item Shop bag for you. Since all the other items from human/elf bags are the exactly the same, and only the bag names are different, I think it would be best to just merge the elf bag entries into the top part of the list after each human bag of the same level.

Re: Modified openGiftbags1To10() function

Posted: Fri Aug 16, 2013 1:40 am
by rock5
Bill D Cat wrote:Because the Elf bags are listed at the end and do not include the Item Shop items they contain, the function will never move them into the Item Shop bag for you.
I see what you mean. It goes through the database in order so if the bag is after the item then the item doesn't get used. Merging would be ok but it's neater and probably would make it easier to update the database if it's left in 2 sections. Maybe we could have the bot look for the bag first and open it, then use the items. It would require 2 passes but shouldn't take long.

I'm not sure about automatically using the fruit of extra experience, for a number of reasons. What if the user wants to save them for when they are at higher lever or maybe they want to use them when they power level their character or maybe they want to make sure it uses the fruit at the optimal time (ie. just before it's about to kill lots of stuff) or maybe they just don't like wasting it on the 1-10 script which usually finishes before the fruit runs out.

Re: Modified openGiftbags1To10() function

Posted: Fri Aug 16, 2013 10:47 am
by Bill D Cat
Taking the Fruit of Extra Experience out of the list would be all that's required to keep the bot from using it. I just put in the failsafe to only use one because I had it use them both at one time during my testing. Here's how I set up my giftbags.xml to merge the elf bags with the rest of the list. This is only the first few bags, but the rest are all done the same way.
<giftbags>
<!-- Giftbags Lvl 1 - 25 -->
<!-- field 'name' is only as info, we read the name later from the client -->
<giftbag itemid="201843" type="bag" armor="" level="1" name="Magic Package" />
<giftbag itemid="221668" type="" armor="" level="1" name="Magic Ring" />

<giftbag itemid="201844" type="bag" armor="" level="2" name="Adventurer's Package" />
<giftbag itemid="221669" type="" armor="cloth" level="2" name="Cloth Belt" />
<giftbag itemid="221670" type="" armor="leather" level="2" name="Leather Belt" />
<giftbag itemid="221671" type="" armor="chain" level="2" name="Chain Belt" />
<giftbag itemid="203571" type="is" armor="" level="2" name="Brown Horse (1 Day)" />

<giftbag itemid="201845" type="bag" armor="" level="3" name="Pioneers Package" /> -- Humans
<giftbag itemid="205931" type="bag" armor="" level="3" name="Academy Package" /> -- Elves
<giftbag itemid="221672" type="" armor="" level="3" name="Pioneers Earring" />

<giftbag itemid="201846" type="bag" armor="" level="4" name="Colony Package" /> -- Humans
<giftbag itemid="205932" type="bag" armor="" level="4" name="Certification Package" /> -- Elves
<giftbag itemid="221673" type="" armor="" level="4" name="Colony Cloak" />

<giftbag itemid="201847" type="bag" armor="" level="5" name="Mine Package" /> -- Humans
<giftbag itemid="205933" type="bag" armor="" level="5" name="Master Package" /> -- Elves
<giftbag itemid="221674" type="" armor="cloth" level="5" name="Cloth Leggings" />
<giftbag itemid="221675" type="" armor="leather" level="5" name="Leather Leggings" />
<giftbag itemid="221676" type="" armor="chain" level="5" name="Chainmail Leggings" />
<giftbag itemid="202902" type="is" armor="" level="5" name="Marking Ink" />
<giftbag itemid="202903" type="is" armor="" level="5" name="Transport Rune" />

Re: Modified openGiftbags1To10() function

Posted: Fri Aug 16, 2013 11:19 am
by rock5
The more I think about it the more I get the urge to rewrite the function, something along the lines of

pseudo code

Code: Select all

repeat
    Search for a bag from the database
    if bag found and bag.level <= _player_level then
        open bag 
        use items of that level
    end
until not bag

Re: Modified openGiftbags1To10() function

Posted: Fri Aug 16, 2013 12:47 pm
by Bill D Cat
The other thing that I was thinking about was the fact that both the elves and dwarves get better gear from their starting quests than what is available from the bags. So auto-equiping the bag items might be downgrading your equipment. Perhaps just opening the bags and moving the IS items would be enough. It would be up to the player to code in the proper inventory:useItem() calls to equip the bag items or quest rewards based on their preference.

I was building up a series of waypoints for the Elven Island quests and noticed that two of the early quest rewards are earrings. Both of them are better than the bag items, so I wanted to use them instead. However there seems to be a limitation to the way that the inventory:useItem() equips the items. For the RINGS, EARRINGS and MAINHAND/SECONDARY HAND, it doesn't have an option to pick which slot you want to equip the item into.

Here's what happened with my elf experiment:

Level 1 -> Opened bag -> Equip RING to RING1 slot
Level 2 -> Opened bag -> Equip BELT
Level 3 -> Opened bag -> Equip EARRING to EARRING1 slot
Level 4 -> Opened bag -> Equip CLOAK
Level 5 -> Opened bag -> Moved IS items -> Equip LEGGINGS

Now, at this point I had completed some quests that gave me two other earrings. When I try to equip them, the first gets sent to EARRING2 slot, and the next replaces it in EARRING2 leaving the earring from the level 3 gift bag still equiped. Is there a way to specify what slot you want to use for an item, or perhaps a command to remove an equipped piece first to create an empty slot so it gets filled with the item specified in the function call?

Re: Modified openGiftbags1To10() function

Posted: Fri Aug 16, 2013 2:41 pm
by rock5
After finding the item, you should be able to move it to a particular slot

Code: Select all

item = inventory:findItem(...)
item:moveTo("left earring") -- or "right earring"

Re: Modified openGiftbags1To10() function

Posted: Fri Aug 16, 2013 4:24 pm
by Bill D Cat
Ah, thanks. I was focused in on the :useItem() too much. I didn't even think to try the :moveTo() variation. That will help me a lot with this set of waypoints I'm working on now. I'll go dig up the StatRating thread I saw earlier and see if I can incorporate something like that into my arsenal to help equip the best pieces on hand.

Re: Modified openGiftbags1To10() function

Posted: Thu Sep 12, 2013 1:10 pm
by Bill D Cat
rock5 wrote:After finding the item, you should be able to move it to a particular slot

Code: Select all

item = inventory:findItem(...)
item:moveTo("left earring") -- or "right earring"
Finally got around to testing this, and it doesn't work. The item class just uses the self:use() method, and does not allow you to specify what slot you want to place the item into.

Code: Select all

function CItem:moveTo(bag)

	if location == "equipment" then
		-- Check if is type equipment
		if self.ObjType ~= 0 and self.ObjType ~= 1 then
			return
		end

		if bag == "equipment" or bag == "amulets" then -- No particular slot. Just use item to equip.
			self:use()
		else
			self:pickup()
			equipment.BagSlot[first]:pickup()
		end

		return
	end
I thought that the inventory:findItem() might return a bag position value that I could use with a EquipItem() romscript call, but looking over the item class it doesn't seem to support it. I think it would be easy to add, since the inventory:findItem() does a bag search by slot, so the value is known at some point, just not passed to the item class for retrieval later.

Re: Modified openGiftbags1To10() function

Posted: Thu Sep 12, 2013 2:54 pm
by rock5
Bill D Cat wrote: Finally got around to testing this, and it doesn't work. The item class just uses the self:use() method, and does not allow you to specify what slot you want to place the item into.
Yes it does. I tested it, it worked fine.

This gets the slot number for "left earring".

Code: Select all

	local first, last, location = getInventoryRange(bag)
And because bag doesn't equal "equipment" or "amulets", this is the code it uses to move it. I doesn't use item:use().

Code: Select all

			self:pickup()
			equipment.BagSlot[first]:pickup()
Bill D Cat wrote:I thought that the inventory:findItem() might return a bag position value that I could use with a EquipItem() romscript call, but looking over the item class it doesn't seem to support it.
The item class found in item.lua is a generic class used by inventoryitem.lua, bankitem.lua, etc. It doesn't include the slot information. Look to those other files to see the slot info.

There are 2 numbers associated with items .SlotNumber and .BagId. SlotNumber is the actual slot number as you see them. BagIds, for all other item classes except inventory, are the same as SlotNumber but in the backpack the BagIds can be different than the SlotNumbers. Certain in game function need either the SlotNumber or the BagId. I think EquipItem uses the BagId.

Re: Modified openGiftbags1To10() function

Posted: Sun Sep 22, 2013 4:10 am
by Bill D Cat
And now for yet another twist to this puzzle. The level 1 to 9 starting bags for the Dwarves are completely different names/IDs from the ones that Humans and Elves get. The contents are the same (other than the next bag in the sequence). So here's my updated database/giftbags.xml and the latest modified version of the openGiftbags1To10 function from the functions.lua file. Feel free to include it in the next commit if you feel it is worth adding.

Re: Modified openGiftbags1To10() function

Posted: Sun Sep 22, 2013 6:45 am
by rock5
I guess it doesn't matter if we include the higher level giftbags, especially as I see you have it stopping at bag 19 so the mount can be kept until the user wants to use it.

I see you marked the experience potion with "xp". This means nothing to the bot. Have you modified your bot to use this or are you just hoping for something? I certainly wouldn't want it to automatically use an xp pot that I could use later when I could make the most of it.

Putting everything in order with the bags first solves that bug you mentioned earlier.

Now looking at openGiftbags. First you search for which bag you have. You should probably break after finding it. You'll have to break out of 2 for loops. I'd use a better variable name than ll, something like foundlevel. And it should be local. And one last thing, you search for every item in the inventory before checking if it's a bag. Probably better if you check if it's a bag first before bothering to do a search for it.

Then the next part where it uses the items looks all good but again I would use a better variable than jj. :) Something like currentlevel. Also I noticed you messed with the timings. The original gave 2s to equip gear and 6s to open bags. You have no time to equip gear and 8s to open bags. Have you tried equiping multiple items with no pause? As to opening bags, I have an idea for that. Does the bag contents fill the item queue before going into the bag? If so we could use ItemQueueCount(). Eg.

Code: Select all

repeat yrest(1000) until ItemQueueCount() == 0
One last thing, what are we going to do about the function name? It's no longer 1 to 10. We could change it but then if users have the function in their own custom profiles then it wont work anymore. We could leave it as it is I suppose.

Re: Modified openGiftbags1To10() function

Posted: Sun Sep 22, 2013 8:48 am
by Bill D Cat
My original intent was to get it to properly equip all the items from the bags, which is why the non class specific stuff like jewelry and such now have an armor type of "any". The Fruit of Extra Experience can be completely removed from the list and left for the end user to decide when they want to use it. I just added the "xp" flag so that the function could identify it as something NOT to equip. It will look for "cloth", "leather", "chain" or "any" and try to equip those items instead.

The first loop to search for the bags was needed for those that play on the Nexon private server, as turning in the very first quest took you to level 3 and totally messed up the original function since it went looking for that bag and only the one for level 2 was in the users backpack.

All in all, I don't care what the variables are for the loops, I just picked something to use while getting it all working right. The timing was just me counting how long it took for the bag with the most items (bags for level 5 and 10 I believe) to dump their contents into the backpack. Checking for the ItemQueueCount would certainly be a more elegant and faster solution, but one that I as a new user of the bot probably wouldn't have even been aware existed. So if you can clean it up and maintain the functionality where it finds the next available bag and starts from that point, that's all that really matters in the end.

Renaming the function would be unnecessary I think. It's intent was to be used in the demo to show the power and flexibility of the bot. I just wanted it to work properly no matter what race you were playing, or on whatever server you decided to call home.

Re: Modified openGiftbags1To10() function

Posted: Sun Sep 22, 2013 10:05 am
by rock5
Something like this?

Re: Modified openGiftbags1To10() function

Posted: Sun Sep 22, 2013 12:38 pm
by Bill D Cat
Yeah, that will work fine. Only thing I'd suggest is to remove the comment regarding the XP Fruit, as the function won't use it anyway. I guess I missed it when I uploaded my copy.

Code: Select all

-- Only use Fruit of Extra Experience at level 9, otherwise the second one is wasted at level 10 if the 1hr buff hasn't expired.

Re: Modified openGiftbags1To10() function

Posted: Sun Sep 22, 2013 1:33 pm
by rock5
I'll probably just leave the top comment like it was.

Code: Select all

-- open gift bag (at the moment level 1-19)

Re: Modified openGiftbags1To10() function

Posted: Fri Sep 27, 2013 12:30 pm
by rock5
I've committed what we've done so far.
http://www.solarstrike.net/phpBB3/viewt ... 861#p52861