• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Solved] Why isnt my Infinite and Instant chain lightning trigger not actually infinite?

Status
Not open for further replies.
Level 2
Joined
Dec 29, 2017
Messages
16
Hey again~

I have a trigger that spawns a dummy caster at targeted unit whenever a (Previous) dummy unit casts chain lightning, and then that dummy unit is ordered to cast chain lightning at a random unit around him, checking for enemy and and dead units. (Once the initial chain lighting is cast, an expiration timer is set on that unit)

The result is a near instant chain of lighting that infinitely loops until everything is dead... except its not actually infinite...?

It just randomly stops, and my dummy caster doesn't actually get issued an order to cast an ability. (Or maybe it does and targets something I'm not aware of?) and the strangest thing, if I cast it again, it may bounce one or two times, and thats it. It completely breaks, even when there are several units in range. The most times I have seen it chain is maybe 25 times, and then it stops and breaks!

Is it possible to create an infinite chain lighting? (At least until everything is dead anyways) is this a limitation or is there an oversight i need to be aware of?

Trigger Below:
  • cl2
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Instant Chain Lightning
    • Actions
      • Set Dummy_Chain_Lightning_TARGET = (Target unit of ability being cast)
      • Unit - Add a 0.02 second Generic expiration timer to (Triggering unit)
      • Unit - Create 1 Dummy Caster for Player 1 (Red) at (Position of Dummy_Chain_Lightning_TARGET) facing (Facing of Dummy_Chain_Lightning_TARGET) degrees
      • Unit - Cause (Triggering unit) to damage (Target unit of ability being cast), dealing 50.00 damage of attack type Spells and damage type Normal
      • Set Dummy_Chain_Lightning = (Last created unit)
      • Unit Group - Pick every unit in (Units within 512.00 of (Position of Dummy_Chain_Lightning_TARGET)) and do (Unit Group - Add (Picked unit) to Tempgroup)
      • Unit Group - Remove all units of (Units owned by Player 1 (Red)) from Tempgroup
      • Unit Group - Pick every unit in Tempgroup and do (Actions)
        • Loop - Actions
          • If (((Picked unit) is dead) Equal to True) then do (Unit Group - Remove (Matching unit) from Tempgroup) else do (Do nothing)
      • Unit - Order Dummy_Chain_Lightning to Orc Far Seer - Chain Lightning (Random unit from Tempgroup)

I would love any input on this, it would be a key mechanic in a campaign I'm making if its possible. And if anyone would like a test map, just let me know and I'll arrange one for you guys to tinker with!
 
Last edited:
Level 5
Joined
Jul 27, 2017
Messages
73
I´m not 100% sure but i think that this line isn´t correct:
If (((Picked unit) is dead) Equal to True) then do (Unit Group - Remove (Matching unit) from Tempgroup) else do (Do nothing)

It should be: Remove (Picked unit)
--> If i see it correctly: Matching unit is only used if you use something like "Unit Group - Pick every unit in (Unitgroup) matching (condition)"
So the dead units aren´t really removed and can still be the target of the ability which will never be casted.

I hope i helped and didn´t made any mistakes.
 
Try these tags for your triggers: [trigger][/trigger]

_________________________

Let's see here: (Translated from GUI)

JASS:
function Trig_cl2_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == CHAIN_ID ) ) then
        return false
    endif
    return true
endfunction

function Trig_cl2_1000_Actions takes nothing returns nothing
    call GroupAddUnitSimple(GetEnumUnit(), udg_Tempgroup)
endfunction

function Trig_cl2_2000_Actions takes nothing returns nothing
    call GroupRemoveUnitSimple(GetEnumUnit(), udg_Tempgroup)
endfunction

function Trig_cl2_3000_Actions takes nothing returns nothing
    if (not ( not (IsUnitDeadBJ(GetEnumUnit())))) then
        call GroupRemoveUnitSimple(GetFilterUnit(), udg_Tempgroup)
    endif
endfunction

