Jump to content

Recommended Posts

Thanks for the article.

I personally only defined functions as inline functions and put them into one script file and precompiled that. That was until I found out about CfgFunctions. Definitely a way better for debugging.

Share this post


Link to post
Share on other sites

Within the context of Arma scripting, what exactly would constitute an inline function?

Share this post


Link to post
Share on other sites

 

OK, I kind of expected that. I disagree with the idea that this kind of function is somehow less efficient. The game processes this code in exactly the same way as it processes functions split into dedicated files. This isn't like C++ where making a function inline actually changes the way it is compiled. At the end of the day, it's all just interpreted SQF code anyway. 

Share this post


Link to post
Share on other sites

OK, I kind of expected that. I disagree with the idea that this kind of function is somehow less efficient. The game processes this code in exactly the same way as it processes functions split into dedicated files. This isn't like C++ where making a function inline actually changes the way it is compiled. At the end of the day, it's all just interpreted SQF code anyway. 

I remember a similar conversation/thread on this subject from a long time ago, I don't remember exactly what was said as to why one would be better than the other (or even if it was worth taking the time to choose), but at least as far as I'm concerned it comes down to the script author's preference with inline vs file functions.

Share this post


Link to post
Share on other sites

Well, the reason I changed from inline functions to functions as files, is, it looks more organized and I can add detailed functions headers.

Share this post


Link to post
Share on other sites

Well, the reason I changed from inline functions to functions as files, is, it looks more organized and I can add detailed functions headers.

 

And that is perfectly reasonable, particularly for larger functions that may be reused in several different scenarios or by several different scripters. That said, I don't think it's right to say that inline function code is less efficient because it is processed in exactly the same way. 

Share this post


Link to post
Share on other sites

Thanks but what is the need to copy most of the wiki ? If you have something to add, add it on the wiki it will help much more people. Just sayin'

Share this post


Link to post
Share on other sites

I think the point is to point peoples noses towards a part of the wiki that many here may not know about.

Share this post


Link to post
Share on other sites

 

 

using exitWith without understanding how it works it does NOT exit a script ALWAYS a better method

would be to use this from within your script if (!isServer) then {terminate _thisScript; }; There is no ambigiousity with this method it exits end of story, exitWith should only ever be used to "break" a loop on a condition e.g while {true} do if (some condition) exitWith {};  };

 

Please do not speak of things you do not understand. There is nothing wrong with exitWith and terminate is not an alternative to it. 

  • Like 2

Share this post


Link to post
Share on other sites

I prefer breakTo when trying to return to an outer scope with the return value retained.

 

Also dont forget your semi-colons. Use them wherever possible as they provide a nice performance boost. 

 

Regarding readability. 

 

Some scripts I expect others to use, others I don't. This affects how detailed the comments/headers are.

Share this post


Link to post
Share on other sites

Regarding readability. 

 

Some scripts I expect others to use, others I don't. This affects how detailed the comments/headers are.

Personal maintainability could also be a reason to have sufficient comments/headers in your code. I've worked on scripts since OFP, a lot have been transferred to Arma/Arma 2/Arma 3 and are in existence for well over 10 years. Being able to read comments in the code does help in understanding why on earth I did what I did back then.

  • Like 5

Share this post


Link to post
Share on other sites

Also dont forget your semi-colons. Use them wherever possible as they provide a nice performance boost. 

 

Wait, what?

  • Like 2

Share this post


Link to post
Share on other sites

Wait, what?

It is a notion popular among script kiddies, so not sure, this one might have been used in jest.

Share this post


Link to post
Share on other sites

It is a notion popular among script kiddies, so not sure, this one might have been used in jest.

 

i don't understand too... Can you explain it without sarcasm. I'm not a native english

Share this post


Link to post
Share on other sites

It was a joke :)

 

I did not got it. Whatever

Share this post


Link to post
Share on other sites

It was a joke :)

And a funny one, too. The idea is that you don't need to put a semicolon on the last line of a function. I guess there have been performance concerns for years, and this is something that would be brought up from time to time. I always put semicolons at the end of my statements, though, consistency is no joke

 

example:

myLittleFunction =
{
	_plus2 = "";
	if (typeName _this == "SCALAR") then
	{
		_plus2 = _this + 2;
	} else
	{
		["myLittleFunction error, input should be SCALAR, input was: %1", typeName _this] call BIS_fnc_error;
	};
	_plus2; //semicolon not required
};

