• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!

Item Drop System v 1.1.0.1

  • Like
Reactions: TheGoldenGoblin
this is an item drop system for units.
u can give the units there own specific item drop table. and u can give units of the same unit type there own item drop.
this is entirely based on a weighted system

This system is GUI friendly as it will only require some basic knowledge with custom scripts.
If you have any questions on how to use this please ask and I will be glad to help you out.

i made an item drop system that will create a chance of a drop for items when a unit dies. very easy to add items to a table of items that a unit can drop. no more dealing with making an item Table for a unit.
plz tell me if theres anything i should add to this or anything to improve.

here is the system
JASS:
library UnitItemDrops /* by Deathismyfriend version 1.1.0.1

================================ Requirements =================================
               Requires JNGP 
    */uses Table, /* [url]http://www.hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/[/url] by bribe
    *      Alloc  * [url]http://www.hiveworkshop.com/forums/jass-resources-412/snippet-alloc-alternative-221493/[/url] by nestharus

*************************************************************************************
*
*   Used to easily make drop tables for item drops when unit dies.
*
************************************************************************************
*
*   Installing
*       STEP 1: Install JNGP first if you dont have JNGP.
*       STEP 2: Install Table by bribe the link is above.
*       STEP 3: Install Alloc by nestharus the link is above. You may be able to use some other alloc systems.
*       STEP 4: Copy and paste this library to your map.
*
************************************************************************************
*
*       Description
*       -----------------------
*           This is a very easy item drop system.
*           Allows for multi-Chance dropping of items w a simple method call after u call the create method.
*
*       Capabilities
*       -----------------------
*           Allows the user to easily create an item recipe.  
*               -   Easily create item tables for units that drop on percent chance. 
*               -   You can add as many items as wanted for each table for the corresponding unit type id.
*
******************************************************************************************************************************************************************************************************

/ ******************************************************************************************************************************************************************************************************
/ *
/ *     This uses a Weighted System for dropping. It does not use a percent chance drop.
/ *
/ *     CREATORS / DESTRUCTORS
/ *     ----------------------
/ *         struct ItemDropSystem extends array
/ *  
/ *             static method createForType takes integer unitTypeId returns thistype
/ *                 -   this is what you need to start an item drop table. 
/ *                 -   Below is how u add the items to the table
/ *
/ *             static method createForUnit takes unit u, boolean dropTypeTableAlso returns thistype
/ *                 -   this is used for creating item tables for specific units do not call the create function for these units.
/ *                 -   Below is how u add the items to the table
/ *                 -   If you have a table for the unit type. Made by the createForType method and 
/ *                 -   -   want both tables to drop an item set this to true.
/ *
/ *             method destroy takes nothing returns nothing
/ *                  -   to destroy an item drop table for the unit type id 
/ *
/ *
/ *     FIELDS
/ *     ------
/ *         method addItem takes integer itemId, integer weight returns nothing
/ *             -   this is how u add items to the unit drop table.
/ *             -   The weight is the chance this item will be dropped. 
/ *
/ *         method addZeroDropWeight takes integer weight returns nothing
/ *             -   this is how u add a weight for no item drops.
/ *      
/ *         static method duplicateDropTable takes integer newUnitID, boolean createForUnitNew, integer oldUnitID, boolean createForUnitOld returns thistype
/ *             -   this allows you to duplicate an item drop table u previously created. 
/ *             -   You need to tell what the old drop table was. 
/ *             -   If you used the createForUnit method in the old drop table then you set the old one to true. 
/ *             -   As for the new drop table its the same way. If u want to create it for a specific unit you set it to true.
/ *             -   Note: if you want to create it for a specific unit you need to use GetHandle( ur unit) as the integer.  
/ *     
/ *         method setDropCount takes integer multi returns nothing
/ *             -   allows you to change the multi drop. 
/ *             -   Set multidrop integer to 2 or higher for multidrop chance
/ *      
/ *         method getDropCount takes nothing returns integer
/ *             -   returns the multi drop integer that u have set.
/ *
/ *         static method getDataTable takes integer id returns thistype
/ *             - this returns the item Table so u can easily add items to the table or destroy it if u want
/ *
/ ********************************************************************************************************************************/ 
        
    globals
        private Table unitTypeTable
        private Table unitIdTable
        private TableArray itemDropTable
        private TableArray itemIdTable
    endglobals

    struct ItemDropSystem extends array
        implement Alloc
        
        private integer index
        private integer arrayI
        private integer checkPercent
        private integer weight
        private integer ttlWeight
        private integer unitTypeId
        private integer multiDrop
        private boolean specificUnit
        private boolean dropTypeTableAlso
        
        private method setValues takes nothing returns nothing
            set this.multiDrop = 1
            set this.index = 0
            set this.weight = 0
        endmethod
        
        static method createForType takes integer unitTypeId returns thistype
            local thistype this
            if unitTypeTable.has(unitTypeId) then
                return unitTypeTable[unitTypeId]
            else
                set this = thistype.allocate()
                set this.unitTypeId = unitTypeId
                set unitTypeTable[ this.unitTypeId] = this
                set this.specificUnit = false
                set this.dropTypeTableAlso = false
                call this.setValues()
            endif
            return this
        endmethod
        
        static method createForUnit takes unit u, boolean dropTypeTableAlso returns thistype
            local thistype this
            local integer id = GetHandleId( u)
            if unitIdTable.has(id) then
                return unitIdTable[id]
            else
                set this = thistype.allocate()
                set this.unitTypeId = id
                set unitIdTable[ this.unitTypeId] = this
                set this.specificUnit = true
                set this.dropTypeTableAlso = dropTypeTableAlso
                call this.setValues()
            endif
            return this
        endmethod
        
        static method duplicateDropTable takes integer newUnitID, boolean createForUnitNew, integer oldUnitID, boolean createForUnitOld returns thistype
            local thistype this = thistype.allocate()
            local thistype data 
            local integer L = 1
            local integer weight
            local integer itemId
            if createForUnitOld then
                set data = unitIdTable[ this.unitTypeId]
            else
                set data = unitTypeTable[ this.unitTypeId]
            endif
            if createForUnitNew then
                set unitIdTable[ this.unitTypeId] = this
            else
                set unitTypeTable[ this.unitTypeId] = this
            endif
            loop
                exitwhen L > data.index
                set itemId = itemIdTable[data][L]
                set itemIdTable[this][L] = itemId
                set weight = itemDropTable[data][itemId]
                set this.ttlWeight = this.ttlWeight + weight
                set itemDropTable[this][itemId] = this.ttlWeight
                set L = L + 1
            endloop
            set this.specificUnit = createForUnitNew
            call this.setValues()
            return this
        endmethod
                     
        method setDropCount takes integer multi returns nothing
            set this.multiDrop = multi
        endmethod
        
        method getDropCount takes nothing returns integer
            return this.multiDrop
        endmethod
        
        static method getDataTable takes integer id returns thistype
            if unitTypeTable.has( id) then
                return unitTypeTable[ id]
            endif
            return unitIdTable[ id]
        endmethod
        
        method addZeroDropWeight takes integer weight returns nothing
            set this.index = this.index + 1
            set this.ttlWeight = this.ttlWeight + weight
            set itemIdTable[this][index] = 100000
            set itemDropTable[this][100000] = this.ttlWeight
        endmethod
        
        method addItem takes integer itemId, integer weight returns nothing
            set this.index = this.index + 1
            set this.ttlWeight = this.ttlWeight + weight
            set itemIdTable[this][index] = itemId
            set itemDropTable[this][itemId] = this.ttlWeight
        endmethod
        
        private method dropItem takes real x, real y returns boolean
            local integer r
            local integer L = 1
            local integer L1 = 1
            local integer end = 0
            local integer array weights
            set weights[0] = 0
            if this != 0 then
                loop
                    exitwhen L > this.index
                    set weights[L] = itemDropTable[this][itemIdTable[this][L]]
                    set end = end + 1
                    set L = L + 1
                endloop
                set L = 1
                loop
                    exitwhen L > this.multiDrop
                        set r = GetRandomInt( 1, this.ttlWeight)
                        loop
                            exitwhen L1 > end
                            if r > weights[L1 - 1] and r <= weights[L1] then
                                call CreateItem( itemIdTable[this][L1], x, y)
                            endif
                            set L1 = L1 + 1
                        endloop
                    set L = L + 1
                endloop
            endif
            return this.dropTypeTableAlso
        endmethod
        
        method destroy takes nothing returns nothing
            local integer L = 0
            if this.specificUnit then
                call unitIdTable.remove( this.unitTypeId)
            else
                call unitTypeTable.remove( this.unitTypeId)
            endif
            call this.deallocate()
        endmethod
        
        private static method deathEvent takes nothing returns boolean
            local unit u = GetTriggerUnit()
            local integer id = GetUnitTypeId( u)
            local thistype this
            local real x = GetUnitX( u)
            local real y = GetUnitY( u)
            local boolean b = true
            if unitIdTable.has( GetHandleId( u)) then
                set this = unitIdTable[ GetHandleId( u)]
                set b = this.dropItem( x, y)
                call destroy()
            endif
            if unitTypeTable.has( id) and b then
                set this = unitTypeTable[ id]
                call this.dropItem( x, y)
            endif
            set u = null
            return false
        endmethod
        
        private static method onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            set unitTypeTable = Table.create()
            set unitIdTable = Table.create()
            set itemIdTable = TableArray[0x2000]
            set itemDropTable = TableArray[0x2000]
            call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_DEATH)
            call TriggerAddCondition( t, function thistype.deathEvent)
            set t = null
        endmethod
        
    endstruct

