Loading...   

[Show Table of Contents]


This page is the master reference for all Perl Plugins

§Installing DBD::Mysql

  • Since a lot of plugins require database connection abilities for Perl, see Installing Perl DBI and other Modules
    • Your MySQL database connection is created with plugins\MySQL.pl with the sub LoadMysql - this automatically reads the eqemu_config.xml for its database credentials
    • It is recommended for best performance and speed to manually define your MySQL credentials under plugins\MySQL.pl by using LoadMysql_Fast (Rename to LoadMysql) and the old LoadMysql get renamed to LoadMysql_Old - If this is too confusing for you, then do not try it

§Extensive Plugin Explanation Pages:


File Plugin & Description Example
anim.pl
§plugin::DoAnim("salute"); 

Description: Will take in an easy to remember name or string and take care of the conversion to ID in the scripting process.

See DoAnim Plugin String Reference

sub EVENT_SAY{
	if($text=~/Hail/i){
		quest::say("Well hello there ol' lad! How are yeh today!");
		plugin::DoAnim("wave");
	}
	if($text=~/repond to text above/i){
		quest::say("Hah! If you weren't such a kidder $name I'd call yeh a fool!");
		plugin::DoAnim("laugh");
	}
}
anim.pl
§plugin::SetAnim("animation") see below for SetAnim options (stand/sit/duck/dead/kneel)


Description: Will take in an easy to remember name or string and take care of the conversion to ID in the scripting process

sub EVENT_SPAWN{
	quest::settimer("Die",1); 
	quest::set_proximity($x - 5, $x + 5, $y - 5, $y + 5, $z - 4, $z + 4);
}

sub EVENT_TIMER {
	if($timer eq "Die") {
		quest::stoptimer("Die");
		plugin::SetAnim("dead");
	}
}

sub EVENT_ENTER {
	$client->Message(15, "The Iksar appears to be a test subject instead of using their own race, the Shissar.");
}
check_hastitem.pl
§plugin::check_hasitem($client, itemid)

Checks for items in just about every place for a player

  • #Checks to see if player has item
  • #Check main inventory and cursor
  • #Check main inventory's and cursor's containers
  • #Check bank slots
  • #Check bank's containers
  • #Check shared bank
  • #Check shared bank's containers
  • #Check corpses
sub EVENT_SAY{
	if($text=~/hail/i){
		if(plugin::check_hasitem($client, 1001)){
			quest::say("WOW! Is that a cloth cap you have! That's amazing!");
		}
	}
}
check_handin.pl
  • §plugin::check_handin
  • §plugin::return_items
sub EVENT_ITEM {
	if(plugin::check_handin(\%itemcount, 13245 => 1)) {
		plugin::DiaWind("Ye've proven yerself to be a cut above the rest and aided yer fellow warriors, no matter how worthless they were. Ye may take this. It was found in the snow by one of our foraging parties. I hope it can be of use to a warrior like yerself.");
                quest::ding();
		quest::exp(125);
		quest::givecash(3,0,0,0);
		quest::summonitem(quest::ChooseRandom(2012,17001,10004,10017,1038,10016,13877,2135,7007,8008,10009,13007,5014,13003)); # random low level items
		quest::faction(213,10); # 213 : Faction Merchant's of Halas
		quest::faction(294,10); # 294 : Faction Shaman of Justice
		quest::faction(311,10); # 311 : Faction Steel Warriors
		quest::faction(361,10); # 361 : Faction Wolves of the North
	}
    #do all other handins first with plugin, then let it do disciplines
	plugin::try_tome_handins(\%itemcount, $class, 'Warrior');
	plugin::return_items(\%itemcount);
}
guildmasters.pl
  • §plugin::try_tome_handins
    • looks through the items haded in for discipline tomes, processing them as we find them.
