Jump to content
Zenophon

Zenophon's ArmA 3 Co-op Mission Making Framework

Recommended Posts

Hmm. Yes, the config entry errors have no value, just that there was an error. I do note though that when the player joins the server, while the server is waiting to continue past load screen, the lower left shows the player joined and also shows the config error. If you finish loading then the first thing the player sees is the config error prompt.

If I use only the "quadra" loadout then whenever player A respawns and gets the loadout, the error shows up on player B computer, and vice versa. There are no other errors in the rpt, and showscript errors and logfunction errors are enabled. Strange.

Thanks for the response!

Share this post


Link to post
Share on other sites
1. This error is non blocking, meaning that it doesn't stop anything or return some other position; you can just ignore it. Is obviously not supposed to appear when the position is on the map. It is based upon config file data. I assume you are using the Chernarus from here:

http://www.armaholic.com/page.php?id=23863

I just downloaded that to port a mission to Chernarus/Takistan. Looking at the config, the value is there and gives a resulting map size of 10100 meters. However, that is not the true size of the map (about 15360 meters), so there is a mistake somewhere. I am working on fixing this, but it is difficult when it is different for every map.

Hi Zen,

Yes, thats the one. Re removing the error, instead of coding something specific for each map, perhaps you could have a global debug setting? If global debug is set to false, then the error messages will not appear on screen? I am not sure if this is appropriate/possible/easier or not, just an idea.

Thanks again,

CMS

Share this post


Link to post
Share on other sites
Hi Zen,

Yes, thats the one. Re removing the error, instead of coding something specific for each map, perhaps you could have a global debug setting? If global debug is set to false, then the error messages will not appear on screen? I am not sure if this is appropriate/possible/easier or not, just an idea.

Thanks again,

CMS

Such a variable does exist. It is called 'Zen_Print_All_Errors', use:

Zen_Print_All_Errors = false;

Place it directly below the framework #include in the init.sqf to stop all errors printing to the screen as hint/chat. They will still log to the rpt file as always.

Share this post


Link to post
Share on other sites

Hi Zen,

Great, I will use that. The RPG fix and mag repack suggestion are working great!

If I wanted to randomize objectives between "box", "officer, "mortar", "wreck", "convoy" and "Custom", how do you do this, as the convoy and custom objectives require the extra string data (starting position or type)? Should those variables be named in a separate array and then called in?

I also have a question about Zen_SpawnVehicleCrew. I wanted the enemy crew I sapwn to use this same custom loadout as other units, but they do not get the loadout - any idea why? Code example below:

            // Spawn 2 groups per marker 
           for "_i" from 1 to 2 do { 
               _spawnPos = [_x] call Zen_FindGroundPosition; 
               _enemyGroup = [_spawnPos, ENEMY_SIDE, AI_SKILL, [4,6]] call Zen_SpawnInfantry;
               _enemyGroupG = [_spawnPos, ENEMY_SIDE, AI_SKILL, [1,2]] call Zen_SpawnInfantryGarrison;
			_spawnedVehicle = [_spawnPos, "O_G_Offroad_01_armed_F"] call Zen_SpawnVehicle;
			_enemyGroupC = [ _spawnedVehicle, ENEMY_SIDE, AI_SKILL, [2,3]] call Zen_SpawnVehicleCrew;
               0 = [_groupsArray, _enemyGroup, _enemyGroupG, _enemyGroupC] call Zen_ArrayAppend; 
           }; 

           // Equip and patrol the units in their marker 
           0 = [_groupsArray, _loadout1] call Zen_GiveLoadoutCustom; 
           0 = [_groupsArray, _x] spawn Zen_OrderInfantryPatrol; 

This is really twisting my melon - i have been trying to debug but no luck - adding the vehicle crew seems to stop the first to sets (_enemygroup and _enemygroupG) from spawning. I can add the vehicle with no issues. When i add the crew, all units either do not spawn, or stop receiving the custom loadout. What I am trying to achieve is spawn a patrolling vehicle in each town, in addition to the patrolling and garrisoned infantry.

Edited by CallMeSarge
MULTIPLE EDITS COS I DRANK LOADS OF COFFEE AND FIGURED A FEW THINGS OUT AS I WENT ALONG

Share this post


Link to post
Share on other sites
Hi Zen,

Great, I will use that. The RPG fix and mag repack suggestion are working great!

If I wanted to randomize objectives between "box", "officer, "mortar", "wreck", "convoy" and "Custom", how do you do this, as the convoy and custom objectives require the extra string data (starting position or type)? Should those variables be named in a separate array and then called in?

I also have a question about Zen_SpawnVehicleCrew. I wanted the enemy crew I sapwn to use this same custom loadout as other units, but they do not get the loadout - any idea why? Code example below:

            // Spawn 2 groups per marker 
           for "_i" from 1 to 2 do { 
               _spawnPos = [_x] call Zen_FindGroundPosition; 
               _enemyGroup = [_spawnPos, ENEMY_SIDE, AI_SKILL, [4,6]] call Zen_SpawnInfantry;
               _enemyGroupG = [_spawnPos, ENEMY_SIDE, AI_SKILL, [1,2]] call Zen_SpawnInfantryGarrison;
			_spawnedVehicle = [_spawnPos, "O_G_Offroad_01_armed_F"] call Zen_SpawnVehicle;
			_enemyGroupC = [ _spawnedVehicle, ENEMY_SIDE, AI_SKILL, [2,3]] call Zen_SpawnVehicleCrew;
               0 = [_groupsArray, _enemyGroup, _enemyGroupG, _enemyGroupC] call Zen_ArrayAppend; 
           }; 

           // Equip and patrol the units in their marker 
           0 = [_groupsArray, _loadout1] call Zen_GiveLoadoutCustom; 
           0 = [_groupsArray, _x] spawn Zen_OrderInfantryPatrol; 

