• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Item drop system

Status
Not open for further replies.
Level 17
Joined
Nov 13, 2006
Messages
1,814
i could ask a review about how can i make this faster/more efficient?
system must do:

have 3 category:

1. unit type depend drop, specific for each unit type, max limit 512 item for this category (the unit type id the hashtable 1st key)
2. level depend drop, this work for every unit type, also the limit 512 item/level, the drop list depend on creep level (hashtable 1st key is the creep level)
3. shared drop item category, work similiar like previous creep level just we use high number and can assisgn same number to more unit, like we can assign 5000 (5000 is the 1st key in hashtable) to all murloc units etc, so something like common drop like level drop but here you choose what unit types could use same category

Note: each item have his own percentage

how it work?:

i save to the index (how much item added already in current category) to 0 key, like:
1st key: unit type id ('hpea'=human peasant), 0 - 3 (if 3 item added)
the dropable item for peasant saved like this, 'hpea' (unit type id), 1 (index started by 1 till 512), 'rat6' (ItemTypeId )

percentage for this item saved this way: 'hpea', -1 (last saved item index * -1), drop chance






JASS:
function SetUnitDrop takes integer utype, real C1, real C2, integer DSId, real LvDrop returns nothing
    local integer a1 = R2I(C1 / 100)
    local integer a2 = R2I(C2 / 100)
    local integer aLvD = R2I(LvDrop / 100)
    set C1 = C1 - a1 * 100
    set C2 = C2 - a2 * 100
    set LvDrop = LvDrop - aLvD * 100
    call SaveInteger(udg_Drop_Table, utype, 701, a1) // default drop amount
    call SaveInteger(udg_Drop_Table, utype, 702, a2) // shared drop amount
    call SaveInteger(udg_Drop_Table, utype, 710, DSId) // shared drop id
    call SaveInteger(udg_Drop_Table, utype, 703, aLvD) // general level drop amount

    call SaveReal(udg_Drop_Table, utype, 711, C1) // default drop chance
    call SaveReal(udg_Drop_Table, utype, 712, C2) // shared drop chance
    call SaveReal(udg_Drop_Table, utype, 713, LvDrop) // general level drop chance
endfunction

function AddLevelDrop takes integer lv, integer itype, real chance returns nothing
    local integer i = 0
    local integer a = 1
    local real HC
    local integer Index
    if lv < 0 then
        set lv = -lv
    endif

    set HC = LoadReal(udg_Drop_Table, -lv, 700) // highest chance

    set Index = LoadInteger(udg_Drop_Table, -lv, 0) // saved item count in level category
    if chance > 0 then
        loop
            exitwhen i > Index or a == - 1
            set a = LoadInteger(udg_Drop_Table, -lv, i)
            if a == itype then
                call SaveReal(udg_Drop_Table, -lv, -Index, chance)
                set a = - 1
            endif
            set i = i + 1
        endloop
    endif

    if Index < 512 then
        if a != - 1 then
            //increase the index
            call SaveInteger(udg_Drop_Table, -lv, 0, Index + 1)
            // save the itemtypeid and chance
            call SaveInteger(udg_Drop_Table, -lv, Index + 1, itype)
            call SaveReal(udg_Drop_Table, -lv, -Index, chance)
        endif
        if HC > 100.00 then
            set HC = 100
        endif
        if HC < chance then
            call SaveReal(udg_Drop_Table, -lv, 700, chance)
        endif
    endif
endfunction

function AddUnitDrop takes integer utype, integer itype, real chance returns nothing
    local integer Index = LoadInteger(udg_Drop_Table, utype, 0) // saved item count
    local real HC = LoadReal(udg_Drop_Table, utype, 700) // highest chance
    local integer i = 1
    local integer a = 1

//we check if the item already exist on list or no
//if yes then we just upgrade the drop chance
    if chance > 0 then
        loop
            exitwhen i > Index or a == - 1
            set a = LoadInteger(udg_Drop_Table, utype, i)
            if a == itype then
                call SaveReal(udg_Drop_Table, utype, -Index, chance)
                set a = - 1
            endif
            set i = i + 1
        endloop

        //if we dont got the item in drop list then we add it
        if Index < 512 then
            if a != - 1 then
            //increase the index
                call SaveInteger(udg_Drop_Table, utype, 0, Index + 1)
            // save the itemtypeid and chance
                call SaveInteger(udg_Drop_Table, utype, Index + 1, itype)
                call SaveReal(udg_Drop_Table, utype, -Index, chance)
            endif
            if HC > 100.00 then
                set HC = 100
            endif
            if HC < chance then
                call SaveReal(udg_Drop_Table, utype, 700, chance)
            endif
        endif
    endif
endfunction

