Beam Auto Attack

The system has been uploaded: Persistent Beam


So sc2 has some pretty neat stuff when it comes to custom attacks... so I wanted to try recreating it in wc3. This system uses a DDS to create a fake chargeup sequence. Once that sequence is over, a beam is created until the target is dead, the attacker is dead, or the attacker is given an order other than attacking the target. I wanted to replicate the colossus's attack in alpha, but initial attempts have resulted in... not so good results, not to mention than a AoE attack with a DDS means that you are applying the damage that a unit will take, so if there are two units with two different armor types next to one another, attacking the unit that is most vulnerable will damage the other one more than should be damaged. I haven't actively tried to circumvent that, so keep an eye out, I guess.

That being said, I'm sure this can be improved. Anyone care to pitch in?

Using Unit Indexer and Damage Engine v3.5.1.0, both by Bribe, Lightning System v1.03 by Adiktuz, and GetUnitCollisionSize for GUI v1.4 by Almia.

  • Beam Auto Attack
    • Events
      • Game - DamageModifierEvent becomes Equal to 1.00
    • Conditions
      • (Unit-type of DamageEventSource) Equal to Arcane Tower
    • Actions
      • Set BeamID = (Custom value of DamageEventSource)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (DamageEventSource is in Beam_group) Equal to True
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Beam_IsChargingDone[BeamID] Equal to True
            • Then - Actions
              • Set DamageEventType = DamageTypeBeam
            • Else - Actions
              • Set DamageEventAmount = 0.00
        • Else - Actions
          • -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
          • -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
          • -------- CONFIGURE HERE --------
          • Set BeamConfig_AbilityCasterFX[BeamID] = FX - BeamCaster
          • Set BeamConfig_AbilityMoverFX[BeamID] = FX - BeamTarget
          • Set BeamConfig_BeamType[BeamID] = SLSB
          • Set BeamConfig_ImpactPeriodicFX[BeamID] = Abilities\Weapons\PriestMissile\PriestMissile.mdl
          • Set BeamConfig_CasterPeriodicFX[BeamID] = Abilities\Weapons\PriestMissile\PriestMissile.mdl
          • Set BeamConfig_ChargeUpFX[BeamID] = Abilities\Weapons\BlackKeeperMissile\BlackKeeperMissile.mdl
          • Set BeamConfig_ChargeLimit[BeamID] = 66
          • Set BeamConfig_CasterOffset[BeamID] = 0.00
          • Set BeamConfig_CasterHeight[BeamID] = 260.00
          • Set BeamConfig_Range[BeamID] = 800.00
          • -------- END CONFIGURATION --------
          • -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
          • -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
          • Set BeamOwner[BeamID] = (Owner of DamageEventSource)
          • Set Beam_interval[BeamID] = 0
          • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
          • Set Beam_loc1 = (Position of DamageEventSource)
          • Set Beam_loc2 = (Position of DamageEventTarget)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • BeamConfig_CasterOffset[BeamID] Greater than 0.00
            • Then - Actions
              • Set Beam_loc3 = (Beam_loc1 offset by BeamConfig_CasterOffset[BeamID] towards (Angle from Beam_loc1 to Beam_loc2) degrees)
              • Unit - Create 1 Dummy Unit (0 Collision) for BeamOwner[BeamID] at Beam_loc3 facing Beam_loc2
              • Custom script: call RemoveLocation(udg_Beam_loc3)
            • Else - Actions
              • Unit - Create 1 Dummy Unit (0 Collision) for BeamOwner[BeamID] at Beam_loc1 facing Beam_loc2
          • Set BeamCaster[BeamID] = (Last created unit)
          • Animation - Change BeamCaster[BeamID] flying height to ((Current flying height of DamageEventSource) + BeamConfig_CasterHeight[BeamID]) at 0.00
          • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
          • Unit - Create 1 Dummy Unit (0 Collision) for BeamOwner[BeamID] at Beam_loc2 facing (Angle from Beam_loc1 to Beam_loc2) degrees
          • Set BeamMover[BeamID] = (Last created unit)
          • Animation - Change BeamMover[BeamID] flying height to ((Current flying height of DamageEventTarget) + 50.00) at 0.00
          • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
          • Custom script: call RemoveLocation(udg_Beam_loc2)
          • Custom script: call RemoveLocation(udg_Beam_loc1)
          • Set BeamTarget[BeamID] = DamageEventTarget
          • Set DamageEventAmount = 0.00
          • Unit Group - Add DamageEventSource to Beam_group
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Beam Move <gen> is on) Equal to False
            • Then - Actions
              • Trigger - Turn on Beam Move <gen>
              • Trigger - Turn on Beam Stop <gen>
            • Else - Actions
  • Beam Move
    • Events
      • Time - Every (1.00 / 32.00) seconds of game time
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Beam_group is empty) Equal to True
        • Then - Actions
          • Trigger - Turn off (This trigger)
          • Trigger - Turn off Beam Stop <gen>
        • Else - Actions
          • Unit Group - Pick every unit in Beam_group and do (Actions)
            • Loop - Actions
              • Custom script: local Lightning beam
              • Custom script: local real h1
              • Custom script: local real h2
              • Set Beamer = (Picked unit)
              • Set BeamID = (Custom value of Beamer)
              • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
              • Set Beam_loc1 = (Position of Beamer)
              • Set Beam_loc2 = (Position of BeamTarget[BeamID])
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • BeamConfig_CasterOffset[BeamID] Greater than 0.00
                • Then - Actions
                  • Set Beam_loc3 = (Beam_loc1 offset by BeamConfig_CasterOffset[BeamID] towards (Angle from Beam_loc1 to Beam_loc2) degrees)
                  • Unit - Move BeamCaster[BeamID] instantly to Beam_loc3, facing Beam_loc2
                  • Custom script: call RemoveLocation(udg_Beam_loc3)
                • Else - Actions
                  • Unit - Move BeamCaster[BeamID] instantly to Beam_loc1, facing Beam_loc2
              • Unit - Move BeamMover[BeamID] instantly to Beam_loc2, facing (Angle from Beam_loc1 to Beam_loc2) degrees
              • Animation - Change BeamCaster[BeamID] flying height to ((Current flying height of Beamer) + BeamConfig_CasterHeight[BeamID]) at 0.00
              • Animation - Change BeamMover[BeamID] flying height to ((Current flying height of BeamTarget[BeamID]) + 50.00) at 0.00
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Beam_IsChargingDone[BeamID] Equal to False
                • Then - Actions
                  • Special Effect - Create a special effect attached to the origin of BeamCaster[BeamID] using BeamConfig_ChargeUpFX[BeamID]
                  • Special Effect - Destroy (Last created special effect)
                  • Set Beam_interval[BeamID] = (Beam_interval[BeamID] + 1)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • Beam_interval[BeamID] Greater than or equal to BeamConfig_ChargeLimit[BeamID]
                    • Then - Actions
                      • Set Beam_IsChargingDone[BeamID] = True
                      • Unit - Add BeamConfig_AbilityCasterFX[BeamID] to BeamCaster[BeamID]
                      • Unit - Add BeamConfig_AbilityMoverFX[BeamID] to BeamMover[BeamID]
                      • Custom script: set h1 = 0 - GetUnitFlyHeight(udg_BeamCaster[udg_BeamID])
                      • Custom script: set h2 = 0 - GetUnitFlyHeight(udg_BeamMover[udg_BeamID])
                      • Custom script: set udg_Beam_beam[udg_BeamID] = Lightning.unitToUnit(udg_BeamCaster[udg_BeamID], udg_BeamMover[udg_BeamID], h1, h2, false, 0, udg_BeamConfig_BeamType[udg_BeamID], 1)
                    • Else - Actions
                • Else - Actions
                  • Special Effect - Create a special effect attached to the origin of BeamCaster[BeamID] using BeamConfig_CasterPeriodicFX[BeamID]
                  • Special Effect - Destroy (Last created special effect)
                  • Special Effect - Create a special effect attached to the origin of BeamMover[BeamID] using BeamConfig_ImpactPeriodicFX[BeamID]
                  • Special Effect - Destroy (Last created special effect)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Or - Any (Conditions) are true
                    • Conditions
                      • Beam_TerminateBeam[BeamID] Equal to True
                      • (Distance between Beam_loc1 and Beam_loc2) Greater than or equal to BeamConfig_Range[BeamID]
                      • (BeamTarget[BeamID] is dead) Equal to True
                      • (Beamer is alive) Equal to False
                • Then - Actions
                  • Set Beam_IsInBeamCycle[BeamID] = False
                  • Set Beam_IsChargingDone[BeamID] = False
                  • Set Beam_interval[BeamID] = 0
                  • Unit - Add a 0.01 second Generic expiration timer to BeamCaster[BeamID]
                  • Unit - Add a 0.01 second Generic expiration timer to BeamMover[BeamID]
                  • Set BeamCaster[BeamID] = No unit
                  • Set BeamMover[BeamID] = No unit
                  • Set BeamTarget[BeamID] = No unit
                  • Custom script: set beam = udg_Beam_beam[udg_BeamID]
                  • Custom script: call beam.remove()
                  • Set Beam_TerminateBeam[BeamID] = False
                  • Unit Group - Remove Beamer from Beam_group
                  • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
                  • Custom script: set udg_BeamConfig_AbilityCasterFX[udg_BeamID] = 0
                  • Custom script: set udg_BeamConfig_AbilityMoverFX[udg_BeamID] = 0
                  • Set BeamConfig_BeamType[BeamID] = <Empty String>
                  • Set BeamConfig_ImpactPeriodicFX[BeamID] = <Empty String>
                  • Set BeamConfig_CasterPeriodicFX[BeamID] = <Empty String>
                  • Set BeamConfig_ChargeUpFX[BeamID] = <Empty String>
                • Else - Actions
              • Custom script: call RemoveLocation(udg_Beam_loc2)
              • Custom script: call RemoveLocation(udg_Beam_loc1)
  • Beam Stop
    • Events
      • Unit - A unit Is issued an order targeting an object
      • Unit - A unit Is issued an order targeting a point
      • Unit - A unit Is issued an order with no target
    • Conditions
      • ((Triggering unit) is in Beam_group) Equal to True
    • Actions
      • Set BeamID = (Custom value of (Triggering unit))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Target unit of issued order) Equal to BeamTarget[BeamID]
          • Or - Any (Conditions) are true
            • Conditions
              • (Issued order) Equal to (Order(attack))
              • (Issued order) Equal to (Order(smart))
        • Then - Actions
        • Else - Actions
          • Set Beam_TerminateBeam[BeamID] = True

Added sweeping beam attack. This one mimics the Colossus's attack in sc2 alpha. The only issue is that the Beamer (unit channelling the beam) will not disengage its beam is its target is slow enough when it moves out of range, meaning the Beamer than just constantly keep the pressure on. Now this may be a desirable feature, but I'd like to be able to remove it as well - so I slow the Beamer down when it's channelling by adding a custom Tornado Slow to it. This can be toggled on and off by setting BeamConfig_IsImmobilised to TRUE or FALSE. Setting it to TRUE will apply the debuff.

