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

I'm a trigger-newb, can't figure out the problem with this?

Status
Not open for further replies.
Level 2
Joined
Oct 26, 2014
Messages
13
  • Events
    • Time - Every (Random real number between 15.00 and 25.00) seconds of game time
  • Conditions
  • Actions
    • 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
            • (Current order of BlackSoulRefs[(Integer A)]) Equal to (Order(attack))
          • Then - Actions
            • Set BlackSoulTarget[(Integer A)] = (Random unit from (Units within 900.00 of (Position of BlackSoulRefs[(Integer A)]) matching (((Matching unit) belongs to an enemy of (Owner of BlackSoulRefs[(Integer A)])) Equal to True)))
            • Special Effect - Create a special effect at (Position of BlackSoulRefs[(Integer A)]) using Abilities\Spells\Human\MassTeleport\MassTeleportCaster.mdl
            • Unit - Move BlackSoulRefs[(Integer A)] instantly to (Position of BlackSoulTarget[(Integer A)]), facing (Position of BlackSoulTarget[(Integer A)])
            • Special Effect - Create a special effect at (Position of BlackSoulRefs[(Integer A)]) using Abilities\Spells\Human\MassTeleport\MassTeleportTarget.mdl
            • Unit - Order BlackSoulRefs[(Integer A)] to Attack BlackSoulTarget[(Integer A)]
          • Else - Actions
The basic idea is that the black soul unit selects a random nearby enemy and teleports on top of it. I'll include the 2 triggers that set the unit int the BlackSoulRefs array if the problem may be there:

DemonRefsInit
  • Events
    • Map initialization
    • Conditions
    • Actions
      • Unit Group - Pick every unit in (Units of type Black Soul) and do (Actions)
        • Loop - Actions
          • Set BlackSoulCount = (BlackSoulCount + 1)
          • Set BlackSoulRefs[BlackSoulCount] = (Picked unit)
DemonsAddRefsRun
  • Events
    • Unit - A unit enters (Entire map)
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to Black Soul
    • Actions
      • Set BlackSoulCount = (BlackSoulCount + 1)
      • 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
              • BlackSoulRefs[(Integer A)] Equal to No unit
            • Then - Actions
              • Set BlackSoulRefs[(Integer A)] = (Triggering unit)
              • Skip remaining actions
            • Else - Actions
 
Last edited:
Level 29
Joined
Oct 24, 2012
Messages
6,543
Never use integer A / B. Use a custom integer variable to do your looping.

You also have location leaks and unit group leaks which can make the game laggy and unplayable. This link will help. http://www.hiveworkshop.com/forums/triggers-scripts-269/things-leak-35124/

You have this
  • Set BlackSoulCount = (BlackSoulCount + 1)
But you never use it in anything.

By the way saying there is a problem and not explaining what the problem is / what is happening / what is the expected or desired outcome is impossible for us to know the solution to fix.

You should also look how to make your triggers more efficient / faster and easier to edit. Take a look at my tutorial Things you should know when using triggers / gui. Link is in my sig below.
 
Level 2
Joined
Oct 26, 2014
Messages
13
The problem I run into is that the trigger doesn't cause the black soul that's in combat to select a random target. The outcome I was looking for is that every so often, on a semi-periodic basis, if the black soul unit is actively in combat, it will pick a random nearby enemy and teleport on top of it and begin attacking, thus giving it a chance to ignore melee units altogether and go after a ranged unit, increasing the difficulty of killing it via tanking.

As far as the memory leaks go, I'm asking this because I'm a genuine newb at this stuff, how does the memory leaking of this trigger compare to the memory usage of the array variables needed to keep this where it would fire and work for up to 10 different black soul units?

Last explanation, the BlackSoulCount int is for the purpose of limiting the number of black souls active in gameplay to 10 at any given time. The BlackSoulRefs array is sized to 10, and when one dies, it runs the following trigger:

  • DemonDelRefsRun
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to Black Soul
    • Actions
      • Set BlackSoulCount = (BlackSoulCount - 1)
      • 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
              • BlackSoulRefs[(Integer A)] Equal to (Triggering unit)
            • Then - Actions
              • Set BlackSoulRefs[(Integer A)] = No unit
              • Skip remaining actions
            • Else - Actions