function Trig_cl2_Actions takes nothing returns nothing
    set udg_Dummy_Chain_Lightning_TARGET = GetSpellTargetUnit()
    call UnitApplyTimedLife(GetTriggerUnit(), 'BTLF', 0.02)
    call CreateNUnitsAtLoc(1, DUMMY_CASTER, Player(0), GetUnitLoc(udg_Dummy_Chain_Lightning_TARGET), GetUnitFacing(udg_Dummy_Chain_Lightning_TARGET))
    call UnitDamageTargetBJ(GetTriggerUnit(), GetSpellTargetUnit(), 50., ATTACK_TYPE_SPELLS, DAMAGE_TYPE_NORMAL)
    set udg_Dummy_Chain_Lightning = GetLastCreatedUnit()
    call ForGroupBJ(GetUnitsInRangeOfLocAll(512.00, GetUnitLoc(udg_Dummy_Chain_Lightning_TARGET)), function Trig_cl2_1000_Actions)
    call ForGroupBJ(GetUnitsOfPlayerAll(Player(0)), function Trig_cl2_2000_Actions)
    call ForGroupBJ(udg_Tempgroup, function Trig_cl2_3000_Actions)
    call IssueTargetOrderBJ(udg_Dummy_Chain_Lightning, GroupPickRandomUnit(udg_Tempgroup))
endfunction