sub EVENT_ITEM {
	if(plugin::check_handin(\%itemcount, 13245 => 1)) {
		plugin::DiaWind("Ye've proven yerself to be a cut above the rest and aided yer fellow warriors, no matter how worthless they were. Ye may take this. It was found in the snow by one of our foraging parties. I hope it can be of use to a warrior like yerself.");
                quest::ding();
		quest::exp(125);
		quest::givecash(3,0,0,0);
		quest::summonitem(quest::ChooseRandom(2012,17001,10004,10017,1038,10016,13877,2135,7007,8008,10009,13007,5014,13003)); # random low level items
		quest::faction(213,10); # 213 : Faction Merchant's of Halas
		quest::faction(294,10); # 294 : Faction Shaman of Justice
		quest::faction(311,10); # 311 : Faction Steel Warriors
		quest::faction(361,10); # 361 : Faction Wolves of the North
	}
    #do all other handins first with plugin, then let it do disciplines
	plugin::try_tome_handins(\%itemcount, $class, 'Warrior');
	plugin::return_items(\%itemcount);
}
group_utility.pl
  • §@members = plugin::GetGroupMembers($client)
  • §plugin::MoveGroup(zoneid, x, y, z, h)
  • §plugin::MoveGroupInstance(zoneid, instanceid, x, y, z, h)
  • §plugin::CastOnGroup(SpellID, MaxDist=0, Client=$client);
  • §plugin::MessageGroup(color, message)
  • These methods should be mostly self-explanatory
illusion_tools.pl
  • §plugin::RandomFeatures(Mob);
  • §plugin::CloneAppearance(MobA, MobB, CloneName=false);
sub EVENT_SAY{
	if($text=~/random/i){ #::: Give the client random features, you can do this for $npc too
		plugin::RandomFeatures($client);
	}
	if($text=~/clone/i){ #::: Clone the player's appearance to the NPC that you initiate this with
		plugin::CloneAppearance($client, $npc);
	}
	if($text=~/nclo/i){ #::: Vise Versa, let's clone the NPC's appearance to the players
		plugin::CloneAppearance($npc, $client);
	}
}

§Random Features

§Clone Appearance

  • Order: Left to Right
    • 1 - Normal
    • 2 - Copy player to NPC - plugin::CloneAppearance($client, $npc);
    • 3 - Copy NPC to player - plugin::CloneAppearance($npc, $client);

