Jump to content
Sign in to follow this  
igneous01

fired eventhandler - count how many rounds fired

Recommended Posts

ok so i searched for this one everywhere, but i am lost on how to use eventhandlers, the biki said i can call an eventhandler without calling a script and just need "" around the code block i want executed when it happens.

but im still lost on how it works.

for ex.

i have a little script thats purpose is to check accuracy of players shooting.

i passed a variable that lets me adjust the max number of shots to check until it terminates.

then in the actual script file:

_unit = _this select 0;
_maxshots = _this select 1;
_shotstaken = 0;
_weaponarray = weapons _unit; // dont worry about this 
_mainweapon = _weaponarray select 0; // same with this one, not implemented yet
_unit addEventHandler ["fired", "_shotstaken = _shotstaken + 1; hint format [str _shotstaken];"]; //counts amount of shots taken and hints the string value

if (_shotstaken > _maxshots) then
{hint "mission complete"};

sleep 1;

and it didnt output anything

i also tried to use this in a while loop, with just the variable counting in the eventhandler code block;

while {_shotstaken > _maxshots} do
{
hint str _shotstaken;
sleep 2
}

but still no go

then i tried putting the addeventhandler command in the while loop, still nothing

so how does one actually setup an eventhandler to check and update the variable in the command block? should the eventhandler be used inside of a loop? and the purposes of all the different methods of using eventhandlers (since the fired one has multiple array variables)

or, if someone could link me to a better guide or tutorial on eventhandlers (cant find anything here on the forums or on the biki that made sense)

thanks in advance

Share this post


Link to post
Share on other sites

2 Problems:

1. The second argument for addEventHandler is code, and as such it must be contained inside of {}s. Example:

_myGuy addEventHandler ["fired",{hint format ["Nice shot, %1",name (_this select 0)]}];

2. The variable _shotstaken is local to your script. It is undefined in the eventhandler scope. You need to make it global or use setVariable or something.

Share this post


Link to post
Share on other sites

Not tested, just a quick shot from the hips:

private ["_unit", "_maxShots"];
_unit = _this select 0;
_maxShots = _this select 1;

//Preparing variables as needed
_unit setVariable ["ShotsTaken", 0];
_unit setVariable ["maxShots", _maxshots];

//creating a little function to count fired shots from primary weapon
if (isnil "IGN_fnc_shotcounter") then {
IGN_fnc_shotcounter = {
	private ["_unit", "_weapon"];
	_unit = _this select 0;
	_weapon = _this select 1;
	if (_weapon == (primaryweapon _unit)) then {
		_unit setVariable ["ShotsTaken", (_unit getVariable "ShotsTaken") + 1];
		if ((_unit getVariable "ShotsTaken") < (_unit getVariable "maxShots")) then {
			hintsilent format ["Shots fired: %1", _unit getVariable "ShotsTaken"];
		} else {
			hintsilent format ["Limit of %1 shots reached", _unit getVariable "maxShots"];
		};
	};
};
};
//Adding eventHandler to the unit.
IGN_firedEH = _unit addEventHandler ["fired", {_this call IGN_fnc_shotcounter}];

Share this post


Link to post
Share on other sites

ok so i tried that just now, still wouldnt hint anything on screen as to the shots fired count.

in player init i added:

shotstaken = 0

nul22 = [p1, 10] execVM "accuracycal.sqf"

and now in the script:

hint "activated";
_unit = _this select 0;
_maxshots = _this select 1;
_weaponarray = weapons _unit; // dont worry about this 
_mainweapon = _weaponarray select 0; // same with this one, not implemented yet
_unit addEventHandler ["fired", format [{shotstaken = shotstaken + 1}]]; //counts amount of shots taken and hints the string value

while {shotstaken > _maxshots} do
{
hint "in loop";
hint str shotstaken;
sleep 2;
}

but it still wont output anything, in fact it never makes it into the while loop (even when i fired a shot)

im pretty sure i need the format inside the eventhandler to update the variable so it properly counts, but why does it not make it to the while loop?

---------- Post added at 22:29 ---------- Previous post was at 22:23 ----------

Myke;1808574']Not tested' date=' just a quick shot from the hips:

private ["_unit", "_maxShots"];
_unit = _this select 0;
_maxShots = _this select 1;

//Preparing variables as needed
_unit setVariable ["ShotsTaken", 0];
_unit setVariable ["maxShots", _maxshots];

