[Solved] These triggers are causing permanent lag.

Status
Not open for further replies.
Hey there.
I have been struggling for 3 days to find the cause of the lag that this one spell is making. It works like Stampede, but is more organised. It summons 5 rows of Lightbearers who will move a fixed distance towards the target location, damaging the first enemy they collide with.

However, this trigger is causing a permanent drop of about 20 fps on skill usage. The lag stacks as well. I figured it was maybe because of a leak, but I have checked every nook and cranny for a faulty leak and I was unable to locate it.
I'm hoping someone else could find what's wrong with these triggers.

  • R Holy Crusade Start
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Holy Crusade
    • Actions
      • Set Justicar_TriggeringUnit = (Triggering unit)
      • Set CustomValue = (Custom value of Justicar_TriggeringUnit)
      • Set Justicar_Points[1] = (Position of Justicar_TriggeringUnit)
      • Set Justicar_Points[2] = (Target point of ability being cast)
      • Set Justicar_R_RemainingDuration[CustomValue] = 8
      • Set PlayerIndex = (Player number of (Owner of Justicar_TriggeringUnit))
      • Set TempInteger = Faith_Count[PlayerIndex]
      • Set Justicar_R_FaithCount[PlayerIndex] = TempInteger
      • Set Justicar_R_IsCastingBool[CustomValue] = True
      • Set Justicar_R_Angle[CustomValue] = (Angle from Justicar_Points[1] to Justicar_Points[2])
      • -------- ----------------------------------------------------------------------------------------------- --------
      • Unit - Create 1 Spell - Holy Crusade Delay for (Owner of Justicar_TriggeringUnit) at Justicar_Points[1] facing Justicar_Points[1]
      • Set CustomValue2 = (Custom value of (Last created unit))
      • Set Justicar_R_CasterTarget[CustomValue2] = Justicar_TriggeringUnit
      • Unit - Add a 2.00 second Generic expiration timer to (Last created unit)
      • -------- ----------------------------------------------------------------------------------------------- --------
      • Custom script: set udg_TempReal = GetLocationZ(udg_Justicar_Points[1])
      • Special Effect - Create a special effect at Justicar_Points[1] using HolyCrusade_Line.mdx
      • Set Justicar_R_LineSFX[CustomValue] = (Last created special effect)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • TempReal Less than or equal to 65.00
        • Then - Actions
          • Special Effect - Set Position - Z of (Last created special effect) to (TempReal x 2.30)
        • Else - Actions
          • Special Effect - Set Position - Z of (Last created special effect) to (TempReal x 1.30)
      • Special Effect - Set Orientation of (Last created special effect) to yaw: (Radians((Angle from Justicar_Points[1] to Justicar_Points[2]))), pitch: 0.00, roll: 0.00
      • -------- ----------------------------------------------------------------------------------------------- --------
      • Set Justicar_R_LoopFixedPoint = (Justicar_Points[1] offset by 50.00 towards Justicar_R_Angle[CustomValue] degrees)
      • Set Justicar_R_LoopPoint0 = (Justicar_R_LoopFixedPoint offset by 1300.00 towards Justicar_R_Angle[CustomValue] degrees)
      • Unit - Create 1 Lightbearer for (Owner of Justicar_TriggeringUnit) at Justicar_R_LoopFixedPoint facing Justicar_R_LoopPoint0
      • Unit - Add a ((Distance between Justicar_R_LoopFixedPoint and Justicar_R_LoopPoint0) / 230.00) second Generic expiration timer to (Last created unit)
      • Special Effect - Create a special effect at Justicar_R_LoopFixedPoint using Abilities\Spells\Human\HolyBolt\HolyBoltSpecialArt.mdl
      • Special Effect - Destroy (Last created special effect)
      • Custom script: call RemoveLocation(udg_Justicar_R_LoopPoint0)
      • -------- ----------------------------------------------------------------------------------------------- --------
      • For each (Integer TempInteger) from 1 to 2, do (Actions)
        • Loop - Actions
          • Set Justicar_R_LoopPoint1_1 = (Justicar_R_LoopFixedPoint offset by (140.00 x (Real(TempInteger))) towards (Justicar_R_Angle[CustomValue] - 90.00) degrees)
          • Set Justicar_R_LoopPoint1_2 = (Justicar_R_LoopPoint1_1 offset by 1300.00 towards Justicar_R_Angle[CustomValue] degrees)
          • Unit - Create 1 Lightbearer for (Owner of Justicar_TriggeringUnit) at Justicar_R_LoopPoint1_1 facing Justicar_R_LoopPoint1_2
          • Unit - Add a ((Distance between Justicar_R_LoopPoint1_1 and Justicar_R_LoopPoint1_2) / 230.00) second Generic expiration timer to (Last created unit)
          • Special Effect - Create a special effect at Justicar_R_LoopPoint1_1 using Abilities\Spells\Human\HolyBolt\HolyBoltSpecialArt.mdl
          • Special Effect - Destroy (Last created special effect)
          • Custom script: call RemoveLocation(udg_Justicar_R_LoopPoint1_1)
          • Custom script: call RemoveLocation(udg_Justicar_R_LoopPoint1_2)
          • -------- ----------------------------------------------------------------------------------------------- --------
          • Set Justicar_R_LoopPoint2_1 = (Justicar_R_LoopFixedPoint offset by (140.00 x (Real(TempInteger))) towards (Justicar_R_Angle[CustomValue] + 90.00) degrees)
          • Set Justicar_R_LoopPoint2_2 = (Justicar_R_LoopPoint2_1 offset by 1300.00 towards Justicar_R_Angle[CustomValue] degrees)
          • Unit - Create 1 Lightbearer for (Owner of Justicar_TriggeringUnit) at Justicar_R_LoopPoint2_1 facing Justicar_R_LoopPoint2_2
          • Unit - Add a ((Distance between Justicar_R_LoopPoint2_1 and Justicar_R_LoopPoint2_2) / 230.00) second Generic expiration timer to (Last created unit)
          • Special Effect - Create a special effect at Justicar_R_LoopPoint2_1 using Abilities\Spells\Human\HolyBolt\HolyBoltSpecialArt.mdl
          • Special Effect - Destroy (Last created special effect)
          • Custom script: call RemoveLocation(udg_Justicar_R_LoopPoint2_1)
          • Custom script: call RemoveLocation(udg_Justicar_R_LoopPoint2_2)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (R Holy Crusade March <gen> is on) Equal to False
        • Then - Actions
          • Trigger - Turn on R Holy Crusade March <gen>
        • Else - Actions
      • Sound - Play HolyCrusade1 <gen> at 100.00% volume, attached to Justicar_TriggeringUnit
      • Sound - Play HolyCrusade2 <gen> at 100.00% volume, attached to Justicar_TriggeringUnit
      • -------- ================================= FAITH ================================= --------
      • Set TempInteger = (Player number of (Owner of Justicar_TriggeringUnit))
      • Set PlayerIndex = (100 x TempInteger)
      • Set Faith_Count[TempInteger] = 0
      • Set MyResourceFieldValue[(PlayerIndex + 1)] = ((String(Faith_Count[TempInteger])) + %)
      • Player - Set the current research level of Seraphic Union Faith Buff to Faith_Count[TempInteger] for (Owner of Justicar_TriggeringUnit)
      • -------- ================================= FAITH ================================= --------
      • Custom script: call RemoveLocation(udg_Justicar_Points[1])
      • Custom script: call RemoveLocation(udg_Justicar_Points[2])
      • Custom script: call RemoveLocation(udg_Justicar_R_LoopFixedPoint)
  • R Holy Crusade Spawn Ticks
    • Events
      • Game - DeathEvent becomes Equal to 2.00
    • Conditions
      • (Unit-type of UDexUnits[UDex]) Equal to Spell - Holy Crusade Delay
    • Actions
      • Set TempUnit = UDexUnits[UDex]
      • Set CustomValue2 = (Custom value of TempUnit)
      • Set Justicar_TriggeringUnit = Justicar_R_CasterTarget[CustomValue2]
      • Set CustomValue = (Custom value of Justicar_TriggeringUnit)
      • Set Justicar_Points[1] = (Position of Justicar_TriggeringUnit)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Justicar_R_IsCastingBool[CustomValue] Equal to True
          • Justicar_R_RemainingDuration[CustomValue] Greater than 0
        • Then - Actions
          • Unit - Add a 2.00 second Generic expiration timer to TempUnit
          • Set Justicar_R_RemainingDuration[CustomValue] = (Justicar_R_RemainingDuration[CustomValue] - 2)
          • -------- ----------------------------------------------------------------------------------------------- --------
          • Set Justicar_R_LoopFixedPoint = (Justicar_Points[1] offset by 50.00 towards Justicar_R_Angle[CustomValue] degrees)
          • Set Justicar_R_LoopPoint0 = (Justicar_R_LoopFixedPoint offset by 1300.00 towards Justicar_R_Angle[CustomValue] degrees)
          • Unit - Create 1 Lightbearer for (Owner of Justicar_TriggeringUnit) at Justicar_R_LoopFixedPoint facing Justicar_R_LoopPoint0
          • Unit - Add a ((Distance between Justicar_R_LoopFixedPoint and Justicar_R_LoopPoint0) / 230.00) second Generic expiration timer to (Last created unit)
          • Special Effect - Create a special effect at Justicar_R_LoopFixedPoint using Abilities\Spells\Human\HolyBolt\HolyBoltSpecialArt.mdl
          • Special Effect - Destroy (Last created special effect)
          • Custom script: call RemoveLocation(udg_Justicar_R_LoopPoint0)
          • -------- ----------------------------------------------------------------------------------------------- --------
          • For each (Integer TempInteger) from 1 to 2, do (Actions)
            • Loop - Actions
              • Set Justicar_R_LoopPoint1_1 = (Justicar_R_LoopFixedPoint offset by (140.00 x (Real(TempInteger))) towards (Justicar_R_Angle[CustomValue] - 90.00) degrees)
              • Set Justicar_R_LoopPoint1_2 = (Justicar_R_LoopPoint1_1 offset by 1300.00 towards Justicar_R_Angle[CustomValue] degrees)
              • Unit - Create 1 Lightbearer for (Owner of Justicar_TriggeringUnit) at Justicar_R_LoopPoint1_1 facing Justicar_R_LoopPoint1_2
              • Unit - Add a ((Distance between Justicar_R_LoopPoint1_1 and Justicar_R_LoopPoint1_2) / 230.00) second Generic expiration timer to (Last created unit)
              • Special Effect - Create a special effect at Justicar_R_LoopPoint1_1 using Abilities\Spells\Human\HolyBolt\HolyBoltSpecialArt.mdl
              • Special Effect - Destroy (Last created special effect)
              • Custom script: call RemoveLocation(udg_Justicar_R_LoopPoint1_1)
              • Custom script: call RemoveLocation(udg_Justicar_R_LoopPoint1_2)
              • -------- ----------------------------------------------------------------------------------------------- --------
              • Set Justicar_R_LoopPoint2_1 = (Justicar_R_LoopFixedPoint offset by (140.00 x (Real(TempInteger))) towards (Justicar_R_Angle[CustomValue] + 90.00) degrees)
              • Set Justicar_R_LoopPoint2_2 = (Justicar_R_LoopPoint2_1 offset by 1300.00 towards Justicar_R_Angle[CustomValue] degrees)
              • Unit - Create 1 Lightbearer for (Owner of Justicar_TriggeringUnit) at Justicar_R_LoopPoint2_1 facing Justicar_R_LoopPoint2_2
              • Unit - Add a ((Distance between Justicar_R_LoopPoint2_1 and Justicar_R_LoopPoint2_2) / 230.00) second Generic expiration timer to (Last created unit)
              • Special Effect - Create a special effect at Justicar_R_LoopPoint2_1 using Abilities\Spells\Human\HolyBolt\HolyBoltSpecialArt.mdl
              • Special Effect - Destroy (Last created special effect)
              • Custom script: call RemoveLocation(udg_Justicar_R_LoopPoint2_1)
              • Custom script: call RemoveLocation(udg_Justicar_R_LoopPoint2_2)
          • Custom script: call RemoveLocation(udg_Justicar_R_LoopFixedPoint)
        • Else - Actions
          • Set Justicar_R_RemainingDuration[CustomValue] = 0
          • Unit - Remove Dummy - Resurrect As Delay from TempUnit
          • Unit - Add a 0.01 second Generic expiration timer to TempUnit
          • Special Effect - Destroy Justicar_R_LineSFX[CustomValue]
      • Custom script: call RemoveLocation(udg_Justicar_Points[1])
  • R Holy Crusade March
    • Events
      • Time - Every 0.02 seconds of game time
    • Conditions
    • Actions
      • Set Justicar_R_LightbearerGroup = (Units of type Lightbearer)
      • Unit Group - Pick every unit in Justicar_R_LightbearerGroup and do (Actions)
        • Loop - Actions
          • Set Justicar_TriggeringUnit = (Picked unit)
          • Set Justicar_Points[1] = (Position of Justicar_TriggeringUnit)
          • Set Justicar_R_MovePoint = (Justicar_Points[1] offset by 4.30 towards (Facing of Justicar_TriggeringUnit) degrees)
          • Set PlayerIndex = (Player number of (Owner of Justicar_TriggeringUnit))
          • Set TempReal = ((Real(Justicar_R_FaithCount[PlayerIndex])) + 25.00)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Justicar_TriggeringUnit is alive) Equal to True
            • Then - Actions
              • Unit - Move Justicar_TriggeringUnit instantly to Justicar_R_MovePoint, facing (Facing of Justicar_TriggeringUnit) degrees
              • Set Justicar_R_DamageGroup = (Units within 128.00 of Justicar_R_MovePoint)
              • Unit Group - Pick every unit in Justicar_R_DamageGroup and do (Actions)
                • Loop - Actions
                  • Set Justicar_Targets = (Picked unit)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Justicar_Targets is A structure) Equal to False
                      • (Justicar_Targets is A flying unit) Equal to False
                      • (Justicar_Targets is alive) Equal to True
                      • (Justicar_Targets belongs to an enemy of (Owner of Justicar_TriggeringUnit)) Equal to True
                    • Then - Actions
                      • Unit - Cause Justicar_TriggeringUnit to damage Justicar_Targets, dealing TempReal damage of attack type Spells and damage type Divine
                    • Else - Actions
              • Custom script: call DestroyGroup(udg_Justicar_R_DamageGroup)
            • Else - Actions
          • Custom script: call RemoveLocation(udg_Justicar_Points[1])
          • Custom script: call RemoveLocation(udg_Justicar_R_MovePoint)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in Justicar_R_LightbearerGroup) Equal to 0
        • Then - Actions
          • Trigger - Turn off (This trigger)
        • Else - Actions
      • Custom script: call DestroyGroup(udg_Justicar_R_LightbearerGroup)
