Go Back   EQEmulator Home > EQEmulator Forums > Quests > Quests::Custom

Quests::Custom Custom Quests here

Reply
 
Thread Tools Display Modes
  #1  
Old 11-27-2018, 01:58 PM
Shodai82
Fire Beetle
 
Join Date: May 2015
Posts: 24
Default Creating A Talent System Tutorial

I recently launched a Talent System on UltimateEQ, and wanted to share the implementation details in case others would be interested in doing something similar.

1. Earning Credits To Purchase Talents

On UltimateEQ, to get a talent you purchase it with "Credits". Credits are earned in specific zones on kill based on various criteria, with each zone being specific to a credit rank.

In global_player.pl:


Code:
sub EVENT_KILLED_MERIT {
    #:: Get the name of the mob to use in the quest global
    if($client->InZone()) {
    	my $currentZoneID = $client->GetZoneID();

	    if (!$npc || $npc->GetOwnerID() || $npc->GetSwarmOwner()) {
			return;
		}

		if ($mlevel > 70) {	
			if($currentZoneID == 72) {
				if (defined ($client->GetGlobal("tier7_credit"))) {
					my $total = $client->GetGlobal("tier7_credit");
					
					if($npc->GetNPCTypeID() == 72003 || $npc->GetNPCTypeID() == 207001 || $npc->GetNPCTypeID() == 221008 || $npc->GetNPCTypeID() == 200055 || $npc->GetNPCTypeID() == 76007) {
						$total += 250;
						$client->SetGlobal("tier7_credit", $total, 5, "F");
						$client->Message(5, "You have gained 200 Tier 7 Tokens! You currently have $total.");
					} elsif($npc->GetNPCTypeID() == 72004 || $npc->GetNPCTypeID() == 72000 || $npc->GetNPCTypeID() == 72002 || $npc->GetNPCTypeID() == 72090) {
						$total += 50;
						$client->SetGlobal("tier7_credit", $total, 5, "F");
						$client->Message(5, "You have gained 50 Tier 7 Tokens! You currently have $total.");
					} else {
						$total += 1;
						$client->SetGlobal("tier7_credit", $total, 5, "F");
						$client->Message(5, "You have gained a Tier 7 Token! You currently have $total.");
					}

				}
			}

		}
       }
}

2. Converting Credits To Talents

Once a player has accumulated enough credits they can talk to the Talent NPC to convert them to Talent Points, which can then be spent as such:

In talent_npc.pl:


