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

[Solved] Loop adding abilities crashes game

Status
Not open for further replies.
Level 5
Joined
Jun 25, 2005
Messages
92
Why does this crash the game after ~10 seconds (several units die inbetween)?

VeterancyLevels is an ability array with indices from 0 to 6,
VeterancyLevelsBuffs is a buff array with indices from 0 to 6,
TempUnit is a unit variable.

The trigger is supposed to check for dummy abilities giving buffs, remove the dummy ability and buff, and add a dummy ability that is next on the index. It isn't supposed to do anything when it has the dummy ability with index 6.

  • Veterancy
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
      • Set TempUnit = (Killing unit)
      • For each (Integer A) from 0 to 5, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Triggering player) is giving (Owner of TempUnit) Alliance (non-aggression)) Equal to False
              • (Level of VeterancyLevels[(Integer A)] for TempUnit) Equal to 1
              • (Level of VeterancyLevels[6] for TempUnit) Not equal to 1
            • Then - Actions
              • Unit - Remove VeterancyLevels[(Integer A)] from TempUnit
              • Unit - Remove VeterancyLevelsBuffs[(Integer A)] buff from TempUnit
              • Unit - Add VeterancyLevels[((Integer A) + 1)] to TempUnit
              • Skip remaining actions
            • Else - Actions
 
Last edited:
Level 12
Joined
Mar 24, 2011
Messages
1,082
All looks ok... eh, what about the set-up ?

BTW, why don't you put this "(Level of VeterancyLevels[6] for TempUnit) Not equal to 1" in the trigger conditions instead? (highly doubt that would solve or cause the problem, but looks weird to me...)
 
Level 11
Joined
Nov 23, 2013
Messages
665
Do you have other triggers that use Integer A? If so, these multiple Integer A might interfere with each other if they're used at the same time. Use an integer variable instead.
 
Level 5
Joined
Jun 25, 2005
Messages
92
why don't you put this "(Level of VeterancyLevels[6] for TempUnit) Not equal to 1" in the trigger conditions instead?

You're right, that'd be better for the trigger right now. I will expand the trigger with other if-then-else functions after getting it to work, though, and then it'll be more clear this way.

Do you have other triggers that use Integer A? If so, these multiple Integer A might interfere with each other if they're used at the same time. Use an integer variable instead.

I use Integer A a lot, but I don't use waits and thought those interference problems only happen due to waits. Can there still be interferences?

I made an integer variable called "Veterancy", changed the "For Each Integer A" to "For Each Integer Variable [Veterancy]" and swapped all instances of Integer A in the trigger with Veterancy, but it still crashes after 7-10 seconds. It runs indefinitely without this trigger.

  • Veterancy Copy
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
      • Set TempUnit = (Killing unit)
      • For each (Integer Veterancy) from 0 to 5, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Triggering player) is giving (Owner of TempUnit) Alliance (non-aggression)) Equal to False
              • (Level of VeterancyLevels[Veterancy] for TempUnit) Equal to 1
              • (Level of VeterancyLevels[6] for TempUnit) Not equal to 1
            • Then - Actions
              • Unit - Remove VeterancyLevels[Veterancy] from TempUnit
              • Unit - Remove VeterancyLevelsBuffs[Veterancy] buff from TempUnit
              • Unit - Add VeterancyLevels[(Veterancy + 1)] to TempUnit
              • Skip remaining actions
            • Else - Actions
 
Level 12
Joined
Mar 24, 2011
Messages
1,082
Again, how do you set the variables? (VeterancyLevels skill & buff)
Are you 100% sure that this trigger breaks the game ?

  • Unit - Remove VeterancyLevelsBuffs[Veterancy] buff from TempUnit
You are removing without adding? Now again nothing game breaking here... I'd also guess that he buff is on the skill, so you don't really need this?
 
Level 5
Joined
Jun 25, 2005
Messages
92
Again, how do you set the variables? (VeterancyLevels skill & buff)

  • Set Variables MapInit
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- VeterancyLevels Abilities --------
      • Set VeterancyLevels[0] = Veterancy 0
      • Set VeterancyLevels[1] = Veterancy 1
      • Set VeterancyLevels[2] = Veterancy 2
      • Set VeterancyLevels[3] = Veterancy 3
      • Set VeterancyLevels[4] = Veterancy 4
      • Set VeterancyLevels[5] = Veterancy 5
      • Set VeterancyLevels[6] = Veterancy 6
      • -------- VeterancyLevels Buffs --------
      • Set VeterancyLevelsBuffs[0] = Veterancy 0
      • Set VeterancyLevelsBuffs[1] = Veterancy 1
      • Set VeterancyLevelsBuffs[2] = Veterancy 2
      • Set VeterancyLevelsBuffs[3] = Veterancy 3
      • Set VeterancyLevelsBuffs[4] = Veterancy 4
      • Set VeterancyLevelsBuffs[5] = Veterancy 5
      • Set VeterancyLevelsBuffs[6] = Veterancy 6
