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

[JASS] Help with Wait for multiple condition

Status
Not open for further replies.
Level 3
Joined
Mar 7, 2012
Messages
30
Hello. I'm kinda new to mapmaking & triggering (about 1 month now :) ) and I'm trying to make a trigger. I need to make spells which will "change" the user into an animal and then when the animal uses the ability it will come back to its original form. So this is I got it work so far: First I store the transforming abilities in an array and the form of each ability in another array (I have just put one for now). I also store a Rect which for some reason it won't work.
  • Shape Forms
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set Shape_Rect = (Rect(9.00, 225.00, 13.00, 230.00)) //area,will eplain later
      • Set Shape_Count = 1 //how many spells there are
      • Set Shape_Abil[1] = Shapeshift (Wolf) //the spell
      • Set Shape_Form[1] = Dire Wolf // the form of each spell
I want the trigger to see when a unit casts one of these abilities and move it to a specific area (Shape_Rect), spawn the Shape_Form unit in its place. Also it will make the caster unit neutral and invulnerable. I have succeed half of that. I have made it possible to place the Shape_Form in its place and make it neutral and invulnerable but it won't move to the rect with the specified coordinates. The trigger is in JASS and I will post it in the end.
The second part: When the Shape_Form unit casts the ability "Shift Back" the original unit will come back to the Shape_Form's place with the normal owner and vulnerable. The Shape_Form unit will be removed. So this is the JASS part (I will put a comment on each line I have a problem)
JASS:
function Trig_Shapeshift_Copy_Actions takes nothing returns nothing
    local integer abil_number //this is the number of the ability found in array
    local unit shape_unit //this is the original unit
    local unit shape_unit2 //this is the unit that will be spawned
    local player shape_player //this is the owner of the original unit
    set abil_number = 0
    set shape_unit = GetTriggerUnit()
    set shape_player = GetOwningPlayer(GetTriggerUnit())
    set bj_forLoopAIndex = 1
    set bj_forLoopAIndexEnd = udg_Shape_Count
    loop
      exitwhen bj_forLoopAIndex > bj_forLoopAIndexEnd
      if ( GetSpellAbilityId() == udg_Shape_Abil[GetForLoopIndexA()] ) then
          set abil_number = GetForLoopIndexA()
      else
          call DoNothing(  )
      endif
      exitwhen abil_number > 0
      set bj_forLoopAIndex = bj_forLoopAIndex + 1
  endloop
  if abil_number > 0 then
      call CreateNUnitsAtLocFacingLocBJ( 1, udg_Shape_Form[abil_number], GetOwningPlayer(shape_unit), GetUnitLoc(shape_unit), GetRandomLocInRect(GetPlayableMapRect()) )
      set shape_unit2 = GetLastCreatedUnit()
      call SetUnitInvulnerable( shape_unit, true )
      call SetUnitPositionLoc( shape_unit, GetRandomLocInRect(udg_Shape_Rect) )
      call SetUnitOwner( shape_unit, Player(PLAYER_NEUTRAL_PASSIVE), true )
        loop
            //this is the part I don't know what to add to check for ability until it 
           //gets the ability "Shift Back" (abilcode) casted by the shape_unit2
        endloop //the part below hasn't been tested since I cant make the 
                   //condition
        call SetUnitPositionLoc(shape_unit, GetUnitLoc(shape_unit2) )
        call RemoveUnit( shape_unit2 )
        call SetUnitInvulnerable( shape_unit, false )
        call SetUnitOwner( shape_unit, shape_player, true )           
    else
        call DoNothing(  )
    endif
endfunction

//===========================================================================
function InitTrig_Shapeshift_Copy takes nothing returns nothing
    set gg_trg_Shapeshift_Copy = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Shapeshift_Copy, EVENT_PLAYER_UNIT_SPELL_CAST )
    call TriggerAddAction( gg_trg_Shapeshift_Copy, function Trig_Shapeshift_Copy_Actions )
endfunction

I have used locals because if I use globals it won't work if multiple players shapeshift. Thanks in advance for any help given :) :D
 
Last edited:
Level 19
Joined
Aug 8, 2007
Messages
2,765
First of all, your jassing is quite bad, its just a converted trigger with swapped out locals. To use locals in gui, you would do something like this

local unit u = WhateverUnit
set udg_TempUnit (a temp variable) = u
wait whatever seconds
set udg_tempunit = u (TempUnit may have been overwritten, but since u is a local it will not be)
set u = null (prevent leaks)

