Jump to content
stuguy

scripted child tasks do not end with parent

Recommended Posts

I scripted a bunch of child tasks to go inside of a parent task.  In this case, I have 7 locations that a unit may randomly spawn in and if the player finds him, the parent succeeds.  If the location is empty when the player arrives, the child cancels out so the task WP isn't there.  I would just love it if the left over child tasks complete with the parent when I find the unit.  And yes, I succeed the parent and the parent task is crossed out, but the children are wide open and ready to go still.  Are there any particulars about parent and child tasks that I may not be in the BIS wiki?  If you see this Image, my tasks are listing as children.

Share this post


Link to post
Share on other sites

//A trigger in mission editor activates startingIslandTasks

myCreateTask2 = {
	params ["_unit", "_pos", "_name", "_desc", "_brief","_task"];
	_newTask = _unit createSimpleTask [_name,_task];
	_newTask setSimpleTaskDescription [_desc, _brief, _name];
	_newTask setSimpleTaskDestination (_pos);
	_newTask setTaskState "CREATED";
	_newTask;
};

myCreateTask3 = {
	params ["_unit", "_name", "_desc", "_brief"];
	_task = _unit createSimpleTask [_name];
	_task setSimpleTaskDescription [_desc, _brief, _name];
	_task setTaskState "CREATED";
	_task;
};


//A trigger in mission editor activates startingIslandTasks
startingIslandTasks = {
	"rand_ally1" setMarkerAlpha 1;
	"rand_ally2" setMarkerAlpha 1;
	"rand_ally3" setMarkerAlpha 1;
	"rand_ally4" setMarkerAlpha 1;
	"rand_ally5" setMarkerAlpha 1;
	"rand_ally6" setMarkerAlpha 1;
	"rand_ally7" setMarkerAlpha 1;
	task02 = [player, getMarkerpos "tuvanaka_radio", "Reconnoitre GSM Station.", "Reconnoitre the GSM radio broadcasting station.  Gather any possible intelligence about the facility or island.  If possible, sequester the station and recruit any personnel willing to fight against the QDA.  Should the facility be under QDA protection, it is recommended that you do not engage in hostilities until you comprehend the full capability of the local QDA forces.", "Reconnoitre GSM Station.",taskEnd] call myCreateTask2;
	task03 = [player, getMarkerpos "tuvanaka_comms", "Reconnoitre Comms Whiskey", "Reconnoitre the Comms Whiskey military broadcasting station.  This station is likely the hub for all local military short range radio communications.  If possible, do not engage in open hostilities with the local QDA forces.  It is highly likely that Dedrianna's generals will order reestablishment of communications at this facility should they be disrupted.", "Reconnoitre Comms Whiskey",taskEnd] call myCreateTask2;
	task04 = [player, "Find Michael Connors", "Search possible remote locations for insights to the whereabouts of Michael Connors.", "Find Michael Connors"] call myCreateTask3;
	task04a = [player, getMarkerpos "rand_ally1", "Search location for Connors", "Search this location for signs of Michael Connors.", "Search location for Connors", task04] call myCreateTask2;
	task04b = [player, getMarkerpos "rand_ally2", "Search location for Connors", "Search this location for signs of Michael Connors.", "Search location for Connors", task04] call myCreateTask2;
	task04c = [player, getMarkerpos "rand_ally3", "Search location for Connors", "Search this location for signs of Michael Connors.", "Search location for Connors", task04] call myCreateTask2;
	task04d = [player, getMarkerpos "rand_ally4", "Search location for Connors", "Search this location for signs of Michael Connors.", "Search location for Connors", task04] call myCreateTask2;
	task04e = [player, getMarkerpos "rand_ally5", "Search location for Connors", "Search this location for signs of Michael Connors.", "Search location for Connors", task04] call myCreateTask2;
	task04f = [player, getMarkerpos "rand_ally6", "Search location for Connors", "Search this location for signs of Michael Connors.", "Search location for Connors", task04] call myCreateTask2;
	task04g = [player, getMarkerpos "rand_ally7", "Search location for Connors", "Search this location for signs of Michael Connors.", "Search location for Connors", task04] call myCreateTask2;
	task05 = [player, getMarkerpos "tuvanaka_afb", "Capture Tuvanaka AB", "Capture and hold the Tuvanaka air base.  Holding this location will allow me to bring in equipment and mercenaries and make reinforcing the opposition more logistically complicated.  I should not attack this facility head on, it is highly likely that the entirety of the QDA forces on this island are stationed here.  I should have a full understanding of what I am up against before blindly assaulting a heavily gaurded air base.", "Capture Tuvanaka AB",taskEnd] call myCreateTask2;
	task06 = [player, getMarkerpos "Tuvanaka", "Capture the harbor city Tuvanaka", "Capture and hold the harbor city of Tuvanaka.  This harbor is the second pier location in which supplies may be shipped to the island by sea.  By holding this region, I may launch small boats, assault craft, landing vessels, and ferry troops and vehicles to other harbor locations that I own.  By removing this city from the hands of the QDA, I can prevent my enemy from ferrying over heavy armor.  The size and scope of the military presence located in Tuvanaka is unknown.  It is likely to be gaurded by a security detail originating from Tuvanaka AB.  Should the city fall into my hands, I can expect enemy forces to make an attempt to take it back.", "Capture the harbor city Tuvanaka",taskEnd] call myCreateTask2;
	task07 = [player, getMarkerpos "tuv_hosp", "Reconnoitre the Tuvanaka hospital.", "The Tuvanaka hospital is likely to be a great location to requisition medical supplies and expertise should I be unable to outsource.  According to my intel, this private general hospital has working generators, an ER, clean water, and sanitation.  Perhaps not the most advanced hospital in the world, they should be able to pry a bullet or two from your rear end in a pinch.", "Reconnoitre the Tuvanaka hospital.",taskEnd] call myCreateTask2;
};
//A trigger in mission editor activates startingIslandTasks

 

