Jump to content
Zenophon

Zenophon's ArmA 3 Co-op Mission Making Framework

Recommended Posts

I'm talking about Server FPS/CPS not client (just to make clear).

This occurs with one player, so just imagine what happens with 20-30...mission not playable.

Yeah, something is looping, as the CPS won't recover, no matter how much you wait. And I am giving loadouts to units just fine. Just used that code to spawn some patrols easy way, instead of defining point, spawning, and giving loadout.

About a remote execution loop, I would suggest to check fisrt, as I saw on the first failure, with 25 players, that the server was sending 7MBs per second of data.

I've found the issue; it is an infinite remote execution loop. It occurs when functions that accept a true/false to remote execute get true explicitly in the arguments. When given false or nothing, the functions behave normally. However, when given true, they fail to change that argument to false when sending remote arguments. Thus, the machines being remote executed to thing they must send a request to all machines, and so on in a server-melting O(x^n) sequence (x is the number of clients and n is the number of the iteration, so 25 clients after 10 request loops gives over 95 trillion executions).

The solution is fairly simple (I even created a new macro for it), and I'm in the process of testing every affected function. I believe these are all the functions:

  • Zen_AddEject
  • Zen_AddFastRope
  • Zen_AddGiveMagazine
  • Zen_AddLoadoutDialog
  • Zen_AddRepackMagazines
  • Zen_GiveLoadoutBlufor
  • Zen_GiveLoadoutCustom
  • Zen_GiveLoadoutOpfor
  • Zen_GiveLoadoutIndfor
  • Zen_MultiplyDamage
  • Zen_RemoveFireSupportAction

For which in the documentation has the parameter 'Boolean, true to remote execute the function, (default: true)'. The only functions there that are given true in the framework are Zen_GiveLoadoutBlufor, Zen_GiveLoadoutOpfor, and Zen_GiveLoadoutIndfor by Zen_GiveLoadout.

Thus it is fairly easy to prevent this bug yourself with two things:

  1. Don't give any of the listed functions 'true' for remote execution
  2. Don't use Zen_GiveLoadout, including any macros that use it