This is really twisting my melon - i have been trying to debug but no luck - adding the vehicle crew seems to stop the first to sets (_enemygroup and _enemygroupG) from spawning. I can add the vehicle with no issues. When i add the crew, all units either do not spawn, or stop receiving the custom loadout. What I am trying to achieve is spawn a patrolling vehicle in each town, in addition to the patrolling and garrisoned infantry.

For randomizing extra objective arguments, there are different ways you could organize the data. Here is one:

_objectiveTypes = ["box", "officer", "wreck", "mortar", "convoy", "custom"];
_randomObjectiveType = [_objectiveTypes] call Zen_ArrayGetRandom;
_extraArgs = [];

switch (_randomObjectiveType) do {
   case "convoy": {
       _extraArgs = ["mkConvoy", "normal"];
   };
   case "custom": {
       _extraArgs = [["B_Soldier_F", "B_Soldier_GL_F", "B_Helipilot_F"]];
   };
};

// Define _objPos and _units somewhere
0 = ([_objPos, _units, west, _randomObjectiveType, "eliminate"] + _extraArgs) call Zen_CreateObjective;

For some reason, Zen_SpawnVehicleCrew does not return anything. I think I just assumed that using the 'crew' command would work fine. However, there's no harm in returning the group of the crew, and it certainly fits in with the other spawning functions better. Until the next release though, this will work:

0 = [_spawnedVehicle, ENEMY_SIDE] call Zen_SpawnVehicleCrew;
0 = [_groupsArray, _enemyGroup, _enemyGroupG, (crew _spawnedVehicle)] call Zen_ArrayAppend;

Also, Zen_SpawnVehicleCrew does not have parameters for AI skill or number. It fills the vehicle to however many position it requires (driver, gunners, etc.) and sets their skill to the 'crew' preset. You can still just change the skill with Zen_SetAISkill later.

Share this post


Link to post
Share on other sites

case "custom": {

_extraArgs = [["B_Soldier_F", "B_Soldier_GL_F", "B_Helipilot_F"]];

};

};

// Define _objPos and _units somewhere

0 = ([_objPos, _units, west, _randomObjectiveType, "eliminate"] + _extraArgs) call Zen_CreateObjective;[/php]

Hi Zen,

I am gonna test this tonight, just reading and re-reading before I do. The extra arguments for the convoy make sense, but if I make the custom objective a vehicle, say a tank or a chopper, don't I need a separate line to spawn the vehicle crew? Is that a separate argument like:

    case "custom": { 
       _extraArgs = [["O_MBT_02_cannon_F", "O_Heli_Attack_02_black_F"], ["O_Soldier_F", "O_Soldier_GL_F", "O_Helipilot_F"]]; 
   }; 

Share this post


Link to post
Share on other sites
Hi Zen,

I am gonna test this tonight, just reading and re-reading before I do. The extra arguments for the convoy make sense, but if I make the custom objective a vehicle, say a tank or a chopper, don't I need a separate line to spawn the vehicle crew? Is that a separate argument like:

    case "custom": { 
       _extraArgs = [["O_MBT_02_cannon_F", "O_Heli_Attack_02_black_F"], ["O_Soldier_F", "O_Soldier_GL_F", "O_Helipilot_F"]]; 
   }; 

Unfortunately, Zen_CreateObjective is not that smart; it cannot determine which units should be crew and which should not be in the vehicle. Instead you can spawn the crew yourself:

// ...
_extraArgs = [["O_MBT_02_cannon_F", "O_Heli_Attack_02_black_F"]];
// ...

// Define _objPos and _units somewhere
_objectiveData = ([_objPos, _units, east, _randomObjectiveType, "eliminate"] + _extraArgs) call Zen_CreateObjective;

if (_randomObjectiveType == "custom") then {
   {
       0 = [_x] call Zen_SpawnVehicleCrew;
   } forEach (_objectiveData select 0);
};

This will work regardless of how many vehicles there are, as all the spawned vehicles are returned by Zen_CreateObjective.

Share this post


Link to post
Share on other sites

Eeeer...what is this framework? xD Is it like an easier way to make missions? Like the MCC mod????

Share this post


Link to post
Share on other sites

Hi SparkZ. Have a look at the first page, but in short Zen has made a framework/api for scripting that is EXCEPTIONALLY well documented. I have never scripted before in my life (in any way), but the basics of the framework are easy to pick up. I would reccomend going through the tutorials and seeing if you like it. Zen is very active in this thread offering advice and guidance. Speaking of which...

Unfortunately, Zen_CreateObjective is not that smart; it cannot determine which units should be crew and which should not be in the vehicle. Instead you can spawn the crew yourself:

// ...
_extraArgs = [["O_MBT_02_cannon_F", "O_Heli_Attack_02_black_F"]];
// ...

// Define _objPos and _units somewhere
_objectiveData = ([_objPos, _units, east, _randomObjectiveType, "eliminate"] + _extraArgs) call Zen_CreateObjective;

if (_randomObjectiveType == "custom") then {
   {
       0 = [_x] call Zen_SpawnVehicleCrew;
   } forEach (_objectiveData select 0);
};

This will work regardless of how many vehicles there are, as all the spawned vehicles are returned by Zen_CreateObjective.

