Jump to content
Sign in to follow this  
ange1u5

Attach sign arrow markers to players in vehicles...

Recommended Posts

Hi there. I'm experimenting with attaching these helper markers like Sign_Arrow_Large_Blue_F to objects and that works fine. What I'd like though is to have these markers appear over players heads whilst driving. I can attach it to the player fine but as soon as I get into a vehicle and drive away, the marker sits at the last known position of the player before he got in the car. I can't attach it to specific cars because cars will change over the course of the mission.

_playerarrow = "Sign_Arrow_F" createVehicle position p1;
	_playerarrow attachTo [p1,[0,-0.5,3]];

I have 14 players to assign this to. Any help appreciated :)

Share this post


Link to post
Share on other sites

You will need to run a loop to keep a track of the unit and update it.

_playerarrow = "Sign_Arrow_F" createVehicle position p1;
while {alive p1} do {
vehicle _playerarrow attachTo [p1,[0,-0.5,3]];  
sleep 1;
};

Share this post


Link to post
Share on other sites

Great, would I have to do that individually for each player or can I create an array for it? I did play around with. I tried something like

_player = [p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14]
_playerarrow = "Sign_Arrow_F" createVehicle position _player;
while {alive _player;} do {
vehicle _playerarrow attachTo [_player,[0,-0.5,3]];  
sleep 1;
};  

And a few other variations to no avail.

Share this post


Link to post
Share on other sites

You need to spawn one thread per player, or use a completely different method.

If one of the 14 slots is empty (no player or ai) this will exit with an error (because pX doesn't exist at all). So it's probably better to use playableUnits + switchableUnits instead of direct references.

Also, run this on the server only. Or use createVehicleLocal. Otherwise you will get 14 arrows per player. :D

_player = (playableUnits + switchableUnits);

{

_x spawn {

	_player = _this;
	_playerarrow = "Sign_Arrow_F" createVehicle (getPosATL (vehicle _player));
	_playerarrow attachTo [_player, [0,-0.5,3]];

	while {alive _player} do {
		_vehicle = (vehicle _player);
		waitUntil {sleep 1; ((vehicle _player) != _vehicle)}; // Wait for vehicle change
		deTach _playerarrow; // Not sure if necessary
		_playerarrow attachTo [(vehicle _player), [0,-0.5,3]];
	};

};

} forEach _player;

This will not work with JIP and respawn however. If you use respawn or expect JIP, the code needs to be changed. Let me know.

Edited by sxp2high

Share this post


Link to post
Share on other sites

I do indeed use respawn. JIP is generally not expected as once the race begins, anyone joining later will start at the beginning and there will be no chance for them to catch up. But should expect this as a factor though. Speaking of it though, is there actually a way to disable JIP once the mission begins, and if so is it advisable? Say a player drops out (as so often happens) he can't rejoin I would assume.

I noticed the arrow obviously only moved every second because of sleep. If I set that to say 0.01 do I run the risk of crapping the server out because its running this thread constantly so fast?

Share this post


Link to post
Share on other sites

You can disable JIP, in a way. Advisable? I don't know. That's up to you. I probably wouldn't bother doing so. Usually admins lock the server to archive this.

You could simply add a time check to your init.sqf though:

if (time > 60) then { endMission "End1"; };

This means, if mission has been running for more than 60 seconds, the mission will be ended for new players that join afterwards.

The once-a-second-update is because the code F2k Sel gave you is not really a nice solution. There is no reason to run the attachTo command each second, attachTo attaches it, so you don't have to update it constantly, it will stay with the unit. It should be perfectly fluid following the object/player/vehicle. The loop is only needed to account for the vehicle change.

The code I posted, has this extra line added, that waits for the vehicle to actually change, before attaching again:

waitUntil {sleep 1; ((vehicle _player) != _vehicle)}; // Wait for vehicle change

But no, theoretically the server could easily handle 14 loops with sleep 0.01. Depending on how much else is running, the server could handle 50 of that or more. :)

However, I would let each client handle it's own marker:

if (!isDedicated) then {

_playerarrow = createVehicle ["Sign_Arrow_F", (getPosATL (vehicle player)), [], 0, "NONE"];
_playerarrow attachTo [player, [0,-0.5,3]];

while {true} do {

	_vehicle = (vehicle player);

	waitUntil {sleep 1; ((vehicle player) != _vehicle) || !(alive player)}; // Wait for vehicle change OR player not alive
	deTach _playerarrow; // Not sure if necessary
	if (!(alive player)) then { waitUntil {(alive player)}; }; // If player is dead, wait for respawn
	_playerarrow attachTo [(vehicle player), [0,-0.5,3]];

};

};

Share this post


Link to post
Share on other sites

Works a treat, thank you =D

One more question though, looking at it, though I like it myself, I can imagine some people might find it irritating or an eyesore. Would an addaction work best to toggle the signs on or off as they choose? If so how?

Share this post


Link to post
Share on other sites

Well, good decision, I wouldn't like them either.

addAction should be avoided, especially for minor things like this. Action menu is cumbersome and cluttered enough as it is :)

Probably best to use a button press to toggle them on and off.

First you need to change the code, so all arrows are added to an array, so you can refer to them:

if (isServer) then {

player_arrows = []; publicVariable "player_arrows"; // Create array on the server

};


if (!isDedicated) then {

waitUntil {!(isNil "player_arrows")}; // wait for the server

   _playerarrow = createVehicle ["Sign_Arrow_F", (getPosATL (vehicle player)), [], 0, "NONE"];
   _playerarrow attachTo [player, [0,-0.5,3]];

player_arrows set [(count player_arrows), _playerarrow]; publicVariable "player_arrows"; // Add arrow to the array and publicize

   while {true} do {

       _vehicle = (vehicle player);

       waitUntil {sleep 1; ((vehicle player) != _vehicle) || !(alive player)}; // Wait for vehicle change OR player not alive
       deTach _playerarrow; // Not sure if necessary
       if (!(alive player)) then { waitUntil {(alive player)}; }; // If player is dead, wait for respawn
       _playerarrow attachTo [(vehicle player), [0,-0.5,3]];

   };

};

Then add a displayEventHandler for the button:

[] spawn {

// Function for toggle
fnc_toggleArrows = {
	if (isNil "toggleArrows") then {
		toggleArrows = true;
		{ _x hideObject true; } forEach player_arrows; // Hide all arrows
	} else {
		toggleArrows = nil;
		{ _x hideObject false; } forEach player_arrows; // UN-hide all arrows
	};
};

waituntil {!(isNull (finddisplay 46))}; // needed for displayeventhandlers
sleep 0.1; // sometimes they dont get added without a tiny sleep

// Add keyhandler
_keyHandlerUp = (findDisplay 46) displayAddEventHandler ["KeyUp", "if ((_this select 1) == 23) then { [] call fnc_toggleArrows; };"];

hint "Press I to toggle player markers.";

};

Key would be i in this example. Which is 23.

_keyHandlerUp = (findDisplay 46) displayAddEventHandler ["KeyUp", "if ((_this select 1) == [b][color="#FF0000"]23[/color][/b]) then { [] call fnc_toggleArrows; };"];

Change that to whatever you see fit. A list of the available keycodes can be found here.

  • Thanks 1

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  

×