Due to the severity of this issue and the number of functions affected (and it's exactly a week between releases), I am going to make an official release later today (after I test some more). This release will fix this issue, a few minor ones, and add some new things (likely a new function).

Share this post


Link to post
Share on other sites
I've found the issue; it is an infinite remote execution loop. It occurs when functions that accept a true/false to remote execute get true explicitly in the arguments. When given false or nothing, the functions behave normally. However, when given true, they fail to change that argument to false when sending remote arguments. Thus, the machines being remote executed to thing they must send a request to all machines, and so on in a server-melting O(x^n) sequence (x is the number of clients and n is the number of the iteration, so 25 clients after 10 request loops gives over 95 trillion executions).

The solution is fairly simple (I even created a new macro for it), and I'm in the process of testing every affected function. I believe these are all the functions:

  • Zen_AddEject
  • Zen_AddFastRope
  • Zen_AddGiveMagazine
  • Zen_AddLoadoutDialog
  • Zen_AddRepackMagazines
  • Zen_GiveLoadoutBlufor
  • Zen_GiveLoadoutCustom
  • Zen_GiveLoadoutOpfor
  • Zen_GiveLoadoutIndfor
  • Zen_MultiplyDamage
  • Zen_RemoveFireSupportAction

For which in the documentation has the parameter 'Boolean, true to remote execute the function, (default: true)'. The only functions there that are given true in the framework are Zen_GiveLoadoutBlufor, Zen_GiveLoadoutOpfor, and Zen_GiveLoadoutIndfor by Zen_GiveLoadout.

Thus it is fairly easy to prevent this bug yourself with two things:

  1. Don't give any of the listed functions 'true' for remote execution
  2. Don't use Zen_GiveLoadout, including any macros that use it

Due to the severity of this issue and the number of functions affected (and it's exactly a week between releases), I am going to make an official release later today (after I test some more). This release will fix this issue, a few minor ones, and add some new things (likely a new function).

Awesome Zen. Glad that I'm providing some feedback and work for this community.

But specially, have a nice new year!!

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 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 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 installment is a surprise New Year special (and there was a mission-crippling bug in nearly a dozen functions). That bug has been fixed and all those functions (listed exhaustively in the changelog) now work properly. It was most common when using Zen_Giveloadout, which is how the bug was found. The bug resulted in an infinite remote execution loop that could run a function hundreds of times.

On a happier note, Zen_ArrayFindExtremum is a new exciting function that will replace Zen_ArrayFindMax and Zen_ArrayFindMin (these two have been removed entirely). Zen_ArrayFindExtremum can do what those two functions did and much more. Thus, it is the function spotlit this week.

There are various other fixes, mostly related to multiplayer smoothness. Zen_MoveInVehicle should now put units in the corrects seats in the correct order. Previously, clients could be deferred to a cargo seat due to the synch delay in putting them in a turret. Also of note, Zen_MultiplyDamage should remote execute by default now, making a damage increase/decrease fair in a multiplayer game.

There are also three new macros; ZEN_STD_Parse_GetSetArgumentDefault and ZEN_STD_Parse_GetSetArgumentOptional deal with modifying the arguments to a function (they're used to fix the remote execution bug). ZEN_FMW_Code_SpawnPointBehind is more interesting; it will spawn groups in an area that is behind the center as viewed from a starting point. It's useful if you want to create a new objective nearby players, but don't want AI spawning next to them.

12/31/14

  1. New Function: Zen_ArrayFindExtremum
  2. Fixed: Zen_AddEject, Zen_AddFastRope, Zen_AddGiveMagazine, Zen_AddLoadoutDialog, Zen_AddRepackMagazines, Zen_GiveLoadoutBlufor, Zen_GiveLoadoutCustom, Zen_GiveLoadoutOpfor, Zen_GiveLoadoutIndfor, Zen_MultiplyDamage, and Zen_RemoveFireSupportAction created an infinite remote execution loop when given 'true' for remote execution argument
  3. Fixed: Zen_ArrayFilterCondition, Zen_ArrayFilterValues, Zen_ArrayRemoveDead, Zen_ArrayRemoveDuplicates, and Zen_ArrayRemoveNonLocal used their arguments to return a default value on argument error
  4. Fixed: Zen_FindGroundPosition terrain height filter caused an error
  5. Fixed: Zen_GiveLoadoutBlufor, Zen_GiveLoadoutCustom, Zen_GiveLoadoutOpfor, and Zen_GiveLoadoutIndfor reset units' animation when they were in a vehicle
  6. Fixed: Zen_MoveInVehicle now waits for client synch before checking for units being in a vehicle
  7. Fixed: Zen_MultiplyDamage default for remote execution parameter was wrong
  8. Added: Framework macro ZEN_FMW_Code_SpawnPointBehind
  9. Added: Standard macros ZEN_STD_Parse_GetSetArgumentDefault and ZEN_STD_Parse_GetSetArgumentOptional
  10. Removed: Zen_ArrayFindMax and Zen_ArrayFindMin
  11. Improved: Zen_ArrayGetNestedIndex optimized
  12. Documentation: Added for Zen_ArrayFindExtremum
  13. Documentation: Added for ZEN_FMW_Code_SpawnPointBehind, ZEN_STD_Parse_GetSetArgumentDefault, and ZEN_STD_Parse_GetSetArgumentOptional
  14. Documentation: Removed for Zen_ArrayFindMax and Zen_ArrayFindMin
  15. Documentation: Updated for ZEN_FMW_Code_SpawnPoint

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 think is useful, PM me and I can spotlight it.

The function chosen for this week is: Zen_ArrayFindExtremum. This function uses a hashing function to find the element of an array that maximizes some value. I used the word extremum rather than maximum, because you can easily get the minimum value as well.

A hash function for Zen_ArrayFindExtremum is similar to one for Zen_ArraySort, except for one major difference: it does not have to return a number. That technically makes it not a true hashing function, but because we deal with some many different types in ArmA (sometimes in the same array) it simply needs to hash one or more types to a number. Zen_ArrayFindExtremum will skip any elements that do not hash to a number, excluding them from the possible results.

Here's some examples:

_array = [1,2,3,4];
_max = [_array, {_this}] call Zen_ArrayFindExtremum;
_min = [_array, {-1 * _this}] call Zen_ArrayFindExtremum;

Those lines simply do what Zen_ArrayFindMax and Zen_ArrayFindMin did. Multiplying by -1 will invert the hash function, like it reverses the results from Zen_ArraySort. Previously, to find the extreme of some other data type, you would have to use Zen_ArraySort and then get the first/last element. This is inefficient if you only want one element; it also can't ignore elements of other types in the array.

_array = ["a", "bc", "def", "ghij", "klmno", "pqrstu", "vwxyz"];
_longest = [_array, {count toArray _this}] call Zen_ArrayFindExtremum;
_shortest = [_array, {-1 * (count toArray _this)}] call Zen_ArrayFindExtremum;

You can hash anything you want:

_array = [west] call Zen_ConvertToObjectArray;
_highest = [_array, {(getPosASL _this) select 2}] call Zen_ArrayFindExtremum;
_lowest = [_array, {-1 * ((getPosASL _this) select 2)}] call Zen_ArrayFindExtremum;

You still have to be careful with the hashing function itself when considering different data types. It's always a good idea to explicitly check for the types you want:

_array = [3, "3", 123, "123.45", 42, "41"];
_max = [_array, {if (typeName _this == "SCALAR") then {_this} else {count toArray _this}}] call Zen_ArrayFindExtremum;

You can also use Zen_ArrayGetType (even multiple times and add the results) to remove unwanted types. Finally, you can use Zen_ArrayFindExtremum with complex data structures to do interesting things:

// this is just for the example, you'd compile this data as you spawn the groups
_groupsData = [[group A, "mkPatrolA", _patrolThreadA], [group B, "mkPatrolB", _patrolThreadB], ...];

// '_this' will be each nested array
_largestGroupData = [_groupsData, {count units (_this select 0)}] call Zen_ArrayFindExtremum;
_smallestGroupData = [_groupsData, {-1 * (count units (_this select 0))}] call Zen_ArrayFindExtremum;

// Give them new patrol orders and store the thread
terminate (_largestGroupData select 2);
_largestGroupData set [1, _smallestGroupData select 1];
_largestGroupData set [2, ([_largestGroupData select 0, _largestGroupData select 1] spawn Zen_OrderInfantryPatrol)];

That will reassign the largest group to help the smallest group patrol their sector. If there's more than one group tied for the most units, Zen_ArrayFindExtremum will return the one in the first nested array.

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).

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.

Share this post


Link to post
Share on other sites

Bug fixed.

Regarding custom loadouts, could I suggest to get some option or configuration to get the items/magazines/weapons in the slots we want, instead of getting them randomly?

Remember the loadouts given as cargo not having the defined items spawned.

Share this post


Link to post
Share on other sites

Aaaaand....I do not know why, but in Dedicated Server, loadouts menu is giving one magazine less?? I'm giving 5 but it spawns 1 in the weapon and 3 in the backpack....

Edited by Zriel

Share this post


Link to post
Share on other sites
Bug fixed.

Regarding custom loadouts, could I suggest to get some option or configuration to get the items/magazines/weapons in the slots we want, instead of getting them randomly?

Remember the loadouts given as cargo not having the defined items spawned.

Weapons can only fill their defined inventory slot (I don't think there's a config value to let them be either a primary weapon or a handgun). From a utilitarian standpoint, defining whether a magazine is placed in the vest or the backpack is pointless. Players are free to move things around there inventory, and the AI won't notice.

Because classnames already need to be categorized by the engine command used, further sub-categorizing them into uniform, vest, and backpack adds unnecessary complication (the custom loadouts are confusing enough already due to randomization options). It also puts the burden on the mission-maker to ensure that there's enough room in each container (if too many items are given for the uniform, extras will be missing). It's easier to determine if all items and magazines will fit entirely on the unit (which is nearly guaranteed by a large backpack).

The order is not really randomized; items and magazines fill the uniform, vest, and backpack (this is done by default by the engine) in the order they are given, which is items before magazines. Classnames are given the order they are listed in those categories. What appears in what container is based upon how much space there is in each.

I'm not aware of that issue with Zen_GiveLoadoutCargo (sorry if it's been reported already). If you post the loadout that's not working with Zen_GiveLoadoutCargo, I'll test it and debug Zen_GiveLoadoutCargo.

Aaaaand....I do not know why, but in Dedicated Server, loadouts menu is giving one magazine less?? I'm giving 5 but it spawns 1 in the weapon and 3 in the backpack....

I know about this; it's been around since ArmA 3 Alpha; I don't remember if it happens on a listen server. It's not a simple mistake in the loadout code, because it works fine in SP. I assume it has something to do with BIS network code; the only fix is to give an extra magazine. If I knew how the engine handled giving magazines/weapons different in MP, the solution might be obvious. I don't even list in as a known issue, because it is so minor.

Share this post


Link to post
Share on other sites

This is the loadout. It's just a collection of magazines and CSE medical items, which I use to quickly give some cargo to mission vehicles.

0 = [
[["magazines",[["30Rnd_65x39_caseless_green",50],["30Rnd_65x39_caseless_green_mag_Tracer",50],["30Rnd_9x21_Mag",20],["200Rnd_65x39_cased_Box",20],["200Rnd_65x39_cased_Box_Tracer",20],["10Rnd_762x51_Mag",50],["HandGrenade",30],["SmokeShell",50],["SmokeShellRed",50],["SmokeShellGreen",50],["SmokeShellBlue",50],["1Rnd_HE_Grenade_shell",30],["1Rnd_Smoke_Grenade_shell",30],["1Rnd_SmokeRed_Grenade_shell",30],["RPG32_F",20]]],
["items",[["cse_tourniquet",2],["cse_bandageElastic",6],["cse_quikclot",10],["cse_bandage_basic",4],["cse_packing_bandage",4],["cse_morphine",2],["cse_saline_iv_250",2]]]], "Reabastecimiento OpFor"
] call Zen_CreateLoadout;

Called like this:

0 = [[sT1_HELI_1,ST1_HELI_2,ST1_TEMPEST_1,ST1_TEMPEST_2],"Reabastecimiento OpFor"] call Zen_GiveLoadoutCargo;

Magazines are given fine, but no item is given, so I do not think the problem is mine when defining the loadout. Also, i have tried with another custom defined "player loadouts" and the same problem happens, everything is given to the cargo, except the items. When assinging it to the player, it works perfectly.

About the bug in MP dedicated server, I would suggest then to add a note in documentation, so people know this forehand.

Thanks for your hard work!.

Share this post


Link to post
Share on other sites
Guest

Thanks for informing us about the new version :cool:

Release frontpaged on the Armaholic homepage.

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

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

This means soon 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
This is the loadout. It's just a collection of magazines and CSE medical items, which I use to quickly give some cargo to mission vehicles.

0 = [
[["magazines",[["30Rnd_65x39_caseless_green",50],["30Rnd_65x39_caseless_green_mag_Tracer",50],["30Rnd_9x21_Mag",20],["200Rnd_65x39_cased_Box",20],["200Rnd_65x39_cased_Box_Tracer",20],["10Rnd_762x51_Mag",50],["HandGrenade",30],["SmokeShell",50],["SmokeShellRed",50],["SmokeShellGreen",50],["SmokeShellBlue",50],["1Rnd_HE_Grenade_shell",30],["1Rnd_Smoke_Grenade_shell",30],["1Rnd_SmokeRed_Grenade_shell",30],["RPG32_F",20]]],
["items",[["cse_tourniquet",2],["cse_bandageElastic",6],["cse_quikclot",10],["cse_bandage_basic",4],["cse_packing_bandage",4],["cse_morphine",2],["cse_saline_iv_250",2]]]], "Reabastecimiento OpFor"
] call Zen_CreateLoadout;

Called like this:

0 = [[sT1_HELI_1,ST1_HELI_2,ST1_TEMPEST_1,ST1_TEMPEST_2],"Reabastecimiento OpFor"] call Zen_GiveLoadoutCargo;

Magazines are given fine, but no item is given, so I do not think the problem is mine when defining the loadout. Also, i have tried with another custom defined "player loadouts" and the same problem happens, everything is given to the cargo, except the items. When assinging it to the player, it works perfectly.

About the bug in MP dedicated server, I would suggest then to add a note in documentation, so people know this forehand.

Thanks for your hard work!.

After downloading CSE and testing that loadout, it was just a small mistake in Zen_GiveLoadoutCargo. It used 'addItem' as if for a person because I copied the logic from Zen_GiveLoadoutCustom. You can fix this yourself very quickly; replace lines 68-72 (they will become 68-70) of Zen_GiveLoadoutCargo with :

   _unit addItemCargoGlobal [_type, _count];
} else {
   _unit addItemCargoGlobal [([_x] call Zen_ArrayGetRandom), 1];

I finally got round to editing the video of my Zen framework Mission, if anyone is interested:

Watched the whole video, great video and a great mission. It really captures the essence of the framework: good co-op fun with friends.

Share this post


Link to post
Share on other sites

Anyone have an idea that will efficiently check if a random chosen position is actually on an island? Not like stratis, but on some other maps where there are a few smaller islands off from the main island.

If position is on an island like that, then either all other positions also need to be on that island or a boat needs to be spawned... unless you got time to kill and like swimming ;)

