Jump to content
Sign in to follow this  
eggbeast

AddAction on client

Recommended Posts

Hi

I've searched, read and commented in similarthreads today, but none answer this question very well, as far as I can see.

I'm struggling to make this work. any help most appreciated.

In Evolution, you can capture the officer in a city and then the last 4 infantry.

The Capture function works for the officer but not the infantry.

The script trail looks like this:

OFFICER

in evo_erec.sqf

//Officer
_offobj = createVehicle ["RU_Soldier_Officer", _pos, [], 300, "NONE"];Sleep BIS_EVO_GlobalSleep;
_offobj addEventHandler ["killed", {handle = [_this select 0] execVM "data\scripts\bury.sqf"}];
_offobj setVehicleInit "Ocap = [this] execVM 'data\scripts\submit.sqf'";
_pobj = [_offobj] execVM "data\scripts\objoff.sqf";
processInitCommands;
Sleep 3;

note that the officer is initialised with

_offobj setVehicleInit "Ocap = [this] execVM 'data\scripts\submit.sqf'";

not _Ocap or _this.

SOLDIERS

in evo_missionmanager.sqf

	{_handle = [_x] execVM "data\scripts\submit.sqf"} forEach list BIS_EVO_DetectEast;

this is carried out on the last 4 alive east in the area.

ok scripts/submit.sqf does this for both officer and soldiers

// Puts enemy soldiers into the capture state.
_unit = _this select 0;
_grp = group _unit;
if(_tag > 0) then {_unit removeaction _tag};
_tag = _unit addaction [localize "STR_M04xt10","data\scripts\capture.sqf",0,1, true, true,""]; // "Capture"
if(_tag > 0) exitWith {_unit removeaction _tag};
if (isServer) then
{
	removeallweapons _unit;
	_unit setBehaviour "Careless";
	_unit allowFleeing 0;
	commandStop _unit;
	_unit switchmove "amovpercmstpsnonwnondnon";
	_unit addEventHandler ["killed", {BIS_EVO_sot = format["%1",(_this select 1)];BIS_EVO_sor = -5;BIS_EVO_sop = (_this select 1);publicVariable "BIS_EVO_sop";publicVariable "BIS_EVO_sot";publicVariable "BIS_EVO_sor";(_this select 0) removealleventhandlers "killed"}];
//trying this to stop the AI from changing anim state and being captured twice
_unit disableAI "AUTOTARGET";
};
WaitUntil {not (alive _unit) or animationState _unit == "AmovPercMstpSsurWnonDnon"};
_unit removeaction _tag;
sleep 30.0;
deletevehicle _unit;

so the script capture is called here with

_tag = _unit addaction [localize "STR_M04xt10","data\scripts\capture.sqf",0,1, true, true,""]; // "Capture"

capture.sqf contains

// Attached to enemy prisoners and officers
_unit = _this select 0;
_user = _this select 1;
_usergroup = group _user;
[_unit] join grpNull;
_unit switchMove "AmovPercMstpSsurWnonDnon";
WaitUntil {isNull BIS_EVO_sop};
if (_unit isKindOf "RU_Soldier_Officer") then
{	
_txtpasshead = localize "STR_M04t66";//Officer Captured
_txtpassbody = format["+%1 %2",20,localize "STR_M04t0_5"];//Points
["#0000FF",_txtpasshead,_txtpassbody] call BIS_EVO_Message;
//edited some bits here for brevity - they dont affect the issue
if(BIS_EVO_MissionProgress == 10) then {BIS_EVO_sot = "pitso2"};
BIS_EVO_sor = 20;BIS_EVO_sop = player;publicVariable "BIS_EVO_sor";publicVariable "BIS_EVO_sot";publicVariable "BIS_EVO_sop";
}
else
{
_txtpasshead = localize "STR_M04t67";//Prisoner Captured
_txtpassbody = format["+%1 %2",3,localize "STR_M04t0_5"];//points
["#0000FF",_txtpasshead,_txtpassbody] call BIS_EVO_Message;
BIS_EVO_sot = format["%1",_unit];BIS_EVO_sor = 3;BIS_EVO_sop = player;publicVariable "BIS_EVO_sor";publicVariable "BIS_EVO_sot";publicVariable "BIS_EVO_sop";
};