endlibrary


version 1.1.0.1
*Fixed some documentation.​
version 1.1.0.0
*Fixed major bug.​
version 1.0.7.5
*Fixed a bad bug were multiple items would be dropped when they shouldn't.​
version 1.0.7.1
*Made some small changes.
*Thanks purge​
version 1.0.7.0
*Now Removes the data stored in the hashtable if it is for a specific unit.
*Fixed some mistakes.​
version 1.0.6.8
*Now if u have a unit with a specific handle and the unit has an item table for its item type it will drop items from both item tables.​
version 1.0.6.7
*Added a method that allows the user to duplicate an item drop table that has previously been created​
version 1.0.6.5
*changed the API
*changed the addItem function to only take one item and the weight of that item
*added a getDropCount which returns the multidrop integer
*changed the create method names to make it easier to understand
*changed it over to a weight taking system instead of percents
*added a method for no item drop w weights​
version 1.0.6.0
*got rid of tsa
*Changed the system to increase speed​
version 1.0.5.3
*Added protection from op limit w TSA. ( opend to better options ?)
*Can now change or add items to an old item Table that was previously made
just call the create function u used for that unit also allows you to change the multichance w same time
*Be careful when using this as the item Table keeps the old items percent that were already stored
if percent of drops added to 100 b4 you will have to destroy then recreate the item Table​
version 1.0.5.2
*fixed a mistype which caused unwanted results​
version 1.0.5.1
*allows for up to 400 item Tables now​
version 1.0.5.0
*allows you to create item drops based on preplaced / specific units​
version 1.0.0.0
*first version released​


