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

[Solved] Distance Between Points Greater Than..

Status
Not open for further replies.
Level 2
Joined
Apr 5, 2019
Messages
16
So I'm using this trigger, and for some odd reason it WORKS with "less than" but not with "greater than" which is what I need:

Code:
Arthas return
    Events
        Time - Every 3.00 seconds of game time
    Conditions
    Actions
        Custom script:   local unit udg_target
        Custom script:   local location udg_arthas
        Custom script:   local location udg_arthas2
        Set VariableSet target = Deathlord Arthas 0014 <gen>
        Set VariableSet arthas = (Position of target)
        Set VariableSet arthas2 = (Center of Arthas <gen>)
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            If - Conditions
                (Distance between arthas and arthas2) Greater than 600.00
            Then - Actions
                Unit - Move target instantly to arthas2
            Else - Actions
                Do nothing
        Custom script:   call RemoveLocation(udg_arthas)
        Custom script:   call RemoveLocation(udg_arthas2)
        Custom script:   set udg_target = null

Any ideas?

EDIT: It seems local variables aren't recognized inside the if statement. Is there a way to solve this?
 
Last edited:
Level 2
Joined
Apr 5, 2019
Messages
16
Well, I guess this can be closed/deleted.
I've found that it's impossible (unless using some JASS technique that is probably too much to learn just for that?)
 
Level 6
Joined
Dec 31, 2017
Messages
138
Remove the locals, it's not necessary.
He probably wants to do it MUI.

The easy solution would be converting your trigger to text: Screenshot
Then you can remove "target", "arthas", "arthas2" from global variables.

The only issue is GUI trigger editor is stupid, so it creates another function to calculate if "(Distance between arthas and arthas2) Greater than 600.00": Screenshot
As your variables are local, to this funtion they are unknown.

But since your trigger is fairly easy you don't need JASS to fix it, English will do.
Just replace "Trig_asd_Func004C()" with "DistanceBetweenPoints(udg_arthas, udg_arthas2) > 600.00" and remove unnesessary function entirely.

You'll end with something like this:
Code:
function Trig_asd_Actions takes nothing returns nothing
    local unit udg_target
    local location udg_arthas
    local location udg_arthas2 
    set udg_target = gg_unit_Harf_0000
    set udg_arthas = GetUnitLoc(udg_target)
    set udg_arthas2 = GetRectCenter(gg_rct_Arthas)
    if ( DistanceBetweenPoints(udg_arthas, udg_arthas2) > 600.00 ) then
        call SetUnitPositionLoc( udg_target, udg_arthas2 )
    else
    endif
    call RemoveLocation(udg_arthas)
    call RemoveLocation(udg_arthas2)
endfunction

//===========================================================================
function InitTrig_asd takes nothing returns nothing
    set gg_trg_asd = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic( gg_trg_asd, 2 )
    call TriggerAddAction( gg_trg_asd, function Trig_asd_Actions )
endfunction
 
Last edited:
Level 12
Joined
Jan 30, 2020
Messages
875
Sorry, I don't mean to add something useless to an already solved issue.

I just wanted to point out that the need for local variables is in no way directly related to waits or timers.
Local variables are needed when you need to run multiple instances of the same function simultaneously (being a trigger or any other function)

EDIT :was seeing your signature, don't kill me for grammar, English is not my mother tongue and I am still learning :) But know that I used to have a very similar signature back in the old days on french forums for my own language :D
 
Level 6
Joined
Dec 31, 2017
Messages
138
Local variables are needed when you need to run multiple instances of the same function simultaneously (being a trigger or any other function)
At least before Reforged triggers were single-threaded.
So triggers run line by line unless interrupted by something like Wait.

But I presume Klayz had some reason to go for it. It just isn't on the snippet.
 
Level 12
Joined
Jan 30, 2020
Messages
875
Stupid me, I shouldn't have hooked that to hijack another thread :D

I am still from old school 2004 Jass2.
I don't know what influence single / multi-threading may have on trigger and function instances.

What I know is that even when many instances are running, i can freely use calls to TriggerSleepAction without any conflict / collision, on the condition i store the event response required in local variables.

So can you please explain to me what you mean with "triggers run line by line unless interrupted by something like a wait" ? Is this specifically related to the event responses ?

Side note for the OP : I am really sorry I had no intention to hijack your question.
 
Level 6
Joined
Dec 31, 2017
Messages
138
What I know is that even when many instances are running, i can freely use calls to TriggerSleepAction without any conflict / collision, on the condition i store the event response required in local variables.
Technically speaking you cannot have 2 instances of the same trigger or 2 different triggers running at the same time.

This situation is possible:

Instance A part 1
Instance B part 1
Instance A part 2
Instance B part 2
OR
Instance A part 1
Instance B part 1
Instance B part 2
Instance A part 2

And if trigger A and trigger B use the same global variables, let's say it's amout of damage, calculated in part 1, Instance B will interfere into Instance A.
For example, (Instance A part 2) will damage unit A by the amount of damage (Instance B part 2) damaged unit B by.
Or even damage unit B again.

But for this situation to happen, trigger A must have something that interrupts its running.
Like Wait.
 
Level 12
Joined
Jan 30, 2020
Messages
875
Ok I was not worried about the global variables, I only use them in local triggers in very specific situations where there is no possible conflict.

But I completely understand you example here.

My question was rather about how Warcraft 3 manages to run several instances of the same trigger ? It queues them chronologically ?