Code:
sub EVENT_SAY {
    my $haveTalentsBeenInitialized = $client->GetGlobal("has_set_talents_to_zero");
    if($haveTalentsBeenInitialized eq "Undefined") {
        INITIALIZE_TALENTS();
    }

	if ($text =~/Hail/i) {
        plugin::Whisper("Hello $name, I can assist your with your talents. What would you like to do today?");
		plugin::Whisper("1. [" . quest::saylink("View My Talents") . "]"); 
        plugin::Whisper("2. [" . quest::saylink("Spend Talent Points") . "]"); 
        plugin::Whisper("3. [" . quest::saylink("Reset My Talents") . "]"); 
        plugin::Whisper("4. [" . quest::saylink("Convert Tier 7 Credits To Talent Points") . "]"); 
	}

	if ($text =~/proceed/i) {
        my $totalTalentPointsSpent = $client->GetGlobal("talent_credit_spent");
        my $totalTalentPointsAvailableToSpend = $client->GetGlobal("talent_credit");
        my $totalTierSevenCredits = $client->GetGlobal("tier7_credit");
        my $limitTalents = $totalTalentPointsSpent + $totalTalentPointsAvailableToSpend;

        if($limitTalents < 60) {
            if($totalTierSevenCredits >= 100) {
                my $newTierSevenCreditValue = $totalTierSevenCredits - 100;             
                my $newTalentPointTotal = $totalTalentPointsAvailableToSpend + 1;
                $client->SetGlobal("tier7_credit", $newTierSevenCreditValue, 5, "F");
                $client->SetGlobal("talent_credit", $newTalentPointTotal, 5, "F");
                $client->SendMarqueeMessage(2, 510, 1, 100, 3000, "You have purchased 1 Talent Point. You now have a total of " . $newTalentPointTotal . " Talent Points");
            } else {
                if($totalTierSevenCredits eq "Undefined") {
                    plugin::Whisper("You not yet earned any credits! How can I convert nothing!");                  
                } else {
                    plugin::Whisper("You must have at least 100 Tier 7 Credits to convert. You only have " . $totalTierSevenCredits . "!");
                }
            }

        } else {
            plugin::Whisper("You have already accumulated 60 Talent Points, I can give you no more at this time!");
        }

    }

    if ($text =~/View My Talents/i) {
        if($client->GetClass() == 13) {
		    quest::popup("Talents - $name",                     
                "<br>
                <c \"#32CD32\">Class:</c> " . $class . "
                <br>
                <c \"#32CD32\">Available Points:</c> " . $client->GetGlobal("talent_credit") . "
                <br>
                <c \"#32CD32\">Total Spent:</c> " . $client->GetGlobal("talent_credit_spent") . " (Max 60)
                <br><br>
                <c \"#FFFF33\">Tier 1 Talents</c>: 
                <br>
                <c \"#32CD32\">Frozen Waves:</c> " . $client->GetGlobal("mag_frozen_waves") . "
                <br>
                <c \"#32CD32\">Arcane Servant:</c> " . $client->GetGlobal("mag_arcane_servant") . "
                <br><br>
                <c \"#FFFF33\">Tier 2 Talents</c>: 
                <br>
                <c \"#32CD32\">Enraged Minion:</c> " . $client->GetGlobal("mag_enraged_minion") . "
                <br>
                <c \"#32CD32\">Empowered Absolute Zero:</c> " . $client->GetGlobal("mag_zero_blast") . "
                <br>
                <c \"#32CD32\">Empowered Meteor Blast:</c> " . $client->GetGlobal("mag_meteor_blast") . "
                <br>
                <c \"#32CD32\">Empowered Chromatic Blast:</c> " . $client->GetGlobal("mag_chromatic_blast") . "
                <br>
                <c \"#32CD32\">Empowered Hurricane Tumult:</c> " . $client->GetGlobal("mag_hurricane_blast") . "
                <br>
                <c \"#32CD32\">Empowered Demigod Boon:</c> " . $client->GetGlobal("mag_demigod_boon") . "
                <br><br>
                <c \"#FFFF33\">Tier 3 Talents</c>: 
                <br>
                <c \"#32CD32\">Veracity:</c> " . $client->GetGlobal("mage_veracity") . "
                <br>
                <c \"#32CD32\">Intensify:</c> " . $client->GetGlobal("mag_intensify") . "
                <br><br><br>
                <c \"#FFFF33\">Additional Information: </c> 
                <br>
                <c \"#32CD32\">Tier 2 Talents</c> require a mininum of 20 talent points spent. 
                <br>
                <c \"#32CD32\">Tier 3 Talents</c> require a mininum of 40 talent points spent.
                <br><br>
                "
                , 10002, 0, 120);
		}
	}

	if ($text =~/Spend Talent Points/i) {
        plugin::Whisper("To purchase a Talent just click the + button next to it. You will not be charged a point until you confirm your purchase. You may also view the Talent information after clicking the + button!");

        if($client->GetClass() == 13) {
            plugin::Whisper("Frozen Waves [" . quest::saylink("mag_frozen_waves", 1, "+") . "]");
            plugin::Whisper("Arcane Servant [" . quest::saylink("mag_arcane_servant", 1, "+") . "]");
            plugin::Whisper("Enraged Minion [" . quest::saylink("mag_enraged_minion", 1, "+") . "]");
            plugin::Whisper("Empowered Absolute Zero Blast [" . quest::saylink("mag_zero_blast", 1, "+") . "]");
            plugin::Whisper("Empowered Meteor Blast [" . quest::saylink("mag_meteor_blast", 1, "+") . "]");
            plugin::Whisper("Empowered Chromatic Blast [" . quest::saylink("mag_chromatic_blast", 1, "+") . "]");
            plugin::Whisper("Empowered Hurricane Tumult [" . quest::saylink("mag_hurricane_blast", 1, "+") . "]");
            plugin::Whisper("Demigod Boon [" . quest::saylink("mag_demigod_boon", 1, "+") . "]");
            plugin::Whisper("Veracity [" . quest::saylink("mage_veracity", 1, "+") . "]");
            plugin::Whisper("Intensify [" . quest::saylink("mag_intensify", 1, "+") . "]");
        }
    }

    if ($text =~/mag_frozen_waves/i) {
        $client->SetEntityVariable("BUYID", "Frozen Waves");
        quest::popup("Talent",                     
                         "<br>$Indent Talent Purchase:<c \"#00FFFF\"> Frozen Waves </c><br><br><br>
                         <c \"#FFFF00\">Ranks 1-20:</c> Up to 100% chance to trigger a second Flashfreeze I on cast. Increases by 5% per rank. <br><br>
                         <c \"#FFFF00\">Ranks 11-20:</c> Up to 60% chance to trigger a third Flashfreeze I on cast. Increases by 3% per rank.

                         "
                         , 10003, 1, 0);
    }

}