Be warned: something is leaking and I can't identify what because it doesn't happen all the time.

  • Sweeping Beam Attack
    • Events
      • Game - DamageModifierEvent becomes Equal to 1.00
    • Conditions
      • (Unit-type of DamageEventSource) Equal to Wisp
      • DamageEventType Equal to 0
    • Actions
      • Set DamageEventAmount = 0.00
      • Set BeamID = (Custom value of DamageEventSource)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (DamageEventSource is in Beam_SweepGroup) Equal to True
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Beam_IsChargingDone[BeamID] Equal to True
            • Then - Actions
              • Set Beam_damage[BeamID] = DamageEventPrevAmt
              • Set Beam_interval[BeamID] = 0
            • Else - Actions
        • Else - Actions
          • -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
          • -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
          • -------- CONFIGURE HERE --------
          • Set BeamConfig_AbilityCasterFX[BeamID] = FX - BeamCaster
          • Set BeamConfig_AbilityMoverFX[BeamID] = FX - BeamTarget
          • Set BeamConfig_BeamType[BeamID] = SLSB
          • Set BeamConfig_ImpactPeriodicFX[BeamID] = Abilities\Weapons\PriestMissile\PriestMissile.mdl
          • Set BeamConfig_CasterPeriodicFX[BeamID] = Abilities\Weapons\PriestMissile\PriestMissile.mdl
          • Set BeamConfig_ChargeUpFX[BeamID] = Abilities\Weapons\BlackKeeperMissile\BlackKeeperMissile.mdl
          • Set BeamConfig_ChargeLimit[BeamID] = 33
          • Set BeamConfig_GracePeriod[BeamID] = 44
          • Set BeamConfig_CasterOffset[BeamID] = 70.00
          • Set BeamConfig_CasterHeight[BeamID] = 60.00
          • Set BeamConfig_Range[BeamID] = 700.00
          • Set BeamConfig_SweepSpeed[BeamID] = 300.00
          • Set BeamConfig_DamageAOE[BeamID] = 100.00
          • Set BeamConfig_SweepAOE[BeamID] = 600.00
          • Set BeamConfig_IsImmobilised[BeamID] = True
          • -------- END CONFIGURATION --------
          • -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
          • -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
          • Set BeamOwner[BeamID] = (Owner of DamageEventSource)
          • Set Beam_AttackType[BeamID] = Magic
          • Set Beam_interval[BeamID] = 0
          • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
          • Set Beam_loc1 = (Position of DamageEventSource)
          • Set Beam_loc2 = (Position of DamageEventTarget)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • BeamConfig_CasterOffset[BeamID] Greater than 0.00
            • Then - Actions
              • Set Beam_loc3 = (Beam_loc1 offset by BeamConfig_CasterOffset[BeamID] towards (Angle from Beam_loc1 to Beam_loc2) degrees)
              • Unit - Create 1 Dummy Unit (0 Collision) for BeamOwner[BeamID] at Beam_loc3 facing Beam_loc2
              • Custom script: call RemoveLocation(udg_Beam_loc3)
            • Else - Actions
              • Unit - Create 1 Dummy Unit (0 Collision) for BeamOwner[BeamID] at Beam_loc1 facing Beam_loc2
          • Set BeamCaster[BeamID] = (Last created unit)
          • Animation - Change BeamCaster[BeamID] flying height to ((Current flying height of DamageEventSource) + BeamConfig_CasterHeight[BeamID]) at 0.00
          • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
          • Unit - Create 1 Dummy Unit (0 Collision) for BeamOwner[BeamID] at Beam_loc2 facing (Angle from Beam_loc1 to Beam_loc2) degrees
          • Set BeamMover[BeamID] = (Last created unit)
          • Animation - Change BeamMover[BeamID] flying height to ((Current flying height of DamageEventTarget) + 50.00) at 0.00
          • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
          • Custom script: call RemoveLocation(udg_Beam_loc2)
          • Custom script: call RemoveLocation(udg_Beam_loc1)
          • Set BeamTarget[BeamID] = DamageEventTarget
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • BeamConfig_IsImmobilised[BeamID] Equal to True
            • Then - Actions
              • Trigger - Turn off DamageEventTrigger
              • Unit - Add Max Slow to DamageEventSource
              • Trigger - Turn on DamageEventTrigger
            • Else - Actions
          • Unit Group - Add DamageEventSource to Beam_SweepGroup
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Beam Move <gen> is on) Equal to False
            • Then - Actions
              • Trigger - Turn on Sweeping Beam Tracking <gen>
              • Trigger - Turn on Sweeping Beam Cancel A <gen>
              • Trigger - Turn on Sweeping Beam Cancel B <gen>
            • Else - Actions
  • Sweeping Beam Tracking
    • Events
      • Time - Every (1.00 / 32.00) seconds of game time
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Beam_SweepGroup is empty) Equal to True
        • Then - Actions
          • Trigger - Turn off (This trigger)
          • Trigger - Turn off Sweeping Beam Cancel A <gen>
          • Trigger - Turn off Sweeping Beam Cancel B <gen>
        • Else - Actions
          • Unit Group - Pick every unit in Beam_SweepGroup and do (Actions)
            • Loop - Actions
              • Custom script: local Lightning beam
              • Custom script: local real h1
              • Custom script: local real h2
              • Set Beamer = (Picked unit)
              • Set BeamID = (Custom value of Beamer)
              • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
              • Set Beam_loc1 = (Position of Beamer)
              • Set Beam_loc2 = (Position of BeamTarget[BeamID])
              • Set GUCS_U = BeamTarget[BeamID]
              • Trigger - Run GetUnitCollisionSize <gen> (ignoring conditions)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • GUCS_Size Greater than or equal to 144
                • Then - Actions
                  • Set GUCS_Size = (GUCS_Size + (GUCS_Size / 2))
                • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • GUCS_Size Less than or equal to 2
                    • Then - Actions
                      • Set GUCS_Size = 12
                    • Else - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • GUCS_Size Less than or equal to 8
                        • Then - Actions
                          • Set GUCS_Size = (GUCS_Size x 6)
                        • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Distance between Beam_loc1 and Beam_loc2) Greater than (BeamConfig_Range[BeamID] + ((Real(GUCS_Size)) x 2.00))
                • Then - Actions
                  • Set Beam_TerminateBeam[BeamID] = True
                • Else - Actions
              • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
              • Set Beam_loc3 = (Position of BeamMover[BeamID])
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Distance between Beam_loc3 and Beam_loc2) Greater than (BeamConfig_SweepSpeed[BeamID] / 33.00)
                • Then - Actions
                  • Set Beam_loc4 = (Beam_loc3 offset by (BeamConfig_SweepSpeed[BeamID] / 33.00) towards (Angle from Beam_loc3 to Beam_loc2) degrees)
                • Else - Actions
                  • Set Beam_loc4 = Beam_loc2
              • Unit - Move BeamMover[BeamID] instantly to Beam_loc4, facing (Angle from Beam_loc1 to Beam_loc2) degrees
              • Animation - Change BeamCaster[BeamID] flying height to ((Current flying height of Beamer) + BeamConfig_CasterHeight[BeamID]) at 0.00
              • Animation - Change BeamMover[BeamID] flying height to ((Current flying height of BeamTarget[BeamID]) + 50.00) at 0.00
              • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
              • Custom script: call RemoveLocation(udg_Beam_loc3)
              • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • BeamConfig_CasterOffset[BeamID] Greater than 0.00
                • Then - Actions
                  • Set Beam_loc3 = (Beam_loc1 offset by BeamConfig_CasterOffset[BeamID] towards (Angle from Beam_loc1 to Beam_loc4) degrees)
                  • Unit - Move BeamCaster[BeamID] instantly to Beam_loc3, facing Beam_loc2
                  • Custom script: call RemoveLocation(udg_Beam_loc3)
                • Else - Actions
                  • Unit - Move BeamCaster[BeamID] instantly to Beam_loc1, facing Beam_loc2
              • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (BeamTarget[BeamID] is dead) Equal to True
                • Then - Actions
                  • Set Beam_group1 = (Units within BeamConfig_SweepAOE[BeamID] of Beam_loc4 matching ((((Matching unit) is alive) Equal to True) and ((((Matching unit) is A ground unit) Equal to True) and (((Matching unit) belongs to an enemy of BeamOwner[BeamID]) Equal to True))))
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Beam_group1 is empty) Equal to True
                    • Then - Actions
                      • Set Beam_TerminateBeam[BeamID] = True
                    • Else - Actions
                      • Set Beam_group2 = (Units within BeamConfig_Range[BeamID] of Beam_loc1 matching ((((Matching unit) is alive) Equal to True) and ((((Matching unit) is A ground unit) Equal to True) and (((Matching unit) belongs to an enemy of BeamOwner[BeamID]) Equal to True))))
                      • Unit Group - Pick every unit in (Random 1 units from Beam_group2) and do (Actions)
                        • Loop - Actions
                          • Set BeamerPick = (Picked unit)
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • (BeamerPick is in Beam_group1) Equal to True
                            • Then - Actions
                              • Unit - Order Beamer to Attack BeamerPick
                              • Set BeamTarget[BeamID] = BeamerPick
                            • Else - Actions
                              • Set Beam_TerminateBeam[BeamID] = True
                      • Custom script: call DestroyGroup(udg_Beam_group2)
                  • Custom script: call DestroyGroup(udg_Beam_group1)
                • Else - Actions
              • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
              • Custom script: call RemoveLocation(udg_Beam_loc4)
              • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Beam_IsChargingDone[BeamID] Equal to False
                • Then - Actions
                  • Special Effect - Create a special effect attached to the origin of BeamCaster[BeamID] using BeamConfig_ChargeUpFX[BeamID]
                  • Special Effect - Destroy (Last created special effect)
                  • Set Beam_interval[BeamID] = (Beam_interval[BeamID] + 1)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • Beam_interval[BeamID] Greater than or equal to BeamConfig_ChargeLimit[BeamID]
                    • Then - Actions
                      • Set Beam_interval[BeamID] = 0
                      • Set Beam_IsChargingDone[BeamID] = True
                      • Unit - Add BeamConfig_AbilityCasterFX[BeamID] to BeamCaster[BeamID]
                      • Unit - Add BeamConfig_AbilityMoverFX[BeamID] to BeamMover[BeamID]
                      • Custom script: set h1 = 0 - GetUnitFlyHeight(udg_BeamCaster[udg_BeamID])
                      • Custom script: set h2 = 0 - GetUnitFlyHeight(udg_BeamMover[udg_BeamID])
                      • Custom script: set udg_Beam_beam[udg_BeamID] = Lightning.unitToUnit(udg_BeamCaster[udg_BeamID], udg_BeamMover[udg_BeamID], h1, h2, false, 0, udg_BeamConfig_BeamType[udg_BeamID], 1)
                    • Else - Actions
                • Else - Actions
                  • Set Beam_loc3 = (Position of BeamMover[BeamID])
                  • Set Beam_loc4 = (Position of BeamTarget[BeamID])
                  • Set Beam_group1 = (Units within BeamConfig_DamageAOE[BeamID] of Beam_loc3 matching ((((Matching unit) is alive) Equal to True) and ((((Matching unit) is A ground unit) Equal to True) and (((Matching unit) belongs to an enemy of BeamOwner[BeamID]) Equal to True))))
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Distance between Beam_loc3 and Beam_loc4) Less than or equal to BeamConfig_DamageAOE[BeamID]
                    • Then - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (BeamTarget[BeamID] is in Beam_group1) Equal to False
                        • Then - Actions
                          • Unit Group - Add BeamTarget[BeamID] to Beam_group1
                        • Else - Actions
                    • Else - Actions
                  • Unit Group - Pick every unit in Beam_group1 and do (Actions)
                    • Loop - Actions
                      • Set BeamerPick = (Picked unit)
                      • Set NextDamageType = DamageTypeBeam
                      • Unit - Cause Beamer to damage BeamerPick, dealing (Beam_damage[BeamID] / 33.00) damage of attack type Beam_AttackType[BeamID] and damage type Universal
                      • Trigger - Run ClearDamageEvent (checking conditions)
                  • Custom script: call DestroyGroup(udg_Beam_group1)
                  • Custom script: call RemoveLocation(udg_Beam_loc4)
                  • Custom script: call RemoveLocation(udg_Beam_loc3)
                  • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
                  • Special Effect - Create a special effect attached to the origin of BeamCaster[BeamID] using BeamConfig_CasterPeriodicFX[BeamID]
                  • Special Effect - Destroy (Last created special effect)
                  • Special Effect - Create a special effect attached to the origin of BeamMover[BeamID] using BeamConfig_ImpactPeriodicFX[BeamID]
                  • Special Effect - Destroy (Last created special effect)
                  • Set Beam_interval[BeamID] = (Beam_interval[BeamID] + 1)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • Beam_interval[BeamID] Greater than or equal to BeamConfig_GracePeriod[BeamID]
                    • Then - Actions
                      • Set Beam_TerminateBeam[BeamID] = True
                    • Else - Actions
              • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Or - Any (Conditions) are true
                    • Conditions
                      • Beam_TerminateBeam[BeamID] Equal to True
                      • (Beamer is alive) Equal to False
                • Then - Actions
                  • Set Beam_IsChargingDone[BeamID] = False
                  • Set Beam_interval[BeamID] = 0
                  • Unit - Add a 0.01 second Generic expiration timer to BeamCaster[BeamID]
                  • Unit - Add a 0.01 second Generic expiration timer to BeamMover[BeamID]
                  • Set BeamCaster[BeamID] = No unit
                  • Set BeamMover[BeamID] = No unit
                  • Set BeamTarget[BeamID] = No unit
                  • Custom script: set beam = udg_Beam_beam[udg_BeamID]
                  • Custom script: call beam.remove()
                  • Set Beam_TerminateBeam[BeamID] = False
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • BeamConfig_IsImmobilised[BeamID] Equal to True
                    • Then - Actions
                      • Trigger - Turn off DamageEventTrigger
                      • Unit - Remove Max Slow from Beamer
                      • Unit - Remove Channelling buff from Beamer
                      • Trigger - Turn on DamageEventTrigger
                      • Set BeamConfig_IsImmobilised[BeamID] = False
                    • Else - Actions
                  • Unit Group - Remove Beamer from Beam_SweepGroup
                  • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
                  • Custom script: set udg_BeamConfig_AbilityCasterFX[udg_BeamID] = 0
                  • Custom script: set udg_BeamConfig_AbilityMoverFX[udg_BeamID] = 0
                  • Set BeamConfig_BeamType[BeamID] = <Empty String>
                  • Set BeamConfig_ImpactPeriodicFX[BeamID] = <Empty String>
                  • Set BeamConfig_CasterPeriodicFX[BeamID] = <Empty String>
                  • Set BeamConfig_ChargeUpFX[BeamID] = <Empty String>
                • Else - Actions
              • Custom script: call RemoveLocation(udg_Beam_loc2)
              • Custom script: call RemoveLocation(udg_Beam_loc1)
  • Sweeping Beam Cancel A
    • Events
      • Unit - A unit Is issued an order targeting a point
      • Unit - A unit Is issued an order with no target
    • Conditions
      • ((Triggering unit) is in Beam_SweepGroup) Equal to True
    • Actions
      • Set BeamID = (Custom value of (Triggering unit))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • (Issued order) Equal to (Order(smart))
              • (Issued order) Equal to (Order(stop))
              • (Issued order) Equal to (Order(move))
              • (Issued order) Equal to (Order(patrol))
        • Then - Actions
          • Set Beam_TerminateBeam[BeamID] = True
        • Else - Actions
  • Sweeping Beam Cancel B
    • Events
      • Unit - A unit Is issued an order targeting an object
    • Conditions
      • ((Triggering unit) is in Beam_SweepGroup) Equal to True
    • Actions
      • Set BeamID = (Custom value of (Triggering unit))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Target unit of issued order) Not equal to BeamTarget[BeamID]
          • Or - Any (Conditions) are true
            • Conditions
              • (Issued order) Equal to (Order(smart))
              • (Issued order) Equal to (Order(attack))
        • Then - Actions
          • Set BeamCancel_loc1 = (Position of BeamTarget[BeamID])
          • Set BeamCancel_loc2 = (Position of (Target unit of issued order))
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Distance between BeamCancel_loc1 and BeamCancel_loc2) Greater than BeamConfig_SweepAOE[BeamID]
            • Then - Actions
              • Set Beam_TerminateBeam[BeamID] = True
            • Else - Actions
          • Custom script: call RemoveLocation(udg_BeamCancel_loc2)
          • Custom script: call RemoveLocation(udg_BeamCancel_loc1)
        • Else - Actions
 