Im not going to look over that trigger because it uses things no JASSer would ever use (like bj_forLoopAIndex). Put that back into GUI form (if possible) and use the local trick above and re-post the trigger

e/ also, pro trick, a "do nothing" literaly does NOTHING, its just wasted code space. remove it
 
Level 3
Joined
Mar 7, 2012
Messages
30
First of all thanks for answering. I am very new to triggering and JASS so that's why the JASS part is so bad. Here's the trigger in GUI with global variables. I'd like to use local variables if possible but I can't find out how. The variables Shape_Rect , Shape_Form (array), Shape_Abil (array), Shape_Count are set in another trigger I will post before the main one.

  • Shape Forms
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set Shape_Rect = (Rect(9.00, 225.00, 13.00, 230.00)) //Rect variable
      • Set Shape_Count = 1 //integer
      • Set Shape_Abil[1] = Shapeshift (Wolf) //ability
      • Set Shape_Form[1] = Dire Wolf //unit
And now the script I want to use locals.
  • Shapeshift2
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
    • Actions
      • Set abil_number = 0 //integer ***
      • Set a_tmp_u1 = (Casting unit) //unit ***
      • Set shape_player = (Owner of a_tmp_u1) //player ***
      • For each (Integer A) from 1 to Shape_Count, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Ability being cast) Equal to Shape_Abil[(Integer A)]
            • Then - Actions
              • Set abil_number = (Integer A)
            • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • abil_number Not equal to 0
        • Then - Actions
          • Unit - Create 1 Shape_Form[abil_number] for (Owner of a_tmp_u1) at (Position of a_tmp_u1) facing (Position of a_tmp_u1)
          • Set a_tmp_u2 = (Last created unit) //unit ***
          • Unit - Make a_tmp_u1 Invulnerable
          • Unit - Move a_tmp_u1 instantly to (Random point in Shape_Rect)
          • Unit - Change ownership of a_tmp_u1 to Neutral Passive and Retain color
          • Wait until (((Ability being cast) Equal to Shift Back ) and ((Casting unit) Equal to a_tmp_u2)), checking every 1.00 seconds
          • Unit - Move a_tmp_u1 instantly to (Position of a_tmp_u2)
          • Unit - Remove a_tmp_u2 from the game
          • Unit - Make a_tmp_u1 Vulnerable
          • Unit - Change ownership of a_tmp_u1 to shape_player and Retain color
        • Else - Actions
The type of each variable is stated next to the //. The variables with the *** are the ones I want to be turned to locals.
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
First of all thanks for answering. I am very new to triggering and JASS so that's why the JASS part is so bad. Here's the trigger in GUI with global variables. I'd like to use local variables if possible but I can't find out how. The variables Shape_Rect , Shape_Form (array), Shape_Abil (array), Shape_Count are set in another trigger I will post before the main one.

  • Shape Forms
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set Shape_Rect = (Rect(9.00, 225.00, 13.00, 230.00)) //Rect variable
      • Set Shape_Count = 1 //integer
      • Set Shape_Abil[1] = Shapeshift (Wolf) //ability
      • Set Shape_Form[1] = Dire Wolf //unit
      • // no need for locals here
And now the script I want to use locals.
  • Shapeshift2
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
    • Actions
      • Custom Script: local integer i
      • Custom Script: local unit u
      • Custom Script: local unit u2
      • Custom Script: local player p
      • Set abil_number = 0 //integer ***
      • Set a_tmp_u1 = (Casting unit) //unit ***
      • Set shape_player = (Owner of a_tmp_u1) //player ***
      • Custom Script: set i = udg_abil_number
      • Custom Script: set u = udg_a_tmp_u1
      • Custom Script: set p = udg_shape_player
      • For each (Integer A) from 1 to Shape_Count, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Ability being cast) Equal to Shape_Abil[(Integer A)]
            • Then - Actions
              • Set abil_number = (Integer A)
            • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • abil_number Not equal to 0
        • Then - Actions
          • Unit - Create 1 Shape_Form[abil_number] for (Owner of a_tmp_u1) at (Position of a_tmp_u1) facing (Position of a_tmp_u1)
          • Set a_tmp_u2 = (Last created unit) //unit ***
          • Custom script : set u2 = udg_a_tmp_u2
          • Unit - Make a_tmp_u1 Invulnerable
          • Unit - Move a_tmp_u1 instantly to (Random point in Shape_Rect)
          • Unit - Change ownership of a_tmp_u1 to Neutral Passive and Retain color
          • Wait until (((Ability being cast) Equal to Shift Back ) and ((Casting unit) Equal to a_tmp_u2)), checking every 1.00 seconds // WTF????????????????????????? these are constants and will NEVER change (in one function call that is)
          • Custom Script: set udg_abil_number = i
          • Custom Script: set udg_a_tmp_u1 = u
          • Custom Script: set udg_a_tmp_u2 = u2
          • Custom Script: set udg_shape_player = p
          • Unit - Move a_tmp_u1 instantly to (Position of a_tmp_u2)
          • Unit - Remove a_tmp_u2 from the game
          • Unit - Make a_tmp_u1 Vulnerable
          • Unit - Change ownership of a_tmp_u1 to shape_player and Retain color
        • Else - Actions
