Jump to content
Zenophon

Zenophon's ArmA 3 Co-op Mission Making Framework

Recommended Posts

On 4/22/2017 at 11:20 PM, kman_(kya) said:

 

Hey Atlas, have you released any of your scenarios?

 

Freelancers - Tanoa at War

It has been on steam workshop for like 10 days.

Share this post


Link to post
Share on other sites

Zen, I'm wondering if you can offer some advice.  I am trying to build a method to handle jip players and syncing tasks.  I looked at your example in your sample missions and for the life of me cannot get them to work in my own missions.

I tried my own implementation.

 

In init.sqf I use the following to setup my mission tracking:

 

if ((isServer) or (isDedicated)) then
{	
	HasMission = 0;
	publicVariable "HasMission";
};


if (HasMission > 0) then 
{
	0 = [player] execVM "Sync_Tasks.sqf";
};

// All clients stop executing here, do not delete this line
if (!isServer) exitWith {};  

playerList = [];
{
	if (isPlayer _x) then
		{
		playerList pushBack _x;
		};
} forEach playableUnits;
publicVariable "playerList";

0 = [] spawn 
{
    while {true} do
	{
		sleep 15;
		FoundPlayers = [];
		{
			if (isPlayer _x) then
				{
				FoundPlayers pushBack _x;
				};
		} forEach playableUnits;
		playerList = FoundPlayers;
		publicVariable "playerList";
		//titleText ["Found Players: " + str playerList, "PLAIN"];  // debug purposes
	};
};

Task1Status = 0; 
publicVariable "Task1Status";

// Once players do something to start the mission assignment

// Create the first task for players
_task1text = "Blah blah blah words.";
_task1title = "Blah blah blah task title.";
Task1 = [playerList,_task1text,_task1title,"Mk_Task_1",true,'','search'] call Zen_InvokeTask;
publicVariable "Task1";

HasMission = 1;
publicVariable "HasMission";

Task1Status = 1;
publicVariable "Task1Status";

And in my Sync_Tasks.sqf I have simply:

 

if (Task1Status != 0) then 
{
	0 = [Task1,player ] call Zen_ReassignTask;
};

 

On rejoining a mission (dedicated server) after a task has been assigned, I get an error that the task doesn't exist. (something like: ["Zen_ReassignTask",[<null>,B Alpha 1-1:1 (AccuracyThruVolume), 102.347])

I thought assigning the task to a global variable and publicVariable-ing it would do the trick, but no joy.

 

I tried adding some code into Sync_Tasks to ensure the player is spawned and also what code I saw in your JIP_Sync example:

 

waitUntil {player == player};
sleep 6;

Zen_Task_Array_Global = 1;
Zen_MP_Closure_Packet = ["Zen_SyncJIPServer", player];
publicVariableServer "Zen_MP_Closure_Packet";

// Wait until the client has the necessary data, do not change this
waitUntil {
	(!(isNil "Zen_JIP_Args_Server") && (typeName Zen_Task_Array_Global == "ARRAY"))
};

But then i observe this interesting error in the .rpt

 

 1:33:34 "-- Zen_MP_Closure_Packet Error --"
 1:33:34 "Given function string is undefined"
 1:33:34 205.534
 1:33:34 "Zen_SyncJIPServer"
 1:34:12 Client: Remote object 4:2 not found

 

I'm assuming there is some kind of oversight in my method of using global variables and assign in progress tasks to jips.    Any ideas on how make this functional?     

 

Thanks for your time in advance.

 

--ATV

Share this post


Link to post
Share on other sites

Detecting that a client in JIP should be done correctly by the framework; it will give you the _Zen_Is_JIP boolean in the init.  It will also wait for the player to initialize before compiling the framework.


Task1 is undefined because running publicVariable only sends the variable to current clients.  The JIP client doesn't have this variable defined, or any of the information it needs when it starts.  Zen_SyncJIPServer is given as a template in the JIP demonstration to show how to the JIP client 'asks' the server for the information it needs, but you must define it in your mission and customize it.  For example, in your mission it could include


(owner _this) publicVariableClient "Task1";


Once the waitUntil is over, the JIP client can use that variable.


Also, using Zen_ReassignTask assumes that the JIP player's object did not previously exist.  That means that other clients have no information about it either; thus, every client must be updated with the tasks of the new object.  If you've disabled friendly AI, then using Zen_ReassignTask is correct.


