library AdvancedItemHandlingSystem requires Alloc, RegisterPlayerUnitEvent, Table
// The_Witcher's
//
// <<advanced item system>>
//
// Requirements:
// Alloc
// RegisterPlayerUnitEvent
// Table
//
// This system improves the Warcraft III item engine
//
// If a unit gets an item which it already has it stacks (only if item has charges!)
// In addition this works even if the inventory is full!!!
//
// If you double-right-click an item with charges in your inventory it splits up
// and if you move an item onto an equal one and they are stackable they stack
//
// No Setup Part! Don't touch anything -> fully automatic :)
private struct DataStruct extends array
private static DataStruct array all
private static integer total = 0
private static Table table
private static boolean systemOrder = false
private static timer timer
unit u
item ite
integer index
real x
real y
implement Alloc
private method destroy takes nothing returns nothing
set table[GetHandleId(u)] = 0
set total = total - 1
set all[index] = all[total]
set all[index].index = index
call deallocate()
if (total == 0) then
call PauseTimer(timer)
endif
endmethod
private static method 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
endmethod
private static method itemWalk takes nothing returns nothing
local integer i = 0
local unit u = GetTriggerUnit()
local item ite = GetOrderTargetItem()
local DataStruct this
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 table[GetHandleId(u)] == 0 then
set this = allocate()
set all[total] = this
set index = total
set total = total + 1
set .u = u
set .ite = ite
set x = GetItemX(ite)
set y = GetItemY(ite)
set table[GetHandleId(u)] = this
if (total == 1) then
call TimerStart( timer, 0.05, true, function DataStruct.itemTake )
endif
else
set this = table[GetHandleId(u)]
set .u = u
set .ite = ite
set x = GetItemX(ite)
set y = GetItemY(ite)
endif
set i = 100
endif
set i = i + 1
endloop
set this = table[GetHandleId(u)]
if i < 10 and this != 0 then
call destroy()
endif
endif
set u = null
set ite = null
endmethod
private static method itemStack takes nothing returns nothing
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 not systemOrder and 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
endmethod
private static method itemTake takes nothing returns nothing
local real dx
local real dy
local item it
local integer i = 0
local integer j
local DataStruct this
loop
exitwhen i >= total
set this = all[i]
set dx = GetItemX(ite) - GetUnitX(u)
set dy = GetItemY(ite) - GetUnitY(u)
if ( dx * dx + dy * dy < 10000 ) and IsItemOwned(ite) == false then
set systemOrder = true
call IssueImmediateOrder(u, "stop")
set systemOrder = false
set j = 0
loop
exitwhen j > 5
set it = UnitItemInSlot(u, j)
if GetItemTypeId(ite) == GetItemTypeId(it) then
set j = 5
endif
set j = j + 1
endloop
call SetItemCharges( it, GetItemCharges(it) + GetItemCharges(ite) )
call RemoveItem( ite )
call destroy()
set i = i - 1
endif
set i = i + 1
endloop
set it = null
endmethod
private static method itemWalkAbort1 takes nothing returns nothing
local DataStruct this = table[GetHandleId(GetTriggerUnit())]
if this != 0 and( GetOrderPointX() != x or GetOrderPointY() != y ) then
call destroy()
endif
endmethod
private static method itemWalkAbort2 takes nothing returns nothing
local DataStruct this = table[GetHandleId(GetTriggerUnit())]
if not systemOrder and this != 0 then
call destroy()
endif
endmethod
private static method itemSplit takes nothing returns nothing
local item it = GetOrderTargetItem()
local integer c = GetItemCharges(it)
local integer oId = GetIssuedOrderId()
local unit u = GetOrderedUnit()
if (oId > 852001 and oId < 852008) then
if GetOrderTargetItem() == UnitItemInSlot(u, oId - 852002) then
if c > 1 then
set c = c / 2
call SetItemCharges(it, GetItemCharges(it) - c)
set systemOrder = true
set it = CreateItem(GetItemTypeId(it), GetUnitX(u), GetUnitY(u))
call UnitAddItem(u, it)
set systemOrder = false
call SetItemCharges(it, c)
endif
else
if c > 0 and GetItemTypeId(it) == GetItemTypeId(UnitItemInSlot(u, oId - 852002)) then
call SetItemCharges(it, GetItemCharges(it) + GetItemCharges(UnitItemInSlot(u, oId - 852002)))
call RemoveItem(UnitItemInSlot(u, oId - 852002))
endif
endif
endif
set it = null
set u = null
endmethod
private static method onInit takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER, function DataStruct.itemWalkAbort1)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_ORDER, function DataStruct.itemWalkAbort2)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, function DataStruct.itemWalk)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, function DataStruct.itemSplit)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_PICKUP_ITEM, function DataStruct.itemStack)
set table = Table.create()
set timer = CreateTimer()
endmethod
endstruct
endlibrary
//Code indented using The_Witcher's Script Language Aligner
//Download the newest version and report bugs at www.hiveworkshop.com