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 06-27-2017, 09:00 PM
Eealer
Fire Beetle
 
Join Date: Jul 2016
Location: Alberta, Canada
Posts: 29
Default NPC Script - only casting 1 spell of many

Hello again,

Is there some way that I can make my NPC cast a series of spells without using selfcast? I finally got "CastSpell" to work but in the section of the code I am testing, the NPC will only cast the first spell and then stop. Does anyone have any suggestions for how I can make it continue casting all of the spells in its cast list?

Code:
sub EVENT_SAY
{
	my $Buff = quest::saylink("Buffs", 1);
	my $heal = quest::saylink("Healing", 1);


		if($text=~/Hail/i)
		{
			$client->Message(315, "Hello, $name. Do you need some $Buff? Or maybe you're in need of some $heal?'");
		}
		
		if($text=~/Healing/i)
		{
			$npc->CastSpell(13);
			$client->Message(315, "You have been healed, $name");
		}

		if($text=~/Buffs/i) 
		{			

				
				if ($ulevel >= "61") 
				{
					$npc->CastSpell(5257, $userid);
					$npc->CastSpell(5258, $userid);
					$npc->CastSpell(5261, $userid);
					$npc->CastSpell(60, $userid);
					$npc->CastSpell(61, $userid);
					$npc->CastSpell(62, $userid);
					$npc->CastSpell(63, $userid);
					$npc->CastSpell(64, $userid);
					$client->Message(315, "It's Dangerous to adventure alone, Take this and stay safe");
				}
				if (($ulevel >= "47") && ($ulevel < "61")) 
				{
					$npc->CastSpell(3467, $userid);
					$npc->CastSpell(3472, $userid);
					$npc->CastSpell(4091, $userid);
					$npc->CastSpell(3469, $userid);
					$npc->CastSpell(60, $userid);
					$npc->CastSpell(61, $userid);
					$npc->CastSpell(62, $userid);
					$npc->CastSpell(63, $userid);
					$npc->CastSpell(64, $userid);
					$client->Message(315, "It's Dangerous to adventure alone, Take this and stay safe");
				}
				if ($ulevel == "46") 
				{
					$npc->CastSpell(3467, $userid);
					$npc->CastSpell(3472, $userid);
					$npc->CastSpell(4091, $userid);
					$npc->CastSpell(1548, $userid);
					$npc->CastSpell(60, $userid);
					$npc->CastSpell(61, $userid);
					$npc->CastSpell(62, $userid);
					$npc->CastSpell(63, $userid);
					$npc->CastSpell(64, $userid);
					$client->Message(315, "It's Dangerous to adventure alone, Take this and stay safe");
				}
				if ($ulevel == "45") 
				{
					$npc->CastSpell(1447, $userid);
					$npc->CastSpell(3576, $userid);
					$npc->CastSpell(4090, $userid);
					$npc->CastSpell(1548, $userid);
					$npc->CastSpell(60, $userid);
					$npc->CastSpell(61, $userid);
					$npc->CastSpell(62, $userid);
					$npc->CastSpell(63, $userid);
					$npc->CastSpell(64, $userid);
					$client->Message(315, "It's Dangerous to adventure alone, Take this and stay safe");
				}
				if ($ulevel >= "43") 
				{
					$npc->CastSpell(3692, $userid);
					$npc->CastSpell(3576, $userid);
					$npc->CastSpell(4090, $userid);
					$npc->CastSpell(1548, $userid);
					$npc->CastSpell(60, $userid);
					$npc->CastSpell(61, $userid);
					$npc->CastSpell(62, $userid);
					$npc->CastSpell(63, $userid);
					$npc->CastSpell(64, $userid);
					$client->Message(315, "It's Dangerous to adventure alone, Take this and stay safe");
				}
				if ($ulevel <= "42") 
				{
					$npc->CastSpell(3692, $userid);
					$npc->CastSpell(3576, $userid);
					$npc->CastSpell(4089, $userid);
					$npc->CastSpell(63, $userid);
					$npc->CastSpell(64, $userid);
					$npc->CastSpell(61, $userid);
					$npc->CastSpell(60, $userid);
					$npc->CastSpell(62, $userid);
					$client->Message(315, "It's Dangerous to adventure alone, Take this and stay safe");
				}
			}
		}