How about the preprocessor macros, like DeepSea? I don't see anything obvious, maybe someone else does.

Share this post


Link to post
Share on other sites

Hi Zen,

Glad you liked the video mate.

I am now working on porting the mission to a new map. I have updated to the latest version of the zen framework. I am having an intermittent issue with Zen_SpawnInfantry. This issue presents in the editor when I am previewing the mission.

The issue is: on some of the grids on my map, Zen_SpawnInfantry fails and throws an error message. The error message is like these two examples.

2015-01-11_00001_zps960311e4.jpg

2015-01-11_00003_zps930a56c0.jpg

These occur when I am testing, using editor to move around the map and check that grids are spawning enemies ok. Whats strange - on I can hit the same grid and have it throw an error 3 times but not on the forth time. Not sure what to make of that.

When the error occurs, the following things happen:

  • Infantry spawn with partial gear (screenshot below) - so only part of the custom loadout I am calling
  • Infantry do not patrol - they stay in their spawn position
  • The main mission loop stops

2015-01-11_00005_zpsa901dd81.jpg

Example screen - soldier has weapon from custom loadout but not uniform.

Question: - How can I read the error message to determine what is causing the issue. My best guess is I have something incorrect in custom loadout, but other than that I am not sure.

Mission code: http://pastebin.com/RtuaX5DR

