Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

Search what mobs drop item, by item name.

Legendary Battlemage
Joined
Jan 23, 2013
Messages
695
Reaction score
101
Probably not a really useful release for most of you, because most of you either, already have it or better, or can't figure it out and won't be able to work this out either.


NPCConversationManager.java
Code:
public void getItemByName(String itemname) {        MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
        List <Integer> itemId = ii.getItemIdFromName(itemname);
        System.out.println(" Array Size is " + itemId.size());
        String text = "Please Select Your Item: \r\n";
        for (int i = 0; i < itemId.size(); i++) {
        text += "#L" + itemId.get(i) + "##i" + itemId.get(i) + "# - " + ii.getName(itemId.get(i)) + "\r\n";
        }   
       sendSimple(text);   
    }
    public void getMobs(int itemid) {
       MapleMonsterInformationProvider mi = MapleMonsterInformationProvider.getInstance();
       final List<Integer> mobs = MapleMonsterInformationProvider.getInstance().getMobByItem(itemid);
       String text = "The following mobs drop your item: \r\n";
       for (int i = 0; i < mobs.size(); i++) {
           int quest = 0;
           if (mi.getDropQuest(mobs.get(i)) > 0) {
            quest = mi.getDropQuest(mobs.get(i));
           }
        int chance = mi.getDropChance(mobs.get(i)) * getClient().getChannelServer().getDropRate();
        text += "#o" + mobs.get(i) +"# - "  + (Integer.valueOf(chance >= 999999 ? 1000000 : chance).doubleValue() / 10000.0) + "%. " + (quest > 0 && MapleQuest.getInstance(quest).getName().length() > 0 ? ("Requires quest " + MapleQuest.getInstance(quest).getName() + " to be started.") : "") + "\r\n";
    }
       sendNext(text);
        }

MapleMonsterInformationProvider.java
Code:
public int getDropQuest(int monsterId) {        PreparedStatement ps = null;
        ResultSet rs = null;
        int quest = 0;
        try {
            ps = DatabaseConnection.getConnection().prepareStatement("SELECT questid FROM drop_data where dropperid = ?");
            ps.setInt(1, monsterId);
            rs = ps.executeQuery();
            while (rs.next()) {
                quest = rs.getInt("questid");
            }
        } catch (SQLException e) {
            
        }
        return quest;
    }
    
    public int getDropChance(int monsterId) {
        PreparedStatement ps = null;
        ResultSet rs = null;
        int chance = 0;
        try {
            ps = DatabaseConnection.getConnection().prepareStatement("SELECT chance FROM drop_data where dropperid = ?");
            ps.setInt(1, monsterId);
            rs = ps.executeQuery();
            while (rs.next()) {
                chance = rs.getInt("chance");
            }
        } catch (SQLException e) {
            
        }
        return chance;
    }
   public List<Integer> getMobByItem(final int itemId) {
       final List<Integer> mobs = new LinkedList<Integer>() {};
       PreparedStatement ps = null;
       ResultSet rs = null;
       try {
           ps = DatabaseConnection.getConnection().prepareStatement("SELECT * FROM drop_data WHERE itemid = ?");
           ps.setInt(1, itemId);
           rs = ps.executeQuery();
           int mobid;
           while (rs.next()) {
               mobid = rs.getInt("dropperid");
               if (!mobs.contains(mobid))
               mobs.add(mobid);
           }
       } catch (SQLException e) {
           e.printStackTrace();
           } finally {
            try {
                if (ps != null) {
                    ps.close();
                }
                if (rs != null) {
                    rs.close();
                }
            } catch (SQLException ignore) {
                return null;
            }
       }
       return mobs;
   }

Please note: I did it this way (seperated it all) for testing only, and never went ahead and fixed it. Array size is still printed!
MapleItemInformationProvider.java
Code:
 public List<Integer> getItemIdFromName(String name) {            List <Integer> itemReturn = new LinkedList <Integer> ();
            MapleDataProvider dataProvider = MapleDataProviderFactory.getDataProvider(new File ("wz/String.wz"));
            MapleData data = dataProvider.getData(("items.img"));
           List<Pair<Integer, String>> itemPairList = new LinkedList<Pair<Integer, String>>();
           for  (MapleData itemIdData : data.getChildren()) {
            int itemIdFromData = Integer.parseInt(itemIdData.getName());
            String itemNameFromData = MapleDataTool.getString(itemIdData.getChildByPath("name"), "NO-NAME");
            itemPairList.add(new Pair<Integer, String> (itemIdFromData, itemNameFromData));
           }
           for (Pair<Integer, String> itemPair : itemPairList) {
               if (itemPair.getRight().toLowerCase().contains(name.toLowerCase()) && itemPair.getLeft() > 0) {
                   if (getItemData(itemPair.getLeft()) != null) 
                   itemReturn.add(itemPair.getLeft());
               }
           }
           return itemReturn;
        }

