- Joined
- Jul 26, 2008
- Messages
- 1,009
Alright I'm about to release my map, Vuen's D&D Grand Project. Unfortunately the inventory system I've implemented into the map has issues. Any time I give a hero the inventory system, the hero can no longer pick up items on the ground. (Haven't tested outside of initialization)
Also the stack detection only works when they put their items in say their bag. Help would be greatly appreciated, meanwhile I'm checking through the map to detect any outside problems.
Here's the inventory system by Kricz I'm trying to use. I understand some vJASS, enough to make educated guesses for what everything does, but not enough to let me know what the problem is.
Also the stack detection only works when they put their items in say their bag. Help would be greatly appreciated, meanwhile I'm checking through the map to detect any outside problems.
Here's the inventory system by Kricz I'm trying to use. I understand some vJASS, enough to make educated guesses for what everything does, but not enough to let me know what the problem is.
JASS:
library InventorySystem requires Table, ItemList, SimError BonusMod UnitMaxStateBonuses MovementBonus
globals
//The Rawcodes of the Items for opening the backpack and equipment
private constant integer EQUIPMENT_OPEN_ID = 'I000'
private constant integer BACKPACK_OPEN_ID = 'I00R'
//The rawcodes of the Items for closing the backpack and equipment
private constant integer EQUIPMENT_CLOSE_ID = 'I001'
private constant integer BACKPACK_CLOSE_ID = 'I00S'
//The rawcodes of the Items changing the pages of the backpack and equipment menu
private constant integer EQUIPMENT_PAGE_1 = 'I003'
private constant integer BACKPACK_PAGE_1 = 'I00T'
private constant integer EQUIPMENT_PAGE_2 = 'I002'
private constant integer BACKPACK_PAGE_2 = 'I00U'
//The slots, where the items for opening backpack and equipment menu should be created
private constant integer EQUIPMENT_SLOT = 4
private constant integer BACKPACK_SLOT = 5
//The place, where required items should be stored
private constant real STORE_ITEM_X = 0.
private constant real STORE_ITEM_Y = 0.
//The Max Number of Charges, an item can has maximum
constant integer MAX_ITEM_CHARGES = 8
//If true, the equipment menu will change to first page when opened
private constant boolean CHANGE_TO_FIRST = true
//If trie, an item being picked up will be auto equipped, if its slot is emtpy and the hero can wear it
private constant boolean AUTO_EQUIP = true
//The distance, an item can be picked up by a hero
private constant real ITEM_PICKUP_DIST = 225.00
//Don't change this!!!
private integer array DUMMY_ITEMS[8]
endglobals
private function SETUP_DUMMY_ITEMS takes nothing returns nothing
set DUMMY_ITEMS[0] = 'I004' //Head
set DUMMY_ITEMS[1] = 'I005' //Chest
set DUMMY_ITEMS[2] = 'I006' //Main Hand
set DUMMY_ITEMS[3] = 'I007' //Secondary Hand
set DUMMY_ITEMS[4] = 'I008' //Gloves
set DUMMY_ITEMS[5] = 'I009' //Feet
set DUMMY_ITEMS[6] = 'I00A' //First Acessory
set DUMMY_ITEMS[7] = 'I00B' //Second Acessory
endfunction
//EVERYTHING BELOW HERE IS SYSTEM CODE!!!
private keyword addItem
//This is the triggered item pickup and stack detection System.
private struct StackData
private delegate Inventory inv = 0
item item = null
real x = 0
real y = 0
integer order = 0
private static integer count = 0
private static thistype array datas
private static trigger walkTo
//creates a new instance of the stackdata
static method create takes unit hero, item which returns StackData
local StackData this = StackData.allocate()
set .inv = Inventory.table[hero]
set .item = which
set .x = GetItemX(.item)
set .y = GetItemY(.item)
call IssuePointOrder(.Owner, "move", .x, .y)
set .order = GetUnitCurrentOrder(.Owner)
set .datas[.count] = this
set .count = .count + 1
return this
endmethod
//checks if the issued target was an item and the order is correct
static method check takes nothing returns boolean
if GetOrderTargetItem() != null and (GetIssuedOrderId() == 851971) then
call StackData.create(GetTriggerUnit(), GetOrderTargetItem())
return true
endif
return false
endmethod
//just sorts and checks each stackdata...
static method periodic takes nothing returns nothing
local integer i = .count - 1
loop
exitwhen i < 0
if not .datas[i].control() then
set .count = .count - 1
if .count < 0 then
set .count = 0
else
set .datas[i] = .datas[.count]
endif
endif
set i = i - 1
endloop
endmethod
//checks the hero and the item every interval
method control takes nothing returns boolean
local real dx = GetUnitX(.Owner) - .x
local real dy = GetUnitY(.Owner) - .y
local Item it = Item.getItemById(GetItemTypeId(.item))
if GetUnitCurrentOrder(.Owner) != .order or GetItemX(.item) != .x or GetItemY(.item) != .y or GetWidgetLife(.Owner) <= 0.405 then
return false
elseif SquareRoot(dx * dx + dy * dy) <= ITEM_PICKUP_DIST and GetItemX(.item) == .x or GetItemY(.item) == .y and GetWidgetLife(.Owner) > 0.405 then
call IssueImmediateOrder(.Owner, "stop")
if (AUTO_EQUIP and it.Equipment and .isSlotEmpty(it.Slot) and .checkHero(it, false) and .allowauto) then
return Inventory.equipItem(.Owner, .item, it)
endif
if not .checkItemForStack(.item) then
if not .getSlotForItem(.item) then
call SimError(GetOwningPlayer(.Owner), "Inventory and Backpack are full.")
return false
endif
endif
return false
elseif SquareRoot(dx * dx + dy * dy) > ITEM_PICKUP_DIST then
return true
endif
return false
endmethod
//self explanatory..
static method onInit takes nothing returns nothing
set .walkTo = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(.walkTo, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)
call TriggerAddCondition(.walkTo, Condition(function thistype.check))
call TimerStart(NewTimer(), 0.05, true, function thistype.periodic)
endmethod
endstruct
//private struct required to "recreate" items in their slots when their are dragged or dropped incrorrect
private struct addItem
delegate Inventory inv
integer id
integer charges
integer slot
private timer t
//creates a new instance for an item to a move it to a slot
static method create takes item it, integer slot, Inventory inv returns thistype
local thistype this = thistype.allocate()
set .inv = inv
set .id = GetItemTypeId(it)
set .charges = GetItemCharges(it)
set .slot = slot
set .dropped = false
call RemoveItem(it)
set .dropped = true
set .t = NewTimer()
call SetTimerData(.t, this)
call TimerStart(.t, 0.0, false, function thistype.expire)
return this
endmethod
//0.0 second tiemr interval is required...
private static method expire takes nothing returns nothing
local thistype this = GetTimerData(GetExpiredTimer())
call UnitAddItemToSlotById(.Owner, .id, .slot)
call SetItemCharges(UnitItemInSlot(.Owner, .slot), .charges)
call ReleaseTimer(.t)
call .destroy()
endmethod
endstruct
//Thanks to D1000 for creating this function
private function SearchString takes string WhichString, string ForWhat returns boolean
local integer BaseLength = StringLength(WhichString)
local integer SearchLength = StringLength(ForWhat)
local integer i = 0
loop
exitwhen ForWhat == SubString(WhichString, i, i + SearchLength)
set i = i + 1
if i + SearchLength > BaseLength then
return false
endif
endloop
return true
endfunction
//The Inventory struct..
struct Inventory
unit Owner
string HeroClass = ""
string ItemClasses = ""
item array equip[8]
integer array items[6]
integer array backp[8]
integer array charges[6]
integer array bcharges[8]
boolean allowauto = true
integer bfree = 8
boolean dropped = true
private boolean open = false
private boolean bopen = false
private integer page = 1
private integer bpage = 1
public static HandleTable table
//creates a new Inventory for the unit
static method create takes unit whichUnit, string heroClass, string availableItemClasses returns thistype
local thistype this = 0
local integer i = 0
if not .table.exists(whichUnit) then
set this = thistype.allocate()
set .Owner = whichUnit
set .HeroClass = heroClass
set .ItemClasses = availableItemClasses
loop
exitwhen i > 8
set .equip[i] = CreateItem(DUMMY_ITEMS[i], STORE_ITEM_X, STORE_ITEM_Y)
call SetItemVisible(.equip[i], false)
set i = i + 1
endloop
call TriggerRegisterUnitEvent(.Use, .Owner, EVENT_UNIT_USE_ITEM)
call TriggerRegisterUnitEvent(.Pickup, .Owner, EVENT_UNIT_PICKUP_ITEM)
call TriggerRegisterUnitEvent(.Drag, .Owner, EVENT_UNIT_ISSUED_TARGET_ORDER)
call TriggerRegisterUnitEvent(.Drop, .Owner, EVENT_UNIT_DROP_ITEM)
call UnitAddItemToSlotById(.Owner, EQUIPMENT_OPEN_ID, EQUIPMENT_SLOT)
call UnitAddItemToSlotById(.Owner, BACKPACK_OPEN_ID, BACKPACK_SLOT)
call SetItemCharges(UnitItemInSlot(.Owner, BACKPACK_SLOT), .bfree)
set .table[.Owner] = this
return this
endif
return 0
endmethod
//opens the backpack for the unit
public static method openBackpack takes unit whichUnit returns boolean
local integer i = 0
local integer i2 = 0
local thistype this = .table[whichUnit]
local item temp = null
local integer add = 0
if not .table.exists(whichUnit) then
return false
elseif not .bopen and not .open then
set .bopen = true
set .allowauto = false
loop
exitwhen i > 5
set temp = UnitItemInSlot(.Owner, i)
set .charges[i] = GetItemCharges(temp)
set .items[i] = GetItemTypeId(temp)
call RemoveItem(temp)
set i = i + 1
endloop
call UnitAddItemToSlotById(.Owner, BACKPACK_CLOSE_ID, 5)
if .bpage <= 1 then
set i = 0
loop
exitwhen i > 3
if .backp[i] != 0 then
call UnitAddItemToSlotById(.Owner, .backp[i], i)
call SetItemCharges(UnitItemInSlot(.Owner, i), .bcharges[i])
endif
set i = i + 1
endloop
call UnitAddItemToSlotById(.Owner, BACKPACK_PAGE_2, 4)
elseif .bpage >= 2 then
set i = 0
loop
exitwhen i > 3
if .backp[i+4] != 0 then
call UnitAddItemToSlotById(.Owner, .backp[i+4], i)
call SetItemCharges(UnitItemInSlot(.Owner, i), .bcharges[i+4])
endif
set i = i + 1
endloop
call UnitAddItemToSlotById(.Owner, BACKPACK_PAGE_1, 4)
endif
set temp = null
set .allowauto = true
return true
endif
return true
endmethod
//opens the equipment menu
public static method openEquipment takes unit whichUnit returns boolean
local integer i = 0
local thistype this = .table[whichUnit]
local item temp = null
if not .table.exists(whichUnit) then
return false
elseif not .open and not .bopen then
set .open = true
set .allowauto = false
if .page <= 1 or CHANGE_TO_FIRST then
loop
exitwhen i > 5
set temp = UnitItemInSlot(.Owner, i)
set .charges[i] = GetItemCharges(temp)
set .items[i] = GetItemTypeId(temp)
call RemoveItem(temp)
if i < 4 then
call SetItemVisible(.equip[i], true)
call UnitAddItem(.Owner, .equip[i])
endif
set i = i + 1
endloop
call UnitAddItemToSlotById(.Owner, EQUIPMENT_PAGE_2, 4)
elseif .page >= 2 and not CHANGE_TO_FIRST then
loop
exitwhen i > 5
set temp = UnitItemInSlot(.Owner, i)
set .charges[i] = GetItemCharges(temp)
set .items[i] = GetItemTypeId(temp)
call RemoveItem(temp)
if i < 4 then
call SetItemVisible(.equip[i+4], true)
call UnitAddItem(.Owner, .equip[i+4])
endif
set i = i + 1
endloop
call UnitAddItemToSlotById(.Owner, EQUIPMENT_PAGE_1, 4)
endif
call UnitAddItemToSlotById(.Owner, EQUIPMENT_CLOSE_ID, 5)
set .allowauto = true
return true
endif
return true
endmethod
//closes the hero's backpack
public static method closeBackpack takes unit whichUnit returns boolean
local integer i = 0
local item t = null
local thistype this = .table[whichUnit]
local item temp = null
if not .table.exists(whichUnit) then
return false
elseif .bopen then
set .bopen = false
set .allowauto = false
call RemoveItem(UnitItemInSlot(.Owner, 5))
call RemoveItem(UnitItemInSlot(.Owner, 4))
if .bpage <= 1 then
loop
exitwhen i > 3
set temp = UnitRemoveItemFromSlot(.Owner, i)
set .backp[i] = GetItemTypeId(temp)
set .bcharges[i] = GetItemCharges(temp)
call RemoveItem(temp)
set i = i + 1
endloop
elseif .bpage >= 2 then
loop
exitwhen i > 3
set temp = UnitRemoveItemFromSlot(.Owner, i)
set .backp[i+4] = GetItemTypeId(temp)
set .bcharges[i+4] = GetItemCharges(temp)
call RemoveItem(temp)
set i = i + 1
endloop
endif
set i = 0
loop
exitwhen i > 5
if .items[i] != 0 then
call UnitAddItemToSlotById(.Owner, .items[i], i)
call SetItemCharges(UnitItemInSlot(.Owner, i), .charges[i])
endif
set i = i + 1
endloop
set .bfree = .getBackpackPlace()
call SetItemCharges(UnitItemInSlot(.Owner, BACKPACK_SLOT), .bfree)
set .allowauto = true
set temp = null
return true
endif
return false
endmethod
//closes the hero's equipment menu
public static method closeEquipment takes unit whichUnit returns boolean
local integer i = 0
local item t = null
local thistype this = .table[whichUnit]
local integer add = 0
if not .table.exists(whichUnit) then
return false
elseif .open then
set .open = false
set .allowauto = false
if .page >= 2 then
set add = 4
endif
loop
exitwhen i > 3
set .equip[i+add] = UnitRemoveItemFromSlot(.Owner, i)
call SetItemPosition(.equip[i+add], STORE_ITEM_X, STORE_ITEM_Y)
call SetItemVisible(.equip[i+add], false)
set i = i + 1
endloop
call RemoveItem(UnitItemInSlot(.Owner, 5))
call RemoveItem(UnitItemInSlot(.Owner, 4))
set i = 0
loop
exitwhen i > 5
if .items[i] != 0 then
call UnitAddItemToSlotById(.Owner, .items[i], i)
call SetItemCharges(UnitItemInSlot(.Owner, i), .charges[i])
endif
set i = i + 1
endloop
call SetItemCharges(UnitItemInSlot(.Owner, BACKPACK_SLOT), .bfree)
if CHANGE_TO_FIRST then
set .page = 1
endif
set .allowauto = true
return true
endif
return false
endmethod
//changes the backpack pages of the unit
public static method changePageBackpack takes unit whichUnit returns boolean
local integer i = 0
local thistype this = .table[whichUnit]
local item temp = null
if .bopen and this != 0 then
set .dropped = false
call RemoveItem(UnitItemInSlot(.Owner, 4))
set .dropped = true
set .allowauto = false
if .bpage <= 1 then
loop
exitwhen i > 3
set temp = UnitRemoveItemFromSlot(.Owner, i)
set .backp[i] = GetItemTypeId(temp)
set .bcharges[i] = GetItemCharges(temp)
call UnitAddItemToSlotById(.Owner, .backp[i+4], i)
call SetItemCharges(UnitItemInSlot(.Owner, i), .bcharges[i+4])
call RemoveItem(temp)
set i = i + 1
endloop
call UnitAddItemToSlotById(.Owner, BACKPACK_PAGE_1, 4)
set .bpage = 2
elseif .bpage >= 2 then
loop
exitwhen i > 3
set temp = UnitRemoveItemFromSlot(.Owner, i)
set .backp[i+4] = GetItemTypeId(temp)
set .bcharges[i+4] = GetItemCharges(temp)
call UnitAddItemToSlotById(.Owner, .backp[i], i)
call SetItemCharges(UnitItemInSlot(.Owner, i), .bcharges[i])
call RemoveItem(temp)
set i = i + 1
endloop
call UnitAddItemToSlotById(.Owner, BACKPACK_PAGE_2, 4)
set .bpage = 1
endif
set .allowauto = true
set temp = null
return true
endif
return false
endmethod
//changes the equipment menu pages for the unit
public static method changePageEquipment takes unit whichUnit returns boolean
local integer i = 0
local thistype this = .table[whichUnit]
local integer add = 0
if .open and this != 0 then
if .page >= 2 then
set add = 4
endif
set .allowauto = false
loop
exitwhen i > 3
set .equip[i+add] = UnitRemoveItemFromSlot(.Owner, i)
call SetItemPosition(.equip[i+add], STORE_ITEM_X, STORE_ITEM_Y)
call SetItemVisible(.equip[i+add], false)
call UnitAddItem(.Owner, .equip[i+4-add])
set i = i + 1
endloop
set .dropped = false
call RemoveItem(UnitItemInSlot(.Owner, 4))
set .dropped = true
if .page >= 2 then
call UnitAddItemToSlotById(.Owner, EQUIPMENT_PAGE_2, 4)
set .page = 1
elseif .page <= 1 then
call UnitAddItemToSlotById(.Owner, EQUIPMENT_PAGE_1, 4)
set .page = 2
endif
set .allowauto = true
return true
endif
return false
endmethod
//Only call this method, if you can be shure, that the Item's slot is empty or it will bug!
public static method quickEquip takes unit u, Item it returns boolean
local thistype this = .table[u]
if .checkHero(it, true) then
set .equip[it.Slot] = CreateItem(it.ItemId, STORE_ITEM_X, STORE_ITEM_Y)
call SetItemVisible(.equip[it.Slot], false)
call SetItemDroppable(.equip[it.Slot], false)
call .applyItemStats(it)
return true
endif
return false
endmethod
//equips an item for a hero
public static method equipItem takes unit u, item t, Item it returns boolean
local thistype this = .table[u]
local integer itd1 = 0
local integer itd2 = 0
local integer slot = 0
local integer i = 0
if .checkHero(it, true) then
if not .isItemEquipped(t) and .isSlotEmpty(it.Slot) then
if not .open then
call RemoveItem(.equip[it.Slot])
set .equip[it.Slot] = t
call SetItemPosition(.equip[it.Slot], STORE_ITEM_X, STORE_ITEM_Y)
call SetItemVisible(.equip[it.Slot], false)
call SetItemDroppable(.equip[it.Slot], false)
call .applyItemStats(it)
return true
elseif .open then
set .dropped = false
if .page <= 1 then
if it.Slot <= 3 then
if not (GetItemTypeId(UnitItemInSlot(.Owner, it.Slot)) == DUMMY_ITEMS[it.Slot]) then
if not .getSlotForItem(UnitItemInSlot(.Owner, it.Slot)) then
call SimError(GetOwningPlayer(.Owner), "Inventory and Backpack are full.")
return false
endif
else
call RemoveItem(UnitItemInSlot(.Owner, it.Slot))
endif
call UnitAddItemToSlotById(.Owner, it.ItemId, it.Slot)
call .applyItemStats(it)
return true
elseif it.Slot > 3 then
if not (GetItemTypeId(.equip[it.Slot]) == DUMMY_ITEMS[it.Slot]) then
if not .getSlotForItem(.equip[it.Slot]) then
call SimError(GetOwningPlayer(.Owner), "Inventory and Backpack are full.")
return false
endif
else
call RemoveItem(.equip[it.Slot])
endif
set .equip[it.Slot] = t
call SetItemPosition(.equip[it.Slot], STORE_ITEM_X, STORE_ITEM_Y)
call SetItemVisible(.equip[it.Slot], false)
call SetItemDroppable(.equip[it.Slot], false)
call .applyItemStats(it)
return true
endif
elseif .page >= 2 then
if it.Slot > 3 then
if not (GetItemTypeId(UnitItemInSlot(.Owner, it.Slot - 4)) == DUMMY_ITEMS[it.Slot]) then
if not .getSlotForItem(UnitItemInSlot(.Owner, it.Slot - 4)) then
call SimError(GetOwningPlayer(.Owner), "Inventory and Backpack are full.")
return false
endif
else
call RemoveItem(UnitItemInSlot(.Owner, it.Slot - 4))
endif
call UnitAddItemToSlotById(.Owner, it.ItemId, it.Slot - 4)
call .applyItemStats(it)
return true
elseif it.Slot <= 3 then
if not (GetItemTypeId(.equip[it.Slot]) == DUMMY_ITEMS[it.Slot]) then
if not .getSlotForItem(UnitItemInSlot(.Owner, it.Slot)) then
call SimError(GetOwningPlayer(.Owner), "Inventory and Backpack are full.")
return false
endif
else
call RemoveItem(.equip[it.Slot])
endif
set .equip[it.Slot] = t
call SetItemPosition(.equip[it.Slot], STORE_ITEM_X, STORE_ITEM_Y)
call SetItemVisible(.equip[it.Slot], false)
call SetItemDroppable(.equip[it.Slot], false)
call .applyItemStats(it)
return true
endif
endif
endif
elseif not .isSlotEmpty(it.Slot) then
set itd1 = GetItemTypeId(t)
set slot = .getItemSlot(t)
call RemoveItem(t)
set itd2 = GetItemTypeId(.equip[it.Slot])
call RemoveItem(.equip[it.Slot])
call .removeItemStats(Item.getItemById(itd2))
call .applyItemStats(it)
set .equip[it.Slot] = CreateItem(itd1, STORE_ITEM_X, STORE_ITEM_Y)
call SetItemVisible(.equip[it.Slot], false)
call UnitAddItemToSlotById(.Owner, itd2, slot)
call SetItemDroppable(.equip[it.Slot], false)
return true
endif
endif
return false
endmethod
//un-equips an item for the hero
public static method unequipItem takes unit u, item t, Item it returns boolean
local thistype this = .table[u]
if not .getSlotForItem(t) then
call SimError(GetOwningPlayer(.Owner), "Inventory and Backpack are full.")
return false
else
call .removeItemStats(it)
set .equip[it.Slot] = UnitAddItemById(.Owner, DUMMY_ITEMS[it.Slot])
return true
endif
endmethod
//Returns true, if the given item is equipped (or an item with the same ItemTypeId)
public method isItemEquipped takes item whichItem returns boolean //INLINE FRIENDLY
return GetItemTypeId(.equip[Item.getItemById(GetItemTypeId(whichItem)).Slot]) == GetItemTypeId(whichItem)
endmethod
//Returns true, if the given slot is empty
public method isSlotEmpty takes integer Slot returns boolean //INLINE FRIENDLY
return GetItemTypeId(.equip[Slot]) == DUMMY_ITEMS[Slot]
endmethod
//checks, if the hero has the possibility to stack the given item with another
public method checkItemForStack takes item for returns boolean
local integer i = 0
local integer id = GetItemTypeId(for)
local integer bonus = 0
local Item it = Item.getItemById(GetItemTypeId(for))
if not .open and not .bopen and not it.Equipment then
loop
exitwhen i > 5
if GetItemTypeId(UnitItemInSlot(.Owner, i)) == id and GetItemCharges(UnitItemInSlot(.Owner, i)) + GetItemCharges(for) <= MAX_ITEM_CHARGES and GetItemCharges(UnitItemInSlot(.Owner, i)) + GetItemCharges(for) <= it.MaxStacks then
set bonus = GetItemCharges(for)
call RemoveItem(for)
call SetItemCharges(UnitItemInSlot(.Owner, i), GetItemCharges(UnitItemInSlot(.Owner, i)) + bonus)
return true
endif
set i = i + 1
endloop
set i = 0
loop
exitwhen i > 7
if .backp[i] == id and .bcharges[i] + GetItemCharges(for) <= MAX_ITEM_CHARGES and .bcharges[i] + GetItemCharges(for) <= it.MaxStacks then
set bonus = GetItemCharges(for)
set .bcharges[i] = .bcharges[i] + bonus
call RemoveItem(for)
return true
endif
set i = i + 1
endloop
elseif .open then
loop
exitwhen i > 5
if .items[i] == id and .charges[i] + GetItemCharges(for) <= MAX_ITEM_CHARGES and .charges[i] + GetItemCharges(for) <= it.MaxStacks then
set bonus = GetItemCharges(for)
call RemoveItem(for)
set .charges[i] = .charges[i] + bonus
return true
endif
set i = i + 1
endloop
set i = 0
loop
exitwhen i > 7
if .backp[i] == id and .bcharges[i] + GetItemCharges(for) <= MAX_ITEM_CHARGES and .bcharges[i] + GetItemCharges(for) <= it.MaxStacks then
set bonus = GetItemCharges(for)
call RemoveItem(for)
set .bcharges[i] = .bcharges[i] + bonus
return true
endif
set i = i + 1
endloop
elseif .bopen then
loop
exitwhen i > 5
if .items[i] == id and .charges[i] + GetItemCharges(for) <= MAX_ITEM_CHARGES and .charges[i] + GetItemCharges(for) <= it.MaxStacks then
set bonus = GetItemCharges(for)
call RemoveItem(for)
set .charges[i] = .charges[i] + bonus
return true
endif
set i = i + 1
endloop
if .bpage <= 1 then
set i = 0
loop
exitwhen i > 3
if GetItemTypeId(UnitItemInSlot(.Owner, i)) == id and GetItemCharges(UnitItemInSlot(.Owner, i)) + GetItemCharges(for) <= MAX_ITEM_CHARGES and GetItemCharges(UnitItemInSlot(.Owner, i)) + GetItemCharges(for) <= it.MaxStacks then
set bonus = GetItemCharges(for)
call RemoveItem(for)
call SetItemCharges(UnitItemInSlot(.Owner, i), GetItemCharges(UnitItemInSlot(.Owner, i)) + bonus)
return true
endif
set i = i + 1
endloop
set i = 4
loop
exitwhen i > 7
if .backp[i] == id and .bcharges[i] + GetItemCharges(for) <= MAX_ITEM_CHARGES and .bcharges[i] + GetItemCharges(for) <= it.MaxStacks then
set bonus = GetItemCharges(for)
call RemoveItem(for)
set .bcharges[i] = .bcharges[i] + bonus
return true
endif
set i = i + 1
endloop
elseif .bpage >= 2 then
set i = 0
loop
exitwhen i > 3
if GetItemTypeId(UnitItemInSlot(.Owner, i)) == id and GetItemCharges(UnitItemInSlot(.Owner, i)) + GetItemCharges(for) <= MAX_ITEM_CHARGES and GetItemCharges(UnitItemInSlot(.Owner, i)) + GetItemCharges(for) <= it.MaxStacks then
set bonus = GetItemCharges(for)
call RemoveItem(for)
call SetItemCharges(UnitItemInSlot(.Owner, i), GetItemCharges(UnitItemInSlot(.Owner, i)) + bonus)
return true
endif
set i = i + 1
endloop
set i = 0
loop
exitwhen i > 3
if .backp[i] == id and .bcharges[i] + GetItemCharges(for) <= MAX_ITEM_CHARGES and .bcharges[i] + GetItemCharges(for) <= it.MaxStacks then
set bonus = GetItemCharges(for)
set .bcharges[i] = .bcharges[i] + bonus
call RemoveItem(for)
return true
endif
set i = i + 1
endloop
endif
endif
return false
endmethod
//checks if the hero has a empty item slot
public method getSlotForItem takes item for returns boolean
local integer i = 0
local integer id = GetItemTypeId(for)
if not .open and not .bopen then
loop
exitwhen i > 5
if UnitItemInSlot(.Owner, i) == null then
call UnitAddItemToSlotById(.Owner, id, i)
call SetItemCharges(UnitItemInSlot(.Owner, i), GetItemCharges(for))
call RemoveItem(for)
return true
endif
set i = i + 1
endloop
set i = 0
loop
exitwhen i > 7
if .backp[i] == 0 then
set .backp[i] = id
set .bcharges[i] = GetItemCharges(for)
call RemoveItem(for)
set .bfree = .bfree - 1
if not .open or .bopen then
call SetItemCharges(UnitItemInSlot(.Owner, BACKPACK_SLOT), .bfree)
endif
return true
endif
set i = i + 1
endloop
elseif .open then
loop
exitwhen i > 5
if .items[i] == 0 then
set .items[i] = id
set .charges[i] = GetItemCharges(for)
call RemoveItem(for)
return true
endif
set i = i + 1
endloop
set i = 0
loop
exitwhen i > 7
if .backp[i] == 0 then
set .backp[i] = id
set .bcharges[i] = GetItemCharges(for)
call RemoveItem(for)
set .bfree = .bfree - 1
if not .open or .bopen then
call SetItemCharges(UnitItemInSlot(.Owner, BACKPACK_SLOT), .bfree)
endif
return true
endif
set i = i + 1
endloop
elseif .bopen then
if .bpage <= 1 then
set i = 0
loop
exitwhen i > 3
if UnitItemInSlot(.Owner, i) == null then
call UnitAddItemToSlotById(.Owner, id, i)
call SetItemCharges(UnitItemInSlot(.Owner, i), GetItemCharges(for))
call RemoveItem(for)
return true
endif
set i = i + 1
endloop
set i = 4
loop
exitwhen i > 7
if .backp[i] == 0 then
set .backp[i] = id
set .bcharges[i] = GetItemCharges(for)
call RemoveItem(for)
return true
endif
set i = i + 1
endloop
set i = 0
loop
exitwhen i > 5
if .items[i] == 0 then
set .items[i] = id
set .charges[i] = GetItemCharges(for)
call RemoveItem(for)
return true
endif
set i = i + 1
endloop
elseif .bpage >= 2 then
set i = 0
loop
exitwhen i > 3
if UnitItemInSlot(.Owner, i) == null then
call UnitAddItemToSlotById(.Owner, id, i)
call SetItemCharges(UnitItemInSlot(.Owner, i), GetItemCharges(for))
call RemoveItem(for)
return true
endif
set i = i + 1
endloop
set i = 0
loop
exitwhen i > 3
if .backp[i] == 0 then
set .backp[i] = id
set .bcharges[i] = GetItemCharges(for)
call RemoveItem(for)
return true
endif
set i = i + 1
endloop
set i = 0
loop
exitwhen i > 5
if .items[i] == 0 then
set .items[i] = id
set .charges[i] = GetItemCharges(for)
call RemoveItem(for)
return true
endif
set i = i + 1
endloop
endif
endif
return false
endmethod
private effect array fx[8] //attached effects of the items
//Applies the item's stats to the hero
private method applyItemStats takes Item it returns nothing
call AddUnitBonus(.Owner, BONUS_ARMOR, it.Armor)
call AddUnitBonus(.Owner, BONUS_DAMAGE, it.Dmg)
call AddUnitBonus(.Owner, BONUS_ATTACK_SPEED, it.As)
call AddUnitBonus(.Owner, BONUS_LIFE_REGEN, it.HpReg)
call AddUnitBonus(.Owner, BONUS_MANA_REGEN_PERCENT, it.MpReg)
call AddUnitBonus(.Owner, BONUS_STRENGTH, it.Str)
call AddUnitBonus(.Owner, BONUS_AGILITY, it.Agi)
call AddUnitBonus(.Owner, BONUS_INTELLIGENCE, it.Int)
call AddUnitBonus(.Owner, BONUS_LIFE, it.Life)
call AddUnitBonus(.Owner, BONUS_MANA, it.Mana)
call AddUnitBonus(.Owner, BONUS_MOVEMENT_SPEED, it.Ms)
if it.Effect != "" and it.EffectAttach != "" then
set .fx[it.Slot] = AddSpecialEffectTarget(it.Effect, .Owner, it.EffectAttach)
endif
if it.Abil != 0 then
call UnitAddAbility(.Owner, it.Abil)
endif
endmethod
//removes the ItemStats for the hero
private method removeItemStats takes Item it returns nothing
call AddUnitBonus(.Owner, BONUS_ARMOR, - it.Armor)
call AddUnitBonus(.Owner, BONUS_DAMAGE, - it.Dmg)
call AddUnitBonus(.Owner, BONUS_ATTACK_SPEED, - it.As)
call AddUnitBonus(.Owner, BONUS_LIFE_REGEN, - it.HpReg)
call AddUnitBonus(.Owner, BONUS_MANA_REGEN_PERCENT, - it.MpReg)
call AddUnitBonus(.Owner, BONUS_STRENGTH, - it.Str)
call AddUnitBonus(.Owner, BONUS_AGILITY, - it.Agi)
call AddUnitBonus(.Owner, BONUS_INTELLIGENCE, - it.Int)
call AddUnitBonus(.Owner, BONUS_LIFE, - it.Life)
call AddUnitBonus(.Owner, BONUS_MANA, - it.Mana)
call AddUnitBonus(.Owner, BONUS_MOVEMENT_SPEED, - it.Ms)
if it.Effect != "" and it.EffectAttach != "" then
call DestroyEffect(.fx[it.Slot])
endif
if it.Abil != 0 then
call UnitRemoveAbility(.Owner, it.Abil)
endif
endmethod
//returns the slot of an item
private method getItemSlot takes item it returns integer
local item temp = null
local integer i = 0
loop
set temp = UnitItemInSlot(.Owner, i)
exitwhen i > 5 or temp == it
set i = i + 1
endloop
set temp = null
return i
endmethod
//Returns the first free Inventory slot of the hero
private method getFreeSlot takes nothing returns integer
local integer i = 0
local integer free
loop
exitwhen i > 4
if .items[i] == 0 then
set free = i
endif
exitwhen .items[i] == 0
set i = i + 1
endloop
return free
endmethod
//Returns the first free backpack slot of the hero
private method getFreeBackpackSlot takes nothing returns integer
local integer i = 0
local integer free
loop
exitwhen i > 7
if .backp[i] == 0 then
set free = i
endif
exitwhen .backp[i] == 0
set i = i + 1
endloop
return free
endmethod
//Returns the free place of the hero's backpack
private method getBackpackPlace takes nothing returns integer
local integer i = 0
local integer i2 = 8
loop
exitwhen i > 7
if .backp[i] != 0 then
set i2 = i2 - 1
endif
set i = i + 1
endloop
return i2
endmethod
//Returns the free place of the hero's Inventory
private method getInventoryPlace takes nothing returns integer
local integer i = 0
local integer i2 = 4
loop
exitwhen i > 3
if .items[i] != 0 then
set i2 = i2 - 1
endif
set i = i + 1
endloop
return i2
endmethod
//moves an item to the hero's backpack
private method moveToBackpack takes item Moved, item Bag returns boolean
local integer i = 0
local integer id = GetItemTypeId(Moved)
local integer Slot
local Item it = Item.getItemById(id)
if .getBackpackPlace() > 0 then
loop
exitwhen i > 7
if .backp[i] == id and .bcharges[i] + GetItemCharges(Moved) <= MAX_ITEM_CHARGES and .bcharges[i] + GetItemCharges(Moved) <= it.MaxStacks and it.AllowStacks then
set .bcharges[i] = .bcharges[i] + GetItemCharges(Moved)
call RemoveItem(Bag)
call RemoveItem(Moved)
call UnitAddItemToSlotById(.Owner, BACKPACK_OPEN_ID, BACKPACK_SLOT)
call SetItemCharges(UnitItemInSlot(.Owner, BACKPACK_SLOT), .bfree)
return true
endif
set i = i + 1
endloop
set i = 0
loop
exitwhen i > 7
if .backp[i] == 0 then
set .backp[i] = id
set .bcharges[i] = GetItemCharges(Moved)
set .bfree = .bfree - 1
call RemoveItem(Bag)
call RemoveItem(Moved)
call UnitAddItemToSlotById(.Owner, BACKPACK_OPEN_ID, BACKPACK_SLOT)
call SetItemCharges(UnitItemInSlot(.Owner, BACKPACK_SLOT), .bfree)
return true
endif
set i = i + 1
endloop
elseif .getBackpackPlace() <= 0 then
set Slot = .getItemSlot(Moved)
set i = GetItemCharges(Moved)
call RemoveItem(Bag)
call RemoveItem(Moved)
call UnitAddItemToSlotById(.Owner, BACKPACK_OPEN_ID, BACKPACK_SLOT)
call SetItemCharges(UnitItemInSlot(.Owner, BACKPACK_SLOT), .bfree)
call UnitAddItemToSlotById(.Owner, id, Slot)
call SetItemCharges(UnitItemInSlot(.Owner, Slot), i)
call SimError(GetOwningPlayer(.Owner), "Backpack is full!")
return false
endif
return false
endmethod
//moves an item from the first page to the second page
private method moveToSecondPage takes item Moved, item Second returns boolean
local integer i = 0
local integer id = GetItemTypeId(Moved)
local integer Slot
loop
exitwhen i > 3
if .backp[i+4] == id and .bcharges[i+4] + GetItemCharges(Moved) <= MAX_ITEM_CHARGES and .bcharges[i+4] + GetItemCharges(Moved) <= Item.getItemById(GetItemTypeId(Moved)).MaxStacks then
set .bcharges[i+4] = .bcharges[i+4] + GetItemCharges(Moved)
call RemoveItem(Second)
call RemoveItem(Moved)
call UnitAddItemToSlotById(.Owner, BACKPACK_PAGE_2, 4)
return true
endif
set i = i + 1
endloop
set i = 0
loop
exitwhen i > 3
if .backp[i+4] == 0 then
set .backp[i+4] = id
set .bcharges[i+4] = GetItemCharges(Moved)
call RemoveItem(Second)
call RemoveItem(Moved)
call UnitAddItemToSlotById(.Owner, BACKPACK_PAGE_2, 4)
return true
endif
set i = i + 1
endloop
set Slot = .getItemSlot(Moved)
set i = GetItemCharges(Moved)
call RemoveItem(Second)
call RemoveItem(Moved)
call UnitAddItemToSlotById(.Owner, BACKPACK_PAGE_2, 4)
call UnitAddItemToSlotById(.Owner, id, Slot)
call SetItemCharges(UnitItemInSlot(.Owner, Slot), i)
call SimError(GetOwningPlayer(.Owner), "Cannot move item to a full page!")
return false
endmethod
//moves an item from the second page to the first page
private method moveToFirstPage takes item Moved, item First returns boolean
local integer i = 0
local integer id = GetItemTypeId(Moved)
local integer Slot
loop
exitwhen i > 3
if .backp[i] == id and .bcharges[i] + GetItemCharges(Moved) <= MAX_ITEM_CHARGES and .bcharges[i] + GetItemCharges(Moved) <= Item.getItemById(GetItemTypeId(Moved)).MaxStacks then
set .bcharges[i] = .bcharges[i] + GetItemCharges(Moved)
call RemoveItem(First)
call RemoveItem(Moved)
call UnitAddItemToSlotById(.Owner, BACKPACK_PAGE_1, 4)
return true
endif
set i = i + 1
endloop
set i = 0
loop
exitwhen i > 3
if .backp[i] == 0 then
set .backp[i] = id
set .bcharges[i] = GetItemCharges(Moved)
call RemoveItem(First)
call RemoveItem(Moved)
call UnitAddItemToSlotById(.Owner, BACKPACK_PAGE_1, 4)
return true
endif
set i = i + 1
endloop
set Slot = .getItemSlot(Moved)
set i = GetItemCharges(Moved)
call RemoveItem(First)
call RemoveItem(Moved)
call UnitAddItemToSlotById(.Owner, BACKPACK_PAGE_1, 4)
call UnitAddItemToSlotById(.Owner, id, Slot)
call SetItemCharges(UnitItemInSlot(.Owner, Slot), i)
call SimError(GetOwningPlayer(.Owner), "Cannot move item to a full page!")
return false
endmethod
//moves an item to the heroes inventory
private method moveToInventory takes item Moved, item Close returns boolean
local integer i = 0
local integer id = GetItemTypeId(Moved)
local integer Slot
local Item it = Item.getItemById(id)
set .allowauto = false
if .getInventoryPlace() > 0 then
loop
exitwhen i > 3
if .items[i] == id and .charges[i] + GetItemCharges(Moved) <= MAX_ITEM_CHARGES and .charges[i] + GetItemCharges(Moved) <= it.MaxStacks and it.AllowStacks then
set .charges[i] = .charges + GetItemCharges(Moved)
set .bfree = .bfree + 1
call RemoveItem(Close)
call RemoveItem(Moved)
call UnitAddItemToSlotById(.Owner, BACKPACK_CLOSE_ID, 5)
set .allowauto = true
return true
endif
set i = i + 1
endloop
set i = .getFreeSlot()
set .items[i] = id
set .charges[i] = GetItemCharges(Moved)
set .bfree = .bfree + 1
call RemoveItem(Close)
call RemoveItem(Moved)
call UnitAddItemToSlotById(.Owner, BACKPACK_CLOSE_ID, 5)
set .allowauto = true
return true
elseif .getInventoryPlace() <= 0 then
set Slot = .getItemSlot(Moved)
set i = GetItemCharges(Moved)
call RemoveItem(Close)
call RemoveItem(Moved)
call UnitAddItemToSlotById(.Owner, BACKPACK_CLOSE_ID, 5)
call UnitAddItemToSlotById(.Owner, id, Slot)
call SetItemCharges(UnitItemInSlot(.Owner, Slot), i)
call SimError(GetOwningPlayer(.Owner), "Inventory is full!")
set .allowauto = true
return false
endif
set .allowauto = true
return false
endmethod
//checks, if a hero can equip an item
public method checkHero takes Item it, boolean UseError returns boolean
if it.HeroClasses != "" then
if not SearchString(it.HeroClasses, .HeroClass) then
if UseError then
call SimError(GetOwningPlayer(.Owner), "Only " + it.HeroClasses + " can equip this item.")
endif
return false
endif
endif
if it.ItemClass != "" then
if not SearchString(.ItemClasses, it.ItemClass) then
if UseError then
call SimError(GetOwningPlayer(.Owner), "This unit can't equip " + it.ItemClass + ".")
endif
return false
endif
endif
if GetHeroLevel(.Owner) >= it.Level then
return true
else
if UseError then
call SimError(GetOwningPlayer(.Owner), "This item requires a hero level of " + I2S(it.Level) + " or greater.")
endif
endif
return false
endmethod
//will be runned, whenever an item is used
private static method useItem takes nothing returns boolean
local thistype this = .table[GetTriggerUnit()]
local Item it = Item.getItemById(GetItemTypeId(GetManipulatedItem()))
if GetItemTypeId(GetManipulatedItem()) == EQUIPMENT_OPEN_ID then
return .openEquipment(GetTriggerUnit())
elseif GetItemTypeId(GetManipulatedItem()) == BACKPACK_OPEN_ID then
return .openBackpack(GetTriggerUnit())
elseif GetItemTypeId(GetManipulatedItem()) == EQUIPMENT_CLOSE_ID or GetItemTypeId(GetManipulatedItem()) == BACKPACK_CLOSE_ID then
if .open then
return .closeEquipment(GetTriggerUnit())
elseif .bopen then
return .closeBackpack(GetTriggerUnit())
endif
elseif GetItemTypeId(GetManipulatedItem()) == EQUIPMENT_PAGE_1 or GetItemTypeId(GetManipulatedItem()) == EQUIPMENT_PAGE_2 or GetItemTypeId(GetManipulatedItem()) == BACKPACK_PAGE_1 or GetItemTypeId(GetManipulatedItem()) == BACKPACK_PAGE_2 then
if .open then
return .changePageEquipment(GetTriggerUnit())
elseif .bopen then
return .changePageBackpack(GetTriggerUnit())
endif
elseif it.Equipment and not .isItemEquipped(GetManipulatedItem()) then
return .equipItem(GetTriggerUnit(), GetManipulatedItem(), it)
elseif it.Equipment and .isItemEquipped(GetManipulatedItem()) and .open then
return .unequipItem(GetTriggerUnit(), GetManipulatedItem(), it)
endif
return false
endmethod
//Will be runned, whenever an item is dragged on another item or on an empty slot
private static method dragItem takes nothing returns boolean
local item manipul = GetOrderTargetItem()
local integer slot = GetIssuedOrderId() - 852002
local thistype this = .table[GetTriggerUnit()]
local item dropped = UnitItemInSlot(.Owner, slot)
local integer id = GetItemTypeId(manipul)
local integer idd = GetItemTypeId(dropped)
if (GetIssuedOrderId() > 852001) and (GetIssuedOrderId() < 852008) and this != 0 then
if manipul != dropped and id != BACKPACK_PAGE_1 and id != BACKPACK_PAGE_2 and id != BACKPACK_CLOSE_ID and id != BACKPACK_OPEN_ID then
if idd == BACKPACK_OPEN_ID then
set .dropped = false
call .moveToBackpack(manipul, dropped)
set .dropped = true
set manipul = null
set dropped = null
return false
elseif idd == BACKPACK_CLOSE_ID then
set .dropped = false
call .moveToInventory(manipul, dropped)
set .dropped = true
set manipul = null
set dropped = null
return false
elseif idd == BACKPACK_PAGE_2 then
set .dropped = false
call .moveToSecondPage(manipul, dropped)
set .dropped = true
set manipul = null
set dropped = null
return false
elseif idd == BACKPACK_PAGE_1 then
set .dropped = false
call .moveToFirstPage(manipul, dropped)
set .dropped = true
set manipul = null
set dropped = null
return false
endif
endif
endif
if id == BACKPACK_OPEN_ID or id == BACKPACK_CLOSE_ID or id == BACKPACK_PAGE_1 or id == BACKPACK_PAGE_2 and dropped == null then
if id == BACKPACK_OPEN_ID and not .bopen and not .open then
call SimError(GetOwningPlayer(.Owner), "Cannot drop this item.")
call addItem.create(manipul, BACKPACK_SLOT, this)
set manipul = null
set dropped = null
return false
elseif id == BACKPACK_CLOSE_ID or id == BACKPACK_PAGE_1 or id == BACKPACK_PAGE_2 and .bopen then
call SimError(GetOwningPlayer(.Owner), "Cannot drop this item.")
if id == BACKPACK_CLOSE_ID then
call addItem.create(manipul, 5, this)
elseif id == BACKPACK_PAGE_1 or id == BACKPACK_PAGE_2 then
call addItem.create(manipul, 4, this)
endif
set manipul = null
set dropped = null
return false
endif
endif
if (id == BACKPACK_PAGE_1 or id == BACKPACK_PAGE_2) and idd == BACKPACK_CLOSE_ID and .bopen then
call SimError(GetOwningPlayer(.Owner), "Cannot drop this item.")
call addItem.create(manipul, 4, this)
call addItem.create(dropped, 5, this)
set manipul = null
set dropped = null
return false
elseif id == BACKPACK_CLOSE_ID and (idd == BACKPACK_PAGE_1 or idd == BACKPACK_PAGE_2) and .bopen then
call SimError(GetOwningPlayer(.Owner), "Cannot drop this item.")
call addItem.create(manipul, 5, this)
call addItem.create(dropped, 4, this)
set manipul = null
set dropped = null
return false
endif
set manipul = null
set dropped = null
return true
endmethod
//will be runned whenever an item is picked up
private static method pickupItem takes nothing returns boolean
local thistype this = .table[GetTriggerUnit()]
local item i = GetManipulatedItem()
local Item it = Item.getItemById(GetItemTypeId(i))
if AUTO_EQUIP and it.Equipment and .isSlotEmpty(it.Slot) and .checkHero(it, false) and .allowauto then
call thistype.equipItem(GetTriggerUnit(), GetManipulatedItem(), it)
set i = null
return true
endif
return false
endmethod
//Will be runned whenever an item is dropped
private static method dropItem takes nothing returns boolean
local thistype this = .table[GetTriggerUnit()]
local item ite = GetManipulatedItem()
local integer id = GetItemTypeId(ite)
if this == 0 or ite == null or not .dropped then
return false
elseif this != 0 and ite != null and .dropped then
if id == BACKPACK_OPEN_ID and not .bopen and not .open then
call SimError(GetOwningPlayer(.Owner), "Cannot drop this item.")
call addItem.create(ite, BACKPACK_SLOT, this)
set ite = null
return true
elseif id == BACKPACK_CLOSE_ID or id == BACKPACK_PAGE_1 or id == BACKPACK_PAGE_2 and (.bopen or .open) then
if id == BACKPACK_CLOSE_ID then
call SimError(GetOwningPlayer(.Owner), "Cannot drop this item.")
call addItem.create(ite, 5, this)
set ite = null
return true
elseif id == BACKPACK_PAGE_1 or id == BACKPACK_PAGE_2 then
call SimError(GetOwningPlayer(.Owner), "Cannot drop this item.")
call addItem.create(ite, 4, this)
set ite = null
return true
endif
endif
endif
return false
endmethod
private static trigger Use = CreateTrigger()
private static trigger Pickup = CreateTrigger()
private static trigger Drag = CreateTrigger()
private static trigger Drop = CreateTrigger()
//initialization of the Inventory struct
private static method onInit takes nothing returns nothing
call TriggerAddCondition(.Use, Condition(function thistype.useItem))
call TriggerAddCondition(.Pickup, Condition(function thistype.pickupItem))
call TriggerAddCondition(.Drag, Condition(function thistype.dragItem))
call TriggerAddCondition(.Drop, Condition(function thistype.dropItem))
set .table = HandleTable.create()
call SETUP_DUMMY_ITEMS()
endmethod
endstruct
endlibrary