library subitems initializer init
globals
private timer eTim = CreateTimer ( )
endglobals
///============== EXTRA FUNCTIONS ===================\\\
private function ItemCount takes unit u, integer id returns integer
local integer i = 0
local integer count = 0
loop
exitwhen i == bj_MAX_INVENTORY
if GetItemTypeId(UnitItemInSlot(u, i)) == id then
set count = count + 1
endif
set i = i + 1
endloop
return count
endfunction
///////////////////===================================\\\\\\\\\\\\\\\\\\
private struct cool
integer id
unit u
real time = 0
item i
endstruct
private struct Item
integer a
integer b
integer charges = 0
real cooldown = 0
boolean charged
boolean hascooldown
static integer max = 0
private static integer total = 0
private static Item array arr
private static timer tim = CreateTimer( )
static method create takes integer a, integer b, boolean flag, integer c, boolean hc, real cd returns Item
local Item that = Item.allocate()
set that.a = a
set that.b = b
set that.charges=c
if that.charges > 99 then
set that.charges = 99 //Just in case..
endif
set that.charged = flag
set that.hascooldown = hc
set that.cooldown = cd
set Item.max = Item.max + 1
return that
endmethod
static method GetCopy takes integer a returns integer
local Item that
local integer i = 0
loop
exitwhen i > Item.max
set that = i
if that.a == a then
return that.b
elseif that.b == a then
return that.a
endif
set i = i + 1
endloop
return 0
endmethod
static method IsStackable takes integer a returns boolean
local Item that
local integer i = 0
loop
exitwhen i > Item.max
set that = i
if (that.a == a) or (that.b == a) then
return that.charged
endif
set i = i + 1
endloop
return false
endmethod
static method HasCooldown takes integer a returns boolean
local Item that
local integer i = 0
loop
exitwhen i > Item.max
set that = i
if (that.a == a) or (that.b == a) then
return that.hascooldown
endif
set i = i + 1
endloop
return false
endmethod
static method MaxCharges takes integer a returns integer
local Item that
local integer i = 0
loop
exitwhen i > Item.max
set that = i
if (that.a == a) or (that.b == a) then
return that.charges
endif
set i = i + 1
endloop
return 0
endmethod
static method GetCooldown takes integer id returns real
local Item that
local integer i = 0
local real cd = 0
loop
exitwhen i > Item.max
set that = i
if (that.a == id) or (that.b == id) then
set cd = that.cooldown
endif
set i = i + 1
endloop
return cd
endmethod
static method AddCooldown takes unit u, item i returns cool
local cool down = cool.create()
local integer id = GetItemTypeId(i)
local integer w = 0
local item k
set down.u = u
set down.i = i
set down.time = Item.GetCooldown(id)
loop
exitwhen w == bj_MAX_INVENTORY
set k = UnitItemInSlot(u, w)
if GetItemTypeId(k) == id then
call SetItemDroppable(k, false)
endif
set w = w + 1
endloop
set k = null
if Item.total == 0 then
call TimerStart(Item.tim, .50, true, function Item.Tick)
//I suggest you keep the interval to this
//JASS is fragile, threads crash if you push them too much
endif
set Item.total = Item.total + 1
set Item.arr[Item.total-1] = down
return down
endmethod
static method Tick takes nothing returns nothing
local cool down
local integer i = 0
local integer w = 0
local item k
loop
exitwhen i >= Item.total
set down = Item.arr[i]
if down.time > 0 then
set down.time = down.time - .50
set w = 0
loop
exitwhen w == bj_MAX_INVENTORY
set k = UnitItemInSlot(down.u, w)
if GetItemTypeId(k) == GetItemTypeId(down.i) then
call SetItemDroppable(k, false)
endif
set w = w + 1
endloop
else
set w = 0
loop
exitwhen w == bj_MAX_INVENTORY
set k = UnitItemInSlot(down.u, w)
if GetItemTypeId(k) == GetItemTypeId(down.i) then
call SetItemDroppable(k, true)
endif
set w = w + 1
endloop
set k = null
set down.u = null
set down.i = null
set Item.total = Item.total - 1
set Item.arr[i] = Item.arr[Item.total]
call down.destroy()
endif
set i = i + 1
endloop
if Item.total == 0 then
call PauseTimer(Item.tim)
endif
endmethod
endstruct
private function Stack takes unit u, integer ID, integer ch returns nothing
local integer i = 0
local item array items
local item k
local boolean exit = false
local integer c = 0
local integer w = 0
local integer q = 0
local integer mc = Item.MaxCharges(ID)
//Got any better ideas?
loop
exitwhen i == bj_MAX_INVENTORY
set k = UnitItemInSlot(u, i)
set items[i] = null
if GetItemTypeId(k)==ID then
set c = GetItemCharges(k)
if (c+ch)<=mc then
set items[i] = k
set q = q + 1
else
set w = w + 1
endif
endif
set i = i + 1
endloop
/////////////////////////////////////////////
///Setting charges on weird case scenarios///
/////////////////////////////////////////////
set i = 0
set c = 0
if q>0 then
loop
exitwhen (i == bj_MAX_INVENTORY) or (c>0)
set k = UnitItemInSlot(u, i)
if k == items[i] then
set c = GetItemCharges(k)
call SetItemCharges(k, (c+ch))
endif
set i = i + 1
endloop
else
if UnitInventoryCount(u)==bj_MAX_INVENTORY then
set k = CreateItem(Item.GetCopy(ID), GetUnitX(u), GetUnitY(u))
else
set k = CreateItem(ID, GetRectMaxX(bj_mapInitialPlayableArea)-50, GetRectMaxY(bj_mapInitialPlayableArea)-50)
call SetItemCharges(k, ch)
call UnitAddItem(u, k)
endif
endif
set w = 0
loop
exitwhen w == bj_MAX_INVENTORY
set items[w] = null
set w = w + 1
endloop
set k = null
endfunction
private function Replace takes nothing returns nothing
local item i = GetManipulatedItem()
local integer it = GetItemTypeId(i)
local integer copy = Item.GetCopy(it)
local boolean b = Item.IsStackable(it)
local integer c = GetItemCharges(i)
local unit u
if copy == 0 then
set i = null
return
else
set u = GetTriggerUnit()
if b then
if (ItemCount(u, copy)>0) then
call Stack(u, copy, c)
set i = null
set u = null
return
endif
endif
if UnitInventoryCount(u)==bj_MAX_INVENTORY then
set i = CreateItem(it, GetUnitX(u), GetUnitY(u))
else
set i = UnitAddItemById(u, copy)
call SetItemCharges(i, c)
endif
endif
set i = null
set u = null
endfunction
private function EnumReplace takes nothing returns nothing
local item i = GetEnumItem()
local integer id = Item.GetCopy(GetItemTypeId(i))
local real x = GetItemX(i)
local real y = GetItemY(i)
local integer c = GetItemCharges(i)
call RemoveItem(i)
set i = CreateItem(id, x, y)
call SetItemCharges(i, c)
set i = null
endfunction
private function EnumCheck takes nothing returns boolean
return (GetItemType(GetFilterItem()) != ITEM_TYPE_POWERUP) and (Item.GetCopy(GetItemTypeId(GetFilterItem()))>0)
endfunction
private function EnumStart takes nothing returns nothing
call EnumItemsInRect(bj_mapInitialPlayableArea, Condition(function EnumCheck), function EnumReplace)
endfunction
private function OnUse takes nothing returns nothing
if Item.HasCooldown(GetItemTypeId(GetManipulatedItem())) then
call Item.AddCooldown(GetTriggerUnit(), GetManipulatedItem())
endif
endfunction
//=========================================================================================================================
private function Cond2 takes nothing returns boolean
local real r = 0
if (GetItemType(GetManipulatedItem()) != ITEM_TYPE_POWERUP) then
set r = TimerGetRemaining(eTim)
if r == 0 then
set r = .07
endif
call PauseTimer(eTim)
call TimerStart(eTim, r, false, function EnumStart)
endif
return false
endfunction
private function Cond3 takes nothing returns boolean
return GetItemType(GetManipulatedItem()) == ITEM_TYPE_POWERUP
endfunction
private function PreloadItems takes nothing returns nothing
//DEMO
//In case you want to use this instead of calling a function to register your item types, read the lines above and
//Do the exact same thing in this block
//===============================================================
//call Item.create('I000', 'I001', false, 0, false, 0)
//call Item.create('I002', 'I003', true, 10, true, 2)
//===============================================================
//These two calls are an example of how to instantly preload your items inside this block
//We give the pair of items in first and second arguments, then we give the flag of stackability (potions, etc.) and the maximum amount of charges
//Locking used items for a duration --->
//4th argument marks the item as undroppable when used
//5th argument gives the cooldown for the item
//Let's assume 'I005' is a healing potion and 5 is it's cooldown, the item gets locked for 5 seconds, becoming undroppable :)
endfunction
function PreloadItem takes integer a, integer b, boolean s, integer c, boolean hc, real cd returns nothing
call Item.create(a, b, s, c, hc, cd)
//A function that can be accessed from outside
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger ( )
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerAddCondition(t, Condition(function Cond3))
call TriggerAddAction( t, function Replace )
set t = CreateTrigger ()
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_USE_ITEM )
call TriggerAddAction( t, function OnUse )
set t = CreateTrigger ()
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_DROP_ITEM )
call TriggerAddCondition( t, Condition(function Cond2))
call PreloadItems()
set t = null
endfunction
endlibrary