Ok, here i wrote a little thing for you. To activate the whole thing, just insert this line into your init.sqf script.
if (isServer && (!local player)) exitwith {};
glt_smoker_position = [];
"glt_smoker_position" addPublicVariableEventHandler {nul = this execVM "smoker_updater.sqf"};
player addEventHandler ["fired", {_this execVM "smoker.sqf"}];
As you see, this will add the EH to the player and will also prepare the clientscript to make the smoke appear on all clients.
_unit = _this select 0;
_weapon = _this select 1;
_stopped = false;
_timestamp = 0;
if (_weapon == "Throw") then {
_shell = nearestObject [_unit, "SmokeShell"];
if (isnull _shell) exitwith {};
_timestamp = time;
while {!_stopped} do {
_velX = velocity _shell select 0;
_velY = velocity _shell select 1;
if ((_velX == 0) && (_velY == 0)) then {
_stopped = true;
};
if (time > (_timestamp + 2)) then {
_stopped = true;
};
sleep 0.1;
};
glt_smoker_position = getpos _shell;
publicvariable "glt_smoker_position";
deletevehicle _shell;
_particleSource = "#particlesource" createVehicle glt_smoker_position;
_particleSource setParticleCircle [10, [2, 0, 0]];
_particleSource setParticleRandom [0, [0, 0, 0], [0.54, 0.54, 0], 0, 0.25, [1e-005, 1e-006, 1e-006, 0.2], 0, 0];
_particleSource setParticleParams [["\Ca\Data\ParticleEffects\FireAndSmokeAnim\SmokeAnim.p3d", 8, 5, 1], "", "Billboard", 1, 15, [0, 0, 0], [2, 0, 0], 1, 12, 10, 0.2, [5, 10, 25, 35, 45, 50], [[0.9, 0.9, 0.9, 0.4], [0.9, 0.9, 0.9, 0.2], [0.9, 0.9, 0.9, 0], [0.9, 0.9, 0.9, 0]], [2, 1], 0, 0, "", "", SmokeLogic];
_particleSource setDropInterval 0.08;
};
glt_smoker_position = [];
_particleSource = "#particlesource" createVehicle glt_smoker_position;
_particleSource setParticleCircle [10, [2, 0, 0]];
_particleSource setParticleRandom [0, [0, 0, 0], [0.54, 0.54, 0], 0, 0.25, [1e-005, 1e-006, 1e-006, 0.2], 0, 0];
_particleSource setParticleParams [["\Ca\Data\ParticleEffects\FireAndSmokeAnim\SmokeAnim.p3d", 8, 5, 1], "", "Billboard", 1, 15, [0, 0, 0], [2, 0, 0], 1, 12, 10, 0.2, [5, 10, 25, 35, 45, 50], [[0.9, 0.9, 0.9, 0.4], [0.9, 0.9, 0.9, 0.2], [0.9, 0.9, 0.9, 0], [0.9, 0.9, 0.9, 0]], [2, 1], 0, 0, "", "", SmokeLogic];
_particleSource setDropInterval 0.08;
glt_smoker_position = [];
As you see, the smoker.sqf does manage the smoke on the client that has thrown the smokeshell and also does update the publicvariable glt_smoker_position which will then launch the smoker_updater.sqf on the other clients so they will also get the new smoke.
As always, test it as much as you can to make sure it work as expected.