Keywords:
item, drop, system, item drop, drop system, item drop system, deathismyfriend, dimf, vJass, easy to use GUI, GUI friendly, GUI
Contents

System Item Drop System (Map)

Reviews
21:14, 15th Jul 2013 PurgeandFire: Changes have been made. Approved!

Moderator

M

Moderator

21:14, 15th Jul 2013
PurgeandFire: Changes have been made. Approved!
 
Here is my review:
  • In the method deathEvent, you can use "u" in GetUnitTypeId(GetTriggerUnit()).
  • Your library requirements--"Alloc" is commented out.
  • In the documentation, you have:
    JASS:
    /* struct itemDropSystem extends array */
    The "i" should be capitalized since the actual struct's first letter is capitalized.

Otherwise it looks good to me. :) There is one thing that is a personal pet peeve--"DuplicateDropTable". You capitalized the "D" in "Duplicate" even though you use camel case for all the others. That is just my own opinion though, you don't have to change it.
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
Here is my review:
  • In the method deathEvent, you can use "u" in GetUnitTypeId(GetTriggerUnit()).
  • Your library requirements--"Alloc" is commented out.
  • In the documentation, you have:
    JASS:
    /* struct itemDropSystem extends array */
    The "i" should be capitalized since the actual struct's first letter is capitalized.

