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

Quests::Submissions This is where you submit your quests for review

Reply
 
Thread Tools Display Modes
  #1  
Old 09-25-2023, 12:24 PM
diemuzi
Fire Beetle
 
Join Date: Nov 2021
Location: Pensacola, Florida
Posts: 1
Default Prestige

This custom NPC script will allow you to take a character and change their class into another. On my development server I am allowing all race/class/deity combinations.

The character will retain all spent AA points and AA XP.

Requirements to prestige can be changed at the top of the script but these are the defaults:
  • Must be level 100
  • Have Epic 2.0 completed and have the item

You can change the minimum required level, required item, and the default level to attain after prestige.

The following will happen:
  • Summons and removes all corpses, so make sure you've looted any remaining corpses
  • Changes from level 100 to level 1
  • Sets the appropriate experience
  • Resets all skills
  • Resets all languages
  • Untrain all discs
  • Unscribe all spells
  • WorldKick to login

Character must be naked (if not, the script will tell you to remove X item from Y slot)

When you hail the NPC, choose "prestige". If you meet the base requirements then you can select the class of your choice. A popup will ask you to confirm this change before continuing. Once you've confirmed, it's done! If you cancel, no changes will take place.

I tried to document the entire code base to make it easier to follow what happens during each stage.

If you find any problems, want changes, etc. Please let me know.

Example 1 - Meets requirements:





Example 2 - Does not meet the base requirements:



Prestige.pl

HTML Code:
######################
# Quest Name: Prestige
# Author: Diemuzi
# NPCs Involved: 1
# Items Involved: 1
######################

# Minimum level required to prestige
my $min_level_required = 100;

# Required Item ID for each class in order to prestige, currently set to Epic 2.0
# Class Bitmask => Required ItemID
my %required_item = (
    1     => 60332, # Warrior
    2     => 20076, # Cleric
    4     => 48147, # Paladin
    8     => 62649, # Ranger
    16    => 48136, # Shadow Knight
    32    => 62880, # Druid
    64    => 67742, # Monk
    128   => 77640, # Bard
    256   => 52348, # Rogue
    512   => 57405, # Shaman
    1024  => 64067, # Necromancer
    2048  => 16575, # Wizard
    4096  => 19839, # Magician
    8192  => 52962, # Enchanter
    16384 => 57054, # Beastlord
    32768 => 20072  # Berserker
);

# Default level after prestige
my $set_level = 1; # Level 1 - 100

############################################
# DO NOT CHANGE ANYTHING BEYOND THIS POINT #
############################################

my $can_prestige = 0;         # 0 = No, 1 = Yes
my $class_type = undef;       # Class type is undef until choosen later
my $has_gear_equipped = 0;    # 0 = No, 1 or more = Yes
my $has_meet_requirement = 0; # 0 = No, 1 = Yes

# Available classes
my %classes = (
    1  => 'Warrior',
    2  => 'Cleric',
    3  => 'Paladin',
    4  => 'Ranger',
    5  => 'Shadow Knight',
    6  => 'Druid',
    7  => 'Monk',
    8  => 'Bard',
    9  => 'Rogue',
    10 => 'Shaman',
    11 => 'Necromancer',
    12 => 'Wizard',
    13 => 'Magician',
    14 => 'Enchanter',
    15 => 'Beastlord',
    16 => 'Berserker'
);