As usual Zen, everything works like a dream - and as usual, I have one more question! I started by putting the objective vehicles in an array, as I was unintentionally spawning one of each. I decided I wanted to make the objective vehicles move around a bit (the helicopter spawns parked for example). Using the example from the MultiSquadObjectives.altis tutorial, I am trying to make them patrol their spawn markers - it is not working though. Can you offer any advice as to why? Thanks again for your input, I knot this is painstakingly slow but I am learning a ton!

    // Check if the clock is past when the side objective is scheduled 
   if (time > _sideObjTime) then { 
_markerArray = ["SM1","SM2","SM3","SM4","SM5","SM6","SM7","SM8"]; 
_selectedmarker = [_markerArray] call Zen_ArrayGetRandom; 

// Random objectives array
_objectiveTypes = ["custom"]; 
_randomObjectiveType = [_objectiveTypes] call Zen_ArrayGetRandom; 
_objectiveVeh = ["O_APC_Tracked_02_cannon_F","O_Heli_Attack_02_black_F"]; 
_randomObjectiveVeh = [_objectiveVeh] call Zen_ArrayGetRandom; 
_extraArgs = []; 

switch (_randomObjectiveType) do { 
	case "convoy": { 
		_extraArgs = ["mkConvoy", "normal"]; 
	}; 
	case "custom": { 
		_extraArgs = [_randomObjectiveVeh]; 
	}; 
}; 

// create an objective for the selected marker 
_objPos = [_selectedmarker] call Zen_FindGroundPosition; 

       // Create the objective and reset the timer 
       _Objective1 = ([_objPos, _players, ENEMY_SIDE, _randomObjectiveType, "eliminate"] + _extraArgs) call Zen_CreateObjective;  
	if (_randomObjectiveType == "custom") then { 
   { 
       0 = [_x] call Zen_SpawnVehicleCrew; 
   } forEach (_Objective1 select 0); 
};  
	if (_randomObjectiveType isKindOf "Air") 
	then {[_randomObjectiveType, _objPos] spawn Zen_OrderAircraftPatrol;}
	else {[_randomObjectiveType, _objPos] spawn Zen_OrderVehiclePatrol;};



   _sideObjTime = time + (60*([0.1, 0.2] call Zen_FindInRange)); 

       // Spawn and patrol a few guards 
       _objGuards = [_objPos, ENEMY_SIDE, AI_SKILL, [3,4]] call Zen_SpawnInfantry; 
       0 = [_objGuards, _loadout1] call Zen_GiveLoadoutCustom; 
       0 = [_objGuards, _objPos, [10, 75]] spawn Zen_OrderInfantryPatrol; 
	waituntil { sleep 5; [[(_Objective1 select 1)]] call Zen_AreTasksComplete }; 
   };

Share this post


Link to post
Share on other sites
Hi SparkZ. Have a look at the first page, but in short Zen has made a framework/api for scripting that is EXCEPTIONALLY well documented. I have never scripted before in my life (in any way), but the basics of the framework are easy to pick up. I would reccomend going through the tutorials and seeing if you like it. Zen is very active in this thread offering advice and guidance. Speaking of which...

As usual Zen, everything works like a dream - and as usual, I have one more question! I started by putting the objective vehicles in an array, as I was unintentionally spawning one of each. I decided I wanted to make the objective vehicles move around a bit (the helicopter spawns parked for example). Using the example from the MultiSquadObjectives.altis tutorial, I am trying to make them patrol their spawn markers - it is not working though. Can you offer any advice as to why? Thanks again for your input, I knot this is painstakingly slow but I am learning a ton!

    // Check if the clock is past when the side objective is scheduled 
   if (time > _sideObjTime) then { 
_markerArray = ["SM1","SM2","SM3","SM4","SM5","SM6","SM7","SM8"]; 
_selectedmarker = [_markerArray] call Zen_ArrayGetRandom; 

// Random objectives array
_objectiveTypes = ["custom"]; 
_randomObjectiveType = [_objectiveTypes] call Zen_ArrayGetRandom; 
_objectiveVeh = ["O_APC_Tracked_02_cannon_F","O_Heli_Attack_02_black_F"]; 
_randomObjectiveVeh = [_objectiveVeh] call Zen_ArrayGetRandom; 
_extraArgs = []; 

switch (_randomObjectiveType) do { 
	case "convoy": { 
		_extraArgs = ["mkConvoy", "normal"]; 
	}; 
	case "custom": { 
		_extraArgs = [_randomObjectiveVeh]; 
	}; 
}; 

// create an objective for the selected marker 
_objPos = [_selectedmarker] call Zen_FindGroundPosition; 

       // Create the objective and reset the timer 
       _Objective1 = ([_objPos, _players, ENEMY_SIDE, _randomObjectiveType, "eliminate"] + _extraArgs) call Zen_CreateObjective;  
	if (_randomObjectiveType == "custom") then { 
   { 
       0 = [_x] call Zen_SpawnVehicleCrew; 
   } forEach (_Objective1 select 0); 
};  
	if (_randomObjectiveType isKindOf "Air") 
	then {[_randomObjectiveType, _objPos] spawn Zen_OrderAircraftPatrol;}
	else {[_randomObjectiveType, _objPos] spawn Zen_OrderVehiclePatrol;};



   _sideObjTime = time + (60*([0.1, 0.2] call Zen_FindInRange)); 

       // Spawn and patrol a few guards 
       _objGuards = [_objPos, ENEMY_SIDE, AI_SKILL, [3,4]] call Zen_SpawnInfantry; 
       0 = [_objGuards, _loadout1] call Zen_GiveLoadoutCustom; 
       0 = [_objGuards, _objPos, [10, 75]] spawn Zen_OrderInfantryPatrol; 
	waituntil { sleep 5; [[(_Objective1 select 1)]] call Zen_AreTasksComplete }; 
   };

The code to check the vehicle's type and have it patrol uses '_randomObjectiveType' (which is 'custom') instead of the vehicle that was spawned. You must get the object created:

// This is the first and only object spawned
_objectiveVehicle = (_Objective1 select 0) select 0;

