library AdvancedItemSystem initializer Init
// The_Witcher's
//
// <<advanced item system>>
//
// this system improves the warcraft III item engine
//
// if a unit gets an item which it already has it stacks
// in addition this works even if the inventory is full!!!
//
// if you double-right-click an item with charges it splits up
// and if you move a item onto an equal item and they are stackable they stack
// no Setup Part! don't touch anything
private struct data
unit u
item ite
integer index
real x
real y
endstruct
globals
private data array DATAS
private integer total = 0
private hashtable h = InitHashtable()
private timer tim = CreateTimer()
private trigger trg = CreateTrigger( )
endglobals
private function IsInventoryFull takes unit u returns boolean
local integer i = 0
loop
exitwhen i == 6
if UnitItemInSlot(u, i) == null then
return false
endif
set i = i + 1
endloop
return true
endfunction
function ItemWalk takes nothing returns boolean
local integer i = 0
local unit u = GetTriggerUnit()
local item ite = GetOrderTargetItem()
local data dat
if IsInventoryFull(u) and GetItemCharges(ite)!= 0 then
loop
exitwhen i > 5
if GetItemTypeId(ite) == GetItemTypeId(UnitItemInSlot(u, i)) and UnitHasItem(u,ite)== false then
call IssuePointOrder( u, "move", GetItemX(ite),GetItemY(ite) )
if LoadInteger(h,GetHandleId(u),0) == 0 then
set dat = data.create()
set DATAS[total] = dat
set dat.index = total
set total = total + 1
set dat.u = u
set dat.ite = ite
set dat.x = GetItemX(ite)
set dat.y = GetItemY(ite)
call SaveInteger(h,GetHandleId(u),0,dat)
else
set dat = LoadInteger(h,GetHandleId(u),0)
set dat.u = u
set dat.ite = ite
set dat.x = GetItemX(ite)
set dat.y = GetItemY(ite)
endif
set i = 100
endif
set i = i + 1
endloop
set dat = LoadInteger(h,GetHandleId(u),0)
if i < 10 and dat != 0 then
set total = total - 1
set DATAS[dat.index] = DATAS[total]
set DATAS[dat.index].index = dat.index
call FlushChildHashtable(h,GetHandleId(dat.u))
call dat.destroy()
endif
endif
set u = null
set ite = null
return false
endfunction
private function ItemStack takes nothing returns boolean
local integer i = 0
local integer id
local item k
local item m = GetManipulatedItem()
local unit u = GetTriggerUnit()
local integer ite = GetItemTypeId(m)
local integer c = GetItemCharges(m)
local integer it
if GetItemCharges(GetManipulatedItem()) > 0 then
loop
exitwhen i > 6
set it = GetItemTypeId(UnitItemInSlot(u, i - 1))
set k = UnitItemInSlot(u, i - 1)
if ( ( it == ite ) and( m != k ) ) then
call SetItemCharges( k, GetItemCharges(k) + c )
call RemoveItem( m )
set i = 10
endif
set i = i + 1
endloop
endif
set k = null
set m = null
set u = null
return false
endfunction
function ItemTake takes nothing returns nothing
local real dx
local real dy
local item it
local integer i
local integer ii = 0
local data dat
loop
exitwhen ii >= total
set dat = DATAS[ii]
set dx = GetItemX(dat.ite) - GetUnitX(dat.u)
set dy = GetItemY(dat.ite) - GetUnitY(dat.u)
if ( SquareRoot(dx * dx + dy * dy) < 100.00 ) and IsItemOwned(dat.ite) == false then
set i = 0
loop
exitwhen i > 5
set it = UnitItemInSlot(dat.u,i)
if GetItemTypeId(dat.ite) == GetItemTypeId(it) then
set i = 5
endif
set i = i + 1
endloop
call SetItemCharges( it, GetItemCharges(it) + GetItemCharges(dat.ite) )
call RemoveItem( dat.ite )
set total = total - 1
set DATAS[ii] = DATAS[total]
set DATAS[ii].index = ii
call FlushChildHashtable(h,GetHandleId(dat.u))
call dat.destroy()
call IssueImmediateOrder(dat.u,"stop")
endif
set ii = ii + 1
endloop
set it = null
endfunction
private function ItemWalkAbort1 takes nothing returns boolean
local data dat = LoadInteger(h,GetHandleId(GetTriggerUnit()),0)
if dat != 0 and( GetOrderPointX() != dat.x or GetOrderPointY() != dat.y )then
set total = total - 1
set DATAS[dat.index] = DATAS[total]
set DATAS[dat.index].index = dat.index
call FlushChildHashtable(h,GetHandleId(dat.u))
call dat.destroy()
endif
return false
endfunction
private function ItemWalkAbort2 takes nothing returns boolean
local data dat = LoadInteger(h,GetHandleId(GetTriggerUnit()),0)
if dat != 0 then
set total = total - 1
set DATAS[dat.index] = DATAS[total]
set DATAS[dat.index].index = dat.index
call FlushChildHashtable(h,GetHandleId(dat.u))
call dat.destroy()
endif
return false
endfunction
function ItemSplit takes nothing returns boolean
local integer i = GetItemCharges(GetOrderTargetItem())
if GetIssuedOrderId() > 852001 and GetIssuedOrderId() < 852008 then
if GetOrderTargetItem() == UnitItemInSlot(GetOrderedUnit(), GetIssuedOrderId()-852002) then
if i > 1 then
set i = i/2
call SetItemCharges(GetOrderTargetItem(), GetItemCharges(GetOrderTargetItem()) - i)
call DisableTrigger(trg)
call UnitAddItemByIdSwapped(GetItemTypeId(GetOrderTargetItem()), GetTriggerUnit())
call EnableTrigger(trg)
call SetItemCharges(bj_lastCreatedItem, i)
endif
else
if i > 0 and GetItemTypeId(GetOrderTargetItem()) == GetItemTypeId(UnitItemInSlot(GetOrderedUnit(), GetIssuedOrderId()-852002)) then
call SetItemCharges(GetOrderTargetItem(), GetItemCharges(GetOrderTargetItem()) + GetItemCharges(UnitItemInSlot(GetOrderedUnit(), GetIssuedOrderId()-852002)))
call RemoveItem(UnitItemInSlot(GetOrderedUnit(), GetIssuedOrderId()-852002))
endif
endif
endif
return false
endfunction
private function Init takes nothing returns nothing
local trigger a = CreateTrigger( )
local trigger b = CreateTrigger( )
local trigger c = CreateTrigger( )
call TimerStart( tim, 0.05, true, function ItemTake )
call TriggerRegisterAnyUnitEventBJ( a, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER )
call TriggerAddCondition( a, Condition( function ItemWalkAbort1 ) )
call TriggerRegisterAnyUnitEventBJ( b, EVENT_PLAYER_UNIT_ISSUED_ORDER )
call TriggerAddCondition( a, Condition( function ItemWalkAbort2 ) )
call TriggerRegisterAnyUnitEventBJ( c, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER )
call TriggerAddCondition( c, Condition( function ItemWalk ) )
call TriggerAddCondition( c, Condition( function ItemSplit ) )
call TriggerRegisterAnyUnitEventBJ( trg, EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerAddCondition( trg, Condition( function ItemStack ) )
endfunction
endlibrary