function RemoveItemDropFromUnit takes integer utype, integer itype returns nothing
    local integer i = 1
    local integer Index = LoadInteger(udg_Drop_Table, utype, 0) // saved item count
    local integer a = 1
    loop
        exitwhen i > Index or a == - 1
        set a = LoadInteger(udg_Drop_Table, utype, i)
        if a == itype then
            if i != Index then
                call SaveInteger(udg_Drop_Table, utype, i, LoadInteger(udg_Drop_Table, utype, Index))
                call SaveReal(udg_Drop_Table, utype, -i, LoadReal(udg_Drop_Table, utype, -i))
            endif
            call SaveInteger(udg_Drop_Table, utype, 0, Index - 1 )
        endif
        set i = i + 1
    endloop

endfunction

function GetDefaultDropItem takes integer utype returns integer
    local integer i
    local integer itemId = 0
    local integer Index = LoadInteger(udg_Drop_Table, utype, 0) // saved item count
    local integer rndI
    local real HC = LoadReal(udg_Drop_Table, utype, 700) // highest chance
    local real rndC
    if Index > 0 then
        loop
            exitwhen itemId > 0
            set rndI = GetRandomInt(1, Index)
            set rndC = GetRandomReal(0, HC)
            if LoadReal(udg_Drop_Table, utype, -rndI) > rndC then
                set itemId = LoadInteger(udg_Drop_Table, utype, rndI)
            endif
        endloop
        call DisplayTextToForce( GetPlayersAll(), "default drop item is |cffffaaaa" + GetObjectName(LoadInteger(udg_Drop_Table, utype, rndI)) + "|r with |cffffffaa" + R2S(LoadReal(udg_Drop_Table, utype, rndI * - 1)) + "|r %% chance and random number is " + R2S(rndC))
    endif
    return itemId
endfunction

function GetLevelDropItem takes integer lv returns integer
    local integer i
    local integer itemId = 0
    local integer Index = LoadInteger(udg_Drop_Table, -lv, 0) // saved item count
    local integer rndI
    local real HC = LoadReal(udg_Drop_Table, -lv, 700) // highest chance
    local real rndC
    if Index > 0 then
        loop
            exitwhen itemId > 0
            set rndI = GetRandomInt(1, Index)
            set rndC = GetRandomReal(0, HC)
            if LoadReal(udg_Drop_Table, -lv, -rndI) > rndC then
                set itemId = LoadInteger(udg_Drop_Table, -lv, rndI)
            endif
        endloop
        call DisplayTextToForce( GetPlayersAll(), "level drop item is |cffffaaaa" + GetObjectName(LoadInteger(udg_Drop_Table, lv * - 1 , rndI)) + "|r with |cffffffaa" + R2S(LoadReal(udg_Drop_Table, lv * - 1, rndI * - 1)) + "|r %% chance and random number is " + R2S(rndC))
    endif
    return itemId
endfunction


JASS:
function Trig_map_init_Actions takes nothing returns nothing
    local integer ut
    call InitHashtableBJ(  )
    set udg_Drop_Table = GetLastCreatedHashtableBJ()
    set ut = 'hpea'
    call SetUnitDrop (ut, 225, 420, 5000, 335)
    call AddUnitDrop (ut, 'rde1', 14)
    call AddUnitDrop (ut, 'rde2', 12)
    call AddUnitDrop (ut, 'rde3', 7)
    call AddUnitDrop (ut, 'rat6', 12)
    call AddUnitDrop (ut, 'rat9', 17)
    call AddUnitDrop (ut, 'ratc', 2.3)
    call AddLevelDrop(1, 'hslv', 5.7)
    call AddLevelDrop(1, 'phea', 12.3)
    call AddLevelDrop(1, 'pman', 5.7)
    call AddLevelDrop(1, 'pinv', 1.4)

    call AddLevelDrop(3, 'shea', 12.3)
    call AddLevelDrop(3, 'sman', 5.7)
    call AddLevelDrop(3, 'spro', 1.4)

    call SetUnitDrop ('nmrl', 0, 430, 5000, 0)
    call SetUnitDrop ('nogr', 0, 370, 5000, 0)
    call AddLevelDrop(5000, 'shea', 12.3)
    call AddLevelDrop(5000, 'sman', 5.7)
    call AddLevelDrop(5000, 'spro', 1.4)


//call SetUnitDrop (unit type, default drop chance, shared drop chance, shared drop id, level drop chance)
//call AddUnitDrop (unit type, item type id, drop chance)
//call RemoveItemDropFromUnit (unit type, item type id)
//call AddLevelDrop (level, item type id, chance)

endfunction

//===========================================================================
function InitTrig_map_init takes nothing returns nothing
    set gg_trg_map_init = CreateTrigger(  )
    call TriggerAddAction( gg_trg_map_init, function Trig_map_init_Actions )
