System ABC - Struct Attachment System

Cohadar

master of fugue
Reaction score
209
v6.1 (compatibility release for patch 1.23b and 1.24)
JASS:

//==============================================================================
//  ABC -- STRUCT ATTACHMENT SYSTEM BY COHADAR -- v6.1
//==============================================================================


//==============================================================================
//  Quick function index:
//==============================================================================
//
//    ----------------------------------------------------------------------
//      Set Functions - these functions attach struct to a handle
//    ----------------------------------------------------------------------
//    SetTimerStructA(timer, struct)
//    SetTimerStructB(timer, struct)
//    SetTimerStructC(timer, struct)
//
//    SetTriggerStructA(trigger, struct)
//    SetTriggerStructB(trigger, struct)
//    SetTriggerStructC(trigger, struct)
//
//    SetDialogStructA(dialog, struct)
//    SetDialogStructB(dialog, struct)
//    SetDialogStructC(dialog, struct)
//
//    SetRegionStructA(region, struct)
//    SetRegionStructB(region, struct)
//    SetRegionStructC(region, struct)
//
//    ----------------------------------------------------------------------
//      Get Functions - these functions retrieve attached structs
//    ----------------------------------------------------------------------
//    GetTimerStructA(timer) -> struct
//    GetTimerStructB(timer) -> struct
//    GetTimerStructC(timer) -> struct
//
//    GetTriggerStructA(trigger) -> struct
//    GetTriggerStructB(trigger) -> struct
//    GetTriggerStructC(trigger) -> struct
//
//    GetDialogStructA(dialog) -> struct
//    GetDialogStructB(dialog) -> struct
//    GetDialogStructC(dialog) -> struct
//
//    GetRegionStructA(region) -> struct
//    GetRegionStructB(region) -> struct
//    GetRegionStructC(region) -> struct
//
//    ----------------------------------------------------------------------
//      Clear Functions - these functions clear and return attached value
//    ----------------------------------------------------------------------
//    ClearTimerStructA(timer) -> struct
//    ClearTimerStructB(timer) -> struct
//    ClearTimerStructC(timer) -> struct
//
//    ClearTriggerStructA(trigger) -> struct
//    ClearTriggerStructB(trigger) -> struct
//    ClearTriggerStructC(trigger) -> struct
//
//    ClearDialogStructA(dialog) -> struct
//    ClearDialogStructB(dialog) -> struct
//    ClearDialogStructC(dialog) -> struct
//
//    ClearRegionStructA(region) -> struct
//    ClearRegionStructB(region) -> struct
//    ClearRegionStructC(region) -> struct
//
//==============================================================================


//==============================================================================
//  DOCUMENTATION:
//==============================================================================
//
//  PURPOUSE OF ABC:
//       * Type safe handle attaching.
//      
//       * Currently supported handle types are timer, trigger, dialog and region
//
//  PROS: 
//       * ABC is faster than gamecache based systems.
//
//       * You can attach up to 3 structs on the same handle
//         
//       * System reports collision, and clearing of non-existent value.
//
//       * This system will work even if your map leaks
//         and will NOT slow down because of it.
//
//  CONS:
//       * you must manually clear the stored value - REMEMBER THIS RULE!!!
//         Don't forget to use Clear functions
//
//  DETAILS:
//       * You can use Get to check if struct is attached to handle
//         It will return 0 if it is not.
//
//       * ABC will not interfere with other attachment systems
//         You can freely use any other system alongside ABC
//
//       * For unit attaching I recommend using PUI
//
//  SPECIAL THANKS TO: 
//       * NagelBagel - for finding errors in versions 4.3 and 4.4
//       * Here-b-Trollz - for testing ABC and for making cool spells with it.
//       * Toadcop - for being pain in the ass and for pushing me to improve ABC.
//       * emjlr3 - for pointing out the need for non-generic trigger attachments
//       * PandaMine - I found a bug in ABC by examining his HSAS vs ABC test
//       * All those people out there who use and support my systems
//         Thank you guys.
//
//  HOW TO IMPORT:
//       * Just create a trigger named ABC
//       * convert it to text and replace the whole trigger text with this one
//
//==============================================================================


//==============================================================================
//  Macro function cores
//==============================================================================