Reply With Quote
  #2  
Old 06-27-2017, 09:07 PM
ghanja's Avatar
ghanja
Dragon
 
Join Date: Aug 2012
Location: Hershey, PA
Posts: 499
Default

Replace the CastSpell's

Code:
$npc->SpellFinished (xxx, $client);
Reply With Quote
  #3  
Old 06-27-2017, 09:10 PM
Eealer
Fire Beetle
 
Join Date: Jul 2016
Location: Alberta, Canada
Posts: 29
Default

Quote:
Originally Posted by ghanja View Post
Replace the CastSpell's

Code:
$npc->SpellFinished (xxx, $client);
I tried doing that on the section I am testing and the NPC looks at me and doesnt do anything. I ran the quest errors and I get this message:
"spell_target is not of the type Mob" and specifies the line I changed
Reply With Quote
  #4  
Old 06-27-2017, 09:54 PM
ghanja's Avatar
ghanja
Dragon
 
Join Date: Aug 2012
Location: Hershey, PA
Posts: 499
Default

Sounds like you didn't replace $userid with $client?

As noted in the remarks within the code, I would probably have used a hash, but I didn't want the revision to deviate too much from your original.
Code:
## I would have made a hash for the spells and their corresponding minimum levels but keeping it relatively like the old
## so too much isn't change all at once

sub EVENT_SAY {
	if($text=~/Hail/i) {
		$client->Message(315, "Hello, $name. Do you need some [".quest::saylink("Buffs", 1)."? Or maybe you're in need of some [".quest::saylink("Healing", 1)."?'");
	}
	elsif($text=~/Healing/i) {
		$npc->SpellFinished(13, $client);
		$client->Message(315, "You have been healed, $name");
	}
	elsif($text=~/Buffs/i) {			
		$npc->SpellFinished(60, $client);
		$npc->SpellFinished(61, $client);
		$npc->SpellFinished(62, $client);
		$npc->SpellFinished(63, $client);
		$npc->SpellFinished(64, $client);
		if ($ulevel >= "61") {
			$npc->SpellFinished(5257, $client);
			$npc->SpellFinished(5258, $client);
			$npc->SpellFinished(5261, $client);
		}
		elsif (($ulevel >= "47") && ($ulevel < "61")) {
			$npc->SpellFinished(3467, $client);
			$npc->SpellFinished(3472, $client);
			$npc->SpellFinished(4091, $client);
			$npc->SpellFinished(3469, $client);
		}
		elsif ($ulevel == "46") {
			$npc->SpellFinished(3467, $client);
			$npc->SpellFinished(3472, $client);
			$npc->SpellFinished(4091, $client);
			$npc->SpellFinished(1548, $client);
		}
		elsif ($ulevel == "45") {
			$npc->SpellFinished(1447, $client);
			$npc->SpellFinished(3576, $client);
			$npc->SpellFinished(4090, $client);
			$npc->SpellFinished(1548, $client);
		}
		elsif ($ulevel >= "43") {
			$npc->SpellFinished(3692, $client);
			$npc->SpellFinished(3576, $client);
			$npc->SpellFinished(4090, $client);
			$npc->SpellFinished(1548, $client);
		}
		elsif ($ulevel <= "42") {
			$npc->SpellFinished(3692, $client);
			$npc->SpellFinished(3576, $client);
			$npc->SpellFinished(4089, $client);
		}
		$client->Message(315, "It's Dangerous to adventure alone, Take this and stay safe");
	}
}
Reply With Quote
  #5  
Old 06-27-2017, 09:58 PM
Eealer
Fire Beetle
 
Join Date: Jul 2016
Location: Alberta, Canada
Posts: 29
Default

Thank you ghanja!!

I had replaced the $userid with $client and that was when I had gotten that error. What i had not done was replace every line of $npc->CastSpell with $npc->SpellFinished

Thank you again for your help - it works just the way I want it to!
Reply With Quote
  #6  
Old 06-27-2017, 10:15 PM
ghanja's Avatar
ghanja
Dragon
 