The type of each variable is stated next to the //. The variables with the *** are the ones I want to be turned to locals.

The wait in that trigger confuses me.
 
Level 3
Joined
Mar 7, 2012
Messages
30
I want the trigger to move on to the next actions when a_tmp_u2 unit casts the ability Shift Back. That wait trigger is what confuses me as well :p
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
I want the trigger to move on to the next actions when a_tmp_u2 unit casts the ability Shift Back. That wait trigger is what confuses me as well :p

why dont use 2 trigger?

example you can save the progress to variable or to hashtable

wait usefull when u want define the duration but if its undefinied and condition is spell casting then u can do 2 trigger or 1 trigger wiht condition

//notice neutral passive dont use ability :p

basic example:

  • Melee Initialization
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Berserker Upgrade
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Owner of (Triggering unit)) Not equal to Neutral Passive
        • Then - Actions
          • Set OwnerPlayer[(Custom value of (Triggering unit))] = (Triggering player)
          • ------- idk if needed but u can store the unit type to variable ------- Set TransformedForm[(Custom value of (Triggering unit))] = (Unit-type of (Triggering unit))
          • Set Old_Position[(Custom value of (Triggering unit))] = (Position of (Triggering unit))
          • Set Point = (Random point in Region 000 <gen>)
          • Unit - Add Invulnerable (Neutral) to (Triggering unit)
          • Unit - Change ownership of (Triggering unit) to Neutral Passive and Change color
          • Custom script: call RemoveLocation(udg_Point)
        • Else - Actions
          • Unit - Move (Triggering unit) instantly to Old_Position[(Custom value of (Triggering unit))]
          • Unit - Remove Invulnerable (Neutral) from (Triggering unit)
          • Unit - Change ownership of (Triggering unit) to OwnerPlayer[(Custom value of (Triggering unit))] and Change color
          • Custom script: call RemoveLocation(udg_Old_Position[GetUnitUserData(GetTriggerUnit())])
 
Level 3
Joined
Mar 7, 2012
Messages
30
I have to use locals. I don't think globals will be good because in the game there can be many different units using this kind of ability or the same unit using different abilities in the array. About the notice: unit2 is using the ability which is owned by the triggering player until it casts the ability Shift Back which will destroy it and bring unit1 back. (at least that's what i want it to do lol)
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
I have to use locals. I don't think globals will be good because in the game there can be many different units using this kind of ability or the same unit using different abilities in the array.

if u can indentify the unit then globals arent problem..

this problem when use something like Pista[1] for spells, but when u use unique index for array then it is work well this is why exist the unit indexers

http://www.hiveworkshop.com/forums/...rev=search=bribe%20unit%20indexer&d=list&r=20

about abilities u can make a loop where u check if casted ability is Ability[For Loop A]

  • For each (Integer A) from 1 to 10, do (Actions)
    • Loop - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Ability being cast) Equal to Ability[(Integer A)]
        • Then - Actions
          • -------- transform to UnitInteger A] --------
        • Else - Actions
 
Level 3
Joined
Mar 7, 2012
Messages
30
if u can indentify the unit then globals arent problem..

this problem when use something like Pista[1] for spells, but when u use unique index for array then it is work well this is why exist the unit indexers

http://www.hiveworkshop.com/forums/...rev=search=bribe%20unit%20indexer&d=list&r=20

about abilities u can make a loop where u check if casted ability is Ability[For Loop A]

  • For each (Integer A) from 1 to 10, do (Actions)
    • Loop - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Ability being cast) Equal to Ability[(Integer A)]
        • Then - Actions
          • -------- transform to UnitInteger A] --------
        • Else - Actions

I have already made the array with the abilities (see the GUI part in my 1st post) I will try what you suggested and I'll post how it went ;)
 