Instances.pl
§plugin::SendToInstance("solo/guild/group/public", "Zone Short Name", Version, X, Y, Z, "Identifier", duration in seconds");

Description

Used to simplify the instancing process.

Also keeps track of the Zone ID via qglobals, so whatever NPC you use this on must have qglobals enabled!

  • Using a popup window response to send a character to an instance... (Player or NPC Script)
sub EVENT_POPUPRESPONSE{
	if($popupid == 150){ plugin::SendToInstance("public", "atiiki", 1, -916, -1089, -39, "EXP", 648000); }
}
  • Using it on clicking a door (Player Script):
sub EVENT_CLICKDOOR {
	if($instanceversion == 1) {
		if($doorid == 2) {
			plugin::SendToInstance("public", "stillmoonb", 1, 1347.1, 5356.6, 0.9, "public2", 680000);
		}
		if($doorid == 10) {
			plugin::SendToInstance("public", "stillmoonb", 1, 1340, 2488.1, 519.8, "public2", 680000);
		}
	}
}

 

Multiple_QGlobals.pl
§plugin::setmglobal(Name, Value, Options, Duration, Index#);

This serves as a system to store qglobals with multiple values stored in one record so the database is much more efficiently utilized.

For example you can use this to store multiple character flags that all belong to the character to maximize on qglobal table space. The value field in the quest_globals table can store up to 128 bytes or characters so you could potentially fit up to 100 indexes or values per qglobal with this system.

Speed: FAST (Memory)

In this example, I am storing a character setting that I have coded on the server side, it stores whether or not a player wants a camerashakes to occur on their character.

I store it in the first index:

sub EVENT_SAY{
	#::: Player Settings, Stored via a Multiple QGlobal :::#
	my @arg = split(' ', $text); #::: Let's split character messages into an array delimited by spaces so we can break out arguements
	if($text=~/#settings/i){
		$Set = -1;
		if(!$arg[1]){ 
			$client->Message(15, "#settings camerashake on/off - This setting affects certain situations where camerashake occurs"); 
		}
		elsif($arg[1] eq "camerashake"){ 
			if($arg[2] eq "on"){ 
				$Set = 0; 
			}
			elsif($arg[2] eq "off"){ 
				$Set = 1; 
			} 
			if($Set >= 0){ 
				plugin::setmglobal("CharSettings", $Set, 5, "F", 1); 
				$client->Message(15, $arg[1] . " set to " . $arg[2]); 
			} 
		}
	}
}
Multiple_QGlobals.pl
§plugin::readmglobal(Name, Index)

This will read the qglobal values from the multiple qglobals that you set. In this case we will use a running example of reading from the example of camerashake above

In this example I read the CharSettings qglobal that I set and if the value returns 1, it will return true and go through with the CameraEffect, simple:

sub EVENT_ENTERZONE{
	if($instanceversion == 1){
		quest::settimer("shake", 10);
	}
}

sub EVENT_TIMER{
	if($timer eq "shake"){
		if(plugin::readmglobal("CharSettings", 1) != 1){ $client->CameraEffect(plugin::RandomRange(1000, 2000), plugin::RandomRange(1, 4)); }
		if(plugin::RandomRange(1, 100) < 10){ $client->Message(15, "You feel as if the library is going to explode!"); }
		quest::stoptimer("shake"); 
		quest::settimer("shake", plugin::RandomRange(1, 30));
	}
}
spawn_utils.pl
  • §my $LoSDistance = plugin::GetMaxLoSDistFromHeading(Heading, [DistIncrements, MaxDist, Mob]);
  • §plugin::FaceBestHeading([MinLoSDist]);
  • §my $ShortestHeading = plugin::HeadingToShortestLoS([MaxDistToCheck=8]);
  • §my $NPCMoved = plugin::MoveAwayFromWall([MinLoSDist=5]);
  • §plugin::MoveToFirstBestZ();
  • §plugin::SpawnZone(X, Y, Z, Distance, Variance, Columns, Rows);
  • §my $ReverseHeading = plugin::GetReverseHeading([$mob]);
  • §my $Degrees = plugin::ConvertHeadingToDegrees(Heading);

 

This is used for populating zones from scratch

sub EVENT_SAY {

	my $SpawnZone = quest::saylink("Spawn Zone", 0, "Spawn the Zone");
	if ($status > 20)
	{
		if ($text =~/Hail/i)
		{
			quest::say("Are you ready to [ $SpawnZone ]?");
		}
		if ($text =~/Spawn Zone/i)
		{
			quest::say("Starting Zone Spawn");
			#Usage: plugin::SpawnZone(X, Y, Z, Distance, Variance, Columns, Rows);
			plugin::SpawnZone($x, $y, $z, 50, 20, 40, 40,
				264200,	# A_Blighted_Jin_Master
				264228,	# A_Cursed_Guktan
				264202,	# A_Cursed_Korta_Researcher
				264223,	# A_Dazzling_Oculus
				264220,	# A_Decaying_Yunta_Witchdoctor
				264221,	# A_Doomed_Yunta_Witchdoctor
				264217,	# A_Ghoulish_Dar_Warrior
				264212,	# A_Ghoulish_Darta_Knight
				264219,	# A_Miserable_Jinta_Phantasm
				264213,	# A_Witness_of_Hate_Bonecollector
				264216,	# A_Witness_of_Hate_Seer
				264226,	# A_Witness_of_Hate_assassin
				264214,	# A_Witness_of_Hate_knave
				264207,	# a_cursed_burrower
				264215,	# a_forlorn_Darta_soldier
				264218	# an_unsanctified_Korta_priest	
			);
			quest::say("Zone Spawn complete");
		}
	}
	else
	{
		quest::say("Sorry, I only speak with GMs");
	}

}
spawn_utils.pl
  • §plugin::moelib_spawn_block(npctypeid, fromx, tox, fromy, toy, space, zposition=20, heading=0, grid=0)
    • Spawns NPC's in a block
  • §plugin::moelib_spawn_block_center(npctypeid, centerx, centery, range, amount, zposition=20, heading=0, grid=0)
    • Spawns NPC's in a block around specified 'center' coordinate
  • §plugin::moelib_spawn_circle(npctypeid, centerx, centery, radius, amount, zposition=20, heading=0, grid=0)
    • Spawns NPC's in a circle
 
random_messages.pl
  • §plugin::RandomSay(chance(1-100), "message1","message2", etc..);
  • §plugin::RandomSay(chance(1-100), "message1","message2", etc..);
  • §plugin::RandomEmote(chance(1-100), "message1","message2", etc..);
  • §plugin::RandomGroupEmote(chance(1-100), "message1","message2", etc..);
  • §plugin::RandomCloseEmote(chance(1-100), "message1","message2", etc..);
 
text_formatting.pl
  • plugin::commify(12302302); Would output value 12,302,302
  • If you need an example for this, you need help
random_range
  • plugin::RandomRange(minvalue, maxvalue);
#::: NPC will spawn with a 20% change to yell 'YArghhhhh!'
sub EVENT_SPAWN{
	if(plugin::RandomRange(1, 100) < 20){
		quest::shout("YArghhhhh!");
	}
}
mob_utils.pl
  • §plugin::MobHealPercentage(Percent [1-100]);
  • §plugin::MobDamagePercentage(Percent [1-100]);
  • §plugin::MobHealPoints(Number);
  • §plugin::MobDamagePoints(Number);
  • §plugin::SpawnInPlace(NPCID To Spawn In Place, [1 = Don't depop what spawns in place]);
  • §plugin::SpawnInPlaceByEnt{(NPCID To Spawn In Place, [1 = Don't depop what spawns in place]);
  • §plugin::SpawnChest{(NPCID To Spawn In Place, [1 = Don't depop what spawns in place]);
    • This will spawn a chest within proximity with specified NPC ID
sub EVENT_SAY{
	if($text=~/mobhealpercent/i){
		plugin::MobHealPercentage(100);
		quest::say("I just healed 100%");
	}
	if($text=~/mobdamagepercent/i){
		plugin::MobDamagePercentage(30);
		quest::say("I just damaged 30%");
	}
	if($text=~/mobhealpoint/i){
		plugin::MobHealPoints(1000);
		quest::say("I just healed 1000 hitpoints");
	}
	if($text=~/spawninplace/i){
		quest::say("Spawning another NPC (Skeleton Pet) in place of me...");
		plugin::SpawnInPlace(628);
	}
	if($text=~/SpawnChest/i){
		quest::say("Spawning Chest in proximity");
		plugin::SpawnChest(39056);
	}
}
npc_tools.pl
  • §plugin::CountNPCTYPE($NPC_TYPE_ID);
    • Description: Will return the number of NPC's in the zone from NPC ID
  • §plugin::SetProx(X/Y Axis Range, Z Axis Range, [1 = Skeleton Reference proximity for debugging]);
    • Description: This will set the proximity of an NPC, with simply two arguments, 30 (x-y axis) and 30 (z axis)
    • Note, if you set the 3rd arguement of SetProx to 1, it will spawn skeletons that represent how truly big your proximity is
sub EVENT_SPAWN{
	plugin::SetProx(10, 40, 1);
}

sub EVENT_ENTER{
	plugin::MM("You have walked inside my proximity");
}

utility.pl
§plugin::AddLoot(amount, chance, @itemarray)
sub EVENT_SPAWN{
	plugin::AddLoot(1, 1200, 132064); # Drop 1 Minor Rainbow Crystal, 1:1200 drop
	plugin::AddLoot(1, 2750, 132065); # Drop 1 Lesser Rainbow Crystal, 1:2750 drop
	my @item_STONES = (10299, 10300, 10400, 112170); 			# Light Stones
	plugin::AddLoot(8, 1, @item_STONES); # Drop 8 from list, 1/1 (100%) Chance, from Array
}
utility.pl
§plugin::SEV(entity, variable_name, variable_value)

This is a shorthand way of setting an entity variable.

NOTE: Entity variables are EXTREMELY powerful! Know how to use them!

sub EVENT_SAY{
	if($text=~/hail/i){
		plugin::SEV($client, "you_said", $text);
		quest::say("Oh my god did you just say what you thought you said? ");
		$client->Message(15, quest::saylink("What did I just say", 1));
	}
	if($text=~/did I just say/i){
		quest::say("You just said '" . plugin::REV($client, "you_said") . "', crazy I know right?");
	}
}
utility.pl
§plugin::REV(entity, variable_name);

This is a shorthand way of reading an entity variable, it will return a value.

NOTE: Entity variables are EXTREMELY powerful! Know how to use them!

sub EVENT_SAY{
	if($text=~/hail/i){
		plugin::SEV($client, "you_said", $text);
		quest::say("Oh my god did you just say what you thought you said? ");
		$client->Message(15, quest::saylink("What did I just say", 1));
	}
	if($text=~/did I just say/i){
		quest::say("You just said '" . plugin::REV($client, "you_said") . "', crazy I know right?");
	}
}
utility.pl
§plugin::CheckDist(entity, distance);

A simple way to return the distance between the NPC initiating this plugin and the player, useful for all kinds of situations. Will return true if within distance, false if not.If you are not familiar with entites, they can be a client, npc, object, door etc.You have to utilize entity_list calls to get an entity object

The below example is checking the distance between a player and the NPC that has initiated the timer.

The NPC is getting the player from their name in the entity list because we grabbed the players name on proximity enter

sub EVENT_TIMER{
	if($timer eq "check_c_dist"){
		my $c = $c = $entity_list->GetClientByName(plugin::REV($npc, "c_name"));
		#::: Check to See if client is in distance
		# quest::say("CLIENT " . $c->GetCleanName());
		if(plugin::CheckDist($c, 50)){ quest::say("CLIENT IN DISTANCE"); 
			$nwp = plugin::REV($npc, "wp");
			if($nwp == 1){ $npc->MoveTo(1179, 3716, -21, 149, 1);   }
			if($nwp == 2){ $npc->MoveTo(947, 3398, -33, 150, 1);    }
			if($nwp == 3){ $npc->MoveTo(608, 2857, -34, 151, 1);    }
			if($nwp == 4){ $npc->MoveTo(-221, 2549, -35, 210, 1);   }
			if($nwp == 5){ $npc->MoveTo(-492, 2667, -16, 159, 1);   }
			if($nwp == 6){ quest::stoptimer($timer); }
			plugin::SEV($npc, "wp", ($nwp + 1));
			# quest::say("WAYPOINT " . $nwp);
		} else{ 
			# quest::say("CLIENT NOT IN DISTANCE"); 
		}
	}
}
utility.pl
§plugin::CheckDistBetween2Ents(entity1, entity2, distance);

A simple way to return the distance between two select entities, useful for all kinds of situations. Will return true if within distance, false if not. If you are not familiar with entites, they can be a client, npc, object, door etc.You have to utilize entity_list calls to get an entity object

sub EVENT_SAY{
	my $npc1 = $entity_list->GetNPCByNPCTypeID(10001);
	my $npc2 = $entity_list->GetNPCByNPCTypeID(10002);
	#::: Check to See if these NPC's are within distance
	if(plugin::CheckDistBetween2Ents($npc1, $npc2, 50)){ 
		quest::say("NPC's are in distance of 50"); 
		quest::say("NPC 1 is " . $npc1->GetCleanName()); 
		quest::say("NPC 2 is " . $npc2->GetCleanName()); 
	} else{ 
		quest::say("These NPC's are not in distance at all"); 
	}
}
Expeditions.pl
§plugin::InitInstanceQueue

This is an extensive mod. To get full details of this mod you need to go here The Expedition and Shared Tasks (Perl Version)  

 

sub EVENT_SAY{
    if($status > 200){ $ReqPlayer = 1; } else { $ReqPlayer = 4; }
    @AdvInfo = plugin::LoadExpeditionInfo2(); plugin::CheckForStaleInstances();
    if($AdvInfo[0] > 0){ plugin::DisplayInstanceQueue($AdvInfo[0]);  }
    else{
        plugin::InitInstanceQueue("Velketors Assignment", #Instance Identifier
            "Small Raid", #Description of Adventure (Ex: Group)
            24, #Number of Players
            707, #Task ID Association
            "Velketors Assignment", #Description of Adventure
            7200, #Duration Timer (Seconds)
            0, #Version
            "velketor", #ZoneSN
            -65, #Instance Destination X
            581, #Instance Destination Y
            -152, #Instance Destination Z
            191, #Instance Destination H
            50, #Required Average Level
            $ReqPlayer, #Minimum # of Players
            1, #Is Shared Task (0/1)
            86400, #Lockout Duration
            0, #:::  Boot on completion
            17, # X Compass Loc
            79, # Y Compass Loc
            3, # Z Compass Loc
        );
    }
}
client_messages.pl
§plugin::Autovtell("voicemessage");

Options: 

  • greet
  • battle
  • disagree
  • follow
  • greet
  • heal
  • help
  • laugh
  • part
  • retreat
  • stop
  • thanks

This is probably more annoying for players than anything because it over rides the default tell window. But this will send the player a voice tell message based on the a string parameter specified from the left

sub EVENT_SAY{
	#::: Example using a Barbarian Male
	if($text=~/hail/i){
		quest::say("Yargh!");
		plugin::Autovtell("greet");
	}
}

 

client_messages.pl
§plugin::Whisper("Message");

Whispers a message to the player

sub EVENT_SAY { 
	if($text=~/Hail/i)  { 
		plugin::Whisper("Hello, $name, I can " . quest::saylink("scribe", 1) . " spells and I can " . quest::saylink("unscribe", 1) . " spells, too."); 
	} 
}
client_messages.pl
§plugin::ClientSay("Message", "Message2", "Message3"); 

If Multiple arguments are supplied, it will return a random message from the list.
If any of the arguments is a number, it will parse that number as the color to use for the TextColor of the message

sub EVENT_SAY{
	if($text=~/hail/i){
		plugin::ClientSay("Hello $name, are you having a hard time figuring out where to gain experience? In this book next to me I have all of Norrath's secrets that I can help you with");
		plugin::ClientSay("How would you like me to show you around? " . quest::saylink("By Level", 1) . " - " . quest::saylink("By Expansion", 1));
		plugin::ClientSay("Would you like to take the tour again? " . quest::saylink("Take the Tour", 1));
	}
}
client_messages.pl
§plugin::MM("Message")

Will display a Marquee message on the screen

sub EVENT_SAY{
	if($text=~/hail/i){
		plugin::MM("Hello there " . $name . "!");
	}
}

sub EVENT_SAY{
	if($text=~/hail/i){
		plugin::MM("This is a super long message that says absolutely nothing but it is another example of using marquees");
	}
}

DiaWind.pl
§plugin::DiaWind("Window text");

Plugin for making use of popup windows

See The DiaWind Plugin

 

sub EVENT_SAY{
	if($text=~/hail/i){                
		plugin::DiaWind("Yawwnnn. Your name is {gold}$name~? Hrmm, I just can't {gold}remember anymore...~ {gray}I, I, I, ugh... what was it again...~ 
		Ah, yes strange one.  You wake me from my {lb}slumber~... wait what was it, {lb}who are you?~  I just want to {lb}remember~ [I can help you remember> +31+");
	}
	if($text=~/help you Remember/i){
		plugin::DiaWind("The dreams I {lb}used to have~, they were {y}wondeakkadiusrful~.  {lb}Dreams~ of {gold}mountains and skeletons~ and err... 
		fire I..I...{gray}I just don't remember~.  Have you ventured into the {gold}angels tower and slept in their wonderful beds~? 
		They are amazing but it has been ages since I was able to {lb}feel those beds~.  
		The {y}angels~ {r}banished me~ from the {lb} tower~ for my deeds, but alas, that is another {y}story~...
		Wait, I have a {y}wonderful idea~! {y}YES~!!! This idea is {lb}amazing~ and perhaps you would like to {lb}help~ me with it!!! [I will help you> +cheer+");
	}
	if($text=~/I will help/i){
		plugin::DiaWind("Yes... whoever you are, small being.  {lb}Sleep~ in each of those {lb}wonderful beds~ and fall into the dreams in which I try to remember.  
		Bring me back what you remember of the dreams and help {y}ME~ remember the days when I was able to sleep in those amazing beds, will yeh?  
		So what do you think?  {y}Are you willing to take on this~ {lb}task~? [I will take on this task for you> +shrug+");
	}
	if($text=~/I will take on this task/i){
		plugin::DiaWind("{y}Perfect~! Start now small one! I am going to try and sleep on this {gray}horrible bed~... +cheer+");
		quest::taskselector(190);
	}
}

Doors_Manip.pl This is a hooked mod, to see how to install and use. See Placing_Doors

MP3.pl
§plugin::U_MP3

This plugin utilizes a database full of the EverQuest sound files and their lengths to utilize sound looping and other features.

This is an extension of $client->PlayMP3 which can play both mp3/wav as well as the old EverQuest .xmi file format (MIDI)

PlayMP3 packet will ignore the clients music and sound level sliders so this can be annoying if you use it, however this restores the ability to use music in EverQuest because this plugin will only play one sound file per IP, which allows music to be played without walking over each clients sound files.

All of the sound file lengths are queried from the custom table listed below. All Wav/MP3 files are in this database, no XMI's. If you want to use XMI's you will have to use them on your own accord.

Options:

repeat_on_end - Will repeat the sound file after the song plays

delay_repeat - How long the sound timer will wait before repeating

interrupt - This will interrupt another sound that is playing

Required Database Table:

DOWNLOAD

sub EVENT_SAY{
	if($text=~/soundtest1/i){
		quest::say("Hi");
		%options = ("repeat_on_end" => 1,  "delay_repeat" => 5);
		plugin::U_MP3("guildhall.mp3", \%options);
	}
	if($text=~/soundtest2/i){
		%options = ("repeat_on_end" => 1, "delay_repeat" => 5, "interrupt" => 1);
		plugin::U_MP3("povalor.mp3", \%options);
	}
	if($text=~/soundtest3/i){
		%options = ("repeat_on_end" => 1, "delay_repeat" => 5, "interrupt" => 1); 
		plugin::U_MP3("thevoid_loop.mp3", \%options);
	}
	if($text=~/eqthrowback/i){
		$client->PlayMP3("opener4.xmi");
	}
}
constants.pl
  • §plugin::Skill(SkillID)
  • §plugin::Class(class_id)
  • §plugin::Race(Race_ID)
  • §plugin::Deity(Deity_Name);
  • §plugin::Gender(gender_id)
  • §plugin::Zone(zone_id) Returns zone long name
  • §plugin::ZoneShortName(zone_id) Returns zone short name
  • §plugin::ZoneIDBySN(zoneshortname) Returns zone short name
  • §plugin::SlotName(slotid) Returns slot name
  • §plugin::IP($client->GetIP()) Gets the clients human readable IP
sub EVENT_SAY{
	if($text=~/hail/i){
		quest::say("Wow, I can teach you a couple skills, one of them is " . plugin::Skill(0) . ".");
		quest::say("I am a non-player race, specifically " . plugin::Race(666) . ".");
		quest::say("So you're a " . plugin::Deity(201) . " follower?");
		quest::say("Hello $name,  you're a " . plugin::Gender($client->GetGender()) . "!");
		quest::say("Would you like to go to " . plugin::Zone(2) . "?");
		quest::say("Would you like to go to " . plugin::ZoneShortName(2) . "?");
		quest::say("The Zone ID for Crushbone is " . plugin::ZoneIDBySN("crushbone") . "?");
		quest::say("You have a " . quest::varlink($client->GetItemIDAt(9999)) . " in your " . plugin::Slot(9999) . " slot.");
		quest::say("Your IP is: " . plugin::IP($client->GetIP()));
	}
}

Task_Utils.pl
  • §plugin::AssignTask(UpdateType=[solo, group, raid], TaskID, [NPCID = 0] ($npc>GetID());
  • §plugin::FailTask(UpdateType=[solo, group, raid], TaskID);
  • §plugin::UpdateTaskActivity(UpdateType [solo, group, raid], TaskID, ActivityID, Count);
sub EVENT_SAY{
	if($text=~/assign/i){ plugin::AssignTask("group", 177); } #::: This will assign a task to an entire group that is in the zone
	if($text=~/fail/i){ plugin::FailTask("group", 177); } #::: This will fail a task to an entire group (That is currently in the zone)
	if($text=~/update/i){ plugin::UpdateTaskActivity("group", 177, 0, 1); } #::: This will update a task activity for a group of players  (That is currently in the zone)
}
§formation_tools.pl
  • §plugin::FollowFormLeader([LeaderMob, OnGrid = 0, MoveToX = 0, MoveToY = 0, NoSpeedBuffs = false]);
  • §plugin::MoveInFormation(NPCID, [$npc = 0, OnGrid = 0, MoveToX = 0, MoveToY = 0, NoSpeedBuffs = false]);
  • §plugin::MoveToFormation(NPCID, LeaderMob, Distance, Columns, Rows, [LeadDist, MaxZDiff]);
  • §plugin::RandomFormRoam(MaxVariance, MaxZVariance, LoSMobSize);
  • §plugin::SpawnInFormation(NPCID, LeaderMob, Distance, Columns, Rows, [LeadDist, MaxZDiff]);
  • §plugin::SpawnInFormationXY(NPCID, X, Y, Z, Distance, Columns, Rows, Heading, MaxZDiff);
  • §plugin::SpawnMixedFormation(LeaderMob, Distance, Columns, Rows, LeadDist=Distance, MaxZDiff=15, NPCID, NPCID...);
  • §plugin::FollowInFormation(NPCID, Mob, [MaxZDiff]);
  • §plugin::SquadAttackTarget(SquadNPCID, TargetID);
  • §plugin::SquadAttackSquad(Squad1NPCID, Squad2NPCID);
  • §plugin::GetReverseHeading($mob);
# This script goes on the formation leader, in which this case is Kobold Captain Buark
# The Captain will spawn as many of the patrollers that you specify in your formation with SpawnInFormation
# 
#
# 2701876 - Kobold_Captain_Buark
# 2700096 - Kobold_Patroller

my $LeaderNPCID = 2701876;
my $SquadNPCID = 2700096;
my $SpawnDist = 10;

sub EVENT_SPAWN {
	quest::depopall($SquadNPCID);
	quest::settimer("spawn_guards", 2);
	
}

sub EVENT_TIMER {
	if ($timer eq "spawn_guards") {
		quest::stoptimer("spawn_guards");
		#Usage: plugin::SpawnInFormation(NPCID, LeaderMob, Distance, Columns, Rows, [LeadDist, MaxZDiff]);
		plugin::SpawnInFormation($SquadNPCID, $npc, $SpawnDist, 2, 2, 10, 10);
		#Usage: plugin::MoveInFormation(NPCID, [$npc = 0, OnGrid = 0, MoveToX = 0, MoveToY = 0, NoSpeedBuffs = false]);
		plugin::MoveInFormation($SquadNPCID, $npc , 1);
	}
	if ($timer eq "WPArrive") {
		quest::stoptimer("WPArrive");
		plugin::MoveInFormation($SquadNPCID, $npc, 1);
	}
}

my $MoveSquad = 1;
sub EVENT_WAYPOINT_DEPART {
	if ($MoveSquad){
		quest::settimer("WPArrive", 0);
	}
	else {
		quest::stop();
	}
}

The result looks something like this, given that your NPC's have been created and the ID's are right in the script and you have a Grid on the Captain:

weapon_tools.pl
  • §plugin::RandomWeapons(MinModelNum, MaxModelNum, MyChance, MinShieldNum, MaxShieldNum, NoDualWield?, IgnoreClass? );
  • §plugin::SetWeapons(PrimaryModel, SecondaryModel, EnableRemoving? );
plugin::SetWeapons(11); # Will set the primary weapon model to 11 but not change what the second weapon model is currently.
plugin::SetWeapons(11, 200); # Will set the primary to 11 and secondary to 200.
plugin::SetWeapons(0, 200); # Will set the secondary to model 200 without changing whatever model might be set in the primary.
plugin::SetWeapons(0, 200, 1); # Will remove the weapon model from the primary and set the secondary to model 200
plugin::SetWeapons(11, 0, 1); # Will set the primary model to 11 and remove any secondary model.
sub EVENT_SPAWN {
	quest::settimer("WeaponChange", 5);
}

sub EVENT_TIMER {
	if($timer eq "WeaponChange") {
		quest::stoptimer("WeaponChange");
		#Any random weapon and shield available through SoF
		plugin::RandomWeapons(1, 11169, 50, 200, 230);
	}
}