if (_objectiveVehicle isKindOf "Air") then {
   0 = [_objectiveVehicle, _objPos] spawn Zen_OrderAircraftPatrol;
} else {
   0 = [_objectiveVehicle, _objPos] spawn Zen_OrderVehiclePatrol;
};

---------- Post added at 22:09 ---------- Previous post was at 21:47 ----------

Eeeer...what is this framework? xD Is it like an easier way to make missions? Like the MCC mod????

As CallMeSarge said, this is function library and SQF API with a strong focus on good documentation and learning to script missions. The functions are higher level than the built-in SQF commands, while being smaller pieces than large systems like EOS or UPSMON. For example, you can create any fire support imaginable with two lines, or randomly spawn dozens of squads patrolling in an area with about 6 lines. I am aiming for the right balance of ease of use that plain SQF lacks and adaptability that larger systems lack.

It is not like MCC in that players can get editor-like functionality during the mission. It is a toolset for scripters and mission makers to aid them in building their mission using external scripts. In my opinion, scripting with my framework is easier and better for almost every part of mission making than using the editor.

The point of using my framework for scripting is that instead of e.g. struggling to make tasks work or being frustrated about an AI helicopter insertion, you simply use the Zen function that does what you want. Although the framework is advertised as beta software, about 80-90% of it is nearly finished and working very well. It is very possible to create a mission using 100% scripting and dozens of my functions. The two missions in my signature are perfect examples of that.

When creating a mission with the framework, you focus on the important logic in your mission and coding concrete steps using functions. When you want to change or improve your mission, or you need to fix a bug, all of your mission code is easy to find and read. If you want to change the skill of all AI, find and replace a few values and it's done; that would take hundreds of tedious clicks in the editor.

  • Like 1

Share this post


Link to post
Share on other sites

Alright, thanks for the heads up. I didn't actually get the first post. But I think I'm going to take a look through the tutorials. I'm a mission maker, and the only scripts I use for my missions are revive and virtual ammo system. But I'm all new with this. Looks complicated. But as you said, changing skills of AI can take hundreds of clicks in the editor. Sometimes too much that I need a break to not get crazy from the clicking sound, ridiculous. Normally I save all the init codes I'm using in a note, so I'm sure I don't forget some of them. But more to copy paste them cause it could take so much time typing all that out.

Anyway, this framework sounds interesting, with all the possibilities. I'm still "new" with scripts so understanding ALL of this could take a while. And I'm sending this thread to a mission maker I know who's pretty good with scripts, he's called SaOk and made the Whole lotta Altis mission. The best mission I've played, but I think he can make a good use of this.

Again, thanks for the information, appreciated :)

Share this post


Link to post
Share on other sites

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 link 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 should be on Armaholic when Foxhound sees this or I PM him. Please bring any technical issues or mistakes to my attention, so e.g. people don't download the wrong version etc.

Changelog

This week sees a more impressive turnout, with 27 changes ranging from new functions, old functions remade, and minor fixes of all kinds. It seems that a framework release wouldn't be complete without a new function, so this week Zen_IsHillArea rounds out the new Position Functions category in helping you evaluate terrain. Zen_IsHillArea is especially valuable, in that is does not consider a slope to be a hill; only a true hill that comes to a top will be given a high value.

Be prepared to find and replace, because Zen_FindMaxTerrainSlope is now named Zen_FindTerrainSlope. This is done so that the function name agrees semantically with what one calls the 'slope' of the terrain, rather than the mathematical meaning of 'slope' or gradient.

In an even more drastic change, the parameters for Zen_FindNearHeight have changed entirely, only the first two were untouched. I know I spotlit that function last week, but I then realized that its search pattern arguments were unnecessarily esoteric. It now uses a faster, easier algorithm, similar to that used by Zen_IsNearTerrain. You don't have to worry about its search accuracy, just providing a radius is sufficient.

Another parameter change (an optional one this time) for Zen_SpawnFortification makes the functions significantly more useful. You can now specific the exact radius of the ring of fortifications. Beware that you may experience strange behavior with very low numbers (below 3 meters).

A lot of tweaking has been done to Zen_OrderExtraction and Zen_OrderInsertion to make helicopters land more realistically, and prevent AI stupidity such as taking off while units jump out. Helicopters should fire any weapons they can while approaching for a landing, or even on the ground.

The curse of Zen_SpawnVehicle with heights over the ocean has been lifted. It turns out that boats and flying vehicles were being placed automatically at different heights. The function now carefully checks for all possible combinations of land/water, car/boat/helicopter, and collide/don't collide to make sure every situation is correct. This function is used so extensively that fixing this will make almost every other spawning function work properly now.

Another bug concerns the functionality of Zen_TransformObject in MP, which was previously none for remote objects. Remember, no (public) framework function is meant to only work locally, or needs to be remotely executed manually. If the function runs on the server and doesn't do what the documentation claims, this is a bug and should be reported.

To cut this excessive explanation short, I will end with the only exciting documentation change. The JIP demonstration has been partly rewritten to support JIP players for both enabled and disabled AI for playable characters. It also makes an elegant use of Zen_ReassignTask from the client machine instead of the ugly brute force solution to tasks previously used.