Any advice or insight you can offer would be greatly appreciated.

Share this post


Link to post
Share on other sites

In your appdata/local/arma3 directory are .rpt files. This will be where to find more information. It looks like from your screenshot that the error is actually coming from Zen_ArrayAppend. Hard to say what is causing it, you have multiple Zen_SpawnInfantry commands going on.

You can use

diag_log "some identifying text here on this line shows this line was processed";

just before each spawn infantry call, and you would then see which specific call it was that gave the error.

You can use

diag_log format ["this is :: line 233 :: calling spawn infantry with this position :: %1 :: and this group :: %2 ::",positionXYZ,group123];

to get output with values of variables.

Really you need to include the .rpt file or at least the errors it produced, and to determine which command(s) in your script are erroring. Zen is familiar enough with his own work he could maybe tell you, but the rest of us probably need a little more to work with, short of downloading the map and running the mission etc etc.

Share this post


Link to post
Share on other sites
Anyone have an idea that will efficiently check if a random chosen position is actually on an island? Not like stratis, but on some other maps where there are a few smaller islands off from the main island.

If position is on an island like that, then either all other positions also need to be on that island or a boat needs to be spawned... unless you got time to kill and like swimming ;)

How about the preprocessor macros, like DeepSea? I don't see anything obvious, maybe someone else does.

