PDA

View Full Version : Turn-in trouble


sklead
08-07-2007, 11:47 AM
I've made a few quests that require items to be turned in. Some of them require 1 item, some require 2 or more, and some require multiple item turn-ins at different times. For the quests that need 1 or 2+ items at once, people can turn in 1 of any item (ex. You need an apple but you turn in a twig and it does the same thing). For the multiple turn-in quest, if you turn in 1 of any item, it gives you experience and/or the item(s) for every part of the quest (ex. You need a necklace, then after you get xp you need a ring, but it gives you xp as if you turned in both.). My question is, how might I fix this problem?

Quest needing 1 item:

sub EVENT_SAY{
if ($text=~/Hail/i){quest::say("Aaarrggghhh! [Go away]!");}
if ($text=~/go away/i){quest::say("I want my [axe]!");}
if ($text=~/axe/i){quest::say("Those blasted Crushbone Orcs took it!");}
}
sub EVENT_ITEM{
if ($item1=5014){quest::say("Ggrrr, I didn't need your help...");quest::exp(1000);}
}


Quest needing 2+:

sub EVENT_SAY{
if ($text=~/hail/i){quest::say("Hello there, I am Ligi. I can craft any type of armor out of any materials! Say, you look like someone who might enjoy Orc Skin [armor].");}
if ($text=~/armor/i){quest::say("Only the finest, especially from orc skins. Just bring me back one to four pieces of orc skin and I can craft some armor for you.");}
}
sub EVENT_ITEM{
if ($itemcount{32638}=1){quest::say("Excellent! This is enough to make a fine pair of gloves.");quest::exp(2500);quest::summonitem(2010);}
if ($itemcount{32638}=2){quest::say("Excellent! This is enough to make a fine pair of boots.");quest::exp(2500);quest::summonitem(2012);}
if ($itemcount{32638}=3){quest::say("Excellent! This is enough to make a fine pair of sleeves.");quest::exp(2500);quest::summonitem(2008);}
if ($itemcount{32638}=4){quest::say("Excellent! This is enough to make a fine tunic!");quest::exp(2500);quest::summonitem(2004);}
}

I havent finished my multiple stage quest, but I followed the guide in the wiki on here, but I still have the problem with the items.

John Adams
08-07-2007, 12:27 PM
Search the forums here for the plugin called "check_handin.pl". I am not sure when the emulator started using this method to check for handins, but the documentation is severly lacking in that area - the question has come up a lot lately.

The perl script itself should be in the folder named "plugins" from the CVS, but in case you can't find it:

# plugin::check_handin($item1 => #required_amount,...);
# autoreturns extra unused items on success
sub check_handin {
my $hashref = shift;
my %required = @_;
foreach my $req (keys %required) {
if ((!defined $hashref->{$req}) || ($hashref->{$req} != $required{$req})) {
return(0);
}
}
foreach my $req (keys %required) {
delete $hashref->{$req};
}
return 1;
}

sub return_items {
my $hashref = shift;
foreach my $k (keys(%{$hashref})) {
next if($k == 0);
my $r;
for($r = 0; $r < $hashref->{$k}; $r++) {
quest::summonitem($k);
}
delete $hashref->{$k};
}
}

1;

To use it, here's an example (one of my personal favorite quest NPCs - Schmendrik!):
sub EVENT_ITEM {
# 28044 : Lord Bergurgle's Crown
if (plugin::check_handin(\%itemcount,28044=>1)) {
quest::emote("shoves the crown into a scorch marked leather satchel and cackles uncontrollably as madness twists his features and flames dance in his eyes. 'You, $name, have reduced the Riptides into chaos! Without a king to keep them in control they will ravage the settlements surrounding this lake! After the slaughter I shall return and easily burn the remainder of the villages and fishing shanties to the ground! None shall escape the fires of the Tyrant!!'");
quest::summonitem(28045); # 28045 Oil of Fennin Ro
quest::spawn2(51138,0,0,111,3627.3,51,192.4);

#my $entid=quest::unique_spawn(51138,0,0,111,3627.3,51 ,192.4); # Natasha Whitewater, spawns in the hut nearby (loc to be adjusted)
#my $mob=$entity_list->GetMobID($entid);
#my $mobnpc=$mob->CastToNPC();
#$mobnpc->AddToHateList($npc,1); # she attacks Shmendrik
}

plugin::return_items(\%itemcount); # return unused items
}

There are plenty of quests in the CVS that use this method, and I am pretty sure it'll handle multiple handins just as easily as one.

Darkonig
08-07-2007, 02:38 PM
However, in your original post, the problems are because in the first example you used = instead of ==, resulting in assignment instead of comparison. In the second example you were assigning to a hash instead of checking it for existence and then testing the value.

if ($item1==5014) {
quest::say("Ggrrr, I didn't need your help...");
quest::exp(1000);
}

if (defined($itemcount{32638}) && $itemcount{32638} == 1) {
quest::say("Excellent! This is enough to make a fine pair of gloves.");
quest::exp(2500);
quest::summonitem(2010);
}


Using the plugins is another option depending on what you are trying to accomplish. If you are planning to use the plugins, make sure you have them in the correct place in your server directory.

sklead
08-09-2007, 07:25 AM
Ok, I got that to work, so nobody can take shortcuts through quests now :P

Now I have another problem with turn-ins...I have a series of quests where the first person you talk to hands out items based on class and gives you your quest. The other people in the series will only talk to you if you hand in one of the items, so there are multiple lines that get the same response, then 1 line that gets a different response. However, the NPC only replies to the hail and keyword I have set, any item turn-ins result in the NPC having a nice lunch.