I'll work on fixing the memory leaks and post the new triggers shortly.
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
No memory is leaked when storing arrays. A leak is a piece of memory that can't be destroyed / removed because the reference to that portion of memory was lost.

Never set the array size to more than 1 in the variable editor except for timers / timer dialogs.

To do something like what you are triyng to achieve it is best to use a hashtable. But if it is only 10 units then an array will be ok to use.

If you want to limit the number of units you can do that by setting the training limit for that player to 10 for that unit. That way the player can only have 10 of them at any time. You then do not need to do any triggering for the units.

This action will never be a random time between these.
Every (Random real number between 15.00 and 25.00) seconds of game time

To do a random time period you need to do this.

  • Events
    • Time - Every 1.00 seconds of game time
  • Conditions
  • Actions
    • Set BlackSoulTimeCounter = (BlackSoulTimeCounter + 1)
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • (BlackSoulTimeCounter >= BlackSoulTimer)
      • Then - Actions
        • Set BlackSoulTimer = (Random real number between 15.00 and 25.00)
        • For each unit in BlackSoulUnitGroup Do actions
        • 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
                • (Current order of BlackSoulRefs[(Integer A)]) Equal to (Order(attack))
              • Then - Actions
                • Set BlackSoulTarget[(Integer A)] = (Random unit from (Units within 900.00 of (Position of BlackSoulRefs[(Integer A)]) matching (((Matching unit) belongs to an enemy of (Owner of BlackSoulRefs[(Integer A)])) Equal to True)))
                • Special Effect - Create a special effect at (Position of BlackSoulRefs[(Integer A)]) using Abilities\Spells\Human\MassTeleport\MassTeleportCaster.mdl
                • Unit - Move BlackSoulRefs[(Integer A)] instantly to (Position of BlackSoulTarget[(Integer A)]), facing (Position of BlackSoulTarget[(Integer A)])
                • Special Effect - Create a special effect at (Position of BlackSoulRefs[(Integer A)]) using Abilities\Spells\Human\MassTeleport\MassTeleportTarget.mdl
                • Unit - Order BlackSoulRefs[(Integer A)] to Attack BlackSoulTarget[(Integer A)]
              • Else - Actions
      • Else - Actions
BlackSoulTimer is an integer variable.
BlackSoulTimeCounter is an integer variable.

In the above I have added a timer that will work. If you want this time to be random for all 10 units then change the BlackSoulTimer to an integer array and set it for the unit.

To be more efficient add all the units to a unit group. Then loop through the unit group and check if that unit is in combat. Then move it to desired unit.
 
Level 2
Joined
Oct 26, 2014
Messages
13
Thanks for tips and whatnot so far, here is where I stand with it all at the moment. Eliminated arrays from the code altogether after piecing together in my head a cleaner way to write the triggers where they aren't necessary. This is what I have now, am about to test it out in my test arena.

Here are the 4 triggers related to the black soul unit, please let me know if there is anything left that leaks and how I would fix it. I didn't understand the part in 'Things That Leak' about special effects, so I'm not sure if how I implemented the teleport effect is a leak or not.

  • DemonRefsInit
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set BlackSoulUG = (Units of type Black Soul)
      • Unit Group - Pick every unit in BlackSoulUG and do (Actions)
        • Loop - Actions
          • Set BlackSoulCount = (BlackSoulCount + 1)
      • Custom script: call DestroyGroup(udg_BlackSoulUG)
This just counts number of black soul units at start of game (Added question in edit: Is there a jass function to eliminate this trigger after it runs, rather than just turn it off?)

  • DemonsAddRefsRun
    • Events
      • Unit - A unit enters (Entire map)
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to Black Soul
    • Actions
      • Set BlackSoulCount = (BlackSoulCount + 1)
This just counts new ones

  • DemonDelRefsRun
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to Black Soul
    • Actions
      • Set BlackSoulCount = (BlackSoulCount - 1)
