System ItemStruct 2.0

13lade619

is now a game developer :)
Reaction score
399
Version 1.2

A revamping of the original ItemStruct

What's not yet finished:
Code for Recipe Making.. i.e:

count number of items of class ()
count number of items of type ()
if unit has items of type and number ()
do this for every item of type ()
do this for every item of class ()

Requirements: (Most have their own, check them individually.)
-NewGen
-Latest JassHelper
-AIDS
-Damage
-GT
-TimerUtils
-Status

Documentation.
JASS:
.
        _____  _                    __  _                       _     ____      ___  
        \_   \| |_  ___  _ __ ___  / _\| |_  _ __  _   _   ___ | |_  |___ \    / _ \ 
         / /\/| __|/ _ \| '_ ` _ \ \ \ | __|| '__|| | | | / __|| __|   __) |  | | | |
      /\/ /_  | |_|  __/| | | | | |_\ \| |_ | |   | |_| || (__ | |_   / __/  _| |_| |
      \____/   \__|\___||_| |_| |_|\__/ \__||_|    \__,_| \___| \__| |_____|(_)\___/  1.2.1

              < Original BuffStruct/ItemStruct Concept and Coding by Jesus4Lyf>
                  < ItemStruct Mod for BuffStruct by 13lade619>

      What is ItemStruct 2.0?
     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
          ItemStruct 2.0 is designed for rapid item development for maps. It is designed to automatically 
          create the needed object data to reduce hassle. You can run functions on acquisition and dropping
          of said items. You can also have event-responses associated with the item's holder.


      What ItemStruct 2.0 will not automatically do for you:
     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
          1. You need save and reload the map for the object data to be created.
          2. You will need to manually put the items to their respective shops via the Object Editor.


      How to implement?
     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
          Requires : AIDS, Damage, GT, optional TimerUtils

          1. Create a new trigger named ItemStructHeader. Go to 'Edit -> Convert
          to Custom Text', and replace everything that's there with this script.

          2. Create a new trigger immediately after ItemStructHeader, named
          ItemStructFooter. go to 'Edit -> Convert to Custom Text', and replace
          everything that's there with the script from the ItemStructFooter.

         3. To make an ItemStruct, make a new trigger between ItemStructHeader
         and ItemStructFooter, and use the template indicated on the later part of this documentation.


      Changes from last version (1.2.1).
      ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
          - Added protection for items not created by the system. I found out that these would randomly fire
            rogue drop events and sometimes would result in negative stats.
          
//=========================================================================================================
//  Start Sample        
//

//! runtextmacro ItemType("Sword")
    //! runtextmacro SetItemClass("HAND")
    //! runtextmacro SetItemXY("1","2")
    //! runtextmacro SetItemIcon("ReplaceableTextures\\CommandButtons\\BTNSteelMelee.blp")
    //! runtextmacro SetItemModel("Objects\\InventoryItems\\TreasureChest\\treasurechest.mdl")
    //! runtextmacro SetItemCost("500")
    //! runtextmacro SetItemDesc("Buy this awesome sword.")
    //! runtextmacro SetItemTip("You now have this cool sword.")
    //! runtextmacro SetItemName("Sword")
    //! runtextmacro SetItemAbil("ACfl")
    //! runtextmacro SetItemCat("Artifact")
    //! runtextmacro SetItemCharge("3","1")
    //! runtextmacro SetItemStock("3","1","X")

//! runtextmacro ItemStruct()
    method onAnySpellCast takes nothing returns nothing
        if GetSpellAbilityId() == this.itemAbil then
            call BJDebugMsg("itemspell")
        else
            call BJDebugMsg("anyspell")
        endif
    endmethod
    
    method onDamageReceived takes nothing returns nothing
        if Damage_IsSpell() then
            call BJDebugMsg("magic")
        elseif Damage_IsAttack() then
            call BJDebugMsg("attack")
        endif
    endmethod
    
    method onDamageDealt takes nothing returns nothing
        if Damage_IsSpell() then
            call BJDebugMsg("mtk")
        elseif Damage_IsAttack() then
            call BJDebugMsg("atk")
        endif
    endmethod
    
    method onAcquire takes nothing returns nothing
        call Status[this.unit].modDamageBonus(10)
    endmethod
    
    method onDrop takes nothing returns nothing
        call Status[this.unit].modDamageBonus(-10)
    endmethod
//! runtextmacro EndItem()

//
// End Sample
//=========================================================================================================

         __                _               
        / _\ _   _  _ __  | |_  __ _ __  __
        \ \ | | | || '_ \ | __|/ _` |\ \/ /
        _\ \| |_| || | | || |_| (_| | >  < 
        \__/ \__, ||_| |_| \__|\__,_|/_/\_\ for Objectdata and others.
             |___/                         

    //! runtextmacro ItemType("Identifier")        
                  This must contain a 1 word identifier for the buff. This is
                  used to create new instances with Identifier.create(unit)
                  
        //! runtextmacro SetItemClass("CLAS")    
                  There are 4 predefined Classifications of ItemStructs (can be used as condtions later. 
                  They are ACCS, BOOT, HAND and BODY. 
                  
        //! runtextmacro SetItemXY("X","Y")
                                    ^Positioning on shops.
        //! runtextmacro SetItemIcon("path")
                                    ^icon on shops.
        //! runtextmacro SetItemModel("path")
                                    ^model when dropped.
        //! runtextmacro SetItemCost("gold")
                                    ^Gold cost.
        //! runtextmacro SetItemDesc("text")
                                    ^Text seen on shops.
        //! runtextmacro SetItemTip("text")
                                    ^Text seen the inventory.
        //! runtextmacro SetItemName("Name")
                                    ^Name seen in-game.
    
        //! runtextmacro SetItemAbil("RawCode")
                    (Optional)
                    Raw code of the ACTIVE ability used by item.
                    Do not run this if your item does not have an ability.
    
        //! runtextmacro SetItemCat("Classification")
                    (Optional)
                    In-game item classification of the item, defaults to Permanent.
                    Permanent, Charged, Power Up, Artifact, Purchasable, Campaign or Miscellaneous.
    
        //! runtextmacro SetItemCharge("NumberofCharges","DoesExpire")
                    (Optional)
                    Setup a charged item.
                    Does expire takes 0 for false
                                      1 for true
    
        //! runtextmacro SetItemStock("Max","Replenish","Hotkey")
                    (Optional)
                    Setup the stock properties.
                    Defaults 1 max, 1 sec replenish and no Hotkey.
                    You can leave the Hotkey blank ("").

    //! runtextmacro ItemStruct()
                  This denotes the end of the object data configuration for an item,
                  and the start of the struct that will be instanciated for
                  each instance of an item.
                  You may use the optional event response methods here, which
                  are listed later.

    //! runtextmacro EndItem()
                  This denotes the end of the ItemStruct.
                  
                     _   _               _     
          /\/\   ___| |_| |__   ___   __| |___ 
         /    \ / _ \ __| '_ \ / _ \ / _` / __|
        / /\/\ \  __/ |_| | | | (_) | (_| \__ \
        \/    \/\___|\__|_| |_|\___/ \__,_|___/
        
        
    CREATE / DESTROY METHODS
    
                In Order of Execution, 
                    use this.unit to refer to the itemholder.

        method onCreate takes nothing returns nothing
                        ^Fires on struct creation.
                        
        method onAcquire takes nothing returns nothing
                        ^Fires when the item is acquired by unit.
                        
        method onDrop takes nothing returns nothing
                        ^Fires when the item is dropped/sold.
                        
        method preDestroy takes nothing returns nothing
                        ^Fires just before the ItemStruct is destroyed.
                                       
    EVENT RESPONSE METHODS
    
        method onAnySpellCast takes nothing returns nothing
                    Fires when the itemholder (this.unit) casts any ability.
                    You can check if the ability that was casted was this item's ability 
                    by using:
                                if GetSpellAbilityId() == this.itemAbil
                        
                        
        method onDamageReceived takes nothing returns nothing
                    Fires when the itemholder takes damage.
                    (Optional if you use Damage System)
                    You can use the Damage System to detect damage types.
                                
                                Damage_isPhysical()
                                Damage_isSpell() 
                                Damage_isAttack()
  
        method onDamageDealt takes nothing returns nothing
                    Fires when the itemholder deals damage.
                    (Optional if you use Damage System)
                    You can use the Damage System to detect damage types.
                                
                                Damage_isPhysical()
                                Damage_isSpell() 
                                Damage_isAttack()


Sample
JASS:
//! runtextmacro ItemType("Sword")
    //! runtextmacro SetItemClass("HAND")
    //! runtextmacro SetItemXY("1","2")
    //! runtextmacro SetItemIcon("ReplaceableTextures\\CommandButtons\\BTNSteelMelee.blp")
    //! runtextmacro SetItemModel("Objects\\InventoryItems\\TreasureChest\\treasurechest.mdl")
    //! runtextmacro SetItemCost("5")
    //! runtextmacro SetItemDesc("Buy the awesome SWORD")
    //! runtextmacro SetItemTip("You now have this cool sword.")
    //! runtextmacro SetItemName("Sword")
    //! runtextmacro SetItemAbil("ACfl")
    //! runtextmacro SetItemCat("Artifact")
    //! runtextmacro SetItemCharge("3","1")
    //! runtextmacro SetItemStock("3","1","X")

//! runtextmacro ItemStruct()
    method onAnySpellCast takes nothing returns nothing
    //casting events.. for the item or for any cast.
    //Event Responses for ability casts work here.
        if GetSpellAbilityId() == this.itemAbil then
            call BJDebugMsg("itemspell")
        else
            call BJDebugMsg("anyspell")
        endif
    endmethod
    
    method onDamageReceived takes nothing returns nothing
    //can be used for defense items.
    //Event Responses for receiving damage work here.
        if Damage_IsSpell() then
            call BJDebugMsg("magic")
        elseif Damage_IsAttack() then
            call BJDebugMsg("attack")
        endif
    endmethod
    
    method onDamageDealt takes nothing returns nothing
    //can replicate orb effects.
    //Event Responses for dealing damage work here.
        if Damage_IsSpell() then
            call BJDebugMsg("mtk")
        elseif Damage_IsAttack() then
            call BJDebugMsg("atk")
        endif
    endmethod
    
    method onAcquire takes nothing returns nothing
    //add bonuses, refer to this.unit
        call Status[this.unit].modDamageBonus(50)
    endmethod
    
    method onDrop takes nothing returns nothing
    //remove bonuses, refer to this.unit
        call Status[this.unit].modDamageBonus(-50)
    endmethod
//! runtextmacro EndItem()

Updates
-Initial Release : February 26, 2010, 03:28 PM
-1.1 : February 27, 12:19 PM
>> Used Set/GetItemUserData() instead of hashtables.
-1.2 : Feb. 27, 8:28 PM
>> Optimized Event-response system.
>> Easier Implementation, no more additional textmacros.
 

13lade619

is now a game developer :)
Reaction score
399
Header
JASS:
library ItemStruct initializer ItemStruct_Init requires AIDS, Damage, optional TimerUtils
//! externalblock extension=lua ObjectMerger $FILENAME$
    //! runtextmacro ItemStruct__StartConfig()
    
//===========================================================================
// CONFIG AREA
//
    
    //===========================================================================
    // System Object Editor IDs.
    //
    
    //! runtextmacro ItemStruct__BeginSysIds()
        // Uses:
        //  - 'Ixx&' for ITEM type.
        
        //! runtextmacro ItemStruct__AllowSysId("@a")
        //! runtextmacro ItemStruct__AllowSysId("@b")
        //! runtextmacro ItemStruct__AllowSysId("@c")
        //! runtextmacro ItemStruct__AllowSysId("@d")
        //! runtextmacro ItemStruct__AllowSysId("@e")
        //! runtextmacro ItemStruct__AllowSysId("@f")
        //! runtextmacro ItemStruct__AllowSysId("@g")
        //! runtextmacro ItemStruct__AllowSysId("@h")
        //! runtextmacro ItemStruct__AllowSysId("@i")
        //! runtextmacro ItemStruct__AllowSysId("@j")
        //! runtextmacro ItemStruct__AllowSysId("@k")
        //! runtextmacro ItemStruct__AllowSysId("@l")
        //! runtextmacro ItemStruct__AllowSysId("@m")
        //! runtextmacro ItemStruct__AllowSysId("@n")
        //! runtextmacro ItemStruct__AllowSysId("@o")
        //! runtextmacro ItemStruct__AllowSysId("@p")
        //! runtextmacro ItemStruct__AllowSysId("@q")
        //! runtextmacro ItemStruct__AllowSysId("@r")
        //! runtextmacro ItemStruct__AllowSysId("@s")
        //! runtextmacro ItemStruct__AllowSysId("@t")
        //! runtextmacro ItemStruct__AllowSysId("@u")
        //! runtextmacro ItemStruct__AllowSysId("@v")
        //! runtextmacro ItemStruct__AllowSysId("@w")
        //! runtextmacro ItemStruct__AllowSysId("@x")
        //! runtextmacro ItemStruct__AllowSysId("@y")
        //! runtextmacro ItemStruct__AllowSysId("@z")
        //! runtextmacro ItemStruct__AllowSysId("@A")
        //! runtextmacro ItemStruct__AllowSysId("@B")
        //! runtextmacro ItemStruct__AllowSysId("@C")
        //! runtextmacro ItemStruct__AllowSysId("@D")
        //! runtextmacro ItemStruct__AllowSysId("@E")
        //! runtextmacro ItemStruct__AllowSysId("@F")
        //! runtextmacro ItemStruct__AllowSysId("@G")
        //! runtextmacro ItemStruct__AllowSysId("@H")
        //! runtextmacro ItemStruct__AllowSysId("@I")
        //! runtextmacro ItemStruct__AllowSysId("@J")
        //! runtextmacro ItemStruct__AllowSysId("@K")
        //! runtextmacro ItemStruct__AllowSysId("@L")
        //! runtextmacro ItemStruct__AllowSysId("@M")
        //! runtextmacro ItemStruct__AllowSysId("@N")
        //! runtextmacro ItemStruct__AllowSysId("@O")
        //! runtextmacro ItemStruct__AllowSysId("@P")
        //! runtextmacro ItemStruct__AllowSysId("@Q")
        //! runtextmacro ItemStruct__AllowSysId("@R")
        //! runtextmacro ItemStruct__AllowSysId("@S")
        //! runtextmacro ItemStruct__AllowSysId("@T")
        //! runtextmacro ItemStruct__AllowSysId("@U")
        //! runtextmacro ItemStruct__AllowSysId("@V")
        //! runtextmacro ItemStruct__AllowSysId("@W")
        //! runtextmacro ItemStruct__AllowSysId("@X")
        //! runtextmacro ItemStruct__AllowSysId("@Y")
        //! runtextmacro ItemStruct__AllowSysId("@Z")
        
    //! runtextmacro ItemStruct__EndSysIds()
    
//===========================================================================
// END CONFIG AREA
//
    //! runtextmacro ItemStruct__EndConfig()
    
    
    //===========================================================================
    // SYSTEM AREA
    //
    
    globals
        constant integer ITEM_CLASS_ACCS=1
        constant integer ITEM_CLASS_BOOT=2
        constant integer ITEM_CLASS_HAND=3
        constant integer ITEM_CLASS_BODY=4
    endglobals
    
    private function interface Method takes integer this returns nothing
    
    //! textmacro ItemStruct__StartConfig
    //! endtextmacro
    //! textmacro ItemStruct__EndConfig
    //! endtextmacro
    
    
    //===========================================================================
    // Id Declaration
    //
    //  Exposes a module which implements the system ids, as per the system
    // configuration, automatically filling structs starting from struct ID #1.
    // 
    
    //! textmacro ItemStruct__BeginSysIds
        private keyword itemType
        private keyword idMax
        
        private module SysIds
            /*libprivate*/ integer itemType
            /*libprivate*/ static integer idMax=0
            private static method onInit takes nothing returns nothing
                //! i sysIds={}
                //! i maxSysIds=0
    //! endtextmacro
    //! textmacro ItemStruct__EndSysIds
            endmethod
        endmodule
        //! i sysIdsUsed=0
    //! endtextmacro
    
    //! textmacro ItemStruct__AllowSysId takes SYSID
        set thistype.idMax=thistype.idMax+1
        //! i maxSysIds=maxSysIds+1
        
        set thistype(thistype.idMax).itemType='I$SYSID$&'
        //! i sysIds[maxSysIds]={itemType="I$SYSID$&"}
    //! endtextmacro
    
    //===========================================================================
    // ItemType Struct
    //
    
    private struct ItemType
        implement SysIds // supplies itemType, preloaded.
    endstruct
    
    //===========================================================================
    // ItemStruct
    //

    globals
        private hashtable Store = InitHashtable()
        
    endglobals
    
    private function interface CreateMethodAloc takes unit whichUnit returns integer

    private keyword itemUnit
    private keyword next
    private keyword prev
    private keyword temp
    
    private interface DEFAULTS
        static ItemStruct temp
        
        unit itemUnit
        ItemStruct next
        ItemStruct prev
        
        // User implementable
        method onCreate takes nothing returns nothing defaults nothing
        method onAcquire takes nothing returns nothing defaults nothing
        method onDrop takes nothing returns nothing defaults nothing
        method preDestroy takes nothing returns nothing defaults nothing
        method onDamageReceived takes nothing returns nothing defaults nothing
        method onDamageDealt takes nothing returns nothing defaults nothing
        method onAnySpellCast takes nothing returns nothing defaults nothing
        
        // Module
        method setUnit takes unit whichUnit returns nothing defaults nothing
    endinterface
    
    struct ItemStruct extends DEFAULTS
        private static method timedDestroyCallback takes nothing returns nothing
            static if LIBRARY_TimerUtils then
                local timer t=GetExpiredTimer()
                call thistype(GetTimerData(t)).destroy()
                call ReleaseTimer(t)
            endif
        endmethod
        method destroyTimed takes real time returns nothing
            static if LIBRARY_TimerUtils then
                local timer t=NewTimer()
                call SetTimerData(t,this)
                call TimerStart(t,time,false,function thistype.timedDestroyCallback)
            else
                call BJDebugMsg("TimerUtils Needed.")
            endif
        endmethod
    endstruct
    
    module ItemStruct
        static integer CLASS=ITEM_CLASS_ACCS
        //! textmacro ItemStruct__AttachToWhichUnit
            set ItemStruct.temp=ItemList[whichUnit][thistype.CLASS]
            set ItemStruct.temp.prev.next=this
            set this.prev=ItemStruct.temp.prev
            set ItemStruct.temp.prev=this
            set this.next=ItemStruct.temp
        //! endtextmacro
        
        private static ItemType typeStruct=0
        
        static method isOn takes unit whichUnit returns boolean
            return GetInventoryIndexOfItemTypeBJ(whichUnit,thistype.typeStruct.itemType)!=0
        endmethod
        
        static method itemRawCode takes nothing returns integer
            return thistype.typeStruct.itemType
        endmethod
        
        method operator unit takes nothing returns unit
            return this.itemUnit
        endmethod
        
        method setUnit takes unit whichUnit returns nothing
            if this.itemUnit!=null then
                call this.onDrop()
                set this.next.prev=this.prev
                set this.prev.next=this.next
            endif
            set this.itemUnit=whichUnit
            if whichUnit!=null then
                //! runtextmacro ItemStruct__AttachToWhichUnit()
                call this.onAcquire()
            endif
        endmethod
        
        private method onDestroy takes nothing returns nothing
            if this.itemUnit!=null then
                call this.onDrop()
                call this.preDestroy()
                set this.next.prev=this.prev
                set this.prev.next=this.next
            else
                call this.preDestroy()
            endif
        endmethod
        
        static method create takes unit whichUnit returns thistype
            local thistype this=thistype.allocate()
            set this.itemUnit=whichUnit
            //! runtextmacro ItemStruct__AttachToWhichUnit()
            call this.onCreate()
            if whichUnit!=null then
                call this.onAcquire()
            endif
            return this
        endmethod
        
        private static method onInit takes nothing returns nothing
            set thistype.typeStruct=ItemType.create()
            call SaveInteger(Store, thistype.itemRawCode(), 0, thistype.create)
        endmethod
    endmodule
    
    private function ItemIsDropped takes nothing returns boolean
        if GetItemUserData(GetManipulatedItem())!=0 then
            call ItemStruct(GetItemUserData(GetManipulatedItem())).onDrop()
        endif
        return false
    endfunction
    private function ItemIsAcquired takes nothing returns boolean
        if LoadInteger(Store,GetItemTypeId(GetManipulatedItem()),0)!=0 then
            call SetItemUserData(GetManipulatedItem(),CreateMethodAloc(LoadInteger(Store,GetItemTypeId(GetManipulatedItem()),0)).evaluate(GetTriggerUnit()))
        endif
        return false
    endfunction
    
    private function ItemStruct_Init takes nothing returns nothing
        local trigger t
        set t=CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_PICKUP_ITEM)
        call TriggerAddCondition(t,Filter(function ItemIsAcquired))
        set t=CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_DROP_ITEM)
        call TriggerAddCondition(t,Filter(function ItemIsDropped))
        set t=null
    endfunction
    
    //===========================================================================
    // ObjectData Create
    //
    
    //! textmacro ItemType takes IDENTIFIER
        struct $IDENTIFIER$ extends ItemStruct
            static integer itemAbil
            implement ItemStruct
            //! i itemIdentifier="$IDENTIFIER$"
            private static method onInit takes nothing returns nothing
                //! i sysIdsUsed=sysIdsUsed+1
                // Defaults.
                //! i itemX="0"
                //! i itemY="0"
                //! i itemIcon=""
                //! i itemModel="Objects\\InventoryItems\\TreasureChest\\treasurechest.mdl"
                //! i itemCost=""
                //! i itemDesc=""
                //! i itemTip=""
                //! i itemName="$IDENTIFIER$"
                //! i itemClass="ACCS"
                //! i itemAbil=""
                //! i itemUse="0"
                //! i itemCat="Permanent"
                //! i itemCharge="0"
                //! i itemExpires="0"
                //! i itemKey=""
                //! i itemStockMax="1"
                //! i itemStockRep="1"
    //! endtextmacro
    
    //! textmacro SetItemXY takes XV, YV
        //! i itemX="$XV$"
        //! i itemY="$YV$"
    //! endtextmacro
    
    //! textmacro SetItemY takes VAL
        //! i itemY="$VAL$"
    //! endtextmacro
    
    //! textmacro SetItemIcon takes VAL
        //! i itemIcon="$VAL$"
    //! endtextmacro
    
    //! textmacro SetItemModel takes VAL
        //! i itemModel="$VAL$"
    //! endtextmacro
    
    //! textmacro SetItemCost takes VAL
        //! i itemCost="$VAL$"
    //! endtextmacro
    
    //! textmacro SetItemDesc takes VAL
        //! i itemDesc="$VAL$"
    //! endtextmacro
    
    //! textmacro SetItemTip takes VAL
        //! i itemTip="$VAL$"
    //! endtextmacro
    
    //! textmacro SetItemName takes VAL
        //! i itemName="$VAL$"
    //! endtextmacro
    
    //! textmacro SetItemClass takes VAL
        set thistype.CLASS=ITEM_CLASS_$VAL$
        //! i itemClass="$VAL$"
    //! endtextmacro
    
    //! textmacro SetItemAbil takes VAL
        set thistype.itemAbil='$VAL$'
        //! i itemUse = "1"
        //! i itemAbil = "$VAL$"
    //! endtextmacro
    
    //! textmacro SetItemCat takes VAL
        //! i itemCat = "$VAL$"
    //! endtextmacro
    
    //! textmacro SetItemCharge takes VAL, EXP
        //! i itemCharge = "$VAL$"
        //! i itemExpires = "$EXP$"
    //! endtextmacro
    
    //! textmacro SetItemStock takes MAX, REP, KEY
        //! i itemStockMax = "$MAX$"
        //! i itemStockRep = "$REP$"
        //! i itemKey= "$KEY$"
    //! endtextmacro
    
    //! textmacro ItemStruct
            endmethod
    //! endtextmacro
    //! textmacro EndItem
        endstruct
        
        // Make object data.
        // the Item
        //! i setobjecttype("items")
        //! i createobject("rde1",sysIds[sysIdsUsed].itemType)
        //! i makechange(current,"unsf","(ItemStruct)")
        //! i makechange(current,"ubpx",itemX)
        //! i makechange(current,"ubpy",itemY)
        //! i makechange(current,"iico",itemIcon)
        //! i makechange(current,"ifil",itemModel)
        //! i makechange(current,"igol",itemCost)
        //! i makechange(current,"utip",itemDesc)
        //! i makechange(current,"utub",itemTip)
        //! i makechange(current,"unam",itemName)
        //! i makechange(current,"iabi",itemAbil)
        //! i makechange(current,"icid",itemAbil)
        //! i makechange(current,"iusa",itemUse)
        //! i makechange(current,"icla",itemCat)
        //! i makechange(current,"iuse",itemCharge)
        //! i makechange(current,"iper",itemExpires)
        //! i makechange(current,"istr",itemStockRep)
        //! i makechange(current,"isto",itemStockMax)
        //! i makechange(current,"uhot",itemKey)
        
        //! i makechange(current,"ides","")
    //! endtextmacro
    
    //===========================================================================
    // On Damage
    //
    
    private module DamageEvent
        private static method onDamage takes nothing returns boolean
            // Attacked
            local thistype u=thistype[GetTriggerUnit()]
            local ItemStruct base
            local ItemStruct this
            
            //! textmacro DAMAGELOOP1 takes CLASS
            set base=u[ITEM_CLASS_$CLASS$]
            set this=base.next
            loop
                exitwhen this==base
                call this.onDamageReceived()
                set this=this.next
            endloop
            //! endtextmacro
            //! runtextmacro DAMAGELOOP1("ACCS")
            //! runtextmacro DAMAGELOOP1("BOOT")
            //! runtextmacro DAMAGELOOP1("HAND")
            //! runtextmacro DAMAGELOOP1("BODY")
            
            // Attacker
            if GetEventDamageSource()!=null then
                set u=thistype[GetEventDamageSource()]
                
                //! textmacro DAMAGELOOP2 takes CLASS
                set base=u[ITEM_CLASS_$CLASS$]
                set this=base.next
                loop
                    exitwhen this==base
                    call this.onDamageDealt()
                    set this=this.next
                endloop
                //! endtextmacro
                //! runtextmacro DAMAGELOOP2("ACCS")
                //! runtextmacro DAMAGELOOP2("BOOT")
                //! runtextmacro DAMAGELOOP2("HAND")
                //! runtextmacro DAMAGELOOP2("BODY")
            endif
            return false
        endmethod
        private static method onInit takes nothing returns nothing
            local trigger t=CreateTrigger()
            call Damage_RegisterEvent(t)
            call TriggerAddCondition(t,Filter(function thistype.onDamage))
            set t=null
        endmethod
    endmodule
    
    //===========================================================================
    // On Spell
    //
    
    private module AnySpellEvent
        private static method onAnySpell takes nothing returns boolean
            local thistype u=thistype[GetTriggerUnit()]
            local ItemStruct base
            local ItemStruct this
            
            //! textmacro SPELLLOOP takes CLASS
            set base=u[ITEM_CLASS_$CLASS$]
            set this=base.next
            loop
                exitwhen this==base
                call this.onAnySpellCast()
                set this=this.next
            endloop
            //! endtextmacro
            //! runtextmacro SPELLLOOP("ACCS")
            //! runtextmacro SPELLLOOP("BOOT")
            //! runtextmacro SPELLLOOP("HAND")
            //! runtextmacro SPELLLOOP("BODY")
            
            return false
        endmethod
        
        private static method onInit takes nothing returns nothing
            local trigger t=CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
            call TriggerAddCondition(t,Filter(function thistype.onAnySpell))
            set t=null
        endmethod
    endmodule
    
    //===========================================================================
    // Item Listing
    //
    
    private struct LinkNode extends ItemStruct
    endstruct
    
    struct ItemList extends array
        private static LinkNode array linkNode
        method operator [] takes integer class returns LinkNode
            return thistype.linkNode[this*4+class]
        endmethod
        private method operator []= takes integer class, LinkNode node returns nothing
            set thistype.linkNode[this*4+class]=node
        endmethod
        
        private method AIDS_onCreate takes nothing returns nothing
            set ItemStruct.temp=LinkNode.create()
            set ItemStruct.temp.next=ItemStruct.temp
            set ItemStruct.temp.prev=ItemStruct.temp
            set this[ITEM_CLASS_ACCS]=ItemStruct.temp
            set ItemStruct.temp=LinkNode.create()
            set ItemStruct.temp.next=ItemStruct.temp
            set ItemStruct.temp.prev=ItemStruct.temp
            set this[ITEM_CLASS_BOOT]=ItemStruct.temp
            set ItemStruct.temp=LinkNode.create()
            set ItemStruct.temp.next=ItemStruct.temp
            set ItemStruct.temp.prev=ItemStruct.temp
            set this[ITEM_CLASS_HAND]=ItemStruct.temp
            set ItemStruct.temp=LinkNode.create()
            set ItemStruct.temp.next=ItemStruct.temp
            set ItemStruct.temp.prev=ItemStruct.temp
            set this[ITEM_CLASS_BODY]=ItemStruct.temp
        endmethod
        private method AIDS_onDestroy takes nothing returns nothing
            call this[ITEM_CLASS_ACCS].destroy()
            call this[ITEM_CLASS_BOOT].destroy()
            call this[ITEM_CLASS_HAND].destroy()
            call this[ITEM_CLASS_BODY].destroy()
        endmethod
        //! runtextmacro AIDS()
        
        implement DamageEvent
        implement AnySpellEvent
        
        method forEachItem takes integer class, Method func returns nothing
            local LinkNode base=this[class]
            set this=thistype(base.next)
            loop
                exitwhen this==base
                call func.evaluate(this)
                set this=thistype(LinkNode(this).next)
            endloop
        endmethod
    endstruct
endlibrary



Footer
JASS:
//! endexternalblock


Test Map (1.2, outdated.. pls check code)
 

Attachments

  • ItemStruct1.2.w3x
    134 KB · Views: 244

Narks

Vastly intelligent whale-like being from the stars
Reaction score
90
Why do people not use comments for documentation...
 

Jesus4Lyf

Good Idea™
Reaction score
397
JASS:
    //INITIALIZE ACQUIRE FUNCTIONS HERE:
    //! runtextmacro ItemAquire("Sword")

Unnecessary, use a module initialiser. :thup:
JASS:
    //===========================================================================
    // Buff Listing
    //

Lol. XD
JASS:
        method destroyTimed takes real time returns nothing
            static if LIBRARY_TimerUtils then
                local timer t=NewTimer()
                call SetTimerData(t,this)
                call TimerStart(t,time,false,function thistype.timedDestroyCallback)
            else
                call BJDebugMsg("BuffStruct Error: Must import TimerUtils in order to use .timedDestroy method.")
            endif
        endmethod

That's starting to bother me.

You should use [LJASS]SetItemUserData[/LJASS] and [LJASS]GetItemUserData[/LJASS] instead of hashtables for attachment.

The way to do event responses in structs is extend an interface which default-implements the event response method (so users can override it) and then store that method in a hashtable inside a method operator called by the user ([LJASS]itemType=[/LJASS]). This is an alternative to GTrigger for structy stuff, then when an item is picked up, you check that [LJASS]LoadInteger(Store,GetItemTypeId(GetTriggerItem()),0)!=0[/LJASS] and call [LJASS]Method(LoadInteger(Store,GetItemTypeId(GetTriggerItem()),0)).execute(GetItemUserData(GetTriggerItem()))[/LJASS] and you have your event response subsystem with full and magical data attachment. :)

