|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Quests::Custom Custom Quests here |
|
|
|
01-27-2013, 10:04 AM
|
|
Dragon
|
|
Join Date: Dec 2009
Posts: 719
|
|
random loot, the easy way
i finally got around to using the new global_npc.pl script
it makes loot randomization so much easier...
this small snippet
- doesn't make changes to default loot chances
- only gives npcs with existing loot tables are given an extra item
(so untargetable, invisible npcs won't turn into floating weapons)
- verifies itemid is valid via temporary itemlink creation
EQEmu\quests\templates\global_npc.pl
Code:
sub EVENT_SPAWN {
return unless $npc->GetLoottableID();
my ($tested, $itemid);
do {
$itemid = ( int rand 131474 ) + 1001;
$tested = quest::varlink($itemid);
} while $tested =~ /INVALID/;
$npc->AddItem($itemid);
}
- can easily be expanded upon
examples:
filter specific items from roll
destroy extra item under certain conditions
roll for chance at extra item
additional random items
NOTE: you'll want to change the number from 131474 to whatever the highest itemid is in your items table and subtract 1001 (or your lowest itemid) from that number.
__________________
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;
|
|
|
|
01-27-2013, 11:21 AM
|
|
Developer
|
|
Join Date: Nov 2012
Location: Halas
Posts: 355
|
|
Hah that is awesome!
__________________
Drajor regards you indifferently -- what would you like your tombstone to say?
|
01-27-2013, 12:01 PM
|
|
Dragon
|
|
Join Date: Dec 2009
Posts: 719
|
|
glad you like it. i've added all sorts of bells and whistles to this on my test server. trivial encounter check, filtering based on item usability by encounter participants and/or an arbitrary never-drop list, minimum base chance and additional chance scaled by npc level, etc.
my previous method required that you modify every existing npc quest script you wanted to apply random loot to. needless to say, the recent addition of global_npc simplified things a great deal. thanks, akkadius!
__________________
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;
|
|
|
|
01-28-2013, 06:44 PM
|
|
Dragon
|
|
Join Date: Dec 2009
Posts: 719
|
|
intentional complications
using something very close to this to verify that the npc can equip the item in question before the call to $npc->AddItem(). read: no more augfists, yay!
it can be modified for use as an additional validation step while picking the random item (filtering out items that are not usable by an participant in the encounter, for example).
this was fun! (no sarcasm)
Code:
use 5.012;
no strict 'vars';
use constant {
MIN_ITEMID => 1001,
MAX_ITEMID => 132475,
};
# class patterns used to build regular expressions for bit values
my $war = '1|war(?:rior)?';
my $clr = '2|cl(?:eric|r)';
my $pal = '3|pal(?:adin)';
my $rng = '4|r(?:anger|ng)';
my $shd = '5|sh(?:adowknight|d)';
my $dru = '6|dru(?:id)?';
my $mnk = '7|m(?:o)?nk';
my $brd = '8|b(?:a)?rd';
my $rog = '9|rog(?:ue)?';
my $shm = '10|sh(?:aman|m)';
my $nec = '11|nec(?:romancer)?';
my $wiz = '12|wiz(?:ard)?';
my $mag = '13|mag(?:ician)?';
my $enc = '14|enc(?:hanter)?';
my $bst = '15|b(?:eastlord|st)';
my $ber = '16|ber(?:serker)?';
# race patterns used to build regular expressions for bit values
my $hum = '1|hum(?:an)?';
my $bar = '2|bar(?:barian)?';
my $eru = '3|eru(?:dite)?';
my $elf = '4|(?:wood )?elf';
my $hie = '5|hi(?:gh elf|e)';
my $def = '6|d(?:ark elf|ef)';
my $hel = '7|h(?:alf-elf|el)';
my $dwf = '8|dw(?:ar)?f';
my $trl = '9|tr(?:ol)?l';
my $ogr = '10|ogr(?:e)?';
my $hlf = '11|h(?:alfling|lf)';
my $gnm = '12|gn(?:ome|m)';
my $iks = '128|iks(?:ar)?';
my $vah = '130|vah(?: shir)?';
my $frg = '330|fr(?:oglok|g)';
my $drk = '522|dr(?:akkin|k)';
# get bit value for any playable race/class you pass it
# works with numeric values, abbreviations, and full spellings
sub GetBitFor {
my $bit = {
1 => qr/^$war|$hum$/i,
2 => qr/^$clr|$bar$/i,
4 => qr/^$pal|$eru$/i,
8 => qr/^$rng|$elf$/i,
16 => qr/^$shd|$hie$/i,
32 => qr/^$dru|$def$/i,
64 => qr/^$mnk|$hel$/i,
128 => qr/^$brd|$dwf$/i,
256 => qr/^$rog|$trl$/i,
512 => qr/^$shm|$ogr$/i,
1024 => qr/^$nec|$hlf$/i,
2048 => qr/^$wiz|$gnm$/i,
4096 => qr/^$mag|$iks$/i,
8192 => qr/^$enc|$vah$/i,
16384 => qr/^$bst|$frg$/i,
32768 => qr/^$ber|$drk$/i,
};
my $for = shift;
while ( my ( $key, $val ) = each %$bit ) {
return $key if $for ~~ $val;
}
return 0;
}
sub CanEquip {
# itemid to check
my $itemid = shift;
# coderef for $npc->GetItemStat()
my $GISref = sub { $npc->GetItemStat(@_) };
# list of tests we want to do, in order of importance
# 1. is itemid within valid range?
# 2. is itemid tied to a valid item (some id number gaps exist)?
# 3. is itemid able to be equipped at all?
# 4. is itemid not an aug?
# 5. is itemid not deity specific?
# 6. is itemid's required level less than or equal to my level?
# 7. is itemid's class restriction compatible with my class?
# 8. is itemid's race restriction compatible with my class?
my $test = [
sub { shift ~~ [ MIN_ITEMID .. MAX_ITEMID ] },
sub { quest::varlink(shift) !~ /INVALID/ },
sub { $GISref->( shift, "slots" ) },
sub { !$GISref->( shift, "augtype" ) },
sub { !$GISref->( shift, "deity" ) },
sub { $GISref->( shift, "reqlevel" ) <= $mlevel },
sub { $GISref->( shift, "classes" ) & GetBitFor( $npc->GetClass() ) },
sub { $GISref->( shift, "races" ) & GetBitFor( $npc->GetRace() ) },
];
# run through tests, stopping at first failure
foreach (@$test) {
return 0 unless $_->($itemid);
}
# passed all tests
return 1;
}
__________________
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;
Last edited by c0ncrete; 01-28-2013 at 06:45 PM..
Reason: grammatical failure
|
|
|
|
01-29-2013, 04:21 PM
|
Hill Giant
|
|
Join Date: Jul 2012
Posts: 212
|
|
I've never played on such a server, so I wonder why one would ever fight tough mobs when there are rats in the newbie area potentially dropping end-game gear. (I'm not saying that is necessarily a bad thing, I just wonder how things would play out)
|
|
|
|
01-29-2013, 05:39 PM
|
|
Dragon
|
|
Join Date: Dec 2009
Posts: 719
|
|
some people just like the idea of random loot. the initial snippet was to give those people something to play with. technically speaking, most servers don't actually employ randomization, they simply scramble the drops in the database. they're still static that way. the misnomer is a pet peeve of mine.
as for your concerns, i had them as well. i'm working on implementing ways to determine if the encounter was trivial and remove the extra item. i'm also looking into filtering out loot based on the required level of the item. so the npc won't get something outside of its level range.
my objective on my personal server is for there to only be a very small chance of the extra item, which scales up a tiny bit with npc difficulty (starting at level 11), so the extra item won't be something that is a common occurrence to begin with.
finally, i'm considering giving the npcs in these rare instances abnormal abilities, so as to make things more of a challenge, given the extra bounty.
the devil is in the details ...
__________________
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;
|
|
|
|
01-29-2013, 07:53 PM
|
|
Dragon
|
|
Join Date: Dec 2009
Posts: 719
|
|
yow. the original won't work as posted because of the way quest::varlink() works. if you call it without a client as the initiator, the zone will crash. i was testing the functionality via EVENT_SAY, so it worked without issue.
compiling a minor source modification to see if it takes care of the crash without altering the functionality of quest::varlink() now. it'll just return an empty string if there is no client initiator, but only after it validates the itemid passed to it.
__________________
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;
|
01-29-2013, 09:24 PM
|
|
Dragon
|
|
Join Date: Dec 2009
Posts: 719
|
|
applying the source change found here and changing
Code:
while $tested =~ /INVALID/
to
Code:
while $tested =~ /INVALID ITEM/
resolved the issue.
__________________
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;
|
01-30-2013, 12:48 PM
|
Hill Giant
|
|
Join Date: Jul 2012
Posts: 212
|
|
I can see the attraction of an occasional random item (random rewards are more effective psychologically, think Pavlov did some work on this). I'd actually like to play on such a server to check it out.
If I were doing such a thing, I would create a singleton on the server that built a list of items by level. Then have it select something from a requested range through a new Perl call. (I know you weren't asking for suggestions, but I thought I'd throw that out there. It might inspire someone).
Edit: I just realized that this would be a good candidate for the shared memory region. No need to replicate the table across zones.
|
01-30-2013, 01:04 PM
|
|
Dragon
|
|
Join Date: Dec 2009
Posts: 719
|
|
no worries. suggestions are always appreciated. i've got plenty of ideas, just not enough skill to do anything other than hack them together with perl and my limited knowledge of c++.
__________________
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;
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -4. The time now is 08:17 PM.
|
|
|
|
|
|
|
|
|
|
|
|
|