i used u instead of GetTriggerUnit()
Alloc is commented out because i use it as a module but it is still needed to be downloaded to use. i commented it out to show that it is needed but just as a module.
cant believe i missed that about the I lol

Otherwise it looks good to me. :) There is one thing that is a personal pet peeve--"DuplicateDropTable". You capitalized the "D" in "Duplicate" even though you use camel case for all the others. That is just my own opinion though, you don't have to change it.

changed the case to be correct. this is what i get when i code drunk lol
 
JASS:
CreateItemPool()
ItemPoolAddItemType(Your_Pool,Item_Type,Weight)
PlaceRandomItem(Your_Pool)
The weight's are not limited to 1-100 or 0.0-1.0 but are all relative each other. The only downside to this is that there are no 'blank' items, but that can easily be created with a dummy item type that is checked for. PlaceRandomItem() returns the created item. No need to have a library to do what can be done natively. If your library supports more than itempool does then build on top of the library.
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
remove the Alloc requirement and the system has issues, even if I put 1 in the weight, it still returns 100 item drop, if you addItem to the same id type it will also add weight, so I suggest you separate the weight in a different method, not adding it but 'setting' it...

If you only have one item then yes it will always be dropped. There is a zero drop chance weight that has to be entered.
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
If you only have one item then yes it will always be dropped.

That's bad, and I registered 5 items at 1% and it drops on ANY death...

There is a zero drop chance weight that has to be entered.

I know that, but I think you should remove the this.index in the zero coz it makes no sense since there is no add item in that field...

Plus you should explain to users that the addItem method weight is how often a specific item will drop and the zero is how less the items drops...

But i still preffer a 'set' weight than to add weight and make debug msgs for limit weight and items...
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
That's bad, and I registered 5 items at 1% and it drops on ANY death...

This sysytem uses a weight chance not a percent chance. So if you have a weight of 1 and a weight of 99, the item with the weight of 1 will be dropped 1 percent of the time and the second item will be dropped 99 percent of the time. If you want an item with a weight of 1 and a zero drop chance of 99 then the item will be dropped 1 percent of the time and nothing will be dropped 99 percent of the time.

I know that, but I think you should remove the this.index in the zero coz it makes no sense since there is no add item in that field...

Plus you should explain to users that the addItem method weight is how often a specific item will drop and the zero is how less the items drops...

I did say that this system is based on a weighted system in the first post.
this is entirely based on a weighted system
So saying that the addItem method weight is how often an item will be dropped is a little redundant. The documentation has been updated.

But i still preffer a 'set' weight than to add weight and make debug msgs for limit weight and items...

I'm not sure what you mean. Also simple math tells you how often an item will be dropped when using a weight system.
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
I'm not sure what you mean
this
set this.ttlWeight = this.ttlWeight + weight

to this
set this.ttlWeight = weight

Also simple math tells you how often an item will be dropped when using a weight system.
For vJassers, but how could a Guier read that if it's Gui friendly?

JASS:
/*
method addZeroDropWeight takes integer weight returns nothing
             -   this is how u add a weight for no item drops.
/*
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
this
set this.ttlWeight = this.ttlWeight + weight

to this
set this.ttlWeight = weight

I can't change that as that variable is the total weight which is needed when figuring what item/s to drop.

For vJassers, but how could a Guier read that if it's Gui friendly?

JASS:
/*
method addZeroDropWeight takes integer weight returns nothing
             -   this is how u add a weight for no item drops.
/*

It is pretty straight forward in its documentation. To make no item drop you need to add a zero drop chance by using the above. I don't see how that is hard to understand.

Also it says that it is a weight system. If someone doesn't know how that works they can look up weight system on google or they can ask here.
 
Top