Level 3
Joined
Mar 7, 2012
Messages
30
I think I did it halfway. I made 2 triggers: Shapeshift and Shift Back. Problem is it will only work for the 1st time. The second time, Shift Back will work up to the unit pause command. I also made a modification to adjust the unit's life.

  • Shift Back
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
      • (Ability being cast) Equal to Shift Back
    • Actions
      • For each (Integer A) from 1 to shape_abil_counter, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Owner of shape_u2[(Integer A)]) Equal to (Owner of (Triggering unit))
              • (Triggering unit) Equal to shape_u2[(Integer A)]
            • Then - Actions
              • Unit - Pause shape_u2[(Integer A)]
              • Wait 2.00 game-time seconds
              • Unit - Move shape_u1[(Integer A)] instantly to (Position of shape_u2[(Integer A)])
              • Unit - Set life of shape_u1[(Integer A)] to (Percentage life of shape_u2[(Integer A)])%
              • Unit - Set mana of shape_u1[(Integer A)] to (Percentage mana of shape_u2[(Integer A)])%
              • Unit - Kill shape_u2[(Integer A)]
              • Unit - Make shape_u1[(Integer A)] Vulnerable
              • Unit - Change ownership of shape_u1[(Integer A)] to shape_owner[(Integer A)] and Change color
              • Set shape_u1[(Integer A)] = No unit
              • Set shape_u2[(Integer A)] = No unit
              • Set shape_owner[(Integer A)] = Neutral Hostile
            • Else - Actions
  • Shapeshift
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
    • Actions
      • For each (Integer A) from 1 to Shape_Count, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Ability being cast) Equal to Shape_Abil[(Integer A)]
            • Then - Actions
              • Set abil_number = (Integer A)
            • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • abil_number Greater than 0
        • Then - Actions
          • Set shape_abil_counter = (shape_abil_counter + 1)
          • Set shape_u1[shape_abil_counter] = (Triggering unit)
          • Set shape_owner[shape_abil_counter] = (Owner of shape_u1[shape_abil_counter])
          • Unit - Create 1 Shape_Form[abil_number] for shape_owner[shape_abil_counter] at (Position of shape_u1[shape_abil_counter]) facing (Position of shape_u1[shape_abil_counter])
          • Set shape_u2[shape_abil_counter] = (Last created unit)
          • Set abil_number = 0
          • Unit - Change ownership of shape_u1[shape_abil_counter] to Neutral Passive and Retain color
          • Unit - Move shape_u1[shape_abil_counter] instantly to (Random point in Shape_Rect)
          • Unit - Make shape_u1[shape_abil_counter] Invulnerable
          • Unit - Set life of shape_u2[shape_abil_counter] to (Percentage life of shape_u1[shape_abil_counter])%
          • Unit - Set mana of shape_u2[shape_abil_counter] to (Percentage mana of shape_u1[shape_abil_counter])%
        • Else - Actions
 
Level 11
Joined
Aug 6, 2009
Messages
697
Problem is it will only work for the 1st time. The second time, Shift Back will work up to the unit pause command

This spell isn't MUI

http://www.hiveworkshop.com/forums/trigger-gui-editor-tutorials-279/hashtables-mui-133407/

MUI is Multiple Unit Instances. This means that if you have a trigger where one unit is doing something at one time and a unit does the same thing, the trigger will stop the first unit who is currently doing the trigger or it will just completely bug out.

If your spell is MUI, this problem wont happen, instead both units will be completely fine.
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
The trigger you posted will glitch, if 2 or more units are using that abil and one turns back the others will turn back


Anyway, ill post when i get back from school how to do your above trigger via hashtables.

Also note that Integer A is a global, not a local so integer A can be overwritten in those two seconds
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Actually hashtables are quite unusable in GUI with the JNGP.
It's probably because with the newest patches, the official editor executable was edited.

But leave the obscure side, abandon GUI totally, come to the light one, write only (v)jass.
 
Level 3
Joined
Mar 7, 2012
Messages
30
Since I'm new to the map making I'll stick to GUI for now :p I understand a bit how JASS works but GUI is much easier to use for newbies ^_^
 
Level 3
Joined
Mar 7, 2012
Messages
30
There is a slight problem. When I use the World Editor NewGen as Assassins-Creed suggested it won't let me open the map I am making and will crash showing multiple errors. They have to do about some function which are not found or something like that. Does anyone have any idea about this or shall I post screenshot?
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
to be quite honest, thats kinda true. your statement about hashtables isnt though