Join Date: Aug 2012
Location: Hershey, PA
Posts: 499
Default

Code:
## I would have made a hash for the spells and their corresponding minimum levels but keeping it relatively like the old
## so too much isn't change all at once

%SpellsHash = (
	"first"		=>	[[1  .. 42]	, [60, 61, 62, 63, 64, 3692, 3576, 4089]],
	"second"	=>	[[43 .. 44]	, [60, 61, 62, 63, 64, 3692, 3576, 4090, 1548]],
	"third"		=>	[[45]		, [60, 61, 62, 63, 64, 1447, 3576, 4090, 1548]],
	"fourth"	=>	[[46]		, [60, 61, 62, 63, 64, 3467, 3472, 4091, 1548]],
	"fifth"		=>	[[47 .. 60]	, [60, 61, 62, 63, 64, 3467, 3472, 4091, 3469]],
	"sixth"		=>	[[61 .. 90]	, [60, 61, 62, 63, 64, 5257, 5258, 5261]],
)
	
sub EVENT_SAY {
	my $castedspells = 0;
	if($text=~/Hail/i) {
		plugin::Whisper("Hello, $name. Do you need some [".quest::saylink("Buffs", 1)."? Or maybe you're in need of some [".quest::saylink("Healing", 1)."?'");
	}
	elsif($text=~/Healing/i) {
		$npc->SpellFinished(13, $client);
		plugin::Whisper ("You have been healed, $name");
	}
	elsif($text=~/Buffs/i) {
		foreach my $key (keys %SpellsHash) {
			if ($ulevel ~~ @{$SpellsHash{$key}[0]}) {
				$castedspells = 1;
				foreach my $spelltocast (@{$SpellsHash{$key}[1]}) {
					$npc->SpellFinished ($spelltocast, $client);
				}
				$castedspells = 1;
				$client->Message(315, "It's Dangerous to adventure alone, Take this and stay safe");
			}	  
        }
		if (!$castedspells) { $client->Message(315, "I have no buffs to give to your gimpy ass!"); }
	}
}
I didn't check this for syntax and haven't been Perl'ing for awhile and, not my day job so, it may barf, I dunno.
Reply With Quote
  #7  
Old 06-29-2017, 12:25 AM
ghanja's Avatar
ghanja
Dragon
 
Join Date: Aug 2012
Location: Hershey, PA
Posts: 499
Default