Are you 100% sure that this trigger breaks the game ?

I'm not sure whether it's this one that causes it to crash, but it only crashes if this one is turned on. And, as a test, I removed 3/4ths of the triggers and left this one on, and it still crashes the game.

You are removing without adding? Now again nothing game breaking here...

The variables are set in one of the MapInit triggers. Furthermore, on MapInit, every unit is picked and given Veterancy 0, and new units are given Veterancy 0, when entering the map, too.

  • Init during mapinit
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- Pre-placed unit settings --------
      • Set TempUnitGroup = (Units in (Playable map area))
      • Unit Group - Pick every unit in TempUnitGroup and do (Actions)
        • Loop - Actions
          • Unit - Add Veterancy 0 to (Picked unit)
          • Unit - Turn alarm generation for (Picked unit) Off
      • Custom script: call DestroyGroup(udg_TempUnitGroup)
  • Generic NewUnits
    • Events
      • Unit - A unit enters (Playable map area)
    • Conditions
    • Actions
      • Unit - Add Veterancy 0 to (Triggering unit)
I'd also guess that he buff is on the skill, so you don't really need this?

Yes, they're part of the skills, but if I don't remove the buffs, then they take too long to expire, after the skill is removed. So, you can see two buffs at the same time. I didn't find a way to reduce the expiration time to make the buff disappear instantly.
Removing that line still makes it crash.
 
Last edited:
Level 5
Joined
Jun 25, 2005
Messages
92
Not sure when it happens. It seems to happen some time after hitting Veterancy 6 and killin more units then, maybe ~10 seconds later. I'm having trouble pinning down when it happens. All I know is that something needs to die for it to start.

Maybe it's happening when something is being killed simultaneously.
 
Last edited:
Level 12
Joined
Mar 24, 2011
Messages
1,082
Not sure when it happens. It seems to happen some time after hitting Veterancy 6 and killin more units then, maybe ~10 seconds later. I'm having trouble pinning down when it happens. All I know is that something needs to die for it to start.

Maybe it's happening when something is being killed simultaneously.


Put a bajillion Debug messages and sanitize your test. Start killing units 1 by 1, with 10+ sec intervals to check if only a single veteran unit can break it. If this confirms a working trigger and nothing breaks then increase the size of the test. Clean controlled environment where you know exactly wtf is happening. Debug messages everywhere !!! Use a system that logs them to a txt file if you have to.
 
Level 5
Joined
Jun 25, 2005
Messages
92
Put a bajillion Debug messages and sanitize your test. Start killing units 1 by 1, with 10+ sec intervals to check if only a single veteran unit can break it. If this confirms a working trigger and nothing breaks then increase the size of the test. Clean controlled environment where you know exactly wtf is happening. Debug messages everywhere !!! Use a system that logs them to a txt file if you have to.
I had already tried killing units one by one, with multiple and only a single unit, and debug messages to check for whether if-then-else even fires. Guess I need more debug messages for all sorts of things, but I don't even know which would be useful.

iirc adding leveling removing abilities from a dead unit will crash the game. put a check for the killing unit to not be dead.

also triggering player should probably be owner of triggering unit.

Adding an "is alive" still makes it crash, changing "owner of triggering unit" to "triggering player" makes it not do the actions, but still crash, which is weird.
 
Level 5
Joined
Jun 25, 2005
Messages
92
try running it with the ability altering actions disabled and see if it crashes

Did that. It still crashes.

I found out that killing any units by trigger crashes the game. Dunno why. If I deactivate the Veterancy trigger, killing units by trigger doesn't crash the game anymore.

  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • (Substring((Entered chat string), 2, 5)) Equal to kill
          • (Entered chat string) Equal to -k
    • Then - Actions
      • Game - Display to (Player group((Triggering player))) for 3.00 seconds the text: Killed selected uni...
      • Set TempUnitGroup = (Units currently selected by (Triggering player))
      • Unit Group - Pick every unit in TempUnitGroup and do (Actions)
        • Loop - Actions
          • Unit - Kill (Picked unit)
      • Custom script: call DestroyGroup(udg_TempUnitGroup)
    • Else - Actions
 
