• 🏆 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!

[Trigger] Detect no movement

Status
Not open for further replies.
Level 11
Joined
Feb 22, 2006
Messages
752
After a certain amount of time, check to see if unit's coordinates are the same as they were before. While it is possible that the the unit could have moved and went back to the EXACT same place, it's highly unlikely since wc3 distance units are really small and reals float to like 6 decimals or something in wc3 (or was it 4...i honestly don't remember).
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
You could use this script to check what are the distances between points of any Mechanical unit in the game every 0.2 seconds.

If you want it to be changed to whatever unit/unit type/unit whatever you want, just ask (and you know JASS... no ?).

Warning! This script requires Kattana's Local Handle Vars and a little script I made in your header (I put the little script down).

JASS:
// This will reduce the mana of any mechanical unit on the map upon moving.
// The actual value is the distance that unit moves within 0.2 seconds.
// If you want to change that value, see the comment in 13 lines.

function mechanicCon takes nothing returns boolean
    return IsUnitType(GetFilterUnit(),UNIT_TYPE_MECHANICAL) == true    
endfunction
function mecahnictimer takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit whichUnit = GetHandleUnit(t, "whichUnit")
    local real x = GetHandleReal(t, "x")
    local real y = GetHandleReal(t, "y")
    local real distance = DistanceBetweenPointsXY(x, y, GetUnitX(whichUnit), GetUnitY(whichUnit))
    local real mana = GetUnitState(whichUnit, UNIT_STATE_MANA )
    if distance > 0 then
        call SetUnitState(whichUnit, UNIT_STATE_MANA, mana-distance/20) // if you want to reduce or raise the value, just make it something like "mana-distance*20" or "mana-distance/20"
    endif 
    call FlushHandleLocals(t)
    call DestroyTimer(t) 
    set t = null
    set whichUnit = null
endfunction
function mechanic takes nothing returns nothing
    local timer t = CreateTimer()
    local group g = CreateGroup()
    local unit whichUnit
    local real x
    local real y
    call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, Condition(function mechanicCon)) 
    loop
        set t = null
        set whichUnit = FirstOfGroup(g)
        exitwhen whichUnit == null
        call GroupRemoveUnit(g, whichUnit)
        set t = CreateTimer()
        call SetHandleReal(t, "x", GetUnitX(whichUnit))
        call SetHandleReal(t, "y", GetUnitY(whichUnit))
        call SetHandleHandle(t, "whichUnit", whichUnit)
        call TimerStart(t, 0.2, false, function mecahnictimer)
    endloop
    call DestroyGroup(g)
    set g = null
    set whichUnit = null 
endfunction

//==== Init Trigger NewTrigger ====
function InitTrig_NewTrigger takes nothing returns nothing
    set gg_trg_NewTrigger = CreateTrigger()
    call TriggerRegisterTimerEventPeriodic( gg_trg_NewTrigger, 0.20 )
    call TriggerAddAction(gg_trg_NewTrigger, function mechanic)
endfunction

JASS:
//  --------------PUT ME IN YOUR HEADER-------------------
//****************************************************************************************
//               Distance between two points using coordinates
// call DistanceBetweenPointsXY(real x1, real y1, real x2, real y2)

function DistanceBetweenPointsXY takes real x1, real y1, real x2, real y2 returns real
    local real dx = oldx - x
    local real dy = oldy - y
    return SquareRoot(dx * dx + dy * dy)
endfunction
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
I think something like this should work.

Change the 'h000' to you unit type rawcode.

JASS:
function onesecondCon takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'h000'    
endfunction
function onesecondtimer takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit whichUnit = GetHandleUnit(t, "whichUnit")
    local real x = GetHandleReal(t, "x")
    local real y = GetHandleReal(t, "y")
    local real distance = DistanceBetweenPointsXY(x, y, GetUnitX(whichUnit), GetUnitY(whichUnit))
    if distance == 0 then
        call KillUnit(whichUnit)
    endif
    call FlushHandleLocals(t)
    call DestroyTimer(t)
    set t = null
    set whichUnit = null
endfunction
function onesecond takes nothing returns nothing
    local timer t = CreateTimer()
    local group g = CreateGroup()
    local unit whichUnit
    local real x
    local real y
    call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, Condition(function onesecondCon)) 
    loop
        set t = null
        set whichUnit = FirstOfGroup(g)
        exitwhen whichUnit == null
        call GroupRemoveUnit(g, whichUnit)
        set t = CreateTimer()
        call SetHandleReal(t, "x", GetUnitX(whichUnit))
        call SetHandleReal(t, "y", GetUnitY(whichUnit))
        call SetHandleHandle(t, "whichUnit", whichUnit)
        call TimerStart(t, 1, false, function onesecondtimer)
    endloop
    call DestroyGroup(g)
    set g = null
    set whichUnit = null 
endfunction

//==== Init Trigger NewTrigger ====
function InitTrig_NewTrigger takes nothing returns nothing
    set gg_trg_NewTrigger = CreateTrigger()
    call TriggerRegisterTimerEventPeriodic( gg_trg_NewTrigger, 0.20 )
    call TriggerAddAction(gg_trg_NewTrigger, function onesecond)
endfunction

It still requires that little code I put before and Kattana's local handle vars.
 
Last edited:
Level 11
Joined
Aug 25, 2006
Messages
971
I hate to break it to you, but this is the GUI section. Oh and using handle vars is very slow. I try to avoid them at almost all times.
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
I hate to break it to you, but this is the GUI section. Oh and using handle vars is very slow. I try to avoid them at almost all times.