For example, in my TD maps, I spawn Balls instead of creeps. Everytime I spawn a Ball (it is in fact recycled), I enable a bunch of specific triggers with specific unit events (for performance) for that one Ball. One of these triggers has EVENT_UNIT_DAMAGED (the idea is to shrink the Ball when it loses HP).

As you can Imagine, being a TD, each Ball gets hit an impressive amount of times every second when in the middle of the player's maze. Everything works perfectly, so I supposed the trigger had to run all instances generated everytime the event triggers the trigger (I only set the new size of the Ball to the Ball's HP left, so I can't really check if there is any conflict).
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,202
EDIT: It seems local variables aren't recognized inside the if statement. Is there a way to solve this?
Use JASS directly and one can see the reason pretty obviously. Each conditional statement is its own function, and hence out of scope of the local variables. Possibly a reason why GUI does not support local variables directly at the moment.
 
Level 6
Joined
Dec 31, 2017
Messages
138
My question was rather about how Warcraft 3 manages to run several instances of the same trigger ? It queues them chronologically ?
Well yes, but actually no. Game tries to, but it's easy to brake.
Consider (udg_timer is just a timer I start at Map Init):
Code:
function Trig_sdsad_Actions takes nothing returns nothing
    local real t
    set t = TimerGetElapsed(udg_timer)
    call DisplayTextToForce( GetPlayersAll(), "|c00ff0000 " + R2S(t) + "|r")
    call CreateNUnitsAtLoc( 100, 'hfoo', Player(0), GetRectCenter(GetPlayableMapRect()), bj_UNIT_FACING )
    call TriggerSleepAction( 1.000 )
    call DisplayTextToForce( GetPlayersAll(), "|c0000cc00 " +R2S(t)  + "|r")
endfunction

//===========================================================================
function InitTrig_sdsad takes nothing returns nothing
    set gg_trg_sdsad = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic( gg_trg_sdsad, 1.00 )
    call TriggerAddAction( gg_trg_sdsad, function Trig_sdsad_Actions )
endfunction
 
Level 12
Joined
Jan 30, 2020
Messages
875
Ok so every second, an instance on the callback function is run.
It stores the current time elapsed on your global timer, displays the value to all players, then creates 100 units for Player 1 at map center and 1 second later displays the value you stored at the beginning of the instance.

If I get what you mean correctly, this will make every new instance start before the last ones finish because creating 100 units (+ calls to natives, etc...) is far from being instant, might even take a couple of seconds (never tested it actually). So the game will try to queue these instances by intricating them, but as more new instances are created than instances closed, it will end up loosing track? Is that it ?

I suppose I never ran into this kind of bug because I don't add waits in my callback function for units taking damage.
Fun enough, in some cases I have to use zero seconds triggersleeps to make certain things work properly. But I usually only add sleeps for things like removing dead units after a couple of seconds so that won't cause any issue.

Still, this is a solid reminder that we always have to be careful when it comes to abusing timers and waits.

Thanks. I'll keep that in mind.
 
Level 39
Joined
Feb 27, 2007
Messages
5,024
might even take a couple of seconds (never tested it actually)
Absolutely not. It is reasonable to assume that everything in JASS/Lua runs instantaneously; it's only when many such actions are done in a row (thousands, likely) or a very performance-intensive actions are done that a duration of execution may be relevant. The issue is not that these actions take some significant amount of time to proceed; the issue is that TriggerSleepAction is not always accurate whereas timers (always?) are. In one instance of the trigger the TSA might be slightly less than 1 second and in another slightly more, which would throw the text messages out of whack. If it was always just slightly less than 1 second you would see this:
  • Message 1A

  • Message 1B
  • Message 2A

  • Message 2B
  • Message 3A

    ...

  • Message NA
  • Message NB
If it was always slightly more than 1 second you would see this:
  • Message 1A

  • Message 2A
  • Message 1B
  • Message 3A
  • Message 2B

  • Message 4A
  • Message 3B

    ...

  • Message NA

  • Message (N+1)A
  • Message NB

  • Message (N+2)A
  • Message (N+1)B
Since TSA can be <1 or >1 you will get an output that is a combination of these two possible patterns.
Still, this is a solid reminder that we always have to be careful when it comes to abusing timers and waits.
Using them is not abusing them. The problem comes from trying to mix timers and waits in a way that requires the timing to be very precise. If timing matters greatly, always use only timers. If timing doesn't matter, you can use a combination or just all waits.

Waits also progress while the game is lagging/paused, and timers do not.
 
Level 12
Joined
Jan 30, 2020
Messages
875
Well thanks to the both of you guys.
This information is precious.
You know, nobody knew this back in my time, or so few people that never shared it.

Since I returned in December, and while reading around competent people answering members questions, I often saw references to waits like it was the devil in certain situations, and I had no idea what it was on about !

It probably seems so obvious to today experts that Deserted would not expect me not to understand like I did.

Now you revealed this to me it all makes sense.
The good thing is that it confirms my Jass old times good practices (using things you don't fully understand with caution is one of them), and also that I never made any bad usage of timers and waits. The other good thing is now I will also know when to never rely on waits.

Also, thanks for giving me a scale when execution of actions can start to be considered as not being instant.

I have learnt so much more since December than I had between 2002 and 2004, this is hard to believe !

Not only the entire map making community has become much more mature after 16 years, but also immensely more competent. You guys are amazing !
 
Status
Not open for further replies.
Top