Share this post


Link to post
Share on other sites

Lou_Montana note from biki page says: Succeeding parent task will automatically succeed childs, whatever their taskState was set to. (I.E. If a task is set as a child to another, it will be completed when its parent is complete.. no matter if the child task really was or not)

 

If nothing helps, as temporary workaround, you can create trigger with activation statement:  taskState "Find Michael Connors" == "Succeeded", where manually finalize child tasks.

 

Also,

// Try replace
// "rand_ally1" setMarkerAlpha 1;
// "rand_ally2" setMarkerAlpha 1;
// ...
// "rand_allyN" setMarkerAlpha 1;
// With:
{if (_x find "rand_ally" == 0) then {_x setMarkerAlpha 1}} forEach allMapMarkers;

 

Share this post


Link to post
Share on other sites

@serena

I read Lou Montana's entry, hence I came to the forum and asked if there was something amiss with how I was scripting my tasks.  When I succeed the parent, the remaining children (and cancelled ones) should also succeed, but they aren't.  If I am not doing something goofy, I will make a bug report.  Who knows, it could be a mod that I am using or something?

 

I appreciate you submitting a code, but it doesn't work because you forgot semicolons and a few other things.  You also need to use isEqualTo instead of ==.

Share this post


Link to post
Share on other sites

I made a work around, though I am still not sure why my child tasks will not clear automatically when I set the parent to succeed.  I created a trigger that activates when the Connors character joins my group.  The trigger then executes this command to clean up the mission a bit:

{if (_x find "rand_ally" isEqualto 0) then {deleteMarker _x;};} forEach allMapMarkers;
{if (taskDescription _x find "Search location for Connors" isEqualto 1) then{_x setTaskState "Succeeded"; player removeSimpleTask _x;};}forEach simpleTasks player;
task04 setTaskState "Succeeded";

I manually succeed and remove all of the child tasks that have the "Search location for Connors" string so the task list isn't populated with redundant child tasks that aren't relevant anymore.  They are indeed child tasks, so I am still curious why they do not complete with the parent?

Share this post


Link to post
Share on other sites

Just created mission with two markers, named: rand_ally1 and rand_ally2. Then in debug console:

{if (_x find "rand_ally" == 0) then {_x setMarkerAlpha 0}} forEach allMapMarkers;
// markers disappeared

{if (_x find "rand_ally" == 0) then {_x setMarkerAlpha 1}} forEach allMapMarkers;
// markers visible again

What's wrong?

 

UPD: Experimented with tasks. Making parent task "succeeded" manually does not change states of child tasks.

Share this post


Link to post
Share on other sites
1 hour ago, serena said:

UPD: Experimented with tasks. Making parent task "succeeded" manually does not change states of child tasks.

That's what I gathered so far.  Though the documentation says otherwise.

Share this post


Link to post
Share on other sites
1 hour ago, serena said:

Just created mission with two markers, named: rand_ally1 and rand_ally2. Then in debug console:


{if (_x find "rand_ally" == 0) then {_x setMarkerAlpha 0}} forEach allMapMarkers;
// markers disappeared

{if (_x find "rand_ally" == 0) then {_x setMarkerAlpha 1}} forEach allMapMarkers;
// markers visible again

Just good practice when scripting in SQF to use semicolons after each command in your then {}; block.  Also close out the then block with the semi colon. 

 

if (condition) then {command1; command2;};

if (condition) then {command1; command2;} else {command3;};

if (condition) exitWith {command1;};

 

I use isEqualTo instead of == so I can use the script in multiplayer.

Share this post


Link to post
Share on other sites

To be very clear, I just want to indicate the fact that this statement is not true: "it doesn't work because you forgot semicolons and a few other things".

 

And this is not true too:  "You also need to use isEqualTo instead of ==".

 

And the fact that this code works.

 

It is quite another matter if someone likes a semicolon everywhere where it can be put - this is a matter of taste. But tastes differ :)

Share this post


Link to post
Share on other sites
14 minutes ago, stuguy said:

I use isEqualTo instead of == so I can use the script in multiplayer.

 

Where I can read about different behavior between isEqualTo and == in multiplayer, or it is just a rumors? 

Share this post


Link to post
Share on other sites

The only reason to use isEqualTo (* in case we comparing numbers) - slightly better performance. Test results:

Code		Cycles		Time
0 == 0		10000		0.0018 ms
0 == 1		10000		0.0019 ms
0 isEqualTo 0	10000		0.0014 ms
0 isEqualTo 1	10000		0.0015 ms

 

Share this post


Link to post
Share on other sites
41 minutes ago, stuguy said:

I use isEqualTo instead of == so I can use the script in multiplayer.

23 minutes ago, serena said:

 

Where I can read about different behavior between isEqualTo and == in multiplayer, or it is just a rumors? 

 

Where is this behaviour documented? ( as it needs to be quashed )

Either has no bearing on multiplayer. Only difference between the two that I can think of off the top of my head is,

String == is not case sensitive, Where isEqualTo is.

== cannot check for Null where isEqualTo can.

And the slight performance improvement as shown by Serena.

Share this post


Link to post
Share on other sites

Thank you, Larrow. I need to be corrected in previous post: the only reason to use isEqualTo, when comparing numbers, is slightly better performance. It is important :)

Share this post


Link to post
Share on other sites

:don14:

 

So nobody can explain why children aren't closing out with parents then? 

Share this post


Link to post
Share on other sites

Because at the moment it is the game behavior. It makes sense to create a ticket to correct this behavior in the next patch.

  • Like 1

Share this post


Link to post
Share on other sites

It works correctly if you use the BIs task functions, rather than the simple task commands.

[ player, "task_1", ["a Task", "a short Description", "a Task waypoint" ], player getPos [ 20, getDir player ], "Created", 1, true ] call BIS_fnc_taskCreate;

[ player, [ "task_1a", "task_1" ], ["a child Task", "a short child Description", "a child Task waypoint" ], player getPos [ 10, getDir player ], "Created", 1, true ] call BIS_fnc_taskCreate;