you must create an xml file called items.xml, and populate the data yourself (copy the values from etc, eqp, and consume..don't duck up!)
Also, in most tetra based sources you will have to fix equip loading for them to show up. Hint, it's in getItemData.

If you want screenshots I will supply them, shouldn't be necessary however.

Edit:
Decided I'd add the NPC script in as well, for those who're confused. I'll add screenshots later.

Code:
var status = -1;var item = false;
var map = false;
function start() {
    cm.sendSimple("Please choose which method you would like. \r\n#L0#Search by item name#l\r\n#L1#Search mobs on map#l");
 
}
function action(mode, type, selection) {
    status++;
    if (mode != 1) {
    cm.dispose();
    return;
    }
    if (!item && !map) 
        if (selection == 0)
            item = true;    
        else if (selection == 1)
            map = true;
        if (item)
        items(selection);
        else if (map)
        maps(selection);
    function items(selection) {
    if (status == 0) {
    cm.sendGetText("Please type the name of the item you wish to search for:");
    } else if (status == 1) {
    cm.getItemByName(cm.getText());
    } else if (status == 2) {
    cm.getMobs(selection);
    cm.dispose();
        }    
    }


    function maps(selection){
        if (status == 0) {
    if (cm.getMap().getAllMonstersThreadsafe().size() <= 0) {
        cm.sendOk("There are no monsters in this map.");
        cm.dispose();
        return;
    }
    var selStr = "Select which monster you wish to check.\r\n\r\n#b";
    var iz = cm.getMap().getAllUniqueMonsters().iterator();
    while (iz.hasNext()) {
        var zz = iz.next();
        selStr += "#L" + zz + "##o" + zz + "##l\r\n";
    } 
    cm.sendSimple(selStr);
    } else if (status == 1) {
    cm.sendNext(cm.checkDrop(selection));
    cm.dispose();
        }
    }
}

Oh, that also includes the original checkdrop method included with tetrasea.


Here's the screenshots I promised a while ago.

1Ku34iS - Search what mobs drop item, by item name. - RaGEZONE Forums

C7RHQy - Search what mobs drop item, by item name. - RaGEZONE Forums

hXkU3aQ - Search what mobs drop item, by item name. - RaGEZONE Forums


Note they don't show that a quest is required, because they're ilbis..I can assure you that does work.
 

Attachments

You must be registered for see attachments list
Last edited:
Newbie Spellweaver
Joined
Apr 15, 2010
Messages
33
Reaction score
80
This release got me hot and bothered the first time I saw it. I've been frequently relieving my sexual tension to this release every night since :wink:. Thank you for this wonderful release... of my bodily fluids.
 
Elite Diviner
Joined
Mar 24, 2015
Messages
426
Reaction score
416
Nice stuff! The only thing I really have to say is: I feel like this should be a command rather.
Unless...you do something really cool with it and say, make a new npc "Wiz's Monster Drop Book" which is used to look this up. That way it would even fit in an old maple context. Players wouldn't be spoiled as they have to make their way to the library first to look up a drop.
Edit: Naturally, players should only be able to access this feature if they have completed all of Wiz's quests.
 
Legendary Battlemage
Joined
Jan 23, 2013
Messages
695
Reaction score
101
Nice stuff! The only thing I really have to say is: I feel like this should be a command rather.
Unless...you do something really cool with it and say, make a new npc "Wiz's Monster Drop Book" which is used to look this up. That way it would even fit in an old maple context. Players wouldn't be spoiled as they have to make their way to the library first to look up a drop.
Edit: Naturally, players should only be able to access this feature if they have completed all of Wiz's quests.
That is actually a pretty impressive way to look at it. You could simply copy nexon's method of releasing drop data as you collect monsterbooks and add that to the system. If you were to do something like that I would definitely be interested in seeing your progress!


As it stands now, it does access the database far too often; caching it at server loading would be a better method, but beyond me. I'm sure zygon or fraysa, maybe even kevin would be capable of this, but I definitely do agree with your idea. In fact, implementing monster book levels would be rather easy to do.
 
Elite Diviner
Joined
Mar 24, 2015
Messages
426
Reaction score
416
That is actually a pretty impressive way to look at it. You could simply copy nexon's method of releasing drop data as you collect monsterbooks and add that to the system. If you were to do something like that I would definitely be interested in seeing your progress!


As it stands now, it does access the database far too often; caching it at server loading would be a better method, but beyond me. I'm sure zygon or fraysa, maybe even kevin would be capable of this, but I definitely do agree with your idea. In fact, implementing monster book levels would be rather easy to do.

If you mean the monster book from earlier versions (each level gives you more data on the mob): Actually, monster book is already fixed in moopledev. Most of it is client-sided so any moople based server has no excuse to not have this. The only thing missing from the actual source is that mobs drop their cards.
 
Legendary Battlemage
Joined
Jan 23, 2013
Messages
695
Reaction score
101
If you mean the monster book from earlier versions (each level gives you more data on the mob): Actually, monster book is already fixed in moopledev. Most of it is client-sided so any moople based server has no excuse to not have this. The only thing missing from the actual source is that mobs drop their cards.

Yeah that's what I meant. But you could do this with any version.

Of course to have properly loading drop chances on anything pre-moople you would need to rework drops loading, and switch it to drop_data which is gmslike (chance 1000000 = 100%, though I'm pretty sure GMS had an 8 digit or 9 digit chance rate..)
 
Junior Spellweaver
Joined
Sep 11, 2014
Messages
181
Reaction score
76
A few suggestions:

All this should definitely be cached.

SELECT dropperid FROM drop_data WHERE itemid = ? GROUP BY dropperid
That will stop you from doing the if it contains the dropperid.

You don't need this check: mi.getDropQuest(mobs.get(i)) > 0
 
Legendary Battlemage
Joined
Jan 23, 2013
Messages
695
Reaction score
101
Yeah I know. And thank you for the tip; that was something I didn't know. I am not all too familiar with sql.


As for mi.getDropQuest(mobs.get(i)) > 0; why wouldn't I need that? I mean, I could eliminate the check by adding it into the ternary, but I don't want to give myself more of a headache. I figured it was just easier, and not very sacrificial, to add that check.
 
Junior Spellweaver
Joined
Sep 11, 2014
Messages
181
Reaction score
76
(quest > 0 && MapleQuest.getInstance(quest).getName().length() > 0 ?
("Requires quest " + MapleQuest.getInstance(quest).getName() + " to be started.") : "")

Consider quest to = 0. Then it will say "".
Consider quest to > 0, then it will say "Requires quest ..."

quest = mi.getDropQuest(mobs.get(i));

It's because you set the default of quest to 0 and also mi.getDropQuest returns 0 by default so if it doesn't exist then it's set to 0. The check is redundant.

I also just realized that the find chance of drop is not correct.

Consider the following example:
Orange Mushroom drops ilbis. There's 20 rows of the database due to someone failing at insertion, each at a 5% rate. The current code will give 5% rate, but in actuality when drops are processed, it will drop at a 100% rate.

This query should give you a ResultSet of both the dropperid and the (total) chance of drop:
SELECT dropperid, sum(chance) FROM drop_data WHERE itemid = ? GROUP BY dropperid
Untested, but it's something like this. The #oMonsterID # is pretty interesting as didn't know about that one. I guess you wouldn't have to select from 2 tables to associate dropper name with the chance now.
 
Legendary Battlemage
Joined
Jan 23, 2013
Messages
695
Reaction score
101
(quest > 0 && MapleQuest.getInstance(quest).getName().length() > 0 ?
("Requires quest " + MapleQuest.getInstance(quest).getName() + " to be started.") : "")

Consider quest to = 0. Then it will say "".
Consider quest to > 0, then it will say "Requires quest ..."

quest = mi.getDropQuest(mobs.get(i));

It's because you set the default of quest to 0 and also mi.getDropQuest returns 0 by default so if it doesn't exist then it's set to 0. The check is redundant.

I also just realized that the find chance of drop is not correct.

Consider the following example:
Orange Mushroom drops ilbis. There's 20 rows of the database due to someone failing at insertion, each at a 5% rate. The current code will give 5% rate, but in actuality when drops are processed, it will drop at a 100% rate.

This query should give you a ResultSet of both the dropperid and the (total) chance of drop:
SELECT dropperid, sum(chance) FROM drop_data WHERE itemid = ? GROUP BY dropperid
Untested, but it's something like this. The #oMonsterID # is pretty interesting as didn't know about that one. I guess you wouldn't have to select from 2 tables to associate dropper name with the chance now.

I have to say that is incorrect, at least from what I have noticed. The function puts it in a list; so if it is in their multiple times it returns twice. Snail Shells are an example of this, let me get you a screenshot I'm starting the server right now.


Syre - Search what mobs drop item, by item name. - RaGEZONE Forums


There's the screenshot for snail shells.


Upon re-reading your post I think I see what you mean. You're wrong, and right, at the same time.

20 * 5 = 100; this is true, but 20 5% chances does not mean you have a 100% chance. Probability does not work that way.

As far as I understand it; I am not at all advanced in probability mathematics, but I'll give it a shot.


While each consecutive entry does increase the chance an ilbi will drop; it also decreases the chance the others will drop. So if every entry is at 5%, (5/100, or .05), and you have 20 of them, you would be doing .05 * .05 20 times(19 times?); thus decreasing the drop chance in entirety. I could be wrong; it may increase the drop chance, however, it won't increase it by much.

E.g. having it in there twice, instead of 20 times, at 5%, would mean the overall chance is .05 * .05, which is .0025 (2.5%), of course, that is if they are completely independent drops. I don't pretend to know everything about the drop system in our sources.

If it works this way;

Calculate chance of dropping ilbi1 = fail (5%, no good); overall drop count drops by 1 (lets say there's 20 total?)
chance of dropping ilbi2 is now 5/19 instead of 5/20. Of course I highly HIGHLY doubt it works this way; drops are not calculated by total number of drops the mob has.
 
Last edited:
Junior Spellweaver
Joined
Sep 11, 2014
Messages
181
Reaction score
76
Yeah it returns twice, but how it actually works in the game is that it would drop at a 12% rate
 
Junior Spellweaver
Joined
Sep 11, 2014
Messages
181
Reaction score
76
Whoops, you're right about that. I forgot the drop chances were calculated independently. Anyhow, looks like the base drop code needs some work then.

An increase of drops does not affect the other drops though.
Let's say an item drops at 5% for 20 lines. The code will do this:
for each drop rate in the database:
1. Make a random number from 0-999999 inclusive
2. If the number < the probability, add that item to the drop list

So basically 20 lines of 5% will not equal 100%. However the chance that the item drops at least once in the session is 1-0.05^20. Basically drop_data should be redone because with this code seems like snail shells can drop twice... I'd have to reread the code to make sure. I haven't touched this in too long. Basically when you extract drop rates in the database it should probably do something like the query that I put above, grouping drop rate for item and selecting a list of drops and chances for a mob. That's still not right because area bosses and bosses drop multiple etc and use items that are the same, but it will be more accurate than having some mobs drop 2 of the same item when they shouldn't.
 
Legendary Battlemage
Joined
Jan 23, 2013
Messages
695
Reaction score
101
Whoops, you're right about that. I forgot the drop chances were calculated independently. Anyhow, looks like the base drop code needs some work then.

An increase of drops does not affect the other drops though.
Let's say an item drops at 5% for 20 lines. The code will do this:
for each drop rate in the database:
1. Make a random number from 0-999999 inclusive
2. If the number < the probability, add that item to the drop list

So basically 20 lines of 5% will not equal 100%. However the chance that the item drops at least once in the session is 1-0.05^20. Basically drop_data should be redone because with this code seems like snail shells can drop twice... I'd have to reread the code to make sure. I haven't touched this in too long. Basically when you extract drop rates in the database it should probably do something like the query that I put above, grouping drop rate for item and selecting a list of drops and chances for a mob. That's still not right because area bosses and bosses drop multiple etc and use items that are the same, but it will be more accurate than having some mobs drop 2 of the same item when they shouldn't.


it may seem like that, but that is easy enough to fix; simply add a check for the itemid.


With that said, a couple changes need to be made to this function.

You can do it in either NPCConversationManager.java, or in the NPC script.

for one; a check for getText() == "" (or null? is it like that?) needs to be done.
for two; a check to make sure the returned data is not empty needs to be done.
 
Back
Top