If the player object did exist (as an AI), the JIP demonstration shows how to use the private function Zen_InvokeTaskClient to update tasks.  There is a mistake in the JIP demonstration with Zen_InvokeTaskClient; the line should end with '(_x select 6), (_x select 8)] call Zen_InvokeTaskClient;', since tasks now support different icons.  The error doesn't stop tasks from working though.

Share this post


Link to post
Share on other sites

Thanks Zen,

 

Strange, the description on publicVariable states:

 

Variables broadcast with publicVariable during a mission stay persistent for JIP (Join In Progress) clients. Such persistent variables are synced to the JIP client before the first batch of client side Event Scripts are ran. 

 

I thought that meant that it would cover jippers.

 

So it looks like I just need to do this, correct?

 

if (Task1Status != 0) then 
{
    (owner _this) publicVariableClient "Task1";
    0 = [Task1,player ] call Zen_ReassignTask;
};

 

Although for my example, "player" and "_this" are interchangeable.

 

--ATV

 

Edit: Tried my idea above... still no joy. Someday I'll get this work lol.

Share this post


Link to post
Share on other sites

Hey Zen,

 

loving the framework!

 

Quick question about the Zen_OrderVehiclePatrol, I'm noticing it isn't working for APC's and MRAP's they seem to get their waypoints but don't move to them.

Any idea on how to work around that?

 

Cheers.

Share this post


Link to post
Share on other sites
On 5/6/2017 at 4:37 PM, accuracythruvolume said:

Thanks Zen,

 

Strange, the description on publicVariable states:

 

Variables broadcast with publicVariable during a mission stay persistent for JIP (Join In Progress) clients. Such persistent variables are synced to the JIP client before the first batch of client side Event Scripts are ran. 

 

I thought that meant that it would cover jippers.

 

So it looks like I just need to do this, correct?

 

if (Task1Status != 0) then 
{
    (owner _this) publicVariableClient "Task1";
    0 = [Task1,player ] call Zen_ReassignTask;
};

 

Although for my example, "player" and "_this" are interchangeable.

 

--ATV

 

Edit: Tried my idea above... still no joy. Someday I'll get this work lol.

 

You are correct, publicVariable does say you don't need to manually publicVariable anything to JIP clients, if the latest value has been PV'd previously (which is the case with your code).  I don't remember if I every tried using this when I was creating my JIP code.  I probably just did it manually to be certain it would work.

 

This is somewhat a case of 'trust but verify'.  publicVariableClient must be run on the server; it's essentially repeating the automatic synch'ing that PV should already have done.  Note that variables that are not always PV'd from the server at every update (i.e. a 'server-side' variable that is not guaranteed to be up to date on a client) do require this (e.g. the catch-all Zen_JIP_Args_Server).  You're using the variables as global rather than server-based, but this is an alternate style.

 

On 5/7/2017 at 0:03 AM, SHIFTY_TFD said:

Hey Zen,

 

loving the framework!

 

Quick question about the Zen_OrderVehiclePatrol, I'm noticing it isn't working for APC's and MRAP's they seem to get their waypoints but don't move to them.

Any idea on how to work around that?

 

Cheers.

 

I cannot reproduce this; can you post the exact arguments you gave the function?  It might be an issue with how the function is interpreting the patrol area (e.g. giving the vehicle a destination it cannot reach).  Also, there are issues with AI simply not obeying a move order, but I've never been able find a cause for it.  You could also try adding more vehicles, if none of them move, it's not just random AI confusion.  The type, side, etc. of the vehicle should have no effect on the result (you can even mix vehicles of different sides).

Share this post


Link to post
Share on other sites

here is the snipit of code,

_vPatrols = 5;
_myMarker = ["PMk_1", "PMk_2", "PMk_3", "PMk_4", "PMk_5"]; // placed markers on map
_array = ["O_APC_Wheeled_02_rcws_F", "I_APC_Wheeled_03_cannon_F", "rhs_btr60_msv", "rhs_btr70_msv", "rhs_btr80_msv", "rhs_btr80a_msv", "rhsgref_BRDM2_msv", "rhsgref_BRDM2_ATGM_msv", "rhsgref_BRDM2UM_msv", "rhsgref_BRDM2_HQ_msv"];
_VicCrew = [INF_Crew_Pool]; //defined pool of 3 crew members
_ObjMk = "PatrolZone"; //placed marker on map