At the R Holy Crusade Spawn Tick, I used Bribe's Unit Event system for an accurate spawn timing. Every time the R - Holy Crusade Delay dummy resurrects, the trigger is fired to summon another 5 rows of Lightbearers.

Thanks in advanced.
 
Level 14
Joined
Feb 7, 2020
Messages
392
That's a complex trigger, will take some time to look through. Here are my first thoughts on things to check off to get the silly stuff out of the way:
- how big is the sound file? does disabling it affect anything?
- does disabling the research step affect anything?
- is the unit event system the latest version? I know anything listening for variable updates can have recursion issues (does disabling that death listener trigger in a way that the spell still runs remove the lag?)
- have you done the obvious thing of adding a debug message to the timer and death event triggers to make sure they are not running erroneously?
 
That's a complex trigger, will take some time to look through. Here are my first thoughts on things to check off to get the silly stuff out of the way:
- how big is the sound file? does disabling it affect anything?
- does disabling the research step affect anything?
- is the unit event system the latest version? I know anything listening for variable updates can have recursion issues (does disabling that death listener trigger in a way that the spell still runs remove the lag?)
- have you done the obvious thing of adding a debug message to the timer and death event triggers to make sure they are not running erroneously?

Alright then. Thanks for taking your time into checking this mess out. Now, your questions:

- They are just the vanilla Resurrect and Mass Teleport sound files with altered pitch. The size wouldn't be any different than the original.
- If you mean the March trigger, yes. That trigger is causing the most lag. I have disabled each trigger to find out the which one is the faultiest, and the March trigger is the one making the most lag when activated.
- Yeap. Latest version. I'm not really sure which one you're referring to as "the death listener".
- Yes. Spawn Tick trigger generates a debug message every 2 seconds, which is accurate. The same goes for the March trigger every 0.02 seconds.
 
Level 14
Joined
Feb 7, 2020
Messages
392
Alright, I'm with you now on there being a lot to dig through.

I have some suggestions on things that would also be optimal but may also help with the lag:

1) you could try to convert the .02 timer to a .03 timer and adjust the spell math to match (there are old threads worthy of popcorn reads with hive nerds duking it out over efficiency and bugs that can occur such as negative values Efficiency battle (every 0.01 of gametime vs timers); as far as I know, JASS is still calculated on a 1/32 scale even with Reforged so anything faster than that could probably have unintended effects) [edit 3/30/20: want to clarify for any future readers that this would apply to Lua maps as well]

2) in your R Holy Crusade March trigger, I would wrap the group being empty check around the rest of the code:

  • R Holy Crusade March
  • Events
    • Time - Every 0.02 seconds of game time
  • Conditions
  • Actions
    • Set Justicar_R_LightbearerGroup = (Units of type Lightbearer)
    • If <not empty> goes here
      • Unit Group - Pick every unit in Justicar_R_LightbearerGroup and do (Actions)
        • Loop - Actions
        • Set Justicar_TriggeringUnit = (Picked unit)
    • else
      • <turn off goes here>
  • (...)