//------------------------------------------------------------------------------
//! textmacro ABC_Set takes X, NAME, TYPE
    local integer i = GetHandleId(key)
    set i = i - (i / HASH) * HASH

    if $NAME$Key$X$<i> == null then
        set $NAME$Key$X$<i> = key
        set $NAME$Value$X$<i> = value
    else
        debug   set $NAME$Collision$X$<i> = $NAME$Collision$X$<i> + 1
        debug   if $NAME$MaxCollision$X$ &lt; $NAME$Collision$X$<i> then
        debug       set $NAME$MaxCollision$X$ = $NAME$Collision$X$<i>
        debug       call BJDebugMsg(&quot;|cFFFF00FFWarning: Set$NAME$Struct$X$(&quot;+I2S(GetHandleId(key))+&quot;, &quot;+I2S(value)+&quot;) - index: &quot;+I2S(i)+&quot;, collision: &quot;+I2S($NAME$MaxCollision$X$))
        debug   endif
        call SaveInteger($NAME$Hash, &#039;$X$&#039;, GetHandleId(key), value)
	endif
//! endtextmacro

//------------------------------------------------------------------------------
//! textmacro ABC_Get takes X, NAME, TYPE
    local integer i = GetHandleId(key)
    set i = i - (i / HASH) * HASH
	
    if $NAME$Key$X$<i> == key then
        return $NAME$Value$X$<i>
    else
        return LoadInteger($NAME$Hash, &#039;$X$&#039;, GetHandleId(key))
	endif
//! endtextmacro    

//------------------------------------------------------------------------------
//! textmacro ABC_Clear takes X, NAME, TYPE
    local integer ret
    local integer i = GetHandleId(key)
    set i = i - (i / HASH) * HASH
	
    if $NAME$Key$X$<i> == key then
        set ret = $NAME$Value$X$<i>
        set $NAME$Key$X$<i> = null
        set $NAME$Value$X$<i> = 0
    else
        if HaveSavedInteger($NAME$Hash, &#039;$X$&#039;, GetHandleId(key)) then
            debug set $NAME$Collision$X$<i> = $NAME$Collision$X$<i> - 1
            set ret = LoadInteger($NAME$Hash, &#039;$X$&#039;, GetHandleId(key))
            call RemoveSavedInteger($NAME$Hash, &#039;$X$&#039;, GetHandleId(key))
        else
            call BJDebugMsg(&quot;|cFFFF0000ERROR: Clear$NAME$Struct$X$(&quot;+I2S(GetHandleId(key))+&quot;) - clear attempt on bad key&quot;)
            set ret = 0
        endif
    endif
    
    return ret
//! endtextmacro    


//==============================================================================
library ABC initializer Init

globals
    private constant integer HASH = 8191

    private timer   array TimerKeyA
    private timer   array TimerKeyB
    private timer   array TimerKeyC
    private trigger array TriggerKeyA
    private trigger array TriggerKeyB
    private trigger array TriggerKeyC
    private dialog  array DialogKeyA
    private dialog  array DialogKeyB
    private dialog  array DialogKeyC
    private region  array RegionKeyA
    private region  array RegionKeyB
    private region  array RegionKeyC
    
    private integer array TimerValueA
    private integer array TimerValueB
    private integer array TimerValueC
    private integer array TriggerValueA
    private integer array TriggerValueB
    private integer array TriggerValueC
    private integer array DialogValueA
    private integer array DialogValueB
    private integer array DialogValueC
    private integer array RegionValueA
    private integer array RegionValueB
    private integer array RegionValueC

    private integer array TimerCollisionA
    private integer array TimerCollisionB
    private integer array TimerCollisionC
    private integer array TriggerCollisionA
    private integer array TriggerCollisionB
    private integer array TriggerCollisionC
    private integer array DialogCollisionA
    private integer array DialogCollisionB
    private integer array DialogCollisionC
    private integer array RegionCollisionA
    private integer array RegionCollisionB
    private integer array RegionCollisionC    
    
    private integer TimerMaxCollisionA   = 0
    private integer TimerMaxCollisionB   = 0
    private integer TimerMaxCollisionC   = 0
    private integer TriggerMaxCollisionA = 0
    private integer TriggerMaxCollisionB = 0
    private integer TriggerMaxCollisionC = 0
    private integer DialogMaxCollisionA  = 0
    private integer DialogMaxCollisionB  = 0
    private integer DialogMaxCollisionC  = 0
    private integer RegionMaxCollisionA  = 0
    private integer RegionMaxCollisionB  = 0
    private integer RegionMaxCollisionC  = 0 
    
    private hashtable TimerHash
    private hashtable TriggerHash
    private hashtable DialogHash
    private hashtable RegionHash
endglobals

//==============================================================================
//  Collision check functions
//==============================================================================

//------------------------------------------------------------------------------
function GetTimerCollisionA takes nothing returns integer
    return TimerMaxCollisionA
endfunction

//------------------------------------------------------------------------------
function GetTimerCollisionB takes nothing returns integer
    return TimerMaxCollisionB
endfunction

//------------------------------------------------------------------------------
function GetTimerCollisionC takes nothing returns integer
    return TimerMaxCollisionC
endfunction

//------------------------------------------------------------------------------
function GetTriggerCollisionA takes nothing returns integer
    return TriggerMaxCollisionA
endfunction

//------------------------------------------------------------------------------
function GetTriggerCollisionB takes nothing returns integer
    return TriggerMaxCollisionB
endfunction

//------------------------------------------------------------------------------
function GetTriggerCollisionC takes nothing returns integer
    return TriggerMaxCollisionC
endfunction

//------------------------------------------------------------------------------
function GetDialogCollisionA takes nothing returns integer
    return DialogMaxCollisionA
endfunction

//------------------------------------------------------------------------------
function GetDialogCollisionB takes nothing returns integer
    return DialogMaxCollisionB
endfunction

//------------------------------------------------------------------------------
function GetDialogCollisionC takes nothing returns integer
    return DialogMaxCollisionC
endfunction

//------------------------------------------------------------------------------
function GetRegionCollisionA takes nothing returns integer
    return RegionMaxCollisionA
endfunction

//------------------------------------------------------------------------------
function GetRegionCollisionB takes nothing returns integer
    return RegionMaxCollisionB
endfunction

//------------------------------------------------------------------------------
function GetRegionCollisionC takes nothing returns integer
    return RegionMaxCollisionC
endfunction


//==============================================================================
//  Set functions
//==============================================================================

//------------------------------------------------------------------------------
function SetTimerStructA takes timer key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;A&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function SetTimerStructB takes timer key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;B&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function SetTimerStructC takes timer key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;C&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function SetTriggerStructA takes trigger key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;A&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function SetTriggerStructB takes trigger key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;B&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function SetTriggerStructC takes trigger key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;C&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function SetDialogStructA takes dialog key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;A&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function SetDialogStructB takes dialog key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;B&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function SetDialogStructC takes dialog key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;C&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function SetRegionStructA takes region key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;A&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction

//------------------------------------------------------------------------------
function SetRegionStructB takes region key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;B&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction

//------------------------------------------------------------------------------
function SetRegionStructC takes region key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;C&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction


//==============================================================================
//  Get functions
//==============================================================================

//------------------------------------------------------------------------------
function GetTimerStructA takes timer key returns integer
//! runtextmacro ABC_Get(&quot;A&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function GetTimerStructB takes timer key returns integer
//! runtextmacro ABC_Get(&quot;B&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function GetTimerStructC takes timer key returns integer
//! runtextmacro ABC_Get(&quot;C&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function GetTriggerStructA takes trigger key returns integer
//! runtextmacro ABC_Get(&quot;A&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function GetTriggerStructB takes trigger key returns integer
//! runtextmacro ABC_Get(&quot;B&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function GetTriggerStructC takes trigger key returns integer
//! runtextmacro ABC_Get(&quot;C&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function GetDialogStructA takes dialog key returns integer
//! runtextmacro ABC_Get(&quot;A&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function GetDialogStructB takes dialog key returns integer
//! runtextmacro ABC_Get(&quot;B&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function GetDialogStructC takes dialog key returns integer
//! runtextmacro ABC_Get(&quot;C&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function GetRegionStructA takes region key returns integer
//! runtextmacro ABC_Get(&quot;A&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction

//------------------------------------------------------------------------------
function GetRegionStructB takes region key returns integer
//! runtextmacro ABC_Get(&quot;B&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction

//------------------------------------------------------------------------------
function GetRegionStructC takes region key returns integer
//! runtextmacro ABC_Get(&quot;C&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction


//==============================================================================
//  Clear functions
//==============================================================================

//------------------------------------------------------------------------------
function ClearTimerStructA takes timer key returns integer
//! runtextmacro ABC_Clear(&quot;A&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearTimerStructB takes timer key returns integer
//! runtextmacro ABC_Clear(&quot;B&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearTimerStructC takes timer key returns integer
//! runtextmacro ABC_Clear(&quot;C&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearTriggerStructA takes trigger key returns integer
//! runtextmacro ABC_Clear(&quot;A&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearTriggerStructB takes trigger key returns integer
//! runtextmacro ABC_Clear(&quot;B&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearTriggerStructC takes trigger key returns integer
//! runtextmacro ABC_Clear(&quot;C&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearDialogStructA takes dialog key returns integer
//! runtextmacro ABC_Clear(&quot;A&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearDialogStructB takes dialog key returns integer
//! runtextmacro ABC_Clear(&quot;B&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearDialogStructC takes dialog key returns integer
//! runtextmacro ABC_Clear(&quot;C&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearRegionStructA takes region key returns integer
//! runtextmacro ABC_Clear(&quot;A&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearRegionStructB takes region key returns integer
//! runtextmacro ABC_Clear(&quot;B&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearRegionStructC takes region key returns integer
//! runtextmacro ABC_Clear(&quot;C&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction


//==============================================================================
//  Initialization
//==============================================================================
private function Init takes nothing returns nothing
    set TimerKeyA[HASH-1] = null
    set TimerKeyB[HASH-1] = null
    set TimerKeyC[HASH-1] = null
    set TriggerKeyA[HASH-1] = null
    set TriggerKeyB[HASH-1] = null
    set TriggerKeyC[HASH-1] = null
    set DialogKeyA[HASH-1] = null
    set DialogKeyB[HASH-1] = null
    set DialogKeyC[HASH-1] = null
    set RegionKeyA[HASH-1] = null
    set RegionKeyB[HASH-1] = null
    set RegionKeyC[HASH-1] = null
    
    set TimerValueA[HASH-1] = 0
    set TimerValueB[HASH-1] = 0
    set TimerValueC[HASH-1] = 0
    set TriggerValueA[HASH-1] = 0
    set TriggerValueB[HASH-1] = 0
    set TriggerValueC[HASH-1] = 0
    set DialogValueA[HASH-1] = 0
    set DialogValueB[HASH-1] = 0
    set DialogValueC[HASH-1] = 0
    set RegionValueA[HASH-1] = 0
    set RegionValueB[HASH-1] = 0
    set RegionValueC[HASH-1] = 0    
    
    set TimerCollisionA[HASH-1] = 0
    set TimerCollisionB[HASH-1] = 0
    set TimerCollisionC[HASH-1] = 0
    set TriggerCollisionA[HASH-1] = 0
    set TriggerCollisionB[HASH-1] = 0
    set TriggerCollisionC[HASH-1] = 0
    set DialogCollisionA[HASH-1] = 0
    set DialogCollisionB[HASH-1] = 0
    set DialogCollisionC[HASH-1] = 0
    set RegionCollisionA[HASH-1] = 0
    set RegionCollisionB[HASH-1] = 0
    set RegionCollisionC[HASH-1] = 0    
    
    set TimerHash   = InitHashtable()
    set TriggerHash = InitHashtable()
    set DialogHash  = InitHashtable()
    set RegionHash  = InitHashtable()
endfunction

endlibrary
//==============================================================================
//  END OF ABC STRUCT ATTACHMENT SYSTEM
//==============================================================================
</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>




v6.0
JASS:

//==============================================================================
//  ABC -- STRUCT ATTACHMENT SYSTEM BY COHADAR -- v6.0
//==============================================================================


//==============================================================================
//  Quick function index:
//==============================================================================
//
//    ----------------------------------------------------------------------
//      Set Functions - these functions attach struct to a handle
//    ----------------------------------------------------------------------
//    SetTimerStructA(timer, struct)
//    SetTimerStructB(timer, struct)
//    SetTimerStructC(timer, struct)
//
//    SetTriggerStructA(trigger, struct)
//    SetTriggerStructB(trigger, struct)
//    SetTriggerStructC(trigger, struct)
//
//    SetDialogStructA(dialog, struct)
//    SetDialogStructB(dialog, struct)
//    SetDialogStructC(dialog, struct)
//
//    SetRegionStructA(region, struct)
//    SetRegionStructB(region, struct)
//    SetRegionStructC(region, struct)
//
//    ----------------------------------------------------------------------
//      Get Functions - these functions retrieve attached structs
//    ----------------------------------------------------------------------
//    GetTimerStructA(timer) -&gt; struct
//    GetTimerStructB(timer) -&gt; struct
//    GetTimerStructC(timer) -&gt; struct
//
//    GetTriggerStructA(trigger) -&gt; struct
//    GetTriggerStructB(trigger) -&gt; struct
//    GetTriggerStructC(trigger) -&gt; struct
//
//    GetDialogStructA(dialog) -&gt; struct
//    GetDialogStructB(dialog) -&gt; struct
//    GetDialogStructC(dialog) -&gt; struct
//
//    GetRegionStructA(region) -&gt; struct
//    GetRegionStructB(region) -&gt; struct
//    GetRegionStructC(region) -&gt; struct
//
//    ----------------------------------------------------------------------
//      Clear Functions - these functions clear and return attached value
//    ----------------------------------------------------------------------
//    ClearTimerStructA(timer) -&gt; struct
//    ClearTimerStructB(timer) -&gt; struct
//    ClearTimerStructC(timer) -&gt; struct
//
//    ClearTriggerStructA(trigger) -&gt; struct
//    ClearTriggerStructB(trigger) -&gt; struct
//    ClearTriggerStructC(trigger) -&gt; struct
//
//    ClearDialogStructA(dialog) -&gt; struct
//    ClearDialogStructB(dialog) -&gt; struct
//    ClearDialogStructC(dialog) -&gt; struct
//
//    ClearRegionStructA(region) -&gt; struct
//    ClearRegionStructB(region) -&gt; struct
//    ClearRegionStructC(region) -&gt; struct
//
//==============================================================================


//==============================================================================
//  DOCUMENTATION:
//==============================================================================
//
//  PURPOUSE OF ABC:
//       * Type safe handle attaching.
//      
//       * Currently supported handle types are timer, trigger, dialog and region
//
//  PROS: 
//       * ABC is faster than gamecache based systems.
//
//       * You can attach up to 3 structs on the same handle
//         
//       * System reports collision, and clearing of non-existent value.
//
//       * This system will work even if your map leaks
//         and will NOT slow down because of it.
//
//  CONS:
//       * you must manually clear the stored value - REMEMBER THIS RULE!!!
//         Don&#039;t forget to use Clear functions
//
//  DETAILS:
//       * You can use Get to check if struct is attached to handle
//         It will return 0 if it is not.
//
//       * ABC will not interfere with other attachment systems
//         You can freely use any other system alongside ABC
//
//       * For unit attaching I recommend using PUI
//
//  SPECIAL THANKS TO: 
//       * NagelBagel - for finding errors in versions 4.3 and 4.4
//       * Here-b-Trollz - for testing ABC and for making cool spells with it.
//       * Toadcop - for being pain in the ass and for pushing me to improve ABC.
//       * emjlr3 - for pointing out the need for non-generic trigger attachments
//       * PandaMine - I found a bug in ABC by examining his HSAS vs ABC test
//       * All those people out there who use and support my systems
//         Thank you guys.
//
//  HOW TO IMPORT:
//       * Just create a trigger named ABC
//       * convert it to text and replace the whole trigger text with this one
//
//==============================================================================


//==============================================================================
//  Macro function cores
//==============================================================================

//------------------------------------------------------------------------------
//! textmacro ABC_Set takes X, NAME, TYPE
    local integer i = H2I(key)
    set i = i - (i / HASH) * HASH

    if $NAME$Key$X$<i> == null then
        set $NAME$Key$X$<i> = key
        set $NAME$Value$X$<i> = value
    else
        debug   set $NAME$Collision$X$<i> = $NAME$Collision$X$<i> + 1
        debug   if $NAME$MaxCollision$X$ &lt; $NAME$Collision$X$<i> then
        debug       set $NAME$MaxCollision$X$ = $NAME$Collision$X$<i>
        debug       call BJDebugMsg(&quot;|cFFFF00FFWarning: Set$NAME$Struct$X$(&quot;+I2S(H2I(key))+&quot;, &quot;+I2S(value)+&quot;) - index: &quot;+I2S(i)+&quot;, collision: &quot;+I2S($NAME$MaxCollision$X$))
        debug   endif
        call StoreInteger($NAME$Cache, &quot;$X$&quot;, I2S(H2I(key)), value)
	endif
//! endtextmacro

//------------------------------------------------------------------------------
//! textmacro ABC_Get takes X, NAME, TYPE
    local integer i = H2I(key)
    set i = i - (i / HASH) * HASH
	
    if $NAME$Key$X$<i> == key then
        return $NAME$Value$X$<i>
    else
        return GetStoredInteger($NAME$Cache, &quot;$X$&quot;, I2S(H2I(key)))
	endif
//! endtextmacro    

//------------------------------------------------------------------------------
//! textmacro ABC_Clear takes X, NAME, TYPE
    local integer ret
    local integer i = H2I(key)
    set i = i - (i / HASH) * HASH
	
    if $NAME$Key$X$<i> == key then
        set ret = $NAME$Value$X$<i>
        set $NAME$Key$X$<i> = null
        set $NAME$Value$X$<i> = 0
    else
        if HaveStoredInteger($NAME$Cache, &quot;$X$&quot;, I2S(H2I(key))) then
            debug set $NAME$Collision$X$<i> = $NAME$Collision$X$<i> - 1
            set ret = GetStoredInteger($NAME$Cache, &quot;$X$&quot;, I2S(H2I(key)))
            call FlushStoredInteger($NAME$Cache, &quot;$X$&quot;, I2S(H2I(key)))
        else
            call BJDebugMsg(&quot;|cFFFF0000ERROR: Clear$NAME$Struct$X$(&quot;+I2S(H2I(key))+&quot;) - clear attempt on bad key&quot;)
            set ret = 0
        endif
    endif
    
    return ret
//! endtextmacro    


//==============================================================================
library ABC initializer Init

globals
    private constant integer HASH = 8191

    private timer   array TimerKeyA
    private timer   array TimerKeyB
    private timer   array TimerKeyC
    private trigger array TriggerKeyA
    private trigger array TriggerKeyB
    private trigger array TriggerKeyC
    private dialog  array DialogKeyA
    private dialog  array DialogKeyB
    private dialog  array DialogKeyC
    private region  array RegionKeyA
    private region  array RegionKeyB
    private region  array RegionKeyC
    
    private integer array TimerValueA
    private integer array TimerValueB
    private integer array TimerValueC
    private integer array TriggerValueA
    private integer array TriggerValueB
    private integer array TriggerValueC
    private integer array DialogValueA
    private integer array DialogValueB
    private integer array DialogValueC
    private integer array RegionValueA
    private integer array RegionValueB
    private integer array RegionValueC

    private integer array TimerCollisionA
    private integer array TimerCollisionB
    private integer array TimerCollisionC
    private integer array TriggerCollisionA
    private integer array TriggerCollisionB
    private integer array TriggerCollisionC
    private integer array DialogCollisionA
    private integer array DialogCollisionB
    private integer array DialogCollisionC
    private integer array RegionCollisionA
    private integer array RegionCollisionB
    private integer array RegionCollisionC    
    
    private integer TimerMaxCollisionA   = 0
    private integer TimerMaxCollisionB   = 0
    private integer TimerMaxCollisionC   = 0
    private integer TriggerMaxCollisionA = 0
    private integer TriggerMaxCollisionB = 0
    private integer TriggerMaxCollisionC = 0
    private integer DialogMaxCollisionA  = 0
    private integer DialogMaxCollisionB  = 0
    private integer DialogMaxCollisionC  = 0
    private integer RegionMaxCollisionA  = 0
    private integer RegionMaxCollisionB  = 0
    private integer RegionMaxCollisionC  = 0 
    
    private gamecache TimerCache
    private gamecache TriggerCache
    private gamecache DialogCache
    private gamecache RegionCache
endglobals

//------------------------------------------------------------------------------
public function H2I takes handle h returns integer
    return h
    return 0
endfunction


//==============================================================================
//  Collision check functions
//==============================================================================

//------------------------------------------------------------------------------
function GetTimerCollisionA takes nothing returns integer
    return TimerMaxCollisionA
endfunction

//------------------------------------------------------------------------------
function GetTimerCollisionB takes nothing returns integer
    return TimerMaxCollisionB
endfunction

//------------------------------------------------------------------------------
function GetTimerCollisionC takes nothing returns integer
    return TimerMaxCollisionC
endfunction

//------------------------------------------------------------------------------
function GetTriggerCollisionA takes nothing returns integer
    return TriggerMaxCollisionA
endfunction

//------------------------------------------------------------------------------
function GetTriggerCollisionB takes nothing returns integer
    return TriggerMaxCollisionB
endfunction

//------------------------------------------------------------------------------
function GetTriggerCollisionC takes nothing returns integer
    return TriggerMaxCollisionC
endfunction

//------------------------------------------------------------------------------
function GetDialogCollisionA takes nothing returns integer
    return DialogMaxCollisionA
endfunction

//------------------------------------------------------------------------------
function GetDialogCollisionB takes nothing returns integer
    return DialogMaxCollisionB
endfunction

//------------------------------------------------------------------------------
function GetDialogCollisionC takes nothing returns integer
    return DialogMaxCollisionC
endfunction

//------------------------------------------------------------------------------
function GetRegionCollisionA takes nothing returns integer
    return RegionMaxCollisionA
endfunction

//------------------------------------------------------------------------------
function GetRegionCollisionB takes nothing returns integer
    return RegionMaxCollisionB
endfunction

//------------------------------------------------------------------------------
function GetRegionCollisionC takes nothing returns integer
    return RegionMaxCollisionC
endfunction


//==============================================================================
//  Set functions
//==============================================================================

//------------------------------------------------------------------------------
function SetTimerStructA takes timer key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;A&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function SetTimerStructB takes timer key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;B&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function SetTimerStructC takes timer key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;C&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function SetTriggerStructA takes trigger key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;A&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function SetTriggerStructB takes trigger key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;B&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function SetTriggerStructC takes trigger key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;C&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function SetDialogStructA takes dialog key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;A&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function SetDialogStructB takes dialog key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;B&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function SetDialogStructC takes dialog key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;C&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function SetRegionStructA takes region key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;A&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction

//------------------------------------------------------------------------------
function SetRegionStructB takes region key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;B&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction

//------------------------------------------------------------------------------
function SetRegionStructC takes region key, integer value returns nothing
//! runtextmacro ABC_Set(&quot;C&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction


//==============================================================================
//  Get functions
//==============================================================================

//------------------------------------------------------------------------------
function GetTimerStructA takes timer key returns integer
//! runtextmacro ABC_Get(&quot;A&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function GetTimerStructB takes timer key returns integer
//! runtextmacro ABC_Get(&quot;B&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function GetTimerStructC takes timer key returns integer
//! runtextmacro ABC_Get(&quot;C&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function GetTriggerStructA takes trigger key returns integer
//! runtextmacro ABC_Get(&quot;A&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function GetTriggerStructB takes trigger key returns integer
//! runtextmacro ABC_Get(&quot;B&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function GetTriggerStructC takes trigger key returns integer
//! runtextmacro ABC_Get(&quot;C&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function GetDialogStructA takes dialog key returns integer
//! runtextmacro ABC_Get(&quot;A&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function GetDialogStructB takes dialog key returns integer
//! runtextmacro ABC_Get(&quot;B&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function GetDialogStructC takes dialog key returns integer
//! runtextmacro ABC_Get(&quot;C&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function GetRegionStructA takes region key returns integer
//! runtextmacro ABC_Get(&quot;A&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction

//------------------------------------------------------------------------------
function GetRegionStructB takes region key returns integer
//! runtextmacro ABC_Get(&quot;B&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction

//------------------------------------------------------------------------------
function GetRegionStructC takes region key returns integer
//! runtextmacro ABC_Get(&quot;C&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction


//==============================================================================
//  Clear functions
//==============================================================================

//------------------------------------------------------------------------------
function ClearTimerStructA takes timer key returns integer
//! runtextmacro ABC_Clear(&quot;A&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearTimerStructB takes timer key returns integer
//! runtextmacro ABC_Clear(&quot;B&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearTimerStructC takes timer key returns integer
//! runtextmacro ABC_Clear(&quot;C&quot;, &quot;Timer&quot;, &quot;timer&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearTriggerStructA takes trigger key returns integer
//! runtextmacro ABC_Clear(&quot;A&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearTriggerStructB takes trigger key returns integer
//! runtextmacro ABC_Clear(&quot;B&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearTriggerStructC takes trigger key returns integer
//! runtextmacro ABC_Clear(&quot;C&quot;, &quot;Trigger&quot;, &quot;trigger&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearDialogStructA takes dialog key returns integer
//! runtextmacro ABC_Clear(&quot;A&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearDialogStructB takes dialog key returns integer
//! runtextmacro ABC_Clear(&quot;B&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearDialogStructC takes dialog key returns integer
//! runtextmacro ABC_Clear(&quot;C&quot;, &quot;Dialog&quot;, &quot;dialog&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearRegionStructA takes region key returns integer
//! runtextmacro ABC_Clear(&quot;A&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearRegionStructB takes region key returns integer
//! runtextmacro ABC_Clear(&quot;B&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction

//------------------------------------------------------------------------------
function ClearRegionStructC takes region key returns integer
//! runtextmacro ABC_Clear(&quot;C&quot;, &quot;Region&quot;, &quot;region&quot;)
endfunction


//==============================================================================
//  Initialization
//==============================================================================
private function Init takes nothing returns nothing
    set TimerKeyA[HASH-1] = null
    set TimerKeyB[HASH-1] = null
    set TimerKeyC[HASH-1] = null
    set TriggerKeyA[HASH-1] = null
    set TriggerKeyB[HASH-1] = null
    set TriggerKeyC[HASH-1] = null
    set DialogKeyA[HASH-1] = null
    set DialogKeyB[HASH-1] = null
    set DialogKeyC[HASH-1] = null
    set RegionKeyA[HASH-1] = null
    set RegionKeyB[HASH-1] = null
    set RegionKeyC[HASH-1] = null
    
    set TimerValueA[HASH-1] = 0
    set TimerValueB[HASH-1] = 0
    set TimerValueC[HASH-1] = 0
    set TriggerValueA[HASH-1] = 0
    set TriggerValueB[HASH-1] = 0
    set TriggerValueC[HASH-1] = 0
    set DialogValueA[HASH-1] = 0
    set DialogValueB[HASH-1] = 0
    set DialogValueC[HASH-1] = 0
    set RegionValueA[HASH-1] = 0
    set RegionValueB[HASH-1] = 0
    set RegionValueC[HASH-1] = 0    
    
    set TimerCollisionA[HASH-1] = 0
    set TimerCollisionB[HASH-1] = 0
    set TimerCollisionC[HASH-1] = 0
    set TriggerCollisionA[HASH-1] = 0
    set TriggerCollisionB[HASH-1] = 0
    set TriggerCollisionC[HASH-1] = 0
    set DialogCollisionA[HASH-1] = 0
    set DialogCollisionB[HASH-1] = 0
    set DialogCollisionC[HASH-1] = 0
    set RegionCollisionA[HASH-1] = 0
    set RegionCollisionB[HASH-1] = 0
    set RegionCollisionC[HASH-1] = 0    
    
    call FlushGameCache(InitGameCache(&quot;Timer.gc&quot;))
    call FlushGameCache(InitGameCache(&quot;Trigger.gc&quot;))
    call FlushGameCache(InitGameCache(&quot;Dialog.gc&quot;))
    call FlushGameCache(InitGameCache(&quot;Region.gc&quot;))
    
    set TimerCache   = InitGameCache(&quot;Timer.gc&quot;)
    set TriggerCache = InitGameCache(&quot;Trigger.gc&quot;)
    set DialogCache  = InitGameCache(&quot;Dialog.gc&quot;)
    set RegionCache  = InitGameCache(&quot;Region.gc&quot;)
endfunction

endlibrary
//==============================================================================
//  END OF ABC STRUCT ATTACHMENT SYSTEM
//==============================================================================
</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>



v4.6 compatibility
Code:
library ABCC uses ABC
//==============================================================================
//   Compatibility with ABC v4.6
//
//       old                  new
//     ----------------------------------
//     SetStructA     ==  SetTimerStructA
//     GetStructA     ==  GetTimerStructA
//     ClearStructA   ==  ClearTimerStructA
//
//   This library should be used only as temporary compatibility solution.
//
//   I recommend you to turn off this trigger
//   and then replace all old function calls with new ones.
//==============================================================================


//==============================================================================
function SetStructA takes timer t, integer s returns nothing
    call SetTimerStructA(t,s)
endfunction

function GetStructA takes timer t returns integer
    return GetTimerStructA(t)
endfunction

function ClearStructA takes timer t returns integer
    return ClearTimerStructA(t)
endfunction

//==============================================================================
function SetStructB takes timer t, integer s returns nothing
    call SetTimerStructB(t,s)
endfunction

function GetStructB takes timer t returns integer
    return GetTimerStructB(t)
endfunction

function ClearStructB takes timer t returns integer
    return ClearTimerStructB(t)
endfunction

//==============================================================================
function SetStructC takes timer t, integer s returns nothing
    call SetTimerStructC(t,s)
endfunction

function GetStructC takes timer t returns integer
    return GetTimerStructC(t)
endfunction

function ClearStructC takes timer t returns integer
    return ClearTimerStructC(t)
endfunction


endlibrary
 

Attachments

  • ABC_v6.1.w3x
    57.6 KB · Views: 432

emjlr3

Change can be a good thing
Reaction score
395
well then

will check this out in game when I get a few moments....don't hold your breath
 

Andrewgosu

The Silent Pandaren Helper
Reaction score
715
You can get rid of the "InitTrig_ABC" function - the system is inside a library, so it's moved to the map header (I think you know that already).

Also, you could make the globals and functions private. Then you wouldn't have to use the "ABC_" prefixes.

Although that's just my taste, but I would use lower caps. (Don't worry, I'm just picky:eek: )

E.g

//! runtextmacro abc("a","unit","unit"), not

//! runtextmacro ABC("A","Unit","unit")


And, what's up with these:

"//------------------------------------------------------------------------------"

or

"//=============================================================================="

or

"//------------------------------------------------------------------------------"
"// B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B
"//------------------------------------------------------------------------------"

Makes things so messy.


Lastly, I think the systems name - ABC- is kind of vague. You should use a more informatory name. The previous name was good, but it was too long.



Anyway, the code itself looks look and I just nagged about the little things.

Great work!
 

Doomhammer

Bob Kotick - Gamers' corporate spoilsport No. 1
Reaction score
67
ABC is a highly useful and very fast and efficient struct attachment system.

This should not be graveyarded!
 

SFilip

Gone but not forgotten
Reaction score
633
Well for starters it's not updated...
 

Doomhammer

Bob Kotick - Gamers' corporate spoilsport No. 1
Reaction score
67
Well for starters it's not updated...

that's about it then. I suggest to reconsider this for submission after updating to the current version. This form of struct attachment is too good to be trashed.
 

emjlr3

Change can be a good thing
Reaction score
395
if he cares to update it here perhaps we shall reconsider
 

emjlr3

Change can be a good thing
Reaction score
395
attaching to a dialog? does not make a whole lot of sense, since dialogs are at best player specific....

in anycase, a good system, with the added bonuses of compat with older outdated vresions, if people do not want to update :)

gj
 

Doomhammer

Bob Kotick - Gamers' corporate spoilsport No. 1
Reaction score
67
Well done. From now on, no more struct attachment using handlevars... :D
 

Cohadar

master of fugue
Reaction score
209
ABC v5.1 -- important bugfix

There was an error in ABC v5.0 (a very rare error that actually never happened to anyone)

I found it by doing some serious tests.
What tipped me off there is an error was looking at PandaMine's HSAS, ABC, Gamecache speed comparison test v4.30 . (not jet published)
Tnx man.
 

Cohadar

master of fugue
Reaction score
209
thanks emljr3,
I am actually mad at myself here, letting that error slip away was a noob mistake.

I have 3 test triggers now just to make sure this never happens again.

ABC come a long way from it's first version,
when I compare early algorithms with a current one I can only laugh to myself. :eek:
It was working fine and all even when it was v1.3 but the difference in speed and stability is really significant. Type-safety also did not exist before.

I had at least 7 basically different algorithmic implementations in the course of
development, even thou interface stayed the same.
Current algorithm is fast, reliable, tested and absolutely non-intuitive
It has simply mutated in it's current form. :)

Besides there is an increasing number of people using ABC,
it has become a responsibility as well.
 
S

sinners_la_b

Guest
Hey I am confused do i need the ABCC or just the ABC. Thanks

Sinners
 

Magentix

if (OP.statement == false) postCount++;
Reaction score
107
If you already implemented and used v4.6 or older in a map and can't be arsed changing the ABC_ calls you used there, import both (whilst overwriting the present v4.6 or older with v5.1).

If you haven't used it yet, just import v5.1
 

Technomancer

New Member
Reaction score
14
Cohadar, I'm working on developing a timer system to add units that need to do something in a timely manner to a single timer, because for the most part detecting events has got to be the slowest part of WC3 that can't be messed with and for maps that rely on smooth motion going with a global timer or 3 is the way to go, however I'd like to make it very modular and be able to attach functions to units that are attached to the timer, and at the end of the day, my question is how exactly does this shit work lol

Mostly I'm interested in passing a function parameter to another function, and a dynamic type struct to any function. Can I just use the "code" handle to pass a function_name arguement, and once I'm in the appropriate function which I have passed the function I want to pass to, how would I call it?

With the structs, I assume I have to use H2I(struct) to pass, but how do I return the struct to it's regular form? Or do I have to make a textmacro for every type of struct I want to pass if I want to be able to effectively access it's member functions?

My system will be using ABC because CSCache gives me a headache.


A few more questions: For leak removal, do structs attached to units through their custom value get auto removed when the unit is removed? I assume so because the custom value is just an integer value on the unit.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top