_VehicleArray = [];

for "_i" from 1 to _vPatrols do {
	_pos = (_myMarker + str _i);
	_pos1 = getMarkerPos _pos;
	_dir = markerDir _pos;

	_randUnit = _array call BIS_fnc_selectRandom;
	_Vehicle = _randUnit createVehicle _pos1;
	_Vehicle setDir _dir;
	_Vehicle setVehicleLock "LOCKEDPLAYER";

	_vehCrew = [_pos1, _VicCrew] call Zen_SpawnGroup;
	0 = [_vehCrew, _Vehicle, "All"] call Zen_MoveInVehicle;

	_VehicleArray pushBack _Vehicle;
	sleep 4;
};
sleep 2;
{
	
	0 = [_x, (_ObjMk),[],[0,360],"normal","aware",false] spawn Zen_OrderVehiclePatrol;
	
} forEach _VehicleArray;

I included all the vehicles I tested, note, for the RHS ones I tested the other variants as well as the ones included.

 

In some cases I found that the vehicle would move about 5-10m then stop, or, would turn off the road and stop. When in spectator I saw the vehicles were getting their waypoints but they would be checked as complete almost immediately and the next given and check off and so on.

 

When testing tracked vehicles they work as intended, when testing cars, they also move as intended. It only seems to be the APC and MRAP classes, which is weird!

Share this post


Link to post
Share on other sites

There's nothing wrong with your code or the arguments to Zen_OrderVehiclePatrol.

 

After testing a lot of different possibilities, the fix for this is a simple 'doMove' command added to the existing 'move' and 'addWaypoint' commands in Zen_OrderVehiclePatrol.  Testing a large sample (30 vehicles) without 'doMove' gives about a 60% compliance rate; adding doMove makes it 100%.

 

I cannot explain why 'doMove' works when 'move' does not; repeating the 'move' command does not always work.  Various other factors (vehicle type, side, the method for spawning the crew, checking if the vehicle has complete a move order) have no effect on this as far as I can tell.

 

