Using the "If OldVariable != Variable then {do stuff; OldVariable = Variable)" trick
I want my actor to change color every time an internal variable, let's say it's called HitPoints, is updated. Since this variable can get updated in a number of places, I want the Rule that changes the color to be separate from the ones that update the variable. In order to detect the change and trigger and event, I create another variable of the same type and call it "Old HitPoints." I set this to something different from the original HitPoints so force the first firing of the rule to make sure we start at the right color. I then use this type of Rule:
If OldHitPoints != HitPoints then
Update my color
OldHitPoints = Hitpoints
The rule fires once, but never again. This is the only condition in the rule, and I could swear I've used this kind of detection before to cause the rule to fire every single time the two variables are different. It fires immediately because OldHitPoints != HitPoints, but subsequent changes to HitPoints doesn't make the rule fire again.
I can add a timer-type condition or an actual timer around it to force re-evaluation, but naturally this is a huge performance hit. I can also add a boolean called UpdateColor, and then do this:
Whenever I change HitPoints, I set UpdateColor to "true", then
If UpdateColor then
Update my color
UpdateColor = false
This seems to work, but why does *that* version work when the first version doesn't? It obviously has something to do with whatever conditions cause GS to re-evaluate a Rule, but the only difference I see is that the first version has variables on both sides of the = sign, but the second version has a constant on the right.
Thanks for any help!
If OldHitPoints != HitPoints then
Update my color
OldHitPoints = Hitpoints
The rule fires once, but never again. This is the only condition in the rule, and I could swear I've used this kind of detection before to cause the rule to fire every single time the two variables are different. It fires immediately because OldHitPoints != HitPoints, but subsequent changes to HitPoints doesn't make the rule fire again.
I can add a timer-type condition or an actual timer around it to force re-evaluation, but naturally this is a huge performance hit. I can also add a boolean called UpdateColor, and then do this:
Whenever I change HitPoints, I set UpdateColor to "true", then
If UpdateColor then
Update my color
UpdateColor = false
This seems to work, but why does *that* version work when the first version doesn't? It obviously has something to do with whatever conditions cause GS to re-evaluate a Rule, but the only difference I see is that the first version has variables on both sides of the = sign, but the second version has a constant on the right.
Thanks for any help!
Comments
What I want here is that when an Actor has a certain internal variable altered, it will change color to reflect this.
To do that I make two rules:
Rule 1:
If you click this object
ChangeVariable ClickCount to ClickCount+1
ChangeVariable BooleanUpdateColor to True
Rule 2:
If BooleanUpdateColor is True
Change the color of the object based on ClickCount
ChangeVariable BooleanUpdateColor to False
So when you click on the Actor, ClickCount should increase, and then the second rule should fire and update the color.
If you set the initial value if BooleanUpdateColor to false, it will work with every click, and update the color every time as I expect it to.
If, however, you set the initial value of BooleanUpdateColor to true, Rule 2 will fire once at the beginning, but never again, despite the fact that ClickCount will continue to increment.
This definitely seems like a bug to me. The behavior on the first run through Rule 2 *should* be different based on the initial value of BooleanUpdateColor, but second and subsequent runs should behave *exactly* the same irrespective of the initial value. They do not.
If you watch the value of BooleanUpdateColor, in the first case it stays at False, because it's changed from True to False so fast you can't see it. In the second case, though, when BooleanUpdateColor is initially set to True, it stays at True forever, which is further proof that Rule 2 is never been run again.
To thicken the plot, if you re-write Rule 2 to have the last statement in a timer, it *does* work correctly.
Rule 2:
If BooleanUpdateColor is True
Change the color of the object based on ClickCount
After 0.5 seconds:
ChangeVariable BooleanUpdateColor to False
This would normally make me suspect some kind of synchronization bug, but to me the comparison of the two first cases differing only by the initial value of BooleanUpdateColor means it's a bug.
Thoughts? Rebuttals? Am I missing something? I've already submitted it to GS.
Hi @thebitmaster
As far as I can see, there's no bug. If you set BooleanUpdateColor (why not BoolUpCol? ;-) ) to true, then it'll jump straight to Rule 2 and so bypass the ClickCount updated value.
I can't see your worry – just set the initial state of BooleanUpdateColor to false as you did, and maybe add a condition in Rule 1, and you should be fine.
Rule 1:
When touch is pressed and BooleanUpdateColor is false
ChangeVariable ClickCount to ClickCount+1
ChangeVariable BooleanUpdateColor to True
""You are in a maze of twisty passages, all alike." - Zork temp domain http://spidergriffin.wix.com/alphaghostapps
I the actor that changes color create a local attribute called currentHitPooints
Then put a rule
// this sets the initial value
Change self.currenthitpoints = game.hitpoints
// this updates the color and value of self.currenthitpoints. There might be an 'is not equal to' operator, I just forget, but you can fake it if you need to by using two rules and make the rule flag to any.
Wen self.currenthitpoints > game.hitpoints or self.currenthitpoints< game.hitpoints
Change color
Change attribute self.currenthitpoints = game.hitpoints
That should do it I think. Writing from memory on the train
Send and Receive Data using your own Server Tutorial! | Vote for A Long Way Home on Steam Greenlight! | Ten Years Left
Thanks for trying to help.
If the initial condition of BooleanUpdateColor is set to True, it should fire Rule 2 immediately. The last statement in Rule 2 is to set BooleanUpdateColor to False, which *should* put us back into the original case of it having been set to False to begin with. After that, the behavior should be exactly the same, but it's not.
If I set it to BooleanUpdateColor to False, with each click the color changes correctly, and BooleanUpdateColor ends up as False after each change, as it should be.
If I set it to BooleanUpdateColor to True, the color changes at the beginning of the program, and the BooleanUpdateColor is set to False. This all looks correct. However, if I start clicking, ClickCount increases, but the color never changes again, and BooleanUpdateColor remains True, which means that Rule 2 never fires again, even though BooleanUpdateColor = true is it's one and only condition.
Thanks for trying to help.
How is what you're suggesting different than my first post above? It's using the same OldVariable = Variable methodology. Other than one variable maybe being a global instead of a local (both of mine were local), it looks the same.
That's why I'm confused, though, because I'm pretty sure I used exactly the method that both of us seem to be describing, and whenever Variable was updated by an separate rule, the If OldVariable != Variable rule would fire correctly. Now it's not happening anymore.
the global attribute is needed so all actors can easily track the hitpoints.
give my method a try, it should work (in theory
Send and Receive Data using your own Server Tutorial! | Vote for A Long Way Home on Steam Greenlight! | Ten Years Left
I think you might be looking at the wrong post. The first post I made in this thread didn't use booleans, it used integers, and seems to be exactly the same system you're describing, which, at least currently, doesn't work, even though both of us seem to remember it working in the past. Can you take a look?
In this case the hitpoint-style variable I'm discussing is something that every individual actor has, so it has to be local. But there are several different places within that actor that can alter the hitpoints, which is why I want to have the Rule that changes the color separate, so it fires no matter which other Rule alters the hitpoints.
I did a test using the method I first suggested that you also described. If the initial condition of Variable and OldVariable are the same, it works. However, if they're different, it fires once, and never works again. Try it yourself. I've tried it with both Booleans and Integers, and it's the same bug on either one.
This also means that a simple For loop in a rule doesn't work correctly, either.
ChangeAttribute Looper to 0
Rule 1:
If Looper < 200 then
Do Something
ChangeAttribute Looper to Looper +1
...will only run once, not 200 times. If the entire thing is put inside a timer, or even just the ChangeAttribute is put inside a timer, it will work, but it should not need to be inside the timer. It should keep running as fast as the engine can execute until it's gone 200 times.
forums.gamesalad.com/discussion/5545/tip-arrays-and-loops