endfunction



JASS:
function Trig_getItem_Conditions takes nothing returns boolean
    return GetPlayerController(GetOwningPlayer(GetKillingUnitBJ())) == MAP_CONTROL_USER
endfunction

function CreateDrop takes unit u, unit k returns nothing
    local integer ut = GetUnitTypeId(u)
    local integer boss = 0
    local integer lv = 0
    local integer da = LoadInteger(udg_Drop_Table, ut, 701) //drop amount
    local real dc = LoadReal(udg_Drop_Table, ut, 711) //drop chance
    local integer di
    local integer m = 1 //drop multiplier
    local integer i = 0
    local integer itemId
    local real rnd

    if IsUnitType(u, UNIT_TYPE_HERO) then
        set lv = GetHeroLevel(u)
        set m = 2
    else
        set lv = GetUnitLevel(u)
    endif
    call DisplayTextToForce( GetPlayersAll(), " ")
    call DisplayTextToForce( GetPlayersAll(), " ")
    call DisplayTextToForce( GetPlayersAll(), "------ |cffffff00Default drop|r: max drop amount |cff7777ff" + I2S(da) + "|r piece --- drop chance |cff7777ff" + R2S(dc) + "|r%")
//---default drop---
    loop
        exitwhen i > da * m
        set rnd = GetRandomReal(0, 99.9999)
        if rnd < dc then
            set itemId = GetDefaultDropItem(ut)
            if itemId > 0 then
                call CreateItem(itemId, GetUnitX(u), GetUnitY(u))
            endif
        endif
        set i = i + 1
    endloop
//---level depend drop---
    set da = LoadInteger(udg_Drop_Table, ut, 703) //drop amount
    set dc = LoadReal(udg_Drop_Table, ut, 713) //drop chance
    set i = 0
    if da == 0 then
        set da = 3
        set dc = 33
    endif
    call DisplayTextToForce( GetPlayersAll(), "------ |cffffff00Level drop|r: max drop amount |cff7777ff" + I2S(da) + "|r piece --- drop chance |cff7777ff" + R2S(dc) + "|r%")
    loop
        exitwhen i > da * m
        set rnd = GetRandomReal(0, 99.9999)
        if rnd < dc then
            set itemId = GetLevelDropItem(lv)
            if itemId > 0 then
                call CreateItem(itemId, GetUnitX(u), GetUnitY(u))
            endif
        endif
        set i = i + 1
    endloop
//---specific cat drop, work like level depend just you can add same category for more different level unit
// basic example add if u add same category for all murloc unit so this could be commun drop betrween murlocs
//but here we add same categroy for peasant+murloc+ogre
    set da = LoadInteger(udg_Drop_Table, ut, 702) //drop amount
    set di = LoadInteger(udg_Drop_Table, ut, 710) //drop amount
    set dc = LoadReal(udg_Drop_Table, ut, 712) //drop chance
    set i = 0
    if da == 0 then
        set da = 3
        set dc = 33
    endif
    call DisplayTextToForce( GetPlayersAll(), "------ |cffffff00Shared drop|r: max drop amount |cff7777ff" + I2S(da) + "|r piece --- drop chance |cff7777ff" + R2S(dc) + "|r% and category |cff99ff99" + I2S(di) + "|r")
    loop
        exitwhen i > da * m
        set rnd = GetRandomReal(0, 99.9999)
        if rnd < dc then
            set itemId = GetLevelDropItem(di)
            if itemId > 0 then
                call CreateItem(itemId, GetUnitX(u), GetUnitY(u))
            endif
        endif
        set i = i + 1
    endloop


endfunction

function Trig_getItem_Actions takes nothing returns nothing
    local unit du = GetDyingUnit()
    local integer dt = GetUnitTypeId(du)
    local real x = GetUnitX(du)
    local real y = GetUnitY(du)

    call CreateDrop (du, GetKillingUnit())
    call TriggerSleepAction(2)
    call RemoveUnit(du)
    call CreateUnit(Player(12), dt, x, y, 0)
    set du = null
endfunction

//===========================================================================
    local trigger t = CreateTrigger( )
    call TriggerRegisterPlayerUnitEvent(t, Player(12), EVENT_PLAYER_UNIT_DEATH, null)
    call TriggerAddCondition( t, Condition( function Trig_getItem_Conditions ) )
    call TriggerAddAction( t, function Trig_getItem_Actions )
    set t = null

 

Attachments

  • ItemDrop.w3x
    22.1 KB · Views: 71