8/20/14

  1. New Function: Zen_IsHillArea
  2. Fixed: Zen_GetUnitLoadout did not put magazines loaded into weapons in the correct format
  3. Fixed: Zen_IsUrbanArea printed some debug to the chat
  4. Fixed: Zen_OrderExtraction and Zen_OrderInsertion sometimes did not allow the units to get out normally
  5. Fixed: Zen_OrderExtraction and Zen_OrderInsertion helicopter landing forced stop no longer applies to ground vehicles
  6. Fixed: Zen_SpawnVehicle logic for placing any vehicle over the ocean at the given height ASL with and without exact placement
  7. Fixed: Zen_TransformObject now rotates a remote object properly when called on the server
  8. Added: Zen_FindNearHeight now has a parameter for getting the lowest point
  9. Added: Zen_SpawnFortification now has a parameter for fortification circle radius
  10. Improved: Zen_CreateObjective 'convoy' objective now makes troops disembark better when the convoy is under attack
  11. Improved: Zen_FindGroundPosition now detects a position off the map better
  12. Improved: Zen_FindMaxTerrainSlope renamed Zen_FindTerrainSlope
  13. Improved: Zen_FindNearHeight search pattern parameters removed
  14. Improved: Zen_FindNearHeight greatly optimized, especially for large areas
  15. Improved: Zen_InvokeFireSupport, Zen_MoveInVehicle, and Zen_OrderFastRope remote execution requests optimized
  16. Improved: Zen_InvokeFireSupport round guidance now detects lasers of vehicles and UAV's/UGV's
  17. Improved: Zen_OrderExtraction and Zen_OrderInsertion stop the helicopter from turning on the ground
  18. Improved: Zen_OrderInsertion makes the helicopter pause before taking off
  19. Improved: Zen_OrderHelicopterLand now allows door gunners to fire
  20. Improved: Zen_ReassignTask now removes duplicate units from the task system's internal data
  21. Improved: Zen_SpawnConvoy no longer spawns an unarmed vehicle as the lead vehicle
  22. Improved: Zen_SpawnVehicleCrew now returns the group of the spawned crew
  23. Documentation: Fixed the demonstrations, sample missions, or tutorials did not include StringTable.xml
  24. Documentation: Fixed Zen_SpawningDemonstration used Zen_SpawnFortification wrong
  25. Documentation: Added for Zen_IsHillArea
  26. Documentation: Improved JIP demonstration greatly, it now supports disabled AI
  27. Documentation: Updated for Zen_AddFireSupportAction, Zen_FindTerrainSlope, Zen_FindNearHeight, Zen_InvokeFireSupport, Zen_SpawnFortification, Zen_SpawnVehicleCrew

Roadmap

Although much work has been done, there is always more to do. Next week I plan on a new function: Zen_FindTerrainGradient, which is the 3d vector version of Zen_FindTerrainSlope. I am also planning on improving the algorithm of Zen_AvoidPosition in some way just as was done for Zen_FindTerrainSlope, but testing will reveal if this will work out. The function may change entirely and fill a slightly different role (if you love Zen_AvoidPosition and want it to stay PM me).

With only a few changes planned, I will probably introduce the new preprocessor library next week. I already have a lot of ideas for what will be included, but getting the documentation format set up will slow progress at first.

Function Spotlight

As users of my framework know, there is an enormous number of functions at your disposal. The amount of documentation that has to be sifted through can be extremely daunting. Each week I spotlight a function and talk about its usefulness. If you have found an obscure function (not in tutorials, barely seen in demonstrations or sample missions) that you found useful, PM me and I can spotlight it.

The function chosen for this week is: Zen_SetAISkill. This is the framework tool for controlling mission difficulty and AI balance. The first important thing to note is: you have all been using this function indirectly every time you call Zen_SpawnInfantry. The third parameter of Zen_SpawnInfantry is the skill parameter passed to Zen_SetAISkill.

For ease of use, Zen_SetAISkill offers several presets that differentiate different skill levels. These are all listed in the documentation, but the most useful ones are 'militia', 'infantry', and 'SOF'. These presets categorize the average AI soldier into three difficulty levels. The presets cover all possible AI abilities, including accuracy, recoil, teamwork, and spotting ability.

If you only enter one value (not in an array of value), that is the value for all skills. However, for those who really want control over each skill, you can also enter every value directly. The values are matched with the skills in this order: 'aimingAccuracy', 'aimingShake', 'aimingSpeed', 'commanding', 'courage', 'endurance', 'general', 'reloadSpeed', 'spotDistance', 'spotTime'.

This option has a special feature unique to this function. If you enter fewer values than there are skills, the remaining skills with use the last value entered. For example:

0 = [units X, [0.2, 0.8]] call Zen_SetAISkill;

The units in X's group now have 0.2 accuracy and 0.8 of all other skills. This is most useful when you want to set the accuracy separately from all other skills. Finally, for a more detailed explanation on how these number translate to the AI's true skill, see the AI section of FrameworkIntroduction.txt.

Beta

As already stated, the framework is in the beta stage of development. I am making every effort to quality control releases, but there will be bugs. Both new features and old ones could have bugs, issues, and things people just don't like.

There is no ETA or plan for a 'final' version. The framework is a work in progress, and it will continue to progress while there are improvements to be made (there always will be).

Feedback

As expected, some of the bugs have been pointed out by users, and those fixes are included in the changelog above. I want to thank everyone who has used/supported the framework.

  • Like 1

Share this post


Link to post
Share on other sites

Hi Zen,

Did my first play test tonight and it went great, except for one fly in the ointment. Whenever a player re-spawned (I implemented a standard re-spawn to base function), they would lose the ability to repack mags. I assume that this would also affect other things. I also assume this is because I did not implement any JIP at all. Does this sound correct? I will re-read the JIP Demonstration and have a crack at adding it in.

Share this post


Link to post
Share on other sites
Hi Zen,

Did my first play test tonight and it went great, except for one fly in the ointment. Whenever a player re-spawned (I implemented a standard re-spawn to base function), they would lose the ability to repack mags. I assume that this would also affect other things. I also assume this is because I did not implement any JIP at all. Does this sound correct? I will re-read the JIP Demonstration and have a crack at adding it in.

