PDA

View Full Version : Randomize Loot drops


Furinex
10-28-2012, 03:40 PM
Is there a way to randomize loot among mobs other than the D2Loot tool, which right now is out of commission for this revision as of right now. Im trying to get it so any mob has a chance of dropping any item. Is there some simple query I could run to add all items to the loot tables of every mob?

Edit: I also don't care about no drop status or required levels since all these restrictions will be removed.

c0ncrete
10-28-2012, 11:39 PM
it's not exactly 'simple', but you can add random loot to mobs via perl scripting without touching the original loot tables or the database at all.

example: i've got mine set up for a small chance at a single extra item (not visible to player - npc does not equip item) based on the npc's level. it's limited to npcs with existing loot tables (also controlled via script). the player gets a message indicating something is special about the encounter when they initially engage an npc with extra loot, and if the kill is trivial, the loot gets removed (the player gets another message). i had to make a slight source code modification to allow for the removal of loot before the corpse was created and a python script to automatically add the required lines in every single existing npc script, but it was well worth it.

Maze_EQ
10-29-2012, 12:38 AM
I'd write the query for you, but that's like giving a man a fish.

c0ncrete
10-29-2012, 01:00 AM
I'd write the query for you, but that's like giving a man a fish.

... says the guy using open source software he didn't write.

c0ncrete
10-29-2012, 02:06 AM
this is a trimmed down version of the plugin i use to give a random item to an npc.

#!/usr/bin/perl

# select a random itemID and give to npc
# returns itemID added
sub GetRandomItem {

# defult itemid
my $itemID = 0;

# get npc object from calling script
my $npc = plugin::val('$npc');

# bail if npc has no loot table
if ( !$npc->GetLoottableID() ) {
return 0;
}

# bail if missed chance for extra item
# assuming mob level tops at 80, this should max our chance @ 10%
if ( rand(100) > $npc->GetLevel() * .1 + .2 )
{
return 0;
}

# find valid item id to give to npc (attempts until it gets an item name)
# 1001 is min and 132476 is max itemID in database at time of writing
my $itemName = 0;
until ($itemName) {
$itemID = int( rand(131475) + 1001 );
$itemName = quest::getItemName($itemID);
}

# have npc equip item, where possible
$npc->AddItem( $itemID, 1, 1 );
$npc->Heal();

return $itemID;

}

1;


this is a trimmed version of the python script i used to modify all of the existing script files. as it stands, it is set up to run from a folder i use to keep up to date with the latest svn located in the EQEmu folder along with the running Quests directory. it adds EVENT_COMBAT to all existing npc scripts where needed (which is where the loot is added), and simply modifies the event if it already exists.

import os, sys

written = 0
modified = 0

zone = ''
script = ''

def getScriptList(zone):
script = []
for entry in os.listdir(zone):
if os.path.isdir(entry):
continue
script.append(entry)
return script

def modEventCombat(content):
# modifying or adding EVENT_COMBAT
found = 0
start = 0
for idx, val in enumerate(content):
if found:
break
if val.find('EVENT_COMBAT') > -1:
found = 1
start = idx
if val.find('{') == -1:
start = start+1
break
if found == 1:
content.insert(start+1, '\tif($combat_state) { plugin::GetRandomItem(); }\n')
else:
content.insert(0, 'sub EVENT_COMBAT\n{\n\tif($combat_state) { plugin::GetRandomItem(); }\n\n')

def parseScript(script):
global modified, written
try:
if(os.path.getmtime(script) < os.path.getmtime('..\\Quests\\' + script)):
return
except WindowsError:
pass
content = open(script).readlines()
if os.path.split(script)[-1] not in ('player.pl'):
modified = modified +1
modEventDeath(content)
modEventCombat(content)
modEventItem(content)
# writing new version of script to file
print 'WRITING: ..\\Quests\\%s' % script
written = written +1
script = open('..\\Quests\\' + script, 'w')
script.writelines(content)
script.close()

for entry in os.listdir('.'):
if not os.path.isdir(entry):
print 'SKIPPING: %s [not a directory]' % entry
continue
if entry[0] == '.':
print 'SKIPPING: %s [hidden directory]' % entry
continue
if entry in ('items', 'plugins', 'spells'):
print 'SKIPPING: %s [excluded directory]' % entry
continue
zone = entry
newz = os.path.join('..\\Quests', zone)
try:
os.stat(newz)
except:
os.mkdir(newz)
print 'CURRENT ZONE: %s' % zone
for script in getScriptList(zone):
parseScript(os.path.join(zone, script))

print
print 'modified: %d' % modified
print 'written : %d' % written

Ruyenloresearcher
05-02-2013, 11:35 PM
I have been trying to add in a extra chance of random loot and my last thing I tried ended up in disaster. But now the back up files are loaded I ran across this thread and it was a bit more tailored for what I was interested in.

The first part I got done, made a plugin GetRandomLoot but I am having problems with the Python script. I have Python 2.7 and been getting invalid syntax.

python additem.py
SKIPPING: .keep [not a directory]
SKIPPING: .svn [hidden directory]
CURRENT ZONE: abysmal
Traceback (most recent call last):
File "additem.py", line 73, in <module>
parseScript(os.path.join(zone, script))
File "additem.py", line 45, in parseScript
modEventDeath(content)
NameError: global name 'modEventDeath' is not defined

That is what I get when the bottom Script is ran. Hmmmmm, trying to make heads or tails of code is tough this late at night. Maybe in the morning it will be a bit clearer.

Any clue to point me in the right direction would be much obliged.

I really want to thank you c0ncrete and all the others that post so many examples of code to help us nonprogrammers. I have been trying to pick up some now and then (I can do Hello World in Python) but hard to with family and work taking up much time.

Ruyen

Ruyenloresearcher
05-03-2013, 02:18 PM
Think I got it figured out. Good night's sleep helps.