• 🏆 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!
  • ✅ Time to vote for the top 3 models! The POLL for Hive's 6th HD Modeling Contest: Mechanical is now open! 📅 Poll close on July 16, 2024! 🔗 Cast your vote now!
  • ✅ The POLL for Hive's Texturing Contest #33 is OPEN! Vote for the TOP 3 SKINS! 🔗Click here to cast your vote!

[Solved] Locals + Waits = MUI?

Status
Not open for further replies.
SO... I have just discovered locals and how cool they are, besides that they allow the use of waits. If you disagree please tell me why.
  • test
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Ax Toss
    • Actions
      • Custom script: local effect udg_TempEffect
      • Set TempUnit1 = (Triggering unit)
      • Set TempPoint1 = (Position of TempUnit1)
      • Special Effect - Create a special effect at TempPoint1 using Abilities\Spells\Other\Transmute\GoldBottleMissile.mdl
      • Custom script: call RemoveLocation(udg_TempPoint1)
      • Set TempEffect = (Last created special effect)
      • Wait 5.00 seconds
      • Special Effect - Destroy TempEffect
and this trigger works awesomely, I now see good reason in using waits in my triggers, someone please tell me why no one uses waits lol
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
cuz if u cast the ability twice within 5 secodns of eachother one effect will get destroyed twice (once before its finished) and the other will never get destroyed and leak. you cant use GUI locals. (does that not return a script error?!?!?)
 
cuz if u cast the ability twice within 5 secodns of eachother one effect will get destroyed twice (once before its finished) and the other will never get destroyed and leak. you cant use GUI locals. (does that not return a script error?!?!?)
Perhaps you should only post in the trigger section when you actually know whats going on ;p

This IS MUI and does NOT leak.
 
Level 20
Joined
Jul 6, 2009
Messages
1,885
You can use waits, but they're inaccurate. Especially in multiplayer games.

About your trigger, you don't need the TempUnit1 variable, just do this:
  • Set TempPoint1 = (Position of (Triggering unit))
and also add this action at the end:
  • Custom script: set udg_TempEffect = null
to clear a leak.
Whenever you use handle local variables, you need to null them after you don't need them anymore.

I'll just use this quote from the tutorial http://www.hiveworkshop.com/forums/trigger-gui-editor-tutorials-279/hashtables-mui-133407/ to explain how to distinguish handles:
What is a Handle?
For those needing it, here's a simple overview of what a handle is. There are many types in Warcraft 3: integers, reals, strings, units, players, items, special effects, etc. A handle is any type that is not either an integer, real, boolean, or string. An example of some commonly used handles are: units, destructables, items, players, special effects, floating text, and locations (referred to as "points" in GUI). There are many, many more handles than the list I gave, but these are just some of the more commonly used ones.
 
coz waits makes a system/spell non-MUI except for the above using locals,
and yes it is MUI, but do not use "udg_", just do "local effect eff", and
destroy it like...
  • Custom script: set eff = AddSpecialEffectLoc("Abilities\\Spells\Other\\Transmute\\GoldBottleMissile.mdl", udg_TempPoint1)
  • Custom script: call RemoveLocation(udg_TempPoint1)
  • Wait 5.00 seconds
  • Custom script: call DestroyEffect(eff)
plus you cant use waits in a loop nor a looping trigger, you cant use locals
in other functions as well...
 
You convert globals into locals, and I didn't know to null them ty, and I know what hashtables are, I use them quite frequently. And I know what a handle is
Anyway, destroying an effect doesn't null it?
coz waits makes a system/spell non-MUI except for the above using locals
Dude this is mui, the only thing I see wrong with waits is that it is slightly inaccurate.
plus you cant use waits in a loop nor a looping trigger
Yes you can, polled waits.

Alright well I've heard enough, can a moderator check this as solved?
 
Under certain circumstances, it's possible for a wait's inaccuracy to actually ruin a game.

For example, theoretically:

If I had to create units after waiting 5 seconds and make those invulnerable in a seperate
thread after 4.9, there's a chance they might run so that I'm making units invulnerable
without creating them.

This is only a theoretical example, I know it's stupid, but hey, all theoretical examples are =p
 
Under certain circumstances, it's possible for a wait's inaccuracy to actually ruin a game.

For example, theoretically:

If I had to create units after waiting 5 seconds and make those invulnerable in a seperate
thread after 4.9, there's a chance they might run so that I'm making units invulnerable
without creating them.

This is only a theoretical example, I know it's stupid, but hey, all theoretical examples are =p

If you're threading your triggers you're most likely using jass and know not to ever use TSA...

Anyway, maddeem, I know you've solved your issue, but I would be being lazy if I didn't tell you that you should stop using GUI!!!
 
Level 37
Joined
Mar 6, 2006
Messages
9,240
Waits in single player are always 0.1-0.2 more than what you specify.

0.00 seconds becomes 0.100, 0.125, 0.150, 0.175 or 0.200 seconds
1.00 seconds becomes 1.100, 1.125, 1.150, 1.175 or 1.200 seconds

So always a value chosen randomly from 0.1, 0.125, 0.150, 0.175 and 0.20 is added to the wait.

The method maddeedm used is called shadowing globals and it used to be more common back in the day. Blizzard was supposed to prevent shadowing but they never did.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Actually Blizzard fixed the shadowing, in case a global and a local variable share the same name, the global variable is used.
So, no this trigger is not MUI.

