Go Back   EQEmulator Home > EQEmulator Forums > Quests > Quests::Q&A

Quests::Q&A This is the quest support section

Reply
 
Thread Tools Display Modes
  #1  
Old 10-17-2009, 09:18 PM
Valdaun
Fire Beetle
 
Join Date: Oct 2009
Posts: 28
Question Need some perl array help

I am trying to make a very simple and scalable quest script utilizing arrays of item turnin + rewards. I have it working now, but I am positive I can simplify this just a tad more, hence my post.

Below are some code snippets showing how I am doing it now, then I will ask my questions after the code.

First I define the item turnin + reward array at the top of the .pl file (this particular quest "upgrades" a few old world weapons to fabled status):

Code:
my %turnins = (
	1 => { "item" => 5401, "reward" => 68259 },	#Mithril 2 hander & fabled
	2 => { "item" => 5403, "reward" => 68260 },	#Ghoulbane & fabled
	3 => { "item" => 5500, "reward" => 68263 },	#SS of Ykesha & fabled
	4 => { "item" => 5412, "reward" => 68262 }	#Razing Sword of Skarlon
);

my $max_turnins = 4;	# must manually set to highest number above
my $cost = 22503;	# blue diamond (dropped)
my $cost_link = quest::varlink($cost);
Then in the hailing portion of the script, this is an example of how I use the array and some say + item links:

Code:
$client->Message(315, "At this time, I am able to convert a $cost_link along
with the basic version of any of these weapons into their fabled counterparts:");

# loop through item + reward array and send a list of items to client 
for (my $i = 1; $i <= $max_turnins; $i++)
{
	my $link = quest::varlink($turnins{$i}{"item"});
	$client->Message(315, "$link")
}
Lastly, here is what I am using to actually check for the turnins:

Code:
my $gaveitem = 0;

# loop through item + reward array looking for a match
for (my $i = 1; $i <= $max_turnins; $i++)
{
	# hand out the goods on a match of item + cost
	if (plugin::check_handin(\%itemcount, $turnins{$i}{"item"} => 1, $cost => 1))
	{
		$gaveitem = 1;
		quest::summonitem($turnins{$i}{"reward"});
	}
}

# if there were no matches, give back what was turned in
if ($gaveitem == 0)
{
	plugin::return_items(\%itemcount);
}
Questions -

So the main thing I would like to change is to not have to specify the array index numbers myself, but I do not know enough about perl syntax to know how to do this.

I would then like to know how I can get a count of the number of items in the array. That way I don't have to create the $max_turnins variable.

Lastly, perhaps this would be easier to accomplish using foreach to automatically go through the whole array? So if anyone has an example that could replicate what I am doing above with foreach that would be very helpful.
Reply With Quote
  #2  
Old 10-17-2009, 09:45 PM
joligario's Avatar
joligario
Developer
 
Join Date: Mar 2003
Posts: 1,490
Default

If I am reading you right, I think you might be looking for $itemcount
Reply With Quote
  #3  
Old 10-17-2009, 10:11 PM
Valdaun
Fire Beetle
 
Join Date: Oct 2009
Posts: 28
Default

Sorry, I guess I wasn't totally clear. I need a way to have perl tell me how many entries are in my $turnins array I create at the beginning. That way I don't need to manually create another variable for that number myself. (4 in this case, since I have 4 item + reward entries in my example array) In PHP I could use the count() function to do this:

Code:
$max_turnins = count($turnins);
$itemcount is something else, and you can see I do use that too.

Thanks though
Reply With Quote
  #4  
Old 10-17-2009, 11:39 PM
Kobaz
Hill Giant
 
Join Date: Nov 2008
Location: Gold Coast, Oz
Posts: 119
Default

couldn't you use the ids of the turn-ins as keys to a hash that has the fabled item-id and costs in another hash? Then you wouldn't need an integer index, or a loop.
Reply With Quote
  #5  
Old 10-18-2009, 12:08 AM
pfyon's Avatar
pfyon
Discordant
 
Join Date: Mar 2009
Location: Ottawa
Posts: 495
Default

Not a lot of experience with perl either, but you just want to know the length of the array? A quick google got me this blog posting with 3 ways to determine the number of elements in an array: http://www.devdaily.com/blog/post/pe...gth-perl-array .

Code:
A frequently asked question Perl question is "How do I determine the size of a Perl array?", or the equivalent "How do I determine how many elements are in a Perl array?"

There are at least three different ways to do determine the length of a Perl array. The easiest way to demonstrate this is with some sample source code:

#----------------------------#
# create a simple Perl array #
#----------------------------#
@foods = qw(burgers fries shakes);

#------------------------------------------------------#
# three different ways to get the size of a Perl array #
#------------------------------------------------------#

# 1) implicit scalar conversion:
$size1 = @foods;

# 2) explicit scalar conversion:
$size2 = scalar @foods;

# 3) index of the last element in the array, plus one:
$size3 = $#foods + 1;

printf("The sizes are %d, %d, and %d\n", $size1, $size2, $size3);

which has the corresponding output:

The sizes are 3, 3, and 3
Reply With Quote
  #6  
Old 10-18-2009, 12:21 AM
Valdaun
Fire Beetle
 
Join Date: Oct 2009
Posts: 28
Default

Those are promising and exactly what I want; unfortunately, either it doesn't work for multidimensional arrays, or the way perl and the emulator interact doesn't allow that syntax. I had previously tried the $#array method before, but additionally tried the other two just now and no go. :(
Reply With Quote
  #7  
Old 10-19-2009, 04:18 PM
Kobaz
Hill Giant
 
Join Date: Nov 2008
Location: Gold Coast, Oz
Posts: 119
Default

Do the following work?

Code:
my %turnins = (
	 5401,  68259 ,	#Mithril 2 hander & fabled
	 5403,  68260 ,	#Ghoulbane & fabled
	 5500,  68263 ,	#SS of Ykesha & fabled
	 5412,  68262 	#Razing Sword of Skarlon
);

my $cost = 22503;	# blue diamond (dropped)
my $cost_link = quest::varlink($cost);
Code:
$client->Message(315, "At this time, I am able to convert a $cost_link along
with the basic version of any of these weapons into their fabled counterparts:");
my $key = 0;
# loop through item + reward array and send a list of items to client 
foreach $key (sort keys %turnins) 
{
	my $link = quest::varlink($turnins{$key});
	$client->Message(315, "$link")
}
Code:
my $gaveitem = 0;
my $key = 0;
# loop through item + reward array looking for a match
foreach $key (sort keys %turnins)
{
	# hand out the goods on a match of item + cost
	if (plugin::check_handin(\%itemcount, $turnins{$key} => 1, $cost => 1))
	{
		$gaveitem = 1;
		quest::summonitem($turnins{$key}}{"reward"});
	}
}

# if there were no matches, give back what was turned in
if ($gaveitem == 0)
{
	plugin::return_items(\%itemcount);
}
Reply With Quote
  #8  
Old 10-19-2009, 05:12 PM
Kobaz
Hill Giant
 
Join Date: Nov 2008
Location: Gold Coast, Oz
Posts: 119
Default

aargh typo:

Code:
                $gaveitem = 1;
		quest::summonitem($turnins{$key});
Reply With Quote
  #9  
Old 10-23-2009, 12:42 PM
Valdaun
Fire Beetle
 
Join Date: Oct 2009
Posts: 28
Default

Thank you for that! You got me exactly where I wanted to get to, though I took a slightly different approach for the array.

Using the quest turnin item ID as the primary index in my array was just the ticket.

I'll put up the whole quest in another post, but here's the interesting snippets of the finished product:

Array creation:

Code:
my %fabled_turnins = (
	5401 => { "cost" => $rare_cost, "reward" => 68259 },	#Mithril 2 hander & fabled
	5403 => { "cost" => $rare_cost, "reward" => 68260 },	#Ghoulbane & fabled
	5500 => { "cost" => $rare_cost, "reward" => 68263 },	#SS of Ykesha & fabled
	5412 => { "cost" => $rare_cost, "reward" => 68262 }		#Razing Sword of Skarlon & fabled
);
And from EVENT_ITEM:

Code:
foreach $item_id (sort keys %fabled_turnins)
{
	$cost = $fabled_turnins{$item_id}{"cost"};
	$reward = $fabled_turnins{$item_id}{"reward"};

	# hand out the goods on a match of item + cost
	if (plugin::check_handin(\%itemcount, $item_id => 1, $cost => 1))
	{
		quest::summonitem($reward);
	}
}
Reply With Quote
Reply


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

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

Forum Jump

   

All times are GMT -4. The time now is 07:58 PM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3