sub EVENT_SAY {
    #:: Match text for "hail", case insensitive
    if ($text =~ /hail/i) {
        #:: Send a message that only the client can see, in yellow (15) text
        $client->Message(15, "Hey $name. Would you like to [" . quest::saylink("prestige") . "]?");

        # Reset to default values
        $can_prestige = 0;
        $has_gear_equipped = 0;
        $has_meet_requirement = 0;
    }

    #:: Match text for "prestige", case insensitive
    elsif ($text =~ /prestige/i) {
        # Reset to default values
        $can_prestige = 0;
        $has_gear_equipped = 0;
        $has_meet_requirement = 0;

        # Check that the current class has the required item
        if ($client->CountItem($required_item{$client->GetClassBitmask()}) == 1) {
            $has_meet_requirement = 1;
        }

        # Check if the requirements have been met
        if ($has_meet_requirement && $client->GetLevel() == $min_level_required) {
            #:: Send a message that only the client can see, in yellow (15) text
            $client->Message(15, 'You have the required item and have been granted access.');

            # Make sure we are naked
            INVENTORY_CHECK();

            # Success, we are naked and can continue
            if (!$has_gear_equipped) {
                $client->Message(15, "You are naked and can continue.");

                # Play Ding!
                quest::ding();

                # Can proceed after choosing a class
                $can_prestige = 1;

                # Choose a class
                $client->Message(15, 'Which class would you like to be next?');
                $client->Message(15, "Cloth classes [" . quest::saylink("Enchanter") . "] -- [" . quest::saylink("Magician") . "] -- [" . quest::saylink("Necromancer") . "] -- [" . quest::saylink("Wizard") . "]");
                $client->Message(15, "Leather classes [" . quest::saylink("Beastlord") . "] -- [" . quest::saylink("Druid") . "] -- [" . quest::saylink("Monk") . "]");
                $client->Message(15, "Chain classes [" . quest::saylink("Berserker") . "] -- [" . quest::saylink("Ranger") . "] -- [" . quest::saylink("Rogue") . "] -- [" . quest::saylink("Shaman") . "]");
                $client->Message(15, "Plate classes [" . quest::saylink("Bard") . "] -- [" . quest::saylink("Cleric") . "] -- [" . quest::saylink("Paladin") . "] -- [" . quest::saylink("Shadow Knight") . "] -- [" . quest::saylink("Warrior") . "]");
            }
        }
        else {
            # Character does not meet the basic requirements
            $client->Message(15, "Sorry but you do not meet the requirements. You must be at least level " . $min_level_required . " and have the required item.");
        }
    }

    # We can prestige and continue after confirming
    if ($can_prestige == 1) {
        keys %classes;
        while (my ($k, $v) = each %classes) {
            if ($text =~ /$v/i) {
                # Reset to default value
                $can_prestige = 0;

                # Chosen class type
                $class_type = $k;

                # Display confirmation window
                my $dialogMessage = "{title: Confirm Character Class Change} {button_one: Yes} {button_two: No} wintype:1 popupid:1 secondresponseid:2 Are you sure you want to change your class to a " . $v . "?
                                    {linebreak}
                                    {in}{r}MAKE SURE ALL CORPSES ARE LOOTED BEFORE CONTINUING AS THEY WILL BE DESTORYED.~
                                    {linebreak}
                                    {in}{y}If you continue, you will be disconnected.~";
                quest::crosszonedialoguewindowbycharid($client->CharacterID(), $dialogMessage);
            }
        }
    }
}

sub EVENT_ITEM {
    #:: Return unused items since we don't expect any handins
    plugin::returnUnusedItems();
}