//creating a little function to count fired shots from primary weapon
if (isnil "IGN_fnc_shotcounter") then {
IGN_fnc_shotcounter = {
	private ["_unit", "_weapon"];
	_unit = _this select 0;
	_weapon = _this select 1;
	if (_weapon == (primaryweapon _unit)) then {
		_unit setVariable ["ShotsTaken", (_unit getVariable "ShotsTaken") + 1];
		if ((_unit getVariable "ShotsTaken") < (_unit getVariable "maxShots")) then {
			hintsilent format ["Shots fired: %1", _unit getVariable "ShotsTaken"];
		} else {
			hintsilent format ["Limit of %1 shots reached", _unit getVariable "maxShots"];
		};
	};
};
};
//Adding eventHandler to the unit.
IGN_firedEH = _unit addEventHandler ["fired", {_this call IGN_fnc_shotcounter}];

[/quote']

amazing, that worked exactly as i wanted. i cant believe that was off the top of your head ^^

but sadly i cant understand the logic behind the code you wrote, so while it does work and i praise you for that, i dont understand it.

maybe one day ill understand whats going on here, and why theres so many private variables and setvariables nested in control structures.

ty so much

edit **

dam, i dont know where to check if a popup target got hit or not in this, i guess i could call another script and check it there, but even so.

you think you could tell me where i would do a check to see if a player hit a target?

Edited by Igneous01

Share this post


Link to post
Share on other sites
_unit addEventHandler ["fired", format [{shotstaken = shotstaken + 1}]]; //counts amount of shots taken and hints the string value

Nope.

Look at my example again. Format returns a string, so you can't use that as your event code (unless you compile it, which it sort of seems like you've tried to do). Also, you can not use {}s to enclose strings; format also expects a string as the first argument.

im pretty sure i need the format inside the eventhandler to update the variable so it properly counts, but why does it not make it to the while loop?

All that the format command does is allow you to format a string (ex: insert a variable value into a string). Look at how I used format in my example (or Myke's).

And the answer to your last question is that it never reaches the while loop because you have syntax errors in the previous line. When the interpreter encounters an error it terminates the script.

Edited by Big Dawg KS

Share this post


Link to post
Share on other sites

No problem, i can explain so you see what happens where.

The start is obvious, reading passed parameters:

_unit = _this select 0;
_maxShots = _this select 1;

To make sure you can have more than one unit to count shots (which would interfere when using simply global variables), i use the units (every units) variablespace to store the required variables, in this case the shotcount and the limit:

_unit setVariable ["ShotsTaken", 0];
_unit setVariable ["maxShots", _maxshots];

Yes, each unit can have a different limit of rounds fired. ;)

The next thing is setting up a little function which we store inside a global variable named IGN_fnc_shotcounter.

if (isnil "IGN_fnc_shotcounter") then.....

This does check if the variable (and therefor function) already exists. So on multiple scriptcalls (caused by multiple units running this script) it would be overwritten each time. Wouldn't really hurt in this case, it is just proper scripting (or what i think it is).

The following lines of code aren't executed on scriptcall, just written in the above created variable. This is the code which is executed later on fired EH. You might see it as "script in script", kind of.

In here, the parameter will be given by the EH and aren't terefor linked to the parameters given at scriptstart. As you know, fired EH returns the unit with _this select 0 and the used weapon with _this select 1. There is more info returned but we don't need them so we just ignore them.

	_unit = _this select 0;
	_weapon = _this select 1;

As we only want to count shots from the primary weapon, we check if the weapon passed from the EH is the units primary weapon:

if (_weapon == (primaryweapon _unit)) then...

If it matches, the rest of the code is executed, else it will just end.

Next step is to count the actual shot so we're up-to-date with out counter. Remember, we wrote the shotcounter into the units variablespace, so we just raise it there:

_unit setVariable ["ShotsTaken", (_unit getVariable "ShotsTaken") + 1];

Now, either the limit has been reached or not, depending on that we can throw a hint:

		if ((_unit getVariable "ShotsTaken") < (_unit getVariable "maxShots")) then {
			hintsilent format ["Shots fired: %1", _unit getVariable "ShotsTaken"];
		} else {
			hintsilent format ["Limit of %1 shots reached", _unit getVariable "maxShots"];
		};

After that, a few closing brackets follows and finally the EH setup:

IGN_firedEH = _unit addEventHandler ["fired", {_this call IGN_fnc_shotcounter}];

As you see, we directly call the "script-in-script" we've set up above. So on every shot, the above function is called and behaves like a regular .sqf script.

I hope i could explain it well enough, else just drop your questions.

Share this post


Link to post
Share on other sites

ahh now i understand, i was reading another guide that says format is used to update the value of something even after the eventhandler was added:

http://www.ofpec.com/forum/index.php?topic=17724.0

guess i either misunderstood or it is wrongly explained.

@myke:

thank you so much for explaining that to me, i think i understand it now (thing that confused me the most was the reason behind so many private copy variables)

so if i wanted it to check whether the shot was a hit or miss, then i suppose it would be here:

if ((_unit getVariable "ShotsTaken") < (_unit getVariable "maxShots")) then {
			hintsilent format ["Shots fired: %1", _unit getVariable "ShotsTaken"];
                                             if (alive pop1) then 
                                            {hint "miss";}
                                            else {hint "hit";};
                                            hitcount = hitcount + 1 //dont know where i would define this variable
		} else {
			hintsilent format ["Limit of %1 shots reached", _unit getVariable "maxShots"];
		};

so now i just need to figure where i would define the hitcount variable within this function/script.

and for the final accuracy check, i suppose it would have to become another function within a function within a script?

thanks for the help so far its really helpful

Edited by Igneous01

Share this post


Link to post
Share on other sites
ahh now i understand, i was reading another guide that says format is used to update the value of something even after the eventhandler was added:

http://www.ofpec.com/forum/index.php?topic=17724.0

guess i either misunderstood or it is wrongly explained

This is an old example from OFP. The rules have changed since then. Back then, it was legal to use quotation marks and {}s interchangibly. Since ArmA however, "" is always string and {} is always code.

What you have here however is something very useful that you can do in this game: dynamically generating code. In his example, he is using format to place the contents of _pos (which when converted to a string looks like "[x,y,z]") into a string containing a code statement. So this example could still work in ArmA 2 if you properly converted the string into code.

Here's how it would look:

_pos = getPos Vehicle1;
_unit addEventHandler ["fired",compile format["(_this select 0) setpos %1", _pos]];

Notice here I used compile; this attempts to convert string into code (of course it will fail if there are any errors in your code), allowing it to be used wherever code is expected. Additionally, you can use the call command to execute any piece of code within the current program scope.

Example of executing dynamically generated code:

// move the player into the driver position of veh1 (as it is named in the editor)
_vehName = "veh1";
call compile format ["player moveInDriver %1",_vehName];

This is a very powerful feature, but it is also really easy to create bad code this way.

Share this post


Link to post
Share on other sites

arghh...... the entire script is so nested i cant figure out where to execute my accuracy check function, im not even sure if i should define private variables for its scope.

and a question about this portion of your code myke:

if (_weapon == (primaryweapon _unit)) then {
		_unit setVariable ["ShotsTaken", (_unit getVariable "ShotsTaken") + 1];
		if ((_unit getVariable "ShotsTaken") < (_unit getVariable "maxShots")) then 

your using setvariable for shotstaken for the scope of the _unit in the current fnc, but then your getting the variable for it again. is that still for the _unit of the current scope? if not then how does it know the difference which scoped variable your referring to? actually how does the ShotsTaken variable not get overriden back to default 0 as your setting it on _unit and then getting it at the same time?

i never thought it would be this hard for me to read through this nested structure, but i am lost on this part of it.

Share this post


Link to post
Share on other sites
arghh...... the entire script is so nested i cant figure out where to execute my accuracy check function, im not even sure if i should define private variables for its scope.

and a question about this portion of your code myke:

if (_weapon == (primaryweapon _unit)) then {
		_unit setVariable ["ShotsTaken", (_unit getVariable "ShotsTaken") + 1];
		if ((_unit getVariable "ShotsTaken") < (_unit getVariable "maxShots")) then 

your using setvariable for shotstaken for the scope of the _unit in the current fnc, but then your getting the variable for it again. is that still for the _unit of the current scope? if not then how does it know the difference which scoped variable your referring to? actually how does the ShotsTaken variable not get overriden back to default 0 as your setting it on _unit and then getting it at the same time?

i never thought it would be this hard for me to read through this nested structure, but i am lost on this part of it.

LMAO...don't be affraid, it could be worse....i could, as example, post this script:

//Scriptcall: targetRange = [[[unit1, Limit], [unit2, Limit], [unit3, Limit]], [Target1, Target2, Target3]] execVM "scriptname.sqf"

private ["_unitarray", "_targets"];
_unitarray = _this select 0;
_targets = _this select 1;

//Preparing variables as needed
{
_unit = _x select 0;
_unit setVariable ["ShotsTaken", 0];
_unit setVariable ["maxShots", (_x select 1)];
_unit setVariable ["hits", 0];
} foreach _unitarray;

//creating a little function to count fired shots from primary weapon
if (isnil "IGN_fnc_shotcounter") then {
IGN_fnc_shotcounter = {
	private ["_unit", "_weapon"];
	_unit = _this select 0;
	_weapon = _this select 1;
	if (_weapon == (primaryweapon _unit)) then {
		_unit setVariable ["ShotsTaken", (_unit getVariable "ShotsTaken") + 1];
		waituntil {!alive (_this select 6)};
		if ((_unit getVariable "ShotsTaken") < (_unit getVariable "maxShots")) then {
			hintsilent format ["Shots fired: %1", _unit getVariable "ShotsTaken"];
		} else {
			sleep 0.1;
			hint format ["Limit reached.\n\nShots fired: %1\nTargets hit: %2", _unit getVariable "maxShots", _unit getVariable "hits"];
			_unit setVariable ["ShotsTaken", 0];
			_unit setVariable ["hits", 0];
		};
	};
};
};

if (isnil "IGN_fnv_targetHit") then {
IGN_fnv_targetHit = {
	_tester = (_this select 1) getVariable "hits";
	if (!isnil "_tester") then {
		(_this select 1) setVariable ["hits", ((_this select 1) getVariable "hits") + 1];
	};
};
};

//Adding eventHandler to the unit.
{
IGN_firedEH = (_x select 0) addEventHandler ["fired", {_this spawn IGN_fnc_shotcounter}];
} foreach _unitarray;

{
IGN_hitEH = _x addEventHandler ["hit", {_this call IGN_fnv_targetHit}];
} foreach _targets;

:EDITH:

Remember math lessons? () are handled prior to the rest of the calculation: 5*3+2 or 5*(3+2) or (5*3)+2

Same is here, brackets say, read this first prior to write it. So it reads the actual number, adds 1 to it and then writes it back.

:EDITH2:

It's okay to hate me, i do hate myself, sometimes...but to be honest, not right now. ;)

Edited by [FRL]Myke

Share this post


Link to post
Share on other sites
Myke;1808632']LMAO...don't be affraid' date=' it could be worse....i could, as example, post this script:

//Scriptcall: targetRange = [[[unit1, Limit], [unit2, Limit], [unit3, Limit]], [Target1, Target2, Target3]] execVM "scriptname.sqf"

private ["_unitarray", "_targets"];
_unitarray = _this select 0;
_targets = _this select 1;

//Preparing variables as needed
{
_unit = _x select 0;
_unit setVariable ["ShotsTaken", 0];
_unit setVariable ["maxShots", (_x select 1)];
_unit setVariable ["hits", 0];
} foreach _unitarray;

//creating a little function to count fired shots from primary weapon
if (isnil "IGN_fnc_shotcounter") then {
IGN_fnc_shotcounter = {
	private ["_unit", "_weapon"];
	_unit = _this select 0;
	_weapon = _this select 1;
	if (_weapon == (primaryweapon _unit)) then {
		_unit setVariable ["ShotsTaken", (_unit getVariable "ShotsTaken") + 1];
		waituntil {!alive (_this select 6)};
		if ((_unit getVariable "ShotsTaken") < (_unit getVariable "maxShots")) then {
			hintsilent format ["Shots fired: %1", _unit getVariable "ShotsTaken"];
		} else {
			sleep 0.1;
			hint format ["Limit reached.\n\nShots fired: %1\nTargets hit: %2", _unit getVariable "maxShots", _unit getVariable "hits"];
			_unit setVariable ["ShotsTaken", 0];
			_unit setVariable ["hits", 0];
		};
	};
};
};

if (isnil "IGN_fnv_targetHit") then {
IGN_fnv_targetHit = {
	_tester = (_this select 1) getVariable "hits";
	if (!isnil "_tester") then {
		(_this select 1) setVariable ["hits", ((_this select 1) getVariable "hits") + 1];
	};
};
};

//Adding eventHandler to the unit.
{
IGN_firedEH = (_x select 0) addEventHandler ["fired", {_this spawn IGN_fnc_shotcounter}];
} foreach _unitarray;

{
IGN_hitEH = _x addEventHandler ["hit", {_this call IGN_fnv_targetHit}];
} foreach _targets;

:EDITH:

Remember math lessons? () are handled prior to the rest of the calculation: 5*3+2 or 5*(3+2) or (5*3)+2

Same is here, brackets say, read this first prior to write it. So it reads the actual number, adds 1 to it and then writes it back.

:EDITH2:

It's okay to hate me, i do hate myself, sometimes...but to be honest, not right now. ;)[/quote']

aww, i thought i almost had my version working (i nested my accuracy fnc inside the fnc shotcount, but it didnt work and i got no errors messages from it in game (have showscript errors on)

but here we go:

private ["_unit", "_maxShots"];
_unit = _this select 0;
_maxShots = _this select 1;

//Preparing variables as needed
_unit setVariable ["ShotsTaken", 0];
_unit setVariable ["maxShots", _maxshots];
_unit setVariable ["ShotsHit", 0];

//creating a little function to count fired shots from primary weapon
if (isnil "IGN_fnc_shotcounter") then {
IGN_fnc_shotcounter = {
	private ["_unit", "_weapon"];
	_unit = _this select 0;
	_weapon = _this select 1;
	if (_weapon == (primaryweapon _unit)) then {
		_unit setVariable ["ShotsTaken", (_unit getVariable "ShotsTaken") + 1];
		if ((_unit getVariable "ShotsTaken") < (_unit getVariable "maxShots")) then {
			hintsilent format ["Shots fired: %1", _unit getVariable "ShotsTaken"];
                       if (!alive pop1) then {hint "hit"; _unit setVariable ["ShotsHit", (_unit getVariable "ShotsHit") + 1]};
                       else {hint "miss"};
		} else {
			hintsilent format ["Limit of %1 shots reached", _unit getVariable "maxShots"];
                       if (isnil "IGN_fnc_accuracycheck") then {
                       IGN_fnc_accuracycheck = {
                       private ["_unit", "_accuracy"];
                       _unit = _this select 0;
                       _accuracy = _this select 1;
                       _unit setVariable ("ShotsHit", (_unit getVariable "ShotsHit");
                       _accuracy = (_unit getVariable "ShotsHit") / (_unit getVariable "maxShots");
                       hintsilent format ["Accuracy: %1", _accuracy];
}

		};
	};
};
};

//Adding eventHandler to the unit.
IGN_firedEH = _unit addEventHandler ["fired", {_this call IGN_fnc_shotcounter}];

thought it was gonna work, but it looks like i messed up

gonna try yours then, this is giving me a headache :S

edit**

is there anyway i can just call for unit1 in your script without having to call unit2 or unit3? the script is just intended for a singleplayer mission im working on as part of a greater campaign, so only 1 person really needs to be checked for accuracy, but since theres 3 tests on accuracy, id like to reuse it for simplicity

Edited by Igneous01

Share this post


Link to post
Share on other sites

To use only with one unit:

targetRange = [[[unit1, Limit]], [Target1, Target2, Target3]] execVM "scriptname.sqf"

To add more targets:

targetRange = [[[unit1, Limit]], [Target1, Target2, Target3, Target4,Target5]] execVM "scriptname.sqf"

Or only one target:

targetRange = [[[unit1, Limit]], [Target1]] execVM "scriptname.sqf"

As you see, it is self-adapting. You simply add or remove units/targets in the scriptcall and the script handles the rest itself.

Share this post


Link to post
Share on other sites

ah i feel like an idiot, thanks for helping me out that is very much appreciated myke ^^

Share this post


Link to post
Share on other sites

alright sorry to bring this up again but im having another issue now thats related to the script.

the script itself works fine, managed to get it to remove the handlers after the certain amount of shots is reached.

then i tried using a global variable that would store the information of how many shots hit, and the maximum shots. I did this so i can use another script to assess and calculate scores needed. (im working on a noob function sort of)

so in my init.sqf

Test1Hits = 0

EDIT***

OK nm then it looks like it was text editors fault for formatting it into rich text without me noticing.

so i was a happy camper.....

i cant remove the eventhandlers from the targets, using this line:

 {_x removeEventHandler ["hit", IGN_hitEH]} foreach _targets;

but it removes it from one of the targets... i dont understand why tho, the score keeps updating even after the test is finished, but if i fire on target 1, then the score doesnt update, but on all the other targets in the array the event handler is attached for some reason...

im guessing its a bad syntax from me or something....

Edited by Igneous01
being stupid

Share this post


Link to post
Share on other sites

alright thats it i officially give up on this. I cannot get it to terminate the eventhandlers.

i thought that maybe using using a while loop at the bottom and then after its processed as complete it would remove the handlers after that... but it still doesnt remove the event handlers and it keeps going back into the loop.

i just dont get it anymore, i dont think im gonna use EH after this.

Share this post


Link to post
Share on other sites

Don't give up that easy, scripting is a tough business. It took me quite some time (years) to get to the point where i can write such scripts off the top of my head. And even these days i'm still learning new stuff almost every day i didn't knew before.

I know it can be annoying and frustrating, just keep trying.

So, about your problem, let me know at which point did you tried to remove the EH's?

Share this post


Link to post
Share on other sites

alrighty then thanks for the lifter ^^

well.......

so i managed to remove the eventhandlers - took some time as there was just alot of bugs that just shouldnt have happened. but i managed to remove them.

but now i need to figure out how i can get the static end score of hits from outside the function.

Actually its probably best if i just show you everything thats going on then:

so here i have added an action to the player that lets him skip/finish practicing at the range.

finishpractice.sqf

donepractice = true;
player removeaction finishpractice;

Test1Countdown = [10, "Get Ready:", "Start"] execVM "Timer.sqf";

waituntil {scriptDone Test1Countdown};

_t1spawn = ExecVM "Test1.sqf";

it triggers a timer (the script you updated again :P) to countdown, then once its ready it executes another script called test1, which really should be called Test - as all the tests will be executed here.

then in Test1.sqf

test2active = false;
// TEST1
// Spawning in Targets
t1tar1 setpos (getmarkerpos "t1p1");
t1tar2 setpos (getmarkerpos "t1p2");
t1tar3 setpos (getmarkerpos "t1p3");
t1tar4 setpos (getmarkerpos "t1p4");
t1tar5 setpos (getmarkerpos "t1p5");
t1tar6 setpos (getmarkerpos "t1p6");
t1tar7 setpos (getmarkerpos "t1p7");
t1tar8 setpos (getmarkerpos "t1p8");
t1tar9 setpos (getmarkerpos "t1p9");
t1tar10 setpos (getmarkerpos "t1p10");
Test1Timer = [60, "Time Remaining:", "End of Test"] execVM "Timer.sqf";
testRange1 = [[[player1, 10]], [t1tar1, t1tar2, t1tar3, t1tar4, t1tar5, t1tar6, t1tar7, t1tar8, t1tar9, t1tar10]] execVM "Accuracy_Check.sqf";
waitUntil {scriptDone Test1Timer};
terminate testRange1;
waitUntil {scriptDone testRange1};
// Delete Targets
deleteVehicle t1tar1;
deleteVehicle t1tar2;
deleteVehicle t1tar3;
deleteVehicle t1tar4;
deleteVehicle t1tar5;
deleteVehicle t1tar6;
deleteVehicle t1tar7;
deleteVehicle t1tar8;
deleteVehicle t1tar9;
deleteVehicle t1tar10;
// END TEST1


//Intermission
Intermission1 = [20, "Get Ready:", "Start"] execVM "Timer.sqf";
waituntil {scriptDone Intermission1};

test2active = true;

//Spawn Target
t2tar setpos (getmarkerpos "t2p1");

// TEST2

testRange1 = [[[player1, 1]], [t2tar]] execVM "Accuracy_Check.sqf";
while {test2active == true) do
{

this is so far partially finished, test1 runs through smoothly so far, just theres a bit of a bug with the accuracy_check function as it waits for the bullet to be dead before calculating, which means firing in rapid succession will reset the score as it starts a new one. but that ill think about later.

Then in the Accuracy_Check.sqf, i added a couple global variables that i would use to fetch the values of the current test, and store them in another script to calculate the end overall score and display it.

Accuracy_Check.sqf

//Scriptcall: targetRange = [[[unit1, Limit], [unit2, Limit], [unit3, Limit]], [Target1, Target2, Target3]] execVM "shotcountnewer.sqf"
//targetRange = [[[unit1, Limit]], [Target1, Target2, Target3]] execVM "scriptname.sqf"


endaccuracycheck = 0;
private ["_unitarray", "_targets"];
_unitarray = _this select 0;
_targets = _this select 1;

//Preparing variables as needed
{
_unit = _x select 0;
_unit setVariable ["ShotsTaken", 0];
_unit setVariable ["maxShots", (_x select 1)];
_unit setVariable ["hits", 0];
     Test1Max = _unit getVariable "maxShots"
} foreach _unitarray;

//creating a little function to count fired shots from primary weapon
if (isnil "IGN_fnc_shotcounter") then {
IGN_fnc_shotcounter = {
	private ["_unit", "_weapon"];
	_unit = _this select 0;
	_weapon = _this select 1;
	if (_weapon == (primaryweapon _unit)) then {
		_unit setVariable ["ShotsTaken", (_unit getVariable "ShotsTaken") + 1];
		//waituntil {!alive (_this select 6)};
		if ((_unit getVariable "ShotsTaken") < (_unit getVariable "maxShots")) then {
			hintsilent format ["Shots fired: %1", _unit getVariable "ShotsTaken"];
		} else {
			sleep 0.1;
			hint format ["Limit reached.\n\nShots fired: %1\nTargets hit: %2", _unit getVariable "maxShots", _unit getVariable "hits"];
			 endaccuracycheck = 1;
                       _unit setVariable ["ShotsTaken", 0];
			_unit setVariable ["hits", 0];

		};
	};
};
};

if (isnil "IGN_fnv_targetHit") then {
IGN_fnv_targetHit = {
	_tester = (_this select 1) getVariable "hits";
	if (!isnil "_tester") then {
		(_this select 1) setVariable ["hits", ((_this select 1) getVariable "hits") + 1];
//my line of code
                 Test1Hits = ((_this select 1) getVariable "hits");
                 Test2Hit = ((_this select 1) getVariable "hits");
                 Test3Hit = 
//end of my line 
	};
};
};

//Adding eventHandler to the unit.
{IGN_firedEH = (_x select 0) addEventHandler ["fired", {_this spawn IGN_fnc_shotcounter}];} foreach _unitarray;

{IGN_hitEH = _x addEventHandler ["hit", {_this call IGN_fnv_targetHit}];} foreach _targets;


while {endaccuracycheck == 0} do
{
sleep 0.15;
};

player removeeventhandler ["fired", IGN_firedEH];
{_x removeAllEventHandlers "hit"} foreach _targets;

as you can see, i used a while loop that basically just keeps the script running until the endaccuracycheck == 1 or true, then it removes the eventhandlers (im not sure if this is a smart way or prettiest way of doing it but it works.

also the global variables just store the different number of hits into another script called RangeScore.sqf

and in that script:

//Score Check for Test1
Test1Score = Test1Hits / Test1Max * 10
//Score Check for Test2
//Score Check for Test3
// Overall Score

this scripts purpose is just to merely take all the static and final values of each test and do some math with them and output a score, afterwards ill have an if statement that reads if the score is lower than 200, then the mission will fail, causing you to restart.

now the problem i just realized is in the second test, where i have 10 markers spaced out 100m each, it spawns at the first marker, which is 300m away from the player, he has only 1 shot to hit the target at each range, once the target has been hit, it gets setpos to the next marker, up to 1000m where the test ends (if the player makes it that far)

the thing i just realized is that with the global variables that are getting the values here:

if (isnil "IGN_fnv_targetHit") then {
IGN_fnv_targetHit = {
	_tester = (_this select 1) getVariable "hits";
	if (!isnil "_tester") then {
		(_this select 1) setVariable ["hits", ((_this select 1) getVariable "hits") + 1];
//my line of code
                 Test1Hits = ((_this select 1) getVariable "hits");
                 Test2Hit = ((_this select 1) getVariable "hits");
                 Test3Hit = 
//end of my line 
	};
};
};

is that i believe ill be overwritting the values of the first test, meaning i need to figure out another way of getting the values out of this script and not being overwritten.

And yea, i know what your thinking - 4 scripts just to do all that? well... yea... i just think its easier to understanding what is being executed and also easier to read.

its like a mixing router to me, you know where all the inputs and outputs go.

but yea if you can figure out that one for me, i think that will solve my problems and allow me to move on to finishing this part of the mission.

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  

×