sub EVENT_POPUPRESPONSE {

    if($popupid == 10003) {

        my $BUY = $client->GetEntityVariable("BUYID");

        if($BUY eq "Frozen Waves") {
            my $talentRank = $client->GetGlobal("mag_frozen_waves");
            my $totalTalentPoints = $client->GetGlobal("talent_credit");
            my $totalTalentPointsSpent = $client->GetGlobal("talent_credit_spent");
          
            if($talentRank < 20 && $totalTalentPoints > 0 && $totalTalentPointsSpent <= 59) {
                my $newValue = $talentRank + 1;
                my $newTotalTalentsValue = $totalTalentPoints - 1;
                my $newTotalTalentsSpent = $totalTalentPointsSpent + 1;

                $client->SetGlobal("mag_frozen_waves", $newValue, 5, "F");
                $client->SetGlobal("talent_credit", $newTotalTalentsValue, 5, "F");
                $client->SetGlobal("talent_credit_spent", $newTotalTalentsSpent, 5, "F");
                $client->SendMarqueeMessage(7, 510, 1, 100, 3000, "You spent " . ($totalTalentPoints - $newTotalTalentsValue) . " point(s) on $BUY Rank " . $newValue . " and have " . $newTotalTalentsValue . " left to spend.");
            } else {
                plugin::Whisper("You have already maxed out this talent, do not have enough talent points, or cannot exceed 60 spent points!");
            }

        }
    }

}

sub INITIALIZE_TALENTS {
     if($client->GetClass() == 13) {
            $client->SetGlobal("mag_frozen_waves", 0, 5, "F");
            $client->SetGlobal("mag_arcane_servant", 0, 5, "F");
            $client->SetGlobal("mag_zero_blast", 0, 5, "F");
            $client->SetGlobal("mag_hurricane_blast", 0, 5, "F");
            $client->SetGlobal("mag_chromatic_blast", 0, 5, "F");
            $client->SetGlobal("mag_meteor_blast", 0, 5, "F");
            $client->SetGlobal("mag_demigod_boon", 0, 5, "F");
            $client->SetGlobal("mag_enraged_minion", 0, 5, "F");
            $client->SetGlobal("mage_veracity", 0, 5, "F");
            $client->SetGlobal("mag_intensify", 0, 5, "F");
      }
}
The actual in-game implementation looks like so:

Main Menu for Talent NPC:
https://imgur.com/a/g0oUtf0

My Talents View:
https://imgur.com/a/NWn8URT

Buy Menu:
https://imgur.com/a/O5chvjs

Buy Confirmation:
https://imgur.com/a/7MfKuU6


3. Using Purchased Talents

Talents purchased either apply to Spell Quests or are triggered when using a skill such as 1HB or 1HS. They can do anything from add additional casts based on talent rank, to summon mobs, charge at mobs, cause mobs to fight each other, and dozens of other scenarios.