Last edited:
It never occurred to me to me to turn off triggers without a periodic timer. I guess it does make sense so that it doesn't fire whenever any unit is given an order. As far as damaging dead targets go, it shouldn't do that because it constantly checks whether the BeamTarget is dead or not... which in retrospect might be something to place inside the timer loop instead of checking on every attack.

This brings me to another point: the prototype version of the beam attack tried to mimic the Collossus's attack when sc2 was still in alpha, and I've had a measure of success, but for some reason the entire thing would fall apart whenever multiple Beamers tried to attack different targets far from one another. The beam was supposed to remain 2 seconds after it's initial target died, which gave the Beamer time to reacquire a new target and sweep the beam back towards its new target, were it close enough. That can be made to work well enough, but the main problem is the AoE damage - the value that will be used for damage will depend on your initial target after the armor reduction, which makes me wonder whether there's a way to find out what the pure damage is (before any type of reduction).

EDIT: Okay there are some issues with dead units. Fixed. OP and map updated.

@Bribe: there seems to be a problem with indexing preplaced units - sometimes they dont get indexed, and trying to clean something bound to the index caused problems, like I was getting crashes from the map since one of the towers did not appear to have an index - so trying to clean it's lightning effect was causing crashes. After making the towers create after a timer fixed this issue. Might wanna investigate that.


EDIT2: added sweeping beam. The only issue with that is that the range the beam can extend must be... extended by the collision size of the target or else the attacker will just begin channeling and stopping. I used a library that catches unit collisions, but now if the unit in question is large enough, and moves slowly enough (eg: Uprooted Ancients) the Beamer will just inch forward little by little and the beam will never break. I don't know if that's a good thing or not.
 
Last edited:
Level 36
Joined
Sep 26, 2009
Messages
8,444
So I'm looking over this dummy map and playing around with these abilities, though I am having trouble figuring out what it is that you're describing.

The wisp deals 0 damage to allied units, though it targets them fine, not sure if that's intentional. The arcane tower doesn't have that problem.

As far as damage being blocked... I see the arcane tower doesn't do any damage at all for the first couple of seconds as it's "charging", but the wisp deals damage to the enemy immediately, no charging involved. However, I don't see anything in wisp damage trigger that reduces the damage event amount, so maybe that is the problem?

If you ever suspect that damage is not being blocked, the best way to find out why that might be is to add a Game - text message (auto timed) right above or below the Set DamageEventAmount =0.00 line stating "damage is being blocked".

It seems like this is going to be hard to pinpoint, otherwise.
 
The way the arcane tower deals damage is just by checking if the charging is done, and then stop blocking the damage. The wisp is different - the damage for the wisp is always being blocked, and is then dealt by triggers in the periodic timer trigger. This is because the damage is aoe and is centered on the beam's 'mover', which is a dummy unit that will constantly track its target and move to it's location. If the target dies, the wisp has a little over 1 second to reacquire a new target. Otherwise, it has to charge up all over again. If the new target is close enough, the mover will sweep over to it, damaging any enemy in the way. If the new target is to far, the beam ends and has to charge up anew.

If you look in Sweeping Beam Attack, you'll find the DamageEventAmount is set to 0 at the start of the trigger, so the damage should get blocked all the time, the condition being that the DamageEventType has to be 0. Then, in Sweeping Beam Tracking, triggered damage is dealt there:

  • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
  • Set Beam_DamageGroup = (Units within BeamConfig_DamageAOE[BeamID] of Beam_loc4 matching ((((Matching unit) is alive) Equal to True) and ((((Matching unit) is A ground unit) Equal to True) and (((Matching unit) belongs to an enemy of BeamOwner[BeamID]) Equal to True))))
  • Unit Group - Pick every unit in Beam_DamageGroup and do (Actions)
    • Loop - Actions
      • Set BeamerPick = (Picked unit)
      • Set NextDamageType = DamageTypeBeam
      • Unit - Cause Beamer to damage BeamerPick, dealing (Beam_damage[BeamID] / 33.00) damage of attack type Beam_AttackType[BeamID] and damage type Universal
      • Trigger - Run ClearDamageEvent (checking conditions)
  • Custom script: call DestroyGroup(udg_Beam_DamageGroup)
  • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
That's the reason why allies aren't being targeted, because they're not in the unit group. I guess I could add an exception for BeamTarget[].
 
Level 36
Joined
Sep 26, 2009
Messages
8,444
So what you're saying is that even if the damage is removed from the periodic timer, leaving just the damage set to 0, that it will still take damage from the wisp? If so, go ahead and add a game message in the same block as you set the damage to 0. I need to make sure that point in the code is executing.
 
Okay, what I've noticed from testing this is that initially, before they've dealt any damage, the wisps' damage would be blocked during charge up. Once that initial triggered damage is dealt, however, any consequent damage fails to be blocked. If a wisp stops attacking so that the beam is destroyed and then attacks again, the target will take damage during chargeup...

EDIT: okay, hold for a sec, I think I might have setup my code wrong.

EDIT2: Yeah, I totally screwed up the placement of the damage trigger, and now it works again. HOWEVER, the problem with the Tornado Slow remains. I've updated the map in the OP (I should probably start adding version numbers to those) and if you look at Sweeping Beam Attack and Sweeping Beam Tracking you'll find disabled functions near the bottom of both. Enable those and then when you test the wisp's attack, the targets will take initial damage as the charge up begins. It happens only when the ability is added for some reason.
 
Level 36
Joined
Sep 26, 2009
Messages
8,444
SpellBound, before you add the ability, disable DamageEventTrigger, then enable it after adding the ability. You don't need to update DamageEngine for that.

  • Trigger - Turn off DamageEventTrigger
  • Unit - Add Max Slow to DamageEventSource
  • Trigger - Turn on DamageEventTrigger
It looks like the unit damages itself for 0 when you add the ability, and it was screwing up the recursion.
 
Last edited:
Alright, this seems to have fixed the problem and updated the test map in the OP.

I had to split the cancel trigger into 2 parts because of smart being applicable in a bunch of situations. I was also having some issues to make the unit reacquire a target without destroying the beam, so instead I made the retargeting automatic, ordering the unit to attack a random viable target within attack range and sweeping range. This makes for some rather strange attack patterns, but I guess that can be remedied to with GetClosestWidget.

One thing I can't figure out is why the system crashes sometimes. When multiple wisps attack, sometimes the beams will be destroyed when it's already been stored in an array variable unique to the attacker. Something is leaking and I can't figure out what, or why it doesn't happen all the time. I've has tests where all three wisps attack at the same time and nothing crashes.
 
Well I tried increasing the intervals to 0.05 instead of 0.03 and it still crashed (also paused the dummies). I've noticed that often time when it crashes it's because one of the lightning effects was destroyed when it shouldn't have been, but it's not clear why this is happening. Maybe I should just not use LightningSystem.

EDIT: Okay, I'm pretty sure it's LightningSystem's fault. I disabled the lightning and it's not crashing anymore.

EDIT2: I'm officially stumped. I tried making my own lightning and it crashed even faster...
 
Last edited:
I can't use Timed Lightnings since it's, well, timed :D I have to be able to control when it gets destroyed myself.

I did try to control the movement myself. It crashed even faster.

EDIT: I tried debugging with a message to see why the lightning crashes the game. It's not being destroyed twice, so it has to be something else about it.
EDIT 2: updated the map again. The moving lightning that I made myself are disabled.
 
Well that wouldn't allow me to control where the beam goes. The idea behind replicating the Colossus's attack from alpha sc2 is to have, in essence, a 'crosshair' that tracks the enemy, and that crosshair is connected to the attacker by a lightning effect. If the enemy moves fast enough, they can outrun the crosshair. Damage is applied around the crosshair, not the enemy, so any enemy inside the crosshair's AoE will get hit. A crosshair that sweeps across the ground will hit any enemy along the way. This means that the damage the unit deals must be blocked, and only triggered damage is allowed. The Wisp already does that. There's just this weird issue of the game crashing.

Also using lightning attack with a fast-attacking unit just makes the beam flicker. A constant stream of lightning effect, like Life Drain, looks better.
 
Hmm, can't find one that isn't timed. I don't know why lightning would crash the game like that - do lightning effects leak? I'm using the same system for another attack that uses untimed lightning effects, and I've never had a crash from it. The only difference is that this one is in vJASS. Maybe GUI has some unseen overhead?
 