function InitTrig_cl2 takes nothing returns nothing
    set gg_trg_cl2 = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ(gg_trg_cl2, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(gg_trg_cl2, Condition(function Trig_cl2_Conditions))
    call TriggerAddAction(gg_trg_cl2, function Trig_cl2_Actions)
endfunction

Now let's look at the main Actions function, (Just look at the commentary):

JASS:
function Trig_cl2_Actions takes nothing returns nothing
    // Looks like we're setting udg_Dummy_Chain_Lightning_TARGET to the target of the spell, nothing wrong here.
    set udg_Dummy_Chain_Lightning_TARGET = GetSpellTargetUnit()

    // The triggering unit is the caster of the spell, nothing wrong here.
    call UnitApplyTimedLife(GetTriggerUnit(), 'BTLF', 0.02)

    // Now, we're creating a new dummy caster at the location of the target.
    // Examining leaks:
    //      GetUnitLoc(unit u) returns location
    //      - Returns a location handle mapped to the unit. (Leak 1)
    call CreateNUnitsAtLoc(1, DUMMY_CASTER, Player(0), GetUnitLoc(udg_Dummy_Chain_Lightning_TARGET), GetUnitFacing(udg_Dummy_Chain_Lightning_TARGET))

    // Looks like we're damaging the target. 1 leak still exists.
    // Optimization:
    //      GetSpellTargetUnit has already been called once, look above.
    //      We can refer to the variable above instead.
  
    //      GetTriggerUnit has been called again.
    //      One more call and it gets a variable.
    call UnitDamageTargetBJ(GetTriggerUnit(), GetSpellTargetUnit(), 50., ATTACK_TYPE_SPELLS, DAMAGE_TYPE_NORMAL)
  
    // Assigning the variable udg_Dummy_Chain_Lightning to the last created unit.
    set udg_Dummy_Chain_Lightning = GetLastCreatedUnit()
  
    // Now, here's the juicy part.
    // We're enumerating every unit within range.
    // Examining leaks:
    //      GetUnitsInRangeOfLocAll(real r, location loc) returns group
    //      - Returns a group that has already included the units within the range of the location. (Leak 2)
  
    //      GetUnitLoc(unit u) returns location (Leak 3)
  
    // Optimization:
    // Use custom script and set bj_wantDestroyGroup to true.
    // Custom Script: set bj_wantDestroyGroup = true
  
    // Try to remove the location after by setting a temporary variable to it and calling RemoveLocation in custom script.
    // Global variables start with an udg_<varName>
    call ForGroupBJ(GetUnitsInRangeOfLocAll(512.00, GetUnitLoc(udg_Dummy_Chain_Lightning_TARGET)), function Trig_cl2_1000_Actions)
  
    // Now, we check if there are units of player 1 and remove them from the group
    // Examining leaks:
    //      GetUnitsOfPlayerAll(player p) returns group
    //      - Returns a group that has already included the units of a certain player. (Groups when created don't have any units at first) (Leak 4)
  
    // Optimization:
    //      set bj_wantDestroyGroup = true
    call ForGroupBJ(GetUnitsOfPlayerAll(Player(0)), function Trig_cl2_2000_Actions)
  
    // We also remove those in the group that are already dead.
    call ForGroupBJ(udg_Tempgroup, function Trig_cl2_3000_Actions)

    // We then issue another chain lightning.
    call IssueTargetOrderBJ(udg_Dummy_Chain_Lightning, "chainlightning", GroupPickRandomUnit(udg_Tempgroup))

    // After this, we are left with a group (udg_Tempgroup) with a load of enemy units and allied units.
    // Since it hasn't been filtered out in the previous ForGroupBJ call, the IssueTargetOrderBJ function may return false
    // On top of that, this creates 4 leaks, which can be drastic in the late game if not cleaned up.
endfunction

Now, let's look at the auxiliary actions.

JASS:
function Trig_cl2_1000_Actions takes nothing returns nothing
    // Adds a unit to the udg_Tempgroup if it has not been added already.
    call GroupAddUnitSimple(GetEnumUnit(), udg_Tempgroup)
endfunction

function Trig_cl2_2000_Actions takes nothing returns nothing
    // From the filter portion removing Player 1 units from the Tempgroup
    call GroupRemoveUnitSimple(GetEnumUnit(), udg_Tempgroup)
endfunction

function Trig_cl2_3000_Actions takes nothing returns nothing
    // Now, we consider if the picked unit is dead.
    // Picked unit == GetEnumUnit()
    if (not ( not (IsUnitDeadBJ(GetEnumUnit())))) then
        // As pointed above, matching unit does not equal picked unit. Consequently, Matching unit == GetFilterUnit()
        // Ergo, GetFilterUnit should be replaced with GetEnumUnit or Matching unit with Picked unit
        // Credits to Gauda
        call GroupRemoveUnitSimple(GetFilterUnit(), udg_Tempgroup)
    endif
endfunction

There are certain problems with the logic of the actions trigger itself, mainly that it does not consider filtering out allies before selecting a random unit in the tempgroup (Chain lightning usually requires that the targets are enemies, and are valid targets at that) and the numerous amount of leaks.


Now, it has been reported that 4 leaks will be generated, that is, generated objects that can no longer be accessed by memory. This can cause problems late in the game as the server client will have to deal with updating an increasing amount of data that never gets deallocated (can't find the right time). To resolve that issue, one must remove the leaks. (Try to find memory leak threads in the HIVE)




Assume that at the start of the lightning chain, the tempgroup is initially empty. After the first iteration, the tempgroup should be filled with targets. One can make it so that the tempgroup gets all relevant units (viable enemy targets) and removes the irrelevant units (viable enemy targets but dead or far away and not viable targets) so that the issued order succeeds.

- As such, the implementation is that we get units within 512 units away from the desired location and add them to the group if they are viable targets.
- After that, we remove the units in the tempgroup which are not viable targets.

This will guarantee that the issued order is a success.

Result: From three ForGroupBJ calls to two ForGroupBJ calls (for better or worse).

Now, assuming that the cooldown of the dummy spell is 0, and manacost is 0, the creation and destruction of dummy units would turn out to be a waste. Instead, we can store an initialized dummy unit with the ability and change its' player attributes at will.



I hope that wasn't too much to read. Also, I would like to state that the manner in which I explain these things are not meant to be taken offensively.

Cheers!
 
Last edited:
Level 2
Joined
Dec 29, 2017
Messages
16
Try these tags for your triggers: [trigger][/trigger]

_________________________

Let's see here: (Translated from GUI)

JASS:
function Trig_cl2_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == CHAIN_ID ) ) then
        return false
    endif
    return true
endfunction

function Trig_cl2_1000_Actions takes nothing returns nothing
    call GroupAddUnitSimple(GetEnumUnit(), udg_Tempgroup)
endfunction

function Trig_cl2_2000_Actions takes nothing returns nothing
    call GroupRemoveUnitSimple(GetEnumUnit(), udg_Tempgroup)
endfunction

function Trig_cl2_3000_Actions takes nothing returns nothing
    if (not ( not (IsUnitDeadBJ(GetEnumUnit())))) then
        call GroupRemoveUnitSimple(GetFilterUnit(), udg_Tempgroup)
    endif
