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

Quests::Custom Custom Quests here

 
 
Thread Tools Display Modes
Prev Previous Post   Next Post Next
  #1  
Old 04-05-2018, 04:04 PM
c0ncrete's Avatar
c0ncrete
Dragon
 
Join Date: Dec 2009
Posts: 719
Default dispatch tables, by example (Absor)

Was puttering around with ideas to clean up Absor (repetition & lots of if/elsif statements) in tutorialb in the wee hours, and this is the result. It's not the entirety of the script, but it is most of it. I left out the simpler bits and commented everything in order to make the logic easier to follow.

NOTE: This, and most other code, is orders of magnitude easier to read with proper syntax highlighting. Do yourself a favor and take advantage of it, even if you're using vim.

Code:
use constant {
    DAGGER => 9997,
        SHARPENED_DAGGER => 59950,
    SHORT_SWORD => 9998,
        SHARPENED_SHORT_SWORD => 59951,
    CLUB => 9999,
        POLISHED_CLUB => 59925,
    DULL_AXE => 55623,
        SHARPENED_AXE => 55623,
    CHUNK_OF_BRONZE => 54229,
        BRONZE_GLOOMINGDEEP_DAGGER => 54230,
        BRONZE_GLOOMINGDEEP_SWORD => 54231,
        BRONZE_GLOOMINGDEEP_MACE => 54232,
        BRONZE_GLOOMINGDEEP_AXE => 54233,
    CHUNK_OF_IRON => 59954,
        IRON_GLOOMINGDEEP_DAGGER => 54235,
        IRON_GLOOMINGDEEP_SWORD => 54236,
        IRON_GLOOMINGDEEP_MACE => 54237,
        IRON_GLOOMINGDEEP_AXE => 54238
};

# works like quest::summonitem(quest::chooserandom())
my $summon_from = sub {
    # accepts array or array ref as pool to select randomly from
    my @pool = ( ref $_[0] ) =~ /array/i ? @{ +shift } : @_;
    quest::summonitem( $pool[ int ( rand ( scalar @pool ) ) ] );
    # required because summonitem method returns nothing
    return 1;
};

# select item from pool based on player class and turn-in material value
my $forge_weapon = sub {
    my ( $class, $value ) = @_;
    # ! WARNING: see warning below about short circuiting ...
    # iterate over anon hash (dispatch table)
    while ( my ( $archetype, $reward_pool ) = each {
         # key ($archetype) is a simple regex to match against $class
        'warr|rang|shad|bard|rogu' => [
            # val 0 ($reward_pool->[0]) is reward list for bronze chunk
            [BRONZE_GLOOMINGDEEP_DAGGER..BRONZE_GLOOMINGDEEP_MACE],
            # val 1 ($reward_pool->[1]) is reward list for iron chunk
            [IRON_GLOOMINGDEEP_DAGGER..IRON_GLOOMINGDEEP_MACE],
        ],
        'cler|drui|monk|sham' => [
            [BRONZE_GLOOMINGDEEP_MACE],
            [IRON_GLOOMINGDEEP_MACE],
        ],
        'necr|wiza|magi|ench' => [
            [BRONZE_GLOOMINGDEEP_DAGGER],
            [IRON_GLOOMINGDEEP_DAGGER],
        ],
        'pala' => [
            [BRONZE_GLOOMINGDEEP_SWORD, BRONZE_GLOOMINGDEEP_MACE],
            [IRON_GLOOMINGDEEP_SWORD, IRON_GLOOMINGDEEP_MACE],
        ],
        'beas' => [
            [BRONZE_GLOOMINGDEEP_DAGGER, BRONZE_GLOOMINGDEEP_MACE],
            [IRON_GLOOMINGDEEP_DAGGER, IRON_GLOOMINGDEEP_MACE],
        ],
        'berz' => [
            [BRONZE_GLOOMINGDEEP_AXE],
            [IRON_GLOOMINGDEEP_AXE],
        ]
    # returns on first archetype match and successful item summon
    } ) { return 1 if $class =~ /$archetype/i && $summon_from->( $reward_pool->[$value] ) }
}

# grouping stuff this way helps with abstraction
my $forged_weapon_for = sub {
    # these variables control everything
    my ( $class, $material ) = @_;
    my $value = ( $material == CHUNK_OF_IRON );
    # single-line, dynamic quest::say example
    quest::say("Now let me see... Ah ha! Here ya go! ".(
      # ternary op controls which additional text is used
      $value
        # first is for chunk of iron turnin
        ? "A spiffy, new weapon to aid you in your adventures!"
        # second is for chunk of bronze turnin
        : "A much better weapon to help fend off those nasties!"
    ));
    # call dispatch table for weapon forging
    return $forge_weapon->($class, $value);
};

# everything in the event is clearly defined elsewhere in the script
# this makes it easier to have an overview of what the event does
sub EVENT_ITEM {
    # ! WARNING: make sure you have a path to short circuit ...
    # we define a list of trigger => responses pairs here
    while ( my ($condition_met, $action_taken) = each {
        # scenario group: improve existing weapon
        $accepted_broken->(DAGGER)      => $returned_repaired->(SHARPENED_DAGGER),
        $accepted_broken->(SHORT_SWORD) => $returned_repaired->(SHARPENED_SHORT_SWORD),
        $accepted_broken->(CLUB)        => $returned_repaired->(POLISHED_CLUB),
        $accepted_broken->(DULL_AXE)    => $returned_repaired->(SHARPENED_AXE),
        # scenario group: forge new weapon
        $accepted_metal->(CHUNK_OF_BRONZE) => $forged_weapon_for->($class, CHUNK_OF_BRONZE),
        $accepted_metal->(CHUNK_OF_IRON)   => $forged_weapon_for->($class, CHUNK_OF_IRON)
    # short circuit on first instance of condition_met AND return of 1 from action_taken
    } ) { last if $condition_met && $action_taken } # ! ... or loop forever!
    # return what we didn't use
    $return_unused_stuff;
}
__________________
I muck about @ The Forge.
say(rand 99>49?'try '.('0x'.join '',map{unpack 'H*',chr rand 256}1..2):'incoherent nonsense')while our $Noport=1;
Reply With Quote
 


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 01:03 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