Last edited:
Level 5
Joined
Jun 25, 2005
Messages
92
Okay, I removed this following condition and it doesn't crash anymore:

((Triggering player) is giving (Owner of TempUnit) Alliance (non-aggression)) Equal to False

But removing this allows players to gain Veterancy by killing their own units, so I need some other way to check for killing players being hostile to the owner of the dying unit.

Edit: Now, I just swapped the triggering and killing player with each other and it works fine:

((Owner of TempUnit) is giving (Triggering player) Alliance (non-aggression)) Equal to False

Problem seems to be solved, though it worries me that I don't know why.
 
Last edited:
Level 21
Joined
Mar 27, 2012
Messages
3,232
Might it be that the things you are killing belong to one of the neutral players, or maybe a player in an empty slot?
I've noticed that neutral players are not quite equal to others when alliance functions are concerned, so trying to see what they think of you might be what caused the crashes.
 
Level 12
Joined
Mar 24, 2011
Messages
1,082
Mmm... How about this:
  • ((Triggering unit) belongs to an enemy of (Owner of (Killing unit))) Equal to True
Yo make it a bit more robust you can do:
  • ((Dying unit) belongs to an enemy of (Owner of (Killing unit))) Equal to True
Although, I believe this should be enough.

@doom_sheep "Triggering Player" exists almost in all cases and corresponds to something. In "Unit - A unit Dies" this would be... Hold on, wouldn't that be the owner of the dying unit? Because, if otherwise, if the death source is not a player there would be no "Triggering player"...

AAHHH! Why do you make me think !
 
All events which you can also select also only for a certain player are playerunitevent in JASS.
"A unit dies" is a playerunitevent, which then just will be applied for all players. (one can see that if you convert GUI to JASS)

So the universal "A unit dies" is the same as if I add events for each player "A unit by Player 1 dies, A unit by Player 2 dies, ..."

Important is, in all playerunitevent, you can refer also to "TriggeringPlayer", which will equal the owner of triggering unit. That's why "TriggeringPlayer" is also useable like this in event "A unit dies", because it's actually multiple playerunitevents.

Event "A Unit Enters Region" for example, is not a playerunitevent, so TriggeringPlayer does not work there.

If one always use TriggeringPlayer at unit events one might realize sometimes they work, and sometimes not, depending if it's applyable for a playerunitevent. "Owner of unit" is always safe to use, if one is unsure.
 
Level 5
Joined
Jun 25, 2005
Messages
92
Might it be that the things you are killing belong to one of the neutral players, or maybe a player in an empty slot?
I've noticed that neutral players are not quite equal to others when alliance functions are concerned, so trying to see what they think of you might be what caused the crashes.
Yes, some of the units killed and killing are owned by Neutral Extra, Neutral Passive and Neutral Hostile (others by regular players), but I triggered the alliance aspects of the neutral players to be similar to those of normal players.

why do you have "triggering player" if the trigger is triggered by a unit, not a player?
I remember reading somewhere that "triggering player" is faster than "owner of unit", and it does the same thing in this case.

Mmm... How about this:
  • ((Triggering unit) belongs to an enemy of (Owner of (Killing unit))) Equal to True
Yo make it a bit more robust you can do:
  • ((Dying unit) belongs to an enemy of (Owner of (Killing unit))) Equal to True
Although, I believe this should be enough.

@doom_sheep "Triggering Player" exists almost in all cases and corresponds to something. In "Unit - A unit Dies" this would be... Hold on, wouldn't that be the owner of the dying unit? Because, if otherwise, if the death source is not a player there would be no "Triggering player"...

AAHHH! Why do you make me think !

Triggering player is supposed to be the owner of the dying unit.

Important is, in all playerunitevent, you can refer also to "TriggeringPlayer", which will equal the owner of triggering unit. That's why "TriggeringPlayer" is also useable like this in event "A unit dies", because it's actually multiple playerunitevents.

Event "A Unit Enters Region" for example, is not a playerunitevent, so TriggeringPlayer does not work there.

Good to know why that is. Thank you.
 
Status
Not open for further replies.
Top