Going to post it for now. May need more work, as I was unable to test the complete functionality for Hitting of All clients (couldn't set it up to connect more than one).
What this plugin will do is allow a mob to do a custom archery attack against either, Current Target, All Targets on hatelist, or a random target on the mob's hatelist.
Certain variables are settable in the main plugin file.
Plugin requires RandomRange() from the following link:
http://www.eqemulator.org/forums/showthread.php?t=30421
Here are the steps to add this plugin to your server:
1. Open notepad, or whatever text editor you prefer.
2. Copy and paste the following code into Notepad:
Code:
# Usage: plugin::ArcheryAttack(MeanDamage, Variance, TargNumber);
# MeanDamage - average damage of the attack
# Variance - +- % of mean as a range.
# TargNumber - 1: Current target, 2: All Targets on Hatelist, 3: Random Target from Hatelist
# Requires most current globals.pl and randomrange.pl plugins.
sub ArcheryAttack {
## Variables, set these to customize how the script works
$ACDiv = 75; # 35% shielding (max default) at 2625 AC with ACDiv of 75
$PCTMiss = 5; # Percent chance to miss outright
$PCTCrit = 5; # Percent chance to critically hit
$MaxShield = 35; # Max Shielding percent
$ThroatDamage = 1.25; # Following variables edit the damage
$HeadDamage = 1.1; # Based on where the arrow is striking
$ChestDamage = 1.0; # Feel free to edit these to
$ArmDamage = 0.9; # Suit your needs.
$LegDamage = 0.9;
$HandDamage = 0.75;
$FootDamage = 0.75;
## End Variables
$PCTMiss = 100-$PCTMiss+1;
$npc = plugin::val('$npc');
$entity_list = plugin::val('entity_list');
my $MeanDamage = $_[0];
my $Variance = $_[1];
my $TargNumber = $_[2];
my $MobName = $npc->GetCleanName();
my $MinDamage = int ( $MeanDamage * (1-($Variance/100)) );
my $MaxDamage = int ( $MeanDamage * (1+($Variance/100)) );
$HitDmg = plugin::RandomRange($MinDamage, $MaxDamage);
if ($TargNumber == 1) {
$targ = $npc->GetHateTop();
$hitname = $targ->GetName();
$targid = $targ->GetID();
$targid = $entity_list->GetClientByID($targid);
LocDmg();
quest::emote("sights and releases an arrow at his most infuriating enemy, $hitname.");
quest::doanim(9);
ApplyDamage();
}
if ($TargNumber == 2) {
quest::emote("begins to a fire off a furious barrage of arrows, aiming at everyone around him!");
quest::doanim(9);
LocDmg();
HitAllClients();
}
if ($TargNumber == 3) {
$target = $npc->GetHateRandom();
$targid = $target->GetID();
$targid = $entity_list->GetClientByID($targid);
$hitname = $target->GetName();
LocDmg();
quest::emote("looses an arrow at $hitname at random.");
quest::doanim(9);
ApplyDamage();
}
}
sub LocDmg {
$HitLoc = quest::ChooseRandom("head","head","leg","arm","chest","chest","throat","throat","hand","foot");
CritOrMiss();
if ($HitLoc eq "head") {
$HitDmg = int($HitDmg*$HeadDamage);
}
if ($HitLoc eq "leg") {
$HitDmg = int($HitDmg*$LegDamage);
}
if ($HitLoc eq "arm") {
$HitDmg = int($HitDmg*$ArmDamage);
}
if ($HitLoc eq "throat") {
$HitDmg = int($HitDmg*$ThroatDamage);
}
if ($HitLoc eq "hand" ) {
$HitDmg = int($HitDmg*$HandDamage);
}
if ($HitLoc eq "foot") {
$HitDmg = int($HitDmg*$FootDamage);
}
if ($HitLoc eq "chest") {
$HitDmg = int($HitDmg*$ChestDamage);
}
}
sub HitAllClients {
my @hatelist = $npc->GetHateList();
foreach $ent (@hatelist)
{
if($ent)
{
my $h_ent = $ent->GetEnt();
if($h_ent)
{
$targid = $h_ent->GetID();
$targid = $entity_list->GetClientByID($targid);
ApplyDamage();
}
}
}
}
sub ApplyDamage {
if ($HitDmg != 0) {
$pac = $targid->CastToMob()->GetAC();
$shielding = $pac/$ACDiv;
if ($shielding > $MaxShield) {
$shielding = $MaxShield;
}
$shielding = $shielding/100;
$HitDmg = int ($HitDmg * (1-$shielding));
$targid->Damage($npc,$HitDmg,0,4);
if ($DidCrit eq "crit") {
$targid->Message(13,"You have been CRITICALLY STRUCK by an arrow in the $HitLoc for $HitDmg points of non-melee damage!");
}
else {
$targid->Message(13,"You have been struck by an arrow in the $HitLoc for $HitDmg points of non-melee damage!");
}
}
else {
$targid->Message(13,"You breathe a sigh of relief as the arrow narrowly misses you!");
}
}
sub CritOrMiss {
$didmiss = int(rand(100));
if ($didmiss > $PCTMiss) {
$HitDmg = 0;
}
if ($didmiss <= $PCTCrit) {
$DidCrit = "crit";
$HitDmg = $HitDmg*2;
}
else {
$DidCrit = "no";
}
}
3. Save that file to your server /plugins/ folder and name it "ArcheryAttack.pl".
4. Look over the variables in the ArcheryAttack.pl that you just saved, can edit a few different variables to customize how it works in accordance with what you want.
5. Do a #questreload and the new plugin should be ready for use
Here is an example script:
Code:
sub EVENT_SPAWN {
quest::stoptimer("attack");
}
sub EVENT_COMBAT {
if ($combat_state == 1) {
quest::settimer("attack",10);
}
if ($combat_state == 0) {
quest::stoptimer("attack");
}
}
sub EVENT_TIMER {
plugin::ArcheryAttack(1000, 10, 1);
}
Every 10 seconds, the example script will fire an arrow at the the main tank. This arrow will have a base damage in the range of 900-1100, which is then further modified by where the arrow will strike. The arrow will then check to see if it crits or misses, and doubles damage on a crit, or set to 0 if it misses. The damage is then applied to the player through an invisible message, and a custom message is sent to the player telling them where they were struck by the arrow, and for how much.
Usage for this Plugin? Can set up a mob to have three timers once aggroed, one for the Single Target, one for the Hit all, one for hit random target on a permarooted mob and you now have a ranged fight. Give the mob high min/max damage to encourage people to stay out of melee. Was more developed as a way to see if I could do something like this.
Current caveat, I could not find a way to pull a player's Shielding, so I used AC to simulate (poorly) a player's shielding. AC / 75 = Shielding Percent. If anyone has any ideas to get around that, please let me know!