Log in

View Full Version : Hash Array in Perl Question


Shin Noir
06-14-2016, 04:28 AM
I got this little plugin i'm mucking around, this is just a snippet, but the idea is still there:

The problem: quest::say always just says "Requires " once, and never iterates/echos anything of note.

pastebin probably easier to read.

http://pastebin.com/NGwDt2Rj

sub DoArmorHandin {

my $armor_list;
$tmp_zone = 113;
$tmp_class = 9;
$armor_list[$tmp_zone][$tmp_class][6] = {slot => 19, item => 24938, reward => 31014}; #boots

foreach my $entry ($armor_list[$zoneid][$class]) {
quest::say("Requires ".$entry);
if (plugin::check_handin(\%itemcount,$entry{item}) => 1 &&
$cash >= (plugin::DoPricingBySlot($entry{slot})*1000)) {
quest::summonitem($entry{reward});
return 1;
}
}
return 0;
}

Kingly_Krab
06-14-2016, 04:47 AM
Change this: foreach my $entry ($armor_list[$zoneid][$class]) {

To this: foreach my $entry (@{$armor_list[$zoneid][$class]}) {

Kingly_Krab
06-14-2016, 04:48 AM
That change uses Perl's dynamic type casting and allows the foreach to recognize it as an array rather than a singular variable.

Shin Noir
06-14-2016, 05:57 AM
I was still having some peculiar issues, that aside though.. my next issue is..

I'm trying to check_handin and it seems to always be empty with itemcount, so, i'm trying to pass itemcount, similar to how check_handin does it.


plugin::velious_armor_handin($zoneid, $cash, $client->GetClass(), \%itemcount)


I call it itemref. the Got Item! line never triggers, even if I use proper item id.

sub velious_armor_handin {
my $zoneid = shift;
my $cash = shift;
my $classid = shift;
my $itemref = shift; #I don't know if perl does a pointer reference or what, emulating check_handin's code to pass along
my $armor_list = plugin::velious_armor_list();

for $x (0...6) {
$slot = $armor_list[$zoneid][$classid][$x]{slot};
$item = $armor_list[$zoneid][$classid][$x]{item};
$reward = $armor_list[$zoneid][$classid][$x]{reward};
quest::say("Looking for $slot in $item for reward $reward");
if (plugin::check_handin(\%itemref, $item => 1)) { #i'm passing itemref here, to check_handin.
quest::say("Got item!"); #this line never echos.
if ($cash >= (plugin::pricing_by_slot($slot)*1000)) {
quest::summonitem($reward);
return 1;
} else { #fail!
return 0;
}
}
}
return 0;
}

ghanja
06-14-2016, 09:43 AM
Would be curious to see the hash itself as it looks like a hash of arrays of arrays, however, at a very quick glance as I'm just perusing with limited time atm:


for $x (0...6) {


You have an extra period in the range operator.

I assume this hash that you're concocting contains quest hand-in/reward?

Shin Noir
06-14-2016, 03:47 PM
Didn't even see that, but oddly, perl is OK with three dots. I'll change it up to ensure no other side effects.
http://codepad.org/7A83V6CT

The challenge/solution I originally posted I ended up re-approaching and iterating the $armor_list as an array, and then grabbing the hash data as seen on the bottom example.

My only snag now is that I'm trying to transfer the %itemcount hash to plugin::check_handin() via another function, plugin::velious_armor_handin() and for some reason, passing the variable from function to function is not doing pointer refs. May end up picking up a programming book about perl, but figured perl experts can peek and be like "Do X instead of Y", and save me a ton of time of fiddling and google research that inevitably is probably a 2 line fix.

c0ncrete
06-14-2016, 04:08 PM
from http://perldoc.perl.org/perlref.html

"References are easy to use in Perl. There is just one overriding principle: in general, Perl does no implicit referencing or dereferencing. When a scalar is holding a reference, it always behaves as a simple scalar. It doesn't magically start being an array or hash or subroutine; you have to tell it explicitly to do so, by dereferencing it."

Shin Noir
06-14-2016, 05:17 PM
Thanks c0ncrete. So the answer to my question is: \%{$itemref}

sub velious_armor_handin {
my $zoneid = shift;
my $cash = shift;
my $classid = shift;
my $itemref = shift; #I don't know if perl does a pointer reference or what, emulating check_handin's code to pass along
my $armor_list = plugin::velious_armor_list();

for $x (0...6) {
$slot = $armor_list[$zoneid][$classid][$x]{slot};
$item = $armor_list[$zoneid][$classid][$x]{item};
$reward = $armor_list[$zoneid][$classid][$x]{reward};
quest::say("Looking for $slot in $item for reward $reward");
if (plugin::check_handin(\%{$itemref}, $item => 1)) { #i'm passing itemref here, to check_handin.
quest::say("Got item!"); #this line never echos.
if ($cash >= (plugin::pricing_by_slot($slot)*1000)) {
quest::summonitem($reward);
return 1;
} else { #fail!
return 0;
}
}
}
return 0;
}



ghanja sent me a PM that informed shift is destructive and pulls data out of the argument list @_ so, I will keep that in mind while I finish fixing other issues.

This is all complete, and I posted the solutions to my question on each part, for anyone else who may have similar questions.

Thanks for your help guys.

c0ncrete
06-14-2016, 05:23 PM
it's been a very long time since i've been eyeball deep in perl, but that looks syntactically correct at least. i don't have my old work to reference at the moment (at the office currently), but i'll be digging up some old stuff where i was using references all over the place when i get back to the house in a few hours.

Shin Noir
06-14-2016, 05:28 PM
my tl;dr to answer my own question:

perl == c++

/$var == &var
{$var} == *var