A while ago a said I was going to do a Zen_IsIsland, mostly for this reason. I haven't done it yet, but the basic design is this: check points along an expanding circle around the center for being on water. If all point in one ring are on the water, it is an island. It requires some fine tuning for optimization and reliability, but it's the easiest way.

Another techniques might something like try to search a path around the center that is all water. Go out in a direction until you see water, then make small search rings looking for more water. If you get all the way back around to the start, it must be an island. This sounds less efficient though, as you need to decide which way to go if there is water in every direction.

Hi Zen,

Glad you liked the video mate.

I am now working on porting the mission to a new map. I have updated to the latest version of the zen framework. I am having an intermittent issue with Zen_SpawnInfantry. This issue presents in the editor when I am previewing the mission.

The issue is: on some of the grids on my map, Zen_SpawnInfantry fails and throws an error message. The error message is like these two examples.

http://i227.photobucket.com/albums/dd250/joelees/2015-01-11_00001_zps960311e4.jpg

http://i227.photobucket.com/albums/dd250/joelees/2015-01-11_00003_zps930a56c0.jpg

These occur when I am testing, using editor to move around the map and check that grids are spawning enemies ok. Whats strange - on I can hit the same grid and have it throw an error 3 times but not on the forth time. Not sure what to make of that.

When the error occurs, the following things happen:

  • Infantry spawn with partial gear (screenshot below) - so only part of the custom loadout I am calling
  • Infantry do not patrol - they stay in their spawn position
  • The main mission loop stops

http://i227.photobucket.com/albums/dd250/joelees/2015-01-11_00005_zpsa901dd81.jpg

Example screen - soldier has weapon from custom loadout but not uniform.

Question: - How can I read the error message to determine what is causing the issue. My best guess is I have something incorrect in custom loadout, but other than that I am not sure.

Mission code: http://pastebin.com/RtuaX5DR

Any advice or insight you can offer would be greatly appreciated.

Infantry not patrolling and the loop exiting are the results of the error. The loadouts I can't explain; they should give all or nothing.

As m0nkey says, you have 4 Zen_ArrayAppend calls in your init. Without knowing which one is giving that error, you can't know which call to Zen_SpawnInfantry is returning a null group. That last two Zen_ArrayAppend likely aren't the problem it; '_groupsArray' is defined as [] and '_x' should never be null.

You can debug by first logging '_townMkArray' before the forEach loop, to make sure that all its value are not null and make sense (a valid marker). Then check the entire log for an error from Zen_SpawnInfantry. You might also want to try without any mods (except maybe the map) if that's easy for you. Everything you do to eliminate possible causes helps you debug faster.

Share this post


Link to post
Share on other sites

Thank you m0nkey and Zen. I did not get time to debug properly yet, will hopefully do that at the weekend, but reading your input got me thinking. i had created a second groups array called _groupsArray2, first referenced in line 251. The purpose of this was to allow spawned vehicle crews to have a different loadout to the main enemy group. As process of elimination, I commented the references to _groupsArray2 out and had all of the spawned units held in _groupsArray instead - the issue did not occur when I tested. Will debug more and report back - thank you both for the guidance.

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 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 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