Share this post


Link to post
Share on other sites

  • ​​initPlayerserver.sqf (Executed only on server when a player joins mission (includes both mission start and JIP). See Figure 1. for details about when the script is exactly executed.)

 

 

One deficiency with using 'initPlayerServer.sqf' event script is that as of A3 1.56 it requires the function 'BIS_fnc_execVM' to be whitelisted for remote execution in CfgRemoteExec. Generally if you care about the code security, you'll not want functions like BIS_fnc_call/BIS_fnc_spawn/BIS_fnc_execVM to be whitelisted, as they allow virtually anything to pass and sort of defeats the purpose of cfgRemoteExec.

 

Also a deficiency of event scripts in general (the recurring ones like initplayerserver,onplayerkilled,onplayerrespawn) is that the code is not saved in memory and as such must be compiled every time its executed, which, while perhaps not significant, is a low-hanging fruit for code optimization, to ensure you are doing all your compiling of frequently used code at the start of the session. initserver and initplayerlocal event scripts are less important as they are only expected to run once, so no need to store in memory.

 

Alternative to initplayerserver.sqf:

//initServer.sqf or better, cfgFunctions library
tag_fnc_initplayerserver = {
     params ['_player','_isJip'];
     /* Code to run on server when client connects */
};
publicVariable 'tag_fnc_initplayerserver';
 
 
//initPlayerLocal.sqf
[player,didJIP] remoteExec ['tag_fnc_initplayerserver',2,FALSE];
 
//description.ext
class cfgRemoteExec {
     Functions {
          class tag_fnc_initplayerserver {allowedTargets = 2;};
     };
};

..

 

^ Same functionality as initplayerserver.sqf, without the BIS_fnc_execVM remote execution loophole.

  • Like 1

Share this post


Link to post
Share on other sites

Seeing as we are talking about standardization, I hope to offer a little input into UI scripting and configuration. I've read a few times that it is best to define the UI event handlers in the config (some performance increase, and some security increase - depending on where and when these handlers are initialized of course). Obviously there are some instances where handlers will still need to be defined in the function/script files (best example of this is when attempting to execute the serverCommand command as it can only be called inside an eventHandler for security reasons). I find it better to have all the functions/script commands to be in one script so that there is less to find, but it is still important to structure your code so that others can make sense of it! I have never tried this method with more than 20 switch cases, so I dont know what the performance of that would be like, but I think that if you need 20 different cases, the task you are attempting to complete needs to be restructured as having a small interface that can do 20 things at once starts verging on becoming complicated.

 

For interfaces that take use actions I found that the best set-up is the following:

 

Example of interface:

class RscdisplaySomeDisplay {
  idd = 100;
  onLoad = "_nul = [""onLoad"",_this] execVM ""RscDisplaySomeDisplay.sqf"";";
  onUnLoad = "_nul = [""onUnLoad"",_this] execVM ""RscDisplaySomeDisplay.sqf"";";
  class Controls {
    class ButtonConfirm : RscButton {
      idc = 1000;
      text = "Close";
      x = 0;
      y = 0;
      w = 0.02;
      h = 0.01;
      onButtonClick = "_nul = [""buttonClose"",_this] execVM ""RscDisplaySomeDisplay.sqf"";";
    };
  };
};

RscDisplaySomeDisplay.sqf

if !(hasInterface) exitWith { false; }; // does nothing -- returns false
disableSerialization;
_this params [
  ["_mode","",[""]],
  ["_params",[],[]]
];
switch (_mode) do {
  case "onLaod" : {
    // code to run on load event
    _display = _params [0,displayNull,[displayNull];

  };
  case "onUnLoad" : {
    // code to run on unload event
    _params params [
      ["_dislpay",displayNull,[displayNull]],
      ["_exitCode",-1,[0]]
    ];
  };
  case "buttonClose" : {
    // closes display - uses exitCode 1
    _btnCloseCtrl = _params param [0,controlNull,[controlNull]];
    _display = ctrlParent _btnCloseCtrl;
    _display closeDisplay 1;
  };
  default {
    /*
      - insert default code into this scope.
      - code in here is usualy an error message based on the mode
      that was attempted to be run
    */
  };
};

You could even better the situation by setting these scripts as compiled functions and either spawning or calling them!

 

I hope this is a useful contribution,

 

Bull

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

×