Okey. This crashes the game the after a lightning is created after one is destroyed. That happens with or without the if != null conditions


  • Sweeping Beam Tracking
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Beam_SweepGroup is empty) Equal to True
        • Then - Actions
          • Trigger - Turn off (This trigger)
          • Trigger - Turn off Sweeping Beam Cancel A <gen>
          • Trigger - Turn off Sweeping Beam Cancel B <gen>
        • Else - Actions
          • Unit Group - Pick every unit in Beam_SweepGroup and do (Actions)
            • Loop - Actions
              • Custom script: local real x1
              • Custom script: local real y1
              • Custom script: local real z1
              • Custom script: local real x2
              • Custom script: local real y2
              • Custom script: local real z2
              • Set Beamer = (Picked unit)
              • Set BeamID = (Custom value of Beamer)
              • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
              • Custom script: set x1 = GetUnitX(udg_BeamCaster[udg_BeamID])
              • Custom script: set y1 = GetUnitY(udg_BeamCaster[udg_BeamID])
              • Custom script: set z1 = 0 - GetUnitFlyHeight(udg_BeamCaster[udg_BeamID])
              • Custom script: set x2 = GetUnitX(udg_BeamMover[udg_BeamID])
              • Custom script: set y2 = GetUnitY(udg_BeamMover[udg_BeamID])
              • Custom script: set z2 = 0 - GetUnitFlyHeight(udg_BeamMover[udg_BeamID])
              • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
              • Set Beam_loc1 = (Position of Beamer)
              • Set Beam_loc2 = (Position of BeamTarget[BeamID])
              • Set GUCS_U = BeamTarget[BeamID]
              • Trigger - Run GetUnitCollisionSize <gen> (ignoring conditions)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • GUCS_Size Greater than or equal to 144
                • Then - Actions
                  • Set GUCS_Size = (GUCS_Size + (GUCS_Size / 2))
                • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • GUCS_Size Less than or equal to 2
                    • Then - Actions
                      • Set GUCS_Size = 12
                    • Else - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • GUCS_Size Less than or equal to 8
                        • Then - Actions
                          • Set GUCS_Size = (GUCS_Size x 6)
                        • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Distance between Beam_loc1 and Beam_loc2) Greater than (BeamConfig_Range[BeamID] + ((Real(GUCS_Size)) x 2.00))
                • Then - Actions
                  • Set Beam_TerminateBeam[BeamID] = True
                • Else - Actions
              • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
              • Set Beam_loc3 = (Position of BeamMover[BeamID])
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Distance between Beam_loc3 and Beam_loc2) Greater than (BeamConfig_SweepSpeed[BeamID] / 33.00)
                • Then - Actions
                  • Set Beam_loc4 = (Beam_loc3 offset by (BeamConfig_SweepSpeed[BeamID] / 33.00) towards (Angle from Beam_loc3 to Beam_loc2) degrees)
                • Else - Actions
                  • Set Beam_loc4 = Beam_loc2
              • Unit - Move BeamMover[BeamID] instantly to Beam_loc4, facing (Angle from Beam_loc1 to Beam_loc2) degrees
              • Custom script: if udg_BeamLightning[udg_BeamID] != null then
              • Custom script: call MoveLightningEx(udg_BeamLightning[udg_BeamID], true, x1, y1, z1, x2, y2, z2)
              • Custom script: endif
              • Animation - Change BeamCaster[BeamID] flying height to ((Current flying height of Beamer) + BeamConfig_CasterHeight[BeamID]) at 0.00
              • Animation - Change BeamMover[BeamID] flying height to ((Current flying height of BeamTarget[BeamID]) + 50.00) at 0.00
              • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
              • Custom script: call RemoveLocation(udg_Beam_loc3)
              • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • BeamConfig_CasterOffset[BeamID] Greater than 0.00
                • Then - Actions
                  • Set Beam_loc3 = (Beam_loc1 offset by BeamConfig_CasterOffset[BeamID] towards (Angle from Beam_loc1 to Beam_loc4) degrees)
                  • Unit - Move BeamCaster[BeamID] instantly to Beam_loc3, facing Beam_loc2
                  • Custom script: call RemoveLocation(udg_Beam_loc3)
                • Else - Actions
                  • Unit - Move BeamCaster[BeamID] instantly to Beam_loc1, facing Beam_loc2
              • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (BeamTarget[BeamID] is dead) Equal to True
                • Then - Actions
                  • Set Beam_group1 = (Units within BeamConfig_SweepAOE[BeamID] of Beam_loc4 matching ((((Matching unit) is alive) Equal to True) and ((((Matching unit) is A ground unit) Equal to True) and (((Matching unit) belongs to an enemy of BeamOwner[BeamID]) Equal to True))))
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Beam_group1 is empty) Equal to True
                    • Then - Actions
                      • Set Beam_TerminateBeam[BeamID] = True
                    • Else - Actions
                      • Set Beam_group2 = (Units within BeamConfig_Range[BeamID] of Beam_loc1 matching ((((Matching unit) is alive) Equal to True) and ((((Matching unit) is A ground unit) Equal to True) and (((Matching unit) belongs to an enemy of BeamOwner[BeamID]) Equal to True))))
                      • Unit Group - Pick every unit in (Random 1 units from Beam_group2) and do (Actions)
                        • Loop - Actions
                          • Set BeamerPick = (Picked unit)
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • (BeamerPick is in Beam_group1) Equal to True
                            • Then - Actions
                              • Unit - Order Beamer to Attack BeamerPick
                              • Set BeamTarget[BeamID] = BeamerPick
                            • Else - Actions
                              • Set Beam_TerminateBeam[BeamID] = True
                      • Custom script: call DestroyGroup(udg_Beam_group2)
                  • Custom script: call DestroyGroup(udg_Beam_group1)
                • Else - Actions
              • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
              • Custom script: call RemoveLocation(udg_Beam_loc4)
              • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Beam_IsChargingDone[BeamID] Equal to False
                • Then - Actions
                  • Special Effect - Create a special effect attached to the origin of BeamCaster[BeamID] using BeamConfig_ChargeUpFX[BeamID]
                  • Special Effect - Destroy (Last created special effect)
                  • Set Beam_interval[BeamID] = (Beam_interval[BeamID] + 1)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • Beam_interval[BeamID] Greater than or equal to BeamConfig_ChargeLimit[BeamID]
                    • Then - Actions
                      • Set Beam_interval[BeamID] = 0
                      • Set Beam_IsChargingDone[BeamID] = True
                      • Unit - Add BeamConfig_AbilityCasterFX[BeamID] to BeamCaster[BeamID]
                      • Unit - Add BeamConfig_AbilityMoverFX[BeamID] to BeamMover[BeamID]
                      • Custom script: set udg_BeamLightning[udg_BeamID] = AddLightningEx(udg_BeamConfig_BeamType[udg_BeamID], true, x1, y1, z1, x2, y2, z2)
                      • Game - Display to (All players) for 5.00 seconds the text: Lightning Created.
                    • Else - Actions
                • Else - Actions
                  • Set Beam_loc3 = (Position of BeamMover[BeamID])
                  • Set Beam_loc4 = (Position of BeamTarget[BeamID])
                  • Set Beam_group1 = (Units within BeamConfig_DamageAOE[BeamID] of Beam_loc3 matching ((((Matching unit) is alive) Equal to True) and ((((Matching unit) is A ground unit) Equal to True) and (((Matching unit) belongs to an enemy of BeamOwner[BeamID]) Equal to True))))
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Distance between Beam_loc3 and Beam_loc4) Less than or equal to BeamConfig_DamageAOE[BeamID]
                    • Then - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (BeamTarget[BeamID] is in Beam_group1) Equal to False
                        • Then - Actions
                          • Unit Group - Add BeamTarget[BeamID] to Beam_group1
                        • Else - Actions
                    • Else - Actions
                  • Unit Group - Pick every unit in Beam_group1 and do (Actions)
                    • Loop - Actions
                      • Set BeamerPick = (Picked unit)
                      • Set NextDamageType = DamageTypeBeam
                      • Unit - Cause Beamer to damage BeamerPick, dealing (Beam_damage[BeamID] / 33.00) damage of attack type Beam_AttackType[BeamID] and damage type Universal
                      • Trigger - Run ClearDamageEvent (checking conditions)
                  • Custom script: call DestroyGroup(udg_Beam_group1)
                  • Custom script: call RemoveLocation(udg_Beam_loc4)
                  • Custom script: call RemoveLocation(udg_Beam_loc3)
                  • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
                  • Special Effect - Create a special effect attached to the origin of BeamCaster[BeamID] using BeamConfig_CasterPeriodicFX[BeamID]
                  • Special Effect - Destroy (Last created special effect)
                  • Special Effect - Create a special effect attached to the origin of BeamMover[BeamID] using BeamConfig_ImpactPeriodicFX[BeamID]
                  • Special Effect - Destroy (Last created special effect)
                  • Set Beam_interval[BeamID] = (Beam_interval[BeamID] + 1)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • Beam_interval[BeamID] Greater than or equal to BeamConfig_GracePeriod[BeamID]
                    • Then - Actions
                      • Set Beam_TerminateBeam[BeamID] = True
                    • Else - Actions
              • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Or - Any (Conditions) are true
                    • Conditions
                      • Beam_TerminateBeam[BeamID] Equal to True
                      • (Beamer is alive) Equal to False
                • Then - Actions
                  • Custom script: set udg_BeamConfig_AbilityCasterFX[udg_BeamID] = 0
                  • Custom script: set udg_BeamConfig_AbilityMoverFX[udg_BeamID] = 0
                  • Set BeamConfig_BeamType[BeamID] = <Empty String>
                  • Set BeamConfig_ImpactPeriodicFX[BeamID] = <Empty String>
                  • Set BeamConfig_CasterPeriodicFX[BeamID] = <Empty String>
                  • Set BeamConfig_ChargeUpFX[BeamID] = <Empty String>
                  • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
                  • Set Beam_IsChargingDone[BeamID] = False
                  • Set Beam_interval[BeamID] = 0
                  • Unit - Unpause BeamCaster[BeamID]
                  • Unit - Unpause BeamMover[BeamID]
                  • Unit - Kill BeamCaster[BeamID]
                  • Unit - Kill BeamMover[BeamID]
                  • Set BeamCaster[BeamID] = No unit
                  • Set BeamMover[BeamID] = No unit
                  • Set BeamTarget[BeamID] = No unit
                  • Game - Display to (All players) for 5.00 seconds the text: Lightning Destroyed...
                  • Custom script: if udg_BeamLightning[udg_BeamID] != null then
                  • Custom script: call DestroyLightning(udg_BeamLightning[udg_BeamID])
                  • Custom script: endif
                  • Set Beam_TerminateBeam[BeamID] = False
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • BeamConfig_IsImmobilised[BeamID] Equal to True
                    • Then - Actions
                      • Trigger - Turn off DamageEventTrigger
                      • Unit - Remove Max Slow from Beamer
                      • Unit - Remove Channelling buff from Beamer
                      • Trigger - Turn on DamageEventTrigger
                      • Set BeamConfig_IsImmobilised[BeamID] = False
                    • Else - Actions
                  • Unit Group - Remove Beamer from Beam_SweepGroup
                • Else - Actions
              • Custom script: call RemoveLocation(udg_Beam_loc2)
              • Custom script: call RemoveLocation(udg_Beam_loc1)
 
Oh, it works! I tried doing that with LightningSystem and it still crashed, so that probably why I never tried it here. I'll need to do some more testing but it's looking like the issue's been resolved. Hopefully! (fingers crossed)

EDIT: Okay, it's definitely not crashing anymore. Now I need to figured out of a way to make the targeting parameters configurable.

EDIT2: okay... uhm... I need help to get this call beamfilter.filtertargets(GetLocationX(udg_Beam_loc3),GetLocationY(udg_Beam_loc3), udg_BeamConfig_DamageAOE[udg_BeamID]) to work. I tried making a library but honestly I have no idea what I'm even doing lol. The idea is that you setup what targets you can hit and then add said targets to a unit group, Beam_group1 to be specific. It's sort of just a filter because it's used in two different pats in the code.


