Jump to content
evans d [16aa]

Help Creating a While Loop

Recommended Posts

Ladies and gentlemen,

 

I'm trying to get a light to turn off by way of dimming so it's not a sudden binary change from on to of, and while I've got it working manually (by way of about 20 sleep commands), I feel like I should be able to do it a lot more aesthetically with a While loop.

 

The problem is, I don't have a clue how to word it.

 

I've just spent 5 minutes trying to type in example code that I've thought of, but the syntax just doesn't look right and I can't wrap my noggin' around it.

 

My current method is bellow, and you can see what I mean: it's functional, but amateur, clunky and untidy.

 

Spoiler

insertHeliLight = "#lightpoint" createVehicle position insertHeliLight;

insertHeliLight setLightBrightness 0.3;

insertHeliLight setLightAmbient[0.3, 0.1, 0.1];

insertHeliLight setLightColor[1, 0, 0];

insertHeliLight lightAttachObject [insertHeli, [0,0,0]];

hint "Light created. Waiting for trigger activation.";

waitUntil {triggerActivated trig_test_PlayFlightpath};

hint "Trigger Activated";

sleep 3;

	insertHeliLight setLightAmbient[0.285, 0.095, 0.095];

	insertHeliLight setLightColor[0.95, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.27, 0.09, 0.09];

	insertHeliLight setLightColor[0.9, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.255, 0.085, 0.085];

	insertHeliLight setLightColor[0.85, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.24, 0.08, 0.08];

	insertHeliLight setLightColor[0.8, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.225, 0.075, 0.075];

	insertHeliLight setLightColor[0.75, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.21, 0.07, 0.07];

	insertHeliLight setLightColor[0.7, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.195, 0.065, 0.065];

	insertHeliLight setLightColor[0.65, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.18, 0.06, 0.06];

	insertHeliLight setLightColor[0.6, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.165, 0.055, 0.055];

	insertHeliLight setLightColor[0.55, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.15, 0.05, 0.05];

	insertHeliLight setLightColor[0.5, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.135, 0.045, 0.045];

	insertHeliLight setLightColor[0.45, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.12, 0.04, 0.04];

	insertHeliLight setLightColor[0.4, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.105, 0.035, 0.035];

	insertHeliLight setLightColor[0.35, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.09, 0.03, 0.03];

	insertHeliLight setLightColor[0.3, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.075, 0.025, 0.025];

	insertHeliLight setLightColor[0.25, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.06, 0.02, 0.02];

	insertHeliLight setLightColor[0.2, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.045, 0.015, 0.015];

	insertHeliLight setLightColor[0.15, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.03, 0.01, 0.01];

	insertHeliLight setLightColor[0.1, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.015, 0.005, 0.005];

	insertHeliLight setLightColor[0.05, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0, 0, 0];

	insertHeliLight setLightColor[0, 0, 0];
	
hint "Light off";

 

 

Cheers in advance for the help.

 - Evans

 

EDIT 1:

I've been dicking about with my script and I've come up with the following. The problem is, it still throws a generic error (missing ;) on the highlighted line(s):

Spoiler

a = 0.3;
b = 0.1;
c = 0.1;
d = 1;

testInt = 0;

insertHeliLight = "#lightpoint" createVehicle position insertHeliLight;

insertHeliLight setLightBrightness 0.3;

insertHeliLight setLightAmbient[a, b, c];

insertHeliLight setLightColor[d, 0, 0];

insertHeliLight lightAttachObject [insertHeli, [0,0,0]];

hint "Light created. Waiting for trigger activation.";

waitUntil {triggerActivated trig_test_PlayFlightpath};

hint "Trigger Activated";

hint "While loop started.";

while {
	a != 0; 
	b != 0; 
	c != 0;
	d != 0;
	}; do

//+++++++++++++++++++++++++++++++\\
//++++++++++ ERROR ++++++++++++++\\
//+++++++++++++++++++++++++++++++\\
	{
		a = a - 0.15;
		b = b - 0.05;
		c = c - 0.05;
		d = d - 0.05;

		testInt = testInt + 1;

		hint testInt;
	};
//+++++++++++++++++++++++++++++++\\

hint "While loop completed.";

 

 

Share this post


Link to post
Share on other sites
_ambientR = 0.285;
_ambientGB = 0.095;
_colorR = 0.95;

for "_i" from 1 to 20 do {
      insertHeliLight setLightAmbient [ _ambientR, _ambientGB, _ambientGB]; 
      insertHeliLight setLightColor [_colorR, 0, 0];
  
     _ambientR = _ambientR - 0.015;
     _ambientGB  = _ambientGB  - 0.005;
     _colorR  = _colorR  - 0.05;

     sleep 0.1;
};

I think this could work, didn't test it tho, so no guarantees.

Share this post


Link to post
Share on other sites

Cheers for the help. That works, but it seems happen that little bit too quick. Do you know how you'd change it to work with sleep commands?

 

EDIT:

Perhaps it would be better if I posted the whole of my script. I've also edited my OP so the whole script is shown, rather than just the dimming bits.

Spoiler

insertHeliLight = "#lightpoint" createVehicle position insertHeliLight;

insertHeliLight setLightBrightness 0.3;

insertHeliLight setLightAmbient[0.3, 0.1, 0.1];

insertHeliLight setLightColor[1, 0, 0];

insertHeliLight lightAttachObject [insertHeli, [0,0,0]];

hint "Light created. Waiting for trigger activation.";

waitUntil {triggerActivated trig_test_PlayFlightpath};

hint "Trigger Activated";

sleep 3;

	insertHeliLight setLightAmbient[0.285, 0.095, 0.095];

	insertHeliLight setLightColor[0.95, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.27, 0.09, 0.09];

	insertHeliLight setLightColor[0.9, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.255, 0.085, 0.085];

	insertHeliLight setLightColor[0.85, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.24, 0.08, 0.08];

	insertHeliLight setLightColor[0.8, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.225, 0.075, 0.075];

	insertHeliLight setLightColor[0.75, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.21, 0.07, 0.07];

	insertHeliLight setLightColor[0.7, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.195, 0.065, 0.065];

	insertHeliLight setLightColor[0.65, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.18, 0.06, 0.06];

	insertHeliLight setLightColor[0.6, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.165, 0.055, 0.055];

	insertHeliLight setLightColor[0.55, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.15, 0.05, 0.05];

	insertHeliLight setLightColor[0.5, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.135, 0.045, 0.045];

	insertHeliLight setLightColor[0.45, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.12, 0.04, 0.04];

	insertHeliLight setLightColor[0.4, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.105, 0.035, 0.035];

	insertHeliLight setLightColor[0.35, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.09, 0.03, 0.03];

	insertHeliLight setLightColor[0.3, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.075, 0.025, 0.025];

	insertHeliLight setLightColor[0.25, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.06, 0.02, 0.02];

	insertHeliLight setLightColor[0.2, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.045, 0.015, 0.015];

	insertHeliLight setLightColor[0.15, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.03, 0.01, 0.01];

	insertHeliLight setLightColor[0.1, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0.015, 0.005, 0.005];

	insertHeliLight setLightColor[0.05, 0, 0];

sleep 0.1;

	insertHeliLight setLightAmbient[0, 0, 0];

	insertHeliLight setLightColor[0, 0, 0];
	
hint "Light off";

 

 

EDIT 2:

I'm a mong. Your code DOES have a sleep command...

Share this post


Link to post
Share on other sites

Why not just change the brightness?

Assuming you have it set to 1 when created:

 

[] spawn {
    _br = 1;
    for "_i" from 1 to 20 do 
    {
        _sub = _i / 20;
        insertHeliLight setLightBrightness (_br - _sub);
        sleep 0.1;
    };
};

Tested.

Share this post


Link to post
Share on other sites

Oh, that's my debug version, just remove the spawn wrapper for placement into your script.

Share this post


Link to post
Share on other sites

Harzach, thanks for the help. Brightness actually starts at 0.3, so I edited your code to read:

_br = 0.3;
    for "_i" from 1 to 20 do 
    {
        _sub = _i / 20;
        insertHeliLight setLightBrightness (_br - _sub);
        sleep 0.1;
    };

The problem now is that it dims (still rather fast, but I wonder if I could change that by changing the 20s to 100s or something) but then lights back up again.

Share this post


Link to post
Share on other sites
_br = 0.3;
_sub = 0.01;
for "_i" from 1 to 30 do 
{
    _br = _br - _sub;
    insertHeliLight setLightBrightness _br;
    sleep 0.1;
};

 

Share this post


Link to post
Share on other sites

You can either increase the sleep time or the amount of times the loop runs to make it go less fast.  If you increase the amount of times the loop runs don't forget to change the step-size of the decrease in light brightness etc.  

Share this post


Link to post
Share on other sites

Also, the longer the sleep time, the more "stepping" you'll see in the dimming.

Share this post


Link to post
Share on other sites

Gentlemen, thank you very much. You'd sorted that out nicely for me. I'd a bit disappointed that my idea of a while loop kept flagging that error, but you've created a great workaround.

 

Cheers again!

  • Like 1

Share this post


Link to post
Share on other sites

Up

_duration = 4;
_maxB = 1;
_minB = 0;
_startAt = time;
_stopAt = time + _duration;
waitUntil {
        insertHeliLight setLightBrightness linearConversion [_startAt, _stopAt, time, _maxB, _minB, true ];
        time >= _stopAt
};

insertHeliLight setLightBrightness _minB;

Here's another way to do it using waitUntil, the following gives direct control over duration without the stepping issue, the light should be updated each frame giving optimal smoothness. (I'm sorry about the formatting, I can't access the code tool on my phone.  Fixed!)

_duration = 4;
_maxB = 1;
_minB = 0;
_startAt = time;
_stopAt = time + _duration;
waitUntil {
        insertHeliLight setLightBrightness linearConversion [_startAt, _stopAt, time, _maxB, _minB, true ];
        time < _stopAt
};