endfunction

function Trig_cl2_Actions takes nothing returns nothing
    set udg_Dummy_Chain_Lightning_TARGET = GetSpellTargetUnit()
    call UnitApplyTimedLife(GetTriggerUnit(), 'BTLF', 0.02)
    call CreateNUnitsAtLoc(1, DUMMY_CASTER, Player(0), GetUnitLoc(udg_Dummy_Chain_Lightning_TARGET), GetUnitFacing(udg_Dummy_Chain_Lightning_TARGET))
    call UnitDamageTargetBJ(GetTriggerUnit(), GetSpellTargetUnit(), 50., ATTACK_TYPE_SPELLS, DAMAGE_TYPE_NORMAL)
    set udg_Dummy_Chain_Lightning = GetLastCreatedUnit()
    call ForGroupBJ(GetUnitsInRangeOfLocAll(512.00, GetUnitLoc(udg_Dummy_Chain_Lightning_TARGET)), function Trig_cl2_1000_Actions)
    call ForGroupBJ(GetUnitsOfPlayerAll(Player(0)), function Trig_cl2_2000_Actions)
    call ForGroupBJ(udg_Tempgroup, function Trig_cl2_3000_Actions)
    call IssueTargetOrderBJ(udg_Dummy_Chain_Lightning, GroupPickRandomUnit(udg_Tempgroup))
endfunction