so the first part ofthis script works for the officer and the second for the infantry

now when I run this on a dedi, the officer can be captured but the capture action is not visible to clients. when i run it on my pc, i can capture both.

i think it must be the fact that the addaction is being run differently for each...

officer (looks like public)

_offobj setVehicleInit "Ocap = [this] execVM 'data\scripts\submit.sqf'";

soldiers (looks like server side only)

{_handle = [_x] execVM "data\scripts\submit.sqf"} forEach list BIS_EVO_DetectEast;

and both demand this, which looks like it should run on the client

_tag = _unit addaction [localize "STR_M04xt10","data\scripts\capture.sqf",0,1, true, true,""]; // "Capture"

can someone explain how i might make this work for clients joining a MP dedi server wishing to capture the soldiers as well as the officer?

I get so confused by the client/server public/private thing...

thanks in advance

Edited by eggbeast

Share this post


Link to post
Share on other sites

I think your problem has to do with officers being defined in a separate file from soldiers.

evo_erec.sqf = officer

evo_missionmanager.sqf = soldiers

In the case of the Officer, when he is created he gets an init status - basically means that when all clients join, they see that init code and thus run it. For the Soldiers, it looks like a script runs (maybe server exclusive) that detects soldiers and then runs a foreach command on the array of soldiers it finds. It doesn't run that routine on all clients, and since the soldiers aren't created, the init code doesn't apply.

So somehow you either need to find out exactly who runs evo_missionmanager.sqf and locate the detection routine for soldiers, and make sure that routine is run by all clients. Although I don't understand setVehicleInit that well, you could try this in place of the code in evo_missionmanager.sqf:

{_x setvehicleinit "_handle = [_x] execVM ""data\scripts\submit.sqf""";} forEach list BIS_EVO_DetectEast;

Which, hopefully, would cause the code to be ran in the same way as it does on the officer.

Share this post


Link to post
Share on other sites

hi Franze

thanks for trying to help me!

some more info...

in the mission sqm, there is a trigger like this

		class Item24
	{
		position[]={4753.2314,0.23779801,1905.8721};
		timeoutMin=1;
		timeoutMid=1;
		timeoutMax=1;
		interruptable=1;
		age="UNKNOWN";
		text="sinit";
		name="sinit";
		expCond="isServer";
		expActiv="plays = [] execVM ""data\scripts\sinit.sqf"";";
		class Effects
		{
		};
	};

the main server init (sinit.sqf) calls the routine which monitors the city:

_events = [] execVM "data\scripts\EVO_MissionManager.sqf";

EVO_MissionManager.sqf looks like this in its entirety

// City Setup
_mkr = (BIS_EVO_MissionTowns select BIS_EVO_MissionProgress);
_pos = getMarkerPos _mkr;
BIS_EVO_DetectEast = createTrigger ["EmptyDetector", _pos];
BIS_EVO_DetectEast setTriggerActivation ["EAST", "PRESENT", true];
BIS_EVO_DetectEast setTriggerArea [500, 500, 0, true];
BIS_EVO_DetectEast setTriggerTimeout [2, 2, 2, true ];

BIS_EVO_DetectWest = createTrigger ["EmptyDetector", _pos];
BIS_EVO_DetectWest setTriggerActivation ["WEST", "PRESENT", true];
BIS_EVO_DetectWest setTriggerArea [600, 600, 0, true];
BIS_EVO_DetectWest setTriggerTimeout [2, 2, 2, true ];
_count = (count BIS_EVO_MissionTowns);