{
	[ _x ] params[ "_taskID" ];

	_trigger = createTrigger [ "EmptyDetector", [ _taskId ] call BIS_fnc_taskDestination, false ];
	_trigger setTriggerArea [ 1, 1, 0, false, 5];
	_trigger setTriggerActivation [ "WEST", "PRESENT", false ];
	_trigger setTriggerStatements ["this", format[ "
		[ %1, 'Succeeded', true ] call BIS_fnc_taskSetState;
	", str _taskID ], ""];
}forEach [ "task_1", "task_1a" ];

But still as Serena says you should enter a support ticket for the original problem.

 

Edited by Larrow
updated rough test code

Share this post


Link to post
Share on other sites

Guys, what you think about this code:

_prevData = [];
for "_index" from 0 to 11 do {
	_prevData pushBack (
		(if ((missionNamespace getVariable [format["%1.%2",_taskVar,_index],
			["","",[],[],[objNull,false],-1,"","","","CREATED","Default",false] select _index]) isEqualType [])
				then {+(missionNamespace getVariable [format["%1.%2",_taskVar,_index],
					["","",[],[],[objNull,false],-1,"","","","CREATED","Default",false] select _index])}
							else {(missionNamespace getVariable [format["%1.%2",_taskVar,_index],
							["","",[],[],[objNull,false],-1,"","","","CREATED","Default",false] select _index])}));};

And do you want to know where this code from?

Share this post


Link to post
Share on other sites

Its terrible to read formatted like that but from all the "%1.%2" I would imagine it is pulled from one of the new BI task functions.

Share this post


Link to post
Share on other sites

It is original formatting:

VVvwU2X.png

 

But problem is not in bad format. Problem is whole API include all BIS_fnc_TaskXXX functions is just a trash :)

Share this post


Link to post
Share on other sites

This is how to BIS_fnc_SetTaskState updates children state:

// ...
{
	// ...
	{
		[_x,nil,nil,nil,_state,nil,false] call bis_fnc_setTask;
	};
} foreach _children;

 

 

Share this post


Link to post
Share on other sites

What file and how are you pulling that? That just looks like a no formatted loadFile.

Ive read through all the task functions, a while back when they where rewritten ~1.56, and I cant remember seeing anything as badly formatted as that.

Admittedly they are hard to read due to the heavy usage of macros but they are pretty lean network wise, only sending the part of task vars that have changed over the network in minimalist var names.

 

TBH and I know some people dont like it but I prefer the way Moricky writes some of his functions as switch statements, easy to read, all in one place and you can collapse each section your not working on via code folding. ok can be situational when you can write them this way but its so much easier to work on.

Share this post


Link to post
Share on other sites
4 minutes ago, Larrow said:

What file and how are you pulling that? That just looks like a no formatted loadFile.

 

copyToClipboard str BIS_fnc_taskCreate
// then BIS_fnc_taskSetState, BIS_fnc_setTask, BIS_fnc_setTaskLocal, BIS_fnc_taskVar

 

Share this post


Link to post
Share on other sites

Unpack the files and read them as written. eg your previous post for _prevData looks like....

_prevData = [];
for "_index" from 0 to 11 do {_prevData pushBack (GET_DATA(_taskVar,_index));};

And you have to read it along with the macro file..

#define ID						0	// _id			| ""
#define PARENT						1       // _parent		| ""
#define CHILDREN					2       // _children		| []
#define OWNERS						3       // _owners		| []
#define DESTINATION					4       // _destination		| [objNull,false]
#define PRIORITY					5       // _priority		| -1
#define DESCRIPTION					6       // _description		| ""
#define TITLE						7       // _title		| ""
#define MARKER						8       // _marker		| ""
#define STATE						9       // _state		| "CREATED"
#define TYPE						10      // _type		| "Default"
#define CORE						11      // _core		| false

#define VAR_TEMPLATE					"%1.%2"
#define GET_VAR(TASKVAR,INDEX)				format[VAR_TEMPLATE,TASKVAR,INDEX]
#define GET_DEFAULT_DATA(INDEX)				["","",[],[],[objNull,false],-1,"","","","CREATED","Default",false] select INDEX

#define GET_DATA_NIL(TASKVAR,INDEX)			(missionNamespace getVariable (GET_VAR(TASKVAR,INDEX)))

//this is internal, only for use in GET_DATA macro, don't use outside as it is not safe :)
#define GET_DATA_UNSAFE(TASKVAR,INDEX)			(missionNamespace getVariable [GET_VAR(TASKVAR,INDEX),GET_DEFAULT_DATA(INDEX)])

#define GET_DATA(TASKVAR,INDEX)				(if (GET_DATA_UNSAFE(TASKVAR,INDEX) isEqualType []) then {+GET_DATA_UNSAFE(TASKVAR,INDEX)} else {GET_DATA_UNSAFE(TASKVAR,INDEX)})
#define SET_DATA(TASKVAR,INDEX,VALUE)			(missionNamespace setVariable [GET_VAR(TASKVAR,INDEX),VALUE])
#define SET_DATA_BROADCAST(TASKVAR,INDEX,VALUE)		(missionNamespace setVariable [GET_VAR(TASKVAR,INDEX),VALUE,true])

It will make a lot more sense than the twisted mess you get through copying it to clipboard.

Share this post


Link to post
Share on other sites
23 minutes ago, Larrow said:

It will make a lot more sense than the twisted mess you get through copying it to clipboard.

 

For me it is there all terrible like a death, does not matter formatted or not.

 

Anyway, it is clear from the code: updating state of parent task entails cyclic update task state of each children. And no magic behind :)

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

×