Jump to content
Sign in to follow this  
afp

Some advises

Recommended Posts

I've been looking through several scripts made by community, I'd like to share some of the tricks/things I've realised etc while doing this. There is no special chapter nor order just a bunch of advices some of you may find useful:

1. Naming conventions. There are tons of documents about this, most of community people working in IT know it and use it. But some of you have learnt the basics of programming here, so you need to know something about the best practices. You can find lot of naming conventions on internet, most used today are the ones of C++ or.Net/Java styles (I'd personally go with the last one).

I'll tell you several basic rules, you will discover their utility in time.

  • Use sugestive names for variables, do not use letters/abreviations. There is no point in saving hard disk space by naming a folder "m" instead of "models", "s" instead of "scripts" or "_s" instead of "_speed". As a common exception, a single letter is used for loops iterator (index), as _i.
  • Do not use redundant names, if a folder is named "model" do not put inside "model_m14.p3d", "model_m16.p3d" etc., "m14", "m16" would be just enough. So in classes, the members do not have to repeat class name's.
  • Do not overload the name if not necessary, use _speed instead of _bulletSpeed if the whole script has one single speed and is about fire processing.
  • Indent and align the scripts code, align brackets. Use a single line for each statement, leave horizontal spaces between logical parts. Again, do not "save" disk space.
  • Use comments, you will forget in time what you did in that piece of code. Describe the whole script in the beggining, so the usage.
  • You can also use the so called "CamelNotation" for your scripts, for example naming variables and functions like "aceGetCurrentWeapon()" or "aceGlobalVariable". If you start with one of the styles, stick to it.
  • Use suggestive names for boolean variables, like "isReady", "isDead", "hasLeft", "canPiss" etc.
  • Use plural if logic requires it, for example name a folder "models" if it contains several, or "scripts" if more than one. So in arrays, use "units[]" if they are more. You can use "_unit" for one element later.

2. Rewriting. Avoid to rewrite default variables or functions under different names. Renaming a function just for adding a parameter check is redundant, you now have two things doing the same, need to memorize two names, some other guys will use the original function and the code become a mess. So the macros, masking original names or default statements under macros is not always a good ideea.

3. Even if some may say this breaks some programming rules, the lack of "continue" statement for loops leads many times of some weird code where several tens of "if"s shift the code one metter to the right, horizontally, which sucks badly. Not sure if it is a better way but I used something like bellow, making a double loop to be able to "skip" some processing

scopeName "main";
while {true} do 
{ 
scopeName "continue"; 
while {true} do 
       {
         // some condition that never happen for the current item, skip it
	if (skipCondition) then
	{
		breakTo "continue"; // or exitWith{}, will do the same
	};


	// current loop item is valid, processing here, no code shifted to the right
	....

	if (someEndCondition) then
	{
		// end whole loop, actually both of them
		breakTo "main";
	};

};
};

or simplier:

scopeName "main";
while {true} do 
{ 
while {true} do 
       {
         // some condition that never happen 
	if (skipCondition) exitWith{};


	// current loop item is valid, processing here, no code shifted to the right
	....

	if (someEndCondition) then
	{
		// end whole loop, actually both of them
		breakTo "main";
	};

};
};

This lead to a more understandable code when you have to process many conditions. Just be carefull when leaving the second loop with exitWith{}, this will get you in the first one.

Also you can compact "if"'s by adding more conditions under the same "if".

if (condition1) then 
{
	if (condition2) then 
{
	<code1>
}
else
{
	<code2>
}
}
else
{
<code3>
}

can become

if (condition1 && condition2) then 
{
       <code1>
}

if (condition1 && !condition2) then 
{
       <code2>
}

if (!condition1) then 
{
       <code3>
}

4. Config files. Well most of us modify them a lot, "unbinarizing" them is not a good ideea since you lose comments, indentation etc or can even mess the file. The best way to save the original is to put the config file archived (zipped) inside the .pbo. This way when you come back to it after some time, you don't need to remember where you let it.

5. You can derive a class from the base class "Mode_SingleFire" or "Mode_FullAuto" and make a general AI engagement class easier to update/control. For example class MG762Auto: Mode_FullAuto{...maxDistance=.....} ...... then each machinegun will have: modes[] = "MG762Auto"; Sometimes AI engage with one fire per second at 600m away, which is more than weird. You can test it by changing in AiSkills accuracy to 0. Also, AI should not use automatic fire over 100m I guess, unless having a machine gun.

6. Sounds - some of the sounds in the sound mods have some seconds of silence in the end, thus making the sound grow from 100k to half megabyte. That is useless and can be removed with any sound editing program, making the sound load faster and the mod smaller.

That's it for the moment, I hope some of you may find some utility in these.

Edited by afp

Share this post


Link to post
Share on other sites

Good points.

2) could need an example

First example of three is badly formatted making it misleading.

Also instead of breakTo, you can use exit conditions as part of the while condition or exitWith to leave the current scope.

The second example should be done with switch case.

Share this post


Link to post
Share on other sites

Yes, I know is bad formatted, I just put it that way to suggest its actually a single loop. So the "breakTo" command, to see it acts like "continue".

In the second sample, I reffer at pieces of code like with 10 "if", but I simplified. Feel free to post best practices here, after checking some scripts I realized this can really help.

EDIT:

Rewriting:

I reffer at things like this: "removeAllWeapons" becames MYADDON_REMOVE_WEAPONS { _unit = _this select 0; if (!alive _unit) then { ....exit...}; removeAllWeapons _unit};

Edited by afp

Share this post


Link to post
Share on other sites

Great, just feel free to add it. I have searched that page a lot yesterday, related to some multiplayer issues, it have had some other name before, something with "multiplayer", that's why I couldn't find it...

Share this post


Link to post
Share on other sites

There is another situation I have to remind, the "continue" loops above only work for infinite loops like "while (true)". If you need to skip some items in an iterative finite loop, you need to embed an "if" inside the loop. Here's the code:

for "_i" from 0 to (count Units - 1) do
{
if (true) then
{
              _unit = Units select _i;

              if (!(alive _unit)) exitWith{}; // skip dead units                

              if (speed _unit > 70) exitWith{}; // also skip fast units

              process _unit; // code not shifted 8 screens any more
               ....
};
};

That's it, you got the point. Hope it helps. Or maybe they will add "continue" in a future patch.

Edited by afp

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  

×