Sleep 2.0;
while {BIS_EVO_MissionProgress < _count} do
{
	_mkr = (BIS_EVO_MissionTowns select BIS_EVO_MissionProgress);
	_pos = getMarkerPos _mkr;

BIS_EVO_DetectEast setpos _pos;
BIS_EVO_DetectWest setpos _pos;
Sleep 2.0;
//adding
CityClear=false;

[_mkr,BIS_EVO_DetectEast,BIS_EVO_DetectWest,BIS_EVO_MissionProgress] call BIS_EVO_Erec;

Sleep 10.0;

for [{_loop=0}, {_loop<1}, {_loop=_loop}] do
{
	if ("Man" countType list BIS_EVO_DetectEast <= 4) then
	{
		if ("Tank" countType list BIS_EVO_DetectEast  == 0) then
		{
			if("Car" countType list BIS_EVO_DetectEast == 0) then
			{
				if ("Land" countType list BIS_EVO_DetectWest > 0) then{_loop=1};
			};
		};
	};
	Sleep 4;
};

//	{_handle = [_x] execVM "data\scripts\submit.sqf"} forEach list BIS_EVO_DetectEast;

{_x setvehicleinit "_handle = [_x] execVM ""data\scripts\submit.sqf""";} forEach list BIS_EVO_DetectEast;

processInitCommands;

{_x addscore 10} forEach list BIS_EVO_DetectWest;
BIS_EVO_MissionProgress = BIS_EVO_MissionProgress+1;
publicVariable "BIS_EVO_MissionProgress";
//player globalchat format ["BIS_EVO_MissionProgress: %1",BIS_EVO_MissionProgress]; 
};

you can see I tried your suggestion, with some added processinitcommands in case this might help, but it didn't work either way - when I was the server host

the original script works when I'm host.

can an init really be run on something that has already been created?

is there another way to run the submit routine for clients on each soldier in the trigger zone (on a serverside script)?

i am so puzzled with this but im sure if we can work it out the whole scripting game will become clear...

Edited by eggbeast

Share this post


Link to post
Share on other sites

Ok, whats happening is the trigger only runs on the server, as noted by the "isServer" condition. The server itself tracks the units, no clients do that. MissionManager needs to either run on all clients, or the data gathered by the server with it needs to be sent to all clients.

You could try piling the units detected by the trigger into an array, then broadcast that array to all clients using publicVariable. That may or may not work - I'm not exactly sure. You would need to run a script on all clients that detects changes to the array, which would then apply the action to the units.

change made in MissionManager

west_surrender_array = list BIS_EVO_DetectEast;
publicvariable "west_surrender_array"

part of the looping script on client

while {time > 0} do
{
base_west_surrender_array = west_surrender_array;
sleep 5;
if (count west_surrender_array > count base_west_surrender_array || count west_surrender_array < count base_west_surrender_array) then
{
player execvm "clientsoldieraddaction.sqf";
};
sleep 5;
};

clientsoldieraddaction.sqf

while {time > 0} do
{
{_handle = [_x] execVM "data\scripts\submit.sqf"} forEach west_surrender_array;
sleep 5;
};

Share this post


Link to post
Share on other sites

ooh that's so elegant

cheers mate I'll give it a go...

***sound of massive lightbulb going on***

huge thanks

Share this post


Link to post
Share on other sites

ok ive got it to the point where it will run the submit script on the clients... so thanks for your help so far.

the next problem in the chain is that submit is a server-side script - see below

using hints i worked out that the array west_surrender_array contains 81 units. i tracked the system to the point where it calls submit on each of the units in the west_surrender_array

only submit doesn't work on these soldiers - how to modify it so the client-called script affects them?

FULL PATH

in the sinit.sqf server init, cevo_missionmanager is called, which now contains this after the surrender condition is met

	west_surrender_array = list BIS_EVO_DetectEast;
publicvariable "west_surrender_array";
hint format["array count: %1",(count west_surrender_array)]; //returns 81 units

in init.sqf I added this line

west_surrender_array = [];				//added to make array of capturable soldiers on clients

mainthreadc is called on the clients, it contains all the looping stuff including

_base_west_surrender_array = west_surrender_array;
for [{_loop=0}, {_loop<1}, {_loop=_loop}] do
{
//[] call BIS_EVO_CWeath;
//	sleep 1.011;
[] call BIS_EVO_Repair;
sleep 1.011;
if (score player != _tscore and alive player) then {[] call BIS_EVO_Rank};
if (BIS_EVO_MissionProgress > _currentprog) then {[] call BIS_EVO_CityClear};
sleep 1.011;
[] call BIS_EVO_CTime;
sleep 1.011;
[] call BIS_EVO_HPM;
sleep 1.011;
[] call BIS_EVO_Surrender; //new
};

