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

Unit Group acts weird...

Status
Not open for further replies.
Level 10
Joined
Mar 17, 2012
Messages
579
Hi everyone. I have a basic unit group that receives damage in 400 AoE, but surprisingly only 1 unit receives damage... I've checked the trigger several times, but I don't understand what works wrong. I've done it plenty of times and now I'm confused:

  • Infernal Explosion
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Infernal Explosion
    • Actions
      • Set Player_Number_Int = (Player number of (Owner of (Triggering unit)))
      • Set Infernal_Explosion_Caster[Player_Number_Int] = (Triggering unit)
      • Set Infernal_Explosion_Point[Player_Number_Int] = (Target point of ability being cast)
      • -------- effect --------
      • Unit - Create 1 Regular Dummy for (Owner of Infernal_Explosion_Caster[Player_Number_Int]) at Infernal_Explosion_Point[Player_Number_Int] facing Default building facing degrees
      • Unit - Add a 3.00 second Generic expiration timer to (Last created unit)
      • Unit - Add Infernal Explosion (Neutral Hostile 2) to (Last created unit)
      • Unit - Order (Last created unit) to Human Blood Mage - Flame Strike Infernal_Explosion_Point[Player_Number_Int]
      • -------- damage --------
      • Special Effect - Create a special effect at Infernal_Explosion_Point[Player_Number_Int] using Abilities\Spells\Human\FlameStrike\FlameStrike1.mdl
      • Special Effect - Destroy (Last created special effect)
      • Set Infernal_Explosion_Group[Player_Number_Int] = (Units within 400.00 of Infernal_Explosion_Point[Player_Number_Int] matching ((((Matching unit) belongs to an enemy of (Owner of Infernal_Explosion_Caster[Player_Number_Int])) Equal to True) and ((((Matching unit) is An Ancient) Not equal to True) and (((Matc
      • Unit Group - Pick every unit in Infernal_Explosion_Group[Player_Number_Int] and do (Actions)
        • Loop - Actions
          • Set Infernal_Explosion_Damage[Player_Number_Int] = (((((Real((Level of Infernal Explosion for Infernal_Explosion_Caster[Player_Number_Int]))) x 30.00) + 30.00) + ((Real((Intelligence of Infernal_Explosion_Caster[Player_Number_Int] (Include bonuses)))) x (((Real((Level of Infernal Explosion for Infernal_Expl
          • Unit - Cause Infernal_Explosion_Caster[Player_Number_Int] to damage (Picked unit), dealing Infernal_Explosion_Damage[Player_Number_Int] damage of attack type Spells and damage type Fire
          • Special Effect - Create a special effect attached to the chest of (Picked unit) using OrbOfFire.mdx
          • Special Effect - Destroy (Last created special effect)
      • Custom script: call RemoveLocation(udg_Infernal_Explosion_Point[udg_Player_Number_Int])
      • Custom script: call DestroyGroup(udg_Infernal_Explosion_Group[udg_Player_Number_Int])
Any help, please :)
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
Can't see anything wrong at the moment. Might be interfering with other triggers. Do you have triggers with events "unit takes damage" (also from DDS) or "unit dies"?
Is Player_Number_Int used by other triggers?
 
Level 10
Joined
Mar 17, 2012
Messages
579
Can't see anything wrong at the moment. Might be interfering with other triggers. Do you have triggers with events "unit takes damage" (also from DDS) or "unit dies"?
Is Player_Number_Int used by other triggers?
I'm using Bribe's damage system so I have lots of events of damage detection.
Player_Number_Int is used by almost every trigger when it comes to Indexing as I make all triggers MUI
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
That's bad then.
The action "unit cause damage" in your unit group will trigger other triggers that use the damage detection system. If one of those triggers overwrites Player_Number_Int, you got a problem.
Does the special effect show for every unit, but only one is damaged?
Also when Player_Number_Int is overwritten the custom scripts will remove the wrong location/group, which will result in leaks.
 
Level 10
Joined
Mar 17, 2012
Messages
579
That's bad then.
The action "unit cause damage" in your unit group will trigger other triggers that use the damage detection system. If one of those triggers overwrites Player_Number_Int, you got a problem.
Does the special effect show for every unit, but only one is damaged?
Also when Player_Number_Int is overwritten the custom scripts will remove the wrong location/group, which will result in leaks.

I can't get how Player_Number_Int can overwrite anything as it only stores the Number of player.
Special effect works for everyone in the group.... :(
well, at least I know what causes a problem...
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
player 4 uses the spell, Player_Number_Int is 4 and
Infernal_Explosion_Damage[4] is 100 (just an example)
Infernal_Explosion_Caster[4] is the caster
lets say the group runs for your first unit.
it is damaged by 100 damage
now before the trigger continues to run, all triggers with the damage event from the DDS will run.
In one of the trigger that runs now, Player_Number_Int is used as well and set to 2.

the group trigger will continue with the next unit, but it will try to use
Infernal_Explosion_Caster[2] and Infernal_Explosion_Damage[2] to damage the unit, because Player_Number_Int was changed by the trigger that run from the damage event.
As Infernal_Explosion_Caster[2] and Infernal_Explosion_Damage[2] have not been defined, and Infernal_Explosion_Caster[2] is probably no unit (null) and Infernal_Explosion_Damage[2] is probably 0, no damage will be dealt.
If Infernal_Explosion_Damage[2] and Infernal_Explosion_Caster[2] would have been set at some point, because player 2 used the spell, it would work, however the wrong unit would deal damage and the damage would be wrong. Also if Infernal_Explosion_Caster[2] would have died by then it would not work at all.

You need to make sure, that Player_Number_Int is not overwritten while the trigger runs, by triggers that run in between. You could do that by using Infernal_Explosion_Int instead of Player_Number_Int, so you have an integer variable for each spell, so they can't be overwritten. This works, if this trigger cannot fire itself again.
An example where this would still cause problems is:

Infernal Explosion:
-unit damage target triggers Trigger B
Trigger B:
- order unit to cast Infernal Explosion triggers Infernal Explosion

I would recommend using local variables, as they are completely safe, however they do not work with GUI group actions and require FirstOfGroup loops.
 
Level 7
Joined
Jan 23, 2011
Messages
350
I would recommend just don't use array variables on instantaneous triggers. There is absolutely no reason why this
  • Set Infernal_Explosion_Caster[Player_Number_Int]
to be better than this
  • Set Infernal_Explosion_Caster
It is actually worst
 
Level 11
Joined
Jun 2, 2004
Messages
849
An easy fix without changing anything is adding this custom script at the top:

Code:
local integer udg_Player_Number_Int

In fact I suggest doing this with all globals-used-as-locals that are often seen in GUI. The unit and point could mess up too so should probably also be made local.
 
Level 10
Joined
Mar 17, 2012
Messages
579
Simple but ugly solution would be: set Player_Number_Int again on the last line of the group actions.
How is it supposed to help me?

I would recommend just don't use array variables on instantaneous triggers. There is absolutely no reason why this
  • Set Infernal_Explosion_Caster[Player_Number_Int]
to be better than this
  • Set Infernal_Explosion_Caster
It is actually worst

I'd see the point in it if I was using some loop trigger not to write GetForLoopIndexA(), but here... I don't fully undestand :(

An easy fix without changing anything is adding this custom script at the top:

Code:
local integer udg_Player_Number_Int

In fact I suggest doing this with all globals-used-as-locals that are often seen in GUI. The unit and point could mess up too so should probably also be made local.

What's the difference between locals and globals in means of influence on the game?


P.S. Thank you all for your participation, I'll take your advices into account and try to fix my problem. I'll be in touch :)
 
Level 7
Joined
Jan 23, 2011
Messages
350
Your trigger is Instant. You can't get problems like losing reference of your unique variables.
Your problem is caused by the variable Player_Number_Int (like Jampion explained), but you can also remove it completely from the trigger without any downside because your variables are Unique for this trigger and Damage Event won't mess it up
 
Level 10
Joined
Mar 17, 2012
Messages
579
Your trigger is Instant. You can't get problems like losing reference of your unique variables.
Your problem is caused by the variable Player_Number_Int (like Jampion explained), but you can also remove it completely from the trigger without any downside because your variables are Unique for this trigger and Damage Event won't mess it up

Are you telling me that if I replace my Player_Number_Int in this trigger with any other variable representing the player number, there's a probability that my problem will be solved?
 
Level 11
Joined
Jun 2, 2004
Messages
849
As was mentioned, some actions in triggers can make other triggers fire in the middle of your first trigger. So the "damage unit" action will fire all "damage taken" events BEFORE the rest of the trigger is allowed to finish, meaning globals can be overwritten even without waits. Local variables cannot be changed by other triggers no matter what.
 
Status
Not open for further replies.
Top