Jump to content

Recommended Posts

I have searched both google and the forums for this and see a couple answers to this question that do not make sense to me.

I have a couple different firing ranges for my unit that are run via script. They work correctly in both hosted and on the dedi with one small exception. The rangemaster - which is a recording of one of our members played in the script - only executes on the player that activated the firing range, even though the range itself is working for every player on the server. I am 100% sure that it is a locality issue, as the addAction that calls the sqf is located in the init.sqf of the mission. I keep finding answers that have things like this:

[Computadora1, ['Disparar a Barco',{<your code here>}] ] remoteExec ["addAction",0,true];

But I do not understand exactly what it all means as most people just provide a script and not an explanation of why it fixes the issues.

My question is: how do I execute the addAction in game via remoteExec so that all players can both see the range and hear the rangemaster?

Below is a snippet of my range code that involves the recordings - just to ensure that I haven't made a boneheaded error.

 

init.sqf

Spoiler

 


laptop1        addAction ["Activate Range","Scripts\range4.sqf"];

 

 

range4.sqf (partial)

Spoiler

{_x  animate["terc",1]} forEach _targets;

nopop=true;

sleep 4;
loud4 say3D "L1";
loud5 say3D "L1";
sleep 1;
loud4 say3D "QR1";
loud5 say3D "QR1";
sleep 12;
loud4 say3D "Hot";
loud5 say3D "Hot";
sleep 3;

l4_200_1 animate["terc", 0];
l4_200_2 animate["terc", 0];
l4_200_3 animate["terc", 0];
l4_200_4 animate["terc", 0];
l4_200_5 animate["terc", 0];

sleep 25;


if (l4_200_1 animationPhase "terc" != 0) then {
	_count = _count + 1;
};
l4_200_1 animate["terc", 1];
_inc = _inc +1;

if (l4_200_2 animationPhase "terc" != 0) then {
	_count = _count + 1;
};
l4_200_2 animate["terc", 1];
_inc = _inc +1;

if (l4_200_3 animationPhase "terc" != 0) then {
	_count = _count + 1;
};
l4_200_3 animate["terc", 1];
_inc = _inc +1;

if (l4_200_4 animationPhase "terc" != 0) then {
	_count = _count + 1;
};
l4_200_4 animate["terc", 1];
_inc = _inc +1;

if (l4_200_5 animationPhase "terc" != 0) then {
	_count = _count + 1;
};
l4_200_5 animate["terc", 1];
_inc = _inc +1;

loud4 say3D "L1";
loud5 say3D "L1";
sleep 1;
loud4 say3D "Cease";
loud5 say3D "Cease";
sleep 8;
loud4 say3D "L1";
loud5 say3D "L1";
sleep 1;
loud4 say3D "QR2";
loud5 say3D "QR2";
sleep 14;
loud4 say3D "Hot";
loud5 say3D "Hot";
sleep 3;

l4_200_1 animate["terc", 0];
l4_200_2 animate["terc", 0];
l4_200_3 animate["terc", 0];
l4_200_4 animate["terc", 0];
l4_200_5 animate["terc", 0];

sleep 25;

 

 

Thank you all in advance for the help!

  • Like 1

Share this post


Link to post
Share on other sites

first of all you need to decide where you put addaction command. Editor init field of object or script.

This addaction command is simple. Works like eventhandler without event (push by player)

 

If you use init.sqf or editors init field of object (laptop) you do not need to remoteexec addaction because those places are executed by any client already.

But keep in mind it will only add a action to object.

Next is commands locality in your scrip executed by action. There are two "params" about. Argument and effect.

For example say3d:

loud4 say3D "L1";

In this case Argument is loud4 and this dont have to be local to the client where command is executed.

An effect of this is local it means sound "L1" can be hear only by client where the say3d command was executed.

To allow it to be hear by everyone you need to remoteexec it like this:

[loud4,"L1"] remoteexec ["say3d",[0,-2] select isDedicated,false];

Commands parameters locality you can always check on wiki and this looks like:

arguments_global.gif  effects_local.gif

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

Thanks for the response!

 

So should I change the say3D command over to a playSound3D instead?
I thought since the init.sqf was executed on every client that the script would also execute that way, hence the use of say3D.

But since that is not the case, using playSound3D, which executes on every computer on the network, should work.....

 

Right?

Share this post


Link to post
Share on other sites