BIS_EVO_Surrender = 
{
hint "surrender array called";//note this pings every 8 secs or so on the server
sleep 2;
if ((count west_surrender_array > count _base_west_surrender_array) || (count west_surrender_array < count _base_west_surrender_array)) then
{
//		_surrender = player execvm "data\scripts\clientsoldieraddaction.sqf";
	hint "surrender script called";
	player execvm "data\scripts\clientsoldieraddaction.sqf";
	sleep 5;
	_base_west_surrender_array = west_surrender_array;
};
sleep 2;
};

clientsoldieraddaction.sqf contains

//applies submit routine to 4 surrendering troops on all clients at end of city
//while {time > 0} do
//{
hint "new script called submit";// this pings up ok when town surrenders
sleep 5;
{_handle = [_x] execVM "data\scripts\submit.sqf"} forEach west_surrender_array;
sleep 5;
//};

submit looks like this

// Puts enemy soldiers into the capture state.
_unit = _this select 0;
_grp = group _unit;

//if(_tag > 0) then {_unit removeaction _tag};
_tag = _unit addaction [localize "STR_M04xt10","data\scripts\capture.sqf",0,1, true, true,""]; // "Capture"

//if(_tag > 0) exitWith {_unit removeaction _tag};

if (isServer) then
{
	removeallweapons _unit;
//adding
	_unit setBehaviour "Careless";
	_unit allowFleeing 0;
	commandStop _unit;
//
	_unit switchmove "amovpercmstpsnonwnondnon";
	_unit addEventHandler ["killed", {BIS_EVO_sot = format["%1",(_this select 1)];BIS_EVO_sor = -5;BIS_EVO_sop = (_this select 1);publicVariable "BIS_EVO_sop";publicVariable "BIS_EVO_sot";publicVariable "BIS_EVO_sor";(_this select 0) removealleventhandlers "killed"}];
	_unit disableAI "AUTOTARGET";
};

WaitUntil {not (alive _unit) or animationState _unit == "AmovPercMstpSsurWnonDnon"};
_unit removeaction _tag;

sleep 30.0;

deletevehicle _unit;

i tried remming out the "if is server" but it didn't work.

basically the enemy units keep firing and attacking

any ideas? thanks for your patience with me!

Edited by eggbeast

Share this post


Link to post
Share on other sites

You can try to change the if condition in submit - change it from isServer to:

alive _unit

Assuming that the action is working but the unit behavior isn't being followed.

Share this post


Link to post
Share on other sites

still doesn't work :(

I'm going for a different approach - basically calling makepow instead of submit for the units in the detect east array.

makepow deletes the units and replaces them like-for-like with a new init line the same as the officer had, with the submit called there.

// remakes enemy pows to be able to be put into the capture state
_unit = _this select 0;
_grp = group _unit;
_type = typeof _unit;
_posu = position _unit;

if (_type == "RU_Soldier_Officer") exitwith {};

unassignVehicle _unit;
_unit setPos _posu;
deleteVehicle _unit;

//hint "makepow active";

_lastgroup = createGroup east; 
_unitn = _lastgroup createUnit [_type, _posu, [], 1, "NONE"];Sleep BIS_EVO_GlobalSleep;
_unitn addEventHandler ["killed", {handle = [_this select 0] execVM "data\scripts\bury.sqf"}];
[_unitn] join _lastgroup;
_unitn setVehicleInit "ucap = [this] execVM 'data\scripts\submit.sqf'";
processInitCommands;
_recy = [objnull,_lastgroup] execVM "data\scripts\grecycle.sqf";
Sleep 3;

seems to work ok on my PC (but this doesn't mean anything right?) so gonna check it out on the dedi.

not ideal but saves a load of trouble trying to get this working on living units...

Edited by eggbeast

Share this post


Link to post
Share on other sites

yes it works like a dream

thanks for your help in my darkest hour franze - you gave me the inspiration to keep at it until it was fixed :D

Share this post


Link to post
Share on other sites

Always happy to help, especially when I've been there many times with the client-server issues. ;)

Share this post


Link to post
Share on other sites

yeah, it's not the best way to do it,cos if i had some routine like a side mission running with this, it might end the mission when they were deleted etc, but hey ho, it works...

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  

×