Tried to describe it the best I can in such a short title.
You may ask why I care about this bug, thats because it happened to sneak into my map and took me hours to find out what was screwing up my map. I know a way to get around it but I can't directly fix the bug yet. I think Blizzard will need to see this. Maybe some bad coding habit.
The Problem: When you set a unit to a unit variable array. Then make a trigger that fires when that unit variable takes damage, Zerg buildings are so dumb that they believe they are the unit variable.
So what do you think of this. Strangest bug in the editor so far?
Btw I uploaded map so you can check. Change the variable to a non-array after and you can see the problem goes away.
I'll take a crack at this. I'll edit this post when I've come to a conclusion. :)
EDIT: Okay, looked at it. Apparently, it also fires if the marines shoot at each other. So it's not just zerg building decay. I'd love to know the reason behind this (what's going on with the memory stack), but it does appear that the event is unstable with unit arrays.
Congrats sir, you deserve at least a month of premium Curse.
This is not a bug. It is designed to be so. This has been brought up so many time: Never use a variable inside many events, including yours: unit taking damage. It's always not working as intended since variable inside event never get updated. It is set as what it is at map initialization. (In your case, your variable = no unit ) So it should fire when any unit taking damage. What people do instead is to set the event Any unit taking damage. And use condition to check whether that unit is what you want. (this case it does update variable value)
Hope this help
Edit: The reason for this is probably because event need to be stable/ unchanged for triggering a lot of actions
I figured out some more information. If its a normal unit variable (non-array) and you set the trigger later, other units taking damage will trigger it, until that variable is set. So the variable does get updated.
However I like you said, adding it to the condition does fix the problem, because not only does it update with array variables, but when its set to no unit, other units don't believe its them.
Not quite. As he said, and as I tested it, it works fine if you use a simple unit variable. It's when you turn it into an array (and register the event with a valid slot in the array) that things go awry. While I understand that it's a coding practice carried over from WC3 to avoid using variables in events, since WC3 binds events by value, these experiments have shown that the event responds as if it binds by reference.
EDIT: Experimented with it again, I made a trigger that changes the Bunker variable (not an array anymore) to the Nydus Network building upon typing "-test". I first had the marines attack the Bunker - trigger fired. Then I typed "-test" and it started reporting the Nydus Network building's decay damage.
Further evidence that this event appears to function by reference.
EDIT 2: "Unit is Attacked" behaves the exact same way as reported above in every post in this thread.
Also, while it's true that using the condition solves the problem, it is inefficient. You now have the trigger firing every time any unit takes damage (and it checks the condition). If we could get it so array variables are ok with events, then you can dramatically reduce the number of trigger calls.
It's not game breaking or anything, I'm just pointing out that it is more inefficient than it should be.
Also, while it's true that using the condition solves the problem, it is inefficient. You now have the trigger firing every time any unit takes damage (and it checks the condition). If we could get it so array variables are ok with events, then you can dramatically reduce the number of trigger calls.
It's not game breaking or anything, I'm just pointing out that it is more inefficient than it should be.
That's why I was debating to just create 6 variables or to use a condition. I was going to ask if adding the condition makes it less efficient. I wasn't sure if having the unit in the event and having it in the condition were efficiently the same thing and that it just added the condition in the background. I guess I could look at the code in galaxy to find out. For now I'll stick with 6 variables.
What's happening is "gt_InitialSpawn_Init()" is being called right before map initialization by InitMap().
What this does is add the trigger to set the gv_bunkers[1] at map initialization (next game cycle update).
Then it moves on and calls gt_BunkerAttacked_Init(). At this time, however, gv_bunkers[1] = null. Remember, the map hasn't actually been initialized yet.
So why does it work when we make the Bunkers variable a simple unit variable?
EDIT: And like I said in my previous post here, it's definitely behaving like events are registered by reference rather than value.
Also, I should point out that if you made the initial value of gv_bunkers (still an array variable in this experiment) point to the nydus network building, it still screws up.
It's working when it's a simple unit variable, because InitGlobals() is called before InitTriggers().
A simple variable is defined in InitGlobals(), then InitTriggers() creates the event with the correct value of the variable, because it's no longer null.
As for the whole initial value of the array thing, a far more likely explanation is that UnitRefFromVariable can't parse the brackets of an array. It probably wasn't intended for complex markup at all.
The OP should've used UnitRefFromUnit(gv_bunkers[1]) to begin with.
To demonstrate my point regarding flow order I've uploaded the map again, with the fix to allow it to actually parse gv_bunkers[1] correctly.
The bug persists, because it was a problem with the way the code was written, not a bug with the event.
As for the UnitRefFromVariable() thing, they probably should. But if they did, they'd also have to make it capable of parsing non-constants such as gv_bunkers[EventPlayer()] and the like. It'd just end up a mess and require them to support real-time compiling in-game.
Tried to describe it the best I can in such a short title.
You may ask why I care about this bug, thats because it happened to sneak into my map and took me hours to find out what was screwing up my map. I know a way to get around it but I can't directly fix the bug yet. I think Blizzard will need to see this. Maybe some bad coding habit.
The Problem: When you set a unit to a unit variable array. Then make a trigger that fires when that unit variable takes damage, Zerg buildings are so dumb that they believe they are the unit variable.
So what do you think of this. Strangest bug in the editor so far?
Btw I uploaded map so you can check. Change the variable to a non-array after and you can see the problem goes away.
Link Removed: http://www.mediafire.com/?qb8b7ud7dw1i4kf
@KelvCM: Go
I'll take a crack at this. I'll edit this post when I've come to a conclusion. :)
EDIT: Okay, looked at it. Apparently, it also fires if the marines shoot at each other. So it's not just zerg building decay. I'd love to know the reason behind this (what's going on with the memory stack), but it does appear that the event is unstable with unit arrays.
Congrats sir, you deserve at least a month of premium Curse.
@OneSoga: Go
I guess I should change the name of the topic.
This is not a bug. It is designed to be so. This has been brought up so many time: Never use a variable inside many events, including yours: unit taking damage. It's always not working as intended since variable inside event never get updated. It is set as what it is at map initialization. (In your case, your variable = no unit ) So it should fire when any unit taking damage. What people do instead is to set the event Any unit taking damage. And use condition to check whether that unit is what you want. (this case it does update variable value)
Hope this help
Edit: The reason for this is probably because event need to be stable/ unchanged for triggering a lot of actions
@progammer: Go
I figured out some more information. If its a normal unit variable (non-array) and you set the trigger later, other units taking damage will trigger it, until that variable is set. So the variable does get updated.
However I like you said, adding it to the condition does fix the problem, because not only does it update with array variables, but when its set to no unit, other units don't believe its them.
@progammer: Go
Not quite. As he said, and as I tested it, it works fine if you use a simple unit variable. It's when you turn it into an array (and register the event with a valid slot in the array) that things go awry. While I understand that it's a coding practice carried over from WC3 to avoid using variables in events, since WC3 binds events by value, these experiments have shown that the event responds as if it binds by reference.
EDIT: Experimented with it again, I made a trigger that changes the Bunker variable (not an array anymore) to the Nydus Network building upon typing "-test". I first had the marines attack the Bunker - trigger fired. Then I typed "-test" and it started reporting the Nydus Network building's decay damage.
Further evidence that this event appears to function by reference.
EDIT 2: "Unit is Attacked" behaves the exact same way as reported above in every post in this thread.
Also, while it's true that using the condition solves the problem, it is inefficient. You now have the trigger firing every time any unit takes damage (and it checks the condition). If we could get it so array variables are ok with events, then you can dramatically reduce the number of trigger calls.
It's not game breaking or anything, I'm just pointing out that it is more inefficient than it should be.
@OneSoga: Go
That's why I was debating to just create 6 variables or to use a condition. I was going to ask if adding the condition makes it less efficient. I wasn't sure if having the unit in the event and having it in the condition were efficiently the same thing and that it just added the condition in the background. I guess I could look at the code in galaxy to find out. For now I'll stick with 6 variables.
Let's take a look at the map script here.
What's happening is "gt_InitialSpawn_Init()" is being called right before map initialization by InitMap().
What this does is add the trigger to set the gv_bunkers[1] at map initialization (next game cycle update).
Then it moves on and calls gt_BunkerAttacked_Init(). At this time, however, gv_bunkers[1] = null. Remember, the map hasn't actually been initialized yet.
So this is not a bug. It is working as intended.
@MotiveMe: Go
So why does it work when we make the Bunkers variable a simple unit variable?
EDIT: And like I said in my previous post here, it's definitely behaving like events are registered by reference rather than value.
Also, I should point out that if you made the initial value of gv_bunkers (still an array variable in this experiment) point to the nydus network building, it still screws up.
So no, sorry, it's not working as intended.
It's working when it's a simple unit variable, because InitGlobals() is called before InitTriggers().
A simple variable is defined in InitGlobals(), then InitTriggers() creates the event with the correct value of the variable, because it's no longer null.
As for the whole initial value of the array thing, a far more likely explanation is that UnitRefFromVariable can't parse the brackets of an array. It probably wasn't intended for complex markup at all.
The OP should've used UnitRefFromUnit(gv_bunkers[1]) to begin with.
Assuming that's true, then shouldn't Blizzard make UnitRefFromVariable capable of parsing array brackets?
That's probably a 2 minutes fix.
To demonstrate my point regarding flow order I've uploaded the map again, with the fix to allow it to actually parse gv_bunkers[1] correctly.
The bug persists, because it was a problem with the way the code was written, not a bug with the event.
As for the UnitRefFromVariable() thing, they probably should. But if they did, they'd also have to make it capable of parsing non-constants such as gv_bunkers[EventPlayer()] and the like. It'd just end up a mess and require them to support real-time compiling in-game.