I've found that the game will hang if you try to enumerate over things that are null/nil with certain GUI functions (it waits for a timeout somewhere); so this would be a safety check.

3) In recent research around unit groups in my own bug squashing, I've learned that using any GUI group builders that use type id are a big no-no and highly inefficient (you can see the code here GetUnitsOfTypeIdAll which is quite taxing)

  • Set Justicar_R_LightbearerGroup = (Units of type Lightbearer)
I would use another method to cycle units into the group (add last created unit, search playable map area for units owned by player X and manually insert based on type, etc.)
 
Last edited:
Alright, I'm with you now on there being a lot to dig through.

I have some suggestions on things that would also be optimal but may also help with the lag:

1) you could try to convert the .02 timer to a .03 timer and adjust the spell math to match (it looks like your map is JASS, and there are old threads worthy of popcorn reads with hive nerds duking it out over efficiency and bugs that can occur such as negative values Efficiency battle (every 0.01 of gametime vs timers); as far as I know, JASS is still calculated on a 1/32 scale even with Reforged so anything faster than that could probably have unintended effects)

2) in your R Holy Crusade March trigger, I would wrap the group being empty check around the rest of the code:

  • R Holy Crusade March
  • Events
    • Time - Every 0.02 seconds of game time
  • Conditions
  • Actions
    • Set Justicar_R_LightbearerGroup = (Units of type Lightbearer)
    • If <not empty> goes here
      • Unit Group - Pick every unit in Justicar_R_LightbearerGroup and do (Actions)
        • Loop - Actions
        • Set Justicar_TriggeringUnit = (Picked unit)
    • else
      • <turn off goes here>
  • (...)
