• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

Run actions when units try to leave specific area. Can you help me about this annoying system?

Status
Not open for further replies.
Level 17
Joined
Jun 2, 2009
Messages
1,148
One of my players requested skill from one of the moba games. I have created it but still not works properly.

Hero creates spikes at targeted area. Units trying to get in or out stuns for x seconds.
When units contacts with spikes (check the attachment) i want to run actions for any unit who contacted.

How can i make it properly? I believe i have messed up. It works but not properly. I have messed up because of changing system many times.
Additionally i am sharing map file if you want. But it is 1.26 version.

  • Veigar E Cast Copy
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Thorns // Dryad
    • Actions
      • Set TempPointVeigarE = (Target point of ability being cast)
      • Set Veigar_E_Caster = (Casting unit)
      • Set VeigarE_Prison = 0.00
      • Set DENEME = ((Target point of ability being cast) offset by 115.00 towards 0.00 degrees)
      • Set DENEME2 = ((Target point of ability being cast) offset by 185.00 towards 0.00 degrees)
      • For each (Integer A) from 1 to 12, do (Actions)
        • Loop - Actions
          • Special Effect - Create a special effect at (TempPointVeigarE offset by 250.00 towards VeigarE_Prison degrees) using Abilities\Spells\Orc\SpikeBarrier\SpikeBarrier.mdl
          • Unit - Create 1 DUMMY [JFA] for (Owner of Hero_Veigar) at (TempPointVeigarE offset by 250.00 towards VeigarE_Prison degrees) facing Default building facing degrees
          • Set VeigarEffect = (VeigarEffect + 1)
          • Set Veigar_Dummy_E[VeigarEffect] = (Last created unit)
          • Set VeigarEffect2[VeigarEffect] = (Last created special effect)
          • Set VeigarE_Prison = (VeigarE_Prison + 30.00)
      • Wait 1.00 seconds
      • Trigger - Turn on Veigar E Stun Copy <gen>
      • Wait 4.00 seconds
      • For each (Integer A) from 1 to 12, do (Actions)
        • Loop - Actions
          • Special Effect - Destroy VeigarEffect2[(Integer A)]
          • Unit - Kill Veigar_Dummy_E[(Integer A)]
          • Unit - Remove Veigar_Dummy_E[(Integer A)] from the game
      • Set VeigarEffect = 0
      • Custom script: call RemoveLocation(udg_TempPointVeigarE)
      • Trigger - Turn off Veigar E Stun Copy <gen>
  • Veigar E Stun Copy
    • Events
      • Time - Every 0.15 seconds of game time
    • Conditions
    • Actions
      • For each (Integer A) from 1 to 12, do (Actions)
        • Loop - Actions
          • Unit Group - Pick every unit in (Units of type DUMMY [JFA]) and do (Actions)
            • Loop - Actions
              • For each (Integer A) from 1 to 12, do (Actions)
                • Loop - Actions
                  • Unit Group - Pick every unit in (Units within 75.00 of ((Position of (Picked unit)) offset by 0.00 towards 0.00 degrees)) and do (Actions)
                    • Loop - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • ((Picked unit) is A structure) Equal to False
                          • ((Picked unit) is Mechanical) Equal to False
                          • ((Picked unit) is alive) Equal to True
                          • ((Picked unit) belongs to an enemy of (Owner of Veigar_E_Caster)) Equal to True
                        • Then - Actions
                          • Unit - Order Veigar_Dummy_E[VeigarEffect] to Human Mountain King - Storm Bolt (Picked unit)
                        • Else - Actions
I know probably it is not proper way to do that. It is the first time i am trying to create system like this and i think you will solve this with "unit comes within x range" thing.
 

Attachments

  • region.png
    region.png
    770 KB · Views: 6
  • veigartest.w3x
    127.5 KB · Views: 0
Level 25
Joined
Sep 26, 2009
Messages
2,387
That spell is not MUI - it will not work for multiple casters. I don't know if that is fine by you or not (perhaps the spell can be cast by a single hero in the entire game).

Given that your 'Veigar E Cast Copy' has the following actions:
  • Veigar E Cast Copy
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Thorns // Dryad
    • Actions
      • Set TempPointVeigarE = (Target point of ability being cast)
      • ...
      • Wait 1.00 seconds
      • ...
      • Wait 4.00 seconds
      • ...
      • Custom script: call RemoveLocation(udg_TempPointVeigarE)
Then you cannot consider TempPointVeigarE to be temporal variable, as it stores the location for ~5 seconds. During that time, the value in this variable may be overwritten, causing memory leak.
Instead of the creating the dummies and special effects then waiting 5 seconds and then killing dummies and removing the special effect, you could bind the special effect to a dummy via hashtable and give each dummy timed life.
Then when the dummy dies, load the special effect from hashtable and destroy it.

The 'Veigar E Stun Copy' is completely wrong.
Let's just assume that a single instance of the spell is active. That means the trigger 'Veigar E Cast Copy' creates 12 DUMMY [JFA] units.
What does your 'Veigar E Stun Copy' do now?
  • Loop 12 times
    • For each loop iteration, pick every DUMMY [JFA] in the game (= creates a group of 12 units)
      • For each picked DUMMY [JFA] loop 12 times
        • For each inner loop iteration, pick all enemies of Veigar_E_Caster nearby picked DUMMY [JFA]
          • For each such picked enemy, order Veigar_Dummy_E[12] to stun the enemy
Assuming all other issues have been resolved, a single DUMMY [JFA] would hit an enemy 144 times

Also, your loop trigger has memory leaks - it leaks points and unit groups.