The twentieth release includes 14 changes, which makes 392 total changes since public release. The highlights include a whitelist option for Zen_FindGroundPosition, physics ropes for Zen_OrderFastRope, and two new functions.

Zen_FindGroundPosition's third parameter has been extending (meaning no existing code is broken) to allow a number to indicate exclusion or inclusion (0 is blacklist). Also, thanks to dedicated framework user m0nkey, Zen_FindGroundPosition now has correct world size data for 50 maps; this allows it detect positions that are off the map.

Zen_OrderFastRope now uses physics ropes and allows units to slide down them smoothly. However, it sometimes looks like there are two ropes right next to each other (there are), and I can't find a way to detach the rope from the helicopter and let it fall to the ground. Nevertheless, fastroping looks better than ever.

The first new function is Zen_FindTerrainGradient, which mimics Zen_FindTerrainSlope. However, the word gradient has its mathematical definition: the direction of greatest increase. In this case, the 2D (XY) angle that points towards the greatest increase in terrain elevation. The second function, Zen_ExecuteCommand, is a helper function for multiplayer synch'ing and locality issues. The function spotlight will review its purpose and usage.

As for bugs, Zen_SpawnConvoy allowed the vehicles to remained stopped even if their lead vehicle moved; that resulted in rather lonely convoys. Also, Zen_MoveInVehicle should be used with 'spawn' not 'call' due to its new sleep commands for multiplayer synch'ing. That wasn't changed in the documentation, nor in the functions that used Zen_MoveInVehicle. Finally, Zen_GiveLoadoutCargo did not give objects from the 'items' category.

1/14/15

  1. New Function: Zen_ExecuteCommand
  2. New Function: Zen_FindTerrainGradient
  3. Fixed: Zen_GiveLoadoutCargo did not give items
  4. Fixed: Zen_SpawnConvoy did not order all vehicles to follow the lead vehicle
  5. Fixed: Zen_SpawnConvoy, Zen_SpawnVehicleCrew, and ZEN_FMW_Code_Insertion used Zen_MoveInVehicle wrong
  6. Improved: Zen_ArrayGetNestedIndex and Zen_ArrayGetNestedValue ignore elements that are not nested arrays
  7. Improved: Zen_FindGroundPosition uses reliable hard-coded values to detect off-map positions
  8. Improved: Zen_FindGroundPosition offers a white list option for its black list parameter
  9. Improved: Zen_OrderFastRope uses physics ropes for more realistic fastroping
  10. Improved: Zen_OrderFastRope and Zen_SpawnParachute optimized building detection
  11. Documentation: Corrected for Zen_FindTerrainSlope
  12. Documentation: Added for Zen_ExecuteCommand, Zen_FindTerrainGradient
  13. Documentation: Updated for Zen_FindGroundPosition
  14. Documentation: Improved for Zen_ArrayFindExtremum, Zen_MoveInVehicle

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 think is useful, PM me and I can spotlight it.

The function chosen for this week is: Zen_ExecuteCommand. This function is literally a framework, as I intend for you to add to suit your needs. Unlike other functions, which I advise against modifying, Zen_ExecuteCommand is designed for you to add functionality in a simple way. Thus, the file itself is at Zen_FrameworkFunctions\Zen_MiscFunctions\Zen_ExecuteCommand.sqf.

If you look at the file, it contains a few simple BIS commands. You might suggest that using BIS_fnc_MP with the commands would suffice. However, there is sometimes code that falls between a single command and a real function. In an effort to organize code and eliminate 2-3 line functions in MP, Zen_ExecuteCommand allows you to map any string to any sequence of commands using any arguments.

The advantages to this are: a stack trace for errors, argument checking, and a helpful error message for missing commands. Rather than creating another function just to send some simple commands to other machines, you can use just one function that supports many commands.

Now to some examples for how to use and modify it. You can use the framework's helpful remote execution macros to simplify the process. Here we use a command that is already there:

_args = ["allowDamage", [X, false]];
ZEN_FMW_MP_REClient("Zen_ExecuteCommand", _args, X)

You can use ZEN_FMW_MP_REAll, ZEN_FMW_MP_REClient, ZEN_FMW_MP_REServerOnly, and ZEN_FMW_MP_RENonDedicated for different RE needs.

