//:-----<-->----<-->----<-->----<-->----<-->----<-->----
//: AdvancedInventoryHandling
//: by dhk_undead_lord / aka Anachron
//:
//: Table of Content
//: *==============*
//: 1.) About
//: 2.) Importing
//: 3.) Features
//: 4.) Misc
//:
//: > ABOUT
//: --------
//:
//: This system allows to create dynamically inventories
//: which can held item and its effects.
//:
//: This system also allows you, the user, to create any
//: aspect of the item easily. If you want drop, pick or
//: use events, you can simply define them at item creation.
//:
//: Please note that this is the first Beta, so it might
//: has less features, but it works and I think its very nice.
//:
//: > IMPORTING
//: --------------
//:
//: I.) Copy this code.
//: II.) Paste it into the head of your map.
//: (Therefor go to the Trigger Editor, select the mapname and paste
//: into the area on the right)
//: III.) Save your map!
//: (With File - Save Map (S) or control + S. DO NOT SAVE WITH SAVE AS!)
//: IV.) You got it! You imported the system.
//:
//: To make sure this system works, you should try a few tests!
//:
//: > FEATURES
//: --------------
//:
//: * Create endless item wildcards
//: * Let the system automaticly handle items
//: * Load / Save Inventories easily
//: * Many more!
//:
//: > MISC
//: ----------
//:
//: Version: 1.00 Beta
//: A better docu to come!
//:
//:-----<-->----<-->----<-->----<-->----<-->----<-->----
library AdInvHan initializer init requires Table, AttMod
//==#=======================================#
//== USER CONFIGURATEABLE AREA =============>
//==#=======================================#
globals
//: Define the amount of maximum items
//: being in an inventory
//: DEFAULT: bj_MAX_INVENTORY
constant integer INV_PLACES = 6
//: Define whether items should be dropped
//: on inventory object destruction or not.
//: If not dropped, the items will be removed.
//: DEFAULT: false
constant boolean INV_DROP_ON_DESTROY = false
//: Sets whether all units on the map
//: automaticly gets inventory objects or not.
//: WARNING: IF YOU SET THIS TO FALSE AND THE
//: UNIT HAS NO INVENTORY, ITEMS WILL NOT
//: WORK FOR IT!
//: DEFAULT: true
constant boolean INV_GENERATE_AUTO = true
//: Sets whether all units on the map
//: automaticly loose inventory objects or not.
//: WARNING: IF YOU SET THIS TO TRUE, ITEMs
//: WILL NOT WORK FOR IT!
//: DEFAULT: true
constant boolean INV_REMOVE_AUTO = true
//: Sets whether the item should be checked
//: to apply to the condition function or not.
//: If the ConditionFunction returns false,
//: the itemObj instance can't created.
//: DEFAULT: true
constant boolean ITEMOBJ_CHECK_AUTO = true
//: Sets whether itemobjects should be
//: automaticly created on pickup or not.
//: DEFAULT: true
constant boolean ITEMOBJ_GENERATE_AUTO = true
//: Sets whether itemobjects should be
//: automaticly destroyed on drop or not.
//: DEFAULT: true
constant boolean ITEMOBJ_REMOVE_AUTO = true
//: Sets whether the statmod should be applied
//: automaticly on pickup
//: DEFAULT: true
constant boolean ADDMOD_PICKUP_APPLIES = true
//: Sets whether the statmod should be removed
//: automaticly on drop
//: DEFAULT: true
constant boolean ADDMOD_DROP_REMOVES = true
endglobals
//==#=======================================\\
//== DO NOT TOUCH THIS! ====================\\
//==#=======================================\\
globals
private trigger SYSTEM_TRIG = CreateTrigger()
private constant integer ID_NULL = -1
endglobals
//== GENERAL ITEM INTERFACES ====================>
//== GENERAL ITEM INTERFACES ====================>
function interface onPickup takes nothing returns nothing
function interface onDrop takes nothing returns nothing
function interface onUse takes nothing returns nothing
function interface onCheck takes nothing returns boolean
//== ITEM WILDCARD ===================>
//: #=#=#=#=#=#=#=#=#=#=#=#=
//: ItemWildcard
//: #=#=#=#=#=#=#=#=#=#=#=#=
struct itemWC
//: =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//: Storage members
//: =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
integer itemID = 0
item dummy = null
//: =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//: Attached itemdata
//: =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
AttributeMod AttMod = ID_NULL
//: =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//: Attached interface for advanced usage
//: =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
onPickup pickAct = ID_NULL
onDrop dropAct = ID_NULL
onUse useAct = ID_NULL
onCheck checkAct = ID_NULL
public static method create takes integer itID, AttributeMod mod returns thistype
local thistype itwc = thistype.allocate()
set itwc.itemID = itID
set itwc.AttMod = mod
set itwc.dummy = CreateItem(itID, 0., 0.)
call SetItemVisible(itwc.dummy, false)
call SetItemInvulnerable(itwc.dummy, true)
return itwc
endmethod
endstruct
//: #=#=#=#=#=#=#=#=#=#=#=#=
//: Load & Save Wildcards
//: #=#=#=#=#=#=#=#=#=#=#=#=
globals
private Table itWcTab = 0
endglobals
public function LoadWildCard takes item it returns itemWC
return itemWC(itWcTab[GetItemTypeId(it)])
endfunction
public function SaveWildCard takes itemWC itWC returns nothing
set itWcTab[GetItemTypeId(itWC.dummy)] = integer(itWC)
endfunction
public function DestroyWildCard takes item it returns nothing
call itWcTab.flush(GetItemTypeId(it))
endfunction
//== ITEM OBJECT =====================>
//: #=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=
//: Create items based on WildCard
//: #=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=
public function CreateItemObj takes item it, unit u returns itemObj
local itemObj io = itemObj.create(it, u)
local itemWC iwc = ID_NULL
set iwc = LoadWildCard(it)
if iwc != ID_NULL and io != ID_NULL then
debug call BJDebugMsg(SCOPE_PREFIX + "NOTICE [CreateItemObj]: Loaded wildcard for item with type " + GetItemName(it) + ".")
set io.AttMod = iwc.AttMod
set io.pickAct = iwc.pickAct
set io.dropAct = iwc.dropAct
set io.useAct = iwc.useAct
set io.checkAct = iwc.checkAct
else
debug call BJDebugMsg(SCOPE_PREFIX + "NOTICE [CreateItemObj]: Could not load wildcard for item with type " + GetItemName(it) + ".")
endif
if ITEMOBJ_CHECK_AUTO then
if not io.onCheckEvent() then
debug call BJDebugMsg(SCOPE_PREFIX + "NOTICE [create]: ItemObj has been destroyed (False return).")
call DisableTrigger(SYSTEM_TRIG)
call SetItemPosition(it, GetUnitX(u), GetUnitY(u))
call EnableTrigger(SYSTEM_TRIG)
call io.destroy()
set io = ID_NULL
endif
endif
return io
endfunction
//: #=#=#=#=#=#=#=#=#=#=#=#=
//: ItemObject
//: #=#=#=#=#=#=#=#=#=#=#=#=
struct itemObj
//: =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//: Item attributes saved in object
//: =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
integer Type = 0
player Owner = null
item Handle = null
integer Charges = 0
integer Level = 0
string Name = null
integer UserData = 0
real LocX = 0.
real LocY = 0.
itemtype Class = null
unit Carrier = null
//: =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//: Attached itemdata
//: =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
AttributeMod AttMod = ID_NULL
//: =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//: Attached interface for advanced usage
//: =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
onPickup pickAct = ID_NULL
onDrop dropAct = ID_NULL
onUse useAct = ID_NULL
onCheck checkAct = ID_NULL
//: =-=-=-=-=-=-=-=-=-=-
//: General Object
//: =-=-=-=-=-=-=-=-=-=-
integer objID = ID_NULL
//: #=#=#=#=#=#=#=#=#=#=#=#=
//: Object Methods
//: #=#=#=#=#=#=#=#=#=#=#=#=
public method onCheckEvent takes nothing returns boolean
if .checkAct != ID_NULL then
debug call BJDebugMsg(SCOPE_PREFIX + "NOTICE [onCheckEvent]: Check stats.")
return .checkAct.evaluate()
else
return true
endif
endmethod
public method onPickEvent takes nothing returns nothing
if .pickAct != ID_NULL then
call .pickAct.execute()
debug call BJDebugMsg(SCOPE_PREFIX + "NOTICE [onPickEvent]: Run interface.")
endif
if .AttMod != ID_NULL then
if ADDMOD_PICKUP_APPLIES then
set TMP_UNIT = .Carrier
call .AttMod.apply()
debug call BJDebugMsg(SCOPE_PREFIX + "NOTICE [onPickEvent]: Itemstats applied to hero.")
endif
endif
endmethod
public method onDropEvent takes nothing returns nothing
if .dropAct != ID_NULL then
call .dropAct.execute()
debug call BJDebugMsg(SCOPE_PREFIX + "NOTICE [onDropEvent]: Run interface.")
endif
if .AttMod != ID_NULL then
if ADDMOD_DROP_REMOVES then
set TMP_UNIT = .Carrier
call .AttMod.remove()
debug call BJDebugMsg(SCOPE_PREFIX + "NOTICE [onPickEvent]: Itemstats removed from hero.")
endif
endif
endmethod
public method onUseEvent takes nothing returns nothing
call .useAct.execute()
endmethod
public method updateData takes nothing returns nothing
set .Charges = GetItemCharges(.Handle)
set .Level = GetItemLevel(.Handle)
set .Name = GetItemName(.Handle)
set .UserData = GetItemUserData(.Handle)
set .LocX = GetItemX(.Handle)
set .LocY = GetItemY(.Handle)
set .Class = GetItemType(.Handle)
set .Type = GetItemTypeId(.Handle)
set .Owner = GetItemPlayer(.Handle)
endmethod
public method updateHandles takes item i, unit u returns nothing
set .Handle = i
set .Carrier = u
endmethod
public static method create takes item i, unit u returns thistype
local thistype iO = thistype.allocate()
call iO.updateData()
call iO.updateHandles(i, u)
return iO
endmethod
endstruct
//== INVENTORY OBJECT =====================>
//: #=#=#=#=#=#=#=#=#=#=#=#=
//: InventoryObject
//: #=#=#=#=#=#=#=#=#=#=#=#=
struct InventoryObj
//: =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//: Inventory data saved in object
//: =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
itemObj array itemObjects[INV_PLACES]
integer itemInt = 0
unit owner = null
//: #=#=#=#=#=#=#=#=#=#=#=#=
//: Object Methods
//: #=#=#=#=#=#=#=#=#=#=#=#=
public static method create takes unit u returns thistype
local thistype inv = thistype.allocate()
set inv.owner = u
return inv
endmethod
public method loadItems takes nothing returns nothing
local integer i = 0
local boolean e = false
local item it = null
loop
exitwhen e
set it = UnitItemInSlot(.owner, i)
if it != null then
call .addItem(it)
endif
if i >= 6 then
set e = true
else
set i = i + 1
endif
endloop
endmethod
public static method createAndLoad takes unit u returns thistype
local thistype inv = thistype.create(u)
call inv.loadItems()
return inv
endmethod
//: #=#=#=#=#=#=#=#=#=#=#=#=
//: Add and remove items
//: #=#=#=#=#=#=#=#=#=#=#=#=
public method addItem takes item it returns nothing
local itemObj tmp = CreateItemObj(it, .owner)
if tmp != ID_NULL then
call tmp.onPickEvent()
set .itemObjects[.itemInt] = tmp
set .itemInt = .itemInt + 1
else
debug call BJDebugMsg(SCOPE_PREFIX + "NOTICE [addItem]: ItemObj could not be created.")
endif
endmethod
public method removeItem takes item it returns nothing
local integer i = 0
local itemObj tmp = 0
local boolean e = false
loop
exitwhen e
set tmp = .itemObjects[i]
if tmp.Handle == it then
call tmp.onDropEvent()
call tmp.destroy()
set .itemObjects[i] = .itemObjects[.itemInt]
set .itemInt = .itemInt - 1
set e = true
else
if i >= .itemInt then
set e = true
debug call BJDebugMsg(SCOPE_PREFIX + "ERROR [removeItem]: The item was not found.")
else
set i = i + 1
endif
endif
endloop
endmethod
//: #=#=#=#=#=#=#=#=#=#=#=#=
//: GetItemsFromInventory
//: #=#=#=#=#=#=#=#=#=#=#=#=
public method getItemObjFromSlot takes integer i returns itemObj
if i <= .itemInt and i >= 0 then
return .itemObjects[i]
else
debug call BJDebugMsg(SCOPE_PREFIX + "ERROR [getItemObjFromSlot]: All slots are already taken.")
return ID_NULL
endif
endmethod
public method getItemObjFromItem takes item it returns itemObj
local itemObj io = 0
local integer i = 0
local boolean e = false
loop
exitwhen e
set io = .itemObjects[i]
if io.Handle == it then
set e = true
else
if i >= .itemInt then
set e = true
set io = -1
else
set i = i + 1
endif
endif
endloop
return io
endmethod
public method getItemFromSlot takes integer i returns item
if i <= .itemInt and i >= 0 then
return .itemObjects[i].Handle
else
return null
endif
endmethod
//: #=#=#=#=#=#=#=#=#=#=#=#=
//: Destructor Method
//: #=#=#=#=#=#=#=#=#=#=#=#=
private method onDestroy takes nothing returns nothing
local itemObj io = 0
local integer i = 0
local boolean e = false
loop
exitwhen e
set io = .itemObjects[i]
if INV_DROP_ON_DESTROY then
call UnitDropItem(.owner, io.Type)
else
call io.destroy()
call RemoveItem(io.Handle)
endif
if i >= .itemInt then
set e = true
else
set i = i + 1
endif
endloop
endmethod
endstruct
//: #=#=#=#=#=#=#=#=#=#=#=#=
//: Load & Save Inventories
//: #=#=#=#=#=#=#=#=#=#=#=#=
globals
private HandleTable invTab = 0
endglobals
public function LoadInventory takes unit u returns InventoryObj
return InventoryObj(invTab[u])
endfunction
public function SaveInventory takes InventoryObj inv returns nothing
set invTab[inv.owner] = integer(inv)
endfunction
public function DestroyInventory takes unit u returns nothing
call invTab.flush(u)
endfunction
//== SYSTEM FUNCTIONS ======================>
private function sys_PickUpItem takes nothing returns nothing
local InventoryObj inv = LoadInventory(GetTriggerUnit())
if inv != ID_NULL then
call inv.addItem(GetManipulatedItem())
else
debug call BJDebugMsg(SCOPE_PREFIX + "ERROR [sys_PickUpItem]: Unit has no inventory")
endif
endfunction
private function sys_DropItem takes nothing returns nothing
local InventoryObj inv = LoadInventory(GetTriggerUnit())
if inv != ID_NULL then
call inv.removeItem(GetManipulatedItem())
else
debug call BJDebugMsg(SCOPE_PREFIX + "ERROR [sys_DropItem]: Unit has no inventory")
endif
endfunction
private function sys_registerUnit takes nothing returns nothing
call SaveInventory(InventoryObj.create(GetTriggerUnit()))
endfunction
private function sys_unregisterUnit takes nothing returns nothing
call DestroyInventory(GetTriggerUnit())
endfunction
private function eventHandler takes nothing returns nothing
local eventid eventID = GetTriggerEventId()
if eventID == EVENT_PLAYER_UNIT_PICKUP_ITEM then
debug call BJDebugMsg(SCOPE_PREFIX + "NOTICE -> PICKUP ITEM")
call sys_PickUpItem()
elseif eventID == EVENT_PLAYER_UNIT_DROP_ITEM then
debug call BJDebugMsg(SCOPE_PREFIX + "NOTICE -> DROP ITEM")
call sys_DropItem()
elseif eventID == EVENT_PLAYER_UNIT_DEATH then
debug call BJDebugMsg(SCOPE_PREFIX + "NOTICE -> DESTROY INVENTORY")
call sys_unregisterUnit()
else
debug call BJDebugMsg(SCOPE_PREFIX + "NOTICE -> CREATE INVENTORY")
call sys_registerUnit()
endif
endfunction
private function onlyHeroes takes nothing returns boolean
return not IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO)
endfunction
private function returnTrue takes nothing returns boolean
return true
endfunction
private function init takes nothing returns nothing
local integer i = 0
local rect rec = bj_mapInitialPlayableArea
local region reg = CreateRegion()
local boolexpr expr = Condition(function onlyHeroes)
call TriggerAddAction(SYSTEM_TRIG, function eventHandler)
if ITEMOBJ_GENERATE_AUTO then
call RegionAddRect(reg, rec)
call TriggerRegisterEnterRegion(SYSTEM_TRIG, reg, expr)
endif
call DestroyBoolExpr(expr)
set expr = Condition(function returnTrue)
loop
exitwhen i > 15
if ITEMOBJ_GENERATE_AUTO then
call TriggerRegisterPlayerUnitEvent(SYSTEM_TRIG, Player(i), EVENT_PLAYER_UNIT_PICKUP_ITEM, expr)
endif
if ITEMOBJ_REMOVE_AUTO then
call TriggerRegisterPlayerUnitEvent(SYSTEM_TRIG, Player(i), EVENT_PLAYER_UNIT_DROP_ITEM, expr)
endif
if INV_REMOVE_AUTO then
call TriggerRegisterPlayerUnitEvent(SYSTEM_TRIG, Player(i), EVENT_PLAYER_UNIT_DEATH, expr)
endif
set i = i + 1
endloop
//: Initialisate the tables!
set itWcTab = Table.create()
set invTab = HandleTable.create()
//call RemoveRect(rec)
//call RemoveRegion(reg)
call DestroyBoolExpr(expr)
set rec = null
set reg = null
set expr = null
endfunction
endlibrary