• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Is Walking v0.01

This thing is a system which tells you if a unit walks or not. But it has some other usefull abilitys. For example you can add Events or get the walked distance since the last stop.

I created it for a spell after that I looked around here and I haven't found such a system. So I upload it here.

For more infos look into the head of the system code.

JASS:
library_once IsWalking initializer init

//=====================================================================================================//
//                                           Is Walking v0.01                                          //
//                                                   by                                                //
//                                                  cedi                                               //
//=====================================================================================================//
//This system tells you when an unit walks, but for that you need to add the unit to the walkers. For
//that you have the Add function:
//call IsWalking_Add( unit walker )
//When you want to remove the unit from the group use:
//call IsWalking_Remove( unit walker )
//
//Now can you use these functions:
//
//call IsWalking_Moving( unit walker ) returns boolean. ( true the unit walks false it stays around )
//call IsWalking_Distance( unit walker ) returns real. ( returns the distance since the unit walked 
//since last stop )
//call IsWalking_LastDistance( unit walker ) returns real. ( returns the distance walked at the last interval )
//call IsWalking_Duration( unit walker ) returns real. ( returns the time the unit walks )
//
//WARNING: when a walker dies the system removes the unit from the system. But when you don't want this
//( for heros for example ) use:
//call IsWalking_Protect( unit walker )
//when you want to unprotect use this:
//call IsWalking_UnProtect( unit walker )
//
//There is the possibility to add events to the system. Use these functions:
//Event e is a function interface which takes Walking w and returns nothing
//
//call IsWalking_EventOnStart( Event e, unit walker ) Triggers when the walker starts to walk.
//call IsWalking_EventOnStop( Event e, unit walker ) Triggers when the walker stops to walk.
//call IsWalking_EventOnWalk( Event e, unit walker ) Triggers when the walker walks ( each TIMER_INTERVAL ).
//
//Use the functions with Event e == 0 to remove the events.
//
//Below are some values:


globals
    private constant real TIMER_INTERVAL    = 0.035 
    //Interval of the check timer
    private constant real MIN_WALK_TIME     = 0.10 
    //The minimum time the unit has to walk.
    private constant real MIN_WALK_DISTANCE = 0.20 
    //The minimum distance the unit has to walk. ( don't use 0 )
    private constant real MAX_WALK_DISTANCE = 50.00 
    //The max distance the unit can walk. ( Protection for teleport )
    private constant boolean TEST_MODE      = true
    //Should the test mode be on ( creates an effect above walkers when they walk ).

    // End of Setup, don't change anything below!
    
    private boolean ON = false
    private unit TEMP_UNIT
    private timer TIMER
    private group WALKERS = CreateGroup()
    private group TEMP_GROUP = CreateGroup()
    private hashtable HASH = InitHashtable()
endglobals

private keyword Walking

public function interface Event takes Walking w returns nothing

private function OutControl takes nothing returns nothing
    local unit u
    local Walking w
    call GroupAddGroup( WALKERS, TEMP_GROUP )
    loop
        set u = FirstOfGroup( TEMP_GROUP )
        exitwhen u == null
        call GroupRemoveUnit( TEMP_GROUP, u )
        set w = LoadInteger( HASH, GetHandleId( u ), 1 )
        call w.Control()
    endloop
endfunction

//Use IsWalking_EventOnStop from the outside of the scope
public function EventOnStop takes Event e, unit u returns nothing
    local Walking w
    if IsUnitInGroup( u, WALKERS ) then
        set w = LoadInteger( HASH, GetHandleId( u ), 1 )
        set w.onstop = e
    else
        debug call BJDebugMsg( "Not in group" )
    endif
endfunction

//Use IsWalking_EventOnStart from the outside of the scope
public function EventOnStart takes Event e, unit u returns nothing
    local Walking w
    if IsUnitInGroup( u, WALKERS ) then
        set w = LoadInteger( HASH, GetHandleId( u ), 1 )
        set w.onstart = e
    else
        debug call BJDebugMsg( "Not in group" )
    endif
