• 🏆 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] DestroyLightning crashes WC3

Status
Not open for further replies.
Level 24
Joined
Aug 1, 2013
Messages
4,657
Hi all.

For Soviet655, I have made a spell (Mind Control) similar to the Yuri of Red Alert 2 (Yuri's Revenge), but there is something that I have never seen before.
I have a lightning between the target and the caster but when either of the units die, that lightning has to be destroyed.
So I call DestroyLightning (tried both GUI and JASS) but then the map crashes.

When I randomly call the same destroylightning (referencing to a null value) nothing is wrong, but wen I have a value, mostly (~80%) it crashes.

Does anyone have any idea what is wrong?

One more thing that I find extremely rare is that everything worked fine, until I was told that there is a bug and suddenly everything crashes.
 

Attachments

  • Mind Control.w3x
    21.6 KB · Views: 82
Level 24
Joined
Aug 1, 2013
Messages
4,657
It doesnt crashes because the value is null.

And I tested if it runs multiple times (destroying multiple times) but that ain't the problem.

This is the trigger that removes the lightning:
  • Remove Mind Control
    • Events
    • Conditions
    • Actions
      • Set MCS_Index = (MCS_Index - 1)
      • Set TempInteger2 = TempInteger
      • Lightning - Destroy MCS_LightningArray[TempInteger2]
      • Unit - Change ownership of MCS_UnitTargetArray[TempInteger2] to MCS_OriginalPlayerArray[TempInteger2] and Change color
      • For each (Integer A) from TempInteger2 to MCS_Index, do (Actions)
        • Loop - Actions
          • Set MCS_LightningArray[TempInteger2] = MCS_LightningArray[(TempInteger2 + 1)]
          • Set MCS_OriginalPlayerArray[TempInteger2] = MCS_OriginalPlayerArray[(TempInteger2 + 1)]
          • Set MCS_SEControllerArray[TempInteger2] = MCS_SEControllerArray[(TempInteger2 + 1)]
          • Set MCS_SETargetArray[TempInteger2] = MCS_SETargetArray[(TempInteger2 + 1)]
          • Set MCS_UnitControllerArray[TempInteger2] = MCS_UnitControllerArray[(TempInteger2 + 1)]
          • Set MCS_UnitTargetArray[TempInteger2] = MCS_UnitTargetArray[(TempInteger2 + 1)]
          • Set TempInteger2 = (TempInteger2 + 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • MCS_Index Equal to 0
        • Then - Actions
          • Trigger - Turn off Mind Control Loop <gen>
        • Else - Actions
It is called when either the caster or the target dies or when the ability is cast while the caster is already controlling a unit.
 
Level 25
Joined
Sep 26, 2009
Messages
2,378
what value does tempInteger have? Is that whole trigger? If so, then tempInteger should not be tempInteger but a unique variable (e.g. MCS_intenger or something) since it holds data for a period of time (unless it's bypassed by the Run Trigger function).

Also, what you do with the loop is that you use it as a "While" loop in code language. However this "For each integer variable from X to Y" loop has more similarity to "For" loop in code language.
Use "Integer A" to refer to the current loop instead of tempInteger2

It may really be that the tempInteger holds bad value and so you destroy non-existing lightning, resulting in game crash.
Just try to get rid of that action alone and check if your game still crashes.
 
Destroyed handles are not null. There is a difference.

When a handle is destroyed, the reference still points to that spot in memory. In the case of DestroyLightning(), if a valid lightning object is not at that point in memory, then it will force a crash.

To fix this, you have to null a lightning variable after destroying it. In your case:
  • Lightning - Destroy MCS_LightningArray[TempInteger2]
  • Custom script: set udg_MCS_LightningArray[udg_TempInteger2] = null
That should fix the crashes (assuming that operating on a null lightning variable won't cause crashes. if it still crashes, try checking if the variable points to null before operating on the lightning).

If it still crashes after all that, then perhaps it is unrelated to lightning.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
what value does tempInteger have? Is that whole trigger? If so, then tempInteger should not be tempInteger but a unique variable (e.g. MCS_intenger or something) since it holds data for a period of time (unless it's bypassed by the Run Trigger function).
Well I said that this trigger was called on very specific moments.
When a unit dies, another trigger will loop through the array of units (with TempInteger as its index instead of regular indexes) and will call this while it is looping. The TempInteger doesnt have to be a unique variable and therefor I just make it a Temp... variable so I know that I can use it in every other trigger too.

Also, what you do with the loop is that you use it as a "While" loop in code language. However this "For each integer variable from X to Y" loop has more similarity to "For" loop in code language.
Use "Integer A" to refer to the current loop instead of tempInteger2
That could indeed be done but then I get cought by the efficiency police (Mythic) to make an index variable myself instead of using the basic WC3 ForEachLoopA.

It may really be that the tempInteger holds bad value and so you destroy non-existing lightning, resulting in game crash.
Just try to get rid of that action alone and check if your game still crashes.

1 thing: I KNOW that the destroylightning action crashes the game otherwise I wouldve made another title for this thread.
And I already said that in the first post.

2: Even if I refer to a null variable, then it still doesnt crash the game.
I copied the destoy lightning action and put it in the trigger that catches the ability, before there is any lightning on the whole map.

____________________________________________________________________________

Destroyed handles are not null. There is a difference.

When a handle is destroyed, the reference still points to that spot in memory. In the case of DestroyLightning(), if a valid lightning object is not at that point in memory, then it will force a crash.

To fix this, you have to null a lightning variable after destroying it. In your case:
  • Lightning - Destroy MCS_LightningArray[TempInteger2]
  • Custom script: set udg_MCS_LightningArray[udg_TempInteger2] = null
That should fix the crashes (assuming that operating on a null lightning variable won't cause crashes. if it still crashes, try checking if the variable points to null before operating on the lightning).

If it still crashes after all that, then perhaps it is unrelated to lightning.

I am very confused right now because I cannot understand how this is actually working... yes it works perfectly now.

First of all I assumed that when I override the previous variable in the part where I put all data of the rows one place back, the value of that memory had no pointer any more and is therefor removed.

The point is that this value is only accessed by that trigger that is turned off after the lightning is removed.
So the crash comes because I set a new value to a variable that referred to a destroyed lightning...
I actually kinda start to lose confidence in the engine.
 
Level 25
Joined
Sep 26, 2009
Messages
2,378
That could indeed be done but then I get cought by the efficiency police (Mythic) to make an index variable myself instead of using the basic WC3 ForEachLoopA.
Mythic was most likely pointing out to not use Integer A and Integer B.
GUI has actually 3 loops.
1) For each (Integer A) from X to Y do (Actions)
2) For each (Integer B) from X to Y do (Actions)
3) For each (Integer variable) from X to Y do (Actions)

He meant to use the 3rd option. There you put your own variable instead of Integer A/B and work with it.
 
Level 12
Joined
Oct 16, 2010
Messages
680
Its possible that when one of the units die the lighting is get destroyed and therefor u try to destroy a non existing lightning.. I had similar problem once ago and solved like this
make 2 dummy(link those with the lightning) repos them on top of the two units in the loop and if one of 'em dies that won't affect the lightning in any way and u can destroy/null it properly.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Its possible that when one of the units die the lighting is get destroyed and therefor u try to destroy a non existing lightning.. I had similar problem once ago and solved like this
make 2 dummy(link those with the lightning) repos them on top of the two units in the loop and if one of 'em dies that won't affect the lightning in any way and u can destroy/null it properly.

But a lightning cannot be attached to a unit. Instead it is attached to a location (equal to the unit's location)
If you call DestroyLightning on a null value, it will just negate the order.


Next to that it was already fixed XD
 
Status
Not open for further replies.
Top