Finally, structuring your loops like this will not work correctly:
  • For each (Integer A) from 1 to 12, do (Actions) //OUTER loop using (Integer A)
    • Loop - Actions
      • Unit Group - ...
        • Loop - Actions
          • For each (Integer A) from 1 to 12, do (Actions) //INNER loop referencing same (Integer A)
            • Loop - Actions
              • ...
The inner and outer loop both use (Integer A), which is just another global variable.
So the loop execution looks as follows:
  1. Outer loop starts, (Integer A) = 1
  2. Inner loop starts, rewriting value of (Integer A) to 1 (to same value)
  3. Inner loop iterates over and over, increasing the value of (Integer A), until (Integer A) reaches value 12, then the inner loop ends
  4. Back in Outer loop, the (Integer A) still has value = 12 as assigned from the inner loop, because (Integer A) is global variable
  5. The outer loop breaks, because the max value for outer loop is 12 and at that moment the (Integer A) is 12 as well
Effectively, the outer loop executes a single time and the inner loop executes 12 times.
To fix this, you would need to change the inner loop to use (Integer B), or even better, use a custom integer variable.
 
Level 17
Joined
Jun 2, 2009
Messages
1,148
It is far advanced to me but one of my friends created system like this.
It works well but running the trigger for every 0.02 seconds can causes any issues? In other words is it optimized?

  • Events
    • Time - Every 0.02 seconds of game time
  • Conditions
  • Actions
    • Set DyradEIntegerA = (Integer A)
    • Set DyradEIntegerAValue = 1
    • For each (Integer DyradEIntegerAValue) from DyradEIntegerAValue to 1, do (Actions)
      • Loop - Actions
        • Unit Group - Pick every unit in (Units of type DUMMY [JFA]) and do (Actions)
          • Loop - Actions
            • For each (Integer B) from 1 to 1, do (Actions)
              • Loop - Actions
                • Unit Group - Pick every unit in (Units within 75.00 of ((Position of (Picked unit)) offset by 0.00 towards 0.00 degrees)) and do (Actions)
                  • Loop - Actions
                    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                      • If - Conditions
                        • ((Picked unit) is A structure) Equal to False
                        • ((Picked unit) is Mechanical) Equal to False
                        • ((Picked unit) is alive) Equal to True
                        • ((Picked unit) belongs to an enemy of (Owner of Veigar_E_Caster)) Equal to True
                      • Then - Actions
                        • Unit - Order Veigar_Dummy_E[VeigarEffect] to Human Mountain King - Storm Bolt (Picked unit)
                      • Else - Actions
 
Level 25
Joined
Sep 26, 2009
Messages
2,387
The tutorial I posted is not advanced, it's for beginners.
I understand that you may not be good in triggering, but what you should do is make a new map and try to create the triggers in the tutorial I linked and see what happens.
A good idea is to place debug messages inside the loops to print the loop integer, for example let's take the outer-most loop in the trigger you posted and add a debug message printing the value of DyradEIntegerAValue:
  • For each (Integer DyradEIntegerAValue) from DyradEIntegerAValue to 1, do (Actions)
    • Loop - Actions
      • Game - Display to (All players) the text: (Outer-most loop: + (String(DyradEIntegerAValue)))
      • //rest of the loop actions
How many messages does it print? I can tell right away from the trigger that it will just print 'Outer-most loop: 1', but from how the triggers looked in your first post in this thread, I think you would want this loop to print more messages.

Let's look further, at the inner loop:
  • For each (Integer B) from 1 to 1, do (Actions)
    • Loop - Actions
      • ...
As the tutorial I posted stated, in loop you specify 3 numbers (either directly values or as variables):
  • start-value (in your loop above, this is the '1' on the left)
  • end-value (in your loop above, this is the '1' on the right)
  • counter (in your loop, this is the (Integer B) variable)
Further, the tutorial says the following:
tutorial said:
... and with using our 3 numbers the loop works in following steps:
  1. Counter starts with value of start-value
  2. Check if counter is greater than the end-value. If yes, the loop will directly exit, if not, proceed to step 3
  3. Perform all actions inside the loop ( loop run )
  4. Increase Counter by +1
  5. Go back to step 2
So in for the loop above, (Integer B) will start with start-value, which is in your case '1'
  • The loop checks that the counter (Integer B) is not greater than the end-value (in your case, '1'). So it checks if 1 is greater than 1, which it is not, so it continues with next step
  • Next, the loop body is executed
  • Then the counter (Integer B) is increased by 1, so (Integer B) value is now '2'
  • The loop now checks again if counter (Integer B) is not greater than end-value ('1'). So it checks if 2 is greater than 1, which it is, so the loop ends.
So essentially, your loop executes the loop body only a single time, meaning that the loop is entirely useless.

Same thing with this:
  • Set DyradEIntegerAValue = 1
  • For each (Integer DyradEIntegerAValue) from DyradEIntegerAValue to 1, do (Actions)
    • Loop - Actions
      • ...
As the DyradEIntegerAValue value is 1, you can think of the loop as being 'For each (Integer xx) from 1 to 1, do (Actions)' which again defeats the purpose of the loop and makes this loop entirely useless as well.
Also, in your trigger, you use this 'DyradEIntegerAValue' as both the [counter] and [start-value], which may end up in unexpected behavior for you.

Finally, what did you want to achieve with this:
  • Set DyradEIntegerA = (Integer A)
When this is used outside of loop?
 
Level 17
Joined
Jun 2, 2009
Messages
1,148
Hello dear @Nichilus sorry for late reply. Now it is time to add this system into my map but my last attempt we're failed.
I made changes and here it is the map file. It is not working.

What i need: Units gets stunned while trying to leave OR enter region.
 

Attachments

  • ThornsAbility.w3x
    18.8 KB · Views: 4
Status
Not open for further replies.
Top