This fix will be duplicated to various other Orders functions for the next framework release (which should be in about a week, as I'm finishing up some new things).  If you want to modify Zen_OrderVehiclePatrol yourself, just add  (driver _veh) doMove _mpos;  as lines 60 and 93 after the 'move' line.

Share this post


Link to post
Share on other sites

Update and Release #50


Introduction

 

Greetings fellow scripters and Armaholics, in this latest installment, I will continue to discuss the development of the framework and, of course, shamelessly advertise the framework in any way possible.

 

If this sounds boring, you can download the latest version from the original post. As always, the links to Google Drive for the .7z and .zip versions are already up to date. For those looking for older versions, go to file>revisions. The new version will be on Armaholic soon. Please bring any technical issues or mistakes to my attention, so e.g. people don't download the wrong version etc.

 

Changelog

 

This release introduces a major addition to the framework, a system for managing actions.  It currently uses ArmA's traditional action menu, since it is simple and doesn't seem to going anywhere.  There are several benefits of this system; you no longer have to write your own functions for adding and removing actions, all MP synch'ing is done for you, and adding actions to JIP client is much easier.

 

All framework functions and documentation have been updated to take advantage of this new system.  This now allows you to interact with actions added by framework functions; you can add and remove them manually during the mission.  All framework actions now have a global variable stated in their the function's documentation.  The JIP demonstration and all sample missions that implement JIP have been updated.  The updating of actions and the usage of many framework action functions has changed.

 

Also of note is another new function, Zen_ArrayTranspose.  This function makes a two dimensional transpose of an array, which means it leaves nested, nested arrays and lower intact.  It is mainly intended for transforming data structures to separate a list of properties from their assigned identifiers.  ZEN_FMW_Code_GetRemoteVarArray and ZEN_FMW_Code_GetRemoteVarArrayT have been added to make remote access to such data structures easier.

 

In order to provide the greatest possible performance increase to the dialog system, Zen_RefreshDialog now allows the user to optimize the refresh process for their specific dialog/refresh.  You can now specify which controls to force refresh (without checking for changes, i.e. you know there were changes), which to ignore (i.e. you know there were no changes), and which to check and update normally (the remainder from those two arguments).  This allows you create separate, efficient refreshes for different parts of your dialog, massively speeds up refreshing of large text blocks (e.g. cycling pages of text), and improves the users' experience.


5/24/17

Spoiler
  1. New Function: Zen_ArrayTranspose
  2. New Function: Zen_CreateAction
  3. New Function: Zen_DeleteAction
  4. New Function: Zen_GetActionDataGlobal
  5. New Function: Zen_GetObjectActions
  6. New Function: Zen_InvokeAction
  7. New Function: Zen_RemoveAction
  8. New Function: Zen_UpdateAction
  9. Fixed: Zen_OrderAircraftPatrol, Zen_OrderBoatPatrol, Zen_OrderHelicopterLand, Zen_OrderInfantryPatrol, Zen_OrderVehicleMove, and Zen_OrderVehiclePatrol failed to make the AI move in some cases
  10. Fixed: Zen_ArrayRemoveIndex did not exit on error
  11. Fixed: Zen_MoveInVehicle did not follow its fourth argument when the third argument was 'All'
  12. Fixed: Zen_UnlinkControl did not synch the change in MP
  13. Added: Framework macros ZEN_FMW_Code_GetRemoteVarArray, ZEN_FMW_Code_GetRemoteVarArrayT
  14. Added: Zen_RefreshDialog arguments for force and ignore refresh for controls
  15. Improved: Zen_RefreshDialog checks its arguments better
  16. Documentation: Added for Zen_ArrayTranspose, Zen_CreateAction, Zen_DeleteAction, Zen_GetActionDataGlobal, Zen_GetObjectActions, Zen_InvokeAction, Zen_RemoveAction, Zen_UpdateAction, ZEN_FMW_Code_GetRemoteVarArray, and ZEN_FMW_Code_GetRemoteVarArrayT
  17. Documentation: Updated for Zen_AddEject, Zen_AddFastRope, Zen_AddFireSupportAction, Zen_AddGiveMagazine, Zen_AddLoadoutDialog, Zen_AddRepackMagazines, Zen_AddSupportActionCustom, ZEN_FMW_Code_GetRemoteVar, Zen_RefreshDialog
  18. Documentation: Updated demonstrations and sample missions with action system
  19. Documentation: Updated Notepad++ SQF language and autocompletion file with ArmA 1.70 stable commands

 

 

  • Like 2

Share this post


Link to post
Share on other sites

Hey Zen,

 

I'm still trying to get jip syncing working with tasks.  I assign tasks with a global variable such as:

 

_task1text = "Go here, break stuff";
_task1title = "Break all the things";
Task1 = [playerList,_task1text,_task1title,"Mk_Task_1",true,'','meet'] call Zen_InvokeTask;
publicVariable "Task1";

 

And when a player jips I do have a working script that fires and does:

 

publicVariable "Task1";
sleep 6;
0 = [Task1,player ] call Zen_ReassignTask;

 

But the get this error:

 

 

"-- Zen_GetTaskDataGlobal Error --"
21:45:20 "Given task does not exist."
21:45:20 106.039
21:45:20 ["Zen_task_global_NR1$Nzlf#|"]
21:45:20 ["Zen_GetTaskDataGlobal",["Zen_task_global_NR1$Nzlf#|"],106.039]
21:45:20 ["Zen_ReassignTask",["Zen_task_global_NR1$Nzlf#|",B Alpha 1-1:1 (AccuracyThruVolume)],106.039]
21:45:20 "-- Zen_ReassignTask Error --"
21:45:20 "Given task does not exist"
21:45:20 106.039
21:45:20 ["Zen_task_global_NR1$Nzlf#|",B Alpha 1-1:1 (AccuracyThruVolume)]
21:45:20 ["Zen_ReassignTask",["Zen_task_global_NR1$Nzlf#|",B Alpha 1-1:1 (AccuracyThruVolume)],106.039]
 

 

Any ideas?

 

I also tried 

 

_clientID = owner player;


_clientID publicVariableClient "Task1";

 

But no joy either.

 

Share this post


Link to post
Share on other sites
10 hours ago, accuracythruvolume said:

Hey Zen,

 

I'm still trying to get jip syncing working with tasks.  I assign tasks with a global variable such as:

 

_task1text = "Go here, break stuff";
_task1title = "Break all the things";
Task1 = [playerList,_task1text,_task1title,"Mk_Task_1",true,'','meet'] call Zen_InvokeTask;
publicVariable "Task1";

 

And when a player jips I do have a working script that fires and does:

 

publicVariable "Task1";
sleep 6;
0 = [Task1,player ] call Zen_ReassignTask;

 

But the get this error:

 

 

"-- Zen_GetTaskDataGlobal Error --"
21:45:20 "Given task does not exist."
21:45:20 106.039
21:45:20 ["Zen_task_global_NR1$Nzlf#|"]
21:45:20 ["Zen_GetTaskDataGlobal",["Zen_task_global_NR1$Nzlf#|"],106.039]
21:45:20 ["Zen_ReassignTask",["Zen_task_global_NR1$Nzlf#|",B Alpha 1-1:1 (AccuracyThruVolume)],106.039]
21:45:20 "-- Zen_ReassignTask Error --"
21:45:20 "Given task does not exist"
21:45:20 106.039
21:45:20 ["Zen_task_global_NR1$Nzlf#|",B Alpha 1-1:1 (AccuracyThruVolume)]
21:45:20 ["Zen_ReassignTask",["Zen_task_global_NR1$Nzlf#|",B Alpha 1-1:1 (AccuracyThruVolume)],106.039]
 

 

Any ideas?

 

I also tried 

 

_clientID = owner player;


_clientID publicVariableClient "Task1";

 

But no joy either.

 

 

Might I suggest using the BIS task system that they reworked a while back. They made it simpler to use and added built-in JIP functionality. You can research it here : BIS Task Framework

 

I'm a huge fan of Zenophon and his framework but I personally found that his task system wasn't really designed for persistent missions where there would be cases that no player would be connected to the server and no AI would be present. I found work arounds but ultimately the native (reworked) BIS system was easier and more reliable to use in these circumstances.

 

Sorry Zenophon, this is in no way meant to disrespect your work. The truth is I use your framework in every mission I build and find it irreplaceable!!

Share this post


Link to post
Share on other sites

Isn't the task supposed to be re-assignable if placed in a global variable?

 

One would think it would still be on the server even if all the players leave...

Share this post


Link to post
Share on other sites

The framework's task system appears to fail when all objects assigned to a task are deleted (like when the players leave) because it automatically deletes tasks for which there are no units.  This is done because there is no direct command to remove the data entry itself, only units that have the task.  This is most likely the issue if you are testing the JIP code alone by joining, leaving, then joining your persistent server with team AI disabled.

 

To account for this, you need to manually create a proxy unit that will hold the task for players.  Any invisible/disabled proxy AI unit (preferably local to the server) somewhere on the map will work; you would include this unit with the players when you use Zen_InvokeTask (or you could use Zen_ReassignTask to this unit when some players still exist).  You can then use Zen_ReassignTask normally for this task on JIP players.

 

Share this post


Link to post
Share on other sites

Update and Release #51


Introduction

 

Greetings fellow scripters and Armaholics, in this latest installment, I will continue to discuss the development of the framework and, of course, shamelessly advertise the framework in any way possible.

 

If this sounds boring, you can download the latest version from the original post. As always, the links to Google Drive for the .7z and .zip versions are already up to date. For those looking for older versions, go to file>revisions. The new version will be on Armaholic soon. Please bring any technical issues or mistakes to my attention, so e.g. people don't download the wrong version etc.

 

Changelog

 

This release falls on the third anniversary of the framework's first release; thusfar, I have counted 806 total changes to the framework.  I am truly grateful for all of the comments and suggestions that allowed for so many fixes, improvements, and additions.  The vast majority of what I had planned to do is finished; I will continue to maintain the framework with bugfixes and small improvements.

 

Added in this release is Zen_ArrayRemoveType, which is basically the remove version of Zen_ArrayGetType.  This might be a useful shortcut instead of writing a code condition for Zen_ArrayFilterCondition; it also searches recursively and should be slightly faster.

 

Now that BIS have allowed ctrlCreate to use control classes defined in the mission's .ext file, the dialog system can take advantage of that to be on truly equal footing with tradition dialog creation.  Zen_InvokeDialog will look for the type of defined control and apply properties appropriately (e.g. types 1, 11, 16, and 41 are considered buttons).

 

The template subsystem is now tied into the action system, with Zen_CreateTemplate and Zen_SpawnTemplate being able to copy-paste existing actions onto the new objects.  This greatly reduces the hassle of manually applying your actions to the correct spawned object.

 

7/10/17

  1. New Function: Zen_ArrayRemoveType
  2. Fixed: Zen_ExtendVector did not use relative height if its second argument was a vector
  3. Fixed: Zen_RefreshDialog did not remove controls properly in some cases
  4. Improved: Zen_CreateControl now allows mission defined control classes as the first argument
  5. Improved: Zen_CreateTemplate and Zen_SpawnTemplate now copy actions added using the framework's action system
  6. Documentation: Added for Zen_ArrayRemoveType
  7. Documentation: Updated Notepad++ SQF language and autocompletion file with ArmA 1.72 stable commands
  • Like 4

Share this post


Link to post
Share on other sites

Hey Zenophon

 

Thanks for the awesome framework!

 

I was wondering is it possible to use Zen_AddSupportActionCustom to call in a strike with a Jet to where i click on the map. 

Share this post


Link to post
Share on other sites

You'll have to write a function that creates the jet, makes it fly over, etc. and then given the name of your custom function as the second argument to Zen_AddSupportActionCustom.  The documentation for Zen_AddSupportActionCustom lists the arguments that will be passed to your function.  Note that you could even call a regular fire support (from Zen_CreateFireSupport) manually in your custom function to do the actual explosion (and the jet would just be for visual effect).

 

Share this post


Link to post
Share on other sites

Hi Zenophon,

 

congratz to your third anniversary of the framework. Because of some minor changes to the code, to make it more compatible with RHS, I am still on release version from 5/24/17 (maybe that is important to my following solution).

 

I have a potential bug fix for Zen_SpawnInfantryGarrison:

 

_townMarker = "mkTown0";
private ["_building"];
_buildingPos = [];
while {count _buildingPos < 2} do {
    _pos = [_townMarker] call Zen_FindGroundPosition;
    _building = nearestBuilding _pos;
    _buildingPos = [_building, false, 20] call Zen_FindBuildingPositions;
}; 

_opforGroup = [_building, east, [[0,1],1,1,1,1,1,1,1,1,1], 1,'rhs_vehclass_infantry_flora','rhs_faction_msv', [], 'RHS_AFRF'] call Zen_SpawnInfantryGarrison;

The problem was related to argument 3 (set AI skill). Set this to "infantry" was working, set it to 1 was good too, even working with an array like [1,1,1,1,1,1,1,1,1,1] was just fine. But trying to work with nested arrays broke up the function call with the following error in the RPT:

22:20:11 "-- Zen_CheckArguments Error --"
22:20:11 "Argument 3 contains a wrong type"
22:20:11 169.594
22:20:11 [229cacec800# 79355: i_stone_housesmall_v3_f.p3d,EAST,[[0,1],1,1,1,1,1,1,1,1,1],1,"rhs_vehclass_infantry_flora","rhs_faction_msv",[],"RHS_AFRF"]
22:20:11 ["Zen_CheckArguments",[229cacec800# 79355: i_stone_housesmall_v3_f.p3d,EAST,[[0,1],1,1,1,1,1,1,1,1,1],1,"rhs_vehclass_infantry_flora","rhs_faction_msv",[],"RHS_AFRF"],169.594]
22:20:11 ["Zen_SpawnInfantryGarrison",[229cacec800# 79355: i_stone_housesmall_v3_f.p3d,EAST,[[0,1],1,1,1,1,1,1,1,1,1],1,"rhs_vehclass_infantry_flora","rhs_faction_msv",[],"RHS_AFRF"],169.594]

Zen_SpawnInfantry was able to handle the nested arrays just fine.

So I compared both functions and their Zen_CheckArguments line. They were different in argument 3 for nested arrays. So I just copied the line from Zen_SpawnInfantry to Zen_SpawnInfantryGarrison and all is fine now.

 

I am not that sure what I have done. But I just wanted to add something to your awesome project, so I let you know :D

Share this post


Link to post
Share on other sites

According to the changelog, the release on 11/20/16 included this fix to Zen_SpawnInfantryGarrison; I've checked the current release and it definitely has it (there have occasionally been code and changelog discrepancies).  Thank you for the detailed bug report so I could verify that.

Share this post


Link to post
Share on other sites

Hi Zen, firstly thanks for your work. For me it really has been a game changer in my Arma dynamic mission creating. It also got me to begin to learn to read scripts and understand them. I have been able to have the flexibility to create units/factions with a healthy randomisation simply and quickly. The ability to have missions in single player missions is also a life saver for my Dynamic missions. I have traditionally used Ravage Random AI to generate random bandit groups around the player, however I have found that this generates at the minimum settings more Bandits groups/Solo Renegades than I require, creating a civil war atmosphere rather than a Post apocalyptic survival atmosphere. Because of this I am exploring using Zen to Spawn bandits/Hostiles. From what I can see in the script I can see that I can control the number of units/groups and numbers in the groups (as we do with the mission/tasks patrol spawns). So I am wondering if Zen can spawn groups/individuals around the player, with the same control parameters, AKA, equipped via the Zen_GiveLoadoutOpfor array and then having control over how many groups and numbers in the groups spawn. Also a clean up function is obviously required for dead/destroyed units. I am still using Zenophon's Framework 1-26-17.

     I have messed with this but cannot seem to get it to work. I know this can be done as it is in one of the tutorial missions but I cannot find the correct part of the script to use. I would really appreciate if you could help me out with a script to do this. As ever, awesome work and any help is appreciated!

Share this post


Link to post
Share on other sites

Hi Zenophon,

 

again me, but this time... I haven't a solution. Right now, I am trying to build up a transportation (insertion/extraction) system, where the player can interact with a helicopter via the ACE Interaction Menu. So far so good, everything works fine until someone is trying to execute a second command before the first one has finished. The execution becomes very very weird. For example:

[[Maeh_transSys_insertionHeli, [Maeh_transSys_LZMarker, "TransportSystem_Spawn"], playableUnits, "normal", 50, "land", false] call Zen_OrderInsertion;

The "Maeh_transSys_insertionHeli" got the order above and is already under the way to the LZ. But the player wants to abort this task for a reason and tries to overwrite it with the following to return to base:

[[Maeh_transSys_insertionHeli, "TransportSystem_Spawn", "normal", 50, false, false] call Zen_OrderHelicopterLand;

The InsertionHeli turns around immediately as intended and flies towards the Base LZ, but at the moment he reaches the LZ, the helicopter is doing something like a moonwalk in the air. The nose is pointing a bit down as if the pilot is willing to fly forward towards the base LZ, but the helicopter is actually flying backward towards the LZ provided by the first order/command. He will do so until he reaches this LZ, perform a landing and hover over this LZ until a new order is given.

Do you have any suggestions for me, how I can cancel a previous given ZEN order correctly?

Share this post


Link to post
Share on other sites
On 9/4/2017 at 9:07 AM, Husker-71 said:

Hi Zen, firstly thanks for your work. For me it really has been a game changer in my Arma dynamic mission creating. It also got me to begin to learn to read scripts and understand them. I have been able to have the flexibility to create units/factions with a healthy randomisation simply and quickly. The ability to have missions in single player missions is also a life saver for my Dynamic missions. I have traditionally used Ravage Random AI to generate random bandit groups around the player, however I have found that this generates at the minimum settings more Bandits groups/Solo Renegades than I require, creating a civil war atmosphere rather than a Post apocalyptic survival atmosphere. Because of this I am exploring using Zen to Spawn bandits/Hostiles. From what I can see in the script I can see that I can control the number of units/groups and numbers in the groups (as we do with the mission/tasks patrol spawns). So I am wondering if Zen can spawn groups/individuals around the player, with the same control parameters, AKA, equipped via the Zen_GiveLoadoutOpfor array and then having control over how many groups and numbers in the groups spawn. Also a clean up function is obviously required for dead/destroyed units. I am still using Zenophon's Framework 1-26-17.

     I have messed with this but cannot seem to get it to work. I know this can be done as it is in one of the tutorial missions but I cannot find the correct part of the script to use. I would really appreciate if you could help me out with a script to do this. As ever, awesome work and any help is appreciated!

 

As another reference, look at the init of my Evade and Survive mission; the mission is spawning enemies infinitely around the player with a cap on concurrent enemies.  For any long-term, ambient spawning, you would take the usual spawning code and put into a loop with some timer/limit to space out the spawns.  You can change the random position's parameters to suit your mission (e.g. within markers, around an object, etc.); giving an object as the parameter will use the position of that object at the time the code runs.
 

Spoiler

 

 


while {true} do {
    _pos = [_player, [400, 800]] call Zen_FindGroundPosition;
    _group = [_pos, ...] call Zen_SpawnInfantry;
    0 = [_group, ...] call Zen_GiveLoadout;

    sleep 120;
};


 

 

For patrolling those groups, I suggest either terminating and recreating the patrol thread for patrols in the same area (see Multi thread management demonstration), or using a single threaded patrol manager (you can try my multi patrol function in the release #48 post as a starting point).

 

Also, see the FAQ for an explanation of Zen_SpawnInfantry's unit selection arguments.  You might also be interested in the custom loadout system; there is a demonstration for it.  For the cleanup of dead bodies, you could put an EH on each unit and delete them with a timer, or you could make cleanup 'sweeps' on an interval, e.g.
 

Spoiler



while {true} do {
    sleep 120;

    {
        if (([_x, (units _group) call Zen_FindCenterPosition] call Zen_Find2dDistance) > 400) then {
            deleteVehicle _x;
        };
    } forEach allDead;
};


 

 

On 9/4/2017 at 10:28 AM, dasmaeh said:

Hi Zenophon,

 

again me, but this time... I haven't a solution. Right now, I am trying to build up a transportation (insertion/extraction) system, where the player can interact with a helicopter via the ACE Interaction Menu. So far so good, everything works fine until someone is trying to execute a second command before the first one has finished. The execution becomes very very weird. For example:


[[Maeh_transSys_insertionHeli, [Maeh_transSys_LZMarker, "TransportSystem_Spawn"], playableUnits, "normal", 50, "land", false] call Zen_OrderInsertion;

The "Maeh_transSys_insertionHeli" got the order above and is already under the way to the LZ. But the player wants to abort this task for a reason and tries to overwrite it with the following to return to base:


[[Maeh_transSys_insertionHeli, "TransportSystem_Spawn", "normal", 50, false, false] call Zen_OrderHelicopterLand;

The InsertionHeli turns around immediately as intended and flies towards the Base LZ, but at the moment he reaches the LZ, the helicopter is doing something like a moonwalk in the air. The nose is pointing a bit down as if the pilot is willing to fly forward towards the base LZ, but the helicopter is actually flying backward towards the LZ provided by the first order/command. He will do so until he reaches this LZ, perform a landing and hover over this LZ until a new order is given.

Do you have any suggestions for me, how I can cancel a previous given ZEN order correctly?

 

Many orders functions, like Zen_OrderInsertion and Zen_OrderHelicopterLand recommend that you use 'spawn' to invoke them.  This is because they have a long execution time (typically dependent on how long the AI takes to complete the action) that will interrupt the current thread.

 

This means that calling or spawning more than one of them will cause overlapping orders and conflicting decisions for the AI.  For a detailed look see the multi thread mangement demonstration and the 'Multi-Threading and Spawn vs. Call' section of the SQF overview.  In short, you need to use 'spawn' for the order, save the thread handle (the return value of 'spawn'), and then use 'terminate' to stop that thread from running before issuing new orders.  This is true for both procedural (common top-down execution) and event-driven (i.e. the actions you're using) styles, e.g.

 

// the player uses the insertion action/command
h_heliOrders = [[Maeh_transSys_insertionHeli, [Maeh_transSys_LZMarker, "TransportSystem_Spawn"], playableUnits, "normal", 50, "land", false] spawn Zen_OrderInsertion;

 

and in another script/thread/EH/action

 

//... the player selects another command
// note that checking for scriptDone is not strictly necessary, but allows you flexibility to e.g. let the previous script finish etc.
if !(scriptDone h_heliOrders) then {
    terminate h_heliOrders;
};

// now we have no previous conflicting orders, and the thread variable/pointer is updated
h_heliOrders = [[Maeh_transSys_insertionHeli, "TransportSystem_Spawn", "normal", 50, false, false] spawn Zen_OrderHelicopterLand;

Depending on your system's structure, h_heliOrders can be global, local, assigned to an object, put into a larger data structure etc.  Note that putting 'h_' first is just my personal style to denote a script handle and help me keep track of them in the code.

 

To repeat the documentation I referenced, threads are global on each machine and cannot be transfered or defined remotely.  Finally, the use of spawn to get a thread is distinct from using spawn to get scheduled execution, but if you are using EH's the spawn will also be necessary for that reason (see the FAQ for a discussion of that).

 

  • Like 2

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

×