HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Script validation (or something)

06-17-2009, 05:17 PM#1
Themerion
This is a script I wrote for temporarily adding abilites to units.

I would like feedback or possible bugs pointed out. Thanks!

Collapse JASS:
library TimedAbility initializer Init needs Table,TimerUtils

globals

//===========================================
// This is a sort of Chaining Hash implementation.
//
// For each pair (abitype,unit) added to the system, a struct is created.
// The table binds the structs to the unit, and the abitype is found through
// chainsearching / listing through the structs belonging to that unit.
//===========================================

    private HandleTable tbl
endglobals

//=========================================================
// Struct Data
// Contains data, and also serves as list item.
//=========================================================
private struct Data
    unit u
    timer t
    integer abi

  // For list implementation
    Data next

    static method create takes unit u returns Data
        local Data d2
        local Data d = Data.allocate()
        set d.u=u
        set d.next=0
        
        set d2=Data(tbl[u])
        if d2!=0 then
            set d.next=d2
        endif
        
        set tbl[u]=d
        
        return d
    endmethod
    
    method onDestroy takes nothing returns nothing
        local Data d2 = Data(tbl[.u])
        
      // Is this first in the list?
        if d2==this then
        // Does the list have more Data?
            if .next!=0 then
                set tbl[.u]=.next
            else
              // This was the only data in the list
                call tbl.flush(.u)
            endif
        else
          // Not first in list
          // Find previous data.
            loop
                exitwhen d2.next == this
                set d2=d2.next
            endloop
            // link previous to next
            set d2.next=.next
        endif
        
        set .u=null
        set .t=null
    endmethod
endstruct
//=========================================================

private function End takes nothing returns nothing
    local Data d=Data(GetTimerData(GetExpiredTimer()))

  // If unit is not removed.
    if GetUnitTypeId(d.u)!=0 then
        call UnitRemoveAbility(d.u,d.abi)
    endif
    
    call d.destroy()
    call ReleaseTimer(GetExpiredTimer())
endfunction

public function Add takes unit u, integer abicode, integer level, real duration returns nothing
    local Data d
    
    if GetUnitAbilityLevel(u,abicode) > 0 then
      // Unit is already affected!
      
        set d = Data(tbl[u])
        loop
          // This is to prevent users from doing stupid things.
          // I won't even put 'debug' around it, since stupid
          // things would cause the game to crash.
            if d==0 then
              call BJDebugMsg("TimedAbility: The ability "+GetObjectName(abicode)+" was added to "+GetUnitName(u)+", but not from this system.")
              return
            endif
        
          // Find the data that points to our ability.
            exitwhen d.abi==abicode
            set d=d.next
        endloop
        
      // Reset the existing timer.
        call TimerStart(d.t,duration,false,function End)
    else
      // Unit is not previously affected.
      // Create timer.
          call UnitAddAbility(u,abicode)

        set d=Data.create(u)
        set d.t=NewTimer()
        set d.abi=abicode
        call SetTimerData(d.t,d)
        call TimerStart(d.t,duration,false,function End)
    endif
    
  // Everything went well. Set the desired level.
    call SetUnitAbilityLevel(u,abicode,level)
endfunction

//=========================================================
private function Init takes nothing returns nothing
    set tbl=HandleTable.create()
endfunction

endlibrary