Before the patch, you could typecast types without any function call (without return bug).

Now, with jasshelper you can enable the variable shadowing if i remember.
With the right tag in jasshelper.conf, it will rename the variable for you.
But anyway it's often useless in GUI, just because GUI actions tends to split code in several functions even when it's useless, like the conditions of an if.
So, since you often go outside of the scope, your local variable can't be really used.
Sure, if you know how it compiles in jass, you can still a use a temp global variable when it's needed, but that becomes silly.

EDIT :

It seems i was wrong or it was true in an older patch, i just have tested this code :

JASS:
library Shadowing initializer init2

    globals
        integer i = 1
    endglobals

    private function GoOutsideScope takes nothing returns nothing
        call BJDebugMsg("outside scope i == " + I2S(i))
    endfunction
    
    private function init2 takes nothing returns nothing
        local integer i
        call TriggerSleepAction(0)
        call BJDebugMsg("begin")
        set i = 2
        call BJDebugMsg("there is local and a global sharing the same name ; i == " + I2S(i))
        call GoOutsideScope()
    endfunction
    
endlibrary

And the local usage is still used in case that a global and a local share the same name.

Now, with jasshelper it's trickier, if you don't have the tag [noshadowfixer] in your jasshelper.conf, it will consider you want it ( [doshadowfixer] ), then it will rename the local variable i in something like "l__i".
Btw if you're using the JNGP, the jasshelper.conf is the one in the "root" of your JNGP, not the one in the subfolder jasshelper
 
Last edited:
Level 14
Joined
Apr 20, 2009
Messages
1,543
The data can't be transferred to another trigger
It works for single trigger only, that's why

Exactly, a local variable only exists within the function it is declared in.
The value that is defined to this local variable can not be altered nor retrieved outside it's own function.

However you can pass the local variable as a parameter to a function in order to alter the local variable by returning a value from that function which is then defined as the local variable.
For example:

JASS:
function myFunction takes real i returns real
alter i here and then return it...
endfunction

function somefunction takes nothing returns nothing
local real i
set i = myFunction(i)
endfunction

A GUI trigger basically exists of a initialization function which adds events, actions and conditions to the trigger.
the actions added to a trigger is also a function. This same goes for conditions. If you would do this:
  • Actions
    • Custom script: local effect TempEffect
Then basically you're declaring the local variable within the actions function of the trigger.
Be aware: local variables can only be declared at the top of a function!
Declaring them underneath any other actions will not work. Defining them however does work of course...
 
Last edited:
Magtheridon96 said:
If you pause the game, the trigger continues (the wait time is still running)

Like I said.

This isn't some minor con that can be outweighed easily.

Waits are inaccurate as well.

AND, coupling waits with timers will kill chronology in your map if you have some trigger that waits about 10 minutes and executes a function if the player pauses the game for a small amount of time.

So you either use waits everywhere and NO periodic triggers, or you only use periodic triggers.

mckill2009 said:
Coz I've experienced before that you cant UnPause the unit without the wait...

Seriously?
One second.

edit
Tested it. You can unpause a unit after pausing him. (Or is that not what you meant?)
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
About the spell event and pause, you probably have an infinite delayed loop or something, i mean when you unpause the unit, it try again to cast the spell, and then the event fire again.
As far i remember unpause an unit is not immediate, so the usual trick turn off/on triggering trigger won't work here.

Now, giving a "stop" order or the "stun" order 851973 between the pause and unpause should work.

Note, that i'm just trying to guess what you meant, i have not done any test.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Well, that's still not directly related to the pause but to the spell event, if you use spell_effect event or an other one that won't happen.
And in fact you can pause the unit without a wait but that requires a special handling (no i'm not talking about stop the unit)

And btw i still don't get the usefulness of a such trigger.

EDIT :

Just for fun, here is a quick solution in GUI without any wait, it can be improved in many ways but it works :

  • cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Banish
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Triggering unit) is in Group) Equal To TRUE
        • Then - Actions
          • Unit Group - Remove (Triggering unit) from Group
        • Else - Actions
          • Unit Group - Add (Triggering unit) to Group
          • Unit - Pause (Triggering unit)
          • Wait 5.00 game-time seconds
          • Unit - Unpause (Triggering unit)
And in case the unit can die/be removed before the unpause and can resurect, an additional trigger must be added with the endcast event, in action a simple GroupRemoveUnit is needed.
(i'm assuming the event don't fire again in this case but i have not tested, maybe it still fire)
Ofc as said it can be improved and "vJassified" to make it better and more friendly to use.
 
Last edited:
Level 17
Joined
Apr 27, 2008
Messages
2,455
isnt it it's like this?, coz of the (infinite delayed loop as you said), the spell will be casted again, although I never tested your code...
  • Unit Group - Remove (Triggering unit) from Group
  • Unit - Unpause (Triggering unit)
nothing really important about the trigger I posted in the first place anyway...

I said that unpause it's not an immediate thing, but a delayed one, else i would juste use a DisableTrigger/EnableTrigger and the unpause between them ...
This work as expected, the "first" time the unit will be paused and added to the group, and when it will be unpaused, it will just be removed of the group.

I've posted it because you said that you haven't found a way without a wait. And i hate innacuracy, the fact is that you can pause an unit with a such event, you just need some workaround, mostly because the unpause is not immediate.
 
Status
Not open for further replies.
Top