eggbeast 3684 Posted April 22, 2010 (edited) 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 April 22, 2010 by eggbeast Share this post Link to post Share on other sites
eggbeast 3684 Posted April 23, 2010 bump - anyone got any ideas at all? Share this post Link to post Share on other sites
franze 196 Posted April 27, 2010 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
eggbeast 3684 Posted April 27, 2010 (edited) 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 April 27, 2010 by eggbeast Share this post Link to post Share on other sites
franze 196 Posted April 28, 2010 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
eggbeast 3684 Posted April 28, 2010 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
eggbeast 3684 Posted April 28, 2010 (edited) 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 April 28, 2010 by eggbeast Share this post Link to post Share on other sites
franze 196 Posted April 28, 2010 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
eggbeast 3684 Posted April 29, 2010 (edited) 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 April 29, 2010 by eggbeast Share this post Link to post Share on other sites
eggbeast 3684 Posted April 29, 2010 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
franze 196 Posted April 30, 2010 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
eggbeast 3684 Posted April 30, 2010 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
SpectrumWarrior 0 Posted October 9, 2010 I am so glad I found this post. I have been fighting this matter since arma2 came out lmao Share this post Link to post Share on other sites