This is just 1 of them, but if this problem is solved, the rest will work too:

sub EVENT_SAY{
if ($text=~/hail/i){quest::say("Begone scum!");}
if ($text=~/assignments/i){quest::say("Lord Nadrah continues to disregard our warnings, so we offer him one last chance. Slay his mistress and bring me her signet ring as proof. Perhaps that will teach him a lesson!");}
}
sub EVENT_ITEM{
if ($item1==1359){quest::say("Hmm, so you are the one who is moving through our ranks so quickly. Well, now you're an Agent, you also have more [assignments]!");quest::summonitem(1359);}
}
if ($item1==3617){quest::say("Hmm, so you are the one who is moving through our ranks so quickly. Well, now you're an Agent, you also have more [assignments]!");quest::summonitem(3617);}
}
if ($item1==5217){quest::say("Hmm, so you are the one who is moving through our ranks so quickly. Well, now you're an Agent, you also have more [assignments]!");quest::summonitem(5217);}
}
if ($item1==2563){quest::say("Hmm, so you are the one who is moving through our ranks so quickly. Well, now you're an Agent, you also have more [assignments]!");quest::summonitem(2563);}
}
if ($item1==5325){quest::say("Hmm, so you are the one who is moving through our ranks so quickly. Well, now you're an Agent, you also have more [assignments]!");quest::summonitem(5325);}
}
if ($item1==1868){quest::say("Hmm, so you are the one who is moving through our ranks so quickly. Well, now you're an Agent, you also have more [assignments]!");quest::summonitem(1868);}
}
if ($item1==1073){quest::say("Well now, you've truely done an Agent's work. I think you should speak to one of our undercover agents in Crow's Tavern near the lake.");quest::exp(40000);quest::faction(14,5);}
}

I've also tried it without putting a "}" between the lines, and nothing, as well as putting multiple SUB EVENT_ITEM things.

Darkonig
08-09-2007, 12:02 PM
This example has an extra } for each if statement which ultimately results in the subroutine not compiling. The result of this is that the npc will quietly eat the items. You may find it easier to follow and maintain if you don't try to do everything on one line.


You have:
if ($item1==1359){quest::say("Hmm, so you are the one who is moving through our ranks so quickly. Well, now you're an Agent, you also have more [assignments]!");quest::summonitem(1359);}
}

Easier to read (and without the extra } )
if ($item1==1359) {
quest::say("Hmm, so you are the one who is moving through our ranks so quickly. Well, now you're an Agent, you also have more [assignments]!");
quest::summonitem(1359);
}

sklead
08-09-2007, 12:56 PM
Ok, so I've changed it to look like this:

sub EVENT_SAY{
if ($text=~/hail/i){quest::say("Begone scum!");}
if ($text=~/assignments/i){quest::say("Lord Nadrah continues to disregard our warnings, so we offer him one last chance. Slay his mistress and bring me her signet ring as proof. Perhaps that will teach him a lesson!");}
}
sub EVENT_ITEM{
if ($item1==1359){quest::say("Hmm, so you are the one who is moving through our ranks so quickly. Well, now you're an Agent, you also have more [assignments]!");quest::summonitem(1359);
}
if ($item1==3617){quest::say("Hmm, so you are the one who is moving through our ranks so quickly. Well, now you're an Agent, you also have more [assignments]!");quest::summonitem(3617);
}
if ($item1==5217){quest::say("Hmm, so you are the one who is moving through our ranks so quickly. Well, now you're an Agent, you also have more [assignments]!");quest::summonitem(5217);
}
if ($item1==2563){quest::say("Hmm, so you are the one who is moving through our ranks so quickly. Well, now you're an Agent, you also have more [assignments]!");quest::summonitem(2563);
}
if ($item1==5325){quest::say("Hmm, so you are the one who is moving through our ranks so quickly. Well, now you're an Agent, you also have more [assignments]!");quest::summonitem(5325);
}
if ($item1==1868){quest::say("Hmm, so you are the one who is moving through our ranks so quickly. Well, now you're an Agent, you also have more [assignments]!");quest::summonitem(1868);
}
if ($item1==1073){quest::say("Well now, you've truely done an Agent's work. I think you should speak to one of our undercover agents in Crow's Tavern near the lake.");quest::exp(40000);quest::faction(14,5);
}

I haven't gotten a chance to test it, but if it works, thanks in advance :)

John Adams
08-10-2007, 01:45 AM
If you used the check_handins plugin I mentioned, nothing would get eaten.

Darkonig
08-10-2007, 08:07 AM
Even using check_handin plugin would have eaten the stuff if the subroutine has syntax errors.

The operation of the check_handin routine is a little inconsistent tho.

If you hand in what is needed along with something else it eats what was needed and ignores the rest, acknowledging that it got what it wanted.

If you hand it more of what's needed than it wants, whether or not you also hand anything else, it does not eat anything does not acknowledge it got what it wanted.

Either way, it only returns the items it didn't want or need if you call the return_items plugin at the end.

I would be quicker to use it if check_handin were coded as:

sub check_handin {
my $hashref = shift;
my %required = @_;
foreach my $req (keys %required) {
if ((!defined $hashref->{$req}) || ($hashref->{$req} < $required{$req})) {
return(0);
}
}
foreach my $req (keys %required) {
if ($required{$req} < $hashref->{$req}) {
$hashref->{$req} -= $required{$req};
} else {
delete $hashref->{$req};
}
}
return 1;
}

This would make it still accept if you gave too many of an item and return the excess of that item as well as anything else that was given and not needed.
As to the potential to exploit of using a negative quantity required, the person coding the quest could just summon it directly if they wanted to.