The repack mags uses addAction, which is local. When init.sqf initially is processed by the client, the action is added. When you die, it is left with the old "body" and a new respawned "body" needs to have such things added back. If you look in some of the demonstration/examples you will see the use of an event handler (usually killed and respawn). In this case, on the event of a respawn, you want to add the action again.

JIP would affect players who join after the mission started. However, if your init.sqf file adds the repack mags in the area that a client processes, there is no reason to add it to a JIP script.

The MP aspect of sqf and arma is not really hard to understand. But it takes time (trial and error) to understand what is going on and why. Once you make a number of scripts/missions, you troubleshoot issues like you are having, you learn a new piece (like respawn scripts), and it makes sense. Like I say, not hard just a lot to learn.

The solution to your issues is to use a MP event handler for respawn which can just call a respawn function (ie. f_handleRespawn). There are a number of examples in the documentation.

HTH.

Share this post


Link to post
Share on other sites

AH, that makes sense. This is my first foray into making a mission from scratch versus modifying stuff I have played before. Thanks for the input m0nkey, I can see the example in the Zen_RespawnPatrol.Altis mission, I'll give that a try.

Share this post


Link to post
Share on other sites

The key to it is understanding that you don't even need the "respawn_west" marker. All you need is respawning enabled in description.ext and a script/function to use with the event "respawn". You add an event handler to call your function/script and you are done.

The existence of respawn_west marker (or multiple markers) only lets the game place the new body at one of those marker locations. Thats all it does. If you want the same gear you had or same loadout, you have to use the event handler and give what you want to the new body, as the new body is the basic kit/class.

Share this post


Link to post
Share on other sites
The key to it is understanding that you don't even need the "respawn_west" marker. All you need is respawning enabled in description.ext and a script/function to use with the event "respawn". You add an event handler to call your function/script and you are done.

The existence of respawn_west marker (or multiple markers) only lets the game place the new body at one of those marker locations. Thats all it does. If you want the same gear you had or same loadout, you have to use the event handler and give what you want to the new body, as the new body is the basic kit/class.

Thanks fella,

I understand the process, but I am still doing something wrong, and I am not sure what. What is really strange is that if I open the mission in editor, it previews ok. If I export to MP, the initial script does not even run, but respawn does work. I have reviewed this a few times now and I am not sure what I have done wrong. Code sample below, and link to all mission files for reference. As usual, any advice would be warmly received.

// Town array is now a series of 50x50m grids placed in the editor
_townMkArray = ["Mkr1", "Mkr2", "Mkr3"]; 

// Schedule the first side objective 
_sideObjTime = time + (60*([10, 20] call Zen_FindInRange)); 

// Holds arrays of groups in each town 
_townPatrolsArray = []; 

// Holds all the markers where AI have been spawned 
// _townMkArray is now all markers where AI have not spawned 
_townMkArraySpawned = []; 

// Assume the only Blufor units are the players 
_players = ([west] call Zen_ConvertToObjectArray); 

// keep control over your mission by handling respawn yourself
f_HandleRespawn = {
   if (time < 5) exitWith {};
   private ["_players", "_body"];

   _players = _this select 0;
   _body = _this select 1;

   if (player == _players) then {
       titleText ["Still Alive", "BLACK FADED", 0.2];
   };

    // you must maintain tracking respawned units
   if (isServer) then {
       [] call f_ResetTracking;
   } else {
       Zen_MP_Closure_Packet = ["f_ResetTracking", []];
       publicVariableServer "Zen_MP_Closure_Packet";
   };

   0 = _body spawn {
       sleep 300;
       deleteVehicle _this;
   };
};

#include "JIPSync.sqf"
if (!isServer) exitWith {};

   // some weather management
   if ((time - _fogStart) > _fogTime) then {
       0 = [["fog", -1, random 0.05, _fogTime]] spawn Zen_SetWeather;
       Zen_JIP_Args_Server set [7, time];
   };

   if ((time - _overcastStart) > _overcastTime) then {
       0 = [["overcast", -1, random 1, _overcastTime]] spawn Zen_SetWeather;
       Zen_JIP_Args_Server set [3, time];
   };

// set up JIP and respawning
Zen_JIP_Args_Server = [time, overcast, overcastForecast, _overcastStart, _overcastTime, fog, fogForecast, _fogStart, _fogTime, 3000, _players];

{
   _x addMPEventHandler ["MPRespawn", f_HandleRespawn];
} forEach _players;



0 = [_players] call Zen_AddGiveMagazine;
0 = [_players] call Zen_AddRepackMagazines;

Mission files

Share this post


Link to post
Share on other sites

Not sure, but you might check what gets exported. I think it does nothing but export the mission.sqm file.

What I do is build non MP portions using editor, then copy/paste the mission to MPmissions (in your profile). Then I click play>new server>pick mission > edit. This way all the files are moved by me and I can then test MP parts, like the respawning.

I bet your exported mission is void of dependent files ;)

Share this post


Link to post
Share on other sites
Thanks fella,

I understand the process, but I am still doing something wrong, and I am not sure what. What is really strange is that if I open the mission in editor, it previews ok. If I export to MP, the initial script does not even run, but respawn does work. I have reviewed this a few times now and I am not sure what I have done wrong. Code sample below, and link to all mission files for reference. As usual, any advice would be warmly received.

// Town array is now a series of 50x50m grids placed in the editor
_townMkArray = ["Mkr1", "Mkr2", "Mkr3"]; 

// Schedule the first side objective 
_sideObjTime = time + (60*([10, 20] call Zen_FindInRange)); 

// Holds arrays of groups in each town 
_townPatrolsArray = []; 

// Holds all the markers where AI have been spawned 
// _townMkArray is now all markers where AI have not spawned 
_townMkArraySpawned = []; 