counts dying ones

  • BlackSoulCombat
    • Events
      • Time - Every 20.00 seconds of game time
    • Conditions
    • Actions
      • Set BlackSoulUG = (Units of type Black Soul)
      • Unit Group - Pick every unit in BlackSoulUG and do (Actions)
        • Loop - Actions
          • Set BlackSoul = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Current order of BlackSoul) Equal to (Order(attack))
            • Then - Actions
              • Set TeamBS = (Owner of BlackSoul)
              • Set BlackSoulPos = (Position of BlackSoul)
              • Set BlackSoulTargetPool = (Units within 900.00 of BlackSoulPos matching (((Matching unit) belongs to an enemy of TeamBS) Equal to True))
              • Set BlackSoulTarget = (Random unit from BlackSoulTargetPool)
              • Set BlackSoulTargetPos = (Position of BlackSoulTarget)
              • Special Effect - Create a special effect at BlackSoulPos using Abilities\Spells\Human\MassTeleport\MassTeleportCaster.mdl
              • Unit - Move BlackSoul instantly to BlackSoulTargetPos, facing BlackSoulTargetPos
              • Special Effect - Create a special effect at BlackSoulTargetPos using Abilities\Spells\Human\MassTeleport\MassTeleportTarget.mdl
              • Unit - Order BlackSoul to Attack BlackSoulTarget
              • Custom script: call RemoveLocation(udg_BlackSoulPos)
              • Custom script: call DestroyGroup(udg_BlackSoulTargetPool)
              • Custom script: call RemoveLocation(udg_BlackSoulTargetPos)
            • Else - Actions
      • Custom script: call DestroyGroup(udg_BlackSoulUG)
I removed the usage of integer A/B from all 4 code pieces, and figured out that by using Unit Group variable, I could run a loop on each black soul without the For N Do X loops. Consequently, I was able to delete a bunch of arrays used in other triggers for this map that I knew were written poorly but didn't know how else to do them. (Big thanks!) Also set every location I could perceive into a point variable I could clear with a script action (not sure if RemoveLocation refers to points or just regions, though?)

Also, if I need to clear Unit and Player variables to prevent leaks, I have no idea what jass function to call for that purpose and am having a terrible time trying to find relevant information in the couple of jass manuals I could find. (If you can recommend a JASS tutorial to get me started, especially if it adheres to MUI, I'd appreciate it! I pick up hacking fairly quickly, but would still like to start with the jass basics)
 
Last edited:
Level 29
Joined
Oct 24, 2012
Messages
6,543
There is a GUI action that allows you to destroy a trigger.

RemoveLocation is for points.

The one for regions you do not need to use.

You have to destroy your special effects. For most of them you can destroy them immediately after creating them.

Set unitVariable = No unit.
For players it is ok to ignore the setting them to null.

This isn't hacking lol. This is scripting / programming.

If you are interested in learning jass I have a tutorial in my sig for that. It shows you how to learn jass through the use of GUI.
 
Level 2
Joined
Oct 26, 2014
Messages
13
So, I added a floating text debug message to see if this was even meeting the condition for the ITF, as such:

  • BlackSoulCombat Backup
    • Events
      • Time - Every 10.00 seconds of game time
    • Conditions
    • Actions
      • Set BlackSoulUG = (Units of type Black Soul)
      • Unit Group - Pick every unit in BlackSoulUG and do (Actions)
        • Loop - Actions
          • Set BlackSoul = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Current order of BlackSoul) Equal to (Order(attack))
            • Then - Actions
              • Set TeamBS = (Owner of BlackSoul)
              • Set BlackSoulPos = (Position of BlackSoul)
              • Floating Text - Create floating text that reads Fired at BlackSoulPos with Z offset 50.00, using font size 10.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
              • Set BlackSoulTargetPool = (Units within 900.00 of BlackSoulPos matching (((Matching unit) belongs to an enemy of TeamBS) Equal to True))
              • Set BlackSoulTarget = (Random unit from BlackSoulTargetPool)
              • Set BlackSoulTargetPos = (Position of BlackSoulTarget)
              • Special Effect - Create a special effect at BlackSoulPos using Abilities\Spells\Human\MassTeleport\MassTeleportCaster.mdl
              • Special Effect - Destroy (Last created special effect)
              • Unit - Move BlackSoul instantly to BlackSoulTargetPos, facing BlackSoulTargetPos
              • Special Effect - Create a special effect at BlackSoulTargetPos using Abilities\Spells\Human\MassTeleport\MassTeleportTarget.mdl
              • Special Effect - Destroy (Last created special effect)
              • Unit - Order BlackSoul to Attack BlackSoulTarget
              • Custom script: call RemoveLocation(udg_BlackSoulPos)
              • Custom script: call DestroyGroup(udg_BlackSoulTargetPool)
              • Custom script: call RemoveLocation(udg_BlackSoulTargetPos)
            • Else - Actions
      • Custom script: call DestroyGroup(udg_BlackSoulUG)