For spell-based talents I took the route of creating individual spell quests for each talent. This required me to duplicate certain spells and then trigger them in a spell quest, on many occasions. Here is an example spell quest tied to the above mage talent:

Spell quest 5087.pl in quests/global/spells:


Code:
sub EVENT_SPELL_EFFECT_NPC {
	my $client = $entity_list->GetClientByID($caster_id);
	my $target = $entity_list->GetMobByID($client->GetTarget()->GetID());
	my $talentRank = $client->GetGlobal("mag_frozen_waves");

	if($target) {
		if($talentRank > 0) {
			my $talentSingleMultiplier = 5;
			my $talentRoll = GET_RANDOM_NUMBER();

			if($talentRoll <= ($talentRank * $talentSingleMultiplier)) {
		        $client->SpellFinished(31442, $target);
		        $client->Message(14, "Your Improved Flashfreeze talent triggered an additional cast!");

		        if($talentRank > 10) {
		            my $talentDoubleMultiplier = 3;
		            if($talentRoll <= ($talentRank * $talentDoubleMultiplier)) {
		                $client->SpellFinished(31442, $target);
		                $client->Message(14, "Your Improved Flashfreeze talent triggered a second additional cast!");
		            }
		        }
	        }

		}
	}
 	
}

sub GET_RANDOM_NUMBER {
    $minimum = 1;
    $maximum = 100;
    $rnd_number = $minimum + int(rand($maximum - $minimum));

    return $rnd_number;
}

The other route to enabling talents is with skills. Often player talents add additional melee attacks, or do various interesting things much more advanced than just additional melee attacks.

In order to enable this I added an implementation in EVENT_USE_SKILL within global_player.pl. I also cache all talents within global_player.pl on load:

global_player.pl:


Code:
my $flurryOfHatredRank;
my $flurryOfDestructionRank;

sub EVENT_ENTERZONE {   
    my $currentZoneID = $client->GetZoneID();
    if($currentZoneID != 344 && $currentZoneID != 345 && $currentZoneID != 202) {

        if($client->GetLevel() == 70) {

            if($qglobals{"Ultimate_Unrest_Complete"} == 1 && $qglobals{"has_gotten_charm_rank_nine"} == 1 && $qglobals{"has_gotten_oot_focus"} == 1 && $qglobals{"has_finished_ultimate_quest_line"} == 1) {


                if($client->GetClass() == 5) {
                    $flurryOfHatredRank = $qglobals{"sk_flurry_of_hatred"};
                    $flurryOfDestructionRank = $qglobals{"sk_flurry_of_destruction"};
                }
            }
        }
    }
}

sub EVENT_USE_SKILL {
    my $currentZone = $client->GetZoneID();
    if($currentZone != 344 && $currentZone != 345 && $currentZone != 202) {
        if($client->GetClass() == 5) {
            if($skill_id == 0 || $skill_id == 1) {
                if($flurryOfHatredRank > 0) {
                    my $flurryOfHatredPathSingleMultiplier = 3;
                    my $chanceRollBonusSingleFlurryOfHatred = GET_RANDOM_NUMBER();
                    my $target = $client->GetTarget();
                    if($chanceRollBonusSingleFlurryOfHatred <= ($flurryOfHatredRank * $flurryOfHatredPathSingleMultiplier)) {
                        if($skill_id == 0) {
                            $client->DoSpecialAttackDamage($target, 0, 500, 1000, 0);
                            $client->DoSpecialAttackDamage($target, 0, 500, 1000, 0);
                            $client->DoSpecialAttackDamage($target, 0, 500, 1000, 0);
                            $client->Message(14, "Your Flurry of Hatred talent triggered three additional attacks!");
                        } else {
                            $client->DoSpecialAttackDamage($target, 1, 500, 1000, 0);
                            $client->DoSpecialAttackDamage($target, 1, 500, 1000, 0);
                            $client->DoSpecialAttackDamage($target, 1, 500, 1000, 0);
                            $client->Message(14, "Your Flurry of Hatred talent triggered three additional attacks!");
                        }
                    }
                }
            } elsif($skill_id == 2 || $skill_id == 3) {
                if($flurryOfDestructionRank > 0) {
                    my $flurryOfDestructionPathSingleMultiplier = 4;
                    my $chanceRollBonusSingleFlurryOfDestruction = GET_RANDOM_NUMBER();
                    my $target = $client->GetTarget();
                    if($chanceRollBonusSingleFlurryOfDestruction <= ($flurryOfDestructionRank * $flurryOfDestructionPathSingleMultiplier)) {
                        if($skill_id == 2) {
                            $client->DoSpecialAttackDamage($target, 2, 500, 1000, 0);
                            $client->DoSpecialAttackDamage($target, 2, 500, 1000, 0);
                            $client->DoSpecialAttackDamage($target, 2, 500, 1000, 0);
                            $client->Message(14, "Your Flurry of Destruction talent triggered three additional attacks!");
                        } else {
                            $client->DoSpecialAttackDamage($target, 3, 500, 1000, 0);
                            $client->DoSpecialAttackDamage($target, 3, 500, 1000, 0);
                            $client->DoSpecialAttackDamage($target, 3, 500, 1000, 0);
                            $client->Message(14, "Your Flurry of Destruction talent triggered three additional attacks!");
                        }
                    }
                }
            }
        }
    }
}
When implementing EVENT_USE_SKILL within global_player it is imperative to also make sure you set your perl exports for EVENT_USE_SKILL to 0 for qglobals.