Can't make it with GUI.
And how exacly can you make it without handle vars ? x.X

ok now im confused...

which scripts to i put in the header

and which scripts do i put in a trigger?


The code itself you put inside a trigger called "NewTrigger", then you can call it whatever you want.

Now in your header, put this script
JASS:
function DistanceBetweenPointsXY takes real x1, real y1, real x2, real y2 returns real
    local real dx = x1 - x2
    local real dy = y1 - y2
    return SquareRoot(dx * dx + dy * dy)
endfunction

And put in your header also Kattana's local handle vars if you havn't already.
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
Try making 3 arrays: unit array, LocX array and LocY array ( reals ). Then constantly check whether the X and Y position of every unit in the array is still the same as the corresponding LocX and LocY values. If this is false, the unit has moved thus you need to set LocX and LocY to the new coordinates and do your other actions...

Which would also be possible in GUI... more or less...
 
Level 11
Joined
Aug 25, 2006
Messages
971
And how exacly can you make it without handle vars ? x.X
You do the reverse of handle vars. Instead of attaching the struct to the unit, you attach the unit to the struct. Then periodiclly you cycle through all the structs. (Instead of cylcing through the units) Of course there are times when this is neither practical nor smart, but I've used it many many times.
 
Level 6
Joined
Jun 30, 2006
Messages
230
call TimerStart(t, 1, false, function mecahnictimer)

mecahnictimer? No such function exists, mate. I think you forgot to update the name when you renamed the functions from your first example.
 
ok so what exactly does this code even do...

JASS:
function mechanicCon takes nothing returns boolean
  return IsUnitType(GetFilterUnit(),UNIT_TYPE_MECHANICAL) == true
endfunction
function mecahnictimer takes nothing returns nothing
  local timer t = GetExpiredTimer()
  local unit whichUnit = GetHandleUnit(t, "whichUnit")
  local real x = GetHandleReal(t, "x")
  local real y = GetHandleReal(t, "y")
  local real distance = DistanceBetweenPointsXY(x, y, GetUnitX(whichUnit), GetUnitY(whichUnit))  local real mana = GetUnitState(whichUnit, UNIT_STATE_MANA )  if distance > 0 then
    call SetUnitState(whichUnit, UNIT_STATE_MANA, mana-distance/20)
  endif
  call FlushHandleLocals(t)
  call DestroyTimer(t)
  set t = null
  set whichUnit = null
endfunction
function mechanic takes nothing returns nothing
  local timer t = CreateTimer()
  local group g = CreateGroup()
  local unit whichUnit local real x local real y
  call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, Condition(function mechanicCon))
  loop
    set t = null
    set whichUnit = FirstOfGroup(g)
    exitwhen whichUnit == null
    call GroupRemoveUnit(g, whichUnit)
    set t = CreateTimer()
    call SetHandleReal(t, "x", GetUnitX(whichUnit))
    call SetHandleReal(t, "y", GetUnitY(whichUnit))
    call SetHandleHandle(t, "whichUnit", whichUnit)
    call TimerStart(t, 0.2, false, function mecahnictimer)
  endloop
  call DestroyGroup(g)
  set g = null
  set whichUnit = null
endfunction
//==== Init Trigger NewTrigger ====
function InitTrig_NewTrigger takes nothing returns nothing
  set gg_trg_NewTrigger = CreateTrigger()
  call TriggerRegisterTimerEventPeriodic( gg_trg_NewTrigger, 0.20 )
  call TriggerAddAction(gg_trg_NewTrigger, function mechanic)
endfunction
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
I don't know why you are getting any errors as I got 0.

By the way, I just tested it and it worked.

Incase there are errors in the previous script (though there shouldn't be any), ill post it here.

Make sure to name your trigger "NewTrigger", copy the code into it, and only then change the name to whatever you want.

JASS:
function onesecondCon takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'h000'    
endfunction
function onesecondtimer takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit whichUnit = GetHandleUnit(t, "whichUnit")
    local real x = GetHandleReal(t, "x")
    local real y = GetHandleReal(t, "y")
    local real distance = DistanceBetweenPointsXY(x, y, GetUnitX(whichUnit), GetUnitY(whichUnit))
    if distance == 0 then
        call KillUnit(whichUnit)
    endif
    call FlushHandleLocals(t)
    call DestroyTimer(t)
    set t = null
    set whichUnit = null
endfunction
function onesecond takes nothing returns nothing
    local timer t = CreateTimer()
    local group g = CreateGroup()
    local unit whichUnit
    local real x
    local real y
    call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, Condition(function onesecondCon)) 
    loop
        set t = null
        set whichUnit = FirstOfGroup(g)
        exitwhen whichUnit == null
        call GroupRemoveUnit(g, whichUnit)
        set t = CreateTimer()
        call SetHandleReal(t, "x", GetUnitX(whichUnit))
        call SetHandleReal(t, "y", GetUnitY(whichUnit))
        call SetHandleHandle(t, "whichUnit", whichUnit)
        call TimerStart(t, 1, false, function onesecondtimer)
    endloop
    call DestroyGroup(g)
    set g = null
    set whichUnit = null 
endfunction

//==== Init Trigger NewTrigger ====
function InitTrig_NewTrigger takes nothing returns nothing
    set gg_trg_NewTrigger = CreateTrigger()
    call TriggerRegisterTimerEventPeriodic( gg_trg_NewTrigger, 0.20 )
    call TriggerAddAction(gg_trg_NewTrigger, function onesecond)
endfunction
 
Status
Not open for further replies.
Top