JASS:
library BeamFilter

    globals
        private group ENUM_GROUP = CreateGroup()
    endglobals
    
    struct beamfilter extends array
    
        static method filtertargets takes real x, real y, real r returns nothing
            local unit u
            local effect fx
            
            call GroupEnumUnitsInRange(ENUM_GROUP, x, y, r, null)
            
            loop
                
                set u=FirstOfGroup(ENUM_GROUP)
                exitwhen u==null
            
                    if (GetUnitState(u, UNIT_STATE_LIFE) > 0) and IsUnitEnemy(u, udg_BeamOwner[udg_BeamID]) and ( not ( GetUnitAbilityLevel(u, 'Avul') > 0 ))/*
                    */and ( not (GetUnitAbilityLevel(u, 'bvul') > 0))then
                
                        set fx = AddSpecialEffectTarget("Abilities\\Weapons\\CannonTowerMissile\\CannonTowerMissile.mdl", u, "origin")
                        call DestroyEffect (fx)
                    
                        //This is for picking both ground and flying units only, and checks if they meet the requirements to be added to udg_Beam_group1
                        if udg_BeamConfig_target_GROUND[udg_BeamID] == true and udg_BeamConfig_target_FLYING[udg_BeamID] == true then
                        
                            if udg_BeamConfig_target_HERO[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_HERO) then
                                call GroupAddUnit(udg_Beam_group1, u)
                            endif
                            
                            if udg_BeamConfig_target_ORGANIC[udg_BeamID] == true and not IsUnitType(u, UNIT_TYPE_MECHANICAL) then
                                call GroupAddUnit(udg_Beam_group1, u)
                            endif
                            
                            if udg_BeamConfig_target_MECHANICAL[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_MECHANICAL) then
                                call GroupAddUnit(udg_Beam_group1, u)
                            endif
                            
                            if udg_BeamConfig_target_STRUCTURE[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_STRUCTURE) then
                                call GroupAddUnit(udg_Beam_group1, u)
                            endif
                            
                            if udg_BeamConfig_target_ANCIENT[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_ANCIENT) then
                                call GroupAddUnit(udg_Beam_group1, u)
                            endif
                            
                            if udg_BeamConfig_target_MAGIC_IMMUNE[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) then
                                call GroupAddUnit(udg_Beam_group1, u)
                            endif
                            
                            if udg_BeamConfig_target_ETHEREAL[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_ETHEREAL) then
                                call GroupAddUnit(udg_Beam_group1, u)
                            endif
                            
                            if udg_BeamConfig_target_POLYMORPHED[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_POLYMORPHED) then
                                call GroupAddUnit(udg_Beam_group1, u)
                            endif
                            
                            if udg_BeamConfig_target_SLEEPING[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_SLEEPING) then
                                call GroupAddUnit(udg_Beam_group1, u)
                            endif
                            
                            if udg_BeamConfig_target_RESISTANT[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_RESISTANT) then
                                call GroupAddUnit(udg_Beam_group1, u)
                            endif
                            
                            if udg_BeamConfig_target_UNDEAD[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_UNDEAD) then
                                call GroupAddUnit(udg_Beam_group1, u)
                            endif
                            
                            if udg_BeamConfig_target_TAUREN[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_TAUREN) then
                                call GroupAddUnit(udg_Beam_group1, u)
                            endif
                        
                        else
                        
                            //This is for picking ground units only, and checks if they meet the requirements to be added to udg_Beam_group1
                            if udg_BeamConfig_target_GROUND[udg_BeamID] == true and udg_BeamConfig_target_FLYING[udg_BeamID] == false then
                            
                                if IsUnitType(u, UNIT_TYPE_GROUND) then
                                    
                                    if udg_BeamConfig_target_HERO[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_HERO) then
                                        call GroupAddUnit(udg_Beam_group1, u)
                                    endif
                                    
                                    if udg_BeamConfig_target_ORGANIC[udg_BeamID] == true and not IsUnitType(u, UNIT_TYPE_MECHANICAL) then
                                        call GroupAddUnit(udg_Beam_group1, u)
                                    endif
                                    
                                    if udg_BeamConfig_target_MECHANICAL[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_MECHANICAL) then
                                        call GroupAddUnit(udg_Beam_group1, u)
                                    endif
                                    
                                    if udg_BeamConfig_target_STRUCTURE[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_STRUCTURE) then
                                        call GroupAddUnit(udg_Beam_group1, u)
                                    endif
                                    
                                    if udg_BeamConfig_target_ANCIENT[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_ANCIENT) then
                                        call GroupAddUnit(udg_Beam_group1, u)
                                    endif
                                    
                                    if udg_BeamConfig_target_MAGIC_IMMUNE[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) then
                                        call GroupAddUnit(udg_Beam_group1, u)
                                    endif
                                    
                                    if udg_BeamConfig_target_ETHEREAL[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_ETHEREAL) then
                                        call GroupAddUnit(udg_Beam_group1, u)
                                    endif
                                    
                                    if udg_BeamConfig_target_POLYMORPHED[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_POLYMORPHED) then
                                        call GroupAddUnit(udg_Beam_group1, u)
                                    endif
                                    
                                    if udg_BeamConfig_target_SLEEPING[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_SLEEPING) then
                                        call GroupAddUnit(udg_Beam_group1, u)
                                    endif
                                    
                                    if udg_BeamConfig_target_RESISTANT[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_RESISTANT) then
                                        call GroupAddUnit(udg_Beam_group1, u)
                                    endif
                                    
                                    if udg_BeamConfig_target_UNDEAD[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_UNDEAD) then
                                        call GroupAddUnit(udg_Beam_group1, u)
                                    endif
                                    
                                    if udg_BeamConfig_target_TAUREN[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_TAUREN) then
                                        call GroupAddUnit(udg_Beam_group1, u)
                                    endif
                                    
                                endif //end ground comparison
                            
                            else //end ground booleans
                                
                                //This is for picking flying units only, and checks if they meet the requirements to be added to udg_Beam_group1
                                if udg_BeamConfig_target_GROUND[udg_BeamID] == false and udg_BeamConfig_target_FLYING[udg_BeamID] == true then
                                
                                    if IsUnitType(u, UNIT_TYPE_FLYING) then
                                        
                                        if udg_BeamConfig_target_HERO[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_HERO) then
                                            call GroupAddUnit(udg_Beam_group1, u)
                                        endif
                                        
                                        if udg_BeamConfig_target_ORGANIC[udg_BeamID] == true and not IsUnitType(u, UNIT_TYPE_MECHANICAL) then
                                            call GroupAddUnit(udg_Beam_group1, u)
                                        endif
                                        
                                        if udg_BeamConfig_target_MECHANICAL[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_MECHANICAL) then
                                            call GroupAddUnit(udg_Beam_group1, u)
                                        endif
                                        
                                        if udg_BeamConfig_target_STRUCTURE[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_STRUCTURE) then
                                            call GroupAddUnit(udg_Beam_group1, u)
                                        endif
                                        
                                        if udg_BeamConfig_target_ANCIENT[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_ANCIENT) then
                                            call GroupAddUnit(udg_Beam_group1, u)
                                        endif
                                        
                                        if udg_BeamConfig_target_MAGIC_IMMUNE[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) then
                                            call GroupAddUnit(udg_Beam_group1, u)
                                        endif
                                        
                                        if udg_BeamConfig_target_ETHEREAL[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_ETHEREAL) then
                                            call GroupAddUnit(udg_Beam_group1, u)
                                        endif
                                        
                                        if udg_BeamConfig_target_POLYMORPHED[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_POLYMORPHED) then
                                            call GroupAddUnit(udg_Beam_group1, u)
                                        endif
                                        
                                        if udg_BeamConfig_target_SLEEPING[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_SLEEPING) then
                                            call GroupAddUnit(udg_Beam_group1, u)
                                        endif
                                        
                                        if udg_BeamConfig_target_RESISTANT[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_RESISTANT) then
                                            call GroupAddUnit(udg_Beam_group1, u)
                                        endif
                                        
                                        if udg_BeamConfig_target_UNDEAD[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_UNDEAD) then
                                            call GroupAddUnit(udg_Beam_group1, u)
                                        endif
                                        
                                        if udg_BeamConfig_target_TAUREN[udg_BeamID] == true and IsUnitType(u, UNIT_TYPE_TAUREN) then
                                            call GroupAddUnit(udg_Beam_group1, u)
                                        endif
                                        
                                    endif //end flying comparision
                                
                                endif //end flying booleans
                                
                            endif
                        
                        endif //end ground and flying check
                    
                    endif //end filter
                    
                call GroupRemoveUnit(ENUM_GROUP, u)
                
            endloop
        
        set u = null
        //return false
        
        endmethod
    
    endstruct

endlibrary


EDIT 3: I tried adding a special effect to the filter and it showed up, so I guess the code is working, but my filtering method is bad.

EDIT 4: chaged to use FoG and tried to make the code a bit less retarded.
 
