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

Periodic damage trigger not working

Status
Not open for further replies.
Level 10
Joined
Mar 17, 2012
Messages
579
Hi everyone! In my map I'm workin with kind of "ability power for heroes" and I faced such a problem with periodic damage:
For example - Shadow Strike:
  • Events
  • Unit - A unit starts the effect of an ability
  • Conditions
  • (Ability being cast) Equal to Shadow Strike
  • Actions
  • Unit - Cause (Casting unit) to damage (Target unit of ability being cast), dealing ((Real(Agility of (Casting unit)(include bonuses) x 0.5) damage of type Spells and damage type Shadow Strike
  • Wait 1.00 seconds
  • Unit - Cause (Casting unit) to damage (Target unit of ability being cast), dealing ((Real(Agility of (Casting unit)(include bonuses) x 0.5) damage of type Spells and damage type Shadow Strike
  • Wait 1.00 seconds
... and 8 times such a way...

But it strikes only 1 time, and I need it to strike 8 times, why it doesn't work?

Than i tried to create dummy to strike target... no progress...
What should I do? :ogre_rage:
 
Last edited by a moderator:
Level 26
Joined
Aug 18, 2009
Messages
4,097
For example. A single global variable restricts you to only one instance of this trigger simultaneously though. If another unit casts the same ability while the first has not finished, it will get into conflict.

Do the same with Target unit of ability being cast btw.
 
Level 10
Joined
Mar 17, 2012
Messages
579
For example. A single global variable restricts you to only one instance of this trigger simultaneously though. If another unit casts the same ability while the first has not finished, it will get into conflict.

Do the same with Target unit of ability being cast btw.

What about Picked unit in some group matching conditions?
 
Level 5
Joined
Sep 28, 2010
Messages
75
  • Events
    • Unit - A unit starts the effect of an ability
  • Conditions
    • (Ability being cast) Equal to Shadow Strike
  • Actions
    • Custom script: local unit udg_Caster = GetTriggerUnit()
    • Custom script: local unit udg_Target = GetSpellTargetUnit()
    • Unit - Cause Caster to damage Target, dealing ((Real(Agility of Caster(include bonuses) x 0.5) damage of type Spells and damage type Shadow Strike
    • Wait 1.00 seconds...etc x8
    • ---Insert the below code at the end---
    • set udg_Caster = null
    • set udg_Target = null
this should make it MUI
you need to have two GUI unit variables called "Target" and "Caster"

Local variables are used first. If there are two variables of the same name, the compiler would use the local variable first.

Like WaterKnight said, you can't include waits in unit group actions. Nothing will work if you do.

EDIT: If there are two variables of the same name, [highlight]one local and one global[/code], the compiler would use the local variable first.
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
You can use a For Each Integer-loop and put the ForGroup-block and Wait action inside. After all, you do not want to pick one target every second of that group but pick all targets in that group every second. You should however also localize the iteration variables for it to be MI.
 
Level 10
Joined
Mar 17, 2012
Messages
579
You can use a For Each Integer-loop and put the ForGroup-block and Wait action inside. After all, you do not want to pick one target every second of that group but pick all targets in that group every second. You should however also localize the iteration variables for it to be MI.

I hardly understand what you say :vw_sad:

In my "Flame Strike" ability I use Flame_Strike_Group as UnitGroup matching conditions that units are in some distance from target point of ability being cast and then pick every unit in Flame_Strike_Group and do actions: cause casting unit to damage picked unit dealing damage multiplied to his Int, but it have to damage 3 times for 1 second, so it strikes only 1 time... that's the problem.
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
  • Events
    • Unit - A unit starts the effect of an ability
  • Conditions
    • (Ability being cast) Equal to Shadow Strike
  • Actions
    • Custom script: local unit udg_Caster = GetTriggerUnit()
    • Custom script: local unit udg_Target = GetSpellTargetUnit()
    • Custom script: local integer bj_forLoopAIndex
    • Custom script: local integer bj_forLoopAIndexEnd
    • For each (Integer A) from 1 to 8, do (Actions)
      • Loop - Actions
        • Unit Group - Pick every unit in <group> and do (Actions)
          • Loop - Actions
            • Unit - Cause Caster to damage (Picked unit), dealing ((Real(Agility of Caster(include bonuses) x 0.5) damage of type Spells and damage type Shadow Strike
        • Wait 1.00 seconds
    • Set Caster = No Unit
    • Set Target = No Unit
I do not really like the idea of overshadowing global variables though. That was not well supported in the past, do not know how it is nowadays.
 
Level 10
Joined
Mar 17, 2012
Messages
579
  • Events
    • Unit - A unit starts the effect of an ability
  • Conditions
    • (Ability being cast) Equal to Shadow Strike
  • Actions
    • Custom script: local unit udg_Caster = GetTriggerUnit()
    • Custom script: local unit udg_Target = GetSpellTargetUnit()
    • Custom script: local integer bj_forLoopAIndex
    • Custom script: local integer bj_forLoopAIndexEnd
    • For each (Integer A) from 1 to 8, do (Actions)
      • Loop - Actions
        • Unit Group - Pick every unit in <group> and do (Actions)
          • Loop - Actions
            • Unit - Cause Caster to damage (Picked unit), dealing ((Real(Agility of Caster(include bonuses) x 0.5) damage of type Spells and damage type Shadow Strike
        • Wait 1.00 seconds
    • Set Caster = No Unit
    • Set Target = No Unit
I do not really like the idea of overshadowing global variables though. That was not well supported in the past, do not know how it is nowadays.

does it work for AoE abilities?
 
Level 5
Joined
Sep 28, 2010
Messages
75
This will be very messy to you, but I am using dynamic indexing to make this flame strike, so here you go, an advanced version.


  • FlameStrike Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Flame Strike
    • Actions
      • Set FlameStrike_CurrentIndex = (FlameStrike_CurrentIndex + 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • FlameStrike_CurrentIndex Greater than FlameStrike_MaxIndex
        • Then - Actions
          • Set FlameStrike_Index[FlameStrike_CurrentIndex] = FlameStrike_CurrentIndex
          • Set FlameStrike_MaxIndex = FlameStrike_CurrentIndex
        • Else - Actions
      • Set FlameStrike_Temp = FlameStrike_Index[FlameStrike_CurrentIndex]
      • Set FlameStrike_Loc[FlameStrike_Temp] = (Target point of ability being cast)
      • Set FlameStrike_Caster[FlameStrike_Temp] = (Triggering unit)
      • Set FlameStrike_Duration[FlameStrike_Temp] = 2.00
      • Special Effect - Create a special effect at FlameStrike_Loc[FlameStrike_Temp] using Objects\Spawnmodels\Human\HCancelDeath\HCancelDeath.mdl
      • Special Effect - Destroy (Last created special effect)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (FlameStrike Loop <gen> is on) Equal to False
        • Then - Actions
          • Trigger - Turn on FlameStrike Loop <gen>
        • Else - Actions
  • FlameStrike Loop
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • For each (Integer FlameStrike_Loop) from 1 to FlameStrike_CurrentIndex, do (Actions)
        • Loop - Actions
          • Set FlameStrike_Temp = FlameStrike_Index[FlameStrike_Loop]
          • Custom script: set bj_wantDestroyGroup = true
          • Unit Group - Pick every unit in (Units within 200.00 of FlameStrike_Loc[FlameStrike_Temp] matching ((((Matching unit) is A structure) Equal to False) and (((Matching unit) is alive) Equal to True))) and do (Actions)
            • Loop - Actions
              • Unit - Cause FlameStrike_Caster[FlameStrike_Temp] to damage (Picked unit), dealing (50.00 / 10.00) damage of attack type Spells and damage type Fire
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • FlameStrike_Duration[FlameStrike_Temp] Less than or equal to 0.00
            • Then - Actions
              • Custom script: call RemoveLocation(udg_FlameStrike_Loc[udg_FlameStrike_Temp])
              • Set FlameStrike_Index[FlameStrike_Loop] = FlameStrike_Index[FlameStrike_CurrentIndex]
              • Set FlameStrike_Index[FlameStrike_CurrentIndex] = FlameStrike_Temp
              • Set FlameStrike_CurrentIndex = (FlameStrike_CurrentIndex - 1)
              • Set FlameStrike_Loop = (FlameStrike_Loop - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • FlameStrike_CurrentIndex Equal to 0
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
            • Else - Actions
              • Set FlameStrike_Duration[FlameStrike_Temp] = (FlameStrike_Duration[FlameStrike_Temp] - 0.10)
EDIT: here is the attachment
 

Attachments

  • FlameStrike.w3x
    18.4 KB · Views: 32
Level 26
Joined
Aug 18, 2009
Messages
4,097
You initially wrote to damage Target unit of ability being cast only, which is why it was strange that you mentioned ForGroup then. You can pick your group like you want. Maybe it even makes sense to store the group in a variable beforehand to ensure you always pick the same units. When you want to pick around a location e.g. the affected units could change otherwise. If you want to use Target point of ability being cast, that should also be saved.

  • Events
    • Unit - A unit starts the effect of an ability
  • Conditions
    • (Ability being cast) Equal to Shadow Strike
  • Actions
    • Custom script: local unit udg_Caster = GetTriggerUnit()
    • Custom script: local unit udg_Target = GetSpellTargetUnit()
    • Custom script: local location udg_TargetPoint = GetSpellTargetLoc()
    • Custom script: local integer bj_forLoopAIndex
    • Custom script: local integer bj_forLoopAIndexEnd
    • Custom script: local group udg_YourGroup
    • Set YourGroup = pick units...
    • For each (Integer A) from 1 to 8, do (Actions)
      • Loop - Actions
        • Unit Group - Pick every unit in YourGroup and do (Actions)
          • Loop - Actions
            • Unit - Cause Caster to damage (Picked unit), dealing ((Real(Agility of Caster(include bonuses) x 0.5) damage of type Spells and damage type Shadow Strike
        • Wait 1.00 seconds
    • Set Caster = No Unit
    • Set Target = No Unit
    • Custom script: call RemoveLocation(udg_TargetPoint)
    • Custom script: set udg_TargetPoint = null
And yes, as you can see, it is quite a frequent practice to require local variables, which GUI does not allow.
 
Level 10
Joined
Mar 17, 2012
Messages
579
This will be very messy to you, but I am using dynamic indexing to make this flame strike, so here you go, an advanced version.


  • FlameStrike Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Flame Strike
    • Actions
      • Set FlameStrike_CurrentIndex = (FlameStrike_CurrentIndex + 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • FlameStrike_CurrentIndex Greater than FlameStrike_MaxIndex
        • Then - Actions
          • Set FlameStrike_Index[FlameStrike_CurrentIndex] = FlameStrike_CurrentIndex
          • Set FlameStrike_MaxIndex = FlameStrike_CurrentIndex
        • Else - Actions
      • Set FlameStrike_Temp = FlameStrike_Index[FlameStrike_CurrentIndex]
      • Set FlameStrike_Loc[FlameStrike_Temp] = (Target point of ability being cast)
      • Set FlameStrike_Caster[FlameStrike_Temp] = (Triggering unit)
      • Set FlameStrike_Duration[FlameStrike_Temp] = 2.00
      • Special Effect - Create a special effect at FlameStrike_Loc[FlameStrike_Temp] using Objects\Spawnmodels\Human\HCancelDeath\HCancelDeath.mdl
      • Special Effect - Destroy (Last created special effect)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (FlameStrike Loop <gen> is on) Equal to False
        • Then - Actions
          • Trigger - Turn on FlameStrike Loop <gen>
        • Else - Actions
  • FlameStrike Loop
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • For each (Integer FlameStrike_Loop) from 1 to FlameStrike_CurrentIndex, do (Actions)
        • Loop - Actions
          • Set FlameStrike_Temp = FlameStrike_Index[FlameStrike_Loop]
          • Custom script: set bj_wantDestroyGroup = true
          • Unit Group - Pick every unit in (Units within 200.00 of FlameStrike_Loc[FlameStrike_Temp] matching ((((Matching unit) is A structure) Equal to False) and (((Matching unit) is alive) Equal to True))) and do (Actions)
            • Loop - Actions
              • Unit - Cause FlameStrike_Caster[FlameStrike_Temp] to damage (Picked unit), dealing (50.00 / 10.00) damage of attack type Spells and damage type Fire
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • FlameStrike_Duration[FlameStrike_Temp] Less than or equal to 0.00
            • Then - Actions
              • Custom script: call RemoveLocation(udg_FlameStrike_Loc[udg_FlameStrike_Temp])
              • Set FlameStrike_Index[FlameStrike_Loop] = FlameStrike_Index[FlameStrike_CurrentIndex]
              • Set FlameStrike_Index[FlameStrike_CurrentIndex] = FlameStrike_Temp
              • Set FlameStrike_CurrentIndex = (FlameStrike_CurrentIndex - 1)
              • Set FlameStrike_Loop = (FlameStrike_Loop - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • FlameStrike_CurrentIndex Equal to 0
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
            • Else - Actions
              • Set FlameStrike_Duration[FlameStrike_Temp] = (FlameStrike_Duration[FlameStrike_Temp] - 0.10)
EDIT: here is the attachment

It seems to me that there are minimum a half of superfluous code ^^,
 
Level 10
Joined
Mar 17, 2012
Messages
579
You initially wrote to damage Target unit of ability being cast only, which is why it was strange that you mentioned ForGroup then. You can pick your group like you want. Maybe it even makes sense to store the group in a variable beforehand to ensure you always pick the same units. When you want to pick around a location e.g. the affected units could change otherwise. If you want to use Target point of ability being cast, that should also be saved.

  • Events
    • Unit - A unit starts the effect of an ability
  • Conditions
    • (Ability being cast) Equal to Shadow Strike
  • Actions
    • Custom script: local unit udg_Caster = GetTriggerUnit()
    • Custom script: local unit udg_Target = GetSpellTargetUnit()
    • Custom script: local location udg_TargetPoint = GetSpellTargetLoc()
    • Custom script: local integer bj_forLoopAIndex
    • Custom script: local integer bj_forLoopAIndexEnd
    • Custom script: local group udg_YourGroup
    • Set YourGroup = pick units...
    • For each (Integer A) from 1 to 8, do (Actions)
      • Loop - Actions
        • Unit Group - Pick every unit in YourGroup and do (Actions)
          • Loop - Actions
            • Unit - Cause Caster to damage (Picked unit), dealing ((Real(Agility of Caster(include bonuses) x 0.5) damage of type Spells and damage type Shadow Strike
        • Wait 1.00 seconds
    • Set Caster = No Unit
    • Set Target = No Unit
    • Custom script: call RemoveLocation(udg_TargetPoint)
    • Custom script: set udg_TargetPoint = null
And yes, as you can see, it is quite a frequent practice to require local variables, which GUI does not allow.

Why do you use for integer???
 
Level 5
Joined
Sep 28, 2010
Messages
75
You can not use waits in groups, so an easy walkaround would be using a loop.
You save the data of the caster and the target point in a local variable, and then use loops to pick units in range of the saved location, damage them, wait 1 second, and repeat until the loop ends.
 
Level 5
Joined
Sep 28, 2010
Messages
75
your global variable, Flame_Strike_Caster, in jass, is udg_Flame_Strike_Caster.

declaring a local variable udg_Flame_Strike_Caster will cause the map to use the local variable instead of the global variable. By doing this, GUI functions are also able to use the local variable, which is Flame_Strike_Caster in GUI.

For example,
you declare a global variable Integer and set its default value to 5.
you declare a local variable udg_Integer and set its value to 10.
In the same function with the declared local variable udg_Integer, udg_Integer will return 10. Outside the function however, udg_Integer returns 5.

Also,
  • Set Flame_Strike_Caster = (Triggering Unit)
is equal to set udg_Flame_Strike_Caster = GetTriggerUnit()
 
Level 10
Joined
Mar 17, 2012
Messages
579
your global variable, Flame_Strike_Caster, in jass, is udg_Flame_Strike_Caster.

declaring a local variable udg_Flame_Strike_Caster will cause the map to use the local variable instead of the global variable. By doing this, GUI functions are also able to use the local variable, which is Flame_Strike_Caster in GUI.

For example,
you declare a global variable Integer and set its default value to 5.
you declare a local variable udg_Integer and set its value to 10.
In the same function with the declared local variable udg_Integer, udg_Integer will return 10. Outside the function however, udg_Integer returns 5.

Also,
  • Set Flame_Strike_Caster = (Triggering Unit)
is equal to set udg_Flame_Strike_Caster = GetTriggerUnit()

Why can't I use global variable?
 
Level 5
Joined
Sep 28, 2010
Messages
75
  • For each (Integer A) from 1 to 3, do (Actions)
    • Loop - Actions
      • Unit Group - Pick every unit in Flame_Strike_Group and do (Actions)
        • Loop - Actions
          • Unit - Cause Flame_Strike_Caster to damage (Picked unit), dealing (((Real((Intelligence of Flame_Strike_Caster (Include bonuses)))) x 1.25) + 0.00) damage of attack type Spells and damage type Fire
          • Wait 0.20 seconds
As you can see, the wait is inside the unit group. You should make it like this:
  • For each (Integer A) from 1 to 3, do (Actions)
    • Loop - Actions
      • Unit Group - Pick every unit in Flame_Strike_Group and do (Actions)
        • Loop - Actions
          • Unit - Cause Flame_Strike_Caster to damage (Picked unit), dealing (((Real((Intelligence of Flame_Strike_Caster (Include bonuses)))) x 1.25) + 0.00) damage of attack type Spells and damage type Fire
      • Wait 0.20 seconds
 
Level 10
Joined
Mar 17, 2012
Messages
579
  • For each (Integer A) from 1 to 3, do (Actions)
    • Loop - Actions
      • Unit Group - Pick every unit in Flame_Strike_Group and do (Actions)
        • Loop - Actions
          • Unit - Cause Flame_Strike_Caster to damage (Picked unit), dealing (((Real((Intelligence of Flame_Strike_Caster (Include bonuses)))) x 1.25) + 0.00) damage of attack type Spells and damage type Fire
          • Wait 0.20 seconds
As you can see, the wait is inside the unit group. You should make it like this:
  • For each (Integer A) from 1 to 3, do (Actions)
    • Loop - Actions
      • Unit Group - Pick every unit in Flame_Strike_Group and do (Actions)
        • Loop - Actions
          • Unit - Cause Flame_Strike_Caster to damage (Picked unit), dealing (((Real((Intelligence of Flame_Strike_Caster (Include bonuses)))) x 1.25) + 0.00) damage of attack type Spells and damage type Fire
      • Wait 0.20 seconds

it has no infuince to damage. there is still no damage))) check it out)))
 
Level 5
Joined
Sep 28, 2010
Messages
75
Maybe i have given the original one by accident. let me reattach it again.

edit
There is nothing wrong with the map, plus it has a very visible change. Maybe you loaded the original one instead?
By the way, my Warcraft III version is 1.24b, and i found out that the spell will glitch in 1.21b.
 
Level 10
Joined
Mar 17, 2012
Messages
579
Maybe i have given the original one by accident. let me reattach it again.

edit
There is nothing wrong with the map, plus it has a very visible change. Maybe you loaded the original one instead?
By the way, my Warcraft III version is 1.24b, and i found out that the spell will glitch in 1.21b.

What do you mean? o_O
and yes, now it's realy changed)
 
Level 10
Joined
Mar 17, 2012
Messages
579
Why did you create LOOPER variable? it doesn't use anywhere)

I don't complete understand such manoeuvre like Caster2 = Caster
could you please explain what it gave and why?

And one more moment: do you know why Flame Strike's triggered damage damages caster??
 
Last edited:
Level 10
Joined
Mar 17, 2012
Messages
579
F1ashB0nd, before you left this topic, could you also help me to manage Acid Bomb ability the same way? Feature of this spell is that it periodically damages tagreted unit of ability being cast and all units in AoE around Target unit of ability being cast ^^
 
Level 5
Joined
Sep 28, 2010
Messages
75
Why did you create LOOPER variable? it doesn't use anywhere
I forgot to delete it. It was for testing purposes.

I don't complete understand such manoeuvre like Caster2 = Caster
could you please explain what it gave and why?
I need a global variable to temporarily store the data of Caster (since Caster is local, i cannot transfer the data to another function)
So, i created another global called Caster2 which stores the data of Caster to be used in the ForGroup function.

And one more moment: do you know why Flame Strike's triggered damage damages caster??
Add the condition in Unit Group: (Matching Unit) not equal to Flame_Strike_Caster
 
Level 5
Joined
Sep 28, 2010
Messages
75
Here is the slightly altered version of Flame Strike known as Acid Bomb. You will need to add a delay before the effect happens, because the unit will already take damage before the missile touches it. You should consult others to help you as I will be absent for more than 12 hours starting from now. Good Luck in your progress!

You should also add in special effects or the spell would look really blank.
 

Attachments

  • AcidBomb.w3x
    18.6 KB · Views: 35
Level 10
Joined
Mar 17, 2012
Messages
579
Here is the slightly altered version of Flame Strike known as Acid Bomb. You will need to add a delay before the effect happens, because the unit will already take damage before the missile touches it. You should consult others to help you as I will be absent for more than 12 hours starting from now. Good Luck in your progress!

You should also add in special effects or the spell would look really blank.

Don't leave me alone! :ogre_rage: :goblin_cry: you didn't help me to fix Flame Strike yet((((

First of all - this Acid Bomb damages Caster again and buildings and it has not right damage delay)))
 
Level 10
Joined
Mar 17, 2012
Messages
579
Here is the slightly altered version of Flame Strike known as Acid Bomb. You will need to add a delay before the effect happens, because the unit will already take damage before the missile touches it. You should consult others to help you as I will be absent for more than 12 hours starting from now. Good Luck in your progress!

You should also add in special effects or the spell would look really blank.

Don't worry about acid bomb. it's okay :wink:
 
Status
Not open for further replies.
Top