endfunction

//Use IsWalking_EventOnWalk from the outside of the scope
public function EventOnWalk takes Event e, unit u returns nothing
    local Walking w
    if IsUnitInGroup( u, WALKERS ) then
        set w = LoadInteger( HASH, GetHandleId( u ), 1 )
        set w.onwalk = e
    else
        debug call BJDebugMsg( "Not in group" )
    endif
endfunction

//Use IsWalking_UnProtect from the outside of the scope
public function UnProtect takes unit u returns nothing
    local Walking w
    if IsUnitInGroup( u, WALKERS ) then
        set w = LoadInteger( HASH, GetHandleId( u ), 1 )
        set w.protect = false
    else
        debug call BJDebugMsg( "Not in group" )
    endif
endfunction

//Use IsWalking_Protect from the outside of the scope
public function Protect takes unit u returns nothing
    local Walking w
    if IsUnitInGroup( u, WALKERS ) then
        set w = LoadInteger( HASH, GetHandleId( u ), 1 )
        set w.protect = true
    else
        debug call BJDebugMsg( "Not in group" )
    endif
endfunction

//Use IsWalking_Duration from the outside of the scope
public function Duration takes unit u returns real
    local Walking w
    if IsUnitInGroup( u, WALKERS ) then
        set w = LoadInteger( HASH, GetHandleId( u ), 1 )
        return w.walktime
    else
        debug call BJDebugMsg( "Not in group" )
    endif
    return 0.00
endfunction

//Use IsWalking_Distance from the outside of the scope
public function Distance takes unit u returns real
    local Walking w
    if IsUnitInGroup( u, WALKERS ) then
        set w = LoadInteger( HASH, GetHandleId( u ), 1 )
        return w.distance
    else
        debug call BJDebugMsg( "Not in group" )
    endif
    return 0.00
endfunction

//Use IsWalking_LastDistance from the outside of the scope
public function LastDistance takes unit u returns real
    local Walking w
    if IsUnitInGroup( u, WALKERS ) then
        set w = LoadInteger( HASH, GetHandleId( u ), 1 )
        return w.distance_since
    else
        debug call BJDebugMsg( "Not in group" )
    endif
    return 0.00
endfunction

//Use IsWalking_Moving from the outside of the scope
public function Moving takes unit u returns boolean
    local Walking w
    if IsUnitInGroup( u, WALKERS ) then
        set w = LoadInteger( HASH, GetHandleId( u ), 1 )
        return w.walking
    else
        debug call BJDebugMsg( "Not in group" )
    endif
    return false
endfunction

//Use IsWalking_Remove from the outside of the scope
public function Remove takes unit u returns nothing
    local Walking w
    if IsUnitInGroup( u, WALKERS ) then
        set w = LoadInteger( HASH, GetHandleId( u ), 1 )
        call w.destroy()
    else
        debug call BJDebugMsg( "Not in group" )
    endif
endfunction

//Use IsWalking_Add from the outside of the scope
public function Add takes unit u returns nothing
    local Walking w
    if not IsUnitInGroup( u, WALKERS ) then
        set w = Walking.create( u )
        call SaveInteger( HASH, GetHandleId( u ), 1, w )
        if not ON then
            call TimerStart( TIMER, TIMER_INTERVAL, true, function OutControl )
            set ON = true
        endif
    else
        debug call BJDebugMsg( "Already in group" )
    endif
endfunction