Now for adding a command; this fairly simple. Each command is case in a switch statement. Copy and paste the case and its code above the 'default' case in the function. If you wanted to put in a sidechat command:

       // ...
   };
   case "sidechat": {
       (_args select 0) sideChat (_args select 1);
   };
   default {
       // ...

It is important that the case value be all lowercase letters and that you use _args to refer to the arguments. Then execute the command:

_args = ["sidechat", [X, "Hello World"]];
ZEN_FMW_MP_REAll("Zen_ExecuteCommand", _args)

Everyone in a MP mission will see that text from X (whoever X is).

Finally, if you add commands to this function to help make your mission, PM or email them to me and I will include them in the function. What's useful to one person is likely useful to more. Zen_ExecuteCommand can grow to become its own library of useful snippets.

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).

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.

Share this post


Link to post
Share on other sites
Guest

Thanks again for informing us about the new version :cool:

Release frontpaged on the Armaholic homepage.

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

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

This means soon 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

Hi Zenophon,

Thank you for this excellent framework. I am new to scripting in A3 but you have documented everything so well that I have been learning quickly.

I have a question I was hoping you could help me with in regards to your MissionHelicopterRandom.Stratis tutorial. Specifically I am trying to modify the area in which the LZ marker is placed. It is currently placed very close to the objective (where the convoy ends) and I would like to make it appear between 600-1200 meters away from the objective while still matching your other criteria for it to be away from buildings and debris and also not too steep of a slope. Is this possible? I'm using Takistan so there should be plenty of locations within 600-1200 meters of any city that meet the requirements.

Share this post


Link to post
Share on other sites

Hi Zen, could You please help me a little?

I have written this code:

_heliSpawnPos = ["mk_heli", 0, [], 0] call Zen_FindGroundPosition;
_heliSpawnPos2 = ["mk_heli", 0, [], 0] call Zen_FindGroundPosition;
0 = [_heliSpawnPos, "Heli Spawn 1"] call Zen_SpawnMarker;
0 = [_heliSpawnPos2, "Heli Spawn 2"] call Zen_SpawnMarker;
_lz = ["mk_lz", 0, [], 1, [2,0], [0,360], [0,0,0], [0,0,0], [0,0], [0,0,0], [1,1,20] ] call Zen_FindGroundPosition;
0 = [_lz, "LZ"] call Zen_SpawnMarker;

fnc_insertion = {
_heli = [_heliSpawnPos, "B_Heli_Light_01_F", 150,300] call Zen_SpawnHelicopter;
_soldiers = [_lz, west, "infantry", [3,5]] call Zen_SpawnInfantry;
0 = [[player,_soldiers], _heli] call Zen_MoveInVehicle;
0 = [_heli, [_lz, _heli], [player, _soldiers], "full", 15, True] call Zen_OrderInsertion;
0 = [_soldiers, _lz, [50, 200], [200, 300], "normal"] call Zen_OrderInfantryPatrol;
};

fnc_vehdrop = {
_heli2 = [_heliSpawnPos2, "B_Heli_Transport_01_F", 150,300] call Zen_SpawnHelicopter;
_mrap = [[0,0,0], "B_MRAP_01_F"] call Zen_SpawnGroundVehicle;
0 = [_heli2, ["mk_drop", _lz], _mrap, "full"] call Zen_OrderVehicleDrop;
};

0 = [] call fnc_insertion;
0 = [] call fnc_vehdrop;

Is it possible to call both functions simultaneous?

I want both helicopters to start at this same time.

Right now it works like that:

- spawns heli1, move all into it, insertion, heli go away, wait for heli to stop executing insertion, start infantry patrolling ...

and I want this like that:

- spawns heli1 and heli2, move all into heli1, insertion from heli1 and drop veh from heli2 (in this same time), start infantry patrolling when they are on the ground, helis go away ...

This in rpt is normal?

3:12:06 Starting mission:
3:12:06  Mission file: testZen1
3:12:06  Mission world: Stratis
3:12:06  Mission directory: C:\Users\Jarek\Documents\Arma 3 - Other Profiles\Doman\missions\testZen1.Stratis\
3:12:07 Attempt to override final function - bis_functions_list
3:12:07 Attempt to override final function - bis_functions_listpreinit
3:12:07 Attempt to override final function - bis_functions_listpostinit
3:12:07 Attempt to override final function - bis_functions_listrecompile
3:12:08 Attempt to override final function - bis_fnc_missiontaskslocal
3:12:08 Attempt to override final function - bis_fnc_missionconversationslocal
3:12:08 Attempt to override final function - bis_fnc_missionflow

Arma stable, no mods, late night :)

Share this post


Link to post
Share on other sites

I would like to make it appear between 600-1200 meters away from the objective while still matching your other criteria for it to be away from buildings and debris and also not too steep of a slope. Is this possible?

It's possible. Change line 45 to

