- Joined
- Mar 18, 2012
- Messages
- 1,716
I quickly wrote it this evening for own usage.
I think it turned out quite nice. maybeit's useful for others.
The first is a wrapper around the itempool handle.
The second is a item drop snippet. You create a drop list for an id ( unit id or any integer you wish )
Then you add ItemPools to it with a drop chance and a max drop.
Drop items whenever you want or automatically on unit death event.
See yourself.
I think it turned out quite nice. maybeit's useful for others.
The first is a wrapper around the itempool handle.
The second is a item drop snippet. You create a drop list for an id ( unit id or any integer you wish )
Then you add ItemPools to it with a drop chance and a max drop.
Drop items whenever you want or automatically on unit death event.
See yourself.
JASS:
library ItemPool uses Table
//===================================================================================
// Wrapper around the itempool handle. Use in combination with library ItemDrop.
//===================================================================================
struct ItemPool
// implement Alloc; Place your allow module here.
// For removing an id from all pools.
private static thistype array next
private static thistype array prev
// Read and use PlaceRandomItem()
readonly itempool pool
//
private Table items// Tracks added items. I don't know how safe itempool handles are.
private integer itemCounter
private integer references
// Returns the weight for an item id in this pool.
// For setting a new weight simply use this.addItemId(id, newWeight).
method getItemIdWeight takes integer itemId returns real
return items.real[itemId]
endmethod
method operator empty takes nothing returns boolean
return (itemCounter == 0)
endmethod
method removeItemId takes integer itemId returns nothing
debug call ThrowWarning((pool == null), "ItemPool", "removeItemId", "pool", this, "Invalid itempool ( null )!")
//
if items.has(itemId) then
call ItemPoolRemoveItemType(pool, itemId)
call items.remove(itemId)
set itemCounter = itemCounter - 1
endif
endmethod
// Runs for all pools.
static method removeItemIdFromAll takes integer itemId returns nothing
local thistype this = next[0]
loop
exitwhen (0 == this)
call removeItemId(itemId)
set this = next[this]
endloop
endmethod
// Please don't add invalid item ids.
method addItemId takes integer itemId, real weight returns nothing
debug call ThrowError((pool == null), "ItemPool", "addItemId", "pool", this, "Instance not allocated!")
debug call ThrowWarning((weight <= 0), "ItemPool", "addItemId", "weight", this, "Invalid weight ( <= 0 )!")
if items.has(itemId) then
call removeItemId(itemId)
endif
call ItemPoolAddItemType(pool, itemId, weight)
set items.real[itemId] = weight
set itemCounter = itemCounter + 1
endmethod
method destroy takes nothing returns nothing
debug local string msg = "Can't destroy pool. It's still locked to " + I2S(references) + " object ids"
//
if (0 == references) then
call deallocate()
call items.destroy()
call DestroyItemPool(pool)
set pool = null
set next[prev[this]] = next[this]
set prev[next[this]] = prev[this]
endif
//
debug call ThrowWarning((references != 0), "ItemPool", "destroy", "references", this, msg)
endmethod
method lock takes nothing returns thistype
set references = references + 1
return this
endmethod
method unlock takes nothing returns nothing
set references = references - 1
endmethod
static method create takes nothing returns thistype
local thistype this = thistype.allocate()
// Add to list.
set next[this] = 0
set prev[this] = prev[0]
set next[prev[0]] = this
set prev[0] = this
// Set members.
set itemCounter = 0
set references = 0
set items = Table.create()
set pool = CreateItemPool()
return this
endmethod
endstruct
function RemoveItemIdFromAllPools takes integer itemid returns nothing
call ItemPool.removeItemIdFromAll(itemid)
endfunction
endlibrary
JASS:
library ItemDrop initializer Init uses RegisterPlayerUnitEvent, ItemPool, List
//**
//* Settings:
//* =========
// Runs always when an item drop takes place.
private function DropItem takes item justDropped, widget fromWidget returns nothing
endfunction
// API:
//
// static method allocate takes integer id returns ItemPool
// - New pool for this id. ( unit id, destructable id, 1, 2, ... )
//
// method deallocate takes integer nothing returns nothing
// - Destroy the instance.
//
// static method operator [] takes integer id returns thistype
// - Get the instance reference on the id
//
// method addItemPool takes ItemPool pool, integer maxDrop, real dropChance returns thistype
// - add an ItemPool to your id. Set drop parameters for this pool.
// - returns thistype for addItemPool().addItemPool syntax.
//
// method dropItems takes real x, real y, widget from returns nothing
// - Run this when you wish to drop items from this ItemDrop instance.
// - Runs for all added itempools.
// - You can define a widget which drops the items. "null" is also ok.
//===================================================================================
// ItemPool code. Make changes carefully.
//===================================================================================
globals
private Table table
endglobals
// For the table.
private module inits
private static method onInit takes nothing returns nothing
call thistype.init()
endmethod
endmodule
//
struct ItemDrop extends array
implement List
private ItemPool pool
private integer maxItems
private real chance// 1. - 100.
static method operator [] takes integer id returns thistype
return table[id]
endmethod
// Loop through all ItemPool instances queued to this list.
method dropItems takes real x, real y, widget from returns nothing
local thistype node = this.first
local integer amount
loop
exitwhen (0 == node)
set amount = node.maxItems
loop
exitwhen (0 == amount) or (node.pool.empty)
//
if (node.chance >= GetRandomReal(1., 100.)) then
call DropItem(PlaceRandomItem(node.pool.pool, x, y), from)
endif
set amount = amount - 1
endloop
set node = node.next
endloop
endmethod
// static deallocate ....
static method deallocate takes integer id returns nothing
local thistype this = table[id]
local thistype node = first
loop
exitwhen (0 == node)
call node.pool.unlock()
set node = node.next
endloop
call table.remove(id)
call destroy()
endmethod
// Add a itempools to this instance
method addItemPool takes ItemPool pool, integer maxDrop, real dropChance returns thistype
local thistype node = enqueue()
//
set node.pool = pool.lock()
set node.chance = dropChance
set node.maxItems = maxDrop
//
debug call ThrowError((maxDrop <= 0), "ItemDrop", "addItemPool", "node.maxItems", this, "Invalid max item drop ( <= 0 )!")
debug call ThrowError((pool.pool == null), "ItemDrop", "addItemPool", "index.pool", this, "Invalid itempool ( null )!")
return this
endmethod
// Can be any reference key. Type ids, handle ids fictional values.
static method allocate takes integer id returns thistype
local thistype this = thistype.create()
//
debug call ThrowError(table.has(id), "ItemDrop", "allocate", "id", id, "Table already has saved integer " + GetObjectName(id))
//
set table[id] = this
return this
endmethod
private static method init takes nothing returns nothing
set table = Table.create()
endmethod
implement inits
endstruct
//========================================================================
// Event handler.
//========================================================================
private function OnUnitDeath takes nothing returns nothing
local unit source = GetTriggerUnit()
//
// Run item drop for any unit of this type id.
local ItemDrop this = table[GetUnitTypeId(source)]
if (0 != this) then
call this.dropItems(GetUnitX(source), GetUnitY(source), source)
endif
//
// Runs specific for this handle id.
set this = table[GetHandleId(source)]
if (0 != this) then
call this.dropItems(GetUnitX(source), GetUnitY(source), source)
call ItemDrop.deallocate(GetHandleId(source))
endif
endfunction
private function Init takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function OnUnitDeath)
endfunction
endlibrary
Last edited: