Jump to content
Sign in to follow this  
kyfohatl

Improving this badly written script...

Recommended Posts

Ok, here's a script that will monitor an area (defined by a trigger) for different factions, and generate a DAC zone for that faction. It's pretty basic, but it works (mostly). It is quite useful for stimulating the capturing of a sector, and using this script faction can gain strog points.

private ["_unitList", "_factionList", "_N0CDF", "_N0USMC", "_N0GUE", "_N0RU", "_paramCDF", "_paramRU", "_paramUSMC", "_paramGUE", "_rulingFaction", "_CDF", "_USMC", "_RU", "_GUE"];

// Waits untill DAC is initiated
sleep 2;

// Defines parameters for DAC zones
_paramCDF = ["z4",[1,0,0],[6,3,40,40],[3,3,30,30],[],[1,4,50,0,100,500],[1,5,1,1,0]];
_paramRU = ["z4",[1,0,0],[6,3,40,40],[3,3,30,30],[],[1,4,50,0,100,500],[0,0,0,1,0]];
_paramUSMC = ["z4",[1,0,0],[6,3,40,40],[3,3,30,30],[],[1,4,50,0,100,500],[1,1,1,1,0]];
_paramGUE = ["z4",[1,0,0],[6,3,40,40],[3,3,30,30],[],[1,4,50,0,100,500],[2,2,2,1,0]];

_CDF = 0;
_USMC = 1;
_RU = 2;
_GUE = 3;
_rulingFaction = 4;


// Loop
while {true} do {
_unitList = _this;

// Counts number of units per faction
_factionList = [];
{_factionList = _factionList + [(faction _x)]} foreach _unitList;
_N0CDF = {_x == 'CDF'} count _factionList;
_N0USMC = {_x == 'USMC'} count _factionList;
_N0GUE = {_x == 'GUE'} count _factionList;
_N0RU = {_x == 'RU'} count _factionList;


// Checks for dominant faction
if ((_N0CDF > _N0USMC) AND (_N0CDF > _N0GUE) AND (_N0CDF > _N0RU)) then {

// Checks to see if the faction doesn't already contorl the area
if (_rulingFaction != _CDF) then {

// Deletes the previous DAC zone
	if (!isNil 'z4') then{
		["z4"] call DAC_fDeleteZone;
		sleep 20;};

	[(getMarkerPos "zone4"),750,500,0,0,_paramCDF] call DAC_fNewZone;
	sleep 300;

// Markes the controlling faction
	_rulingFaction = _CDF;};
};

if ((_N0USMC > _N0CDF) AND (_N0USMC > _N0GUE) AND (_N0USMC > _N0RU)) then {
if (_rulingFaction != _USMC) then {

	if (!isNil "z4") then {
		["z4"] call DAC_fDeleteZone;
		sleep 20;};

	[(getMarkerPos "zone4"),750,500,0,0,_paramUSMC] call DAC_fNewZone;
	sleep 300;
	_rulingFaction = _USMC;};
};

if ((_N0RU > _N0CDF) AND (_N0RU > _N0GUE) AND (_N0RU > _N0CDF)) then {
if (_rulingFacton != _RU) then {

	if (!isNil "z4") then {

		["z4"] call DAC_fDeleteZone;
		sleep 20;};

	[(getMarkerPos "zone4"),750,500,0,0,_paramRU] call DAC_fNewZone;
	sleep 300;
	_rulingFaction = _RU;};
};

if ((_N0GUE > _N0CDF) AND (_N0GUE > _N0USMC) AND (_N0GUE > _N0RU)) then {
if (_rulingFaction != _GUE) then {

	if (!isNil "z4") then {
		["z4"] call DAC_fDeleteZone;
		sleep 20;};

	[(getMarkerPos "zone4"),750,500,0,0,_paramGUE] call DAC_fNewZone;
	sleep 300;
	_rulingFaction = _GUE;};
};
sleep 60;
};

This script was written with lots of help from all of the people who have posted here, notable Big D KS, so my thanks to them.

Though there is still alot of room for improvement:

1. This script has to be run individually for each capturable zone. So if you have say 6 capturable zones in your mission, you'd have to run 6 of these scripts together... which might cause a fair bit of lag.

2. It does not take into account troop quality, only numbers. So if one side has 10 of their lowest ranking troop (and poorly equipped) vs the other that has 9 very high ranking, very high skill and very well equipped spec ops, the side with the 10 guys win.

Any help is appreciated.

Edited by kyfohatl

Share this post


Link to post
Share on other sites

In all the if statements you're checking a variable called '_N0RGUE' where presumably you mean '_N0RGUE'.

You've declared your _Zone variables as private in the BaseMonitor and FactionCount script. You need to make them global (take out the underscore) if you want them to mean the same thing in both scripts.

In answer to question 3: http://community.bistudio.com/wiki/list

Some general tips:

-Comment your code, especially if you want someone else to debug it.

-Use ANDs and ORs instead of nesting lots of ifs, makes your code easier to read

-Avoid goto. Choose a control structure instead

Share this post


Link to post
Share on other sites

Two extra general tips:

1) Stick to one syntax form. Drop SQS (although the man part was SQF).

2) Paste code using code tags rather than quote tags to preserve indents and have proper "code font". They're in the advanced section.

Share this post


Link to post
Share on other sites

Edit: Ok, I think this is what you were trying to accomplish:

Call once with the name of the trigger: (ex: myTrigger execVM "countFaction.sqf")

_trigger = _this;

_parametersCDF = ["z4", [1,0,0],[6,3,40,40],[3,3,30,30],[],[1,4,50,0,100,500], [1,5,1,1,0]];
_parametersRU = ["z4", [1,0,0],[6,3,40,40],[3,3,30,30],[],[1,4,50,0,100,500], [0,0,0,1,0]];
_parametersUSMC = ["z4", [1,0,0],[6,3,40,40],[3,3,30,30],[],[1,4,50,0,100,500], [1,1,1,1,0]];
_parametersGUE = ["z4", [1,0,0],[6,3,40,40],[3,3,30,30],[],[1,4,50,0,100,500], [2,2,2,1,0]];

// function to increment the faction counter of passed unit
_countUnit = {
 private["_faction"];
 _faction = faction _this;
 call compile format ["if(!isNil '_count%1')then{_count%1 = _count%1 + 1}",_faction];
};

_currentFaction = "Default";
// function to get new zone ruler based on count of passed factions
_getNewRulingFaction = {
 private["_max","_newFaction"];
 _max = 0;
 _newFaction = _currentFaction;
 {
   _count = call compile format ["_count%1",_X];
   if(_count > _max)then{
     _max = _count;
     _newFaction = _X;
   }
 } forEach _this;
 _newFaction
};

// main loop
while{true}do{

// get list of units
_unitList = list _trigger;

_countCDF = 0;
_countUSMC = 0;
_countRU = 0;
_countGUE = 0;

// count units for each faction
{_X call _countUnit} forEach _unitList;

// get new ruling faction
_newFaction = ["CDF","USMC","RU","GUE"] call _getNewRulingFaction;
if(_newFaction != _currentFaction)then{

_currentFaction = _newFaction;
["z4"] call DAC_fDeleteZone;
[(getMarkerPos "zone4"),750,500,0,0,call compile format ["_parameters%1",_newFaction]] call DAC_fNewZone;

};

sleep 40;

};

Edited by Big Dawg KS
Fixed missing semicolon

Share this post


Link to post
Share on other sites

Thanks to everyone for their good advice. I took up the advice and tried to improve my original script (like making some variables global, dropping SQS, making lots of corrections), but it still didn't work. On the other hand Big D. KS' scripts seems to be much simpler (and far superior), so I'm going to try to take up his.

@Big D. KS:Just a few question on this new script (since I still have trouble understanding some of the more advanced stuff):

-Firstly, when I try to run it, the game give gives me an error, saying that there is a missing ";" at line 32. But from what I can see, you are trying to return a value at line 32 (_newFaction), so there shouldn't be ";". I don't understand what the game is talking about. I tried putting ";" infront of it anyway, but it still didn't work.

-With the count faction part, you seem to be creating a mini-function within a procedure (which I didn't know you could do). Is that what the line:

call compile format ["if(!isNil '_count%1')then{_count%1 = _count%1 + 1}",_faction];

does? This is the line that I'm having most difficulty understanding.

-Maybe to avoide the error of the missing ";", I'd have to seperate the "countFaction" and "getNewRulingFaction" into new funtions (i.e. make two more sqf files, one for each mini-function you created), or is what your doing fine? I'm not sure because as I said, I didn't know that you could create functions within a procedure, and then call the function in the same procedure (at least that's what I think your doing, correct me if I'm wrong).

-Since this is a procedure (because your using the "sleep" command), shouldn't I have to put:

MyprocedureHandler = [myTrigger] execVM "FactionCount.sqf"

in the init.sqs? Rather than what you said which was:

myTrigger execVM "countFaction.sqf"

Because according to Taurus' sqf scripting guide:

"All procedures need to have a script handle"

Or maybe I missunderstood what his talking about?

Thanks to everyone for your kind help :).

EDIT:

@Big D. : By the way, youve set _currentFaction = "Default"; in a script where there is no "switch" command... what does "Default" do in this case?

Edited by kyfohatl

Share this post


Link to post
Share on other sites

Ok, I figured out why the scripts doesn't work. It's because for some reason, the script:

_parametersCDF = ["z4",[1,0,0],[6,3,40,20],[3,3,30,20],[],[],[1,5,1,1]]] call DAC_fNewZone;

[(position player),750,500,0,0,_parametersCDF] call DAC_fNewZone;

doesn't work. I've tried testing it just by itself. i.e.

in the init.sqs:

MyProcedureHandler = [] execVM "test.sqf"

and in "test.sqf":

sleep 2;

_parametersCDF = ["z4",[1,0,0],[6,3,40,20],[3,3,30,20],[],[],[1,5,1,1]]] call DAC_fNewZone;

[(position player),750,500,0,0,_parametersCDF] call DAC_fNewZone;

I really have no idea why this deosn't work. I've searched the DAC thread, as well as looking at the readme. I've also tried all sorts of variants of the scripts, like making it all one big one liner (i.e. getting rid of "_parametersCDF"), using two double quotes around z4 (i.e. ""z4""), and writing the script in both SQS and SQF format. As you can see, I've also replaced "(getMarkerPos "Zone4")" with "(position player)" to avoid any other possible problems. Still no luck... :(

Before I post this as a possible bug in the DAC thread, can anyone possibly spot a stupid error in the script above? Some sort of a hidden error maybe? Because according to some posters at the DAC thread, this feuture works fine...

Thanks.

Share this post


Link to post
Share on other sites

Don't know if it's just a typo in your post but you have an extra ']' before call DAC_...

Firstly, when I try to run it, the game give gives me an error, saying that there is a missing ";" at line 32.

Actually the error is the missing semi-colon at the end of the _getNewRulingFaction function before the following 'while' statement.

Edited by sbsmac

Share this post


Link to post
Share on other sites
Don't know if it's just a typo in your post but you have an extra ']' before call DAC_...

Ohhh, yeah, that was a typo in my post. Actually, for those who may be having the same problem as me, when looking at the DAC demo mission, I realized that one DAC zone was necessary to be created before this feuture could work. So I created a DAC zone in the editor first, and then tried running an even simpler, SQS form of the script (to minize the chance of mistakes), which works:

~3

_text = "The script is running"

hint format ["%1", _text]

_para = ["z4",[1,0,0],[6,3,40,20],[3,3,30,20],[],[],[1,5,1,1]]

[(position player),750,500,0,0,_para] call DAC_fNewZone

Actually the error is the missing semi-colon at the end of the _getNewRulingFaction function before the following 'while' statement.

Oh yeah... thanks for pointing that out. I'm definately going to try to use Big D.'s script (still don't understand how some parts of his script works though), becuase I can can imagine how mine is a massive system hog. Plus I have to run one of these for each zone, and in my mission I have 7 capturable zones. I can imagine that if I was to use my version of the script, the game would slow don significantly.

Thanks for the help.

EDIT: Fixed some more errors, but still none of the two scripts work. Whilst Big D KS' script is too advanced for me to try and fix, I'll try and fix my older script. For those who want to know, here is the version that should really work:

private ["_unitList", "_parametersCDF", "_parametersRU", "_parametersUSMC", "_parametersGUE", "_class", "_factionText", "_N0CDF", "_N0RU", "_N0USMC", "_N0GUE"];

ZoneCDF = true;
ZoneRU = true;
ZoneUSMC = true;
ZoneGUE = true;

// Defining the parameters for each faction's DAC zone
_parametersCDF = ["z4", [1,0,0],[6,3,40,40],[3,3,30,30],[],[1,4,50,0,100,500], [1,5,1,1,0]];
_parametersRU = ["z4", [1,0,0],[6,3,40,40],[3,3,30,30],[],[1,4,50,0,100,500], [0,0,0,1,0]];
_parametersUSMC = ["z4", [1,0,0],[6,3,40,40],[3,3,30,30],[],[1,4,50,0,100,500], [1,1,1,1,0]];
_parametersGUE = ["z4", [1,0,0],[6,3,40,40],[3,3,30,30],[],[1,4,50,0,100,500], [2,2,2,1,0]];

// The loop
While {true} do {
_unitList = _this select 0;

// Finding the faction of units within trigger area
FactionList = [];
{_class = typeOf _x; _factionText = getText (ConfigFile >> 'CfgVehicles' >> _class >> 'Faction'); FactionList = FactionList + [_factionText]} foreach _unitList;

// Finding the faction with the largest force in the area
_N0CDF = {_x == 'CDF'} count FactionList;
_N0RU = {_x == 'RU'} count FactionList;
_N0USMC = {_x == 'USMC'} count FactionList;
_N0GUE = {_x == 'GUE'} count FactionList;
sleep 2;

if (_N0CDF > _N0RU) then {
if (_N0CDF > _N0USMC) then {
	if (_N0CDF > _N0GUE) then {
// Checking to see if the zone for the dominating faction doesn't already exist
		if (ZoneCDF) then{
			zoneCDF = false;
			ZoneRU = true;
			ZoneUSMC = true;
			ZoneGUE = true;
// Deletes older zones if they exist
			["z4"] call DAC_fDeleteZone;
// Creates new zone with parameters of the newly ruling faction
			[(getMarkerPos "zone4"),750,500,0,0,_parametersCDF] call DAC_fNewZone;
			sleep 300;
};};};};


if (_N0RU > _N0CDF) then {
if (_N0RU > _N0USMC) then {
	if (_N0RU > _N0GUE) then {
		if (ZoneRU) then{
			zoneCDF = true;
			ZoneRU = false;
			ZoneUSMC = true;
			ZoneGUE = true;
			["z4"] call DAC_fDeleteZone;
			[(getMarkerPos "zone4"),750,500,0,0,_parametersRU] call DAC_fNewZone;
			sleep 300;
};};};};


if (_N0USMC > _N0CDF) then {
if (_N0USMC > _N0RU) then {
	if (_N0USMC > _N0GUE) then {
		if (ZoneUSMC) then{
			zoneCDF = true;
			ZoneRU = true;
			ZoneUSMC = false;
			ZoneGUE = true;
			["z4"] call DAC_fDeleteZone;
			[(getMarkerPos "zone4"),750,500,0,0,_parametersUSMC] call DAC_fNewZone;
			sleep 300;
};};};};


if (_N0GUE > _N0CDF) then {
if (_N0GUE > _N0RU) then {
	if (_N0GUE > _N0USMC) then {
		if (ZoneGUE) then{
			zoneCDF = true;
			ZoneRU = true;
			ZoneUSMC = true;
			ZoneGUE = false;
			["z4"] call DAC_fDeleteZone;
			[(getMarkerPos "zone4"),750,500,0,0,_parametersGUE] call DAC_fNewZone;
			sleep 300;
};};};};
sleep 40
};

When I run it, the game says: "

...tionList = FactionList + [_factionText]} foreach _unitList;

Error foreach: Type Object, expected array

line 17

_N0CDF = {_x == 'CDF'...

"

Ok, so there's something wrong at line 17. Can anyone see what's wrong???

Ohh, and this newer version basically fixes some syntax errors, gets rid of some extra brackets, drops the SQS format, removes the "terminate MyProcedureHandler" line, and adds comments to make debugging easier, as adviced by more experienced (and much better) scripters.

-Use ANDs and ORs instead of nesting lots of ifs, makes your code easier to read

Could I use:

If (_N0GUE > (_N0RU AND _N0CDF AND _N0USMC) then { etc...

instead of the several "if" statements I'm using? I was going to do this, I jsut wasn't sure if it would work.

Edited by kyfohatl

Share this post


Link to post
Share on other sites

Actually the error is the missing semi-colon at the end of the _getNewRulingFaction function before the following 'while' statement.

:o It's hard going from real C-based languages to SQF sometimes... you often forget the little differences.

So I edited my code, it should work now.

call compile format ["if(!isNil '_count%1')then{_count%1 = _count%1 + 1}",_faction];

This is kind of a trick that allows execution of dynamic code. Here I am filling in the %1 with the faction to get the variable for that faction (ex: USMC -> _countUSMC), then compiling and executing that code.

@Big D. : By the way, youve set _currentFaction = "Default"; in a script where there is no "switch" command... what does "Default" do in this case?

Default is the default faction. It's what's returned by the faction command if the unit has no real faction.

"All procedures need to have a script handle"

Using execVM will return a script handle, but you don't have to use it. You only have to assign it to something or the interpreter/compiler yells at you. Ex:

0 = [] execVM "myScript.sqf"

Share this post


Link to post
Share on other sites
it should work now

Sadly it doesn't. I ckecked using the editor, and the game says:

Error List: Type array, expeted object

This error is regarding the line:_unitList = list _trigger; It seems that the variable _trigger returns and array and is not an object. So, I tried getting rid of the "list" command since _trigger is already an array. But it didn't work. Any Help would be much appreciated.

Sorry if I can't fix it myself. I kind of understand how your script works, but when I try to edit your script to try and fix errors, I usually cause more errors probably becuase I only know basic scripting (I'm still learning).

Again, sorry about that.

Thanks

Share this post


Link to post
Share on other sites
Sadly it doesn't. I ckecked using the editor, and the game says:

This error is regarding the line:_unitList = list _trigger; It seems that the variable _trigger returns and array and is not an object. So, I tried getting rid of the "list" command since _trigger is already an array. But it didn't work. Any Help would be much appreciated.

Sorry if I can't fix it myself. I kind of understand how your script works, but when I try to edit your script to try and fix errors, I usually cause more errors probably becuase I only know basic scripting (I'm still learning).

Again, sorry about that.

Thanks

You probably called the script wrong. You should execute it like this:

0 = MyTrigger execVM "myScript.sqf";

Where MyTrigger is the name you give the trigger. Notice how there are no []s around MyTrigger to make it an array.

Share this post


Link to post
Share on other sites
You probably called the script wrong. Notice how there are no []s around MyTrigger to make it an array.

Actually, I didn't have "[]" around "MyTrigger". The "[]" problem I was having was relative to my own script (the crappy one, which is why I started a new thread for it by the way), when I tried to run it after yours didn't work. It still doesn't work :confused:. Here is the script call I'm using:

MyProcedureHandler = MyTrigger execVM "CountFaction.sqf"

See, it's jsut what you told me to do, but its not working. Maybe I've set the trigger to wrong parameters? (Activated by ANYBODY, only ONCE)

Or; are there any commands your using that possibly don't appear in ARMA2 (cause I don't have OA).

Again, thanks for your time.

Share this post


Link to post
Share on other sites

Finally... my version of the script works :yay: (although I adopted a few good ideas from Big D.)

private ["_unitList", "_factionList", "_N0CDF", "_N0USMC", "_N0GUE", "_N0RU", "_paramCDF", "_paramRU", "_paramUSMC", "_paramGUE", "_rulingFaction", "_CDF", "_USMC", "_RU", "_GUE"];

// Waits untill DAC is initiated
sleep 2;

// Defines parameters for DAC zones
_paramCDF = ["z4",[1,0,0],[6,3,40,40],[3,3,30,30],[],[1,4,50,0,100,500],[1,5,1,1,0]];
_paramRU = ["z4",[1,0,0],[6,3,40,40],[3,3,30,30],[],[1,4,50,0,100,500],[0,0,0,1,0]];
_paramUSMC = ["z4",[1,0,0],[6,3,40,40],[3,3,30,30],[],[1,4,50,0,100,500],[1,1,1,1,0]];
_paramGUE = ["z4",[1,0,0],[6,3,40,40],[3,3,30,30],[],[1,4,50,0,100,500],[2,2,2,1,0]];

_CDF = 0;
_USMC = 1;
_RU = 2;
_GUE = 3;
_rulingFaction = 4;


// Loop
while {true} do {
_unitList = _this;

// Counts number of units per faction
_factionList = [];
{_factionList = _factionList + [(faction _x)]} foreach _unitList;
_N0CDF = {_x == 'CDF'} count _factionList;
_N0USMC = {_x == 'USMC'} count _factionList;
_N0GUE = {_x == 'GUE'} count _factionList;
_N0RU = {_x == 'RU'} count _factionList;


// Checks for dominant faction
if ((_N0CDF > _N0USMC) AND (_N0CDF > _N0GUE) AND (_N0CDF > _N0RU)) then {

// Checks to see if the faction doesn't already contorl the area
if (_rulingFaction != _CDF) then {

// Deletes the previous DAC zone
	if (!isNil 'z4') then{
		["z4"] call DAC_fDeleteZone;
		sleep 20;};

	[(getMarkerPos "zone4"),750,500,0,0,_paramCDF] call DAC_fNewZone;
	sleep 300;

// Markes the controlling faction
	_rulingFaction = _CDF;};
};

if ((_N0USMC > _N0CDF) AND (_N0USMC > _N0GUE) AND (_N0USMC > _N0RU)) then {
if (_rulingFaction != _USMC) then {

	if (!isNil "z4") then {
		["z4"] call DAC_fDeleteZone;
		sleep 20;};

	[(getMarkerPos "zone4"),750,500,0,0,_paramUSMC] call DAC_fNewZone;
	sleep 300;
	_rulingFaction = _USMC;};
};

if ((_N0RU > _N0CDF) AND (_N0RU > _N0GUE) AND (_N0RU > _N0CDF)) then {
if (_rulingFacton != _RU) then {

	if (!isNil "z4") then {

		["z4"] call DAC_fDeleteZone;
		sleep 20;};

	[(getMarkerPos "zone4"),750,500,0,0,_paramRU] call DAC_fNewZone;
	sleep 300;
	_rulingFaction = _RU;};
};

if ((_N0GUE > _N0CDF) AND (_N0GUE > _N0USMC) AND (_N0GUE > _N0RU)) then {
if (_rulingFaction != _GUE) then {

	if (!isNil "z4") then {
		["z4"] call DAC_fDeleteZone;
		sleep 20;};

	[(getMarkerPos "zone4"),750,500,0,0,_paramGUE] call DAC_fNewZone;
	sleep 300;
	_rulingFaction = _GUE;};
};
sleep 60;
};

Feel free to use. Though I must say I'm still more interested in Big D's script because it is shorter and neater (plus it'll probably teach me quite laot about scripting).

An immediate problem is that this script has to be run for EVERY capturable zone, and my mission has 8 of them. This means running 8 of these scripts at once... should be a massive resource hog. Any ideas???

Also, edited first post so that people can see the script immediately.

Cheers

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  

×