private struct Walking
    unit walker = null
    real distance = 0.00
    real distance_since = 0.00
    real startx = 0.00
    real starty = 0.00
    real lastx = 0.00
    real lasty = 0.00
    real walktime = 0.00
    boolean walking = false
    boolean protect = false
    effect sfx = null
    Event onwalk = 0
    Event onstart = 0
    Event onstop = 0
    
    method onDestroy takes nothing returns nothing
        call FlushChildHashtable( HASH, GetHandleId( .walker ) )
        set .walker = null
        call GroupRemoveUnit( WALKERS, .walker )
        if TEST_MODE and .sfx != null then
            call DestroyEffect( .sfx )
            set .sfx = null
        endif
        set TEMP_UNIT = FirstOfGroup( WALKERS )
        if TEMP_UNIT == null then
            call PauseTimer( TIMER )
            set ON = false
        else
            set TEMP_UNIT = null
        endif
    endmethod
    
    method Control takes nothing returns nothing
        local real x = GetUnitX( .walker )
        local real y = GetUnitY( .walker )
        local real dx = x - .lastx
        local real dy = y - .lasty
        if IsUnitType( .walker, UNIT_TYPE_DEAD ) and not .protect then
            call .destroy()
            return
        endif
        set .distance_since = SquareRoot( dx * dx + dy * dy )
        set .lastx = x
        set .lasty = y
        if .distance_since > MAX_WALK_DISTANCE then
            debug call BJDebugMsg( "Teleporting" )
            return
        endif
        if .distance_since < MIN_WALK_DISTANCE then
            set .distance_since = 0.00
            set .distance = 0.00
            if .onstop != 0 and .walking then
                call .onstop.execute( this )
            endif
            set .walking = false
            set .startx = x
            set .starty = y
            set .walktime = 0.00
            if TEST_MODE then
                call DestroyEffect( .sfx )
                set .sfx = null
            endif
        else
            set .walktime = .walktime + TIMER_INTERVAL
            if not .walking and .walktime >= MIN_WALK_TIME then
                if .onstart != 0 then
                    call .onstart.execute( this )
                endif
                set .walking = true
                if TEST_MODE then
                    set .sfx = AddSpecialEffectTarget( "Abilities\\Spells\\Other\\TalkToMe\\TalkToMe.mdl", .walker, "overhead" )
                endif
            endif
            set .distance = .distance + .distance_since
            if .onwalk != 0 then
                call .onwalk.execute( this )
            endif
        endif
    endmethod
    
    static method create takes unit walker returns thistype
        local thistype this = thistype.allocate()
        set .walker = walker
        set .startx = GetUnitX( walker )
        set .starty = GetUnitY( walker )
        set .lastx = .startx
        set .lasty = .starty
        call GroupAddUnit( WALKERS, walker )
        return this
    endmethod
    
endstruct

private function init takes nothing returns nothing
    set TIMER = CreateTimer()
    call TimerStart( TIMER, TIMER_INTERVAL, true, function OutControl )
endfunction

endlibrary[/hidden]

Keywords:
Move, Moving, Walk, Walking, Detection, Movement
Contents

IsWalking v0.01 (Map)

Reviews
22:11, 5th Oct 2009 The_Reborn_Devil: This is quite useful I think, and it seems to be working too. I couldn't find any leaks, so I guess it's Approved. I give this system the rating Useful. If you (or someone else) feel that the rating this...

Moderator

M

Moderator

22:11, 5th Oct 2009
The_Reborn_Devil:

This is quite useful I think, and it seems to be working too.
I couldn't find any leaks, so I guess it's Approved.
I give this system the rating Useful.

If you (or someone else) feel that the rating this system was given is wrong then feel free to PM me.
 
Level 17
Joined
Mar 17, 2009
Messages
1,349
offtopic -- two curious questions:
What's important about library_once? Why not just "library"?
Also, is the library_once the reason for needing the IsWalking_ index before the functions although they're public?

And yes it seems like a useful system =) great job!
 
Level 10
Joined
May 19, 2008
Messages
176
library_once is something special. It tells the syntax checker should be implented only one time. So you can paste this library to times into your map without an error. Because the syntax checker removes the second library...

And the IsWalking_ prefix is added bei the public keyword. You can use it in all librarys and scopes.

cedi
 
Top