Example
You should check the example system, it's the best XStruct system so far. It even has garbage collection!
Good work taking a crack at one of these, but they're tough. :)

PS. This has little to do with the original ItemStruct, which is a complete override of the WC3 item system.
 

13lade619

is now a game developer :)
Reaction score
399
Unnecessary, use a module initialiser.
umm.. what's that and how?

That's starting to bother me.
lol. 'told ya i was just hacking BuffStruct.
half of the time i dont even understand your scripts.. hehe

You should use SetItemUserData and GetItemUserData instead of hashtables for attachment.
i didnt know items had custom values... thanks for that!

..still looking through that other thing you commented..
 

Jesus4Lyf

Good Idea™
Reaction score
397
..still looking through that other thing you commented..
Actually, you can just use MyInterface(GetItemUserData(item)).onDrop() to call the methods. You need the above said method to call the allocator, so you can do [LJASS]call SetItemUserData(someNewItem,Allocator(LoadInteger(Store,GetItemTypeId(someNewItem),ALLOCATOR)).evaluate())[/LJASS].

To do that, you'll need:
JASS:
private function interface Allocator takes nothing returns integer
globals
    private hashtable Store=InitHashtable()
    private constant key ALLOCATOR
endglobals


Edit:
Check this out. Really basic ItemStruct.
JASS:
library ItemStruct initializer OnInit
    globals
        private hashtable Store=InitHashtable()
        private constant key ALLOCATOR
    endglobals
    
    private function interface Allocator takes item whichItem returns integer
        
    interface ItemStruct
        method onCreate takes nothing returns nothing
        method onDrop takes nothing returns nothing
    endinterface
    
    module ItemStruct
        readonly item item
        static method create takes item whichItem returns thistype
            local thistype this=thistype.allocate()
            set this.item=whichItem
            call this.onCreate()
            return this
        endmethod
        static method operator itemType= takes integer whichType returns nothing
            call SaveInteger(Store,whichType,ALLOCATOR,thistype.create)
        endmethod
    endmodule
    
    //==
    private function OnDrop takes nothing returns boolean
        call ItemStruct(GetItemUserData(GetManipulatedItem())).onDrop()
        return false
    endfunction
    private function OnSell takes nothing returns boolean
        call SetItemUserData(GetSoldItem(),Allocator(LoadInteger(Store,GetItemTypeId(GetSoldItem()),ALLOCATOR)).evaluate(GetSoldItem()))
        // should have protection added for if the itemtype has no allocator.
        // ^ really important.
        return false
    endfunction
    
    //==
    private function OnInit takes nothing returns nothing
        local trigger t
        
        set t=CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SELL_ITEM)
        call TriggerAddCondition(t,Filter(function OnSell))
        
        set t=CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_DROP_ITEM)
        call TriggerAddCondition(t,Filter(function OnDrop))
        
        set t=null
    endfunction
endlibrary

Example:
JASS:
struct Boots extends ItemStruct
    implement ItemStruct
    
    private static method onInit takes nothing returns nothing
        set thistype.itemType='bspd'
    endmethod
    
    // the below attaches an incrementing value to the item, starting from 2 and doubling.
    private static integer sequence=1
    private integer someValue
    private method onCreate takes nothing returns nothing
        set thistype.sequence=thistype.sequence*2
        set this.someValue=thistype.sequence
    endmethod
    
    private method onDrop takes nothing returns nothing
        call BJDebugMsg(I2S(this.someValue))
    endmethod
endstruct

Works. :)
 

13lade619

is now a game developer :)
Reaction score
399
update:


Changes from last version (1.2.1).
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
- Added protection for items not created by the system. I found out that these would randomly fire
rogue drop events and sometimes would result in negative stats.

and i just had an idea..

like buffstruct which has a dummy ability, and a 'real' buff...

what if i make itemstruct create 2 items too?
a tome one (for all that question on buying with full inv) and a real one with effects..

sounds good, right?

expect in a few days though.. i have lotsa other stuff to do.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top