// Assume the only Blufor units are the players 
_players = ([west] call Zen_ConvertToObjectArray); 

// keep control over your mission by handling respawn yourself
f_HandleRespawn = {
   if (time < 5) exitWith {};
   private ["_players", "_body"];

   _players = _this select 0;
   _body = _this select 1;

   if (player == _players) then {
       titleText ["Still Alive", "BLACK FADED", 0.2];
   };

    // you must maintain tracking respawned units
   if (isServer) then {
       [] call f_ResetTracking;
   } else {
       Zen_MP_Closure_Packet = ["f_ResetTracking", []];
       publicVariableServer "Zen_MP_Closure_Packet";
   };

   0 = _body spawn {
       sleep 300;
       deleteVehicle _this;
   };
};

#include "JIPSync.sqf"
if (!isServer) exitWith {};

   // some weather management
   if ((time - _fogStart) > _fogTime) then {
       0 = [["fog", -1, random 0.05, _fogTime]] spawn Zen_SetWeather;
       Zen_JIP_Args_Server set [7, time];
   };

   if ((time - _overcastStart) > _overcastTime) then {
       0 = [["overcast", -1, random 1, _overcastTime]] spawn Zen_SetWeather;
       Zen_JIP_Args_Server set [3, time];
   };

// set up JIP and respawning
Zen_JIP_Args_Server = [time, overcast, overcastForecast, _overcastStart, _overcastTime, fog, fogForecast, _fogStart, _fogTime, 3000, _players];

{
   _x addMPEventHandler ["MPRespawn", f_HandleRespawn];
} forEach _players;



0 = [_players] call Zen_AddGiveMagazine;
0 = [_players] call Zen_AddRepackMagazines;

Mission files

Respawning is separate from JIP; JIP players run code to sync up with other clients and get the respawn eventhandler. After this they can respawn normally like other clients. There are more things that are not synch'd at JIP (e.g. weather, tasks) than at respawn (only actions, position, loadout). The respawn event only has to handle those things:

f_HandleRespawn = {
   if (time < 5) exitWith {};
   private ["_players", "_body"];

   _player = _this select 0;
   _body = _this select 1;

   if (player == _player) then {
       titleText ["Still Alive", "BLACK FADED", 0.2];
   };

   0 = [_player] call Zen_AddGiveMagazine;
   0 = [_player] call Zen_AddRepackMagazines;

   0 = _body spawn {
       sleep 300;
       deleteVehicle _this;
   };
};

Because you have a respawn marker, the engine handles moving the new player object there for you. Otherwise, you would have to code teleporting them to base yourself. If you wanted respawned players to have a different loadout than default, you could add that in as well. If an AI unit could be respawning, make sure to set their skill again.

As for the mission not exporting correctly, check the size of the .pbo; it should be just over 500KB with just the framework source code alone. If it's too small, try exporting using the MP editor, or export to SP, or try an external .pbo packing tool. I have never had this issue with the regular editor, but I have seen it reported by other mission makers. I have also seen a bug in which an export to SP does not override an existing .pbo.

Share this post


Link to post
Share on other sites

Hi Zen,

OK, that fixes the repack issue, thank you! I am afraid I am still missing something fundamental though, I did not explain the issue well last time as I needed to test more to figure out exactly what it is. The issue is that on respawn, the player is out of the main mission loop - grids to do not spawn enemies for them. The main mission loop (the one that you wrote a few pages back) starts with:

// Infinite loop that runs every ten seconds 
while {true} do { 
   { 
       // Only spawns patrols if at least one player is within 700 meters 
       if !([_players, getMarkerpos _x, [700, 700], 0, "Ellipse"] call Zen_AreNotInArea) then 

So it seems to me, when a player respawns, they are no longer in the array _players. Whith that in mind, I tried using zen_ArrayAppend in the respawn part, but that produced an invalid argument (because _player is not an array?) - and enemies would not spawn for a unit that had respawned.

// keep control over your mission by handling respawn yourself
// This code does not work - CMS
f_HandleRespawn = { 
   if (time < 5) exitWith {}; 
   private ["_players", "_body"]; 

   _player = _this select 0; 
   _body = _this select 1; 

   if (player == _player) then { 
       titleText ["Still Alive", "BLACK FADED", 0.2]; 
   }; 

   0 = [_player] call Zen_AddGiveMagazine; 
   0 = [_player] call Zen_AddRepackMagazines; 
   0 = [_players, _player] call Zen_ArrayAppend; 

   0 = _body spawn { 
       sleep 300; 
       deleteVehicle _this; 
   }; 
}; 

What should I do to ensure that respawned players are counted in the main mission loop, so that enemies spawn when they approach a marker?

Also, re the mission export not working, it was something I added myself that borked it. I added the line

if (!isServer) exitWith {};

beneath the call to JIPSynq.sqf without really understanding what it did ( I thought it had to do with having AI on the server when units respawned) - removing this line solved the export issue. Right now, I think JIP is not a priority for me, allowing respawn is. Thanks again for all the advice!

Share this post


Link to post
Share on other sites

One simple solution might be to use "group". Most of the frameworks functions can be used with different arguments. Zen_areNotInArea can use array/group/object/side/objects. So, you could use west side, you could use group x11 (or whatever you named it). If you did something like

arrayPlayers = group x11 

(where x11 is the name of the group leader) then it would always equal the group, even on respawn where new bodies technically have replaced old ones. There are many ways actually.

Your problem seems to be that the array has a reference to a unit that no longer exists? Have you tried

diag_log format ["array is:: %1",_players]

before and after to see what values are actually there?

Food for thought anyway.

Share this post


Link to post
Share on other sites
Hi Zen,

OK, that fixes the repack issue, thank you! I am afraid I am still missing something fundamental though, I did not explain the issue well last time as I needed to test more to figure out exactly what it is. The issue is that on respawn, the player is out of the main mission loop - grids to do not spawn enemies for them. The main mission loop (the one that you wrote a few pages back) starts with:

// Infinite loop that runs every ten seconds 
while {true} do { 
   { 
       // Only spawns patrols if at least one player is within 700 meters 
       if !([_players, getMarkerpos _x, [700, 700], 0, "Ellipse"] call Zen_AreNotInArea) then 

So it seems to me, when a player respawns, they are no longer in the array _players. Whith that in mind, I tried using zen_ArrayAppend in the respawn part, but that produced an invalid argument (because _player is not an array?) - and enemies would not spawn for a unit that had respawned.

// keep control over your mission by handling respawn yourself
// This code does not work - CMS
f_HandleRespawn = { 
   if (time < 5) exitWith {}; 
   private ["_players", "_body"]; 

   _player = _this select 0; 
   _body = _this select 1; 

   if (player == _player) then { 
       titleText ["Still Alive", "BLACK FADED", 0.2]; 
   }; 

   0 = [_player] call Zen_AddGiveMagazine; 
   0 = [_player] call Zen_AddRepackMagazines; 
   0 = [_players, _player] call Zen_ArrayAppend; 

   0 = _body spawn { 
       sleep 300; 
       deleteVehicle _this; 
   }; 
}; 

What should I do to ensure that respawned players are counted in the main mission loop, so that enemies spawn when they approach a marker?

Also, re the mission export not working, it was something I added myself that borked it. I added the line

if (!isServer) exitWith {};

beneath the call to JIPSynq.sqf without really understanding what it did ( I thought it had to do with having AI on the server when units respawned) - removing this line solved the export issue. Right now, I think JIP is not a priority for me, allowing respawn is. Thanks again for all the advice!

m0nkey is right, you must get the groups or units dynamically every loop iteration. Using 'group X11' will work fine X11 exists. A more complex solution is:

// Infinite loop that runs every ten seconds 
while {true} do { 
   { 
       // Redefine the players array to account for respawn/JIP
       _players = [west] call Zen_ConvertToObjectArray;
       _players = [_players, "!(isPlayer _x)"] call Zen_ArrayFilterCondition;

       // Only spawns patrols if at least one player is within 700 meters 
       if !([_players, getMarkerpos _x, [700, 700], 0, "Ellipse"] call Zen_AreNotInArea) then {
           // ...
       };
       // ...
   } // ...
};

This will account for any number of players in any number of west groups and filter out AI. The '_players' variable is local to the init, and is undefined in eventhandlers as they are a different scope (the respawn eventhandler is even running on a client machine).

Share this post


Link to post
Share on other sites

This framework is great. I was sort of stuck using a mix of Broma and the F3 frameworks before, but they never include enough documentation to explain how or why things happen. The only thing is, obviously this is a Coop framework, so I need to either find part of it useful for TvTs (I found one of your example missions included a method of randomising the day and weather, perfect!). I guess the only thing this doesn't cover is Paramaterson the lobby screen and a Spec script, but I have already confirmed the Modified Kegety's Spectator works well with this.

All I really need now is a way to block third person and I can finally make missions without worrying about things breaking. I already use my own predefined loadouts, and weather isn't a real issue because I usually have an idea of a specific time or weather setting when I make a mission.

I get these issues aren't really things you set out to cover with this Zen, my issues above are just aspects of mission making I'm used to , I'm just whining about my own problems. You've got something here that is just absolutely wonderful. Everytime I see clean, well laid out and commented code on anything it makes me happy.

Share this post


Link to post
Share on other sites
Guest

Thanks for informing us about the updated release :cool:

Release frontpaged on the Armaholic homepage.

================================================

We have also "connected" these pages to your account on Armaholic.

This means in the future you will be able to maintain these pages yourself if you wish to do so. Once this new feature is ready we will contact you about it and explain how things work and what options you have.

When you have any questions already feel free to PM or email me!

Share this post


Link to post
Share on other sites

Hey Zen

ive been going though your framework for the best part off a week learning how to do things

for the best part i have managed to get infantry and vehicles to spawn and patrol in a large area

to achieve this i have used the spawning code from your random battle demonstration

now my first problem seems to be getting the AI to spawn at Oreokastro and patrol in the town

for this i am using

for "_i" from 1 to 2 do {

_spawnPos = ["Oreokastro",0,0,1,[2,0]] call Zen_FindGroundPosition;

_group = [_spawnPos, east, "infantry", 4] call Zen_SpawnInfantry;

0 = [_group, east] call Zen_GiveLoadout;

0 = [_opforInf, _group] call Zen_ArrayAppend;

};

if correct this should spawn them on roads but for some reason they seem to be ignoring the roads and spawn on the outside of the town

now the second part im having trouble with is a convoy objective

on the map near sytra i have a marker named "ConvoyStart" - this is wear i would like the convoy to start

i then have another marker named "ConvoyAttack" near the dump just south of Oreokastro - this is were i would like the convoy to move to and the area i want the players to attack the convoy

to achieve this i use

_convoySpawnPos = ["ConvoyStart", [100,150],[],1,[2,0]] call Zen_FindGroundPosition;

_yourObjective = ["ConvoyAttack",(group player), east, "Convoy", "eliminate",_convoySpawnPos] call Zen_CreateObjective;

now the convoy starts near the marker "ConvoyStart"

And The Objective Location Shows up near the dump

however when i teleport to the convoy start i see the convoy sitting on the road waiting to move and after a few seconds i hear there engines turn on

now at this point i can hear an explosion but no vehicle seems to be destroyed and upon checking all the convoy vehicles for passengers i notice there all dead

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

×