You can remoteExec the say3D as well as a hint . The inner code is local (only for caller) but the effect of each command can be local or global (public). If effects_local.gif command, you can remoteExec it. The true difficulty for such code (in addAction or event hanlders) is that you need to think about effect for each command/function inside.

 

Furthermore, the arguments are also important, even if, most of time arguments_global.gif are friendly and can be applied without problem. The latest commands are often like that.

But... with arguments_local.gif  command, difficulty raises when you apply such command/function on an object which is not local (doesn't belong to the player caller of addAction). All arguments_local.gif are not equal for that. You can read:

"Arguments of this scripting command have to be local to the client the command is executed on".

There are plenty of cases where a car owner switches (when the driver changes). A laptop is usually on server, but  you can't say in advance whom the car will belong to.
Same for units who depend on their group leader (AI leader on server or HC, players on clients)

So, most of the time, applying a code on an object, here, will look like:

[yourObject, arguments] remoteExec ["yourCommand" , yourObject];

see remoteExec for details.

 

 @davidoss  Did you ever experience an error for a globally remote executed addAction, even on a dedicated server? IMHO,   [0,-2] select isDedicated   is not important. I know there is no player to play addAction on dedi, but that doesn't return any error. Or, i missed something.

 

 

  • Like 1

Share this post


Link to post
Share on other sites

Of course its not.

Anyway we should always carry about where things goes especially about network stuff.

We all knew how laggy/desync arma can get.

If you don't need something there don't put it there - best idea i think.

  • Like 3

Share this post


Link to post
Share on other sites

Not directly related to the thread question but:

Sometimes it isn't ideal to remoteExec actions but rather handle them client-side. Even for JIP. It all comes down to specifics though, and your mission structure.

Just something to keep in mind.

  • Like 1

Share this post


Link to post
Share on other sites
6 hours ago, HazJ said:

Not directly related to the thread question but:

Sometimes it isn't ideal to remoteExec actions but rather handle them client-side. Even for JIP. It all comes down to specifics though, and your mission structure.

Just something to keep in mind.

Yes, very much.

my non expert method is to add the addaction to the players right at the start, but hold them off using a condition. Having the server set the condition on the client is better than having the server add the addaction.

  • Like 1

Share this post


Link to post
Share on other sites
4 hours ago, Tankbuster said:

 Having the server set the condition on the client is better than having the server add the addaction.

 

Could you elaborate?

Share this post


Link to post
Share on other sites
6 hours ago, pierremgi said:

 

Could you elaborate?

The addaction has a condition field. In there, you check a boolean variable which is set by the server when and only when you want to addaction to appear. It can be a public variable if the addaction is to appear of all players simultaneously, or the server can publicvariableclient or setvariable the boolean when the addaction is supposed to be shown to the player.

Share this post


Link to post
Share on other sites
2 hours ago, Tankbuster said:

The addaction has a condition field. In there, you check a boolean variable which is set by the server when and only when you want to addaction to appear. It can be a public variable if the addaction is to appear of all players simultaneously, or the server can publicvariableclient or setvariable the boolean when the addaction is supposed to be shown to the player.

 

As discussion, it's difficult for me to understand: "you check a boolean variable which is set by the server when and only when you want to addaction to appear.

 

Imho,  the addAction checks conditions on clients/hosted where the script runs the addAction command, locally, and each frame. I can't imagine a broadcast check on each frame.

 

If you place this command in an init field of an object, every client/hosted will run this command at local start. There is absolutely no reason to check some conditions from server. Furthermore, apart, if you place this command in a server script (server only trigger, initServer.sqf...) , usually for spawning objects/units, the addaction will be seen on hosted server only (noob error). But you can remoteExec the command from anywhere arguments_global.gif

 

BI says: The action can only be activated when in proximity to the object (default 50m). Adding an action to the player obviously makes that action available to the player at all times.

On my mind, that means that:

- the whole condition is checked on each frame (and locally) if you apply the addAction to the player;

- an embedded distance condition (not your code) has to check if the player is within 50 m of the object, target of the addAction, on each frame. If yes, then your code is checked, on each frame also til the embedded distance condition is false.

 

Now, to see where an addAction condition is checked , in both cases (on player or object), you can write a code like: "hint 'ok'; _target distance _this < 10"  The condition parameter must end by a boolean but you have a cheap onEachFrame code before.

Share this post


Link to post
Share on other sites

I don't think you understand what TB is getting at.

//Some object init field

this addaction[ "Use Me" , {
    hint "Action Used";
},[],1,true,true,
"missionNamespace getvariable[ 'someVar', false ]"
];
//Server side

//when you want the action to be available to clients
someVar = true;
publicVariable "someVar";

//when you don't want the action to be available to clients
someVar = false;
publicVariable "someVar";

 

  • Like 3
  • Thanks 2

Share this post


Link to post
Share on other sites

@Larrow
to the rescue again! Thank you.

You can publicvariableclient the variable to individual clients using this method too

  • Like 1

Share this post


Link to post
Share on other sites

My apologies for the delay in response, work is a cruel mistress.

I will be tweaking the scripts applying the knowledge from what you all have posted. I think I learned more catching up on this forum than I realized.

I will update within the next day or two with the outcome of the editing.

Share this post


Link to post
Share on other sites

Hello Community,

 

May someone can help me here too? I ran into a similar Problem and thought i ask/post it here.

Basically i try to spawn an object on a dedicated Server with an Action:

 

// Spawn OBj on dedicated Server

if (isServer) then
{

terminal = createVehicle ["Land_DataTerminal_01_F", _rndPos, [], 0, "NONE"];
[terminal, ["Download Intel", "scripts\intel.sqf", nil, 2, true, true, "", "true", 3.5, false]] remoteExec ["addAction",0, true];

};

And here goes the simple Action:

//Intel.sqf

if (isServer) then {

Systemchat "Downloading Intel - STANDBY";
sleep 3;
removeAllActions terminal;
sleep 2;
terminal setdamage 1;
Systemchat "Downloading Intel - FINISHED";
sleep 5;
deleteVehicle terminal;

};

 

I tried already different ways to get this work, but failed at every attempt (like systemchats are shown, but the object doesn't get deleted) - kinda clueless now. 

So, if someone could provide me a solution or a hint, what's going on here, it will be highly appreciated!

Share this post


Link to post
Share on other sites

You created a "Land_DataTerminal_01_F" but   terminal    is a variable known on server only.

Your intel.sqf runs locally to the caller, so that can't work with if (isServer) except for the hosting one.

 

if (isServer) then {

  terminal = createVehicle ["Land_DataTerminal_01_F", _rndPos, [], 0, "NONE"];

  [terminal, ["Download Intel", "scripts\intel.sqf", nil, 2, true, true, "", "true", 3.5, false]] remoteExec ["addAction",0, terminal];

};

 

//Intel.sqf

params ["_target"];

Systemchat "Downloading Intel - STANDBY";

 removeAllActions _target;

 sleep 5;

 Systemchat "Downloading Intel - FINISHED";

 sleep 5;

deleteVehicle _target;

 

 

 

  • Like 3
  • Thanks 2

Share this post


Link to post
Share on other sites

Alternative method would be just publicVariable/publicVariableClient the terminal variable, ditch the remoteExec and create addAction locally when joining (initPlayerLocal). All down to you, many possible ways for most things. Not all are best approach, depends for certain situations.

Share this post


Link to post
Share on other sites
On 11/10/2018 at 12:11 AM, Larrow said:

I don't think you understand what TB is getting at.


//Some object init field

this addaction[ "Use Me" , {
    hint "Action Used";
},[],1,true,true,
"missionNamespace getvariable[ 'someVar', false ]"
];

//Server side

//when you want the action to be available to clients
someVar = true;
publicVariable "someVar";

//when you don't want the action to be available to clients
someVar = false;
publicVariable "someVar";

 

 

I think this method is the most efficient bandwidth wise!

 

But how would you apply this method if the object (to get the addAction) is spawned via script rather than EDITOR (So no access to Object's init field)?

Share this post


Link to post
Share on other sites

This  is specific to the init field of the edited object.

But when you spawn an object by a command or a function in a script, usually the returned value is the object and you can run your code on it.Here you need to remoteExec the code   (such as an init field which is "public", ran by all players)

Example:

_veh = "C_Offroad_01_F" createVehicle position player;

[_veh,[ "Use Me" , { hint "Action Used"; },[],1,true,true, "missionNamespace getvariable[ 'someVar', false ]" ] ] remoteExec ["addAction",[0,-2] select isdedicated] ;

  • Like 1
  • 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

×