The result is that I'm getting no period 'Fired' and no other actions, so I'm thinking the problem is in the If condition. Right now I'm testing against computer AI. Is it the case that a unit that auto-acquires and attacks a target doesn't have the current order of attack?

I suspect so, and am going to try the following: A separate countdown trigger that is turned off at 0, then reset to a random between 6 and 20, and turned back on in the DemonCombat trigger (I'm keeping this generic to the entire unit type so that their random target choice is done in tandem).

Modify the DemonCombat trigger as follows:
Change event to Generic Unit - Unit is Attacked
Add 2 conditions: 1 Triggering Unit Type = Black Soul
2 Timer = 0

I'll report how this works in just a minute.
 
Level 2
Joined
Oct 26, 2014
Messages
13
Well, I have it working now! Current iteration is such:

  • BlackSoulTimer
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • BackSoulTimer Greater than 0
        • Then - Actions
          • Set BackSoulTimer = (BackSoulTimer - 1)
        • Else - Actions
          • Trigger - Turn off (This trigger)
          • Game - Display to (All players) the text: BlackSoulCombat Tur...
          • Trigger - Turn on BlackSoulCombat <gen>
Basic timer, works and displays completion message in-game.

  • BlackSoulCombat
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • BackSoulTimer Equal to 0
      • (Unit-type of (Attacked unit)) Equal to Black Soul
    • Actions
      • Trigger - Turn off (This trigger)
      • Set BlackSoulUG = (Units of type Black Soul)
      • Unit Group - Pick every unit in BlackSoulUG and do (Actions)
        • Loop - Actions
          • Game - Display to (All players) the text: Fire
          • Set BlackSoul = (Picked unit)
          • Set TeamBS = (Owner of BlackSoul)
          • Set BlackSoulPos = (Position of BlackSoul)
          • Set BlackSoulTargetPool = (Units within 900.00 of BlackSoulPos matching (((Matching unit) belongs to an enemy of TeamBS) Equal to True))
          • Set BlackSoulTarget = (Random unit from BlackSoulTargetPool)
          • Set BlackSoulTargetPos = (Position of BlackSoulTarget)
          • Special Effect - Create a special effect at BlackSoulPos using Abilities\Spells\Human\MassTeleport\MassTeleportCaster.mdl
          • Special Effect - Destroy (Last created special effect)
          • Unit - Move BlackSoul instantly to BlackSoulTargetPos, facing BlackSoulTargetPos
          • Special Effect - Create a special effect at BlackSoulTargetPos using Abilities\Spells\Human\MassTeleport\MassTeleportTarget.mdl
          • Special Effect - Destroy (Last created special effect)
          • Unit - Order BlackSoul to Attack BlackSoulTarget
          • Custom script: call RemoveLocation(udg_BlackSoulPos)
          • Custom script: call DestroyGroup(udg_BlackSoulTargetPool)
          • Custom script: call RemoveLocation(udg_BlackSoulTargetPos)
      • Set BackSoulTimer = (Random integer number between 6 and 15)
      • Trigger - Turn on BlackSoulTimer <gen>
      • Custom script: call DestroyGroup(udg_BlackSoulUG)
Displays the fire message in-game and operates nicely. About to test if it works with multiple black souls. Not needed for the current map I'm doing, but is of importance in the follow-up.

Test results: This worked great! deathismyfriend, thank you for your help and for the recommended tutorials for GUI and jass. It's running clean, and this black soul unit went from being a weakling annoyance to a fun little monster to fight. :D
 
Last edited:
Status
Not open for further replies.
Top