I've found that the game will hang if you try to enumerate over things that are null/nil with certain GUI functions (it waits for a timeout somewhere); so this would be a safety check.

3) In recent research around unit groups in my own bug squashing, I've learned that using any GUI group builders that use type id are a big no-no and highly inefficient (you can see the code here GetUnitsOfTypeIdAll which is quite taxing)

  • Set Justicar_R_LightbearerGroup = (Units of type Lightbearer)
I would use another method to cycle units into the group (add last created unit, search playable map area for units owned by player X and manually insert based on type, etc.)

That's good to hear, because this spell is making me pull out every inch of my hair.

I will check these out as soon as I can. They seem like they would work.
Although if I would avoid using Get Unit Type, what would be the replacement? Lightbearers are locust units, which can't normally be added into unit groups.
 
Last edited:
Level 14
Joined
Feb 7, 2020
Messages
392
That's good to hear, because this spell is making me pull out every inch of my hair.

I will check these out as soon as I can. They seem like they would work.
Although if I would avoid using Get Unit Type, what would be the replacement? Lightbearers are locust units, which can't normally be added into unit groups.
Although beforehand,

I believe you could get around this by adding the unit to a group upon creation and then adding locust to it with a custom script.

call UnitAddAbility(udg_YourUnitVarHere, 'Aloc')

(edit: I'd have to test this, but I think you can add Locust units to groups whenever you want as long as you can reference them; it's picking units in a radius that doesn't work AFAIK)
 
I believe you could get around this by adding the unit to a group upon creation and then adding locust to it with a custom script.

call UnitAddAbility(udg_YourUnitVarHere, 'Aloc')

(edit: I'd have to test this, but I think you can add Locust units to groups whenever you want as long as you can reference them; it's picking units in a radius that doesn't work AFAIK)

Neat trick. Tested and worked.

Okay, so I've made the appropriate changes, and the FPS difference is phenomenal. I have no idea how, but it doesn't lag anymore (at least, not as close as what it used to drop to). I blame Warcraft's old code.
There's still some lag here and there, but nothing too impactful. Thread solved for now.

Big thanks for your help! Definitely deserve a spot in the credit list.
 
Status
Not open for further replies.
Top