EQEmulator Forums

EQEmulator Forums (https://www.eqemulator.org/forums/index.php)
-   Quests::Custom (https://www.eqemulator.org/forums/forumdisplay.php?f=671)
-   -   Creating A Talent System Tutorial (https://www.eqemulator.org/forums/showthread.php?t=42192)

Shodai82 11-27-2018 01:58 PM

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.

Almusious 11-27-2018 03:22 PM

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.

Shodai82 11-27-2018 05:45 PM

I updated my post to include that sub.

ChaosSlayerZ 11-27-2018 10:34 PM

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!

superpally1 11-28-2018 05:47 PM

wow! very cool idea. thankyou for sharing this.

Shodai82 11-30-2018 02:07 AM

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!");
                        }
                    }
                }
            }
        }
    }
}


Kingly_Krab 12-05-2018 11:41 AM

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!");
                    }
                }
            }
        }
    }
}


Almusious 12-06-2018 06:37 PM

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.


All times are GMT -4. The time now is 09:08 AM.

Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.