function InitTrig_cl2 takes nothing returns nothing
    set gg_trg_cl2 = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ(gg_trg_cl2, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(gg_trg_cl2, Condition(function Trig_cl2_Conditions))
    call TriggerAddAction(gg_trg_cl2, function Trig_cl2_Actions)
endfunction

Now let's look at the main Actions function, (Just look at the commentary):

JASS:
function Trig_cl2_Actions takes nothing returns nothing
    // Looks like we're setting udg_Dummy_Chain_Lightning_TARGET to the target of the spell, nothing wrong here.
    set udg_Dummy_Chain_Lightning_TARGET = GetSpellTargetUnit()

    // The triggering unit is the caster of the spell, nothing wrong here.
    call UnitApplyTimedLife(GetTriggerUnit(), 'BTLF', 0.02)

    // Now, we're creating a new dummy caster at the location of the target.
    // Examining leaks:
    //      GetUnitLoc(unit u) returns location
    //      - Returns a location handle mapped to the unit. (Leak 1)
    call CreateNUnitsAtLoc(1, DUMMY_CASTER, Player(0), GetUnitLoc(udg_Dummy_Chain_Lightning_TARGET), GetUnitFacing(udg_Dummy_Chain_Lightning_TARGET))

    // Looks like we're damaging the target. 1 leak still exists.
    // Optimization:
    //      GetSpellTargetUnit has already been called once, look above.
    //      We can refer to the variable above instead.
 
    //      GetTriggerUnit has been called again.
    //      One more call and it gets a variable.
    call UnitDamageTargetBJ(GetTriggerUnit(), GetSpellTargetUnit(), 50., ATTACK_TYPE_SPELLS, DAMAGE_TYPE_NORMAL)
 
    // Assigning the variable udg_Dummy_Chain_Lightning to the last created unit.
    set udg_Dummy_Chain_Lightning = GetLastCreatedUnit()
 
    // Now, here's the juicy part.
    // We're enumerating every unit within range.
    // Examining leaks:
    //      GetUnitsInRangeOfLocAll(real r, location loc) returns group
    //      - Returns a group that has already included the units within the range of the location. (Leak 2)
 
    //      GetUnitLoc(unit u) returns location (Leak 3)
 
    // Optimization:
    // Use custom script and set bj_wantDestroyGroup to true.
    // Custom Script: set bj_wantDestroyGroup = true
 
    // Try to remove the location after by setting a temporary variable to it and calling RemoveLocation in custom script.
    // Global variables start with an udg_<varName>
    call ForGroupBJ(GetUnitsInRangeOfLocAll(512.00, GetUnitLoc(udg_Dummy_Chain_Lightning_TARGET)), function Trig_cl2_1000_Actions)
 
    // Now, we check if there are units of player 1 and remove them from the group
    // Examining leaks:
    //      GetUnitsOfPlayerAll(player p) returns group
    //      - Returns a group that has already included the units of a certain player. (Groups when created don't have any units at first) (Leak 4)
 
    // Optimization:
    //      set bj_wantDestroyGroup = true
    call ForGroupBJ(GetUnitsOfPlayerAll(Player(0)), function Trig_cl2_2000_Actions)
 
    // We also remove those in the group that are already dead.
    call ForGroupBJ(udg_Tempgroup, function Trig_cl2_3000_Actions)

    // We then issue another chain lightning.
    call IssueTargetOrderBJ(udg_Dummy_Chain_Lightning, "chainlightning", GroupPickRandomUnit(udg_Tempgroup))

    // After this, we are left with a group (udg_Tempgroup) with a load of enemy units and allied units.
    // Since it hasn't been filtered out in the previous ForGroupBJ call, the IssueTargetOrderBJ function may return false
    // On top of that, this creates 4 leaks, which can be drastic in the late game if not cleaned up.
endfunction

Now, let's look at the auxiliary actions.

JASS:
function Trig_cl2_1000_Actions takes nothing returns nothing
    // Adds a unit to the udg_Tempgroup if it has not been added already.
    call GroupAddUnitSimple(GetEnumUnit(), udg_Tempgroup)
endfunction

function Trig_cl2_2000_Actions takes nothing returns nothing
    // From the filter portion removing Player 1 units from the Tempgroup
    call GroupRemoveUnitSimple(GetEnumUnit(), udg_Tempgroup)
endfunction

function Trig_cl2_3000_Actions takes nothing returns nothing
    // Now, we consider if the picked unit is dead.
    // Picked unit == GetEnumUnit()
    if (not ( not (IsUnitDeadBJ(GetEnumUnit())))) then
        // As pointed above, matching unit does not equal picked unit. Consequently, Matching unit == GetFilterUnit()
        // Ergo, GetFilterUnit should be replaced with GetEnumUnit or Matching unit with Picked unit
        // Credits to Gauda
        call GroupRemoveUnitSimple(GetFilterUnit(), udg_Tempgroup)
    endif
endfunction

There are certain problems with the logic of the actions trigger itself, mainly that it does not consider filtering out allies before selecting a random unit in the tempgroup (Chain lightning usually requires that the targets are enemies, and are valid targets at that) and the numerous amount of leaks.


Now, it has been reported that 4 leaks will be generated, that is, generated objects that can no longer be accessed by memory. This can cause problems late in the game as the server client will have to deal with updating an increasing amount of data that never gets deallocated (can't find the right time). To resolve that issue, one must remove the leaks. (Try to find memory leak threads in the HIVE)




Assume that at the start of the lightning chain, the tempgroup is initially empty. After the first iteration, the tempgroup should be filled with targets. One can make it so that the tempgroup gets all relevant units (viable enemy targets) and removes the irrelevant units (viable enemy targets but dead or far away and not viable targets) so that the issued order succeeds.

- As such, the implementation is that we get units within 512 units away from the desired location and add them to the group if they are viable targets.
- After that, we remove the units in the tempgroup which are not viable targets.

This will guarantee that the issued order is a success.

Result: From three ForGroupBJ calls to two ForGroupBJ calls (for better or worse).

Now, assuming that the cooldown of the dummy spell is 0, and manacost is 0, the creation and destruction of dummy units would turn out to be a waste. Instead, we can store an initialized dummy unit with the ability and change its' player attributes at will.



I hope that wasn't too much to read. Also, I would like to state that the manner in which I explain these things are not meant to be taken offensively.

Cheers!


Wow, that was a great read! Thank you so much!

I have since came up with a workaround, and it works fairly well (Maybe not that optimized though!) Simply, I just added this trigger to work in conjunction

Edit: I no longer need this trigger after changing "Matching unit" to "Picked unit" - Thanks Gauda
  • Caster casting
    • Events
      • Time - Every 0.02 seconds of game time
    • Conditions
    • Actions
      • Unit - Order Dummy_Chain_Lightning to Orc Far Seer - Chain Lightning (Random unit from Tempgroup)
The result is an infinite chain lightning, except that sometimes there is a delay between bounces, (As a result of the faulty trigger above)
I don't understand JASS very well but I do know about using custom scripts to remove temporary stored variables. Your commentary was very helpful on this.

I also used two triggers for the purpose of limiting the the bounces

This trigger basically starts the chain lightning process via a targeted ability. As you can see, there is a "timer" there
  • sdda
  • Boss Cast Chain Lightning
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Chain Lightning (Boss)
    • Actions
      • Countdown Timer - Start Timer as a One-shot timer that will expire in 2.00 seconds
      • Set Dummy_Chain_Lightning_TARGET = (Target unit of ability being cast)
      • Unit - Create 1 Dummy Caster for Player 1 (Red) at (Position of (Triggering unit)) facing Default building facing degrees
      • Set Dummy_Chain_Lightning = (Last created unit)
      • Unit - Order Dummy_Chain_Lightning to Orc Far Seer - Chain Lightning (Target unit of ability being cast)
This trigger first turns off the periodic event trigger, then causes "Dummy_Chain_Lightning" to die, thus breaking the chain. The result is 2 seconds of lightning bouncing all over the place.
  • Stop Lightning Trigger
    • Events
      • Time - Timer expires
    • Conditions
    • Actions
      • Trigger - Turn off Caster casting <gen>
      • Unit - Kill Dummy_Chain_Lightning
      • Wait 1.00 game-time seconds
      • Trigger - Turn on Caster casting <gen>
For the most part, this works good for my purposes, but I would love any imput anyways, any way i can optimize my triggers sounds like a good idea to me. Thanks guys!
 
Last edited:
Level 2
Joined
Dec 29, 2017
Messages
16
You should consider to check your inbox...

It's pretty obvious why this doesn't work.

- Generic timers of 0.02 also depends on (the cast time of the ability itself) I'm assuming it's instant
- Wh...

Thank you for the input! I am reworking the triggers as best as I can to not leak as we speak. I appreciate the criticism!
 
Last edited:
Level 2
Joined
Dec 29, 2017
Messages
16
So - I reworked the trigger and here goes! I put commentary where appropiate
  • Wild Lightning Dummy Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Instant Chain Lightning
    • Actions
      • Set Dummy_Chain_Lightning_TARGET = (Target unit of ability being cast)
      • Set Dummy_Chain_Lightning_TARGET_P = (Position of Dummy_Chain_Lightning_TARGET)
      • Unit - Add a 0.02 second Generic expiration timer to (Triggering unit) //remove unit leak
      • Unit - Cause (Triggering unit) to damage Dummy_Chain_Lightning_TARGET, dealing 50.00 damage of attack type Spells and damage type Normal
      • Unit - Create 1 Dummy Caster for Player 1 (Red) at Dummy_Chain_Lightning_TARGET_P facing (Facing of Dummy_Chain_Lightning_TARGET) degrees
      • Custom script: call RemoveLocation (udg_Dummy_Chain_Lightning_TARGET_P) // remove loc for next actions
      • Set Dummy_Chain_Lightning = (Last created unit)
      • Wait 0.00 seconds // A wait just incase I want to slow down the rate of bouncing
      • Set Dummy_Chain_Lightning_TARGET_P = (Position of Dummy_Chain_Lightning_TARGET) //set loc for next action
      • Unit - Move Dummy_Chain_Lightning instantly to Dummy_Chain_Lightning_TARGET_P // makes bouncing look better on moving targets
      • Set UnitsWithinTarget = (Units within 400.00 of Dummy_Chain_Lightning_TARGET_P)
      • Unit Group - Pick every unit in UnitsWithinTarget and do (Actions) //target filters
        • Loop - Actions
          • If (((Picked unit) belongs to an ally of Owner_Of_Caster) Equal to True) then do (Unit Group - Remove (Picked unit) from UnitsWithinTarget) else do (Do nothing)
          • If ((Picked unit) Equal to Dummy_Chain_Lightning_TARGET) then do (Unit Group - Remove (Picked unit) from UnitsWithinTarget) else do (Do nothing) // prevents repeat strikes on the same target
          • If (((Picked unit) is dead) Equal to True) then do (Unit Group - Remove (Picked unit) from UnitsWithinTarget) else do (Do nothing)
          • Unit Group - Remove all units of (Units owned by Player 1 (Red)) from UnitsWithinTarget
      • Unit - Order Dummy_Chain_Lightning to Orc Far Seer - Chain Lightning (Random unit from UnitsWithinTarget)
      • Custom script: call RemoveLocation (udg_Dummy_Chain_Lightning_TARGET_P) //clean up leak
      • Custom script: call DestroyGroup (udg_UnitsWithinTarget) //clean up leak
This works perfect for my purposes and as a result my post has been resolved. Thank you for all your help!

If you guys notice anything else that could be optimized, do let me know!

My only question would be, how would I be able to modify this trigger to allow two separate instances of the ability to exist at once without confusing the logic? Is that even possible? If you guys have any ideas do let me know!
 
Last edited:
Level 6
Joined
Dec 31, 2017
Messages
138
So - I reworked the trigger and here goes! I put commentary where appropiate
  • Wild Lightning Dummy Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Instant Chain Lightning
    • Actions
      • Set Dummy_Chain_Lightning_TARGET = (Target unit of ability being cast)
      • Set Dummy_Chain_Lightning_TARGET_P = (Position of Dummy_Chain_Lightning_TARGET)
      • Unit - Add a 0.02 second Generic expiration timer to (Triggering unit) //remove unit leak
      • Unit - Cause (Triggering unit) to damage Dummy_Chain_Lightning_TARGET, dealing 50.00 damage of attack type Spells and damage type Normal
      • Unit - Create 1 Dummy Caster for Player 1 (Red) at Dummy_Chain_Lightning_TARGET_P facing (Facing of Dummy_Chain_Lightning_TARGET) degrees
      • Custom script: call RemoveLocation (udg_Dummy_Chain_Lightning_TARGET_P) // remove loc for next actions
      • Set Dummy_Chain_Lightning = (Last created unit)
      • Wait 0.00 seconds // A wait just incase I want to slow down the rate of bouncing
      • Set Dummy_Chain_Lightning_TARGET_P = (Position of Dummy_Chain_Lightning_TARGET) //set loc for next action
      • Unit - Move Dummy_Chain_Lightning instantly to Dummy_Chain_Lightning_TARGET_P // makes bouncing look better on moving targets
      • Set UnitsWithinTarget = (Units within 400.00 of Dummy_Chain_Lightning_TARGET_P)
      • Unit Group - Pick every unit in UnitsWithinTarget and do (Actions) //target filters
        • Loop - Actions
          • If (((Picked unit) belongs to an ally of Owner_Of_Caster) Equal to True) then do (Unit Group - Remove (Picked unit) from UnitsWithinTarget) else do (Do nothing)
          • If ((Picked unit) Equal to Dummy_Chain_Lightning_TARGET) then do (Unit Group - Remove (Picked unit) from UnitsWithinTarget) else do (Do nothing) // prevents repeat strikes on the same target
          • If (((Picked unit) is dead) Equal to True) then do (Unit Group - Remove (Picked unit) from UnitsWithinTarget) else do (Do nothing)
          • Unit Group - Remove all units of (Units owned by Player 1 (Red)) from UnitsWithinTarget
      • Unit - Order Dummy_Chain_Lightning to Orc Far Seer - Chain Lightning (Random unit from UnitsWithinTarget)
      • Custom script: call RemoveLocation (udg_Dummy_Chain_Lightning_TARGET_P) //clean up leak
      • Custom script: call DestroyGroup (udg_UnitsWithinTarget) //clean up leak
This works perfect for my purposes and as a result my post has been resolved. Thank you for all your help!

If you guys notice anything else that could be optimized, do let me know!

My only question would be, how would I be able to modify this trigger to allow two separate instances of the ability to exist at once without confusing the logic? Is that even possible? If you guys have any ideas do let me know!
If you give the ablity to several units it may stop working. Especially, If you extend waiting time. Becouse global variables may change while trigger sleeps.
 
Status
Not open for further replies.
Top