insertHeliLight setLightBrightness _minB;

 

Simply change maxB, minB and duration to your liking.

 

Works for turning on lights too, to do that switch min and max values. 

Edited by mrcurry
Corrected waitUntil exit condition
  • Like 1

Share this post


Link to post
Share on other sites
2 hours ago, mrcurry said:

Here's another way to do it using waitUntil, the following gives direct control over duration without the stepping issue, the light should be updated each frame giving optimal smoothness. (I'm sorry about the formatting, I can't access the code tool on my phone.)

 

_duration = 4;

_maxB = 1;

_minB = 0;

_startAt = time;

_stopAt = time + _duration;

 

waitUntil {

        insertHeliLight setLightBrightness linearConversion [_startAt, _stopAt, time, _maxB, _minB, true ];

        time < _stopAt

};

insertHeliLight setLightBrightness _minB;

 

Simply change maxB, minB and duration to your liking.

 

Works for turning on lights too, to do that switch min and max values. 

 

Can you give me a little explanation on how this works so I'm able to use this with a modicum of intelligence? I assume I need to change the variable "time" to an integer?

Share this post


Link to post
Share on other sites
1 hour ago, evans d [16aa] said:

 

Can you give me a little explanation on how this works so I'm able to use this with a modicum of intelligence? I assume I need to change the variable "time" to an integer?

 

As @stanhope said it should work out of the box, no changes required. As for the explanation, read on.

 

Bare with me but this is gonna involve math... and I will most likely underrate your knowledge level, but that's on me.

Here's the quick pseudo code for the function:

Define minimum and maximum brightness and desired duration for the fade effect
Get current time and assign it to startTime.
Get current time and add duration, assign it to stopTime.
Assume B(x) is a brightness function.
while current time < stopTime do
	set brightness as B(current time)


Define variables

This is pretty self-explanatory but I'll explain it anyway.

 

We need to know how bright the light should be before we start, so maxValue.

We also need the desired brightness after the fade is complete, so minValue.

We need to know how long it should take, so duration.

 

We need the time we should start which is right away, so startTime = current time.

We need the time to stop which is in duration time, so stopTime = startTime + duration.

 

Assume B(x) is a brightness function

The magic lies in the linearConversion command (I'll link it at the end of this post).

 

We assume that the brightness of the light is a function of time, specifically a linear function since we want the light to fade out at a steady rate. I'm calling that function B(x).

On our imagined line we have two points: P with the coordinates (startTime,maxValue) and Q with the coordinates (stopTime,minValue). These points P and Q give us the line function B(x).

Once we got the function we can input our current time into the B(x) and get a value of brightness corresponding to our current time.

 

(The above three lines is what the linearConversion command does. I recommend you learn to use it, there are countless applications for it.)

 

We input the brightness value into the light and we repeat this step each frame until we've reached the point Q a.k.a. current time >= stopTime.

 

while do

I've chosen to use waitUntil instead since it fires only once per frame, any faster than this would be unnecessary, saving a little bit on performance.

You could replace the waitUntil with a while do loop if you so desired, a while do could run more often then each frame though which we don't need in our case.

 

Hope that helps.

 

BIKI Link:

https://community.bistudio.com/wiki/linearConversion

 

Share this post


Link to post
Share on other sites
2 hours ago, stanhope said:

Not really, time is already an integer, it's an arma function that returns the amount of seconds passed since the start of your mission.  More here: https://community.bistudio.com/wiki/time

 

 

 

Time is not an integer, since it contains fractional components (can be 5.00345 as an example).

On a sidenote time will also never be equal to another number:

time == 10 

will never return true, using "round time" will solve that, worth mentioning.

 

5 hours ago, mrcurry said:

Here's another way to do it using waitUntil, the following gives direct control over duration without the stepping issue, the light should be updated each frame giving optimal smoothness. (I'm sorry about the formatting, I can't access the code tool on my phone.)

 

_duration = 4;

_maxB = 1;

_minB = 0;

_startAt = time;

_stopAt = time + _duration;

 

waitUntil {

        insertHeliLight setLightBrightness linearConversion [_startAt, _stopAt, time, _maxB, _minB, true ];

        time < _stopAt

};

insertHeliLight setLightBrightness _minB;

 

Simply change maxB, minB and duration to your liking.

 

Works for turning on lights too, to do that switch min and max values. 

 

In your example time < _stopAt will immediately return true and exit the waitUntil.

Use >= instead.

 

It's also possible to use an eachFrame eventhandler to guarantee the execution on every frame, since waitUntil can skip one frame, especially with a very complex waitUntil condition or engine load.

 

Cheers

 

 

 

  • Like 1
  • Thanks 2

Share this post


Link to post
Share on other sites
12 hours ago, Grumpy Old Man said:

In your example time < _stopAt will immediately return true and exit the waitUntil.

Use >= instead

Cheers, good spot! Fixed it. 

  • Like 1

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×