Last edited:
Level 36
Joined
Sep 26, 2009
Messages
8,444
!!!!! Spellbound, look what you have gotten into, here! It's just a beam, you don't need all types, just if the unit is an enemy, alive and if you use invisibility or invulnerability you can check for those (although the user shouldn't configure that, it should just be forced, since the damage is physical it need not worry about spell immune. Perhaps an ethereal check? It depends on what damage type you're using. Also, to make it look nice in GUI, don't use (matching conditions), just put your conditions in the ForGroup (pick all units).
 
So I'm attempting to optimise the performance on Persistent Beam and v1.9 will be free of any location variables and ForGroup calls, using instead x/y coordinates and FirstOfGroup will loops. Most of it works as required, but my tracking trigger is bugging out, and I can't figure out why.

  • Persistent Beam Tracking
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Custom script: local unit u
      • Custom script: local integer ID
      • Custom script: local real z1
      • Custom script: local real z2
      • Custom script: local real z3
      • Custom script: local real zInc
      • Custom script: local real xA
      • Custom script: local real yA
      • Custom script: local real xB
      • Custom script: local real yB
      • Custom script: local real xC
      • Custom script: local real yC
      • Custom script: local real xD
      • Custom script: local real yD
      • Custom script: local real xE
      • Custom script: local real yE
      • Custom script: local real angle
      • Custom script: local real dx
      • Custom script: local real dy
      • Custom script: local real distance
      • Custom script: local group grp1 = CreateGroup()
      • Custom script: local group grp2 = CreateGroup()
      • Custom script: local group grp3 = CreateGroup()
      • Custom script: local group grp4 = CreateGroup()
      • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
      • -------- Check if Beam_MainGroup is empty. If empty, turn this trigger off --------
      • Custom script: set u = FirstOfGroup(udg_Beam_MainGroup)
      • Custom script: if u == null then
      • Trigger - Turn off (This trigger)
      • Trigger - Turn off Persistent Beam Cancel A <gen>
      • Trigger - Turn off Persistent Beam Cancel B <gen>
      • Custom script: else
      • -------- --------
      • Custom script: set u = null
      • -------- Main loop --------
      • Custom script: loop
      • Custom script: set udg_Beamer = FirstOfGroup(udg_Beam_MainGroup)
      • Custom script: exitwhen udg_Beamer == null
      • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
      • Set BeamID = (Custom value of Beamer)
      • Set Beam_IntervalFX[BeamID] = (Beam_IntervalFX[BeamID] + 1)
      • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
      • Set GUCS_U = BeamTarget[BeamID]
      • Trigger - Run GetUnitCollisionSize <gen> (ignoring conditions)
      • Set Beam_ImpactOffset = GUCS_Size
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • GUCS_Size Greater than or equal to 144
        • Then - Actions
          • Set GUCS_Size = (GUCS_Size + (GUCS_Size / 2))
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • GUCS_Size Less than or equal to 2
            • Then - Actions
              • Set GUCS_Size = 12
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • GUCS_Size Less than or equal to 8
                • Then - Actions
                  • Set GUCS_Size = (GUCS_Size x 6)
                • Else - Actions
      • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
      • Custom script: set xA = GetUnitX(udg_Beamer)
      • Custom script: set yA = GetUnitY(udg_Beamer)
      • Custom script: set xB = GetUnitX(udg_BeamTarget[udg_BeamID])
      • Custom script: set yB = GetUnitY(udg_BeamTarget[udg_BeamID])
      • Custom script: set dx = xB-xA
      • Custom script: set dy = yB-yA
      • Custom script: set distance = SquareRoot(dx*dx+dy*dy)
      • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
      • Custom script: if (distance > (udg_BeamConfig_Range[udg_BeamID] + (udg_GUCS_Size * 2.00))) or (GetUnitState(udg_Beamer, UNIT_STATE_LIFE) <= 0) or (GetUnitAbilityLevel(udg_Beamer, 'BPSE') > 0) then
      • Set Beam_TerminateBeam[BeamID] = True
      • Custom script: endif
      • -------- ________________________________________ --------
      • -------- | | --------
      • -------- * * * * SWEEP BEAM --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • BeamConfig_SweepSpeed[BeamID] Greater than 0.00
        • Then - Actions
          • Custom script: set xC = GetUnitX(udg_BeamMover[udg_BeamID])
          • Custom script: set yC = GetUnitY(udg_BeamMover[udg_BeamID])
          • Custom script: set dx = xC-xB
          • Custom script: set dy = yC-yB
          • Custom script: set distance = SquareRoot(dx*dx+dy*dy)
          • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
          • Custom script: if distance > (udg_BeamConfig_SweepSpeed[udg_BeamID] / 33.00) then
          • Custom script: set angle = Atan2(yB-yC,xB-xC)
          • Custom script: set xD = xC + Cos(angle) * (udg_BeamConfig_SweepSpeed[udg_BeamID] / 33.00)
          • Custom script: set yD = yC + Sin(angle) * (udg_BeamConfig_SweepSpeed[udg_BeamID] / 33.00)
          • Custom script: else
          • Custom script: set xD = xB
          • Custom script: set yD = yB
          • Custom script: endif
          • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
          • Custom script: set angle = Atan2(yD-yA,xD-xA)
          • Custom script: call SetUnitPosition(udg_BeamMover[udg_BeamID], xD, yD)
          • Custom script: call SetUnitFacing(udg_BeamMover[udg_BeamID], angle * bj_RADTODEG)
        • Else - Actions
          • Custom script: set xD = xB
          • Custom script: set yD = yB
          • Custom script: set angle = Atan2(yA-yD,xA-xD)
          • Custom script: set xE = xD + Cos(angle) * (udg_Beam_ImpactOffset - (udg_Beam_ImpactOffset * 0.20))
          • Custom script: set yE = yD + Sin(angle) * (udg_Beam_ImpactOffset - (udg_Beam_ImpactOffset * 0.20))
          • Custom script: call SetUnitPosition(udg_BeamMover[udg_BeamID], xE, yE)
          • Custom script: call SetUnitFacing(udg_BeamMover[udg_BeamID], angle + 180)
      • Animation - Change BeamCaster[BeamID] flying height to ((Current flying height of Beamer) + BeamConfig_CasterHeight[BeamID]) at 0.00
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • BeamConfig_IsMoverGrounded[BeamID] Equal to False
        • Then - Actions
          • Custom script: set z1 = GetUnitFlyHeight(udg_BeamCaster[udg_BeamID])
          • Custom script: set z2 = GetUnitFlyHeight(udg_BeamMover[udg_BeamID])
          • Custom script: set z3 = GetUnitFlyHeight(udg_BeamTarget[udg_BeamID]) + 60
          • Custom script: set zInc = udg_BeamConfig_SweepSpeed[udg_BeamID] / 33
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • BeamConfig_SweepSpeed[BeamID] Greater than 0.00
            • Then - Actions
              • Custom script: if z2 < z3 then
              • Custom script: if z3 - z2 > (zInc) then
              • Custom script: call SetUnitFlyHeight(udg_BeamMover[udg_BeamID], z2 + zInc, 0)
              • Custom script: else
              • Custom script: call SetUnitFlyHeight(udg_BeamMover[udg_BeamID], z3, 0)
              • Custom script: endif
              • Custom script: else
              • Custom script: if z2 - z3 > (zInc) then
              • Custom script: call SetUnitFlyHeight(udg_BeamMover[udg_BeamID], z2 - zInc, 0)
              • Custom script: else
              • Custom script: call SetUnitFlyHeight(udg_BeamMover[udg_BeamID], z3, 0)
              • Custom script: endif
              • Custom script: endif
            • Else - Actions
              • Custom script: call SetUnitFlyHeight(udg_BeamMover[udg_BeamID], z3, 0)
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • BeamConfig_CasterOffset[BeamID] Greater than 0.00
        • Then - Actions
          • Custom script: set angle = Atan2(yD-yA,xD-xA) + (udg_BeamConfig_CasterAngle[udg_BeamID] * bj_DEGTORAD)
          • Custom script: set xC = xA + Cos(angle) * udg_BeamConfig_CasterOffset[udg_BeamID]
          • Custom script: set yC = yA + Sin(angle) * udg_BeamConfig_CasterOffset[udg_BeamID]
          • Custom script: set angle = Atan2(yD-yC,xD-xC)
          • Custom script: call SetUnitPosition(udg_BeamCaster[udg_BeamID], xC, yC)
          • Custom script: call SetUnitFacing(udg_BeamCaster[udg_BeamID], angle * bj_RADTODEG)
        • Else - Actions
          • Custom script: set angle = Atan2(yD-yA,xD-xA)
          • Custom script: call SetUnitPosition(udg_BeamCaster[udg_BeamID], xA, yA)
          • Custom script: call SetUnitFacing(udg_BeamCaster[udg_BeamID], angle * bj_RADTODEG)
      • Custom script: if udg_BeamLightning[udg_BeamID] != null then
      • Custom script: call MoveLightningEx(udg_BeamLightning[udg_BeamID], true, GetUnitX(udg_BeamCaster[udg_BeamID]), GetUnitY(udg_BeamCaster[udg_BeamID]), z1, GetUnitX(udg_BeamMover[udg_BeamID]), GetUnitY(udg_BeamMover[udg_BeamID]), z2)
      • Custom script: endif
      • -------- // END SWEEP BEAM --------
      • -------- [_______________________________________] --------
      • -------- --------
      • -------- --------
      • -------- --------
      • -------- ________________________________________ --------
      • -------- | | --------
      • -------- * * * * REACQUIRE TARGETING --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (BeamTarget[BeamID] is dead) Equal to True
        • Then - Actions
          • Custom script: call GroupEnumUnitsInRange(grp1, xA, yA, udg_BeamConfig_Range[udg_BeamID], null)
          • Custom script: call GroupEnumUnitsInRange(grp2, xD, yD, udg_BeamConfig_SweepAOE[udg_BeamID], null)
          • -------- -------- -------- -------- -------- --------
          • Custom script: loop
          • Custom script: set udg_BeamerPick = FirstOfGroup(grp1)
          • Custom script: exitwhen udg_BeamerPick == null
          • Custom script: if IsUnitInGroup(udg_BeamerPick,grp2) then
          • Custom script: call GroupAddUnit(grp3,udg_BeamerPick)
          • Custom script: endif
          • Custom script: call GroupRemoveUnit(grp1, udg_BeamerPick)
          • Custom script: endloop
          • -------- -------- -------- -------- -------- --------
          • Custom script: loop
          • Custom script: set udg_BeamerPick = FirstOfGroup(grp3)
          • Custom script: exitwhen udg_BeamerPick == null
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (BeamerPick is alive) Equal to True
              • (BeamerPick belongs to an enemy of BeamOwner[BeamID]) Equal to True
              • (BeamerPick has buff Invulnerable) Equal to False
              • (Level of Invulnerable (Neutral) for BeamerPick) Less than or equal to 0
            • Then - Actions
              • Unit - Order Beamer to Attack BeamerPick
              • Set BeamTarget[BeamID] = BeamerPick
              • Custom script: call GroupClear(grp3)
            • Else - Actions
              • Custom script: call GroupRemoveUnit(grp3, udg_BeamerPick)
              • Custom script: set udg_BeamerPick = FirstOfGroup(grp3)
              • Custom script: if udg_BeamerPick == null then
              • Custom script: set udg_Beam_TerminateBeam[udg_BeamID] = true
              • Custom script: endif
          • Custom script: endloop
          • -------- -------- -------- -------- -------- --------
          • Custom script: call DestroyGroup(grp3)
          • Custom script: call DestroyGroup(grp2)
          • Custom script: call DestroyGroup(grp1)
        • Else - Actions
      • -------- // END REACQUIRE TARGETING --------
      • -------- [_______________________________________] --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Beam_IsChargingDone[BeamID] Equal to False
        • Then - Actions
          • -------- ________________________________________ --------
          • -------- | | --------
          • -------- * * * * CHARGE-UP PHASE --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Beam_IntervalFX[BeamID] Greater than or equal to BeamConfig_IntervalFXLimit[BeamID]
            • Then - Actions
              • Special Effect - Create a special effect attached to the origin of BeamCaster[BeamID] using BeamConfig_ChargeUpFX[BeamID]
              • Special Effect - Destroy (Last created special effect)
              • Set Beam_IntervalFX[BeamID] = 0
            • Else - Actions
          • Set Beam_Interval[BeamID] = (Beam_Interval[BeamID] + 1)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Beam_Interval[BeamID] Greater than or equal to BeamConfig_ChargeLimit[BeamID]
            • Then - Actions
              • Set Beam_Interval[BeamID] = 0
              • Set Beam_IsChargingDone[BeamID] = True
              • Unit - Add BeamConfig_AbilityCasterFX[BeamID] to BeamCaster[BeamID]
              • Unit - Add BeamConfig_AbilityMoverFX[BeamID] to BeamMover[BeamID]
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • BeamConfig_BeamType[BeamID] Not equal to <Empty String>
                • Then - Actions
                  • Custom script: set udg_BeamLightning[udg_BeamID] = AddLightningEx(udg_BeamConfig_BeamType[udg_BeamID], true, GetUnitX(udg_BeamCaster[udg_BeamID]), GetUnitY(udg_BeamCaster[udg_BeamID]), z1, GetUnitX(udg_BeamMover[udg_BeamID]), GetUnitY(udg_BeamMover[udg_BeamID]), z2)
                • Else - Actions
              • Set Beam_Damage[BeamID] = ((Beam_DamageStack[BeamID] / (Real(Beam_HitStack[BeamID]))) / (Real(BeamConfig_HitsPerSecond[BeamID])))
              • Set Beam_HitStack[BeamID] = 0
              • Set Beam_DamageStack[BeamID] = 0.00
              • Set Beam_IntervalDPS[BeamID] = 0
            • Else - Actions
          • -------- // END CHARGE-UP --------
          • -------- [_______________________________________] --------
        • Else - Actions
          • -------- ________________________________________ --------
          • -------- | | --------
          • -------- * * * * DAMAGE PHASE --------
          • Set Beam_IntervalDPS[BeamID] = (Beam_IntervalDPS[BeamID] + 1)
          • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
          • -------- Calculate average damage --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Beam_IntervalDPS[BeamID] Greater than or equal to 132
            • Then - Actions
              • Set Beam_Damage[BeamID] = ((Beam_DamageStack[BeamID] / (Real(Beam_HitStack[BeamID]))) / (Real(BeamConfig_HitsPerSecond[BeamID])))
              • Set Beam_HitStack[BeamID] = 0
              • Set Beam_DamageStack[BeamID] = 0.00
              • Set Beam_IntervalDPS[BeamID] = 0
            • Else - Actions
          • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
          • Set Beam_IntervalDMG[BeamID] = (Beam_IntervalDMG[BeamID] + 1)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Beam_IntervalDMG[BeamID] Greater than or equal to Beam_IntervalDMGTrigger[BeamID]
            • Then - Actions
              • Set Beam_IntervalDMG[BeamID] = 0
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • BeamConfig_DamageAOE[BeamID] Greater than 0.00
                • Then - Actions
                  • Custom script: set xC = GetUnitX(udg_BeamMover[udg_BeamID])
                  • Custom script: set yC = GetUnitY(udg_BeamMover[udg_BeamID])
                  • Custom script: set xD = GetUnitX(udg_BeamTarget[udg_BeamID])
                  • Custom script: set yD = GetUnitY(udg_BeamTarget[udg_BeamID])
                  • -------- -------- -------- -------- -------- --------
                  • Custom script: if (distance <= udg_BeamConfig_DamageAOE[udg_BeamID]) and (IsUnitAlly(udg_BeamTarget[udg_BeamID], udg_BeamOwner[udg_BeamID])) then
                  • Set NextDamageType = BeamConfig_DamageType[BeamID]
                  • Unit - Cause Beamer to damage BeamTarget[BeamID], dealing Beam_Damage[BeamID] damage of attack type BeamConfig_AttackType[BeamID] and damage type Universal
                  • Trigger - Run ClearDamageEvent (checking conditions)
                  • Custom script: endif
                  • -------- -------- -------- -------- -------- --------
                  • Custom script: call GroupEnumUnitsInRange(grp1, xC, yC, udg_BeamConfig_DamageAOE[udg_BeamID], null)
                  • Custom script: loop
                  • Custom script: set udg_BeamerPick = FirstOfGroup(grp1)
                  • Custom script: exitwhen udg_BeamerPick == null
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (BeamerPick is alive) Equal to True
                      • (BeamerPick belongs to an enemy of BeamOwner[BeamID]) Equal to True
                      • (BeamerPick has buff Invulnerable) Equal to False
                      • (Level of Invulnerable (Neutral) for BeamerPick) Less than or equal to 0
                    • Then - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • BeamConfig_HitAll[BeamID] Equal to True
                        • Then - Actions
                          • Set NextDamageType = BeamConfig_DamageType[BeamID]
                          • Unit - Cause Beamer to damage BeamerPick, dealing Beam_Damage[BeamID] damage of attack type BeamConfig_AttackType[BeamID] and damage type Universal
                          • Trigger - Run ClearDamageEvent (checking conditions)
                        • Else - Actions
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • Or - Any (Conditions) are true
                                • Conditions
                                  • (BeamerPick is A ground unit) Equal to True
                                  • (BeamerPick is A structure) Equal to True
                              • Or - Any (Conditions) are true
                                • Conditions
                                  • (BeamTarget[BeamID] is A ground unit) Equal to True
                                  • (BeamTarget[BeamID] is A structure) Equal to True
                            • Then - Actions
                              • Set NextDamageType = BeamConfig_DamageType[BeamID]
                              • Unit - Cause Beamer to damage BeamerPick, dealing Beam_Damage[BeamID] damage of attack type BeamConfig_AttackType[BeamID] and damage type Universal
                              • Trigger - Run ClearDamageEvent (checking conditions)
                            • Else - Actions
                              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                • If - Conditions
                                  • (BeamerPick is A flying unit) Equal to True
                                  • (BeamTarget[BeamID] is A flying unit) Equal to True
                                • Then - Actions
                                  • Set NextDamageType = BeamConfig_DamageType[BeamID]
                                  • Unit - Cause Beamer to damage BeamerPick, dealing Beam_Damage[BeamID] damage of attack type BeamConfig_AttackType[BeamID] and damage type Universal
                                  • Trigger - Run ClearDamageEvent (checking conditions)
                                • Else - Actions
                    • Else - Actions
                  • Custom script: call GroupRemoveUnit(grp1, udg_BeamerPick)
                  • Custom script: endloop
                  • Custom script: call DestroyGroup(grp1)
                  • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
                • Else - Actions
                  • Set NextDamageType = BeamConfig_DamageType[BeamID]
                  • Unit - Cause Beamer to damage BeamTarget[BeamID], dealing Beam_Damage[BeamID] damage of attack type BeamConfig_AttackType[BeamID] and damage type Universal
                  • Trigger - Run ClearDamageEvent (checking conditions)
            • Else - Actions
          • -------- // END DAMAGE --------
          • -------- [_______________________________________] --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Beam_IntervalFX[BeamID] Greater than or equal to BeamConfig_IntervalFXLimit[BeamID]
            • Then - Actions
              • -------- ________________________________________ --------
              • -------- | | --------
              • -------- * * * * SPECIAL EFFECTS --------
              • Special Effect - Create a special effect attached to the origin of BeamCaster[BeamID] using BeamConfig_CasterPeriodicFX[BeamID]
              • Special Effect - Destroy (Last created special effect)
              • Special Effect - Create a special effect attached to the origin of BeamMover[BeamID] using BeamConfig_ImpactPeriodicFX[BeamID]
              • Special Effect - Destroy (Last created special effect)
              • Set Beam_IntervalFX[BeamID] = 0
              • -------- // END SPECIAL EFFECTS --------
              • -------- [_______________________________________] --------
            • Else - Actions
      • -------- ======================================================================== --------
      • -------- ======================================================================== --------
      • -------- if TERMINATE BEAM = TRUE --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Beam_TerminateBeam[BeamID] Equal to True
        • Then - Actions
          • Set Beam_Damage[BeamID] = 0.00
          • Set Beam_Interval[BeamID] = 0
          • Set Beam_IntervalDMG[BeamID] = 0
          • Set Beam_IntervalDPS[BeamID] = 0
          • Set Beam_IntervalFX[BeamID] = 0
          • Set Beam_HitStack[BeamID] = 0
          • Set Beam_DamageStack[BeamID] = 0.00
          • Unit - Unpause BeamCaster[BeamID]
          • Unit - Unpause BeamMover[BeamID]
          • Unit - Add a 0.01 second Generic expiration timer to BeamCaster[BeamID]
          • Unit - Add a 0.01 second Generic expiration timer to BeamMover[BeamID]
          • Set BeamSource[BeamID] = No unit
          • Set BeamTarget[BeamID] = No unit
          • Set BeamCaster[BeamID] = No unit
          • Custom script: if udg_BeamLightning[udg_BeamID] != null then
          • Custom script: call DestroyLightning(udg_BeamLightning[udg_BeamID])
          • Custom script: set udg_BeamLightning[udg_BeamID] = null
          • Custom script: endif
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • BeamConfig_IsImmobilised[BeamID] Equal to True
            • Then - Actions
              • Custom script: call SetUnitPropWindow(udg_Beamer, GetUnitDefaultPropWindow(udg_Beamer))
              • Set BeamConfig_IsImmobilised[BeamID] = False
            • Else - Actions
          • Set Beam_IsChargingDone[BeamID] = False
          • Set Beam_TerminateBeam[BeamID] = False
          • Set BeamMover[BeamID] = No unit
          • Set BeamStop[BeamID] = True
        • Else - Actions
      • Set BeamerPick = No unit
      • Custom script: call GroupAddUnit(grp4,udg_Beamer)
      • Custom script: call GroupRemoveUnit(udg_Beam_MainGroup,udg_Beamer)
      • Custom script: endloop
      • -------- --------
      • -------- Beamer is added to grp4 in the above loop and if BeamStop[BeamID] is FALSE, add Beamer back into Beam_MainGroup in the loop below --------
      • Custom script: loop
      • Custom script: set u = FirstOfGroup(grp4)
      • Custom script: exitwhen u == null
      • Custom script: set ID = GetUnitUserData(u)
      • Custom script: if udg_BeamStop[ID] == true then
      • Custom script: set udg_BeamStop[ID] = false
      • Custom script: else
      • Custom script: call GroupAddUnit(udg_Beam_MainGroup, u)
      • Custom script: call GroupRemoveUnit(grp4, u)
      • Custom script: endif
      • Custom script: endloop
      • Custom script: call DestroyGroup(grp4)
      • -------- --------
      • Custom script: endif
 
Level 36
Joined
Sep 26, 2009
Messages
8,444
I tried making sure the FoG loop looks good, I can't find any problems there. I've never seen that kind of FirstOfGroup implementation, though. It's kind of risky to have the GroupRemoveUnit way at the bottom in case you lose track of things. You can let it add to grp4 at the end, though, as that is fine.

Don't create 4 unit groups per 0.03 seconds. Just create 4 global groups in the variables list. udg_BeamTGrp1/2/3/4 perhaps. You never have to create or destroy those groups as they are automatically created by the InitGlobals call from the main function. As of now there is another issue in not switching to globals where you never destroy the group and that is that you destroy all 1/2/3 within the loop but you never re-create them for any consecutive iterations. Probably why it's bugging. Just switch to globals.
 
Ah, groups. Well, I did just switch over to globals and it's still bugging - one thing I noted is that calling DestroyGroup on the globals like I normally do after being done with a ForGroup was that the trigger just didn't work altogether (in Persistent Beam). I'm a bit confused as to the purpose of DestroyGroup at this point as it seems to do more harm than good outside of ForGroups. I have disabled the DestroyGroup calls and I've returned to a similar situation as before.

Bribe said:
As of now there is another issue in not switching to globals where you never destroy the group and that is that you destroy all 1/2/3 within the loop but you never re-create them for any consecutive iterations.

Oh, right. I forgot those were inside a loop. Does creating group have a lot of overhead?
 
Level 36
Joined
Sep 26, 2009
Messages
8,444
Creating a group doesn't need a lot of overhead, but when you know you're working with 4 groups throughout the gane which will never overwrite each other, they should be persistent globals. The only thing to do is make sure they are empty before using them for something new (which is done automatically when you do a GroupEnum... and also done when you do a FirstOfGroup loop due to the nature of how that works, with one exception and that is ghost references (not really an issue in this case).

I mainly use bj_wantDestroyGroup for my purposes. If I know I'll never use a group again, I might use DestroyGroup and null the global. In either case, there's pretty much never a need to in JASS to create a group that will need to get destroyed in the same thread.

What is bugging?
 
The only thing to do is make sure they are empty before using them for something new (which is done automatically when you do a GroupEnum...

Wait, really? so if I do call GroupEnumUnitsInRange(udg_Beam_group1, ... and immediately after I do call GroupEnumUnitsInRange(udg_Beam_group1,... again, does that mean that the first enumerations is removed from the group?

As for bj_wantDestroyGroup, the only context I know how to use it is to call it right before I do a 'Pick every unit in range' call to avoid a leak. Dunno how it would be used for GroupEnumUnitsInRange.

What is bugging?

Well, when I make a beamer attack for the first time, it does it without a hitch. When the beam is terminated, however, the beamer can't make a new beam. It's constantly being re-added to Beam_MainGroup even though BeamStop[BeamID] is true.
 
Right, triggers. The DestroyGroups are disabled in the map... so I guess I should remove them to avoid confusion.

  • Persistent Beam Tracking
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Custom script: local unit u
      • Custom script: local integer ID
      • Custom script: local real z1
      • Custom script: local real z2
      • Custom script: local real z3
      • Custom script: local real zInc
      • Custom script: local real xA
      • Custom script: local real yA
      • Custom script: local real xB
      • Custom script: local real yB
      • Custom script: local real xC
      • Custom script: local real yC
      • Custom script: local real xD
      • Custom script: local real yD
      • Custom script: local real xE
      • Custom script: local real yE
      • Custom script: local real angle
      • Custom script: local real dx
      • Custom script: local real dy
      • Custom script: local real distance
      • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
      • -------- Check if Beam_MainGroup is empty. If empty, turn this trigger off --------
      • Custom script: set u = FirstOfGroup(udg_Beam_MainGroup)
      • Custom script: if u == null then
      • Trigger - Turn off (This trigger)
      • Trigger - Turn off Persistent Beam Cancel A <gen>
      • Trigger - Turn off Persistent Beam Cancel B <gen>
      • Custom script: else
      • -------- --------
      • Custom script: set u = null
      • -------- Main loop --------
      • Custom script: loop
      • Custom script: set udg_Beamer = FirstOfGroup(udg_Beam_MainGroup)
      • Custom script: exitwhen udg_Beamer == null
      • Custom script: call GroupRemoveUnit(udg_Beam_MainGroup,udg_Beamer)
      • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
      • Set BeamID = (Custom value of Beamer)
      • Set Beam_IntervalFX[BeamID] = (Beam_IntervalFX[BeamID] + 1)
      • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
      • Set GUCS_U = BeamTarget[BeamID]
      • Trigger - Run GetUnitCollisionSize <gen> (ignoring conditions)
      • Set Beam_ImpactOffset = GUCS_Size
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • GUCS_Size Greater than or equal to 144
        • Then - Actions
          • Set GUCS_Size = (GUCS_Size + (GUCS_Size / 2))
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • GUCS_Size Less than or equal to 2
            • Then - Actions
              • Set GUCS_Size = 12
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • GUCS_Size Less than or equal to 8
                • Then - Actions
                  • Set GUCS_Size = (GUCS_Size x 6)
                • Else - Actions
      • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
      • Custom script: set xA = GetUnitX(udg_Beamer)
      • Custom script: set yA = GetUnitY(udg_Beamer)
      • Custom script: set xB = GetUnitX(udg_BeamTarget[udg_BeamID])
      • Custom script: set yB = GetUnitY(udg_BeamTarget[udg_BeamID])
      • Custom script: set dx = xB-xA
      • Custom script: set dy = yB-yA
      • Custom script: set distance = SquareRoot(dx*dx+dy*dy)
      • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
      • Custom script: if (distance > (udg_BeamConfig_Range[udg_BeamID] + (udg_GUCS_Size * 2.00))) or (GetUnitState(udg_Beamer, UNIT_STATE_LIFE) <= 0) or (GetUnitAbilityLevel(udg_Beamer, 'BPSE') > 0) then
      • Set Beam_TerminateBeam[BeamID] = True
      • Custom script: endif
      • -------- ________________________________________ --------
      • -------- | | --------
      • -------- * * * * SWEEP BEAM --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • BeamConfig_SweepSpeed[BeamID] Greater than 0.00
        • Then - Actions
          • Custom script: set xC = GetUnitX(udg_BeamMover[udg_BeamID])
          • Custom script: set yC = GetUnitY(udg_BeamMover[udg_BeamID])
          • Custom script: set dx = xC-xB
          • Custom script: set dy = yC-yB
          • Custom script: set distance = SquareRoot(dx*dx+dy*dy)
          • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
          • Custom script: if distance > (udg_BeamConfig_SweepSpeed[udg_BeamID] / 33.00) then
          • Custom script: set angle = Atan2(yB-yC,xB-xC)
          • Custom script: set xD = xC + Cos(angle) * (udg_BeamConfig_SweepSpeed[udg_BeamID] / 33.00)
          • Custom script: set yD = yC + Sin(angle) * (udg_BeamConfig_SweepSpeed[udg_BeamID] / 33.00)
          • Custom script: else
          • Custom script: set xD = xB
          • Custom script: set yD = yB
          • Custom script: endif
          • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
          • Custom script: set angle = Atan2(yD-yA,xD-xA)
          • Custom script: call SetUnitPosition(udg_BeamMover[udg_BeamID], xD, yD)
          • Custom script: call SetUnitFacing(udg_BeamMover[udg_BeamID], angle * bj_RADTODEG)
        • Else - Actions
          • Custom script: set xD = xB
          • Custom script: set yD = yB
          • Custom script: set angle = Atan2(yA-yD,xA-xD)
          • Custom script: set xE = xD + Cos(angle) * (udg_Beam_ImpactOffset - (udg_Beam_ImpactOffset * 0.20))
          • Custom script: set yE = yD + Sin(angle) * (udg_Beam_ImpactOffset - (udg_Beam_ImpactOffset * 0.20))
          • Custom script: call SetUnitPosition(udg_BeamMover[udg_BeamID], xE, yE)
          • Custom script: call SetUnitFacing(udg_BeamMover[udg_BeamID], angle + 180)
      • Animation - Change BeamCaster[BeamID] flying height to ((Current flying height of Beamer) + BeamConfig_CasterHeight[BeamID]) at 0.00
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • BeamConfig_IsMoverGrounded[BeamID] Equal to False
        • Then - Actions
          • Custom script: set z1 = GetUnitFlyHeight(udg_BeamCaster[udg_BeamID])
          • Custom script: set z2 = GetUnitFlyHeight(udg_BeamMover[udg_BeamID])
          • Custom script: set z3 = GetUnitFlyHeight(udg_BeamTarget[udg_BeamID]) + 60
          • Custom script: set zInc = udg_BeamConfig_SweepSpeed[udg_BeamID] / 33
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • BeamConfig_SweepSpeed[BeamID] Greater than 0.00
            • Then - Actions
              • Custom script: if z2 < z3 then
              • Custom script: if z3 - z2 > (zInc) then
              • Custom script: call SetUnitFlyHeight(udg_BeamMover[udg_BeamID], z2 + zInc, 0)
              • Custom script: else
              • Custom script: call SetUnitFlyHeight(udg_BeamMover[udg_BeamID], z3, 0)
              • Custom script: endif
              • Custom script: else
              • Custom script: if z2 - z3 > (zInc) then
              • Custom script: call SetUnitFlyHeight(udg_BeamMover[udg_BeamID], z2 - zInc, 0)
              • Custom script: else
              • Custom script: call SetUnitFlyHeight(udg_BeamMover[udg_BeamID], z3, 0)
              • Custom script: endif
              • Custom script: endif
            • Else - Actions
              • Custom script: call SetUnitFlyHeight(udg_BeamMover[udg_BeamID], z3, 0)
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • BeamConfig_CasterOffset[BeamID] Greater than 0.00
        • Then - Actions
          • Custom script: set angle = Atan2(yD-yA,xD-xA) + (udg_BeamConfig_CasterAngle[udg_BeamID] * bj_DEGTORAD)
          • Custom script: set xC = xA + Cos(angle) * udg_BeamConfig_CasterOffset[udg_BeamID]
          • Custom script: set yC = yA + Sin(angle) * udg_BeamConfig_CasterOffset[udg_BeamID]
          • Custom script: set angle = Atan2(yD-yC,xD-xC)
          • Custom script: call SetUnitPosition(udg_BeamCaster[udg_BeamID], xC, yC)
          • Custom script: call SetUnitFacing(udg_BeamCaster[udg_BeamID], angle * bj_RADTODEG)
        • Else - Actions
          • Custom script: set angle = Atan2(yD-yA,xD-xA)
          • Custom script: call SetUnitPosition(udg_BeamCaster[udg_BeamID], xA, yA)
          • Custom script: call SetUnitFacing(udg_BeamCaster[udg_BeamID], angle * bj_RADTODEG)
      • Custom script: if udg_BeamLightning[udg_BeamID] != null then
      • Custom script: call MoveLightningEx(udg_BeamLightning[udg_BeamID], true, GetUnitX(udg_BeamCaster[udg_BeamID]), GetUnitY(udg_BeamCaster[udg_BeamID]), z1, GetUnitX(udg_BeamMover[udg_BeamID]), GetUnitY(udg_BeamMover[udg_BeamID]), z2)
      • Custom script: endif
      • -------- // END SWEEP BEAM --------
      • -------- [_______________________________________] --------
      • -------- --------
      • -------- --------
      • -------- --------
      • -------- ________________________________________ --------
      • -------- | | --------
      • -------- * * * * REACQUIRE TARGETING --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (BeamTarget[BeamID] is dead) Equal to True
        • Then - Actions
          • Custom script: call GroupEnumUnitsInRange(udg_Beam_group1, xA, yA, udg_BeamConfig_Range[udg_BeamID], null)
          • Custom script: call GroupEnumUnitsInRange(udg_Beam_group2, xD, yD, udg_BeamConfig_SweepAOE[udg_BeamID], null)
          • -------- -------- -------- -------- -------- --------
          • Custom script: loop
          • Custom script: set udg_BeamerPick = FirstOfGroup(udg_Beam_group1)
          • Custom script: exitwhen udg_BeamerPick == null
          • Custom script: if IsUnitInGroup(udg_BeamerPick,udg_Beam_group2) then
          • Custom script: call GroupAddUnit(udg_Beam_group3,udg_BeamerPick)
          • Custom script: endif
          • Custom script: call GroupRemoveUnit(udg_Beam_group1, udg_BeamerPick)
          • Custom script: endloop
          • -------- -------- -------- -------- -------- --------
          • Custom script: loop
          • Custom script: set udg_BeamerPick = FirstOfGroup(udg_Beam_group3)
          • Custom script: exitwhen udg_BeamerPick == null
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (BeamerPick is alive) Equal to True
              • (BeamerPick belongs to an enemy of BeamOwner[BeamID]) Equal to True
              • (BeamerPick has buff Invulnerable) Equal to False
              • (Level of Invulnerable (Neutral) for BeamerPick) Less than or equal to 0
            • Then - Actions
              • Unit - Order Beamer to Attack BeamerPick
              • Set BeamTarget[BeamID] = BeamerPick
              • Custom script: call GroupClear(udg_Beam_group3)
            • Else - Actions
              • Custom script: call GroupRemoveUnit(udg_Beam_group3, udg_BeamerPick)
              • Custom script: set udg_BeamerPick = FirstOfGroup(udg_Beam_group3)
              • Custom script: if udg_BeamerPick == null then
              • Custom script: set udg_Beam_TerminateBeam[udg_BeamID] = true
              • Custom script: endif
          • Custom script: endloop
        • Else - Actions
      • -------- // END REACQUIRE TARGETING --------
      • -------- [_______________________________________] --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Beam_IsChargingDone[BeamID] Equal to False
        • Then - Actions
          • -------- ________________________________________ --------
          • -------- | | --------
          • -------- * * * * CHARGE-UP PHASE --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Beam_IntervalFX[BeamID] Greater than or equal to BeamConfig_IntervalFXLimit[BeamID]
            • Then - Actions
              • Special Effect - Create a special effect attached to the origin of BeamCaster[BeamID] using BeamConfig_ChargeUpFX[BeamID]
              • Special Effect - Destroy (Last created special effect)
              • Set Beam_IntervalFX[BeamID] = 0
            • Else - Actions
          • Set Beam_Interval[BeamID] = (Beam_Interval[BeamID] + 1)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Beam_Interval[BeamID] Greater than or equal to BeamConfig_ChargeLimit[BeamID]
            • Then - Actions
              • Set Beam_Interval[BeamID] = 0
              • Set Beam_IsChargingDone[BeamID] = True
              • Unit - Add BeamConfig_AbilityCasterFX[BeamID] to BeamCaster[BeamID]
              • Unit - Add BeamConfig_AbilityMoverFX[BeamID] to BeamMover[BeamID]
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • BeamConfig_BeamType[BeamID] Not equal to <Empty String>
                • Then - Actions
                  • Custom script: set udg_BeamLightning[udg_BeamID] = AddLightningEx(udg_BeamConfig_BeamType[udg_BeamID], true, GetUnitX(udg_BeamCaster[udg_BeamID]), GetUnitY(udg_BeamCaster[udg_BeamID]), z1, GetUnitX(udg_BeamMover[udg_BeamID]), GetUnitY(udg_BeamMover[udg_BeamID]), z2)
                • Else - Actions
              • Set Beam_Damage[BeamID] = ((Beam_DamageStack[BeamID] / (Real(Beam_HitStack[BeamID]))) / (Real(BeamConfig_HitsPerSecond[BeamID])))
              • Set Beam_HitStack[BeamID] = 0
              • Set Beam_DamageStack[BeamID] = 0.00
              • Set Beam_IntervalDPS[BeamID] = 0
            • Else - Actions
          • -------- // END CHARGE-UP --------
          • -------- [_______________________________________] --------
        • Else - Actions
          • -------- ________________________________________ --------
          • -------- | | --------
          • -------- * * * * DAMAGE PHASE --------
          • Set Beam_IntervalDPS[BeamID] = (Beam_IntervalDPS[BeamID] + 1)
          • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
          • -------- Calculate average damage --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Beam_IntervalDPS[BeamID] Greater than or equal to 132
            • Then - Actions
              • Set Beam_Damage[BeamID] = ((Beam_DamageStack[BeamID] / (Real(Beam_HitStack[BeamID]))) / (Real(BeamConfig_HitsPerSecond[BeamID])))
              • Set Beam_HitStack[BeamID] = 0
              • Set Beam_DamageStack[BeamID] = 0.00
              • Set Beam_IntervalDPS[BeamID] = 0
            • Else - Actions
          • -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
          • Set Beam_IntervalDMG[BeamID] = (Beam_IntervalDMG[BeamID] + 1)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Beam_IntervalDMG[BeamID] Greater than or equal to Beam_IntervalDMGTrigger[BeamID]
            • Then - Actions
              • Set Beam_IntervalDMG[BeamID] = 0
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • BeamConfig_DamageAOE[BeamID] Greater than 0.00
                • Then - Actions
                  • Custom script: set xC = GetUnitX(udg_BeamMover[udg_BeamID])
                  • Custom script: set yC = GetUnitY(udg_BeamMover[udg_BeamID])
                  • Custom script: set xD = GetUnitX(udg_BeamTarget[udg_BeamID])
                  • Custom script: set yD = GetUnitY(udg_BeamTarget[udg_BeamID])
                  • -------- -------- -------- -------- -------- --------
                  • Custom script: if (distance <= udg_BeamConfig_DamageAOE[udg_BeamID]) and (IsUnitAlly(udg_BeamTarget[udg_BeamID], udg_BeamOwner[udg_BeamID])) then
                  • Set NextDamageType = BeamConfig_DamageType[BeamID]
                  • Unit - Cause Beamer to damage BeamTarget[BeamID], dealing Beam_Damage[BeamID] damage of attack type BeamConfig_AttackType[BeamID] and damage type Universal
                  • Trigger - Run ClearDamageEvent (checking conditions)