HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Hook Grab

12-20-2009, 06:36 PM#1
SockSquirrelMouthwash
Based on a conglomeration of different "meathook" spells out there I put together a somewhat cleaner version from the gui versions. However, I am wondering if this will cause any problems in multiplayer. It uses the TimerUtils.

Collapse JASS:
library Hook needs TimerUtils

private struct HookData
    unit array chains[200]
    unit caster
    unit victim
    
    real angle
    real distance
    real linkdistance
    real maxdistance
    real snatchrange
    
    integer chainlink
    integer playerid
    integer hookart
endstruct

private function HookFilter takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'z000' // Hook will only "grab" this unit type
endfunction

private function HookGrab takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local HookData d = HookData(GetTimerData(t))    
    
    local real PolarX = GetUnitX(d.caster) + d.distance * Cos(d.angle)
    local real PolarY = GetUnitY(d.caster) + d.distance * Sin(d.angle)
    
    call RemoveUnit(d.chains[d.chainlink])
    set d.chains[d.chainlink] = null
    set d.chainlink = d.chainlink - 1
    
    call SetUnitPosition(d.victim, PolarX, PolarY)
    
    if d.chainlink == 0 then
        call ReleaseTimer(t)
        call SetUnitMoveSpeed(d.caster, GetUnitDefaultMoveSpeed(d.caster))
    else  
        set d.distance = d.distance - d.linkdistance
    endif
endfunction

private function HookLaunch takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local timer x
    local HookData d = HookData(GetTimerData(t))
    
    local group grabselection = CreateGroup()

    local unit cast = d.caster
    local real PolarX = GetUnitX(cast) + d.distance * Cos(d.angle)
    local real PolarY = GetUnitY(cast) + d.distance * Sin(d.angle)
    local real count

    set d.chains[d.chainlink] = CreateUnit(Player(d.playerid), d.hookart, PolarX, PolarY, d.angle)
    call GroupEnumUnitsInRange(grabselection, PolarX, PolarY, d.snatchrange, Condition(function HookFilter))

    set count = CountUnitsInGroup(grabselection)
    
    if count > 0 then
        set d.victim = GroupPickRandomUnit(grabselection)
    endif

    if count > 0 or d.distance >= d.maxdistance then
        call ReleaseTimer(t)
        set x = NewTimer()

        //call DisplayTimedTextToPlayer(Player(0), 0, 0, 5, "RETRACT!")

        call SetTimerData(x, integer(d))
        call TimerStart(x, 0.035, true, function HookGrab)
    else
        set d.distance = d.distance + d.linkdistance
        set d.chainlink = d.chainlink + 1
    endif
    
    call DestroyGroup(grabselection)
    set grabselection = null
    set cast = null    
endfunction

// call Hook_Launch(caster, targetx, targety, distance, linkdistance, art) 
public function Launch takes unit cast, real x, real y, real distance, real linkdist, integer art, real speed, real grabsize returns nothing
    local timer t = NewTimer()
    local HookData d = HookData.create()
    
    set d.hookart = art
    set d.playerid = GetPlayerId(GetOwningPlayer(cast))
    set d.caster = cast
    set d.angle = Atan2(y-GetUnitY(cast),x-GetUnitX(cast))
    set d.maxdistance = distance 
    set d.linkdistance = linkdist
    set d.distance = 0.25
    set d.chainlink = 1
    set d.snatchrange = grabsize
    
    call SetUnitFacing(cast, d.angle)
    call SetUnitMoveSpeed(d.caster, 0)
    
    call SetTimerData(t, integer(d))
    call TimerStart(t, speed, true, function HookLaunch)

    set cast = null
endfunction


endlibrary

I'm not too experienced with structs and the such, let alone playing with timers like these. Please advise.

Any help appreciated.

Thanks

EDIT: Whoa I noticed the x timer is defined twice. Gotta fix.
12-20-2009, 07:07 PM#2
Kueken
Collapse JASS:
       set x = CreateTimer()
        call SetTimerData(x, integer(d))
       ...
        local timer t = CreateTimer()

Use NewTimer, CreateTimer+SetTimerData+ReleaseTimer should make this fail, or at least not use TimerUtils Timer Stack properly.

Also, for all the people out here who not play dota, you might want to explain, what this spell should actually do.
12-20-2009, 07:21 PM#3
SockSquirrelMouthwash
Quote:
Originally Posted by Kueken
Collapse JASS:
       set x = CreateTimer()
        call SetTimerData(x, integer(d))
       ...
        local timer t = CreateTimer()

Use NewTimer, CreateTimer+SetTimerData+ReleaseTimer should make this fail, or at least not use TimerUtils Timer Stack properly.

Also, for all the people out here who not play dota, you might want to explain, what this spell should actually do.

I'm confused on what you mean, can you elaborate? I want to get this to work without problems. It does work atm but I want to make sure I eliminate anything that might cause problems behind the scenes.

As for what the spell should do, it should in effect launch what looks to be like a "chain" from the target and whatever unit the chain comes across (in this case a unittypeid 'z000', it will "grab" that unit and drag it back to point of origin.
12-20-2009, 07:25 PM#4
Kueken
TimerUtils has the functions NewTimer() and ReleaseTimer() to replace CreateTimer() and DestroyTimer(). For the system to work correctly, do not use Create or Destroy Timer but always New/Release Timer.
12-20-2009, 07:32 PM#5
SockSquirrelMouthwash
Quote:
Originally Posted by Kueken
TimerUtils has the functions NewTimer() and ReleaseTimer() to replace CreateTimer() and DestroyTimer(). For the system to work correctly, do not use Create or Destroy Timer but always New/Release Timer.

Did NOT know that, awesome! I got a lot of replacing to do then.