Last edited:
Level 23
Joined
Apr 16, 2012
Messages
4,041
if you dont mind using vJass then switch from Hashtable to struct.
also in header you have set a = - 1[/code], you forgot a!(function SetUnitDrop in the loop) :D [icode=jass]Index * - 1 - will this even compile? In terms of math this makes no sence, it should be Index * (-1), also dont put all -1 to form of - 1, it drops a readbility and understandability(is this a word?) of the code
JASS:
//dummy line
    call InitHashtableBJ(  )
    set udg_Drop_Table = GetLastCreatedHashtableBJ()
->
JASS:
    set udg_Drop_Table = InitHashtable()
(In Map init)

JASS:
    set gg_trg_map_init = CreateTrigger(  )
    call TriggerAddAction( gg_trg_map_init, function Trig_map_init_Actions )
->
JASS:
    call ExecuteFunc("Trig_map_init_Actions")
    //or at least
    local trigger t = CreateTrigger()
    call TriggerAddAction(t, function Trig_map_init_Actions)
the same, init

creep die + create item trigger:
JASS:
    call DisplayTextToForce( GetPlayersAll(), " ")
//->
    call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, " ")
   //faster, runs locally and DisplayTextToForce must run 12 times(for each player) + it does ForForce

again, make the trigger on the init local
you can use condition with huge if block instead of condition and action, you wont be able to use Sleep tho(it will crash thread)

for some concepts, there may be flaws but I didnt really go to if the loop itterates the right number of times because there are better here to check it
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
JASS:
//dummy line
    call InitHashtableBJ(  )
    set udg_Drop_Table = GetLastCreatedHashtableBJ()
->
JASS:
    set udg_Drop_Table = InitHashtable()
(In Map init)

JASS:
    set gg_trg_map_init = CreateTrigger(  )
    call TriggerAddAction( gg_trg_map_init, function Trig_map_init_Actions )
->
JASS:
    call ExecuteFunc("Trig_map_init_Actions")
    //or at least
    local trigger t = CreateTrigger()
    call TriggerAddAction(t, function Trig_map_init_Actions)
the same, init

creep die + create item trigger:
JASS:
    call DisplayTextToForce( GetPlayersAll(), " ")
//->
    call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, " ")
   //faster, runs locally and DisplayTextToForce must run 12 times(for each player) + it does ForForce

again, make the trigger on the init local
you can use condition with huge if block instead of condition and action, you wont be able to use Sleep tho(it will crash thread)

for some concepts, there may be flaws but I didnt really go to if the loop itterates the right number of times because there are better here to check it

you dont got it...
displaytext are only used like debug, only for test if everything executed well, not premanent thing, same like bj at hashtable create

mainly i need opinion/ideea about improve the random drop mechanism :p

set a = - 1[/code], you forgot a!(function SetUnitDrop in the loop) :D Index * - 1 - will this even compile? In terms of math this makes no sence, it should be Index * (-1), also dont put all -1 to form of - 1 [/quote] jass ngp have problem with that? because in WE worked well the Index * -1, i dont wanted use () because everywhere is its longer :D i dont knwo what do you mean with !a, because there dont have a = - 1 [code=jass] call ExecuteFunc("Trig_map_init_Actions") [/code] i never ysed this, give a example where to place it, or what is the different between this and call Trig_map_init_Actions()
 
Last edited:
Level 23
Joined
Apr 16, 2012
Messages
4,041
sorry, I didnt read properly
but for some part its because of how you wrote it, if you write between - and number a space than most people except to have something before it(decrementation)
Also I dont know if index * -1 will parse, but the () would be handy, from math perspective *(or /) and - cant stand next to each other

by the way you dont need to do Index * -1, you can just do -Index, it does the same thing

For better performace, change all BJs(GetKillingUnitBJ(), InitHashtableBJ, GetLastCreatedHashtableBJ() or w/e) and for debugging you can use BJDebugMsg(string)
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
sorry, I didnt read properly
but for some part its because of how you wrote it, if you write between - and number a space than most people except to have something before it(decrementation)
Also I dont know if index * -1 will parse, but the () would be handy, from math perspective *(or /) and - cant stand next to each other

by the way you dont need to do Index * -1, you can just do -Index, it does the same thing

For better performace, change all BJs(GetKillingUnitBJ(), InitHashtableBJ, GetLastCreatedHashtableBJ() or w/e) and for debugging you can use BJDebugMsg(string)

lol why dont started with this :D

by the way you dont need to do Index * -1, you can just do -Index,

its make shorter,whatever where i guess i need improve is the random calculation so header function, maybe the hashtablke useage or create drop function, there u got any ideea?
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
I dont think you can get any more random numbers from Wc3 than using GetRandomInt/Real, maybe if you change seed everytime you call the function and prerandom some numbers, which would slow down the function tho
As the indexing goes, its fine I think, it again cant get any better with hashtables
to me it looks just fine as is
 
Status
Not open for further replies.
Top