Was a little bored and I can't say that I've ever (or at least it's been awhile) seen a script explained in a forum post. Either way, perhaps it will be useful to the OP or someone. I'm by far the best teacher, in fact perhaps not even mediocre, but, offering what I have.

Code:
## Perl Hash of Array (of Arrays)
## There is a key and value to every hash, in the below hash the value is are arrays (ordered list of scalar values)
## The words (eg. first, second, third, etc..) are "keys", which I've shown quoted but since they're all letters with no spaces, dashes, etc. didn't
## need to be, as the => treats the left operand to be treated as a string, but I've done so for sanity check
##
## Following the => is the "value" again in this case is an array of arrays.
## An element within an array begins at position 0, not 1 as most may figure.
##
## [1 .. 9] specifies that that array (the value(s) within the brackets] is a range, thus the array contains 1, 2, 3, 4, 5, 6, 7, 8, 9
##
## Format for usage (as coded):
## "key" => "value" that corresponds to that "key"

## "key" name isn't used (but can be depending upon the circumstance and creative programming method employed) in this script, thus is insignificant
## "value" (between the outer most brackets), is an array (because the brackets the values are in tells the code so)
## the first array (eg. [1 .. 42]) in this code (or rather usage of the hash) indicates the player levels to which the following spell ID's in the second
## array should be applied, thus if the player level is within this range, they will be given the spells corresponding with the ID numbers found in the
## second array.  Also deviation a little from the code posted above, is the addition of ranges for spell ID's 60 through 64, rather than specifying
## them individually (saves on typing and condensing visible code)

## I've formatted the hash a little bit differently in an attempt to perhaps make it a little easier on the eyes of those looking at it

%SpellsHash = (
	"first"		=>	[
						[1  .. 42], ## array containing a range of scalar values 1 to 42 corresponding to users within this range (due to use of it in code below)
						[60 .. 64, 3692, 3576, 4089] ## array containing scalar values corresponding to the spell ID's that will be casted
					],
	"second"	=>	[
						[43 .. 44],  ## same deal here but for a different range (notice none of the ranges should overlap in "level")
						[60 .. 64, 3692, 3576, 4090, 1548]  ## same deal here as well but only a little variance to the spell ID's
					],
	"third"		=>	[
						[45], ## not a range however even one scalar value can be an "array" because we've declared/use it as such
						[60 .. 64, 1447, 3576, 4090, 1548]
					],
	"fourth"	=>	[
						[46], 
						[60 .. 64, 3467, 3472, 4091, 1548]
					],
	"fifth"		=>	[
						[47 .. 60],
						[60 .. 64, 3467, 3472, 4091, 3469]
					],
	"sixth"		=>	[
						[61 .. 90],
						[60 .. 64, 5257, 5258, 5261]
					],
);
	
sub EVENT_SAY {
	my $castedspells = 0;  ## setting $castedspells to 0 (false) as we'll want to know if any were later down the line
	if($text=~/Hail/i) {
		plugin::Whisper("Hello, $name. Do you need some [".quest::saylink("Buffs", 1)."? Or maybe you're in need of some [".quest::saylink("Healing", 1)."?'");
	}
	elsif($text=~/Healing/i) {
		$npc->SpellFinished(13, $client);
		plugin::Whisper ("You have been healed, $name");
	}
	elsif($text=~/Buffs/i) {
		## let's iterate through all the keys of the hash one by one, assigning the key name to local (through use of "my") $key
		## perhaps explaining the foreach a bit would be best:
		## foreach = iterate through a list found within the parenthesis executing code found within its curly brackets with each iteration
		## (keys %SpellsHash) = keys when used with the hash reference will return a list of a hash's keys (as mentioned above in this case is:
		## first, second, third, fourth, etc.) - but not in that order as hashes are unordered, we could sort them but I see no value in doing so
		## foreach my $key = place the list element currently being iterated on into $key (keeping it local due to "my") 
		foreach my $key (keys %SpellsHash) {
			## @{$SpellsHash{$key}[0]}
			## I'll try to break the above line down
			## @{ = dereference [the array]
			##   $SpellsHash  = using $ rather than % as we're dealing with a single scalar rather than the entire Hash itself
			##              {$key}  = referencing which key-value pair we want within the hash, as said above $key now contains the current
			##                        element from the list of keys we made above in the foreach line 
			##                    [0] = further referencing the first array element (eg. [1  .. 42] )
			##                       } = enclosing the dereference
			##
			## I suppose another way to look at it is
			## @ {$SpellsHash{"first"}[0]}
			##
			## Anyway, lets assume the first iteration was  [1 .. 42] which is an array consisting of all values between 1 and 42 (i.e. range of 1 through 42)
			## Using smart matching (the double tilde), we're saying "if the users level is within the range of 1 and 42 then do"
			if ($ulevel ~~ @{$SpellsHash{$key}[0]}) {
				## changing $castedspells to 1 (true) as we'll be looking to see if we did or not later down the line
				$castedspells = 1;
				## Oh yay this shit again
				## Everything was explained above (as best as I could) however we're using array element 1, which is the array containing the spell ID's
				## in the Hash above
				## So we're going to iterate through the list created by the scalars within that array, assigning the current iterated scalar to $spelltocast
				## which assuming the above user level of 1 through 42, are spell ID's 60 .. 64, 3692, 3576 and 4089
				foreach my $spelltocast (@{$SpellsHash{$key}[1]}) {
					$npc->SpellFinished ($spelltocast, $client);
				}
				$client->Message(315, "It's Dangerous to adventure alone, Take this and stay safe");
			}	  
        }
		## we're still in the "if $text equalled Hail" code block, but if not $castedspells then give message
		## which should only happen if their user level was not found to be specified in the hash above
		## I suppose a better way to show it would have been:
		## if ($castedspells == 0), but habit I guess
		if (!$castedspells) { $client->Message(315, "I have no buffs to give to your gimpy ass!"); }
	}
}
Copy/paste to something like Notepad++, as I doubt the formatting will be precise in the code blocks when viewing the post.

People have their own style and some will even argue "right" or "wrong" regarding it.

For instance:

Code:
sub EVENT_NONEXISTENT
{
	if (not $proper)
	{
		## do stuff
	} else {
		## do this stuff instead
	}
}
Just looks off (to me). I like to associate the opening curly with the line that calls it, then using the closing curly with the first letter of that same code (that called it).

Code:
sub EVENT_NONEXISTENT {
	if (not $proper) {
		## do stuff
	} 
	else {
		## do this stuff instead
	}
}
Formatting has been long debated on many facets (such as the above, indenting, etc.). Really just stick with what you're content with, especially if you don't think anyone else will ever see it.

Anyway, yeah, there ya go. Syntax has been checked on the above, but, nothing more.
Reply With Quote
  #8  
Old 06-29-2017, 12:39 AM
Eealer
Fire Beetle
 
Join Date: Jul 2016
Location: Alberta, Canada
Posts: 29
Default

Quote:
Originally Posted by ghanja View Post
Was a little bored and I can't say that I've ever (or at least it's been awhile) seen a script explained in a forum post. Either way, perhaps it will be useful to the OP or someone. I'm by far the best teacher, in fact perhaps not even mediocre, but, offering what I have.

Code:
## Perl Hash of Array (of Arrays)
## There is a key and value to every hash, in the below hash the value is are arrays (ordered list of scalar values)
## The words (eg. first, second, third, etc..) are "keys", which I've shown quoted but since they're all letters with no spaces, dashes, etc. didn't
## need to be, as the => treats the left operand to be treated as a string, but I've done so for sanity check
##
## Following the => is the "value" again in this case is an array of arrays.
## An element within an array begins at position 0, not 1 as most may figure.
##
## [1 .. 9] specifies that that array (the value(s) within the brackets] is a range, thus the array contains 1, 2, 3, 4, 5, 6, 7, 8, 9
##
## Format for usage (as coded):
## "key" => "value" that corresponds to that "key"

## "key" name isn't used (but can be depending upon the circumstance and creative programming method employed) in this script, thus is insignificant
## "value" (between the outer most brackets), is an array (because the brackets the values are in tells the code so)
## the first array (eg. [1 .. 42]) in this code (or rather usage of the hash) indicates the player levels to which the following spell ID's in the second
## array should be applied, thus if the player level is within this range, they will be given the spells corresponding with the ID numbers found in the
## second array.  Also deviation a little from the code posted above, is the addition of ranges for spell ID's 60 through 64, rather than specifying
## them individually (saves on typing and condensing visible code)

## I've formatted the hash a little bit differently in an attempt to perhaps make it a little easier on the eyes of those looking at it

%SpellsHash = (
	"first"		=>	[
						[1  .. 42], ## array containing a range of scalar values 1 to 42 corresponding to users within this range (due to use of it in code below)
						[60 .. 64, 3692, 3576, 4089] ## array containing scalar values corresponding to the spell ID's that will be casted
					],
	"second"	=>	[
						[43 .. 44],  ## same deal here but for a different range (notice none of the ranges should overlap in "level")
						[60 .. 64, 3692, 3576, 4090, 1548]  ## same deal here as well but only a little variance to the spell ID's
					],
	"third"		=>	[
						[45], ## not a range however even one scalar value can be an "array" because we've declared/use it as such
						[60 .. 64, 1447, 3576, 4090, 1548]
					],
	"fourth"	=>	[
						[46], 
						[60 .. 64, 3467, 3472, 4091, 1548]
					],
	"fifth"		=>	[
						[47 .. 60],
						[60 .. 64, 3467, 3472, 4091, 3469]
					],
	"sixth"		=>	[
						[61 .. 90],
						[60 .. 64, 5257, 5258, 5261]
					],
);
	
sub EVENT_SAY {
	my $castedspells = 0;  ## setting $castedspells to 0 (false) as we'll want to know if any were later down the line
	if($text=~/Hail/i) {
		plugin::Whisper("Hello, $name. Do you need some [".quest::saylink("Buffs", 1)."? Or maybe you're in need of some [".quest::saylink("Healing", 1)."?'");
	}
	elsif($text=~/Healing/i) {
		$npc->SpellFinished(13, $client);
		plugin::Whisper ("You have been healed, $name");
	}
	elsif($text=~/Buffs/i) {
		## let's iterate through all the keys of the hash one by one, assigning the key name to local (through use of "my") $key
		## perhaps explaining the foreach a bit would be best:
		## foreach = iterate through a list found within the parenthesis executing code found within its curly brackets with each iteration
		## (keys %SpellsHash) = keys when used with the hash reference will return a list of a hash's keys (as mentioned above in this case is:
		## first, second, third, fourth, etc.) - but not in that order as hashes are unordered, we could sort them but I see no value in doing so
		## foreach my $key = place the list element currently being iterated on into $key (keeping it local due to "my") 
		foreach my $key (keys %SpellsHash) {
			## @{$SpellsHash{$key}[0]}
			## I'll try to break the above line down
			## @{ = dereference [the array]
			##   $SpellsHash  = using $ rather than % as we're dealing with a single scalar rather than the entire Hash itself
			##              {$key}  = referencing which key-value pair we want within the hash, as said above $key now contains the current
			##                        element from the list of keys we made above in the foreach line 
			##                    [0] = further referencing the first array element (eg. [1  .. 42] )
			##                       } = enclosing the dereference
			##
			## I suppose another way to look at it is
			## @ {$SpellsHash{"first"}[0]}
			##
			## Anyway, lets assume the first iteration was  [1 .. 42] which is an array consisting of all values between 1 and 42 (i.e. range of 1 through 42)
			## Using smart matching (the double tilde), we're saying "if the users level is within the range of 1 and 42 then do"
			if ($ulevel ~~ @{$SpellsHash{$key}[0]}) {
				## changing $castedspells to 1 (true) as we'll be looking to see if we did or not later down the line
				$castedspells = 1;
				## Oh yay this shit again
				## Everything was explained above (as best as I could) however we're using array element 1, which is the array containing the spell ID's
				## in the Hash above
				## So we're going to iterate through the list created by the scalars within that array, assigning the current iterated scalar to $spelltocast
				## which assuming the above user level of 1 through 42, are spell ID's 60 .. 64, 3692, 3576 and 4089
				foreach my $spelltocast (@{$SpellsHash{$key}[1]}) {
					$npc->SpellFinished ($spelltocast, $client);
				}
				$client->Message(315, "It's Dangerous to adventure alone, Take this and stay safe");
			}	  
        }
		## we're still in the "if $text equalled Hail" code block, but if not $castedspells then give message
		## which should only happen if their user level was not found to be specified in the hash above
		## I suppose a better way to show it would have been:
		## if ($castedspells == 0), but habit I guess
		if (!$castedspells) { $client->Message(315, "I have no buffs to give to your gimpy ass!"); }
	}
}
Copy/paste to something like Notepad++, as I doubt the formatting will be precise in the code blocks when viewing the post.

People have their own style and some will even argue "right" or "wrong" regarding it.

For instance:

Code:
sub EVENT_NONEXISTENT
{
	if (not $proper)
	{
		## do stuff
	} else {
		## do this stuff instead
	}
}
Just looks off (to me). I like to associate the opening curly with the line that calls it, then using the closing curly with the first letter of that same code (that called it).

Code:
sub EVENT_NONEXISTENT {
	if (not $proper) {
		## do stuff
	} 
	else {
		## do this stuff instead
	}
}
Formatting has been long debated on many facets (such as the above, indenting, etc.). Really just stick with what you're content with, especially if you don't think anyone else will ever see it.

Anyway, yeah, there ya go. Syntax has been checked on the above, but, nothing more.
Thank you for this ghanja! That should help me understand how to use the arrays and the hash's (I think it even made me understand WTH a Hash is)

I really appreciate the help that you have provided me cause I was thinking that either my code was broken or I was broken and I was really hoping it was just the code. (Yours works perfect, it was my code that was broken)
Reply With Quote
Reply

Thread Tools
Display Modes

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 11:39 AM.


 

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