I mean without any custom script (since we can't seriously consider them as GUI, there is nothing graphic with them ...)

I don't use GUI anymore since years, but i'm 100 % sure that with JNGP many GUI features are not available with the JNGP, related to hashtables and the "new" GUI type : handle (and maybe more stuff, i just don't care)

But now i'm thinking about it, it could be related to the wc3 language installed, just like the RISC colorizer doesn't work on a not english wc3 editor.
Even if i don't believe that much in it, since i think (not sure) it worked in previous wc3 versions.

So say me if you can totally use the handle type in GUI with an english wc3 and the JNGP. (compare it with the official editor)
 
Level 3
Joined
Mar 7, 2012
Messages
30
Since running as admin didn't work I did something else: export, open WE NewGen, import lol. I'll try doing the trigger with the hashtable and I'll let you know soon. :D
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
Dont PM me when im vegetating, because it auto-refreshes and the popup is annoying. doing it in JNGP just requires an extra function call, nothing near the other atrocitys of GUI

  • Hashtable - Save Handle Of(Last created unit) as 0 of 0 in (Last created hashtable)
  • Set TempInt = (Load 0 of 0 from (Last created hashtable))
 
Level 3
Joined
Mar 7, 2012
Messages
30
It seems JNPG must have WEU enabled in order to accept the triggers. Since I can't switch the triggers back (alrdy too many to start over). I'll have to do it different way. Will multi arrays work in any way? If not is it possible to use hashtables with JASS?
EDIT: corrected a stupid mistake
 
Last edited:
Level 17
Joined
Apr 27, 2008
Messages
2,455
Illidans911 said:
Dont PM me when im vegetating, because it auto-refreshes and the popup is annoying. doing it in JNGP just requires an extra function call, nothing near the other atrocitys of GUI

Technically that wasn't a pm.
But for sure, next time i will check my Crystall ball to guess if you're vegetating or not before send you a visitor message (or just don't write a visitor message at all, it could be a more valid solution)

Well, i will believe you on that, i mean ok you have less api in GUI with hashtable on the JNGP, but if you say that can be handled easily i will take as the truth, mostly because i don't care that much :p
I was just curious if it was related to the wc3 language installed or not.

@Assassins-Creed : good question, but i dare to think he has tested his claim.
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
"but i dare to think he has tested his claim"

nahh.....

@Assassin - yes, because in JNGP you cant load handle ids but u can save handle ids
 
Level 3
Joined
Mar 7, 2012
Messages
30
It seems JNPG must have WEU enabled in order to accept the triggers. Since I can't switch the triggers back (alrdy too many to start over). I'll have to do it different way. Will multi arrays work in any way? If not is it possible to use hashtables with JASS?
Someone answer plz? :p
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
You can use hashtables easily with JNGP GUI, the one flaw is that you cant load handle ids but u can save them and than load the saved ID.
 
Level 4
Joined
Feb 22, 2012
Messages
74
to the OP

learning hashtables inside and out will solve almost all of the design problems we have with GUI. I started editing before hashtables were in the GUI editor and back then, the only solution was to learn JASS or wait for SC2. I still do not know JASS, but I was in your position once. If you learn how hastables work, you will find very few cases where you cannot make the trigger you want. Just remember the following things:

Hashtables store data like spreadsheets
If you ever want to put a wait in a trigger, it is time to use a hashtable
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
to the OP

learning hashtables inside and out will solve almost all of the design problems we have with GUI. I started editing before hashtables were in the GUI editor and back then, the only solution was to learn JASS or wait for SC2. I still do not know JASS, but I was in your position once. If you learn how hastables work, you will find very few cases where you cannot make the trigger you want. Just remember the following things:

Hashtables store data like spreadsheets
If you ever want to put a wait in a trigger, it is time to use a hashtable

sometimes u dont even need hashtable, just array.
example i store every player every ability level to a single array

(variable[player number*500+ability index])

and with this i can store till 500 ability level for 12 player if each have 1 hero (because we talk about rpg)

same about my socket system (ofc u dont need to fill each index in array, so dont be 8000 value in array, in ability case each hero have 12 ability, this is max 12*12 value )
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
yeah but I think an array will always reserve space for 8192 values, even if you set its size to 1

just a question, its have bigg different if we talk about integer variable?
still dont need function call, not like at hashtable so i guess integer variable array still more shorter and faster than hashtable :p

(if we talk about another arrays then i am not surem example if u do unit group array u must create group manually for each index what u use )
 
Status
Not open for further replies.
Top