sub EVENT_POPUPRESPONSE {
    # Yes
    if ($popupid == 1) {
        # Make sure we are still naked
        INVENTORY_CHECK();

        if (!$has_gear_equipped) {
            # Summon and remove all corpses
            REMOVE_CORPSES();

            # Level
            $client->SetClientMaxLevel($set_level);

            # Experience per level
            my %exp = (
                1   => 0,
                2   => 1000,
                3   => 8000,
                4   => 27000,
                5   => 64000,
                6   => 125000,
                7   => 216000,
                8   => 343000,
                9   => 512000,
                10  => 729000,
                11  => 1000000,
                12  => 1331000,
                13  => 1728000,
                14  => 2197000,
                15  => 2744000,
                16  => 3375000,
                17  => 4096000,
                18  => 4913000,
                19  => 5832000,
                20  => 6859000,
                21  => 8000000,
                22  => 9261000,
                23  => 10648000,
                24  => 12167000,
                25  => 13824000,
                26  => 15625000,
                27  => 17576000,
                28  => 19683000,
                29  => 21952000,
                30  => 24389000,
                31  => 29700000,
                32  => 32770100,
                33  => 36044800,
                34  => 39530700,
                35  => 43234400,
                36  => 51450000,
                37  => 55987200,
                38  => 60783600,
                39  => 65846400,
                40  => 71182800,
                41  => 83200000,
                42  => 89597296,
                43  => 96314400,
                44  => 103359104,
                45  => 110739200,
                46  => 127575000,
                47  => 136270400,
                48  => 145352192,
                49  => 154828800,
                50  => 164708608,
                51  => 175000000,
                52  => 198976496,
                53  => 224972800,
                54  => 253090896,
                55  => 299181600,
                56  => 349387488,
                57  => 403916800,
                58  => 462982496,
                59  => 526802400,
                60  => 616137024,
                61  => 669600000,
                62  => 703641088,
                63  => 738816768,
                64  => 775145728,
                65  => 812646400,
                66  => 851337472,
                67  => 891237632,
                68  => 932365312,
                69  => 974739200,
                70  => 1018377920,
                71  => 1063299968,
                72  => 1109524096,
                73  => 1157068800,
                74  => 1205952640,
                75  => 1256194432,
                76  => 1307812480,
                77  => 1360825600,
                78  => 1415252352,
                79  => 1471111168,
                80  => 1528420864,
                81  => 1587200000,
                82  => 1647467136,
                83  => 1709240832,
                84  => 1772539648,
                85  => 1837382400,
                86  => 1903787520,
                87  => 1971773568,
                88  => 2041359360,
                89  => 2112563200,
                90  => 2185403904,
                91  => 2259899904,
                92  => 2336070144,
                93  => 2413932800,
                94  => 2493506816,
                95  => 2574810368,
                96  => 2657862400,
                97  => 2742681600,
                98  => 2829286400,
                99  => 2917695232,
                100 => 3007926784
            );

            # Set Experience based on level
            $client->SetEXP($exp{$set_level}, $client->GetAAExp());

            # Reset skills
            my @skills = (0 .. 77);
            for (@skills) {
                if ($client->HasSkill($_)) {
                    $client->SetSkill($_, 1);
                }
            }

            # Reset languages
            my @language = (0 .. 27);
            for (@language) {
                $client->SetLanguageSkill($_, 1);
            }

            # Untrain Discs
            $client->UntrainDiscAll();

            # Unsubscribe Spells
            $client->UnscribeSpellAll();

            # Set Class
            $client->SetBaseClass($class_type);

            # Kick to login
            $client->WorldKick();
        } else {
            $client->Message(15, "Nice try, but you're not naked!");
        }
    }

    # No
    if ($popupid == 2) {
        # No changes will take place
        $client->Message(15, "You will remain a " . $client->GetClassAbbreviation() . ".");
    }
}

sub INVENTORY_CHECK {
    # Inventory items to check if equipped
    my %inventory = (
        0  => 'Charm',       # Charm
        1  => 'Ear',         # Ear1
        2  => 'Head',        # Head
        3  => 'Face',        # Face
        4  => 'Ear',         # Ear2
        5  => 'Neck',        # Neck
        6  => 'Shoulder',    # Shoulders
        7  => 'Arm',         # Arms
        8  => 'Back',        # Back
        9  => 'Wrist',       # Wrist1
        10 => 'Wrist',       # Wrist2
        11 => 'Range',       # Range
        12 => 'Hand',        # Hands
        13 => 'Primary',     # Primary
        14 => 'Secondary',   # Secondary
        15 => 'Finger',      # Finger1
        16 => 'Finger',      # Finger2
        17 => 'Chest',       # Chest
        18 => 'Leg',         # Legs
        19 => 'Feet',        # Feet
        20 => 'Waist',       # Waist
        21 => 'PowerSource', # PowerSource
        22 => 'Ammo'         # Ammo
    );

    # Make sure we are naked
    keys %inventory;
    while (my ($k, $v) = each %inventory) {
        if ($client->GetItemAt($k)) {
            $client->Message(15, "You have a " . lc($v) . " item equipped. Please remove it.");

            $has_gear_equipped++;
        }
    }
}

sub REMOVE_CORPSES {
    if ($client->GetCorpseCount() > 0) {
        quest::summonallplayercorpses($client->CharacterID(), $client->GetX(), $client->GetY(), $client->GetZ(), 0);
    }

    my @corpse_list = $entity_list->GetCorpseList();
    my $count = 0;

    foreach $corpse_found (@corpse_list) {
        if ($corpse_found->GetOwnerName() eq $client->GetName()) {
            $corpse_found->Delete();

            $count++;
        }
    }

    $count;
}

Last edited by diemuzi; 09-25-2023 at 12:48 PM.. Reason: Inventory check twice, can't be too sneaky!
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

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


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3