Code:
INSERT INTO `perl_event_export_settings` (`event_id`, `event_description`, `export_qglobals`, `export_mob`, `export_zone`, `export_item`, `export_event`)
VALUES
    (83, 'EVENT_USE_SKILL', 0, 0, 0, 0, 1);

4. Wrapping It Up

As of right now each class has between 6-10 talents (Class id's 1-16), so the actual implementation is far larger than shown here. Never the less, I've found this approach very scalable and, the best part is, if I can make an idea work with the PERL API, I can make a talent out of it. It has been quite interesting (and popular) making some really outlandish stuff that would never be possible using a traditional spell or AA.

Anyways, hope this can serve as some inspiration to others who might be interested in a Diablo-like talent system.
Reply With Quote
  #2  
Old 11-27-2018, 03:22 PM
Almusious
Fire Beetle
 
Join Date: Sep 2012
Posts: 16
Default

Not sure if you could use this and I haven't tested it beyond compiling:

Code:
sub EVENT_KILLED_MERIT 
{
	%tierhash = 
	(
		72	=>	[
			{
				npcminlevel 	=>	70,
				npcs 			=>	[72003,207001,221008,200055,76007],
				pointsfornpcs 	=>	250,
				tier 			=>	7,
			},
			{
				npcminlevel 	=>	70,
				npcs 			=>	[72004,72000,72002,72090],
				pointsfornpcs	=>	50,
				tier 			=>	7,				
			},
			{
				npcminlevel 	=>	70,
				npcs 			=>	["nonspecific"],
				pointsfornpcs	=>	1,
				tier 			=>	7,				
			},
		],
		72	=>	[
			{
				npcminlevel 	=> 70,
				npcs 			=> [72003,207001,221008,200055,76007],
				pointsfornpcs 	=> 250,
				tier 			=>	7,				
			},
			{
				npcminlevel 	=> 70,
				npcs 			=> [34238,54078,16976],
				pointsfornpcs	=> 80,
				tier 			=>	7,				
			},
		],
	);			
 
	my $pointsearned = 0;
	
	if ($client->InZone() && ($npc || !$npc->GetOwnerID() || !$npc->GetSwarmOwner()))
	{
		if (exists $tierhash{$zoneid})
		{
			
			foreach my $individualhasharray (keys ( @{$tierhash{$zoneid}} ))
			{
				if ($mlevel >= $tierhash{$zoneid}[$individualhasharray]->{npcminlevel})
				{
					
					if ($npc->GetNPCTypeID() ~~ @{$tierhash{$zoneid}[$individualhasharray]->{npcs}})
					{
						$pointsearned = $tierhash{$zoneid}[$individualhasharray]->{pointsfornpcs};
					}
					elsif ("nonspecific" ~~ @{$tierhash{$zoneid}[$individualhasharray]->{npcs}})
					{
						$pointsearned = $tierhash{$zoneid}[$individualhasharray]->{pointsfornpcs};
					}	
					if ($pointsearned)
					{					
						
						if (defined $client->GetGlobal("tier". $tierhash{$zoneid}[$individualhasharray]->{tier} ."_credit")) 
						{
							$client->SetGlobal(	"tier". $tierhash{$zoneid}[$individualhasharray]->{tier} ."_credit", 
												($client->GetGlobal("tier". $tierhash{$zoneid}[$individualhasharray]->{tier} ."_credit") + $pointsearned),
												5, "F");
							$client->Message(5, "You have gained " . 
											$pointsearned .
											" more Tier " . 
											$tierhash{$zoneid}[$individualhasharray]->{tier} .
											" Tokens!  This raises your total to " .
											$client->GetGlobal("tier". $tierhash{$zoneid}[$individualhasharray]->{tier} ."_credit") . "!");
						} else {
							$client->SetGlobal(	"tier". $tierhash{$zoneid}[$individualhasharray]->{tier} ."_credit", 
												$pointsearned,
												5, "F");
							$client->Message(5, "Congratulations, you have gained " . 
											$pointsearned .
											" initial Tier " . 
											$tierhash{$zoneid}[$individualhasharray]->{tier} .
											" Tokens!");
						}						
					}
				}
			}
		}
	}
}
Just one thing, and I only looked over it briefly like, is the "INITIALIZE_TALENTS" sub somewhere in the code?

Awesome work and thank you for sharing.
Reply With Quote
  #3  
Old 11-27-2018, 05:45 PM
Shodai82
Fire Beetle
 
Join Date: May 2015
Posts: 24
Default

I updated my post to include that sub.
Reply With Quote
  #4  
Old 11-27-2018, 10:34 PM
ChaosSlayerZ's Avatar
ChaosSlayerZ
Demi-God
 
Join Date: Mar 2009
Location: Umm
Posts: 1,369
Default

This is FREKOMAZING A+100 WORK!

I have ton of questions on how all this works, but don't really have time to dig into the code right now. Perhaps one day.
Once again AWESOME!

And most importantly thank you for sharing!
Reply With Quote
  #5  
Old 11-28-2018, 05:47 PM
superpally1
Fire Beetle
 
Join Date: Jul 2018
Location: Tennessee
Posts: 24
Default

wow! very cool idea. thankyou for sharing this.
Reply With Quote
  #6  
Old 11-30-2018, 02:07 AM
Shodai82
Fire Beetle
 
Join Date: May 2015
Posts: 24
Default

An update to this, it's probably best to use entity variables in global_player.pl when assigning talent values. I updated my implementation as such:

Code:
sub EVENT_ENTERZONE {   
    my $currentZoneID = $client->GetZoneID();
    if($currentZoneID != 344 && $currentZoneID != 345 && $currentZoneID != 202) {
        if($client->GetLevel() == 70) {
            if($qglobals{"Ultimate_Unrest_Complete"} == 1 && $qglobals{"has_gotten_charm_rank_nine"} == 1 && $qglobals{"has_gotten_oot_focus"} == 1 && $qglobals{"has_finished_ultimate_quest_line"} == 1) {
                if($client->GetClass() == 5) {
                    $client->SetEntityVariable("sk_flurry_of_hatred", $qglobals{"sk_flurry_of_hatred"});
                    $client->SetEntityVariable("sk_flurry_of_destruction", $qglobals{"sk_flurry_of_destruction"});
                }
            }
        }
    }
}

sub EVENT_USE_SKILL {
    my $currentZone = $client->GetZoneID();
    if($currentZone != 344 && $currentZone != 345 && $currentZone != 202) {
        if($client->GetClass() == 5) {
            if($skill_id == 0 || $skill_id == 1) {
                my $flurryOfHatredRank = $client->GetEntityVariable("sk_flurry_of_hatred");
                if($flurryOfHatredRank > 0) {
                    my $flurryOfHatredPathSingleMultiplier = 3;
                    my $chanceRollBonusSingleFlurryOfHatred = GET_RANDOM_NUMBER();
                    my $target = $client->GetTarget();
                    if($chanceRollBonusSingleFlurryOfHatred <= ($flurryOfHatredRank * $flurryOfHatredPathSingleMultiplier)) {
                        if($skill_id == 0) {
                            $client->DoSpecialAttackDamage($target, 0, 500, 1000, 0);
                            $client->DoSpecialAttackDamage($target, 0, 500, 1000, 0);
                            $client->DoSpecialAttackDamage($target, 0, 500, 1000, 0);
                            $client->Message(14, "Your Flurry of Hatred talent triggered three additional attacks!");
                        } else {
                            $client->DoSpecialAttackDamage($target, 1, 500, 1000, 0);
                            $client->DoSpecialAttackDamage($target, 1, 500, 1000, 0);
                            $client->DoSpecialAttackDamage($target, 1, 500, 1000, 0);
                            $client->Message(14, "Your Flurry of Hatred talent triggered three additional attacks!");
                        }
                    }
                }
            } elsif($skill_id == 2 || $skill_id == 3) {
                my $flurryOfDestructionRank = $client->GetEntityVariable("sk_flurry_of_destruction");
                if($flurryOfDestructionRank > 0) {
                    my $flurryOfDestructionPathSingleMultiplier = 4;
                    my $chanceRollBonusSingleFlurryOfDestruction = GET_RANDOM_NUMBER();
                    my $target = $client->GetTarget();
                    if($chanceRollBonusSingleFlurryOfDestruction <= ($flurryOfDestructionRank * $flurryOfDestructionPathSingleMultiplier)) {
                        if($skill_id == 2) {
                            $client->DoSpecialAttackDamage($target, 2, 500, 1000, 0);
                            $client->DoSpecialAttackDamage($target, 2, 500, 1000, 0);
                            $client->DoSpecialAttackDamage($target, 2, 500, 1000, 0);
                            $client->Message(14, "Your Flurry of Destruction talent triggered three additional attacks!");
                        } else {
                            $client->DoSpecialAttackDamage($target, 3, 500, 1000, 0);
                            $client->DoSpecialAttackDamage($target, 3, 500, 1000, 0);
                            $client->DoSpecialAttackDamage($target, 3, 500, 1000, 0);
                            $client->Message(14, "Your Flurry of Destruction talent triggered three additional attacks!");
                        }
                    }
                }
            }
        }
    }
}
Reply With Quote
  #7  
Old 12-05-2018, 11:41 AM
Kingly_Krab's Avatar
Kingly_Krab
Developer
 
Join Date: May 2013
Location: United States
Posts: 1,506
Default

Loops and minor optimization goes a long way.
Code:
sub EVENT_ENTERZONE {   
    if($zoneid !~ [202, 344, 345]) {
        if($client->GetLevel() == 70) {
            if($qglobals{"Ultimate_Unrest_Complete"} == 1 && $qglobals{"has_gotten_charm_rank_nine"} == 1 && $qglobals{"has_gotten_oot_focus"} == 1 && $qglobals{"has_finished_ultimate_quest_line"} == 1) {
                if($client->GetClass() == 5) {
                    $client->SetEntityVariable("sk_flurry_of_hatred", $qglobals{"sk_flurry_of_hatred"});
                    $client->SetEntityVariable("sk_flurry_of_destruction", $qglobals{"sk_flurry_of_destruction"});
                }
            }
        }
    }
}

sub EVENT_USE_SKILL {
    if($zoneid !~ [202, 344, 345]) {
        if($client->GetClass() == 5) {
            if($skill_id == 0 || $skill_id == 1) {
                my $flurryOfHatredRank = $client->GetEntityVariable("sk_flurry_of_hatred");
                if($flurryOfHatredRank > 0) {
                    my $flurryOfHatredPathSingleMultiplier = 3;
                    my $chanceRollBonusSingleFlurryOfHatred = GET_RANDOM_NUMBER();
                    my $target = $client->GetTarget();
                    if($chanceRollBonusSingleFlurryOfHatred <= ($flurryOfHatredRank * $flurryOfHatredPathSingleMultiplier)) {
			$client->DoSpecialAttackDamage($target, $skill_id, 500, 1000, 0) for (1..3);
			$client->Message(14, "Your Flurry of Hatred talent triggered three additional attacks!");
                    }
                }
            } elsif($skill_id == 2 || $skill_id == 3) {
                my $flurryOfDestructionRank = $client->GetEntityVariable("sk_flurry_of_destruction");
                if($flurryOfDestructionRank > 0) {
                    my $flurryOfDestructionPathSingleMultiplier = 4;
                    my $chanceRollBonusSingleFlurryOfDestruction = GET_RANDOM_NUMBER();
                    my $target = $client->GetTarget();
                    if($chanceRollBonusSingleFlurryOfDestruction <= ($flurryOfDestructionRank * $flurryOfDestructionPathSingleMultiplier)) {
                        $client->DoSpecialAttackDamage($target, $skill_id, 500, 1000, 0) for (1..3)
                        $client->Message(14, "Your Flurry of Destruction talent triggered three additional attacks!");
                    }
                }
            }
        }
    }
}
__________________
For Project 1999 related issues, check here.

Click here for the EQEmulator Wiki.
Reply With Quote
  #8  
Old 12-06-2018, 06:37 PM
Almusious
Fire Beetle
 
Join Date: Sep 2012
Posts: 16
Default

May as well kill the randomizing sub, some unneeded variable declarations and also utilize ones that are already passed in the parser (rather than pulling again):

Code:
sub EVENT_ENTERZONE {   
    if ($zoneid !~ [202, 344, 345]) {
        if ($ulevel == 70) {
            if ($qglobals{"Ultimate_Unrest_Complete"} and $qglobals{"has_gotten_charm_rank_nine"} and $qglobals{"has_gotten_oot_focus"} and $qglobals{"has_finished_ultimate_quest_line"}) {
                if ($class eq "Shadow Knight") {  ## Sure could remember every class number but why, also this is already passed
					$client->SetEntityVariable("sk_flurry_of_hatred", $qglobals{"sk_flurry_of_hatred"});
					$client->SetEntityVariable("sk_flurry_of_destruction", $qglobals{"sk_flurry_of_destruction"});
                }
            }
        }
    }
}

sub EVENT_USE_SKILL {
    if ($zoneid !~ [202, 344, 345]) {
        if ($class eq "Shadow Knight") {
            if ($skill_id ~~ [0..1]) {
                if ($client->GetEntityVariable("sk_flurry_of_hatred")) {
                    if (quest::ChooseRandom(1..100) <= ($client->GetEntityVariable("sk_flurry_of_hatred") * 3)) {
						if ($client->GetTarget()->IsNPC()) { ## Slim change of client changing target before the SA's but just in case
							$client->DoSpecialAttackDamage($client->GetTarget(), $skill_id, 500, 1000, 0) for (1..3);
							$client->Message(14, "Your Flurry of Hatred talent triggered three additional attacks!");
						}
                    }
                }
            } elsif ($skill_id ~~ [2..3]) {
                if ($client->GetEntityVariable("sk_flurry_of_destruction")) {
					if (quest::ChooseRandom(1..100) <= ($client->GetEntityVariable("sk_flurry_of_destruction") * 4)) {
						if ($client->GetTarget()->IsNPC()) { ## Slim change of client changing target before the SA's but just in case
							$client->DoSpecialAttackDamage($client->GetTarget(), $skill_id, 500, 1000, 0) for (1..3);
							$client->Message(14, "Your Flurry of Destruction talent triggered three additional attacks!");
						}
					}
                }
            }
        }
    }
}
Also added a check (main reason for posting this) to ensure the target is an NPC, granted not checking if the one that was originally targeted, but a check just the same. At least this way should someone get really lucky (or unlucky I suppose) won't possibly kill themselves if they target self for a buff or such.
Reply With Quote
Reply

Tags
qglobals, spell quests, talents, ultimateeq

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 04:02 PM.


 

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 - 2018, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3