Jump to content
Sign in to follow this  
Matthew10_28

Control Structure for an on/off toggle - it has to be easier than I'm making it out to be

Recommended Posts

I've written several scripts to do various things, and I've recognized the need to simplify things a bit, but I can't envision an equally simply control structure.  For example, I have a script that turn on and off the halogen lights at base via nearestObjects and setHit.  I'm doing that through two separate add actions to execVM the code.  One passes the "on" and the other "off".  I want a single "on/off" addAction/execVM, but I what I'm envisioning seems too involved for such a simple action.  Do I setPublicVariable for _switch, and then branch the code depending on that stored value for future interactions?  Do I just not pass it a "_switch" value and let it run pure code that sorts its self out?

 

More generically for a simple "one addAction" toggle, wouldn't I have to test for whatever is set in setPublicVariable before executing the core of the code?  As in, one cannot assume the lamps (or whatver) are on or off.  How do you test for something that seems to be defined after you want to test for it.  I can't not have some form of if or switch/case statement right?  I'm just not seeing the forest through the trees.

private ["_switch"];

_switch = _this select 0;
_hitpoint = 0;
_LampList = nearestObjects[BaseCargoHouse, [
	"Lamps_base_F",
	"PowerLines_base_F",
	"PowerLines_Small_base_F"
], 600];

if (_switch == 0) then {_hitpoint = 0.97};
if (_switch == 1) then {_hitpoint = 0};


{
		_x setHit ["light_1_hitpoint", _hitpoint];
		_x setHit ["light_2_hitpoint", _hitpoint];
		_x setHit ["light_3_hitpoint", _hitpoint];
		_x setHit ["light_4_hitpoint", _hitpoint];
} forEach _LampList;

ETA: how do you get the "spoiler" functionality to work on these forums?

Share this post


Link to post
Share on other sites
_LampList = nearestObjects[BaseCargoHouse, [
	"Lamps_base_F",
	"PowerLines_base_F",
	"PowerLines_Small_base_F"
], 600];

_hitpoint = 0.97;;
_switch = missionNamespace getVariable "Lamp_var_OnOff";
if (_switch == 1) then [{
      _hitpoint = 0; 
      missionNamespace setVariable ["Lamp_var_OnOff",0,true];
},{
      missionNamespace setVariable ["Lamp_var_OnOff",1,true];
}];

{
		_x setHit ["light_1_hitpoint", _hitpoint];
		_x setHit ["light_2_hitpoint", _hitpoint];
		_x setHit ["light_3_hitpoint", _hitpoint];
		_x setHit ["light_4_hitpoint", _hitpoint];
} forEach _LampList;

I would recommend you do your "nearestObjects" line once at server initialization, and store the result in a missionNamespace variable.  Then, use remoteExec from the server to all clients to add the action to turn the lights on and off.  Then, within each addaction, the addaction code should be written to remoteExec to the server and will run on the server.  

 

So let the server do the work, just have the addaction itself be client side, but the code in the addaction gets run on the server.  Then you keep all your variables local to the server (false in the third parameter for setVariable command), and you dont have to run nearestObjects every time which is a pretty expensive command.

Share this post


Link to post
Share on other sites

Let me restate what I heard to confirm my understanding.

 

Said more generically for an on/off toggle type control structure, you've got to define/or obtain the initial state of some variable and set it.  Then let the script alter that and redefine its new value when its done so others can also "push the button" and have it work.

 

As a matter of best practice, do your defining of those variables necessary in the server init.sqf upon start.  Then (as before) the addAction in a particular objects init does nothing more than call the script to run on the server thereby performing the action, then redefining the state of the switch so the next guy who tries can "push the button" once and it work.

 

Unique to my particular example, the nearestObject array command could also be performed at start by placing it in the server init.sqf.  Based on the function of this particular script, this is a suitable solution as the only reason it would need to be recalculated is if someone added a light via Zeus or something post server start.  It is also taxing on the processor, so it's best to run this once.  Using this function in the context of something like an ATC radar would not catch newly spawned or created units though post server start.

 

Now, specific to the code - What is the difference between PublicVariable and missionNamespace setVariable?  It wasn't clear to me reading the wiki.  I've used PublicVariable inside a triggers on acct to gather up the bad guys it finds in its area and pushback as a pushback array and that works on a dedicated server.

Share this post


Link to post
Share on other sites

You don't have to set a variable initially, the alternate syntax allows to return a default value.

_state = _lamp getvariable ["TurnedOn",true];

Will return true if the variable doesn't exist,

if the variable DOES exist it returns the assigned value, like this:

_state = _lamp getvariable ["TurnedOn",true];
hint str _state; //true

_lamp setvariable ["TurnedOn","no"];
_state = _lamp getvariable ["TurnedOn",true];
hint str _state; //"no"

No need to pre set any variable.

 

Cheers

Share this post


Link to post
Share on other sites


fnc_lightToggle =

{

missionNamespace setVariable [

"LightSwitch",

!(missionNamespace getVariable ["LightSwitch", false]),

true

];

if (LightSwitch) exitWith

{

//switch on lights

};

//switch off lights

};

call fnc_lightToggle; //light on

call fnc_lightToggle; //light off

call fnc_lightToggle; //light on

call fnc_lightToggle; //light off

call fnc_lightToggle; //light on

call fnc_lightToggle; //light off

Share this post


Link to post
Share on other sites
_switch = missionNamespace getVariable "Lamp_var_OnOff";

Had to stare at this one for a while but I think I understand it.  It works if you change that line to _switch = missionNamespace getVariable ["Lamp_var_OnOff",0];  Looks like you forgot that part right?  Odd thing is, once I stopped passing the script a parameter it no longer needed it stopped working.  I must have goofed up the syntax.  

 

 _state = _lamp getvariable ["TurnedOn",true];
hint str _state; //true

_lamp setvariable ["TurnedOn","no"];  //I don't understand why you have to define the nameSpace as _lamp.  Is the only purpose for that as a medium by which to thereby define _state?  Also, shouldn't that "no" be false?
_state = _lamp getvariable ["TurnedOn",true];
hint str _state; //"no"

See comments above.  In any case I couldn't fudge it to work so I'm lacking comprehension on the guidance there.

 

fnc_lightToggle = 
{
	missionNamespace setVariable [  //set a variable name as...
		"LightSwitch",          //"LightSwitch"
		!(missionNamespace getVariable ["LightSwitch", false], //...and set its value to the opposite of what you get when you look for the variable name "Lightswitch" which, if not defined is false. You missed the closing ) 
		true  //...and that value is set to public. 
	];
	if (LightSwitch) exitWith //I don't understand the condition check here.  It's not evaluating anything?  
	{
		//switch on lights
	};
	//switch off lights
};

call fnc_lightToggle; //light on
call fnc_lightToggle; //light off
call fnc_lightToggle; //light on
call fnc_lightToggle; //light off
call fnc_lightToggle; //light on
call fnc_lightToggle; //light off

Elegant.  Made me read about inline functions which is good.  I'm having a hard time commenting my way through what is going on in the noted section above.  Specific to my usage, are you implying that my nearestObjects scan would take place outside of that function?

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
Sign in to follow this  

×