_landingPosition = [_ObjectivePos,[600,1200],0,1,0,0,[1,0,20],0,[1,25],[1,6],[1,[0,0,0],20]] call Zen_FindGroundPosition;

Parameter one is the destination of the convoy, parameter 2 is the range to consider, and parameter 9 keeps the helicopter away from water. 'Loosen' or 'tighten' parameters 7, 10 and 11 based on the map characteristics.

I tested this call on Altis map and it gave good results.

There is one non-trivial side effect. Since the landing zone and convoy start position are both randomly generated you could land very close to the convoy starting point. If you want more time to set up then increase the sleep time, increase the distance to the convoy start point (parameter 2 of line 68) and/or set the convoy travel speed from "normal" to "limited'.

And you can delete lines 31 to 43 since there is no random landing zone calculation needed.

Mimir.

---------- Post added at 04:54 ---------- Previous post was at 04:18 ----------

0 = [_heli, [_lz, _heli], [player, _soldiers], "full", 15, True] call Zen_OrderInsertion;

0 = [_soldiers, _lz, [50, 200], [200, 300], "normal"] call Zen_OrderInfantryPatrol;

0 = [_heli2, ["mk_drop", _lz], _mrap, "full"] call Zen_OrderVehicleDrop;

Change these from 'call' to 'spawn' and see if it works.

Mimir.

Share this post


Link to post
Share on other sites

Many thanks MimirAesir, your recommendation works great!

I do have two more questions about the helicopter script that I was hoping someone could help me with:

Is there a list of what all of the parameters after _landingPosition = are? The .pdf that accompanies the mission details parameters 7 (avoid buildings), 10 (maximum slope of terrain), and 11 (avoid clutter) and MamirAesir detailed 2 (range) and 9 (avoid water). I assume some of the other parameters relate to altitude, forest, etc. but I'm not sure where to find the whole list.

My second question is how to avoid placing the LZ marker outside the bounds of the map? For objectives close to the edges of the map this script is sometimes marking an LZ that is off of the map and an error (from line 204 Zen_FindGroundPosition.sqf) is thrown. When this happens, how could I re-calculate the LZ again until I get a valid location?

Share this post


Link to post
Share on other sites

...but I'm not sure where to find the whole list.

I can only answer the first question.

Look in Zen_PositionFunctions.txt in the Zen_FrameworkDocumentation directory. Index.txt in this directory shows the location of all function documentation.

And for a graphical view look at Zen_FindGroundPosition.html in \Zen_FrameworkDocumentation\Zen_Diagrams\Zen_FindGroundPosition directory.

The demonstration mission in \Zen_RandomPositions.Altis give about 15 varied examples of the Zen_FindGroundPosition function.

Mimir.

Share this post


Link to post
Share on other sites

This in rpt is normal?

3:12:06 Starting mission:
3:12:06  Mission file: testZen1
3:12:06  Mission world: Stratis
3:12:06  Mission directory: C:\Users\Jarek\Documents\Arma 3 - Other Profiles\Doman\missions\testZen1.Stratis\
3:12:07 Attempt to override final function - bis_functions_list
3:12:07 Attempt to override final function - bis_functions_listpreinit
3:12:07 Attempt to override final function - bis_functions_listpostinit
3:12:07 Attempt to override final function - bis_functions_listrecompile
3:12:08 Attempt to override final function - bis_fnc_missiontaskslocal
3:12:08 Attempt to override final function - bis_fnc_missionconversationslocal
3:12:08 Attempt to override final function - bis_fnc_missionflow

Arma stable, no mods, late night :)

Yes, this appears for any mission with or without the framework. Those functions are not used in the framework; it's a bug somewhere in BIS's engine or functions.

My second question is how to avoid placing the LZ marker outside the bounds of the map? For objectives close to the edges of the map this script is sometimes marking an LZ that is off of the map and an error (from line 204 Zen_FindGroundPosition.sqf) is thrown. When this happens, how could I re-calculate the LZ again until I get a valid location?

Since you say line 204, I assume you saw all the world size data in Zen_FindGroundPosition.sqf. You can use those dimensions or just the editor to create a marker that covers most of the real map, then use Zen_FindGroundPosition's whitelist parameter with this marker. That guarantees that all points will be within the map. That error is just a friendly warning; it doesn't mean you can't use that point (e.g. spawning aircraft off the map).

Unfortunately, using the whitelist means you can't simultaneously use a blacklist; this oversight has already been reported by PM. Next release that parameter will support blacklist and whitelist together.

Finally, a general note about the whitelist: whitelist means that the point must be in all the whitelist markers, not just some. Next release, a 'one or more' style whitelist will be added in addition to the 'all' whitelist.

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

×